# NutriCoach v1.5 Combined Candidate and Upgrade Package

## Objective

Seal one exact NutriCoach v1.5 candidate containing the qualified v1.4 weekly
operations source plus the v17-qualified Channel Inbox and bounded
multi-customer capabilities. Both v1.5 capabilities remain OFF by default.
Prepare a read-only, candidate-bound, one-use live-upgrade package and stop at
`AWAITING_AUTHORIZATION`.

## Immutable inputs

- v1.4 source worktree:
  `/home/cube/projects/richard/.worktrees/nutricoach-v140-impl`
- v1.5 feature worktree:
  `/home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150`
- v17 evidence:
  `/home/cube/projects/richard/.senpi-evidence/st_01a0405c-multi-customer-final-v17`
- v17 evidence manifest SHA-256:
  `2f799ea17dfad3b71ce3e07ea78b140f50afeae10b16140a3659f74b84e5dfd7`
- v17 sandbox diff SHA-256:
  `d03fd62f2d28847c9e31566eb23517211ebc236fdc3af97ffc9388dd2b868777`
- v17 source-set SHA-256:
  `05def47bc84eedc249dc424b91e25f0a66963d8b6b381cb3a8dad9d3f288a55d`

## Guardrails

- No commit, push, PR, merge, tag, release, live install, capability enablement,
  Telegram/provider call, or customer activation.
- Never mutate past v1.4 receipts or reuse its authorization/seal.
- Preserve current live profile, service state, customer data, authority
  receipts, other profiles, and watcher byte-for-byte.
- Candidate identity is the canonical full-product derivation, never a wheel,
  source-tree, or arbitrary 64-hex digest.
- `nutricoach_channel_inbox_v1` and `nutricoach_multi_customer_v1` remain
  compiled but configured OFF and unauthorized.
- Initial multi-customer capacity is five only after a separately authorized
  migration.

## Execution phases

### Contract

1. Bind exact v1.4 and v17 source/evidence inputs.
2. Record current plan, ledger, service, live-profile, authority, and watcher
   snapshots.
3. Capture RED for the absent v1.5 verifier and absent v1.5 upgrade controller.

### Candidate

4. Materialize a disposable combined source tree.
5. Derive v1.5 changed-member allowlists and immutable inventory.
6. Build Hermes/profile wheels twice in independent detached roots.
7. Create the canonical full-product candidate manifest.
8. Run the v1.5 verifier against source and installed wheels.
9. Reject tampered manifest/source/wheel copies.

### Qualification

10. Run v1.4 weekly and v17 multi-customer/Channel Inbox matrices under the
    exact candidate interpreter.
11. Prove default-OFF parity, wrong-candidate denial, cross-customer isolation,
    capacity overflow denial, tamper rejection, restart/recovery, and rollback.
12. Run real PTB handlers and the network-disabled disposable Telegram
    surface; capture sanitized transcript and cleanup receipt.
13. Run Ruff, formatter-added-line, basedpyright, ty, no-excuse, compile, LOC,
    full nutrition baseline/ported, and source-hash-stability gates.

### Permission package

14. Snapshot current live profile/service/authority state read-only.
15. Prove a clean boundary: no pending onboarding, owner review, send,
    migration, activation, or unknown provider outcome.
16. Dry-run legacy-customer receipt migration to candidate-bound capacity five.
17. Rehearse byte-exact rollback in a disposable clone.
18. Build a one-use package binding candidate, snapshots, migration, rollback,
    approval digest, and exact approval phrase.
19. Run the package without approval and require `AWAITING_AUTHORIZATION`.
20. Reject old v1.4 seals, wrong approval, stale bytes, pending workflow, and
    rollback drift.

### Audit

21. Run independent provenance/candidate, privacy/authority, rollback/package,
    and hands-on audits against one frozen manifest.
22. Synchronize this plan, the v1.4 operational plan, ledger, todo, notepad,
    and evidence receipts.
23. Present the exact approval phrase and digest; stop before live mutation.

## Success checks

### Candidate verifier

```bash
uv run scripts/verify_nutricoach_v150_candidate.py \
  --base .omo/evidence/nutricoach-v140-weekly-operations/task-12-candidate/manifest.json \
  --successor .omo/evidence/nutricoach-v150-combined/task-1-candidate \
  --manifest .omo/evidence/nutricoach-v150-combined/task-1-candidate/manifest.json
```

PASS: exit `0`, `NUTRICOACH_V150_CANDIDATE_PASS`, two reproducible wheel
builds, full-product candidate identity, and tamper denial.

### Read-only preflight

```bash
uv run scripts/prepare_nutricoach_v150_live_upgrade.py \
  --profile-root /home/cube/.hermes/profiles/dualcoachtest \
  --candidate-manifest .omo/evidence/nutricoach-v150-combined/task-1-candidate/manifest.json \
  --output /home/cube/.hermes/migrations/nutricoach-v1.5.0-combined/preflight \
  --read-only
```

PASS: exact snapshot, clean boundary, migration dry-run, rollback rehearsal,
zero live/provider/network mutation.

### Permission boundary

```bash
uv run scripts/execute_nutricoach_v150_live_upgrade.py \
  --package /home/cube/.hermes/migrations/nutricoach-v1.5.0-combined/preflight/package.json \
  --dry-run
```

PASS: `AWAITING_AUTHORIZATION`, one exact candidate-bound phrase/digest, old
seals rejected, service/profile/Telegram/watcher unchanged.

## Stop

Stop immediately after the candidate is
`QUALIFIED_PENDING_LIVE_AUTHORIZATION`, the package is
`AWAITING_AUTHORIZATION`, cleanup receipts are complete, and the exact approval
phrase/digest is ready. Do not execute the live upgrade in this run.

## Sealed result — 2026-08-27

- Status: `QUALIFIED_PENDING_LIVE_AUTHORIZATION`
- Candidate:
  `066a794d44861d2cd0fe8c1ea14c0050e00219b38a2d2026b389772783056dad`
- Candidate manifest SHA-256:
  `78b2d1790b67cf0d9730cd9a4b0d2d0d3de5bf5f5836e31a70f5be3a62dd7786`
- Hermes wheel SHA-256:
  `5829f799160a7341f5509043c17cecbe5d10cfe25c44eb3f8fde44bbf9720d91`
