# Sub-slice E2 prompt — Sibyla.Deployment Slice 2, the first module-driven production execution

*Written 2026-09-04 after checkpoint C2+D2 closed with both independent reviewers at ACCEPT on
C2 `a2def6b` / D2 `4ca647b` (record:
`local/deploy/tests/Sibyla.Deployment.Tests/evidence/CHECKPOINT-C2D2-review.md`; merged to `main`
as `b038154`). Hand the fenced block to a fresh agent session **only after the owner has named the
E2 time**; everything above and below the block is context for the owner.*

Why E2 is its own session and needs a named time: it is the first time the module writes to the
production host (publish, ACLs, IIS, service, active-install pointers), and it deliberately
provokes a Configure failure to prove `-Resume`. Spec section 9 row E2 requires it "at a time the
owner names, outside the renewal window, run as the principal that holds the `Operator` Modify
ACE on `DocsPath`" (today `EC2AMAZ-NTPJCNO\Administrator`).

## Decisions the owner must take before the session starts

| # | Decision | Recommendation |
|---|---|---|
| D-E2-1 | **Which commit the parallel release is published from.** Spec: "full `-Execute` on a parallel release of the same commit". Since 2026-09-04 12:44 UTC all three hosts run one commit, `bb6a121` (release `20260904-124259-bb6a121`, hand path, run record §7f), so "the same commit" is unambiguous. | Publish `bb6a121` (or the `main` head of the day if it has moved and the owner accepts the delta) for all three hosts with `local\publish-release.ps1` from a clean worktree; a release of the running commit is the code-neutral switch the spec describes. |
| D-E2-2 | **The window.** The run has to be scheduled with its *whole* expected duration outside 09:00–15:00 UTC (the D2 runner checked the window only at start; a 22-second run could not cross it, E2 can). Budget: `-WhatIf` ≈ 2 min, full `-Execute` ≈ 5–10 min (publish copies, two pool recycles, the 20-second service stability window, health checks), injected failure + `-Resume` ≈ 10 min, roll forward ≈ 10 min, inspections between steps. | A 2-hour slot starting no earlier than 15:30 UTC or ending no later than 08:30 UTC, with no hand-path deploy and no win-acme run inside it. |
| D-E2-3 | **The injected Configure failure.** The spec names "an injected Configure failure" without choosing it. | Keep the fault outside IIS and outside the module (no test-only switch exists, and none is added): **after `PublishTree` has succeeded and before Configure, deny the running principal write access to one file under the *parallel* release's `web` tree** so `Acl.Apply` on that install tree fails typed; remove the deny in one `icacls` command and `-Resume`. The exact fault, its detection in the journal and its one-command reversal are written into the RED oracle before the run. |
| D-E2-4 | **Roll forward or roll back after the resume.** | Roll forward (the spec's wording) so the parallel release becomes the active one; keep the previous releases as rollback targets (`PREVIOUS.txt` and `local\rollback-release.ps1` remain valid). |
| D-E2-5 | **`ExpectedCommit` for the run.** The D2 runner hard-codes `97ac43a`; the full plan reads the repository HEAD against `ExpectedCommit`. | The E2 runner takes `-ExpectedCommit` as a mandatory parameter and it is the commit of D-E2-1, verified against `git -C D:\fileStorage\repos\GOTT.Apollo rev-parse HEAD` and the release manifest before the run. |

## Owner rulings (2026-09-04, 15:35 UTC — "accept all five recommendations")

State at the time of the rulings: web runs `20260904-150742-fa5d2df`, api and worker run
`20260904-142821-ecf8ca0` (run record §7j–§7k); main head `7ea96c6` differs from `fa5d2df` only in
`local/deploy` and documents, and `fa5d2df` differs from `ecf8ca0` only in the web project, so one
release of the main head is behaviour-neutral on all three hosts. E2 prep is merged (`666bc9a`,
`evidence/E2-prep-green.txt`).

| # | Ruling |
|---|---|
| D-E2-1 | The parallel release is published from the **`main` head at the moment the E2 session starts** (today `7ea96c6`), for all three hosts, from a clean detached worktree with `local\publish-release.ps1`. The session records that commit as the gate commit before any step. |
| D-E2-2 | A **single two-hour slot** wholly outside 09:00–15:00 UTC — starting at or after 15:30 UTC, or ending by 08:30 UTC — with the owner present for the interactive privilege proof at every executing step; no hand-path deploy and no win-acme run inside it. **Run 2026-09-05 15:54 → 2026-09-06 01:13 UTC in two sittings** (owner's word "start now" at 15:42 UTC on 2026-09-05; the 2026-09-04 15:45 slot had been opened and closed with no production step). The owner ran every executing step from an elevated console (the harness refuses to let the session launch them); the session prepared, analysed, fixed and recorded between steps. Every executing step took a fresh privilege proof (15-minute freshness) and the module's own confirmation. E2 runs in the session that prepared it rather than a fresh one, because the privilege proof at each executing step needs the owner in the same conversation. E2 is a one-time proving run; nothing here recurs. |
| D-E2-3 | The injected failure is **an ACL fault on one file under the parallel release's `web` tree**, placed after `PublishTree` succeeds and before Configure. **Amended 2026-09-05 while typing the RED oracle** (`evidence/E2-red.txt`, `oracles/e2.v2.json`): `Acl.Apply` writes only the target folder's own ACL and cannot fail on a descendant, so the fault is one explicit foreign Allow ACE (`NT AUTHORITY\LOCAL SERVICE`, ReadAndExecute, never a deny) that makes `Acl.Readback(InstallRoot)` fail typed `SIBYLA-S2-READBACK-ACL`; and because a cleanly rolled-back journal refuses `-Resume` (section 6), the same tracked watcher holds that file open so the `PublishTree(web)` rollback is journaled `CompensationFailed` and the run ends `RollbackIncomplete`, the state `-Resume` exists for. One command (a stop file) undoes both; the Configure phase, IIS and the service are never reached by the fault. **Pointer note for D-E2-4:** the module writes the bare release id into `CURRENT.txt`/`PREVIOUS.txt` (spec section 2), the hand path wrote full paths; after E2-4 `local\rollback-release.ps1` therefore needs `-ToPath` (its documented form) instead of reading `PREVIOUS.txt`. |
| D-E2-4 | **Roll forward**: the resumed parallel release becomes the active one; the pre-E2 releases remain the rollback targets (`PREVIOUS.txt`, `local\rollback-release.ps1`). |
| D-E2-5 | The E2 runner takes **`-ExpectedCommit` as a mandatory parameter equal to D-E2-1's commit**, verified against `git rev-parse HEAD` of the candidate worktree and the release manifest before the run; the D2 runner's hard-coded `97ac43a` is not reused. |

## The prompt

```text
You are working in D:\fileStorage\repos\GOTT.Apollo (Windows Server 2025, .NET SDK 10, PowerShell 5.1
for the module; this host is the production host, so every rule below is a safety rule).
Read these first, in this order, and treat them as the authority:

  1. docs/apollo-deployment-slice2-spec.md            — Slice 2 specification, revision 10, ACCEPTED:
                                                        sections 2 (facts of the hand path), 4 (switches),
                                                        5 (execution: 5.1 adapter rules, 5.2 phase table,
                                                        5.3 invoker rules, 5.4 publish, 5.7 compile timing),
                                                        6 (journal and resume), 7 (health), 8 (redaction),
                                                        9 row E2 and the closed C2+D2 checkpoint paragraphs,
                                                        10 (operational restrictions)
  2. local/deploy/tests/Sibyla.Deployment.Tests/evidence/CHECKPOINT-C2D2-review.md
                                                      — both reviewers' reports; their "Notes for E2" are
                                                        binding inputs to your oracles
  3. local/deploy/tests/Sibyla.Deployment.Tests/evidence/D2-run-r3.md, D2-r3-result.json,
     probes/d2-checks-only-v2.ps1, probes/d2-privilege-v2.ps1
                                                      — the accepted read-only binding pattern you extend
  4. docs/apollo-deployment-run-260903.md             — how production was deployed by hand; the rollback lines
  5. docs/apollo-deployment-slice2-e2-prompt-260904.md — this file: the owner's decisions D-E2-1..5 filled in
  6. local/deploy/ on main (head b038154 or later): src/Sibyla.Deployment.Execution (engine, journal,
     resume), src/Sibyla.Deployment.Adapters.Windows (the eight adapters), Sibyla.Deployment/ (module)

GOAL
Deliver sub-slice E2 exactly as spec section 9 row E2 defines it, in this order, each step with its
RED oracle typed and committed before the step runs and its evidence recorded before the next:
  E2-1  full `Invoke-SibylaDeployment -Execute -WhatIf` against production: the complete compiled plan
        for the parallel release (every phase digest, every intent, the ACL target table of section 2),
        no mutation, journal untouched;
  E2-2  full `-Execute` of the parallel release of the commit named in D-E2-1: publish, ACLs, IIS, service,
        active-install pointers, health (section 7, 12 checks) — the journal under D:\ApolloData records it;
  E2-3  the injected Configure failure of D-E2-3 on a second parallel release: the run rolls back per
        5.3/6 (pools and service back on the snapshot release, `RolledBack` or `RollbackIncomplete`
        trailer as the spec predicts), then the fault is removed and `-Execute -Resume <transactionId>`
        completes it per section 6;
  E2-4  roll forward (D-E2-4): the resumed release is the active one; PREVIOUS.txt and the rollback
        scripts still point at the pre-E2 releases.
Then the final checkpoint: two independent read-only reviewers over the whole Slice 2 evidence record.

BINDINGS (extend the D2 pattern; a tracked runner probes/e2-execute-v2.ps1 enforces every one)
  - elevated Windows PowerShell 5.1, run as the principal that holds the Operator Modify ACE on DocsPath
    (Acl.Readback(DocsPath) compares that ACE to the journaled Operator);
  - the whole slot outside 09:00–15:00 UTC (D-E2-2); refuse if the remaining slot is shorter than the
    step's budget; refuse while wacs or a hand-path script runs (Win32_Process command line);
  - clean exact candidate worktree (the branch below) at a recorded commit, source fingerprint from the
    worktree equal to the clean `git archive` export (check the worktree out with the repository's default
    line-ending conversion; on this machine `git archive` applies CRLF — see D2-run-r3.md), module artifact
    hashes and runner hash recorded, C2 ancestor 5121db6 verified;
  - `-ExpectedCommit` = D-E2-1's commit, verified against the repository HEAD and the release manifest
    before the run (the D2 runner's hard-coded 97ac43a is NOT reused);
  - fresh interactive privilege proof (probes/d2-privilege-v2.ps1, 15-minute freshness) before every
    executing step, exactly as D2;
  - before/after state records per step: applicationHost.config hash, production metadata hash,
    the framed journal set, PREVIOUS.txt/CURRENT.txt of the three hosts, the SCM ImagePath, the three
    protected-hash style exclusions are NOT applicable here (production is the target) — record raw hashes;
  - Backup-WebConfiguration named SibylaE2-<yyyyMMdd-HHmmss> before E2-2 and E2-3, never restored by the
    session; its name is in the run record; restore is the owner's by hand.

REVIEWERS' NOTES FOR E2 (from CHECKPOINT-C2D2-review.md; each becomes an oracle row or a runner check)
  - The runner's ExpectedCommit must be the real gate commit (D-E2-5).
  - Schedule the whole duration outside 09:00–15:00 UTC (D-E2-2); the runner refuses a slot too short.
  - Precondition.Schema no longer renders the /health/schema body: under D-S2-7 (ruled 2026-09-04) its
    Observed is "role=ok|mismatch migrations=<n> sha256=<hex>[ overlimit=true][ missing=<n>]". The E2-1
    -WhatIf and the E2-2 journal must show that shape; the guard test SchemaBodyRedactionGuardTests
    stays as a second line.
  - Record both the CRLF working-file and the LF blob SHA-256 of every committed artifact.
  - The harness change of ops/sibyla-deployment-e2-prep (protected hashes recorded in finally for every
    disposable probe run) is in place; if any disposable probe is run again in E2, use it.

PROCEDURE (Slice 1 section 9 discipline, unchanged)
  1. Branch ops/sibyla-deployment-slice2-e2 from main; worktree under
     D:\fileStorage\repos\GOTT.Apollo-worktrees\; keep temp files on D:\fileStorage\tmp\<session>\.
  2. Type the E2 oracles (the -WhatIf plan expectation from sections 2/5.2 for the live inputs; the
     journal shape of section 6 for E2-2; the rollback and resume expectations of 5.3/6 for E2-3 with
     the exact injected fault and its one-command reversal; the roll-forward state for E2-4) and the
     runner's refusals. COMMIT THE RED STATE BEFORE ANY PRODUCTION STEP; save evidence/E2-red.txt with the
     framed SHA-256 from a clean export. A behaviour test that passes on its first run is a HARD STOP.
  3. Run E2-1..E2-4 in order at the owner's time, one step per privilege proof, evidence file per step
     (E2-1-whatif.md, E2-2-execute.md + journal copy, E2-3-resume.md + both journals, E2-4-forward.md),
     each with the before/after state records and the sanitized runner artifacts and their hashes.
     Stop at the first deviation from the oracle; do not improvise on production. Rollback lines are in
     docs/apollo-deployment-run-260903.md section 8 and remain valid throughout.
  4. Save evidence/E2-green.txt; run the deployment suite and local\test.ps1 once; record the spec's section
     9 row E2 and a dated entry in docs/apollo-discovery-and-plan-260826.md; push the branch; do not merge.
  5. Final checkpoint: two independent read-only reviewers (spec, operations) with the CHECKPOINT-C2D2
     brief pattern, over the whole Slice 2 record; merge only if both ACCEPT; then the hand-path scripts
     stop being the deployment method (spec section 10) — record that hand-over in the run record.

HARD CONSTRAINTS
  - The spec is the authority; if code cannot match it, stop and report the section.
  - Never touch Sibyla.Legacy.*, GottSibylaWorker, gott_sibyla_legacy, win-acme, the Hermes configuration
    or crons; never read local\secrets, C:\ProgramData\Sibyla\secrets contents or D:\ApolloData\worker-claude.
  - No -Force. -NoRollbackOnHealth only if the oracle for the step says so (it does not, by default).
  - Never Restore-WebConfiguration; never delete a release folder; never edit PREVIOUS.txt by hand.
  - Evidence files are appended, never rewritten; the earlier evidence files are never edited.
  - Editing: the editor tool for source edits, never perl -pi; check line endings (git ls-files --eol)
    before committing; fingerprints only from clean exports (CRLF on this machine).
  - Drive C: is small; keep temp files on D:.

REPORT
  Per step: the transaction id, the trailer outcome, the journal hash, the before/after state hashes,
  the health results, what the module did that the hand path did not (and the reverse), anything in
  5.1/5.3/6/7 that did not survive contact with production; the final checkpoint verdicts.
```

## For the owner

- Fill D-E2-1..D-E2-5 above (a line each is enough), name the slot, and start a fresh Claude Code
  session in `D:\fileStorage\repos\GOTT.Apollo` with the fenced block.
- Have the PostgreSQL administrator password at hand: E2 asks for the privilege proof before every
  executing step, in a visible elevated window, and never stores it.
- Rollback during or after E2 is the hand path's, in one line per host
  (`docs/apollo-deployment-run-260903.md` section 8); the IIS backup the session takes is restored
  only by you.
