I read this as a documentation task: create two new private runbooks (Golden Path + Recovery) for Task26 bound to candidate 2e0894ea, superseding 19ed0e references, plus a binding receipt, linted against the amended plan - plan. First I need to map the workspace: existing runbooks, the amended plan, candidate hashes, CLI/systemd sources, and evidence layout.


Large session store here. Now I need to find the amended plan (SHA 7ace03c6), existing runbooks, and candidate references (2e0894ea, af4a9d0a, 19ed0e, Task26).


Found the key artifacts. Now reading the amended plan, existing runbooks, and the same-actor preflight evidence from the sibling task.


The plan is fully mapped. Now reading the existing runbooks (to preserve and supersede), the sibling preflight arm-manifest, and the systemd unit.


Candidate gateway CLI is fully mapped. Now the customer bootstrap/invite path and the disable transaction in the candidate.


Now the previous runtime rebind receipt and the freeze/supersession receipts, to ground the deployment steps.


The previous rebind installed the wheel into the repo venv with direct_url proof. Now checking how deployment was performed and the reset situation (blocker B2).


The sibling reset controller is in-flight (empty live-dry-run.json, mutable 0755). Reset stays a fail-closed blocker in my runbooks. Now the ledger's authorization event for the exact action boundary.


The ledger confirms the boundary and that my task closes B4. Now I need the exact gate18 deployment command, the verifier CLI, and the readiness/activation CLI surfaces.


Now checking how activation was performed in the prior rehearsal and the consent/review flow states.


Let me verify how the profile-package CLIs are invoked (import path), then I have everything to write the artifacts.


Checking how the previous invite preparation harness was sealed, so the runbook cites the real mechanism.


Final recon: reading the systemd unit to cite its exact stop semantics, then writing all artifacts.


Recon complete. All command surfaces, bindings, and current state are verified. Now writing the artifacts: two new runbooks (append-only, 0600), a linter, and the binding receipt.


Now expanding the recovery runbook to cover every Spec 3 procedure topic (Start payload, revision conflict, stale/failed callback, restart before/after send, owner rejection), then the linter.


Now the linter that checks both runbooks against every amended plan step and prohibition:


Nine lint failures to fix: two are wrong SHA constants I transcribed (verifying actuals now), the rest are line-wrap and regex false positives plus one missing field.


Fixing the linter: corrected SHA constants, flow-normalized token checks (line wraps were breaking matches), and context-window prohibition checks:


All 40 checks pass. Verifying the edited sections read cleanly before writing the binding receipt:


Docs are clean. Writing the binding receipt:


**Task verdict: PASS** — the runbook rebind (preflight blocker B4) is closed. `READY_FOR_REHEARSAL_PREFLIGHT`: **withheld** (see below).

## Artifacts (all new, append-only, dir 0700 / files 0600)

`.omo/evidence/task26/task26-runbook-rebind-2e0894ea-st_01a0054e/`

| File | SHA-256 |
|---|---|
| `task26-golden-path-2e0894ea.md` | `1f55b8f967c6564113574d41bf1c15ce977d35c38b5687f1623ba37f235a7bdb` |
| `task26-recovery-runbook-2e0894ea.md` | `f4f2d2347b4b68a080b9c437a813accbef8c4bcc471cbf21d67ffff31e56f89b` |
| `runbook-binding-receipt.json` | (self-hash omitted; file is valid JSON, 0600) |
| `lint_runbooks.py` / `lint-results.json` | `8df077ea…` / `3448c564…` |

Both runbooks bind candidate `2e0894ea…`, wheel `af4a9d0a…`, plan `7ace03c6…`, actor `8527916639` (new logical lifecycle only), and supersede the candidate-`19ed0e9232…` runbooks. The old files are preserved byte-identical — recomputed during lint: `32a379d855c6…` (golden contract), `ae2f5f9046c06f…` (recovery).

## Lint: 40/40 PASS (stable across two runs)

Mechanical checks against every amended-plan element: amendment authorized/forbidden lists, all-new IDs/states with forbidden reused values, Spec 2 content + must-not-contain (dangerous tokens like `getUpdates`, `drop_pending_updates=True`, `--all`, `rm` verified to appear only in prohibition context), Spec 3 procedure families + per-procedure fields, Task 25 archive-first reset rules, invariants, no-git-mutation constraint, binding/supersession/preservation hashes, command-citation scope, 0600 modes.

## Coverage matrix (full version in the receipt)