- Profile wheel SHA-256:
  `bdfe94b31d9c98c233301dc2cc552e5e2d672853901bac2bdf73df7e23c709b6`
- Package status: `AWAITING_AUTHORIZATION`
- Package digest:
  `a362d994b41a5d05ed2fcdafc76482e72d18ff69334cd8249eec061bff733acb`
- Package SHA-256:
  `afb91c8cfa6038862763b61ea58d47d880949eb4d8b77c961017a2db02e52f78`
- Package path:
  `/home/cube/.hermes/migrations/nutricoach-v1.5.0-combined/preflight/package.json`
- Active-candidate manual receipt SHA-256:
  `f5bb5f060360ffc7d0defb73da7d97bfb058489ca53fc7cb9c1e5b903538da43`
- Independent evidence audit: `PASS`
- Capacity-5 migration: dry-run only, `persisted=false`
- Authorization consumed: no
- Live/profile/service/Telegram/provider/network mutations: zero
- Old v1.4 package/approval and superseded unformatted v1.5 candidate:
  non-authorizable

## Authorized live execution amendment — 2026-08-27

The owner supplied the exact phrase:

`AUTHORIZE NUTRICOACH V1.5 LIVE UPGRADE a362d994b41a5d05ed2fcdafc76482e72d18ff69334cd8249eec061bff733acb`

Discovery after authorization found that
`scripts/execute_nutricoach_v150_live_upgrade.py` intentionally validates the
package only and cannot mutate live state. The authorization therefore remains
unconsumed until a candidate-bound transaction controller is sealed and
independently rehearsed.

### Live transaction requirements

1. Revalidate the approval phrase, package SHA, candidate manifest, current
   service start identity, current runtime candidate, registry, consent,
   authority, and clean boundary immediately before reservation.
2. Capture RED by invoking the current validator without `--dry-run`; require
   nonzero because no live path exists.
3. Derive the live transaction from the already proven v1.4 v7
   `TransactionGuard` sequence: stop, post-stop snapshot, post-stop ledger
   validation, install, OFF smoke, migration dry-run, migration apply, target
   enablement, systemd switch, restart, post-fence, and atomic commit.
4. Bind the transaction to candidate
   `066a794d44861d2cd0fe8c1ea14c0050e00219b38a2d2026b389772783056dad`,
   manifest SHA
   `78b2d1790b67cf0d9730cd9a4b0d2d0d3de5bf5f5836e31a70f5be3a62dd7786`,
   the two exact wheels, package digest
   `a362d994b41a5d05ed2fcdafc76482e72d18ff69334cd8249eec061bff733acb`,
   capacity `5`, and the current live runtime identity.
5. Preserve Channel Inbox OFF. Apply only the separately sealed
   multi-customer capacity-5 registry migration and the already-approved
   weekly-operations pilot authority needed for the seven-day observation.
6. Use a durable one-use reservation before stopping Gateway. Any wrong,
   duplicate, stale, interrupted, or already-consumed approval must fail
   before live mutation.
7. Rehearse the exact full operation and every rollback boundary in a
   disposable clone using the exact candidate wheels and current live
   snapshot. No fixed sleeps or network/provider calls.
8. Require an independent pre-execution audit of the controller, transaction
   seal, rehearsal receipts, and current clean boundary.
9. After PASS only: stop Gateway, snapshot, install, migrate, switch, restart,
   verify current customer consent/authority/state, run an offline synthetic
   smoke, and create the immutable deployment receipt.
10. Arm the seven-day observer against the installed exact v1.5 candidate.
    Do not onboard or activate a second customer automatically.
11. On any failure after reservation: stop Gateway, restore exact runtime,
    unit/drop-in, registry, profile authority and protected bytes; restart the
    prior runtime; write truthful rollback/NO-GO evidence.

### Pre-execution audit repair

The first generic-controller preseal is rejected and non-authorizable. The
independent audit proved it lacked a concrete target adapter, allowed caller-
controlled transaction roots/path sets, did not consume every `BaseException`,
and did not bind v7 source-level semantics.

The audit also found `stale_protected_bytes`. Read-only path comparison proved
the only changed entries were the actively appended
`dualcoachtest/logs/agent.log` and `dualcoachtest/logs/errors.log`; contract,
registry, unit and drop-in hashes remained exact. These two runtime logs were
misclassified as stable in the original package.

Required correction:

- classify only those two Gateway logs as volatile append-only files;
- keep registry, config, authority, runtime, unit, drop-in and every other
  profile entry protected;
- rebuild the read-only package, concrete target adapter, one-use authority
  and full rehearsal seal;
- mark package `a362d994…` and its approval superseded/non-reusable;
- stop for a new exact owner authorization bound to the corrected package
  digest before any live mutation.

The first concrete v2 rehearsal is also rejected. It proved:

- copying the sealed read-only current runtime into the successor made wheel
  installation fail with `PermissionError`;
- rollback cleanup of that read-only tree raised a second `PermissionError`,
  masked the primary failure, left successor residue, and failed to restart the
  prior synthetic service;
- the OFF smoke incorrectly required a literal `channel_inbox: false` even
  though an omitted key is the shipped default-OFF contract;
- the permission package bound target paths but did not bind the concrete
  controller derivation, so an approval could be paired with altered controller
  bytes.

V3 must create a fresh writable successor runtime, make rollback cleanup
permission-safe and primary-error preserving, interpret omitted Channel Inbox
as OFF, and include a non-circular controller-derivation hash in the permission
package before the concrete seal binds that package digest back.

## V3 safety checkpoint — 2026-08-28

The current Senpi transcript
`/home/cube/.senpi/agent/sessions/--home-cube-projects-richard-traning coach--/2026-08-15T03-46-57-912Z_01a00387-aaf8-7f2f-89e3-e24c1af24859.jsonl`
and completed Oracle Triple were re-read before resuming:

- architecture: `st_01a04394`
- rollback/durability: `st_01a04395`
- authority/security: `st_01a04396`

All three verdicts are **NO-GO** for both `a362d994…` and `869c1e8f…`.
Neither phrase may create a ledger or enter a transaction.

### V3 source contract

V3 uses one V7-shaped external, content-addressed operation plan and one
transaction engine. The owner-approved authority ID must bind, without a hash
cycle:

