# Deployment run record — Sibyla production on the POC server, 2026-09-03

*The written record the deployment prompt (`apollo-deployment-prompt-260901.md`) asks for. Run from
an agent session on the owner's instruction ("Phase L is done, proceed with the whole plan
sequentially"). Phases 0–4 ran; Phase 5 did not, for the reasons in section 6.*

## 1. Rollback baseline (Phase 0)

`D:\Backups\SibylaDeployment\20260903-001541\`

- `baseline.txt` — every IIS site with bindings, certificates, physical paths, pools and identities;
  the `GottSibylaWorker` state (Running, Automatic, `.\GottSibylaDocumental`); installed .NET
  runtimes (ASP.NET Core 10.0.9 present); ASP.NET Core Module V2 20.0.26140.9 registered; http.sys
  certificate bindings; win-acme renewals; Hermes cron jobs; GOTT.Apollo at `e17d096`.
- IIS configuration backup `SibylaDeploy-20260903-001541`
  (`Restore-WebConfiguration -Name SibylaDeploy-20260903-001541`).
- `legacy-Sibyla\`, `legacy-Sibyla.Api\`, `legacy-Sibyla.Worker\` — robocopy `/E` copies of
  `C:\SibylaApps\Sibyla`, `Sibyla.Api` and `Sibyla.Worker` (229 + 72 + 74 files). Zip archiving
  failed on DLLs locked by the running sites, so the copies are folders.
- `hermes-config.yaml`, `hermes-cron-jobs.json` — copies of the Hermes configuration.

## 2. Local proof before deploying (Phase 1)

| Step | Result |
|---|---|
| `local\build.ps1` | OK |
| `local\test.ps1` | TenantIsolation 52/52 · Platform 107/107 · Argus 137/137 · Browser 121/121 · Api 45/45 |
| `local\migrate.ps1` (Main + Preview) | OK, nothing pending |
| `local\run-sync.ps1` (Main + Preview) | idempotent: every table "same"; `ctrl_override` 6 rows updated from source; G8 1,275/1,277 archived files verified (the two known-missing Itoorer BICS files); G11 7/7 |

## 3. Tooling created (Phase 2)

Hand path until `Sibyla.Deployment` Slice 2 (spec section 12); all under `local\`:

- `publish-release.ps1` — `dotnet publish` of Sibyla.Web, Sibyla.Api and Sibyla.Worker.Documents
  (Release, net10.0, framework-dependent) into `artifacts\publish\<release>\{web,api,worker}` with
  `release.json`; refuses a dirty tree unless `-AllowDirty`.
- `deploy-release.ps1 -Release <id>` — copies each host to `C:\Apps\Sibyla\<host>\<release>` with a
  `MANIFEST.json`, then repoints the IIS site (pool recycled) or the service (restarted). It only
  activates a site or service that already points under `C:\Apps\Sibyla`; the previous folder stays
  and is recorded in `PREVIOUS.txt`. Health: `GET /` 200/302 on the web host, `/health` and
  `/health/ready` 200 on the API.
- `rollback-release.ps1 -Target web|api|worker [-ToPath]` — folder swap plus recycle/restart.
- `provision-production.ps1` — one-time, idempotent: renames the legacy sites and pools to
  `Sibyla.Legacy.*`, creates the pools, sites, bindings, `SIBYLA_SECRETS_FILE`, limits, ACLs and
  the worker service (details in section 4).

Release **`20260903-002407-3fa3159`** = commit `3fa3159` (clean tree), published 00:24:36 UTC.

## 4. What was stood up (Phase 3)

| Host | IIS site (id) | Pool | Physical path | Bindings |
|---|---|---|---|---|
| `sibyla.gottsolutions.net` | `Sibyla.Web` (10) | `Sibyla.Web`, No Managed Code, ApplicationPoolIdentity, AlwaysRunning | `C:\Apps\Sibyla\web\20260903-002407-3fa3159` | http 80, https 443 SNI |
| `api.sibyla.gottsolutions.net` | `Sibyla.Api` (11) | `Sibyla.Api`, same | `C:\Apps\Sibyla\api\20260903-002407-3fa3159` | http 80, https 443 SNI |
| `docs.sibyla.gottsolutions.net` | `Sibyla.Docs` (12) | `Sibyla.Docs`, No Managed Code, ApplicationPoolIdentity | `D:\fileStorage\repos\GOTT.Apollo\docs` (working copy) | http 80, https 443 SNI |

- **Legacy sites renamed** (IIS names only, nothing else changed): `Sibyla.Web` → `Sibyla.Legacy.Web`,
  `Sibyla.Api` → `Sibyla.Legacy.Api`, `Sibyla.Docs` → `Sibyla.Legacy.Docs`, pools likewise; the
  pool rename recycled them once (00:26:43–00:26:46). All three answer as before.
- **Certificates**: win-acme renewals `[Platform] sibyla.gottsolutions.net`,
  `[Platform] api.sibyla.gottsolutions.net`, `[Platform] docs.sibyla.gottsolutions.net`
  (`--source manual`, self-hosted http-01, store WebHosting, IIS installation; next renewal after
  2026-10-28). Thumbprints `FD01DBD9…821F` (web), `76A041D3…FD2D` (api), `B7EFDF16…51B5` (docs — the
  certificate issued the day before was reused).
- **Secrets**: `C:\ProgramData\Sibyla\secrets\{web,api,worker}.json` (ACL: Administrators, SYSTEM,
  plus read for that host's identity only). Each host receives only `SIBYLA_SECRETS_FILE`, written
  into `applicationHost.config` `<location path="Sibyla.Web|Sibyla.Api">` (never into a release
  folder's `web.config`). web.json: `ConnectionStrings:SibylaDb` on **`apollo_app`**, `Oidc`
  (authority, client id, secret), `DataProtection:KeysPath`. api.json: the connection on
  **`apollo_api`**. worker.json: the connection on **`apollo_worker`**, the key ring path,
  `Worker:ClaudeCliPath`.
- **API site**: `maxAllowedContentLength` 52 500 000, `requestTimeout` 00:02:00 (applicationHost).
- **Docs site**: anonymous, directory browsing on, `.md` → `text/markdown; charset=utf-8`
  (`.svg`/`.json` are IIS globals), `index.html` default document, pool identity read on the folder.
- **Data Protection ring**: `D:\ApolloData\dp-keys` (ACL: Administrators, SYSTEM, `IIS AppPool\Sibyla.Web`
  modify, `SibylaWorker` modify). The development key `key-cebe9c03…` was copied in, because the
  tenant credentials already stored in `gott_apollo` are protected by it (D19: outside the site
  folder, not in database backups). The API has no ring (ephemeral, as specified).
- **Data folders**: `D:\ApolloData\staging` modify for `Sibyla.Web`, `Sibyla.Api`, `SibylaWorker`;
  `D:\ApolloData\ai` modify for `Sibyla.Web`; `D:\ApolloData\work` modify for `SibylaWorker`.
- **IdP**: the `apollo-web` client's production redirect and post-logout URIs were rewritten from
  `apollo.gottsolutions.net` to `sibyla.gottsolutions.net` by SQL on `OpenIddictApplications`
  (data only, D3); localhost URIs untouched; no secret rotated.
- **Worker service** `Sibyla.Worker.Documents` ("Sibyla Worker (Documents)"): binary
  `C:\Apps\Sibyla\worker\20260903-002407-3fa3159\Sibyla.Worker.Documents.exe`, account
  **`.\SibylaWorker`** (new local user, password in the gitignored
  `local\secrets\worker-account.json`, "Log on as a service" granted), delayed automatic start,
  restart on failure (10 s / 60 s / 300 s), service environment `SIBYLA_SECRETS_FILE` and
  `CLAUDE_CONFIG_DIR=D:\ApolloData\worker-claude`. Claude CLI: a pinned copy of the self-contained
  binary at `C:\Apps\Sibyla\tools\claude\claude.exe` (2.1.259), readable by the account.

Two mistakes on the way, both reverted within a minute and both fixed in the scripts:

1. The first `deploy-release.ps1` run found the *legacy* site still named `Sibyla.Web` and repointed
   it at the release folder (00:24:46); reverted at 00:25:10 (`Set-ItemProperty physicalPath`
   back to `C:\SibylaApps\Sibyla`, pool recycled; `legacy.gottsolutions.net` answered 302 again).
   The script now refuses to activate a site whose path is not under `C:\Apps\Sibyla`.
2. The site settings written with the WebAdministration provider and `-Location` landed in the
   release folders' `web.config` (and a `docs\web.config`) and, once those were cleaned, the web
   and API hosts answered 500 for about a minute until the settings were re-applied with
   `appcmd … /commit:apphost`. The script now uses appcmd for those writes; the release
   `web.config` files are byte-identical to the published ones again.

## 5. Verification in production (Phase 4)

| Check | Result |
|---|---|
| `https://sibyla.gottsolutions.net/` | 200 (`<title>Sibyla</title>`, anonymous shell); `/account/login` → 302 to `login.gottsolutions.net/connect/authorize?client_id=apollo-web&redirect_uri=https://sibyla.gottsolutions.net/signin-oidc…` |
| Sign-in completes; topbar shows licence and company selectors | **Not verified — needs an owner sign-in** (no user credential in the session) |
| Argus screens render synced data under RLS | **Not verified in production** for the same reason; the render smoke suite (121 green) proves the same pipeline against the same `gott_apollo` from the working tree |
| `https://api.sibyla.gottsolutions.net/health`, `/health/ready` | 200, 200 (`SELECT 1` on `apollo_api`) |
| Intake plugin round-trip (`apollo-channel-intake` status tool, random id) | token minted at the IdP as `sibyla-channel-intake`; API answered `404 channel_intake_not_found` with the correlation id echoed — auth and routing work; nothing written |
| `https://docs.sibyla.gottsolutions.net/` and `/naming-glossary.md` | 200 listing; 200 `text/markdown; charset=utf-8` |
| Worker service | Running, pid live, account `.\SibylaWorker`; two `apollo_worker` connections open on `gott_apollo` (polling) |
| Database roles in use (`pg_stat_activity`) | `apollo_app` (web), `apollo_api` (API), `apollo_worker` (worker); **no** `apollo_migrator` from any host |
| Legacy and untouched sites after the changes | `legacy.gottsolutions.net` 302 → `/pt`; `api.legacy…/health/live` 200; `docs.legacy…` 200; `login` 302; `buzz` 200; `nextcloud` 302 to login |
| `dashboard.gottsolutions.net` | **502 — pre-existing**: its site reverse-proxies to the Hermes dashboard on `127.0.0.1:9119`, which is not listening. Not touched (constraint 3). |
| Event log | ASP.NET Core Module: all three applications "started successfully"; no errors from the hosts |
| TLS | Let's Encrypt certificates serve on all three names |