- Preflight → GP §1 (14 fail-closed gates) · Wheel rebind + loaded-byte proof → GP §3 · Archive-first pre/post reset → GP §2/§13 · One invite/one Start → GP §5 · Observers before actions → GP §4 · All-new IDs/states → GP §6 · Handset steps → GP §5/§7/§8/§10 · Exactly-once delivery → GP §11 · Disable/cleanup → GP §12/§13 · Prohibitions → GP §15 · Recovery (15 procedures incl. stale lock, expired invite, claim collision, revision conflict, safety hold, card conflicts, delivery failure, stale/failed callbacks, restart before/after send, owner rejection) + rollback/abort matrix → RC §3/§4 · Other-profile non-touch, redaction, receipts → GP §14/§15, RC §5.

No invented commands: everything cited is verified against the installed candidate (argparse source, unit file, sealed wheel, prior evidence). The old runbooks' `dualcoach_admin` planned interfaces are explicitly declared non-existent in `2e0894ea` with their replacement surfaces.

## Unresolved issues (open fail-closed gates, owned elsewhere)

- **B1** stale `gateway.lock` (dead PID 4091167) — disposal only via sealed reset scope (gate G8, RC R2)
- **B2** reset controller not yet sealed; no dry-run/verify receipts (gate G10, owner `st_01a0054d`)
- **B3** openai-codex readiness needs the billable probe with explicit human authorization (gate G7)
- **B5** no sealed verifier for all five predecessor archive schemas (gate G11)
- **G12** no sealed candidate-bound invite-preparation harness yet (owner `st_01a00547`)

## Readiness decision

The runbook set is decision-complete — every step is an evidenced exact command or a named STOP gate — but not executable end-to-end while B1/B2/B3/B5/G12 stand. Per the issuance rule, I do not attach `READY_FOR_REHEARSAL_PREFLIGHT`. Unblock path: seal the reset controller with passing dry-run/verify receipts, land the archive verifier, reconcile the lock inside the sealed reset scope, authorize and pass the provider probe, seal the invite harness — then re-run GP §1. No product, profile, runtime, archive, service, network, Telegram, provider, or Git actions were taken; all writes stayed in the new evidence directory.


I read this as implementation — produce v2 runbooks correcting the verified blockers, rebind to the sealed reset controller and archive verifier, lint 100%. First, gathering the new sealed evidence (reset controller, archive verifier, verifier invocation contract, ledger path).


All archive-verifier digests verify. Now the remaining contracts: verifier CLI, controller argparse/preconditions, candidate-verifier invocation, test receipt.


Controller semantics confirmed — importantly, `verify` is a **post-execute** check and `--approval` takes the literal phrase; my v1 had both wrong. Checking the contract's preserve list, verifier inventory, test receipt, and candidate-verifier invocation:


All contracts verified. Two important confirmed findings for v2: `verify_candidate.py` takes `verifier-input.json` (exit 0 = PASS, not exit 2), and the candidate has **no ACTIVE→terminal bootstrap transition** while the sealed reset contract requires terminal sessions — a real cleanup-time gate. Quick verification of the "14 tests" claim, then writing v2:


Now the v2 linter with the semantic deadlock checks:


Lint: 91/91 PASS, stable. Now the v2 binding receipt with a self-independent hash sidecar:


All verified. Final state:

**PASS**