1. a self-excluding package inventory, including launcher and transitive
   controller imports;
2. canonical controller closure and exact V7 reference-source hashes;
3. exact target descriptor with every preimage, postimage, path, type, mode,
   absence assertion, wheel/RECORD/script/import identity, systemd property,
   credential binding, capability postcondition, rollback path, isolation
   policy and fixed global ledger;
4. corrected clean-boundary preflight, candidate manifest, wheel digests,
   authority epoch/window and explicit V1/V2 supersessions.

The trusted launcher verifies this closure before importing mutable Python
controller code. Controller/package bytes do not embed the resulting authority
ID. The sole public execute surface accepts only the detached V3 approval.

### V3 transaction contract

Before reservation, and again after confirmed real systemd stop where
applicable, verify exact protected state and semantic clean boundary. After
reservation:

1. persist a durable phase journal and post-stop snapshot/created-path
   ownership manifest;
2. build a fresh writable staging venv without chmodding the predecessor;
3. install exact wheels offline and verify raw wheel, RECORD, generated script,
   candidate and loaded module-origin identity;
4. run no-credential/no-network successor probes;
5. generate and compare exact weekly-operations, capacity-five,
   Channel-Inbox-OFF, unit, drop-in and credential postimages;
6. atomically publish, daemon-reload, start and query real systemd
   ActiveState/SubState/MainPID/ExecStart/start timestamp;
7. commit only after installed identity, capability, protected-state and
   privacy fences pass.

Rollback continues across individual failures but never restarts a mixed
contract. It preserves the primary exception, durably records secondary
failures, restores every byte/mode/type/link-count, removes only paths owned by
the attempt, reloads exact predecessor systemd bytes and proves the predecessor
runtime is active. SIGTERM/SIGKILL/power-loss recovery is rollback-only and
permanently consumes the V3 authority as failed.

### Required RED→GREEN and real-surface evidence

- exact live-config clone where the nested weekly section is absent;
- real offline exact-wheel installation from a read-only predecessor;
- every stage × BaseException plus short/zero/EINTR write,
  fsync/rename/readback, restore and cleanup failures;
- SIGKILL recovery after every durable phase;
- concurrent/same-root/alternate-root replay;
- altered launcher/source/target/ledger/wheel/RECORD/isolation policy;
- real systemd-shaped active/running/PID/runtime observations;
- two unrelated full-success clone roots;
- exact cleanup: no clone/cache/ledger residue and unchanged live
  profile/service/PID/start identity.

Only after fresh V3 rehearsal and independent architecture, rollback and
authority audits all return PASS may the new exact owner authorization be
presented. Live execution remains a later, separately authorized phase.

The first V3 freeze attempt with digest `94953fed…0818` is rejected and
non-authorizable. Its real verifier failed `BootstrapDenied: package_drift`
because controller derivation, source manifest and target contract changed
after the package manifest was computed. Preserve its bytes and rejection
receipt, mint a new digest only after all inputs are final, and generate the
self-excluding manifest last.

The next freeze attempt `d23faa5c…b587d` repeated the same ordering defect and
is also rejected/non-authorizable. No V3 digest is presentable until the exact
real verifier returns PASS after the package manifest is written last and no
bound byte changes afterward.

## V3 owner-authorization gate — 2026-08-28

The third manifest-last freeze is the sole authorizable V3 preseal:

- package digest:
  `3fbaea7e19a77a1007e27f3f0a3610a727baeeb2ab7bded1f5301a3da5872dd9`
- package SHA-256:
  `591852a11ba52e3577a209be05ed220f273998bbdf18fd4606ae8dd97e16fb02`
- manifest SHA-256:
  `c8b8f933dd80c219b88e57156525a74d24db61bcf593274db248365ec2fa93ac`
- closure digest:
  `sha256:007ecce81335d7f9d7eb16337263bc2b6388fec24188219abbb9641734f92e3b`
- verifier: `V3_PRESEAL_VERIFIED`
- rehearsal receipt:
  `babdc8d39d54e74a4bf271881f365a7eff990ad408bca602b20c285aac0cbba9`
- cleanup receipt:
  `45c9231adb75b872718349a4883313c4de5145066888fba7ae0c42243d2f5f41`
- independent audit:
  `e7ed25be87684eb6e79448537696bd02e918a6bf98b8ae84194af7bdffd12b24`

All live critical hashes, service PID/start identity, old/current approval
ledgers and the V3 execution root were independently rechecked. The sole next
step is a new exact owner authorization. The request itself does not reserve
or consume that authorization and does not permit using any predecessor phrase.

## V3 live execution authorization — 2026-08-28

The owner supplied the exact authorization for package digest
`3fbaea7e…5872dd9`. Immediately before execution, the detached verifier
returned `V3_PRESEAL_VERIFIED`, the sealed package SHA remained `591852…fb02`,
all authority/execution roots were absent, the live service remained
active/running at PID `571685` with start identity `2234547821498`, and the
critical unit/drop-in/config/registry hashes matched the independent audit.

The only authorized mutation is one invocation of
`execute_nutricoach_v150_sealed_live.py --approval <exact phrase>`. No automatic
retry is allowed; terminal failure must remain consumed and restore the
predecessor.

## Live attempt 1 — pre-ledger bootstrap denial

The sole authorized invocation exited `1` before controller import, ledger
creation, service stop or any live mutation. Bubblewrap correctly unshared the
network, but the detached bootstrap compared `/proc/self/ns/net` with
`/proc/1/ns/net`; the host's procfs policy denied the latter with
`PermissionError`.

Containment proved the V3 ledger and execution root absent, service
active/running at the original PID/start identity, and all critical hashes
unchanged. The attempted `3fba…72dd9` authorization is non-reusable despite
being unconsumed by the package ledger: the owner authorized one invocation,
and that invocation occurred.

The successor fix replaces the invalid `/proc/1` dependency with a current
namespace `/proc/net` gate that permits only loopback interfaces/routes. Runtime
toggle evidence proves it denies the host namespace and passes the real
Bubblewrap `--unshare-net` namespace. The successor source closure passes
66 tests and all strict static/no-excuse gates. A new seal, rehearsal, audit and
owner authorization are required before another live invocation.

## V4 rehearsal blocker and V5 controller binding