Also true and worth knowing: the `SibylaWorker` account has no Claude subscription login yet
(`D:\ApolloData\worker-claude` is empty), so the first Claude job pauses the lane (JOBLNE, 10 min)
until the owner logs in as that account (section 7). Queue polling, storage transfers and the key
ring do not depend on it.

## 6. Retirement (Phase 5) — run 2026-09-03 00:48–00:49 UTC on the owner's word

The owner verified the sign-in and the screens ("Sign-in verified, screens render; proceed with
Phase 5"), which closed the two open Phase 4 checks and the business check. Then, one at a time
with the checks of the prompt between them:

1. **`Sibyla.Legacy.Web`** (`legacy.gottsolutions.net`): site and pool stopped at 00:48:47. The
   folder `C:\SibylaApps\Sibyla` and the Phase 0 copy stay. `legacy.gottsolutions.net` now answers
   404 from IIS (no started site binds the host). Checked after: `api.legacy…/health/live` 200,
   `docs.legacy…` 200, the three platform hosts 302/200/200, `login` 302, `buzz` 200, `nextcloud`
   302; every other site Started.
2. **`GottSibylaWorker`**: stopped at 00:49:10 and set to Disabled (was Running, Automatic, account
   `.\GottSibylaDocumental`; binary `C:\SibylaApps\Sibyla.Worker\Sibyla.Worker.exe` kept). Checked
   after: `Sibyla.Worker.Documents` Running; PostgreSQL and W3SVC Running; the same hosts as above
   unchanged; the Hermes gateway running (pid 2312); crons `sibyla-email-graph-gateway` and
   `apollo-email-gateway` both paused, last status ok / never run; no Application-log errors.

Restart, if ever needed, is one line each:

```powershell
Import-Module WebAdministration
Start-WebAppPool 'Sibyla.Legacy.Web'; Start-Website 'Sibyla.Legacy.Web'
Set-Service GottSibylaWorker -StartupType Automatic; Start-Service GottSibylaWorker
```

Nothing was deleted (constraint 2).

Not to be retired in that step either way: `Sibyla.Legacy.Api` (intake cutover step 8),
`Sibyla.Legacy.Docs`, the `gott_sibyla` database.

## 7. What waits for the owner

1. ~~Sign in and confirm the selectors and the Argus screens~~ — **done by the owner 2026-09-03**
   ("Sign-in verified, screens render").
2. ~~Claude for the worker~~ — **done by the owner 2026-09-03 01:15 UTC** through
   `local\worker-claude-login.ps1` (a console as `SibylaWorker`, `claude auth login`); the account
   was added to the local `Users` group for the interactive logon; `claude -p` answered as the
   service account and `D:\ApolloData\worker-claude\.credentials.json` exists. No end-to-end
   document run yet (the owner deferred the test upload; the queue held nothing pending).
3. ~~Phase 5~~ — **done 2026-09-03** (section 6).
4. **Intake cutover steps 6–8** (intake spec section 10). Step 1 is done (deployed, `/health/ready`
   green, plugin round-trip green). **Step 5 done 2026-09-03** on the owner's word: the Hermes
   addendum `.hermes.md` rewritten as `sibyla-apolo-document-intake/2.0`, `SOUL.md` and the five
   skills updated to the Apollo plugin's tools, contract, base URL, the quarantine/`senderVerified`
   vocabulary and the SHA-256 rule (backups under the Phase 0 folder, `hermes-step5-pre\`); token
   probe green; gateway restarted cleanly. **Step 6 done 2026-09-03:** the cron
   `apollo-email-gateway` is unpaused and reports `ok` after a fix to the legacy Graph watcher
   (mark-as-read used the pre-move message id; backup `graph_email_gateway.py.pre-step6.bak` in
   the Phase 0 folder); it is mailbox triage only. **F7 built the same night** (intake spec
   section 7.1): the Apollo-owned watcher `apollo-email-intake` registers the `Validar`
   attachments through the plugin's client with DMARC enforcement; its cron `25c3ac4615bf` is
   created **paused**, so unpausing it is the email leg of step 7.
   **Step 7 postponed by the owner** (protocol recorded in the intake spec); step 8 (retire the
   legacy API, plugin and IdP client) follows step 7.
5. **The docs site publishes `docs\` anonymously** to the internet, as the plan entry of 2026-09-03
   warned; say if an allow-list or an IdP front is wanted instead.
6. `dashboard.gottsolutions.net` (Hermes dashboard on port 9119) is down independently of this work.

## 7a. Second release of the API host (02:18 UTC, review round 2)

`local\publish-release.ps1 -Hosts api` → release `20260903-021830-7191ca3`;
`local\deploy-release.ps1 -Release 20260903-021830-7191ca3 -Hosts api` repointed `Sibyla.Api` to
`C:\Apps\Sibyla\api\20260903-021830-7191ca3` (previous `…\20260903-002407-3fa3159` kept and
recorded in `PREVIOUS.txt`), recycled the pool, and passed `/health` and `/health/ready` (200).
The release `web.config` is byte-identical to the published one (site settings stay in
applicationHost). Plugin round-trip green. The web and worker hosts were not redeployed (their
code did not change). Rollback: `local\rollback-release.ps1 -Target api`.

## 7b. ACL hardening (02:55 UTC, Slice 2 spec review finding O2)

The install root, the docs folder and `D:\ApolloData\{staging,ai,work}` had inherited the volume
default ACL, which gives `BUILTIN\Users` (every pool identity and `SibylaWorker`) read on every
host's release and CreateFiles in every release folder and in `docs\`. `provision-production.ps1`
now cuts inheritance and writes the exact ACE set (`SYSTEM`, `Administrators` Full; the host's
own identity RX on its host folder; `SibylaWorker` RX on `tools`; `Administrator` Modify plus
`IIS AppPool\Sibyla.Docs` RX on `docs\`; the data folders with only their intended identities).
Applied and read back the same night; release folders inherit from their host folder and carry
no ACE. The docs site's anonymous identity was switched from `IUSR` (401 after the change) to the
pool identity (`anonymousAuthentication userName=""`). After the change: web 200/302, API
`/health/ready` 200, docs 200 with `text/markdown`, `/.git/HEAD` 404, the worker service
restarted clean under the new ACLs, no Application-log errors. `docs/web.config` is now
gitignored.

## 7c. Two corrections from review round 2 (03:20 UTC)

Reviewer O verified every hardened ACL target on the host (all exact) and found four folders
with a stray explicit `Administrators` ACE materialised before the hardening (the three
first-release folders and `tools\claude`); `provision-production.ps1` now strips explicit entries
from release folders and the four were cleaned. *Correction (round 3, O-N5):* eleven sub-folders
below the targets (`wwwroot`, `runtimes`, an evidence folder under `staging`, one under `work`)
still carried the same materialised `Administrators` ACE; the strip is now recursive in the
script and was applied to every target tree — 0 explicit ACEs below any target (the four
host folders `web`, `api`, `worker`, `tools` are targets themselves and keep their exact ACE
set). The script
also completes the key-ring shape it had only half-written (`dp-keys`: Web and `SibylaWorker`
Modify, both already live) and selects releases by the id regex so a future `.staging` folder is
never taken for a release. Health after: web 302, API `/health/ready` 200, docs 200, worker
Running.

## 7d. Slice 2 A2 API release — `/health/schema` (17:15 UTC)

After the accepted A2+B2 merge `97ac43a` was pushed to `origin/main`,
`local\publish-release.ps1 -Hosts api` produced the clean API-only release
`20260903-171530-97ac43a`. Its manifest names commit
`97ac43a4e6b49d92a731ffa88ff1571361ff28be` and 19 required platform migrations, including
`20260903075049_SchemaHealthGrant`. `local\deploy-release.ps1 -Release
20260903-171530-97ac43a -Hosts api` repointed `Sibyla.Api` to
`C:\Apps\Sibyla\api\20260903-171530-97ac43a`; previous release
`C:\Apps\Sibyla\api\20260903-021830-7191ca3` remains recorded in `PREVIOUS.txt`.

Post-deployment verification: `/health`, `/health/ready` and `/health/schema` all returned 200;
the schema body reported role `sibyla_api` and exactly the same 19 migration ids as the release
manifest (none missing or extra). The installed and published `web.config` hashes matched, IIS site
and pool were Started, the new ANCM start event was present, and there were no error-level
Application-log events for the API. Web, worker, docs, legacy objects, win-acme and the deployment
module were untouched. The explicit `has_table_privilege` database query remains a D2 run-record
precondition; this endpoint result proves the deployed API can read the migration history but does
not replace that recorded check. Rollback: `local\rollback-release.ps1 -Target api`.

## 7e. API release `20260904-114642-d3e32c7` — WebDAV removal for the upload route (2026-09-04 11:47 UTC, owner's word "Deploy now")

Why: cutover step 7's first WhatsApp upload was answered `405` by IIS itself (`Allow: GET, HEAD,
OPTIONS, TRACE`, HTML body): the host-wide WebDAV module handles PUT before ASP.NET Core sees it,
and the channel-intake upload is a PUT. Sibyla Legacy's API removed the module and handler in its
web.config; the platform release `20260903-171530-97ac43a` carried the SDK default. Fix `d3e32c7`:
`src/Sibyla.Api/web.config` removes `WebDAVModule` and the `WebDAV` handler (guard test
`WebConfigTests`, Api suite 47/47).

Run: published from a clean detached worktree of `main` at `d3e32c7`
(`D:\fileStorage\repos\GOTT.Apollo-worktrees\apollo-release-d3e32c7`, because the main checkout
held another session's uncommitted work) with `local\publish-release.ps1 -Hosts api` (manifest
commit `d3e32c7feb6300f4fa8086567d7d9e01a31d55e4`, dirty false, 19 required migrations), then
`local\deploy-release.ps1 -Release 20260904-114642-d3e32c7 -Hosts api` at 11:47:24Z (5 s):
`Sibyla.Api` repointed to `C:\Apps\Sibyla\api\20260904-114642-d3e32c7`, previous
`20260903-171530-97ac43a` recorded in `PREVIOUS.txt`; the script's health checks `/health` and
`/health/ready` returned 200. Guards before the run: no `wacs` process, no other deployment
process, win-acme's next scheduled run 2026-09-05 09:03; the run was inside the 09:00–15:00 UTC
window on the owner's explicit word.

Verification: installed `web.config` and `Sibyla.Api.dll` hash-identical to the published ones;
`MANIFEST.json` release/commit/dirty/19 migrations; site and pool Started; effective site
configuration shows no `WebDAVModule` and no `WebDAV` handler; ANCM logged the shutdown of the
old application at 11:47:25Z and the successful start of the new one at 11:47:28Z, no
error-level event; `/health`, `/health/ready`, `/health/schema` 200 with role `sibyla_api` and the
same 19 ids; an unauthenticated `PUT` to the upload route now answers the API's own
`400 channel_intake_correlation_id_required` problem+json instead of IIS's 405. Web, worker,
docs, legacy objects, win-acme and the deployment module untouched. Rollback:
`local\rollback-release.ps1 -Target api`.

## 7f. Release `20260904-124259-bb6a121` on all three hosts — duplicate-control ruling (2026-09-04 12:44 UTC, owner's word "Do all 3")

Why: the owner ruling of 2026-09-04 (licence-wide duplicate lookup for company-less intakes and
no double extraction on release, `IngestionService`, merged as `82002a2`) runs inside the API
process for channel intakes and inside the web and worker for uploads and triage, so all three
hosts move together. Web and worker had run `20260903-002407-3fa3159` since the first deployment;
the API `20260904-114642-d3e32c7` since 11:47.

Run: clean detached worktree `apollo-release-bb6a121` at `main` `bb6a121`;
`local\publish-release.ps1` (57 s; manifest commit `bb6a1211d08edba9645bfae7043f98c6127ebdbe`,
dirty false, hosts web/api/worker, 19 required migrations — none new, so no migration ran);
`local\deploy-release.ps1 -Release 20260904-124259-bb6a121` at 12:44:27Z (11 s): `Sibyla.Web`
and `Sibyla.Api` repointed and recycled, `Sibyla.Worker.Documents` stopped 12:44:36 and running
again 12:44:37 on the new path; the script's health checks `/` 200, `/health` 200,
`/health/ready` 200. Guards: no `wacs`, no other deployment process, win-acme next run
2026-09-05 09:03; inside the 09:00–15:00 UTC window on the owner's explicit word.

Verification: both sites and pools Started on the release folders; service Running, Auto,
`.\SibylaWorker`, its `Environment` registry value intact; `MANIFEST.json` per host
release/commit/dirty/19; `PREVIOUS.txt` per host (web and worker → `…-3fa3159`, api →
`…-d3e32c7`); ANCM logged clean shutdown/start for both sites; `/`, `/health`, `/health/ready`,
`/health/schema`, docs 200; an unauthenticated `PUT` to the upload route still answers the
API's problem+json. Observed on the API start: three `DataProtection` warnings (ephemeral key
repository) — the API host keeps no key ring and none is needed for bearer tokens; noted, not
acted on. Rollback per host: `local\rollback-release.ps1 -Target web|api|worker`.

## 7g. Intake cutover step 8 — retirement of the legacy intake path (2026-09-04 12:46–12:48 UTC, owner's word)

After step 7 closed (all four legs observed, `apollo-email-intake` live since 12:39 UTC):

1. **`Sibyla.Legacy.Api`** (`api.legacy.gottsolutions.net`): site and pool stopped at 12:46:32Z.
   Its IIS log showed only crawler and favicon requests since 2026-09-03 22:51; no client.
   Nothing deleted; `Start-WebAppPool 'Sibyla.Legacy.Api'; Start-Website 'Sibyla.Legacy.Api'`
   restores it. `Sibyla.Legacy.Docs` untouched.
2. **Legacy plugin `sibyla-channel-intake`**: folder removed from the Hermes plugins directory
   and its `plugins.disabled` / `plugins.entries` lines removed from `config.yaml`; gateway
   restarted (drained cleanly; WhatsApp reconnected 12:47:45Z); `apollo-channel-intake` 1.1.0
   doctor OK, 3 tools, 1 hook. Pre-change copies under
   `D:\Backups\SibylaDeployment\20260904-124632\hermes-step8-pre\`.
3. **IdP client `sibyla-apolo`** deleted from `gott_identity` and the legacy resource
   `sibyla-api` removed from the scope `sibyla.channel-intake.write` (resources now
   `apollo-channel-intake` only) at 12:48:19Z, through `local\tools\RegisterIdpClients
   --retire-legacy-intake` (OpenIddict managers, dry run first; the client's descriptor is
   printed in the run output: display name "Sibyla Apolo Channel Intake", confidential, client
   credentials on the intake scope). Tokens already issued to the platform client keep the old
   audience until they expire; the API validates only its own.

Left as they were at that point: the paused legacy cron `sibyla-email-graph-gateway` (not named
by step 8), the legacy Docs site, `GottSibylaWorker` (Disabled since Phase 5), `gott_sibyla_legacy`.

## 7h. Legacy email cron deleted and legacy worker uninstalled (2026-09-04 13:12 UTC, owner's word)

1. Hermes cron `sibyla-email-graph-gateway` (`06a5e47ae554`, paused since 2026-08-25, the legacy
   Graph triage) removed with `hermes cron delete`; its definition is saved in the backup below.
   Its runner script `sibyla_email_gateway_runner.py` stays, because the live `apollo-email-gateway`
   cron runs the same script. Remaining crons: `backup-diario-hermes-gitlab`,
   `apollo-email-gateway`, `apollo-email-intake`.
2. Service `GottSibylaWorker` (Stopped, Disabled, account `.\GottSibylaDocumental`, no dependents)
   deleted with `sc.exe delete` at 13:12:45Z; the service and its registry key are gone, the
   binaries under `C:\SibylaApps\Sibyla.Worker` are kept (files were not in the order).
   `Sibyla.Worker.Documents` Running throughout. The service's configuration (`sc qc` and the
   WMI record) is saved under `D:\Backups\SibylaDeployment\20260904-131230\legacy-retirement\`.

Legacy still present on the box: `Sibyla.Legacy.Web` (Stopped) and `Sibyla.Legacy.Api` (Stopped)
sites and pools, `Sibyla.Legacy.Docs` (Started), the folders under `C:\SibylaApps`, the database
`gott_sibyla_legacy`, the account `.\GottSibylaDocumental`.

## 7i. Production test-residue cleanup and Fake harness boundary (2026-09-04 13:51 UTC, owner's word)

A read-only inventory found residue from the period before the suites were moved to Preview:
34 `ladder-test-<guid>` and 9 `md-test-<guid>` organizations in Main, with no licences, users,
intakes, jobs or audit rows; their 445 dependent fixture rows were confined to the ten expected
Argus tables. It also found 17 exact `Fake lifecycle test` AI projects, with 20 conversations,
3 project links, 25 messages, 15 executions and 28 audit rows. Their 12 recorded event paths no
longer existed and there were no workspace paths. An exact-marker scan found no further fixture
rows under the two real Main organizations. Preview was clean.

Before mutation, a full custom-format `pg_dump` of the 72 MB Main database was written to
`D:\Backups\SibylaDataCleanup\20260904-135125\gott_sibyla-before-test-residue-cleanup.dump`
(6,057,078 bytes, SHA-256
`C5C150B10B1F2D661B47D090D55904B5A329AD23A63731479AA7AAB46F16359F`, 1,052 archive TOC lines).
One transaction materialized only the strict GUID-suffixed owner/project ids, asserted all counts
above and asserted zero protected operational rows, deleted the dependent rows in FK order, then
deleted the 43 organizations and 17 projects. Every expected delete count matched and the
transaction committed. Post-check: Main has 2 owners, 2 licences, 0 matching test owners, 0 fake
projects and 0 fake conversations; Preview has 1 owner, 1 licence and zero fixture residue.

The application registration is hardened with the same change: `FakeHarness` is no longer a
normal `AddSibylaPlatform` service. `Sibyla.Web` opts it in only when
`Sibyla:TestHarness=true`; `PreviewConnectionGuard` already makes that setting refuse Main
credentials. Production therefore exposes only Codex and Claude while deterministic lifecycle
tests retain the fake on Preview.

## 7j. Release `20260904-142821-ecf8ca0` on all three hosts and plugin 1.1.1 — D-CI-10 final-review fixes (2026-09-04 14:28–14:31 UTC, owner's word "do it, install the plugin and restart the gateway. And deploy")

Source: main merge `ecf8ca0` (final-review fixes; review record "Final review"). Published from
a clean detached worktree `apollo-release-ecf8ca0` with `local\publish-release.ps1` (61 s;
manifest commit `ecf8ca0`, dirty false), removed after the deploy.

1. **Release.** `local\deploy-release.ps1 -Release 20260904-142821-ecf8ca0` at 14:29:55Z (12 s):
   `Sibyla.Web` → `C:\Apps\Sibyla\web\20260904-142821-ecf8ca0` (health `/` 200), `Sibyla.Api` →
   `…\api\20260904-142821-ecf8ca0` (`/health` 200, `/health/ready` 200, `/health/schema` 200 with
   role `sibyla_api`), `Sibyla.Worker.Documents` → `…\worker\20260904-142821-ecf8ca0` (Running,
   Automatic). `PREVIOUS.txt` on every host = `20260904-124259-bb6a121`, the rollback target
   (`local\rollback-release.ps1 -Target web|api|worker`). Carries: `ReleaseQuarantineAsync`
   licence-wide duplicate rule for company-less releases; `trustedMetadata` refuses `null`
   members; the request log names the registration id.
2. **Plugin 1.1.1.** Pre-change copies of the plugin folder, the intake skill and `.hermes.md` under
   `D:\Backups\SibylaDeployment\20260904-142813\hermes-final-review-pre\`. Skill
   `sibyla-channel-intake-operations` step 2 gained one sentence: `received_at_source` is
   `gateway` or `dispatch-clock`, and text reading `[sender-typed text, not a gateway envelope:`
   is a caption the sender typed, never an envelope. `local\hermes\install-plugin.ps1 -Force`
   installed the plugin (deployed `envelope.py` sha256 `3edfecd8…` = repository). `hermes gateway
   restart` at 14:30:48Z: drained cleanly (0 active, 0 cron), WhatsApp disconnected 14:30:50Z and
   reconnected 14:31:00Z; plugin doctor: `apollo-channel-intake 1.1.1`, 3 tools, 1 hook. The
   `Hermes_Gateway` scheduled task is unchanged (the CLI spawns the process directly).

Rollback: release as above; plugin by copying the backup folder over
`%LOCALAPPDATA%\hermes\plugins\apollo-channel-intake` and the skill file back, then
`hermes gateway restart`.

## 7k. Web-only release `20260904-150742-fa5d2df` — Uploads page ruling buttons and evidence modal (2026-09-04 15:08 UTC, owner's request)

The owner could not find the "É duplicado / Não é — processar" buttons for the two held copies of
the AWS invoice, and the inline processing-evidence table was unreadable. Cause: the page's result
cell was one if/else-if chain with the evidence branch first, so any document processed at least
once (both held copies were, before the hold) never rendered its status actions; the evidence table
used a CSS class that did not exist and sat in a 34 rem cell. Fix implemented by a delegated Opus
agent on `ops/uploads-evidence-modal` (head `572dd84`, merged `fa5d2df`): status actions render from
their own `@switch`, independent of evidence; the evidence opens from an "Evidência (N)" button in
the app's wide modal panel (Fechar, Escape, overlay click) with a five-column table and the hashes
and paths on a second quiet line; `.sib-evidence` styles added. Browser suite 122/122 on Preview,
including a new render test that fails on the old markup and passes on the new one (the harness is
a server-side prerender, so the click itself is not exercised).

`local\publish-release.ps1 -Hosts web` from a clean detached worktree at `fa5d2df`, then
`local\deploy-release.ps1 -Release 20260904-150742-fa5d2df -Hosts web` at 15:08:39Z: `Sibyla.Web` →
`C:\Apps\Sibyla\web\20260904-150742-fa5d2df` (health `/` 200; new stylesheet present). API and
worker stay on `20260904-142821-ecf8ca0`. Rollback: `local\rollback-release.ps1 -Target web`
(`PREVIOUS.txt` = `20260904-142821-ecf8ca0`).

## 7l. Release `20260905-135846-bb8b376` on all three hosts — Hermes harness, bilingual UI and AI project administration (2026-09-05 14:02 UTC, owner's word "lets deploy")

Source: `main` head `bb8b376` (Hermes harness `9039589`, bilingual UI and AI project
administration `1250d7c`, the day's plan rulings, the `CliProcessRunnerTests` hidden-window fix
`461cc50`). Published from a clean detached worktree `apollo-release-bb8b376`
(`D:\fileStorage\repos\GOTT.Apollo-worktrees\`, removed after the deploy) with
`local\publish-release.ps1` at 13:58:46Z: manifest commit `bb8b376`, dirty false, SDK 10.0.301,
`requiredMigrations` ending in `20260905010737_HermesHarnessProfiles`.

Before the deploy: `local\test.ps1` on `main` 519/519 (TenantIsolation 58, Platform 141, Browser
127, Api 56, Argus 137); `local\migrate.ps1 -Target All` reported Main and Preview "already up to
date" (the harness migration had been applied by the development session, harness plan entry of
2026-09-05). Hand path, outside the E2 window (D-E2-2: the 2026-09-05 slot is still to be named and
starts at or after 15:30 UTC).

1. **Release.** `local\deploy-release.ps1 -Release 20260905-135846-bb8b376` at 14:02:09Z (12 s):
   `Sibyla.Web` → `C:\Apps\Sibyla\web\20260905-135846-bb8b376` (health `/` 200), `Sibyla.Api` →
   `…\api\20260905-135846-bb8b376` (`/health` 200, `/health/ready` 200, `/health/schema` 200 with
   role `sibyla_api` and 20 migrations, the last `20260905010737_HermesHarnessProfiles`),
   `Sibyla.Worker.Documents` → `…\worker\20260905-135846-bb8b376` (Running, Automatic).
   `PREVIOUS.txt`: web `20260904-150742-fa5d2df`, api and worker `20260904-142821-ecf8ca0`. No
   error-level event after activation; the EF errors logged 14:00:40–14:01:01Z belong to the test
   suite's failure-path tests on Preview (developer exception page), before the deploy.
2. **What the harness still lacks in production (harness plan §8, unchanged).** The web secrets
   file `C:\ProgramData\Sibyla\secrets\web.json` has no `AiHarness` section (no Hermes
   `ExecutablePath`, no `ReaderConnectionString`), and the `Sibyla.Web` app-pool identity holds none
   of the Administrator's CLI credentials (`%LOCALAPPDATA%\hermes`, `~/.claude`, `~/.codex`). A
   Hermes turn started from the production UI fails closed ("Hermes AI-reader database credentials
   are not configured"); harness runs stay on the `local\run-web.ps1` prototype path. Live from this
   release: the `aiprof` table with the NP Group → `default` profile seed, the AI project
   administration and the bilingual UI.

Rollback: `local\rollback-release.ps1 -Target web|api|worker` (`PREVIOUS.txt` as above).

## 7m. Hermes harness configured for production (2026-09-05 14:39–14:58 UTC, owner's word "lets configure the harness for production")

Closes the §8 execution-identity gap of the harness plan for Hermes on the hand path: the
`Sibyla.Web` pool keeps `ApplicationPoolIdentity`; the Hermes CLI it spawns gets its own home and
its own credential, never the gateway's. Pre-change copy of `web.json` under
`D:\Backups\SibylaDeployment\20260905-143919\hermes-web-pre\`.

1. **Dedicated Hermes home** `D:\ApolloData\web-hermes` (exact ACL: SYSTEM and Administrators
   Full, `IIS AppPool\Sibyla.Web` Modify): `config.yaml` with the gateway's model block only
   (`gpt-5.6-sol`, provider `openai-codex`), `SOUL.md` copied from the gateway home, no `.env`, no
   plugins, no gateway state. `HERMES_PROFILE=default` from the harness resolves to this root;
   per-licence profiles (slice 11) will live under its `profiles\`.
2. **Credential.** The owner ran `hermes auth add openai-codex --no-browser` with
   `HERMES_HOME=D:\ApolloData\web-hermes` (device-code flow, own ChatGPT login): `auth.json`
   (2,784 bytes) in the web home, inherited ACL, `hermes auth status openai-codex` = logged in.
   The gateway's `auth.json` and `.env` were not copied.
3. **Runtime reachability for the pool identity.** `Traverse` only (no listing, not inherited) on
   `C:\Users\Administrator`, `…\AppData`, `…\AppData\Local`, `…\AppData\Local\hermes`,
   `…\AppData\Roaming`, `…\AppData\Roaming\uv`; `ReadAndExecute` (inherited) on
   `…\AppData\Local\hermes\hermes-agent` (source and venv) and `…\AppData\Roaming\uv\python`
   (CPython 3.11). The gateway root's own files (`.env`, `auth.json`, sessions) stay unreadable.
   Host-specific: recorded here, not scripted.
4. **`web.json`** gained `AiHarness:Hermes` — `ExecutablePath` (the venv `hermes.exe`),
   `TimeoutMinutes` 10, `ReaderConnectionString` for `apollo_ai_reader` on `gott_sibyla`
   (verified: LOGIN, NOBYPASSRLS, not superuser, SELECT as its only table privilege).
5. **IIS.** `HERMES_HOME=D:\ApolloData\web-hermes` in the site's `aspNetCore` environment
   variables; pool `loadUserProfile=true` so the child gets a real profile and TEMP
   (`C:\Users\Sibyla.Web` exists). Both now also in `local\provision-production.ps1`. IIS restarted
   the site at 14:42:39Z; `/` 200, API health 200.
6. **Smoke turn** as the operator with the harness's exact environment (`HERMES_HOME`,
   `PGHOST/PGPORT/PGDATABASE/PGUSER/PGPASSWORD` of the AI reader, `PGOPTIONS=-c app.owner_id=<NP
   Group>`, `HERMES_PROFILE=default`): `hermes chat -q … -Q --source tool` answered `ROWS=1` for
   `ownmst` through psql in 24 s (only the pinned organization's row is visible) and wrote
   `session_id: 20260905_145711_e1a7f6` to stderr, the line the harness captures.

Not configured: the Codex and Claude harnesses under IIS (no credentials for the pool identity;
they remain on the `run-web.ps1` prototype path), and per-licence Hermes profiles (slice 11).
Rollback: remove `HERMES_HOME` from the site, restore `web.json` from the backup, recycle the
pool; the ACL grants and the home folder can stay or be removed with `icacls … /remove`.

## 7n. First production Hermes turn and two fixes (2026-09-06 01:20–01:50 UTC)

The owner asked "how many organizations can you see" in conversation `dc5e2625-…` at 01:20:06Z.
The pipeline worked end to end under the pool identity: execution `4836b66f…` spawned
`hermes.exe chat -q -Q --source tool --reasoning high`, captured native session
`20260906_012009_d26ba8`, exit 0, answer persisted at 01:24:51Z. Two defects in the answer:

1. **Hermes could not run psql.** Its terminal tool resolves bash from `%LOCALAPPDATA%\hermes\git`
   of the *current* user, then Git-for-Windows paths, then `PATH`; for the pool identity that is
   `C:\Users\Sibyla.Web\…` (nothing there) and the machine `PATH`, which finds the WSL launcher
   `System32\bash.exe` with no distribution. Fix on the host: `HERMES_GIT_BASH_PATH=
   C:\Users\Administrator\AppData\Local\hermes\git\bin\bash.exe` on the site's `aspNetCore`
   environment (Hermes' documented override) and `ReadAndExecute` (inherited) for
   `IIS AppPool\Sibyla.Web` on `…\hermes\git`. Host-specific, so documented here, not scripted.
2. **Mojibake** (`canΓÇÖt`): the child writes UTF-8, the harness read it in the OEM code page.
   Fix in code: `CliProcessRunner` sets `StandardOutputEncoding`/`StandardErrorEncoding` to UTF-8
   (Platform 141/141); belt and braces on the host: `PYTHONIOENCODING=utf-8` and `PYTHONUTF8=1` on
   the site (also in `provision-production.ps1`). The code fix ships with the next web release.
3. **A spinner line in the answer** (`[tool] (face) reflecting...`): Hermes' spinner writes it once to
   stdout when stdout is a pipe. Two guards: `display.tool_progress: off` in the web home's
   `config.yaml` (Hermes' own gate), and `HermesHarness` now drops stdout lines starting with
   `[tool] ` before they reach the persisted answer (unit test; the leak could not be reproduced
   from a console, so the harness guard does not depend on the configuration). Ships with the
   next web release.

Also noted: a turn at `--reasoning high` that fights its terminal takes four to five minutes; the
UI shows nothing until the final answer because Hermes' quiet mode is non-streaming (harness plan,
Hermes section). IIS restarted the site on the environment change; `/` 200.

## 7o. Slice 2 E2 — the module deployed production; the hand path is retired as the deployment method (2026-09-05 15:54 → 2026-09-06 01:13 UTC, owner at the console; checkpoint closed 2026-09-06 ~02:00 UTC)

The Sibyla.Deployment module ran its first production executions through the tracked runner
`local\deploy\tests\Sibyla.Deployment.Tests\probes\e2-execute-v2.ps1` (elevated, interactive, one
step per privilege proof; the session launched none of them). Full record:
`local\deploy\tests\Sibyla.Deployment.Tests\evidence\E2-*.{txt,md}` and `CHECKPOINT-E2-review.md`
(both independent reviewers ACCEPT); spec section 9, "E2 passed 2026-09-06"; merge `baa1f32`.

1. **What ran.** Gate commit `d6c4f79` in a detached clone `D:\fileStorage\tmp\apollo-e2\gate`,
   two clean releases published by `publish-release.ps1` from it. `-Execute -WhatIf` (Planned,
   161 entries). Full `-Execute` of `20260905-155303-d6c4f79` at 00:50 UTC (transaction
   `21bbff76`, Executed, 12/12) after three stopped attempts that each rolled the host back to its
   snapshot and surfaced a module defect (ACL compensation readbacks, install-root descent, secrets
   leaves as files). An injected fault on `20260905-155351-d6c4f79` (transaction `1255f3a0`:
   RollbackIncomplete; a fourth defect in the rollback of a failed publish), then `-Execute -Resume`
   (RolledBack). Roll forward: full `-Execute` of `20260905-155351-d6c4f79` at 01:12 UTC
   (transaction `1d8d606d`, Executed, 12/12).
2. **State now.** `Sibyla.Web`, `Sibyla.Api` on `C:\Apps\Sibyla\{web,api}\20260905-155351-d6c4f79`,
   `Sibyla.Worker.Documents` on `…\worker\20260905-155351-d6c4f79`; `CURRENT.txt` =
   `20260905-155351-d6c4f79` and `PREVIOUS.txt` = `20260905-155303-d6c4f79` on all three hosts —
   **bare release ids, the module's format** (the hand path wrote full paths). Every earlier
   release folder kept; the hand path's last release `20260905-135846-bb8b376` (§7l) is the
   pre-E2 baseline. Failed copies under each host's `.staging\` (`20260905-155303-d6c4f79.failed-…`
   ×2 on every host, `20260905-155351-d6c4f79.failed-1255f3a0-…` on web): the rollbacks' work,
   removable at the owner's word. Five journals under `D:\ApolloData` (`df2867af`, `776693b5`,
   `21bbff76`, `1255f3a0`, `1d8d606d`).
3. **IIS backups taken by the runner, never restored:** `SibylaE2-20260905-155807`,
   `SibylaE2-20260906-003107`, `SibylaE2-20260906-005039`, `SibylaE2-20260906-005342`,
   `SibylaE2-20260906-011253` (`appcmd list backup`; restore is the owner's, by hand).
4. **Hand-over (spec section 10).** From here the module is the deployment method:
   `Invoke-SibylaDeployment -Execute` through the E2 runner pattern (candidate bound by commit and
   fingerprint, gate clone, privilege proof, IIS backup, journal). `publish-release.ps1` stays the
   publisher (the module never builds). `deploy-release.ps1` is retired as the activation step.
   `rollback-release.ps1` remains the emergency exit **with `-ToPath`** (its documented form): it
   reads `PREVIOUS.txt` as a path and refuses the bare id the module writes; after a hand rollback
   the pointer files hold full paths again, which the module tolerates (it derives "previous" from
   the live physical path / binPath, spec section 2). Rollback by the module: `-Execute -Resume
   <transactionId>` on a `RollbackIncomplete` journal, or a fresh `-Execute` of the previous
   release's staged tree.
5. **Untouched all night:** `Sibyla.Legacy.*`, `GottSibylaWorker`, `gott_sibyla_legacy`, win-acme
   (every step outside 09:00–15:00 UTC; the server clock was resynchronised at 15:49:36 UTC on
   2026-09-05), the Hermes configuration and crons, the secrets' contents. `-Force`,
   `-NoRollbackOnHealth` and `Restore-WebConfiguration` were never used.

## 7p. Release `20260906-111227-2c8e5f2` on all three hosts by the module — Hermes harness spinner fix (2026-09-06 19:15–19:16 UTC, owner at the elevated console; prepared 11:12 UTC, owner's word "deploy first then start Phase 2 extraction work")

The first routine deployment through the module after E2 (§7o): the session prepared everything
with `D:\fileStorage\tmp\apollo-deploy\Prepare-Deploy.ps1` (gate clone
`D:\fileStorage\tmp\apollo-deploy\gate` at `2c8e5f2`, one clean release published by
`publish-release.ps1`, a detached candidate worktree at the same commit with the module built and its
fingerprint equal to the clean export), and the owner ran the tracked launcher line at the console —
the session launched nothing. The 15:00 UTC slot passed unused; the owner ran it at 19:15 UTC.

1. **What ran.** `e2-launch-v2.ps1 -Step Execute` → privilege proof (D2 read-only query, `sibyla_api`
   SELECT on `__EFMigrationsHistory`: TRUE, 0.01 min old at start) → `e2-execute-v2.ps1` →
   `Invoke-SibylaDeployment -Execute` on staging root
   `…\gate\artifacts\publish\20260906-111227-2c8e5f2` (release.json sha256 `725cac55…`, 20 required
   migrations, none new — `SchemaObserved` = `role=ok migrations=20 sha256=3eb4e28d…` twice). Candidate
   bound by commit `2c8e5f2`, fingerprint `c382417c…` (235 files), C2 ancestor `5121db6`; module
   artifacts hashed in the result. Transaction `596256ab-0fde-4cb0-a639-7b8a34653915`: **Executed**,
   161 plan entries (ReleaseGate 1, Publish 5, Install 96, Configure 44, Health 15), 110 executed /
   51 skipped / 0 failed / 0 compensated, **12/12 health checks**, 67 seconds (19:15:26 → 19:16:33).
2. **State now.** `Sibyla.Web`, `Sibyla.Api` on `C:\Apps\Sibyla\{web,api}\20260906-111227-2c8e5f2`,
   `Sibyla.Worker.Documents` on `…\worker\20260906-111227-2c8e5f2` (service Running, Auto);
   `CURRENT.txt` = `20260906-111227-2c8e5f2`, `PREVIOUS.txt` = `20260905-155351-d6c4f79` on all three
   hosts (bare ids). Web and api restarted 19:16:07–19:16:31 (IIS AspNetCore Module events), the
   worker restarted 19:16:06–19:16:07 (SCM 7036). Six journals under `D:\ApolloData`.
3. **Evidence.** `D:\fileStorage\tmp\apollo-deploy\results\E2-Execute-20260906-191511-{result.json,
   result.journal.jsonl,privilege.json,transcript.log,done.txt}`; journal copy sha256
   `c8f69a6ab700ae4dd7db31713fc70bfdb78911b3d5312878cd0560b279648eff` (278 lines, equal to the source
   `D:\ApolloData\596256ab-….jsonl`). IIS backup taken by the runner, never restored:
   `SibylaE2-20260906-191526`. Operator `EC2AMAZ-NTPJCNO\Administrator`.
4. **Rollback of this release** (§8): `Invoke-SibylaDeployment -Execute` of the previous release's
   staged tree, or `local\rollback-release.ps1 -Target <host> -ToPath C:\Apps\Sibyla\<host>\20260905-155351-d6c4f79`.
5. **Untouched:** `Sibyla.Legacy.*`, `gott_sibyla_legacy`, win-acme (19:15 UTC is outside 09:00–15:00),
   the Hermes configuration and crons, the secrets' contents. `-Force`, `-NoRollbackOnHealth` and
   `Restore-WebConfiguration` were never used. The candidate worktree was unregistered afterwards.

## 7q. Uploads page: Refresh showed a processed document as Queued (2026-09-07 09:37–10:30 UTC, owner's report)

The owner uploaded `Gott_Invoice_BICS_202601_01.pdf` without a company at 09:37:51Z. The worker
processed it at 09:38:04Z (contract `sibyla.extract.v1`, recipient `PT513362061`) and the one-sided
gate assigned GOTT; `docint` said so. The page kept showing Queued and the Triage box after Refresh.

Cause: `IngestionService.ListAsync` queried with tracking on the circuit's scoped `SibylaDbContext`;
EF identity resolution returns the instances already tracked from the first load, so every later
list carried the first load's values until the circuit was recreated (a full page load). Fix:
`AsNoTracking()` on the list (the page mutates rows by id through the service, never through the
listed instances). Regression test `ListAsyncOnTheSameScopeSeesWhatTheWorkerChangedMeanwhile`
(red without the fix, green with it). Ships with the next web release.

Hotfix release prepared 10:07–10:40 UTC, not launched: `main` head now carries the extraction v1 build
(G1, G2 and half of G3 with migration `20260907094356_ExtractionV2HoldReason`, applied to Preview only),
which the extraction spec sequences on its own terms, so the fix was cherry-picked onto
`hotfix/uploads-refresh` = deployed `2c8e5f2` + `84d8676` (C2 ancestor holds). `Prepare-Deploy.ps1`:
gate clone `D:\fileStorage\tmp\apollo-deploy\gate-hotfix-84d8676`, release `20260907-100739-84d8676`
(20 required migrations, none new), candidate worktree at `84d8676`, fingerprint `c382417c…` equal to
the clean export. Suites on that tree: Platform 143, Browser 128, Api 56, Argus 137, TenantIsolation
57 green; `PreviewHasExactlyTheSameMigrations` red as expected until the owner migrates Main (G3
commit `6e47b59`). Launch line printed for the owner's elevated console, after 15:00 UTC (D-E2-2).

## 8. Rollback of this deployment in one line each

- Web: `local\rollback-release.ps1 -Target web -ToPath <older C:\Apps\Sibyla\web\…>` (or stop the
  site: `Stop-Website Sibyla.Web`). API and worker likewise. Nothing legacy was changed except the
  IIS names; `Rename-Item IIS:\Sites\Sibyla.Legacy.Web Sibyla.Web` (and the pool) restores those,
  or `Restore-WebConfiguration -Name SibylaDeploy-20260903-001541` restores the whole IIS
  configuration of 00:15 UTC (before the platform sites existed).
- **After E2 (2026-09-06):** the pointer files hold bare release ids; use `-ToPath` (the form above) — `rollback-release.ps1` refuses a bare `PREVIOUS.txt` rather than mis-pointing. The five `SibylaE2-*` IIS backups (§7o) are restorable by the owner with `Restore-WebConfiguration -Name <backup>`; the module itself rolls back with `-Execute -Resume <transactionId>` or a fresh `-Execute` of the previous staged release.
