{"type":"transition_applied","payload":{"type":"transition_applied","status":"running","residency_state":"resident"}}
{"type":"assistant_message","payload":{"text":"I read this as a read-only adversarial V14 r2 release audit - I’ll trace source, preseal, candidate, and rehearsal artifacts end to end, test each named failure mode locally, and return one evidence-backed PASS or FAIL without changing or authorizing anything."}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":true}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"assistant_message","payload":{"text":"I read this as a read-only adversarial V14 r2 release audit - I traced the sealed execution path and tested every requested failure class without authorization or mutation.\n\n# Verdict: FAIL\n\nV14 r2 must not be authorized. It currently fails closed before execution, and the frozen design also permits target substitution and unsealed source imports.\n\n## Decisive evidence\n\n### 1. Frozen controller closure no longer matches the specified source\n\n`controller-source-manifest.json` contains 311 entries. A final SHA-256 comparison found five mismatches:\n\n- `scripts/nutricoach_v150_controller_worker.py`\n- `scripts/nutricoach_v150_detached_bootstrap.py`\n- `scripts/nutricoach_v150_sealed_controller.py`\n- `scripts/verify_nutricoach_v150_preseal_v14.py`\n- `tests/test_nutricoach_v150_v14_safety.py`\n\nFor example:\n\n- Expected bootstrap: `1d4b5678...e70f85`\n- Current bootstrap: `c1ef8051...0d8c`\n- Expected controller: `c511f998...86990`\n- Current controller: `0acccdc3...9cf0`\n\nThe bootstrap calls `verify_closure(...)` before importing the worker, so r2 now necessarily denies with `closure_drift`. The source also changed during the audit to reference an r3 preseal, demonstrating why a mutable worktree cannot be the execution closure.\n\n### 2. Source import escape exists in the frozen r2 candidate\n\nThe bootstrap verifies selected files under the mutable source worktree and then places that whole root on `PYTHONPATH`:\n\n- `nutricoach_v150_detached_bootstrap.py:146-155`\n\nThe sealed candidate imports these local modules, but none are present in the controller manifest:\n\n- `scripts/execute_nutricoach_v150_live_upgrade.py`\n- `scripts/nutricoach_v150_live_upgrade_boundary.py`\n- `scripts/nutricoach_v150_live_upgrade_common.py`\n- `scripts/nutricoach_v150_live_upgrade_state.py`\n- `scripts/nutricoach_v150_sealed_authority.py`\n- `scripts/nutricoach_v150_phase_journal.py`\n- `scripts/nutricoach_v150_sealed_target.py`\n\nThese include package validation, rollback snapshots, the global authorization ledger, and the real systemd adapter. Therefore critical transaction behavior can be imported from source bytes not covered by `controller-source-manifest.json`.\n\n### 3. Target/package substitution is not prevented\n\nThe authorization digest covers the package payload, but these operational target fields exist only in `sealed-target.json`:\n\n- `profile_root`\n- `current_runtime`\n- `successor_runtime`\n- `unit`\n- `dropin`\n- `execution_root`\n- `global_approval_ledger`\n- `protected_inventory`\n- `permission_package`\n- `controller_target_binding`\n- `authority_id`\n\nThe bootstrap accepts caller-selected `--preseal`. Although `package-manifest.json` hashes `sealed-target.json`, that manifest is self-excluded and is not covered by the authorized package digest. It can therefore be recomputed around a substituted target while retaining the same approval phrase and permission package.\n\n`execute_verified_target()` checks the phrase and controller derivation, then constructs `ConcreteLiveHost` directly from the substituted target. It does not compare those paths against package payload values.\n\n### 4. Candidate and live authority paths are incompatible\n\nPositive evidence: all 321 candidate inventory rows currently exist and match their recorded hashes; candidate digest `f4198225...58d8f` agrees across candidate, preseal, and rehearsal.\n\nHowever:\n\n- The live package inspector expects `awaiting-authorization.json`, `payload.evidence`, `payload.target`, and `payload.snapshots`.\n- The V14 r2 preflight contains only `package.json` and `snapshot-before.json`.\n- A read-only call to `inspect_package()` returned:\n\n```text\nUpgradeDenied invalid_json:awaiting-authorization.json\n```\n\nThe public bubblewrap command also omits the bootstrap's required `--preseal` argument. Static inspection returned `has_preseal False`.\n\nThe rehearsal does not exercise this path. It calls `execute_disposable(APPROVAL_PHRASE, ...)`, where the controller phrase is based on `DISPOSABLE_V3`, uses `DisposableService`, and only copies the real package digest into the final report afterward.\n\n### 5. Hard-coded stale identities remain in the r2 candidate\n\nThe frozen candidate contains:\n\n- Candidate digest `066a794d...` in `nutricoach_v150_live_models.py`, not `f4198225...`\n- Old package digest `a362d994...`\n- Old `task-1-candidate` wheel paths\n- V13 preseal constants in the bootstrap and controller\n- `DISPOSABLE_V3` as the controller's default package identity\n\nSome live values are overridden from `sealed-target.json`, but the stale defaults are still used by disposable/rehearsal paths and make those paths non-representative.\n\n### 6. Canonical rollback scope is not authority-bound\n\nCurrent live shape is as recorded:\n\n- Enabled: `pilot_20260820_01`\n- Disabled: `task26_claim_20260818145508_1b96b23d`\n- Enabled wizard event and lock files are absent.\n- Enabled `canonical-sequence.jsonl` exists, mode `0600`, one link, empty.\n\nThe implementation mechanically tracks dynamically missing files in `_created_files` and removes them during rollback. However:\n\n- `authority_created_paths_rollback` is never consumed or enforced by `ConcreteLiveHost`.\n- Missing canonical files are recomputed from the runtime registry.\n- `protected_paths()` silently excludes a sealed stable path when it no longer exists.\n- Preflight capture hashes current runtime bytes rather than comparing them with hashes in `snapshot-before.json`.\n\nConsequently registry drift or disappearance of another canonical file can expand the creation/removal set beyond the authorized rollback list.\n\n### 7. Disabled-draft authorization is not stable\n\nAt the captured state, enabled-only filtering is correct: missing-file creation, authority registration, configuration, and startup smoke all skip disabled customers.\n\nBut execution does not verify the live registry against sealed hash `bd61ed95...660b29` or the sealed two-customer projection. If the disabled row becomes enabled before execution, the migration authorizes every currently enabled customer, up to five, and can create their canonical files. The presealed disabled-draft restriction therefore is not enforced at execution time.\n\n### 8. Service and post-fence checks are insufficient\n\nPositive evidence: `ConcreteLiveHost.stop()` re-observes service state and rejects a service that remains running.\n\nFailures:\n\n- `SystemdService`, from the unsealed `nutricoach_v150_sealed_target.py`, hard-codes `hermes-gateway-dualcoachtest.service` instead of binding the service identity from the sealed target.\n- `switch_postimages()` performs a blind byte replacement and does not require the predecessor runtime to have occurred.\n- Post-fence accepts any manager `ExecStart` containing the successor path as a substring.\n- It does not require the exact argv/profile contract.\n- It does not prove `MainPID` or `ExecMainStartTimestampMonotonic` changed across restart.\n- It does not prove the running process loaded the sealed candidate credentials.\n- Weekly authority/configuration is not revalidated after service start.\n\n## Evidence that did pass\n\n- All eight preseal package-manifest entries match.\n- No unexpected files exist in the r2 preseal.\n- Candidate inventories and wheel hashes match.\n- Candidate, package, and rehearsal digest fields agree.\n- The supplied rehearsal reports 13 passing cases.\n- Authorization ledger, execution root, and successor runtime remain absent; no authority was consumed.\n\nThese integrity checks do not overcome the execution-path defects above.\n\n## Architecture options\n\n### Option A - One fully bound descriptor and frozen source closure\n\nPut every target path, exact service name/argv, candidate and wheel hashes, registry/inventory hashes, canonical creation list, and complete transitive controller closure into the canonical payload covered by the approval digest. Execute controller files from a read-only preseal copy, not the worktree. Use one package schema from verifier through executor.\n\n- Lowest migration cost\n- Keeps current controller structure and tests\n- Requires careful complete closure generation\n- Main failure mode becomes ordinary digest mismatch\n\n### Option B - Package the controller as a third immutable wheel or zipapp\n\nBuild the controller, ledger, rollback, target model, and service adapter into one hash-bound executable artifact alongside the two product wheels.\n\n- Strongest protection against source-import escape\n- Cleaner reproducibility and import behavior\n- Higher build and packaging cost\n- More migration work before another rehearsal\n\n## Recommendation\n\nUse Option A. It is the simplest architecture that meets the actual one-host, one-profile transaction requirement. Rebuild a new preseal only after:\n\n1. Binding all operational target fields into the approval digest.\n2. Freezing the complete transitive controller source.\n3. Making verifier and executor consume the same package schema.\n4. Pinning `--preseal` in the public entrypoint.\n5. Comparing live registry/protected bytes against sealed hashes before reservation.\n6. Enforcing exact service identity, ExecStart argv, and restart freshness.\n\nNo files, authority state, services, providers, network operations, or Telegram surfaces were modified or invoked."}}
{"type":"transition_applied","payload":{"type":"transition_applied","status":"completed","residency_state":"resident"}}