V4 sealed the network gate correctly but was rejected during rehearsal before
any transaction: its worker still imported a controller bound to
`DISPOSABLE_V3` and `live-transaction-preseal-v3`. Therefore digest
`cb18…2f41` and its phrase are non-authorizable.

V5 fixes the root binding rather than patching the harness:

- `execute_authorized` retains a one-argument public surface.
- The controller passes its compile-time V5 sealed-target path into the host.
- The expected live approval is loaded from that sealed target and passed into
  transaction execution; disposable approval remains test-only.
- The detached bootstrap binds the V5 preseal.

The failing-first integration regression now reaches a disposable transaction
with a target-bound non-disposable approval. The closure passes 67 tests and
all Ruff, basedpyright, ty and no-excuse gates. V5 must be freshly sealed,
rehearsed and audited before requesting another owner phrase.

## V5 rehearsal blocker and V6 protected inventory

V5 proved the unmodified bootstrap, worker and target-derived approval reach
the transaction, then stopped safely at `post_stop_snapshot`. The protected
inventory expanded 26,960 hardlinked predecessor-runtime files into rollback
copy sources, while sealed capture correctly rejects `st_nlink != 1`.

The predecessor runtime is verify-only: the transaction creates a fresh
successor and never mutates those files. V6 therefore keeps hardlink safety and
separates responsibilities:

- rollback snapshot: only config, registry, unit and drop-in
- protected drift verification: all stable protected files, including
  hardlinked runtime files
- volatile append logs: excluded from exact stable drift
- rollback: restored mutable paths plus full protected re-verification before
  declaring `ROLLED_BACK`

The hardlink regression was RED, then GREEN; all prior rollback/drift tests
remain green. The V6 closure is bound to
`live-transaction-preseal-v6-protected-inventory` and passes 68 tests plus all
31-file strict gates.

## V6 rehearsal blocker and V7 sandbox cleanup

V6 reached `install_exact_wheels` with the unmodified authority and failed
because the read-only Bubblewrap root had no writable `/tmp`; `uv --offline`
still needs a temporary directory. Rollback then failed to remove the partial
successor because permission normalization followed `venv/bin/python` into the
read-only root interpreter.

V7 addresses both roots:

- Bubblewrap mounts an isolated writable `tmpfs` at `/tmp`.
- Successor cleanup skips symlinks and never chmods their targets.
- Root filesystem remains read-only; network namespace remains isolated.

Both regressions were RED then GREEN. A real Bubblewrap probe wrote a temporary
file only inside its tmpfs. The V7 constants bind
`live-transaction-preseal-v7-sandbox-cleanup`; 69 tests and every 32-file
strict gate pass.

## V7 rehearsal blocker and V8 device sandbox

V7 proved isolated `/tmp` and symlink-safe cleanup, but `uv` interpreter
inspection opened `/dev/null` and received `EACCES` because the root-only
sandbox did not mount usable device nodes. Two concurrent clone attempts
consumed FAILED and rolled back cleanly.

V8 adds Bubblewrap's isolated `--dev /dev`, not a host `--dev-bind`. The
sandbox remains network-isolated and root-read-only. A real probe created a
temporary venv and completed `uv pip freeze --python ... --offline` inside the
sandbox while reading `/dev/null`.

The V8 constants bind `live-transaction-preseal-v8-device-sandbox`; 69 tests
and all 33-file strict gates pass.

## V8 full rehearsal PASS

The unmodified V8 bootstrap, worker and controller completed two unrelated
absolute-path clone upgrades under isolated network/tmp/device sandboxes.
Both installed exact wheels, RECORDs, scripts and import origins; applied
weekly authority with capacity five and Channel Inbox OFF; generated exact
postimages; and consumed clone-local SUCCEEDED approvals.

The rehearsal also passed all 66 stage-by-BaseException cases, durable
write/fsync/rename/restore/cleanup faults, SIGTERM/SIGKILL recovery, same-root
and alternate-root replay denial, hardlink verify-only protection and volatile
append tolerance. Successful external network/provider/Telegram/customer
events were zero. Final residue is seven evidence files and no disposable
directories/ledgers. Live PID/start/critical hashes remain exact and the V8
live ledger/execution roots remain absent.

- Rehearsal receipt SHA:
  `a0066988edecd637ad75f1f37dc7f61d2256bf6c0915a17f08b9febc06fbc9df`
- Cleanup receipt SHA:
  `88838fc1992275e67a9761c906aa829b632e15cb73ab00d260c32a8b2ac9952a`

The V8 phrase remains withheld pending fresh independent audit.

## V8 audit blocker and V9 live-log classification

The independent V8 audit passed seal, authority, rollback, rehearsal, privacy
and cleanup criteria but blocked current live immutability. A complete
read-only path-level diff found exactly one changed target row:
`dualcoachtest/logs/gateway.log` appended 403 bytes. All other 86,775
target-stable rows, all contract files, all unrelated profile rows, service
identity, ledger and execution roots remained exact.

`gateway.log` is an active append-only Gateway log alongside already-volatile
`agent.log` and `errors.log`; V8's snapshot classifier omitted it. V9 adds only
`logs/gateway.log` to the explicit volatile set. The regression was RED with
`live_immutability`, then GREEN. The V9 constants bind
`live-transaction-preseal-v9-live-log-classification`; 69 tests and all
34-file strict gates pass. V8 digest/phrase are non-authorizable.

## V9 immutable seal

V9 froze a fresh current snapshot with `logs/gateway.log`, `logs/agent.log`
and `logs/errors.log` explicitly volatile while all remaining target rows and
all contract bytes stay protected.

- Package digest:
  `f64ffbde677fa0f7413a7e5f0bafbcd9f442e61508b092ed56cb1f099ef2e92b`
- Package SHA:
  `8efea3ed40990b2892680ed6ac4c25eb97f81d44cb9428b887a07e1870edc4de`
- Package-manifest SHA:
  `5ea633ca3d3b2b0e5f4d0e8d0c94d3133ca739bf196ab91d4732dca26cdf47a4`
- Closure:
  `sha256:a96bc1b1704ec9be23de78c6f5f496c3957ad0dac1eed948bd350641d09c8e1a`