- `task26-golden-path-2e0894ea-v2.md` (`633d5c25…`), `task26-recovery-runbook-2e0894ea-v2.md` (`6024c26c…`), `runbook-binding-receipt-v2.json` + self-independent sidecar (`9d0ad49c…`), `lint_runbooks_v2.py` + `lint-results-v2.json` — all 0600, dir 0700.
- Lint **91/91 PASS**, stable across two runs, including the semantic deadlock checks: G8 requires only *no active lock holder* pre-reset (stale `gateway.lock` authenticated and scheduled for disposal via the sealed reset's `approved_clear_scopes`), G15 requires the lock *absent* post-reset, hand-removal forbidden everywhere; mode order dry-run → execute → verify; no stale statements remain.
- All fixes landed and independently re-verified: ledger authority cited from `.omo/start-work/ledger.jsonl`; exact sealed reset command bound (`bd051dda`/`4128cece`/`8a290b11`/`2fc323f8`/`776e9030`) with real `--archive-root` semantics (`data/profile-reset-archives/<run-id>` via `.pending-` rename, prior archives read from `data/rehearsal-reset-archives`) and literal approval phrase; B2 **closed**; archive verifier bound (`12b97aa7`/`29db87f2`/`28ff72fd`/`597a37e4`, tests `1b92ac72` — I re-ran them: 14/14 PASS, LSP clean; default-config ruff flags only EXE001/UP035 on the sealed 0400 files, benign); B5 **closed**; candidate-verifier invocation corrected to `verifier-input.json` with exit 0 = PASS; bounded deadlines added; v1 + original runbooks byte-identical (sha re-verified).

**Remaining gates (3):**

1. **B3 (open)** — billable `openai-codex` active probe still needs written human authorization; cheap read-only `provider-auth check` only until then.
2. **G12 (open)** — no sealed candidate-bound invite-preparation harness yet; arm manifest still holds `commands.invite: null` (owner: `st_01a00547`).
3. **B6 (open, new in v2)** — cleanup-reset blocker found while revalidating: the sealed contract requires all bootstrap sessions terminal with empty `role_claims`, but candidate `2e0894ea` has no ACTIVE→terminal transition (verified in wheel source: `transition()` allows only REGISTERING→AWAITING_CONSENT→AWAITING_ACTIVATION→ACTIVE; CANCELLED/FAILED never assigned; no COMPLETED state). After a successful lifecycle the cleanup dry-run/execute will fail closed. Resolution needs a superseding sealed contract/permission revision or candidate support; until then the run ends rehearsal-complete, cleanup-blocked (encoded as gate G16 + procedure R16).


I read this as an implementation task: verify all claimed v3 closure evidence independently, then write append-only v3 runbooks + linter + binding receipt with sidecar. Starting with evidence reconnaissance:


Invite harness pins all match. The B3 receipt isn't in the task26 evidence dir — searching wider:


Raw receipt and index match. Reading the receipt to verify payload, tokens, command/module digests, and the READY verdict:


B3 fully verified. Now confirming the module hash against the sealed wheel and both venvs, and reading the G12/B6 artifact contracts:


All B6 pins match and the exact commands exist. Reading the harness operations contract, its seal enforcement, and the cleanup contract gates:


More v1 pin corrections needed — finding the real module paths in the wheel:


One harness test failed in my clean run despite the sealed receipt claiming 6/6 — diagnosing before I bind anything, and locating the real `hermes_cli` module paths:


No `.venv`, no `secrets/`, no `gateway-credentials.json` in the profile — several v1/v2 path assumptions may be stale. Checking the unit's ExecStart and config digest:


The `nutrition_review_service request-generation` CLI doesn't exist anywhere — likely invented in v1. Checking how the original runbook's lifecycle actually triggered generation:


Generation is event-driven (check-in completion atomically enqueues the job; approval/delivery are staff-room card callbacks) — no CLI exists. Verifying the last two claimed digests (command digest, approval event) before writing v3:


All evidence verified: 27/27 tests reproduce with the sealed interpreter, both command digests match, and I found six stale v1/v2 statements to correct (module pins, venv path, unit path, CLI names, `--reason` flag, invented generation CLI). Writing the v3 golden path:


Now the v3 recovery runbook:


Now the v3 linter with the semantic checks:


Three lint failures — two are over-broad negative patterns (my own void-list mentions), one missing full digest. Fixing the linter patterns and adding the full approval-event digest to the GP:


167/167 PASS, stable. Now the v3 binding receipt with self-independent hash sidecar:


The lint results file regenerated with the 10 receipt checks (177 total now), so re-pinning its digest in the receipt:


Receipt pins match the stable files. Final preservation and mode verification:


**PASS — READY_FOR_REHEARSAL_PREFLIGHT.** All three v2 external gates verified closed with sealed evidence, v3 supersession pair bound, 177/177 lint checks pass (stable across runs, including semantic deadlock/singleton checks).

**Gate closures (all pins re-verified against live files before binding):**

- **B3 (provider READY)** — CLOSED. Raw receipt `8278dde4...`, payload `6aeaaab4...`, index `16acf1b3...`, pre/post profile snapshot identical `7d163cb0...`, one request attempt, `billable: true`, `store: false`, 26 tokens, zero delivery/registry/service/Telegram effects. Digest-domain clarification recorded permanently: `candidate_digest f9a461...` is the provider command digest from module `gateway/platforms/dualcoach_admin.py` (`0e9b4b1f...`, byte-identical in wheel and runtime venv), a different domain from envelope digest `2e0894ea...`. Correct invocation requires profile-bound `HERMES_HOME=/home/cube/.hermes/profiles/dualcoachtest`.
- **G12 (invite harness)** — CLOSED. Harness `2826b1ba...` (0500), permission `c4e85789...`, approval `c7fc4771...`, verification `c2a6393f...`; 6/6 tests + Ruff/LSP/compile PASS reproduced with the runtime interpreter. Live dry-run reproduced the expected lock refusal; ordering enforced: lock survives only as sealed pre-reset input, post-reset harness dry-run+verify mandatory before the single prepare; claim observer READY before Start.
- **B6 (cleanup controller)** — CLOSED. Controller `8b03fa71...`, contract v2 `7b6a1aa5...`, permission `cb063102...`, tests `90fcb04b...` (21/21 reproduced), independent receipt `d8d818cd...`, readiness `fab63227...`, expected live rejection `769db2bd...` (zero ACTIVE lifecycle today). Exact execute/verify commands pinned (`78d7474d...`/`e6888d62...`) verbatim in GP Section 14 with the strict ACTIVE lifecycle gates.

**v1/v2 stale statements corrected in v3** (caught during re-verification): G5 module pin set replaced with the seven real wheel members (digests recomputed from the sealed wheel); runtime venv is `/home/cube/projects/richard/hermes-agent/.venv` (no profile-local `.venv` exists); unit path is `~/.config/systemd/user/...` (sha `0b46e887...` unchanged); lifecycle CLIs corrected (`checkin_cli.readiness_cli --profile-root --customer-key`; real `customer_admin` subcommands; `disable` has no `--reason`); the `request-generation` CLI does not exist — generation is atomically enqueued at check-in completion.

**Artifacts (all 0600, dir 0700):** GP v3 `ff230719eb5a69ae821bb0a4d58356d59b2803c490d692659a197e22083793c7`; RC v3 `e62691493d2a75c312dd248a07bbc52f7f1d98d4acd701b824bbaf5edf8bdd3a`; receipt `fd77a4d387b9bab7978c84cb51b1ab3200d52a126dea411db98492f6be67fb88` + self-independent sidecar (canonical self-hash `343bdf28...`); linter `e3cead7d...`; results `becb7b71...` (177/177 PASS). v1, v2, and original runbooks plus v1/v2 receipts re-verified byte-identical. No profile/runtime/archive/service/network/Telegram/provider/Git mutations (writes confined to the evidence dir; the one earlier test-suite failure was my wrong interpreter, resolved by re-running with the sealed venv).

**Remaining gates:** none open. Remaining items are execution-time actions, in the mandated order: pre-reset arm (dry-run) → pre-reset execute/verify → harness dry-run/verify → wheel deployment + loaded-byte proof → observe before prepare/Start → lifecycle → disable/stop → cleanup execute/verify.


I read this as: issue append-only v4 runbooks with exactly two path-contract corrections (B1 archive seal path, G14 Bot API authority predicates), re-verifying every claim first, re-linting, preserving v1-v3.

First wave: verify the actual archive seal path/hash and the verifier's exact CLI:


Confirmed: actual seal is `retained-archive-verifier-permission-seal.json` (`28ff72fd...`); the v3 CLI path name doesn't exist. Reading the verifier's arg handling and the sealed receipt's recorded command:


Verifier CLI confirmed: `verifier INVENTORY --permission-seal SEAL [--receipt RECEIPT]`, strictly positional. Now verifying all G14 predicates:


All five modules byte-equal between wheel and runtime; chat bindings match. Checking the operator-card block context, token loader path, and the obsolete-path scan:


All predicates verified. Locating every v4 edit point in the v3 files, then generating v4 by surgical replacement (preserving all other v3 content byte-exact):


All edit points enumerated. Generating v4 via asserted replacements from v3 (guaranteeing byte-identical preservation of everything else):


The RC replacement missed — the GP v4 was written but RC wasn't. Checking the exact line bytes:


The leading backtick in my match string doesn't exist in the file. Re-running only the RC generation:


Both v4 files written. Now the v4 linter — all 177 prior checks adapted, plus the new path-existence, no-secret, obsolete-path-negative, and archive-CLI groups:


212/212 PASS pre-receipt. Writing the v4 binding receipt:


223/223 stable. Re-pinning the final results digest in the receipt:


message: 429: {"code":"INFERENCE_CAP_ERROR","message":"Error 429: You have reached your 5-hour Clinepass limit. The limit resets in 3h 19m, please try again later."}

stop_reason: error


message: 429: {"code":"INFERENCE_CAP_ERROR","message":"Error 429: You have reached your 5-hour Clinepass limit. The limit resets in 3h 18m, please try again later."}


last_error: 429: {"code":"INFERENCE_CAP_ERROR","message":"Error 429: You have reached your 5-hour Clinepass limit. The limit resets in 3h 18m, please try again later."}