- Verifier: `V9_LIVE_LOG_CLASSIFICATION_PRESEAL_VERIFIED`

Live PID/start remain `571685`/`2234547821498`, service is active/running,
and V9 ledger/execution roots are absent. The exact V9 phrase remains withheld
pending full rehearsal and independent audit.

## V9 full rehearsal PASS

The exact V9 chain committed successfully in two unrelated absolute clone
roots. Both clone ledgers are consumed SUCCEEDED, installed wheel/RECORD,
script and import identities are exact, capacity is five, and Channel Inbox
is OFF. The matrix passed 66/66 stage-by-BaseException cases, durable
write/fsync/rename/restore faults, SIGTERM/SIGKILL recovery, replay denial,
and all three append-only log checks. External events are zero.

- Rehearsal receipt SHA:
  `1ba9230695d13d7fad62699f466b675dcc61b5b757eb7185ed9639ca5e460e5d`
- Cleanup receipt SHA:
  `8b3af58b9d1ef9cf7ce7f12bc496f3f5f3ddc9be3d81eaf0df798345bae99f1a`
- Final inventory: seven immutable evidence files; zero clones, sources,
  caches or disposable ledgers.

Live PID/start/critical hashes remain exact and V9 live authority roots are
absent. Independent audit is in progress; the phrase remains withheld.

## V9 independent audit PASS and authorization gate

The existing independent auditor recomputed 78 bound hashes with zero
mismatches and passed every seal, authority, rollback, install, capacity,
Inbox-OFF, live-log, privacy/network, cleanup and current-live criterion.
Same-root stale-state replay is fail-closed before mutation; copied spent-ledger
alternate-root replay independently proves durable one-use authority.

- Audit receipt SHA:
  `7ec3374ecdd1794d88a511f067039a4dbd2af2b188fe04b9b1b5f571119168c3`
- Final verifier: `V9_LIVE_LOG_CLASSIFICATION_PRESEAL_VERIFIED`
- Final boundary: `AWAITING_AUTHORIZATION`
- Live service: PID `571685`, start `2234547821498`, active/running
- V9 ledger and execution roots: absent

The V9 package is fully sealed and audited. Stop at requesting the exact new
owner authorization; do not execute it in this checkpoint.

## V9 owner authorization received

The owner supplied the exact digest-bound V9 phrase:
`AUTHORIZE NUTRICOACH V1.5 LIVE UPGRADE
f64ffbde677fa0f7413a7e5f0bafbcd9f442e61508b092ed56cb1f099ef2e92b`.
This authorizes exactly one invocation of the sealed V9 live entrypoint. It
does not revive or authorize V3-V8.

## V9 live attempt terminal pre-ledger failure

The exact V9 entrypoint was invoked once. It exited before package inspection,
ledger creation, service stop or live mutation because Bubblewrap
`--clearenv` omitted `XDG_RUNTIME_DIR`; `systemctl --user show` therefore
could not reach the existing user bus.

- Failure receipt SHA:
  `4a7ef0fe624d3fdeb459d309e167a56c9d4c03183dbfbae92776db5e36b6cc58`
- Service remains PID `571685`, start `2234547821498`, active/running.
- Config, registry, unit and drop-in hashes remain exact.
- Successor runtime, global V9 ledger, V9 execution root and package
  consumption file are absent.
- Live/network/provider/Telegram/customer mutations: zero.
- The V9 phrase is operationally spent and non-reusable despite the
  pre-ledger failure. No retry is allowed.

A read-only three-variant probe confirmed the minimum successor change:
`XDG_RUNTIME_DIR=/run/user/<uid>` alone restores the user-bus query inside the
same network-isolated sandbox; `DBUS_SESSION_BUS_ADDRESS` need not be exposed.
V10 adds exactly that environment variable. Its regression was RED then GREEN;
70 tests and all 35-file strict gates pass. V10 requires a fresh seal,
rehearsal, independent audit and new owner authorization.

## V10 immutable seal

V10 froze a fresh current snapshot with the minimal
`XDG_RUNTIME_DIR=/run/user/<uid>` user-bus environment and no
`DBUS_SESSION_BUS_ADDRESS`. All V9 recovery, log-classification, device,
tmpfs and network-isolation controls remain bound.

- Package digest:
  `e6ddec2ecc8802cb6bf94daa39a03672a19c61ae485d5e64ab387fbddb8f30c7`
- Package SHA:
  `248540f47ce08aac56e311cdca47b782aa0c05f9d27db700671ae33bf9f7cd2b`
- Manifest SHA:
  `20cc15b768622b180eeeb3e5a0a390b68cfcd855582b6509f614fac3bd50c5b8`
- Snapshot SHA:
  `97731e7704607e5c876eb95432d32d7e2046965bb2f89ebfa665f9fde51ac43a`
- Closure:
  `sha256:895b2354b8c8b19ac2a8444ac508bddcec33b30e7368608d7a3b54ebbb8e65e6`
- Verifier: `V10_USER_BUS_ENVIRONMENT_PRESEAL_VERIFIED`

Live PID/start remain exact, service is active/running, and V10 authority
roots are absent. The V10 phrase remains withheld pending full rehearsal and
independent audit.

## V10 rehearsal harness blocker

The first V10 rehearsal harness placed exact-path clone overlays in an outer
Bubblewrap namespace and then called the real entrypoint, which attempted its
mandatory inner Bubblewrap namespace. This host forbids nested unprivileged
namespace creation. The controller was never reached, no clone/live mutation
or authority reservation occurred, and live state stayed exact.

- Blocker receipt SHA:
  `fbb47f38cf6a23873d704ee7ea498f7b1459a9354e42316b44cba866519e6623`
- Cleanup receipt SHA:
  `c8f2f2184ea479cab0c301269c7d6c16439f0537619ae2a6dada6a17420ee24d`

This is a rehearsal topology blocker, not a V10 product-chain failure. The
same rehearsal role is continuing with a single namespace derived directly
from `sandbox_command()`: only the three bind source operands are projected
to clone roots, while all destinations and every security/environment argv
byte remain exact.

The single-namespace projection also stopped before authorization. Exact argv
assertions passed, but the unchanged `systemctl` connected to the live user
manager at `/run/user/1000/systemd/private`. Running the projected transaction
would therefore stop/restart the live service and violate the no-live-use
constraint.

- Projection blocker SHA:
  `3f11001a9026326823208ffaf0b237b5694e31ae257a9336fcd71e271ea10472`
- Cleanup SHA:
  `215139fb05876e1f500d9f75fecb456192acde41a7bf64da0bbb4f2c45661bd4`
- Exact argv assertions SHA:
  `822a6ef330790f0300e0cd59abebdc2f7f5139f459b6f93c7b389da588830103`
- Read-only live-bus probe SHA:
  `97b48e0e3f5bd54ad9dc2f0680342cf777ff038609bc995af2da2ca54e025899`

After four materially different rehearsal topologies, exact V10 full-chain
clone execution is impossible on this host without either touching the live
user manager or altering the sealed transaction's `systemctl` endpoint.
No fifth strategy may be attempted without owner direction. The safe fork is:

1. accept compositional assurance (V9 full transaction matrix + V10 exact argv
   assertions + V10 real read-only user-bus probe), then request independent
   audit adjudication; or
2. provide an isolated user-manager endpoint/host capability and rerun the
   exact V10 full-chain rehearsal there.

The owner selected option 1: compositional assurance. The exact V10 clone
rehearsal is closed as host-impossible without violating zero-live-use. The
existing independent auditor is adjudicating V9's complete transaction matrix
plus V10's exact delta argv, real read-only user-bus probe, strict source gates,
sealed hashes and fresh live boundary.

## V10 compositional audit PASS and authorization gate

The existing independent auditor recomputed 84 sealed, inherited, probe and
topology hashes with zero mismatches. It confirmed the transaction execution
body is byte-identical to V9, the only operational launcher delta is
`XDG_RUNTIME_DIR`, and compositional assurance is sufficient. Every authority,
recovery, install, capacity, Inbox-OFF, log, privacy/network, topology and
fresh-live criterion passed.

- Audit receipt SHA:
  `abd0d3b8befb8f2715586f2232e89021ef98a6690eb701cf13ab2046b26a1f51`
- Final verifier: `V10_USER_BUS_ENVIRONMENT_PRESEAL_VERIFIED`
- Final boundary: `AWAITING_AUTHORIZATION`
- Live service: PID `571685`, start `2234547821498`, active/running
- V10 ledger and execution roots: absent

V10 is fully sealed and independently audited. Stop at requesting the exact
new owner authorization; do not execute it in this checkpoint.

## Simplified owner authorization UX

At the owner's direction, a standalone message containing exactly `진행해`
authorizes one attempt against the single package currently recorded as
fully sealed, independently audited and `AWAITING_AUTHORIZATION`. The
orchestrator resolves that state to the package's exact digest-bound phrase
internally before invoking the unchanged sealed controller.

Mentions of `진행해` inside questions, explanations or quoted text are not
authorization. The short approval remains one-use: any attempt spends it
operationally, and any package replacement requires a new standalone
`진행해`.

The owner then sent standalone `진행해`. It resolved to the current sealed
V10 package digest
`e6ddec2ecc8802cb6bf94daa39a03672a19c61ae485d5e64ab387fbddb8f30c7`
and authorizes exactly one V10 live invocation.

## V10 terminal FAILED rollback

The exact V10 entrypoint was invoked once. It stopped the service, captured
the four mutable snapshots, then failed at `stopped_probe` because
`gateway.pid` was sealed as stable although service stop removes it. The
one-use global authority is durably consumed `FAILED`.

Rollback restored the exact predecessor runtime and four mutable/contract
bytes and restarted the service. Six service-lifecycle files rotated or
appended as expected: auth state, staff-membership journal, PID/state files,
and exit/shutdown diagnostics. A strict no-service-action recovery closure
verified all 86,775 target rows, six contract rows, four snapshots, current
PID identity and absent successor, then durably advanced the phase from
`RECOVERY_REQUIRED` to `ROLLED_BACK`.

- Terminal receipt SHA:
  `9667ff4cd4eb75eb966c2d0ce5fa9f8c483a151d652ff3d4cdae7f92a26918eb`
- Consumed FAILED ledger SHA:
  `d06d951c3b334dac3313b56369ebddd7b27f934088b3065964e93311e475793b`
- ROLLED_BACK phase SHA:
  `8e429e77dd1bdf4c463ac27b23125b9c05543a598559ac91cbe19a6b3d3e3e7d`
- Recovery receipt SHA:
  `cf0a43b88553d096f209da1fa4b232fd1f48721636f407415718719b8a95779b`
- Replay: `authorization_already_used`, zero mutation.
- Service: predecessor active/running, PID `3415172`, start
  `2431627836475`; successor absent.
- Config, registry, unit and drop-in hashes: exact.
- Controller provider/Telegram/customer events: zero; controller network
  namespace remained unshared.

Independent terminal-outcome audit is in progress. No retry or successor
upgrade is authorized.

## V10 independent terminal outcome audit PASS

The existing auditor independently verified the one authorized V10 attempt as
terminal `FAILED/ROLLED_BACK`.

- Audit receipt SHA:
  `fb2eee4d604a93425d8a7a2cc6da17f4fecfe2fa4adfcc4b69e21875fd4d2cef`
- Ledger: `CONSUMED/FAILED`
- Phase: `ROLLED_BACK`
- Replay: `authorization_already_used`, zero mutation
- Stable verification: 86,775 rows with only the six allowed lifecycle drifts
- Contracts/mutable snapshots: exact
- Predecessor active; successor absent; service active/running
- Controller external events: zero

The authorized work is terminally complete through the allowed FAILED branch.
No further package, approval or live attempt is authorized.

## V11 lifecycle-state successor

The owner directed that the update must still complete. V11 moves the six
observed service-lifecycle files into the volatile inventory while keeping all
other protected, contract and mutable-rollback boundaries exact.

- Package digest:
  `9c2f7bcd06777bca77ea4d1c1d5f55588f6facd04a8eee4d22b3cc6394838ffb`
- Package SHA:
  `6df2e5e9b19e6a0da7f8e4d45352084e12e2868abbc52493c34292f67202b85b`
- Manifest SHA:
  `b43556dd494335c50fbd23f0ca1926a3f98562fa4e00951a4f41c38e646871a4`
- Snapshot SHA:
  `f9d5bac6e5e2923b5b4c41e68377b90a4f1035f771b11a4a47b2f2591e757675`
- Closure:
  `sha256:ba1a72ba4486cb6cbff5de3602b2250bf7bcd6107fc3edcd81d7d70aac68e900`
- Verifier: `V11_LIFECYCLE_STATE_PRESEAL_VERIFIED`

V10 consumed failure/rollback evidence remains exact, V11 authority roots are
absent, and the predecessor remains active/running. Compositional lifecycle
rehearsal is in progress.

## V11 compositional lifecycle rehearsal PASS

- Rehearsal receipt SHA:
  `3770a51abcc72f4da4aeda0a7bf407baac664a7e035dd95b44b094ae434e203f`
- Cleanup SHA:
  `42ba251443f80f5f40ecdfe57317afda3ad9fc5123d286a02351d92e81dbb961`
- Compositional evidence SHA:
  `60f3bf6a77ac1f8f54f3c83ce4a5b73b1918c7f6148548b9b0cd9e305c54e0f1`

The exact six lifecycle files are V11 volatile and absent from stable
inventory; all remaining 124,660 stable rows match. Targeted stop/start
deletion, rotation and append cases pass stopped-probe, success, rollback and
replay. The V9 full transaction/install/fault/privacy matrix and V10 XDG bus
boundary were revalidated. Live state and V11 authority roots remain
unchanged/absent. Independent V11 audit is in progress.

## V11 independent audit PASS and execution authorization

- Audit SHA:
  `06ac2cb73425e2477901b50fc1a8e1615ef3ba638d1acce91129ba43984f4d5e`
- Bound hashes: 86, zero mismatches
- Stable rows: 124,660 exact; lifecycle delta limited to six files
- Final verifier: `V11_LIFECYCLE_STATE_PRESEAL_VERIFIED`
- Final boundary: `AWAITING_AUTHORIZATION`
- Live predecessor exact; successor and V11 roots absent

The owner's explicit instruction to complete the update, together with the
standalone `진행해` authorization policy, resolves internally to the exact
V11 digest phrase and authorizes one V11 live attempt without another
user-visible hash prompt.

## V11 and V12 runtime-boundary attempts

V11 consumed `FAILED/ROLLED_BACK` at stopped-probe because root
`state.db-shm` disappears while the Gateway is stopped. V12 moved the root
SQLite trio and all `logs/` files to volatile while preserving archived DB
artifacts. Its seal, rehearsal and audit all passed.

V12 then completed the transaction ledger as `SUCCEEDED/COMMITTED`, but Manual
QA caught the real candidate service exiting immediately:
`WeeklyReminderStartupAuthorityIncident: weekly reminder startup config is
invalid`. The transaction migration had written only a boolean authority
summary, not the candidate's required canonical registry sidecar and complete
operator receipt.

The service restart loop was stopped immediately. V12's sealed snapshots
restored the exact predecessor config, registry, unit and drop-in; the
successor and weekly authority were removed; the predecessor restarted
active/running at PID `3470183`. All 86,756 V12 stable rows are exact.

- V12 postcommit rollback receipt SHA:
  `07a07021d8696925261b017209408b42be6784972493b7ca11041f3d68b5140a`
- V12 phase: `ROLLED_BACK`
- V12 one-use ledger remains immutably consumed.

The next successor must create and smoke-test the full canonical weekly
authority. Disabling weekly operations or weakening startup checks is
forbidden.

### Live stop condition

Stop immediately when either:

- the exact v1.5 candidate is active, the current customer is healthy, capacity
  is five, Channel Inbox remains OFF, the seven-day observer is armed, and
  deployment/post-verification receipts pass; or
- fail-closed rollback restores the exact prior runtime and records NO-GO.

## V14 r13-r20 lifecycle-safe successor

The first sealed V14 attempt, r13, committed its transaction but Manual QA
found a stale/missing activation receipt. It was immediately rolled back to
the exact predecessor. Receipt-preserving admission migration and rollback
ownership were then implemented and locked with RED-to-GREEN tests.

r17 passed sealing, rehearsal and independent audits, but live Manual QA found
two startup blockers: the successor copied the predecessor
`task26-candidate-digest` credential unchanged, and its fresh `--no-deps`
runtime omitted declared dependency `croniter==6.0.0`. r17 was immediately
rolled back; its rollback receipt SHA is
`f056845b1b67a9bf6ab90a6a07a2334634776e390937202a7347b4c1ab75451c`.
The predecessor is active/running and r17 is permanently consumed.

r18 and r19 were rejected before authorization while dependency target
binding and read-only snapshot verification were hardened. No live action was
performed for either candidate.

r20 is the lifecycle-safe successor:

- Candidate:
  `3dab1a5531c71239899c5a836f8689b9b6c59dc07ca7443de76442cf0eb5090d`
- Package:
  `c88bf7cd6354ae36222e7057af5d227a6a966c58d896cb8de994313cd79bea84`
- Closure:
  `sha256:e6a4a4d5aae9d02d2efbc672ada202f8059f9ca1d41115afdbf3501f2eae24c5`
- Frozen croniter snapshot:
  `5eb58ad4c8d4629b8d65b01ebdb50ca74d5782a11120e9a30cd6615c8316bfa0`
- Rehearsal report:
  `a97d0dce6426fa16d46ff6deece98b591fdcbbc88b6f866f85fbdc999c831340`
- Rehearsal: success plus all 12 fault-injected rollback cases PASS.
- Regression tests: 62 controller/safety/weekly tests and 5 profile migration
  tests PASS.
- Three independent audits (`st_01a04bc0`, `st_01a04bc1`,
  `st_01a04bc2`): PASS, no blockers.
- Candidate and preseal: zero writable entries, symlinks or bytecode.
- r20 authorization, execution, successor and weekly-authority roots: absent.
- Current predecessor service: active/running.

The exact one-use phrase is internally bound to:
`AUTHORIZE NUTRICOACH V1.5 LIVE UPGRADE c88bf7cd6354ae36222e7057af5d227a6a966c58d896cb8de994313cd79bea84`.
Per the established owner policy, a new standalone `진행해` resolves to this
exact phrase and authorizes one r20 live attempt. Until then the state is
`AWAITING_AUTHORIZATION`; no prior instruction or phrase is reusable.

## V14 r20 authorized outcome: NO-GO / ROLLED_BACK

The owner supplied a fresh standalone `진행해`; the exact sealed r20 launcher
was executed once. The controller completed `COMMITTED/SUCCEEDED`, but real
service QA immediately showed Telegram rejecting the successor:
`runtime candidate is not current or was revoked`.

No customer, provider or Telegram action was attempted after the rejection.
The narrow postcommit rollback restored the exact predecessor and recorded:

- Controller receipt:
  `sha256:b401a045d4f38b616c8c09b4f51b0bb4d325b6c8e0dea9757fbeff2c184fe3be`
- Consumed r20 ledger:
  `b6465f83219011fb9e281863f3d44a0cd0369ba46e77c589852a2c8a2c784184`
- Rollback receipt:
  `f9cd61020fae91bd324578b937799292b63f5f94403652ac04f0e9bbfc5038e9`
- Phase: `ROLLED_BACK`
- Predecessor runtime:
  `/home/cube/.hermes/profiles/dualcoachtest/.strict-runtime/6c9c4394-v132/venv`
- Predecessor service: active/running, PID `4174948`
- Successor and weekly-authority roots: absent
- Config, registry, unit and drop-in: exact predecessor hashes

r20 is permanently consumed and must never be replayed. The next successor
must repair and rehearse publication of the candidate as the current runtime
authority before any new one-use authorization boundary is created.

## V15 external runtime-authority transaction plan

Three independent read-only investigations (`st_01a04d8c`,
`st_01a04d8d`, `st_01a04d8e`) confirmed the r20 gap and selected a
WAL-protected append-only design.

The fresh successor transaction must:

1. Seal the predecessor authority source/genesis, registry and ledger heads,
   event count, candidate, historical PASS digest, and external root.
2. After install/migration/offline smoke and while the service is stopped,
   persist a transition intent containing canonical paired-chain pre/post
   images.
3. Append exactly one `QUALIFY(successor)` event/row under the external lock.
4. Derive a pin from the verified new heads and event count; bind that pin and
   the same successor candidate into canonical systemd credentials.
5. Run the installed wheel's production authority loader and Telegram
   activation path before systemd switch and before ledger success.
6. Switch/reload/start only after successor authority passes; extend
   post-fence to prove the real candidate, pin and external chain agree.
7. On failure after promotion, reconcile any interrupted paired append,
   append exactly one `QUALIFY(predecessor)` compensation when needed,
   regenerate the predecessor pin at the final heads, restore ordinary
   snapshots, and verify predecessor authority before restart.
8. Accept only baseline `N` predecessor-current, `N+1` successor-current, or
   `N+2` predecessor-current compensation. Any other head state leaves the
   service stopped in `RECOVERY_REQUIRED`.

The predecessor is never revoked. A failed successor is not automatically
revoked; after compensation it is non-current and therefore unauthorized.
Historical authority rows are never deleted or byte-rewound.

The V15 detached closure must include both Task26 authority modules and their
promotion tests. It must pass a faithful installed-wheel credential-surface
adapter smoke, stale/missing/revoked/stale-pin negatives, deterministic
interruption recovery, 13-case transaction rehearsal, immutable closure
verification, and three independent audits before any fresh one-use owner
authorization is requested.

## Production completion — 2026-08-30

- Status: `PRODUCTION_ACTIVE`
- Final candidate:
  `1128e376747835bc75c5cfe43f024ce644d72492796acc5778f8a13aa382c528`
- Final package:
  `8d5ec1a3a551a143cf12f7086033bf96c91f1e7e1eb55858ed8a8c2398d1c89a`
- Package SHA-256:
  `279f0d756e8a7ed5ad5bba8f4107d9334ce2b23927c05354f5a926fdc03f95b2`
- Closure digest:
  `sha256:3b4f53bfc475c48579ed446173b0ceba7e2b93ce6433ebe245836414eeab0e1a`
- Live transaction receipt:
  `sha256:b401a045d4f38b616c8c09b4f51b0bb4d325b6c8e0dea9757fbeff2c184fe3be`
- One-use authorization: `CONSUMED/SUCCEEDED`
- Execution phase: `COMMITTED`
- Service: active/running on `.strict-runtime/1128e376-v150/venv`,
  `NRestarts=0`
- Telegram: connected with two established Telegram API sockets; installed
  Telegram `22.6` exports real `TypeHandler`
- External authority: current candidate matches the final successor at event
  count `18`
- Capacity: `5`; enabled current customers: `1`
- Weekly startup smoke: PASS for `pilot_20260820_01`
- Channel Inbox: absent and OFF
- Replay: denied as `authorization_already_used`; protected hashes unchanged
- Rehearsal: 13/13 PASS, external events `0`, only `report.json` remains
- Independent final audits: closure, authority, runtime all unconditional PASS
  with blocker count `0`
- Commit and push: not performed

## New-customer production patch — 2026-08-31

- Status: `PRODUCTION_ACTIVE`
- Candidate:
  `21c4560efd5abf93df16edf0c6f7471a939e4e4a879fc87aac02ba389a192c1c`
- Package:
  `d80b65b9263ed7501941fdcf370b94a8e676968964cb4abb0408b12712f93d02`
- Transaction receipt:
  `sha256:9e2998e0e88e3c87ea278a2fc83957e6812fc6b3b8505de165fef20ad0924d15`
- Service: active/running on `.strict-runtime/21c4560e-v150/venv`,
  `NRestarts=0`
- Telegram: two established API sockets
- Production authority: candidate current at event count `19`
- Customer operator surface:
  `dualcoach_admin customer invite --profile-root ... --draft ... --json`
- Invite contract: canonical bot/owner, private no-follow boundaries, capacity
  five, 24-hour expiry, single use, private-DM claim
- Disabled registration: owner/customer-only fields; no trainer role
- Weekly authority:
  `data/weekly-operations-authority-21c4560efd5abf93`
- Rehearsal: 13/13 PASS, external events `0`
- Independent final audits: closure, authority, onboarding all unconditional
  PASS with blocker count `0`
- Seven-day observer: active/waiting, every ten minutes,
  `2026-09-01T00:00:00+09:00` through `2026-09-08T00:00:00+09:00`
- Commit and push: not performed
