I read this as a test-first implementation task - I’ll inspect the Golden Path and verifier, capture a focused RED, patch the source-level receipt contract, then run the disposable invocation and independent verifier offline.


I’ve confirmed the existing invocation proves only the successful lifecycle plus cleanup; the adversarial clauses are neither executed nor independently evidenced. I’m adding focused verifier-contract tests first so missing, summary-only, and hash-unbound branch evidence fail before implementation.


RED is captured: both focused tests fail because no Task26 contract verifier exists. I’m now extracting a small receipt writer and wiring branch observations at the actual production API boundaries, while keeping verdict logic independently in the verifier.


The focused rejection tests are now GREEN, and the verifier rejects missing, forged-summary, and hash-unbound evidence before evaluating any claimed verdict. I’m exercising the full disposable invocation now to catch integration issues at the production state transitions.


The full focused suite is GREEN, including a forged artifact whose entire receipt chain is recomputed: the verifier still rejects the false canonical result. I’m doing the final fresh source invocation/verifier run and the installed-provenance regression tests now.


I read this as completed implementation and verification - I’ll report the patch, evidence contract, and exact RED/GREEN results.

Implemented the strict same-invocation Task26 evidence contract.

### Changed files

- `scripts/source_golden_path.py`
- `scripts/task26_evidence_contract.py` — new focused receipt writer
- `scripts/verify_source_golden_path.py`
- `tests/gateway/test_source_golden_path_verifier.py`

Unrelated dirty files were untouched.

### RED

```text
.venv/bin/pytest -q tests/gateway/test_source_golden_path_verifier.py \
  -k 'task26_contract_rejects'
```

Initial result:

```text
2 failed
AttributeError: module 'source_golden_verifier' has no attribute
'verify_task26_contract'
```

### GREEN

Focused and installed-provenance regression tests:

```text
.venv/bin/pytest -q \
  tests/gateway/test_source_golden_path_verifier.py \
  tests/gateway/test_installed_golden_path_provenance.py
```

```text
51 passed in 1.57s
```

Static validation:

```text
.venv/bin/ruff check ...
.venv/bin/python -m py_compile ...
```

```text
All checks passed!
```

Fresh disposable source invocation and independent verifier:

```text
.venv/bin/python scripts/source_golden_path.py \
  --source /home/cube/.cache/task26-strict-successor-1786976146/src-p \
  --evidence-root /tmp/task26-native-branch

.venv/bin/python scripts/verify_source_golden_path.py \
  /tmp/task26-native-branch
```

Result:

```text
status: ACTUAL_SOURCE_GOLDEN_PATH_PASS
task26 clause_count: 7
task26 chain_head: 618570683f6446e825f905b82b6187dca335bef1581eed7c23e0338b37c005b3
terminal: true
```

### Evidence contract

`task26-evidence/receipts.jsonl` contains exactly seven ordered receipts:

1. `onboarding_22_clear`
2. `deterministic_ambiguity_revision`
3. `preview_isolation`
4. `approved_card_projection_gate`
5. `unknown_delivery_no_retry`
6. `successful_lifecycle`
7. `cleanup_resume_terminal`

Each receipt binds:

- one invocation ID
- candidate digest
- sequence and clause
- predecessor receipt hash
- exact artifact filename and SHA-256
- receipt SHA-256

The verifier independently:

- reparses all 22 Korean raw answers and checks canonical production values, including `보통 수준입니다.`
- requires zero re-asks and exact answer-count transitions
- recompiles ambiguity twice and checks deterministic results
- validates an actual isolated production workflow where field-zero revision is rejected and `schedule_constraints` is revised
- distinguishes preview output from the production session
- verifies projection failure leaves no delivery row and capability issuance fails
- checks repeated preparation of an unknown delivery never requests transport
- derives successful lifecycle and exactly-one delivery from native ledgers, transport log, surface receipt, baseline, and generation lineage
- validates duplicate rejection, quiescence, archive integrity, forward-only cleanup journal, and terminal inventory
- rejects missing evidence, summary-only evidence, broken hashes, and semantically forged evidence even after the entire receipt chain is recomputed

Installed-mode candidate binding now also hashes `task26_evidence_contract.py`, and the same driver path emits the contract in source and installed modes.

No blocker.


I read this as a test-first provenance and revocation hardening patch - I’ll inspect packaging, sealed-candidate inputs, and current verifier tests, capture focused RED cases, then implement offline rehydration and authority validation without touching historical evidence.


The failure has two roots: the verifier’s default mode only admits mutable permissions, and the evidence helper is outside the wheel package. I’m adding RED contracts for exact mutable/frozen modes, packaged-byte parity, rehydration tamper detection, and paired append-only authority chains before changing source.


The permission and authority RED contracts are now GREEN. The authority model is a paired registry/ledger chain: every revocation must reference the ledger head containing its predecessor qualification, and historical PASS scope is explicitly non-current. I’m completing the portable runtime/rehydration surface and its tamper tests next.


The focused suite exposed and fixed two integration issues: strict archival call sites still needed to accept the two exact safe states, and production cleanup inventory tries to open write locks on a frozen bundle. Frozen verification now derives terminality from already-verified immutable cleanup/native artifacts without mutating permissions or opening runtime locks.


The offline sealed-wheel run is blocked by the available pre-patch Hermes wheel: inspection confirms it does not contain `gateway/platforms/task26_evidence_contract.py`. I will not build the prohibited final successor; the rehydration path and tamper/scrub behavior are covered with disposable fixtures, while the frozen source bundle is exercised end-to-end.


I read this as completed provenance/revocation hardening - here are the patch, verification evidence, and remaining sealed-wheel blocker.

Implemented without modifying historical bundles, ledger history, plans, profiles, or services.

### Changed files

- `gateway/platforms/task26_candidate_authority.py`
- `gateway/platforms/task26_evidence_contract.py` — moved from `scripts/`
- `gateway/platforms/task26_final_state.py`
- `scripts/installed_wheel_provenance.py`
- `scripts/source_golden_path.py`
- `scripts/verify_source_golden_path.py`
- `tests/gateway/test_installed_golden_path_provenance.py`
- `tests/gateway/test_source_golden_path_verifier.py`
- `tests/gateway/test_task26_final_authority.py`
- `tests/gateway/test_task26_final_state.py`

Obsolete `scripts/task26_evidence_contract.py` was removed.

### RED evidence

Initial focused run:

```text
.venv/bin/pytest -q \
  tests/gateway/test_source_golden_path_verifier.py \
  tests/gateway/test_task26_final_authority.py
```

Failed during collection:

```text
ModuleNotFoundError:
No module named 'gateway.platforms.task26_candidate_authority'
```

The new frozen-mode tests also exposed that default `private()` rejected `0500/0400`.

### GREEN evidence

```text
.venv/bin/pytest -q --basetemp=/tmp/task26-tests-final \
  tests/gateway/test_task26_final_authority.py \
  tests/gateway/test_task26_final_state.py \
  tests/gateway/test_installed_golden_path_provenance.py \
  tests/gateway/test_source_golden_path_verifier.py
```

```text
64 passed in 2.95s
```

Validation:

```text
ruff check <changed Python files>
ty check \
  gateway/platforms/task26_candidate_authority.py \
  gateway/platforms/task26_evidence_contract.py \
  gateway/platforms/task26_final_state.py \
  scripts/installed_wheel_provenance.py
python -m py_compile <changed source files>
```

```text
All checks passed!
All checks passed!
```

### Frozen-bundle verification

A disposable source bundle was frozen recursively to exact `0500/0400` modes and reverified:

```text
status: ACTUAL_SOURCE_GOLDEN_PATH_PASS
candidate: b34b2a12fd0ad3d4c95a58c847a2411e81272a646f5a4f5ec568d0d3640a3747
terminal: true
```

Verified modes:

```text
500 /tmp/task26-frozen-final
400 /tmp/task26-frozen-final/source-provenance.json
400 /tmp/task26-frozen-final/candidate-authority/registry.json
```

Only these exact states are accepted:

- Mutable: directory `0700`, file `0600`
- Frozen: directory `0500`, file `0400`

Group/world access and other writable modes remain rejected.

### Parity and rehydration

- Evidence helper now lives in the packaged `gateway.platforms` namespace.
- Installed candidate binding includes its packaged module name, digest, and source/wheel/installed parity receipt.
- `verify_packaged_module_parity()` validates:
  - source bytes
  - wheel member bytes
  - wheel `RECORD` hash and size
  - installed bytes
- Existing tests reject altered wheel bytes, installed bytes, `RECORD`, and import origins.
- Golden Path bundles retain private copies of the driver, verifier, and provenance helper under `verification-tools/`.

`gateway.platforms.task26_final_state` now provides an offline CLI which:

1. Validates sealed expected-state and wheel digests.
2. Creates a disposable venv.
3. Installs with `pip --no-index`; `PYTHONPATH` and `PYTHONHOME` are removed.
4. Recomputes installed `RECORD`, wheel inventory, interpreter, portable runtime, and import authority.
5. Reruns the bundled independent verifier using `--rehydrated-runtime`.
6. Compares portable result, candidate, authority heads, and expected status.
7. Scrubs the temporary runtime in `finally`, including failure paths without following interpreter symlinks.

### Revocation schema

Two paired append-only documents:

- `candidate-authority/registry.json`
  - `task26-candidate-revocation-registry-v1`
- `candidate-authority/qualification-ledger.json`
  - `task26-qualification-ledger-v1`

Each sequence binds:

- previous registry hash
- previous ledger hash
- candidate digest
- `qualify` or `revoke`
- historical PASS digest
- registry-event-to-ledger-row hash
- `past_qualification_only` scope

The fixed authority statement explicitly says historical immutable PASS records past qualification only; current authority comes solely from the latest registry and ledger chains.

Tests reject:

- missing registry
- revoked current candidate
- invalidation without predecessor qualification
- stale registry/ledger heads
- altered expected-state digest

### Blocker

A full sealed-wheel rehydration could not be run because the available pre-patch sealed Hermes wheel does not contain:

```text
gateway/platforms/task26_evidence_contract.py
```

Building the successor wheel was explicitly prohibited. No historical wheel or bundle was modified.


I read this as a test-only cleanup fix - I’ll add guaranteed fixture finalizers for every test that freezes task-owned paths, then run the exact 64-test command once and Ruff.


The cleanup is now fixture-owned and guaranteed by `finally`; permission assertions still run against frozen or intentionally invalid modes before teardown. I’m running the unchanged 64-test selection once now.


I read this as completed test-hygiene work - guaranteed teardown now restores task-owned permissions on every path.

Changed only:

- `tests/gateway/test_source_golden_path_verifier.py`
- `tests/gateway/test_task26_final_state.py`

Added fixture finalizers using `try/finally` that:

- Restore the root to `0700` before traversal.
- Restore directories to `0700` and files to `0600`.
- Skip symlinks.
- Run after successful assertions, expected exceptions, and failed rehydration.
- Preserve all frozen and invalid-mode assertions before teardown.

Warning-free test run:

```text
.venv/bin/pytest -q --basetemp=/tmp/task26-warning-free-final \
  tests/gateway/test_task26_final_authority.py \
  tests/gateway/test_task26_final_state.py \
  tests/gateway/test_installed_golden_path_provenance.py \
  tests/gateway/test_source_golden_path_verifier.py
```

```text
................................................................ [100%]
64 passed in 2.97s
```

Ruff:

```text
.venv/bin/ruff check \
  tests/gateway/test_source_golden_path_verifier.py \
  tests/gateway/test_task26_final_state.py
```

```text
All checks passed!
```

No production semantics or evidence were changed.


I read this as a test-first Linux observer backend replacement - I’ll inspect the current inotify implementation and receipt verifier, capture focused RED contracts for zero-inotify signal-driven behavior, then implement and exercise it under the current UID watch pressure.


The current observer is confirmed to allocate inotify watches, while this UID is at 130,964 of 131,072 watches across 54 inotify descriptors. I’m adding focused RED tests against the required dnotify/signalfd contract before replacing the backend.


RED is captured under actual pressure: 14 observer tests fail, primarily with `ENOSPC` from inotify, and the normal-backend guard proves `inotify_init1` is still called. I’m replacing only the observer’s kernel subscription layer now.


The zero-inotify observer tests are GREEN: real atomic-replace and in-place commits work under the current `ENOSPC` inotify condition, and normal/partial teardown restores both fd count and signal mask. I’ve added verifier enforcement for backend and resource counts; next is the Golden Path and regression verification.


WebSocket error


I read this as completed zero-inotify observer delivery - here are the implementation and verification results.

### Changed files

- `gateway/commit_observer.py`
- `tests/gateway/test_commit_observer.py`
- `scripts/verify_source_golden_path.py`
- `tests/gateway/test_source_golden_path_verifier.py`

### Backend

Implemented Linux-only `dnotify_signalfd_v1` using:

- `F_NOTIFY` with `DN_MULTISHOT`
- queued `SIGRTMIN + 7`
- blocked signal mask
- `signalfd`
- one directory descriptor per unique watched parent
- zero inotify descriptors or watches
- post-notification watched-file inode/hash comparison
- initial-state replay before waiting

It fails closed if signal, signalfd, directory, or dnotify setup is unavailable. All resources and the original signal mask are restored on normal, exception, and partial-arm paths.

### RED

Initial observer run:

```text
.venv/bin/pytest -q tests/gateway/test_commit_observer.py
```

```text
14 failed, 2 passed
```

Failures included:

```text
OSError: [Errno 28] No space left on device
CommitObservationError: inotify_watch_failed
Failed: inotify_init1 called
AttributeError: no _create_signalfd
```

### GREEN

Observer tests:

```text
.venv/bin/pytest -q tests/gateway/test_commit_observer.py
```

```text
16 passed in 0.15s
```

Coverage includes:

- no calls to `inotify_init1` or `inotify_add_watch`
- atomic replacement final inode/hash
- synchronous in-place final closed hash
- one parent descriptor for multiple watched files
- arm-to-read replay
- unrelated sibling rejection
- malformed/lost notification failure
- timeout failure without polling
- fd and signal-mask restoration
- partial-arm cleanup
- exact backend and errno error receipts

Final-state regression suite:

```text
.venv/bin/pytest -q --basetemp=/tmp/task26-zero-inotify-64 \
  tests/gateway/test_task26_final_authority.py \
  tests/gateway/test_task26_final_state.py \
  tests/gateway/test_installed_golden_path_provenance.py \
  tests/gateway/test_source_golden_path_verifier.py
```

```text
64 passed in 2.98s
```

Ruff and types:

```text
ruff check ...
ty check gateway/commit_observer.py gateway/_commit_receipts.py
```

```text
All checks passed!
All checks passed!
```

### Golden Path under pressure

Disposable source Golden Path and verifier passed:

```text
status: ACTUAL_SOURCE_GOLDEN_PATH_PASS
observer_backend: dnotify_signalfd_v1
observer_directory_resource_count: 1
observer_inotify_watch_count: 0
observer_receipt_count: 5
terminal: true
```

Receipt resource proof:

```text
backend: dnotify_signalfd_v1
directory_resource_count: 1
signal_fd_count: 1
inotify_watch_count: 0
commit_rows: 4
all_commits_zero_inotify: true
```

### Current inotify pressure

Before and after the new observer runs:

```text
max_user_watches=131072
processes=41
inotify_fds=54
watches=130964
```

The count remained unchanged.

All disposable artifacts were removed after restoring their task-owned permissions. No blockers.


I read this as resuming the interrupted security-hardening task - I’ll inspect the current partial patch, continue from its existing RED/GREEN state, and finish only the remaining trust-boundary, isolation, and wheelhouse verification work.


The resumed tree contains no partial security patch, so the remaining work is still at the pre-RED state. I’m adding the focused malicious-CWD, wheelhouse closure, origin-proof, and trust-boundary tests now before changing the implementation.


RED is captured: the focused final-state suite cannot collect because the trust-boundary and wheelhouse/origin verification contracts do not exist. I’m now replacing the rehydration helper with the isolated subprocess and exact dependency-closure design those tests require.


The focused security suite is now GREEN with 16 tests. The malicious caller test installs valid disposable wheels, runs from a CWD containing shadow `gateway` and `checkin_cli`, and confirms neither shadow executes; wheelhouse closure and exact trust-boundary mutations are also rejected. I’m running the broader final-state and observer regressions next.


I read this as completed security hardening - isolated imports, exact wheelhouse closure, and explicit evidence trust boundaries are now enforced.

### Changed files

- `gateway/platforms/task26_final_state.py`
- `scripts/verify_source_golden_path.py`
- `tests/gateway/test_task26_final_state.py`

No candidate was built or sealed. Historical bundles, evidence, ledgers, plans, and live systems were untouched.

### RED

```text
.venv/bin/pytest -q \
  --basetemp=/tmp/task26-security-red \
  tests/gateway/test_task26_final_state.py
```

```text
ImportError: cannot import name 'TRUST_BOUNDARY'
1 error
```

### GREEN

Focused security tests:

```text
16 passed in 1.34s
```

Original 64-test selection, expanded to 77 by the new tests:

```text
77 passed in 3.09s
```

Zero-inotify observer regression:

```text
16 passed in 0.15s
```

Ruff and types:

```text
All checks passed!
All checks passed!
```

Source Golden Path and verifier:

```text
status: ACTUAL_SOURCE_GOLDEN_PATH_PASS
observer_backend: dnotify_signalfd_v1
observer_inotify_watch_count: 0
terminal: true
```

### Isolated-import contract

Every Python subprocess now uses:

- A newly created private, empty controlled CWD.
- Python isolated mode, `-I`.
- Removed inherited `PYTHONPATH`, `PYTHONHOME`, and other `PYTHON*`/`PIP*` variables.
- Explicit `PIP_NO_INDEX=1` and `PIP_CONFIG_FILE=/dev/null`.
- No inherited caller CWD authority.

This applies to:

- venv creation
- pip installation
- site-packages discovery
- provenance probe
- independent verifier

The malicious-CWD test places shadow `gateway` and `checkin_cli` packages in both caller CWD and `PYTHONPATH`; neither executes.

Origin proof schema:

```json
{
  "schema": "task26-installed-origin-proof-v1",
  "execution": {
    "cwd_authority": "private_empty_controlled",
    "python_isolated": true,
    "pythonpath_inherited": false
  },
  "modules": [
    {
      "module": "gateway",
      "distribution": "hermes",
      "installed_relative_path": "gateway/__init__.py",
      "sha256": "...",
      "size": 123
    },
    {
      "module": "checkin_cli",
      "distribution": "profile",
      "installed_relative_path": "checkin_cli/__init__.py",
      "sha256": "...",
      "size": 123
    }
  ]
}
```

Each origin must resolve beneath rehydrated site-packages and match the installed RECORD inventory hash and size.

### Wheelhouse lock contract

```json
{
  "schema": "task26-sealed-wheelhouse-inventory-v1",
  "root_mode": 256,
  "directories": [
    {"relative_path": "nested", "mode": 320}
  ],
  "entries": [
    {
      "relative_path": "dependency.whl",
      "project": "dependency",
      "version": "1.0",
      "requires_dist": [],
      "sha256": "...",
      "size": 1234,
      "mode": 256
    }
  ],
  "inventory_sha256": "..."
}
```

Enforcement includes:

- Recursive exact inventory.
- Root, directory, and file modes.
- No symlinks or non-wheel entries.
- Wheel hash and size.
- METADATA project/version and dependencies.
- No duplicate projects/versions.
- Complete compatible dependency closure.
- No direct URL dependencies.
- Inventory recomputation before installation and after every success/failure.
- Installation only from explicit verified wheel paths using:

```text
pip --no-index --no-deps --no-compile <exact paths>
```

Tests reject wheelhouse symlinks, nested extras, altered wheels, duplicates, missing dependencies, and stale inventories.

### Trust boundary

Schema:

```text
task26-evidence-trust-boundary-v1
```

Trust anchors:

- trusted operator account
- host kernel
- selected Python/pip toolchain
- sealed wheel bytes

Guaranteed within that boundary:

- content identity
- deterministic tamper detection
- reproducibility
- revocation/current-authority selection
- fail-closed workflow

Explicitly not claimed:

- external authenticity
- non-repudiation
- owner-tamper-proof/WORM behavior
- resistance to a compromised operator or administrator

Coherent operator/admin compromise, including coherent repository, ledger, or verifier modification, is explicitly outside the Task26 threat model.

Missing or altered boundary text and forbidden authenticity/WORM claims are rejected.

All task-owned temporary trees were scrubbed successfully. No blockers.


I read this as a test-first identity-separation fix - I’ll add RED coverage for explicit pre-execution candidate binding and cross-mode parity, then update the driver, verifier, and final-state contract so source-tree provenance can never stand in for candidate identity.


The blocker is confirmed in code: source mode assigns `candidate_digest = provenance["tree_digest"]`, while installed mode derives another digest internally. I’m adding the explicit-binding and cross-mode mismatch RED tests before changing either identity path.


Explicit CLI and private-file candidate bindings now drive source qualification, and the source-tree digest is emitted only as provenance. Cross-mode expected-state parity now binds rerun source and installed results plus both authority heads and the outer pre-execution manifest. I’m moving to full regression verification.


I read this as completed candidate/source identity separation - explicit outer candidate binding now governs qualification while source-tree provenance remains independent.

### Changed files

- `scripts/source_golden_path.py`
- `scripts/verify_source_golden_path.py`
- `gateway/platforms/task26_final_state.py`
- `tests/gateway/test_source_golden_path_verifier.py`
- `tests/gateway/test_installed_golden_path_provenance.py`
- `tests/gateway/test_task26_final_state.py`

### RED

Focused pre-patch run:

```text
.venv/bin/pytest -q \
  --basetemp=/tmp/task26-candidate-red \
  tests/gateway/test_source_golden_path_verifier.py \
  -k 'qualification_driver or driver_bundle'
```

```text
2 failed, 45 deselected
```

Failures proved:

- Omitted candidate binding silently used the source tree digest.
- `--candidate-digest` was unsupported.
- Source qualification reported `b34b2a...` as candidate identity.

### GREEN

Focused source binding tests:

```text
3 passed, 65 deselected in 2.36s
```

Expanded final-state selection:

```text
83 passed in 4.10s
```

Zero-inotify observer regression:

```text
16 passed in 0.16s
```

Ruff and types:

```text
All checks passed!
All checks passed!
```

### Explicit synthetic qualification

Command used an exact candidate deliberately distinct from the source tree:

```text
candidate_digest:
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

source_tree_digest:
b34b2a12fd0ad3d4c95a58c847a2411e81272a646f5a4f5ec568d0d3640a3747
```

Verifier result:

```text
ACTUAL_SOURCE_GOLDEN_PATH_PASS
```

Every seven-clause artifact and receipt, observer receipt, capability binding, and candidate-authority event uses the explicit `cccc...` candidate.

### Candidate derivation contract

Qualification requires exactly one of:

```text
--candidate-digest <64-lowercase-hex>
--candidate-binding <private-json-file>
```

Omission, malformed values, or candidate equality with the source tree digest fail closed.

File contract:

```json
{
  "schema": "task26-preexecution-candidate-binding-v1",
  "candidate_digest": "<64-hex>",
  "derivation_contract": {
    "schema": "task26-preexecution-candidate-derivation-v1",
    "derived_from": "pre_execution_product_or_wheel_binding",
    "known_before_golden_path": true,
    "evidence_outputs_are_digest_inputs": false
  },
  "binding_sha256": "<hash-of-unsigned-document>"
}
```

The invocation records a normalized private binding:

```text
qualification-candidate-binding.json
```

Source provenance remains separately bound through:

```text
source-provenance.json.tree_digest
driver-input.json.source_tree_digest
verifier result.source_tree_digest
```

Installed provenance now separates:

- explicit outer `candidate_digest`
- independently recomputed `installed_product_binding_digest`

No evidence output participates in either pre-execution candidate derivation.

### Cross-mode parity schema

```text
task26-cross-mode-candidate-parity-v1
```

It binds:

- exact expected candidate
- source seven-clause chain head
- installed seven-clause chain head
- source and installed current authority candidates and authority heads
- source provenance digest
- installed source provenance digest
- source and installed bundle paths
- outer candidate manifest path, hash, and candidate
- parity document hash

The outer manifest uses:

```text
task26-outer-candidate-manifest-v1
```

Frozen rehydration reruns both source and installed verifiers and requires:

```text
source candidate
= installed candidate
= source current authority
= installed current authority
= sealed expected-state candidate
= outer candidate manifest
```

The source-tree digest is allowed—and expected—to differ from candidate identity, but source and installed runs must agree on that tree provenance.

### Adversarial coverage

Tests reject:

- omitted explicit binding
- malformed digest
- direct source-tree-as-candidate substitution
- source/installed candidate mismatch
- authority mismatch
- outer manifest mismatch
- coherently re-signed seven-clause receipts using the source tree digest
- source and installed tree-provenance mismatch

All prior isolation, wheelhouse, trust-boundary, revocation, frozen-mode, and zero-inotify tests remain GREEN.

Task-owned temporary artifacts were removed after restoring permissions. No blockers.


I read this as a test-first replacement of the remaining tautological product binding - I’ll add RED contracts for canonical derivation and truthful wheel receipts, then centralize derivation in one packaged module and thread it through source, installed, and frozen verification.


The current deployment receipt confirms the second blocker: both wheel SHA fields are populated with `candidate_digest`. I’m adding a focused derivation/deployment RED suite before replacing the old wrapper schema and receipt generation.


The reusable derivation module is now in place: candidate identity is the SHA-256 of the complete canonical input object, and deployment receipts carry the two distinct wheel hashes from that validated object. I’m running the focused derivation, source, cutover, and frozen-parity tests now.


I read this as completed canonical product derivation and truthful deployment provenance - candidate identity is now recomputed from full structured inputs everywhere.

### Changed files

- `gateway/platforms/task26_candidate_derivation.py` — new canonical derivation module
- `gateway/platforms/task26_final_state.py`
- `gateway/platforms/dualcoach_activation_cutover.py`
- `scripts/source_golden_path.py`
- `scripts/verify_source_golden_path.py`
- `tests/gateway/test_task26_candidate_derivation.py`
- `tests/gateway/test_task26_final_state.py`
- `tests/gateway/test_source_golden_path_verifier.py`
- `tests/gateway/test_installed_golden_path_provenance.py`

### RED

```text
pytest tests/gateway/test_task26_candidate_derivation.py
```

```text
ModuleNotFoundError:
No module named 'gateway.platforms.task26_candidate_derivation'
1 error
```

### GREEN

Canonical derivation tests:

```text
7 passed in 0.12s
```

Focused derivation/source tests:

```text
10 passed, 45 deselected in 2.51s
```

Final-state tests:

```text
21 passed in 1.35s
```

Expanded Task26 suite:

```text
92 passed in 4.22s
```

Zero-inotify and activation-cutover regressions:

```text
23 passed in 0.24s
```

Ruff and types:

```text
All checks passed!
All checks passed!
```

### Canonical derivation equation

```text
candidate_digest =
    SHA256(canonical(preexecution_product_derivation_inputs))
```

Canonical encoding uses UTF-8 JSON with sorted keys, compact separators, and no NaN values.

Input schema:

```json
{
  "schema": "task26-preexecution-product-derivation-inputs-v1",
  "generation": 1,
  "hermes_wheel_sha256": "<actual-wheel-hash>",
  "profile_wheel_sha256": "<actual-wheel-hash>",
  "wheelhouse_inventory_sha256": "<recursive-inventory-digest>",
  "wheelhouse_entry_count": 0,
  "trust_boundary_sha256": "<canonical-trust-boundary-digest>",
  "qualification_tool_sha256": {
    "candidate_derivation": "...",
    "evidence_contract": "...",
    "final_state": "...",
    "installed_provenance": "...",
    "source_golden_path": "...",
    "verify_source_golden_path": "..."
  }
}
```

Binding schema:

```json
{
  "schema": "task26-preexecution-product-binding-v1",
  "derivation_inputs": {},
  "candidate_digest": "<recomputed-from-inputs>",
  "binding_sha256": "<wrapper-integrity-digest>"
}
```

The wrapper hash cannot manufacture a valid candidate: validators always recompute the candidate from `derivation_inputs`.

Qualification now requires:

```text
--product-binding <private-structured-binding.json>
```

Arbitrary `--candidate-digest` is rejected as an unknown argument.

### Truthful deployment receipt

Schema:

```text
task26-source-deployment-receipt-v2
```

Fields include:

```json
{
  "candidate_digest": "<canonical-product-candidate>",
  "candidate_product_binding_sha256": "<binding-digest>",
  "hermes_wheel_sha256": "<Hermes-wheel-hash>",
  "profile_wheel_sha256": "<profile-wheel-hash>",
  "product_binding": {}
}
```

Candidate identity remains separate from wheel identity. Validation rejects:

- candidate digest copied into either wheel field
- swapped wheel fields
- altered wheel hashes
- matching but unqualified deployment/membership documents
- source/installed deployment receipt mismatch
- actual sealed wheel bytes differing from derivation inputs

### Synthetic source qualification proof

```text
candidate_digest:
da41c4d521133eca009671b96e007b3fd2b574ee12454a5df848a630baf416f9

Hermes wheel:
59eed6af083b4da6aecda92c6eb4f16aef07aff68491254afb3c2019c6965553

Profile wheel:
2c359bffcbb1dc60c4cbcc643daab4d6ea2422015f404c7efed5ff93da5e0a41

source_tree_digest:
b34b2a12fd0ad3d4c95a58c847a2411e81272a646f5a4f5ec568d0d3640a3747
```

Independent verifier result:

```text
ACTUAL_SOURCE_GOLDEN_PATH_PASS
```

All four identities are distinct where required.

### Validation paths

- Source loader: canonical inputs, tool hashes, trust boundary, wrapper, candidate equation.
- Installed driver/verifier: actual Hermes/profile wheel bytes and installed RECORD provenance.
- Activation cutover: deployment receipt and membership evidence must match the authoritative product binding.
- Independent source verifier: deployment receipt, qualification binding, candidate authority, and seven-clause chain.
- Frozen verifier: actual sealed wheels, recursive wheelhouse, tools, trust boundary, outer manifest, and source/installed deployment parity.
- Rehydration: reruns both source and installed chains and requires identical candidate and wheel receipt projections.

All task-owned temporary files were removed after restoring permissions. No implementation blockers; no final installed candidate was built or sealed, as required.


I read this as a test-first v13 provenance hardening pass - I’ll trace capability serialization, installed RECORD handling, and frozen bootstrap packaging, then add focused RED contracts before changing those three surfaces.


The first v13 blocker is confirmed: source qualification still constructs `DeliveryLaunchAuthorization` by repeating `candidate_digest` eight times, so `wheel_digest` is false. I’m adding strict capability identity fields and then binding verifier/artifact projections to the validated product binding.


Capability identity now carries five explicit product fields, and both successful and unknown-delivery evidence are independently checked against deployment provenance. The portable RECORD projection records raw hashes as nonportable while hashing only validated wheel-owned rows and narrowly classified generated material. The standalone bootstrap is now a candidate-bound verification tool.


I read this as v13 provenance blockers implemented and verified - capability identities, portable RECORD projections, and standalone frozen bootstrap now fail closed.

## Changed files

- `gateway/platforms/nutrition_coaching.py`
- `gateway/platforms/task26_candidate_derivation.py`
- `gateway/platforms/task26_final_state.py`
- `scripts/source_golden_path.py`
- `scripts/verify_source_golden_path.py`
- `scripts/installed_wheel_provenance.py`
- `scripts/task26_frozen_bootstrap.py` — new
- `tests/gateway/test_nutrition_coaching.py`
- `tests/gateway/test_task26_candidate_derivation.py`
- `tests/gateway/test_task26_final_state.py`
- `tests/gateway/test_installed_golden_path_provenance.py`
- `tests/gateway/test_task26_frozen_bootstrap.py` — new

## Capability identity contract

Every delivery capability now requires:

```json
{
  "candidate_digest": "<canonical candidate>",
  "candidate_product_binding_sha256": "<product binding hash>",
  "hermes_wheel_sha256": "<actual Hermes wheel hash>",
  "profile_wheel_sha256": "<actual profile wheel hash>",
  "wheel_digest": "<actual Hermes wheel hash>"
}
```

Enforced invariants:

```text
wheel_digest == hermes_wheel_sha256
candidate_digest != hermes_wheel_sha256
candidate_digest != profile_wheel_sha256
hermes_wheel_sha256 != profile_wheel_sha256
```

Source qualification no longer repeats the candidate into wheel-designated fields. Unknown-delivery, successful-lifecycle, final draft-delivery projections, and independent verification all use the same structured product binding.

Machine-readable receipt:

```text
task26-delivery-capability-identity-receipt-v1
```

Source and installed candidate parity now includes this receipt, preventing coherently re-signed capability artifacts from substituting false wheel identities.

## Portable installed RECORD contract

Schema:

```text
task26-portable-installed-record-projection-v1
```

The projection:

- Requires every wheel-owned installed row, hash, and size to match wheel `RECORD`.
- Rejects missing, altered, and unexpected installed rows.
- Classifies only:
  - wheel `.data/scripts` launchers
  - console-entry-point launchers
  - `INSTALLER`
  - `REQUESTED`
  - `direct_url.json`
- Validates launcher ownership, entry-point semantics, and known pip launcher templates.
- Canonicalizes only the venv path in launcher shebangs.
- Produces `projection_sha256`.
- Records `raw_installed_record_sha256` separately with:

```json
{
  "raw_installed_record_portable": false
}
```

Raw RECORD byte equality is explicitly not claimed.

Frozen schemas:

```text
task26-sealed-final-state-v2
task26-frozen-installed-record-provenance-v1
task26-frozen-installed-record-verification-v1
```

Frozen verification records original and rehydrated raw RECORD hashes separately while requiring matching portable projection digests.

## Standalone frozen bootstrap

New tool:

```text
verification-tools/task26_frozen_bootstrap.py
```

Invocation:

```bash
python -I verification-tools/task26_frozen_bootstrap.py <bundle>
```

It is stdlib-only before venv creation and:

- Requires isolated Python.
- Recursively rejects symlinks and unsafe modes.
- Validates expected-state canonical digest.
- Locates and hashes exact sealed wheels.
- Validates recursive wheelhouse entries before execution.
- Creates a private temporary venv and empty controlled CWD.
- Removes inherited Python/PIP authority.
- Installs exact wheels using `--no-index --no-deps --no-compile`.
- Invokes the installed Task26 final-state verifier.
- Scrubs the runtime on success and failure.

Output schema:

```text
task26-frozen-bootstrap-result-v1
```

The bootstrap hash is now part of `qualification_tool_sha256` and therefore contributes to canonical candidate derivation.

## RED/GREEN

Strict capability migration initially produced:

```text
TypeError: DeliveryLaunchAuthorization.__init__() missing 3 required positional arguments:
'hermes_wheel_sha256', 'profile_wheel_sha256',
and 'candidate_product_binding_sha256'
```

After updating all issuance paths and fixtures:

```text
206 passed in 3.04s
```

Focused bootstrap:

```text
5 passed in 1.33s
```

Focused Task26 provenance/final-state:

```text
94 passed in 4.24s
```

Final expanded selection:

```text
333 passed in 8.18s
```

Observer and cutover regression subset:

```text
23 passed in 0.23s
```

Static checks:

```text
ruff: All checks passed!
ty: All checks passed!
py_compile: passed
```

The clean `ty` scope covered the new bootstrap, installed provenance, candidate derivation, final-state implementation, and bootstrap tests. Broader monolithic typing still exposes pre-existing diagnostics in unrelated dirty `nutrition_coaching.py` sections and the stale installed `checkin_cli` package.

## Manual source Golden Path

Command shape:

```bash
python scripts/source_golden_path.py \
  --source /home/cube/.cache/task26-strict-successor-1786976146/src-p \
  --product-binding <private-binding.json> \
  --evidence-root <temporary-bundle>

python scripts/verify_source_golden_path.py <temporary-bundle>
```

Result:

```text
status:
ACTUAL_SOURCE_GOLDEN_PATH_PASS

candidate_digest:
ebda30fa047bde439d3695df1d81b8f6e629286312500d49bb45209bece71515

candidate_product_binding_sha256:
ac5ffc77253b406b46238c51bb4869f1055cc575955fc5131a3e0a05b1af7620

Hermes wheel:
d08b3b1ced0e815207e1a23f0bd5026a8d919aa13521f7b3cac257741e1f3f8e

Profile wheel:
632f64d5496ce2ad52cd867f84c4226bb45b13da7ba01c580bf5dbdf35faa0f8

legacy wheel_digest:
d08b3b1ced0e815207e1a23f0bd5026a8d919aa13521f7b3cac257741e1f3f8e

source_tree_digest:
b34b2a12fd0ad3d4c95a58c847a2411e81272a646f5a4f5ec568d0d3640a3747
```

All candidate, source, Hermes-wheel, and profile-wheel identities are distinct as required.

## Standalone fixture

A bare isolated bootstrap with caller-CWD shadow `gateway` and `PYTHONPATH` contamination passed:

```text
schema: task26-frozen-bootstrap-result-v1
status: TASK26_FROZEN_BOOTSTRAP_PASS
verifier_status: ACTUAL_INSTALLED_GOLDEN_PATH_PASS
```

Tampered wheel, expected state, permissions, and symlink cases failed closed.

Task-owned temporary fixtures were scrubbed. No final candidate was built or sealed; no evidence, ledger, plan, live system, commit, or push was touched. The only remaining limitation is that a real successor sealed-wheel bootstrap was intentionally not run because creating that candidate was prohibited.


I read this as command-only provenance reporting - I’ll reproduce the exact invocations without executing them.

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_nutrition_coaching.py tests/gateway/test_task7_generation_hardening.py --disable-warnings --maxfail=1
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_frozen_bootstrap.py --maxfail=1
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_final_state.py tests/gateway/test_task26_candidate_derivation.py tests/gateway/test_source_golden_path_verifier.py tests/gateway/test_installed_golden_path_provenance.py tests/gateway/test_installed_golden_path_provenance.py tests/gateway/test_task26_final_authority.py --disable-warnings --maxfail=1
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_candidate_derivation.py tests/gateway/test_task26_final_authority.py tests/gateway/test_task26_final_state.py tests/gateway/test_task26_frozen_bootstrap.py tests/gateway/test_source_golden_path_verifier.py tests/gateway/test_installed_golden_path_provenance.py tests/gateway/test_commit_observer.py tests/gateway/test_dualcoach_activation_cutover.py tests/gateway/test_nutrition_coaching.py tests/gateway/test_task7_generation_hardening.py --maxfail=1
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_commit_observer.py tests/gateway/test_dualcoach_activation_cutover.py --disable-warnings --maxfail=1
cd /home/cube/projects/richard/hermes-agent && .venv/bin/ruff check gateway/platforms/nutrition_coaching.py gateway/platforms/task26_candidate_derivation.py gateway/platforms/task26_final_state.py scripts/source_golden_path.py scripts/verify_source_golden_path.py scripts/installed_wheel_provenance.py scripts/task26_frozen_bootstrap.py tests/gateway/test_task26_candidate_derivation.py tests/gateway/test_task26_final_state.py tests/gateway/test_task26_frozen_bootstrap.py tests/gateway/test_installed_golden_path_provenance.py tests/gateway/test_nutrition_coaching.py
cd /home/cube/projects/richard/hermes-agent && .venv/bin/ty check scripts/installed_wheel_provenance.py scripts/task26_frozen_bootstrap.py gateway/platforms/task26_candidate_derivation.py gateway/platforms/task26_final_state.py tests/gateway/test_task26_frozen_bootstrap.py
cd /home/cube/projects/richard/hermes-agent && root=$(mktemp -d /tmp/task26-v13-source-XXXXXX)
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python - "$root/product-binding.json" <<'PY'
import importlib.util,pathlib,sys
p=pathlib.Path('tests/gateway/test_source_golden_path_verifier.py'); s=importlib.util.spec_from_file_location('v13fixture',p); m=importlib.util.module_from_spec(s); s.loader.exec_module(m)
out=pathlib.Path(sys.argv[1]); out.write_bytes(m._canonical(m.TEST_PRODUCT_BINDING)+b'\n'); out.chmod(0o600)
PY
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python scripts/source_golden_path.py --source /home/cube/.cache/task26-strict-successor-1786976146/src-p --product-binding "$root/product-binding.json" --evidence-root "$root/bundle" > "$root/driver.json"
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python scripts/verify_source_golden_path.py "$root/bundle" > "$root/verifier.json"
cd /home/cube/projects/richard/hermes-agent && chmod -R u+rwX "$root" 2>/dev/null || true
cd /home/cube/projects/richard/hermes-agent && find "$root" -type l -delete 2>/dev/null || true
cd /home/cube/projects/richard/hermes-agent && rm -rf "$root"
```


I read this as a focused v14 typing repair and auditable Ty surface gate - I’ll add the persisted-capability regression first, then narrow only the named delivery paths and build an AST-span gate that reports rather than hides outside monolith debt.


The baseline machine count matches the diagnosis exactly: 527 total GitLab diagnostics, 34 inside the eight AST-derived capability spans, and 493 outside. I’m locking that boundary into the new gate receipt rather than changing or excluding whole-file Ty behavior.


The narrowing is now behavior-neutral and the gate reports the intended boundary: 493 total diagnostics, zero in all eight capability spans, and all 493 explicitly retained as outside-scope debt. I’m running the behavioral and expanded regressions plus direct zero-diagnostic Task26 type checks next.


I read this as completed v14 Ty surface repair - report exact counts, schemas, commands, results, and remaining outside-scope debt.

## Changed files

- `gateway/platforms/nutrition_coaching.py`
- `tests/gateway/test_nutrition_coaching.py`
- `scripts/task26_ty_surface_gate.py`
- `tests/gateway/test_task26_ty_surface_gate.py`

## Ty counts

```text
Before:
527 total
34 capability-surface diagnostics
493 outside-surface diagnostics

After:
493 total
0 capability-surface diagnostics
493 outside-surface diagnostics
```

No diagnostics were ignored, suppressed, excluded, or hidden.

## Receipt

Schema:

```text
task26-ty-capability-surface-receipt-v1
```

Status:

```text
PASS_CHANGED_SURFACE_WITH_PREEXISTING_OUTSIDE_SCOPE_DIAGNOSTICS
```

Hashes:

```text
outside_surface_fingerprint_sha256:
514fd0ce0407e4d7735825cad0fc11b75d732f0aed16ce598a3e3c4790d274d1

receipt_sha256:
55bb9d44636b3d2764a3e9bffe69c23555d920158524e6752f0b9ad918a14f02
```

The receipt explicitly records:

```json
{
  "v13_nutrition_coaching_scanned_or_sealed": false,
  "v14_first_exposed_dirty_monolith_ty_debt": true,
  "outside_scope_diagnostics_fixed_or_claimed_clean": false
}
```

## RED

Gate absent:

```text
1 failed
returncode 2: task26_ty_surface_gate.py did not exist
```

Behavioral regression after gate creation but before narrowing:

```text
1 failed, 174 deselected
capability_diagnostic_count: 34
total_diagnostic_count: 527
outside_surface_diagnostic_count: 493
```

## GREEN

Focused gate tests:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_ty_surface_gate.py --maxfail=1
```

```text
2 passed in 0.15s
```

Persisted-capability regression:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_nutrition_coaching.py -k persisted_delivery_capability_identity_survives_transport_claim --maxfail=1
```

```text
1 passed, 174 deselected in 0.95s
```

Capability behavioral suites:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_nutrition_coaching.py tests/gateway/test_task7_generation_hardening.py --maxfail=1
```

```text
212 passed in 3.29s
```

Expanded selection:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_candidate_derivation.py tests/gateway/test_task26_final_authority.py tests/gateway/test_task26_final_state.py tests/gateway/test_task26_frozen_bootstrap.py tests/gateway/test_task26_ty_surface_gate.py tests/gateway/test_source_golden_path_verifier.py tests/gateway/test_installed_golden_path_provenance.py tests/gateway/test_commit_observer.py tests/gateway/test_dualcoach_activation_cutover.py tests/gateway/test_nutrition_coaching.py tests/gateway/test_task7_generation_hardening.py --maxfail=1
```

```text
336 passed in 8.85s
```

Focused zero-diagnostic Ty scope:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/ty check scripts/task26_ty_surface_gate.py scripts/installed_wheel_provenance.py scripts/task26_frozen_bootstrap.py gateway/platforms/task26_candidate_derivation.py gateway/platforms/task26_final_state.py tests/gateway/test_task26_ty_surface_gate.py tests/gateway/test_task26_frozen_bootstrap.py
```

```text
All checks passed!
```

Full monolith Ty receipt:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python scripts/task26_ty_surface_gate.py --source gateway/platforms/nutrition_coaching.py --receipt /tmp/task26-v14-ty-receipt.json
```

```text
493 total
0 capability surface
493 outside surface
PASS_CHANGED_SURFACE_WITH_PREEXISTING_OUTSIDE_SCOPE_DIAGNOSTICS
```

Ruff:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/ruff check gateway/platforms/nutrition_coaching.py scripts/task26_ty_surface_gate.py tests/gateway/test_nutrition_coaching.py tests/gateway/test_task26_ty_surface_gate.py
```

```text
All checks passed!
```

Compilation:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m py_compile gateway/platforms/nutrition_coaching.py scripts/task26_ty_surface_gate.py tests/gateway/test_task26_ty_surface_gate.py
```

```text
passed
```

## Manual source Golden Path

```bash
cd /home/cube/projects/richard/hermes-agent
root=$(mktemp -d /tmp/task26-v14-source-XXXXXX)
.venv/bin/python - "$root/product-binding.json" <<'PY'
import importlib.util,pathlib,sys
path=pathlib.Path('tests/gateway/test_source_golden_path_verifier.py')
spec=importlib.util.spec_from_file_location('v14_fixture',path)
module=importlib.util.module_from_spec(spec)
assert spec.loader is not None
spec.loader.exec_module(module)
out=pathlib.Path(sys.argv[1])
out.write_bytes(module._canonical(module.TEST_PRODUCT_BINDING)+b'\n')
out.chmod(0o600)
PY
.venv/bin/python scripts/source_golden_path.py --source /home/cube/.cache/task26-strict-successor-1786976146/src-p --product-binding "$root/product-binding.json" --evidence-root "$root/bundle" > "$root/driver.json"
.venv/bin/python scripts/verify_source_golden_path.py "$root/bundle" > "$root/verifier.json"
```

Result:

```text
ACTUAL_SOURCE_GOLDEN_PATH_PASS

candidate_digest:
ebda30fa047bde439d3695df1d81b8f6e629286312500d49bb45209bece71515

candidate_product_binding_sha256:
ac5ffc77253b406b46238c51bb4869f1055cc575955fc5131a3e0a05b1af7620

hermes_wheel_sha256:
d08b3b1ced0e815207e1a23f0bd5026a8d919aa13521f7b3cac257741e1f3f8e

profile_wheel_sha256:
632f64d5496ce2ad52cd867f84c4226bb45b13da7ba01c580bf5dbdf35faa0f8

source_tree_digest:
b34b2a12fd0ad3d4c95a58c847a2411e81272a646f5a4f5ec568d0d3640a3747
```

Task-owned temporary source and receipt files were removed.

## Blocker

The changed capability surface is type-clean. The remaining 493 diagnostics are pre-existing dirty-monolith debt outside the named AST spans; v14 neither fixes nor claims those diagnostics clean. No final candidate was built or sealed, and no evidence, ledger, plan, live system, commit, or push was touched.


I read this as closing the final candidate-integrity gap - I’ll first add a failing derivation test for omitted/tampered `ty_surface_gate`, then extend the canonical tool set so source, frozen, and bootstrap validation all inherit the same binding.


The RED edge is now closed: the candidate test rejected the new required key before implementation, and frozen verification previously accepted changed gate bytes. After adding the canonical key/path and copying the tool into verification bundles, both cases fail closed.


I read this as the final derivation integrity edge completed - `task26_ty_surface_gate.py` is now candidate-bound and frozen verification rejects altered bytes.

## Changed files

- `gateway/platforms/task26_candidate_derivation.py`
- `scripts/source_golden_path.py`
- `tests/gateway/test_task26_candidate_derivation.py`
- `tests/gateway/test_task26_final_state.py`

## Binding change

Added canonical tool key:

```text
ty_surface_gate
```

Bound path:

```text
verification-tools/task26_ty_surface_gate.py
```

`source_golden_path.py` now copies this tool into `verification-tools`. Source qualification, standalone rehydration, and final-state verification inherit the complete exact tool set through `qualification_tool_hashes()`.

## RED

Candidate derivation rejected the newly expected key before implementation:

```text
1 failed
ValueError: candidate derivation inputs are invalid
```

Frozen verification initially accepted changed gate bytes:

```text
1 failed, 1 passed, 20 deselected
Failed: DID NOT RAISE ValueError
```

## GREEN

Candidate derivation:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_candidate_derivation.py --maxfail=1
```

```text
8 passed in 0.13s
```

Ty gate:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_ty_surface_gate.py --maxfail=1
```

```text
2 passed in 0.15s
```

Final-state suite:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_final_state.py --maxfail=1
```

```text
22 passed in 1.37s
```

Expanded focused suite:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_candidate_derivation.py tests/gateway/test_task26_final_authority.py tests/gateway/test_task26_final_state.py tests/gateway/test_task26_frozen_bootstrap.py tests/gateway/test_task26_ty_surface_gate.py tests/gateway/test_source_golden_path_verifier.py tests/gateway/test_installed_golden_path_provenance.py tests/gateway/test_commit_observer.py tests/gateway/test_dualcoach_activation_cutover.py tests/gateway/test_nutrition_coaching.py tests/gateway/test_task7_generation_hardening.py --maxfail=1
```

```text
338 passed in 8.87s
```

Ruff:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/ruff check gateway/platforms/task26_candidate_derivation.py gateway/platforms/task26_final_state.py scripts/source_golden_path.py scripts/task26_ty_surface_gate.py scripts/task26_frozen_bootstrap.py scripts/installed_wheel_provenance.py tests/gateway/test_task26_candidate_derivation.py tests/gateway/test_task26_final_state.py tests/gateway/test_task26_ty_surface_gate.py
```

```text
All checks passed!
```

Ty:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/ty check gateway/platforms/task26_candidate_derivation.py gateway/platforms/task26_final_state.py scripts/task26_ty_surface_gate.py scripts/task26_frozen_bootstrap.py scripts/installed_wheel_provenance.py
```

```text
All checks passed!
```

The tests now reject:

- Omitted `ty_surface_gate` hash.
- Mismatched gate hash.
- Gate-tool byte changes despite an otherwise valid product binding.
- Gate-tool byte changes during frozen expected-state verification.

No blockers. No candidate was built or sealed, and no evidence, ledger, plan, commit, push, or live system was touched.


I read this as a test-first extension for one PEP 427 relocation case - I’ll add `.data/data` fixture failures first, then implement only the static-data mapping while leaving script normalization and all other schemes unchanged.


The narrow `data` branch is green: it requires the installed RECORD hash and size, verifies wheel payload and relocated bytes byte-for-byte, and emits a static-data row with `{data}/...`; script handling is untouched and unsupported schemes still fail closed.


I read this as the v15 portable RECORD blocker completed - `.data/data` relocation is now byte-exact and narrowly classified.

## Changed files

- `scripts/installed_wheel_provenance.py`
- `tests/gateway/test_installed_golden_path_provenance.py`

## RED

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_installed_golden_path_provenance.py -k relocated_static_data --maxfail=1
```

```text
1 failed, 17 deselected
ValueError: unsupported path-dependent wheel entry
```

## Implementation

Only PEP 427 scheme `data` was added:

```text
<distribution>.data/data/<suffix>
    -> <venv>/<suffix>
```

Projection row:

```json
{
  "kind": "wheel_owned_relocated_static_data",
  "wheel_path": "relocated_data-1.0.data/data/share/task26/policy.json",
  "installed_path": "../../../share/task26/policy.json",
  "canonical_destination": "{data}/share/task26/policy.json",
  "sha256": "<exact-wheel-payload-hash>",
  "size": 31
}
```

It rejects:

- Empty, absolute, or `..` suffixes.
- Missing or extra installed RECORD rows.
- Altered RECORD hash or size.
- Altered installed bytes.
- Symlink, special, or multi-link targets.
- Every unsupported `.data` scheme.

No byte, path-content, or shebang normalization is applied. Existing `scripts` handling is unchanged.

## Results

Provenance suite:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_installed_golden_path_provenance.py --maxfail=1
```

```text
23 passed in 0.31s
```

Expanded focused suite:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_candidate_derivation.py tests/gateway/test_task26_final_authority.py tests/gateway/test_task26_final_state.py tests/gateway/test_task26_frozen_bootstrap.py tests/gateway/test_task26_ty_surface_gate.py tests/gateway/test_source_golden_path_verifier.py tests/gateway/test_installed_golden_path_provenance.py tests/gateway/test_commit_observer.py tests/gateway/test_dualcoach_activation_cutover.py tests/gateway/test_nutrition_coaching.py tests/gateway/test_task7_generation_hardening.py --maxfail=1
```

```text
348 passed in 8.89s
```

Ruff:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/ruff check scripts/installed_wheel_provenance.py tests/gateway/test_installed_golden_path_provenance.py gateway/platforms/task26_candidate_derivation.py gateway/platforms/task26_final_state.py scripts/task26_ty_surface_gate.py scripts/task26_frozen_bootstrap.py
```

```text
All checks passed!
```

Ty:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/ty check scripts/installed_wheel_provenance.py tests/gateway/test_installed_golden_path_provenance.py gateway/platforms/task26_candidate_derivation.py gateway/platforms/task26_final_state.py scripts/task26_ty_surface_gate.py scripts/task26_frozen_bootstrap.py
```

```text
All checks passed!
```

Disposable projection result:

```text
schema: task26-portable-installed-record-projection-v1
projection_sha256:
8eebe0ed9b79b968bb3a7dbc074bb352a46deabf53cb7543fb77d209db8a63c4

installed path:
../../../share/task26/policy.json

canonical destination:
{data}/share/task26/policy.json
```

The disposable runtime was removed. No blockers; no final candidate, evidence, ledger, or live system was touched.


I read this as separating portable equality from nonportable RECORD audit evidence - I’ll first add an asymmetric launcher-path RED fixture against the current comparator, then move raw hashes into independently sealed audit receipts and update frozen rehydration validation without weakening projection equality.


Codex error: Our servers are currently overloaded. Please try again later.


The portable object is now v2 and contains no raw RECORD hash or path. Original and rehydrated raw hashes are independently hash-bound under the nonportable audit schema, while the pair verifier compares only candidate, wheels, and portable projection digests.


I read this as the v16 rehydration blocker completed - portable equality now excludes raw RECORD identity while retaining separately sealed audit evidence.

## Changed files

- `scripts/installed_wheel_provenance.py`
- `gateway/platforms/task26_final_state.py`
- `scripts/source_golden_path.py`
- `scripts/verify_source_golden_path.py`
- `tests/gateway/test_installed_golden_path_provenance.py`
- `tests/gateway/test_task26_final_state.py`

## RED

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_installed_golden_path_provenance.py -k portable_runtime_ignores_validated_raw_launcher_record_drift --maxfail=1
```

```text
1 failed, 23 deselected
```

The only difference was:

```text
raw_installed_records_nonportable.profile.sha256
raw_installed_records_nonportable.hermes.sha256
```

Portable projection digests matched.

## Schemas

```text
installed-golden-runtime-portable-v2
task26-nonportable-installed-record-audit-v1
task26-sealed-final-state-v3
task26-frozen-installed-record-verification-v2
```

`installed-golden-runtime-portable-v2` now contains no:

- Raw installed RECORD hash.
- Raw RECORD path.
- Raw portability label.
- Path-dependent launcher entry.

Each original or rehydrated audit independently binds:

```json
{
  "schema": "task26-nonportable-installed-record-audit-v1",
  "install_role": "original|rehydrated",
  "candidate_digest": "<candidate>",
  "distributions": {
    "profile|hermes": {
      "distribution": "<name>",
      "wheel_sha256": "<wheel>",
      "portable_projection_sha256": "<projection>",
      "raw_installed_record_sha256": "<raw hash>",
      "raw_installed_record_portable": false,
      "reason": "validated_path_dependent_installer_material_may_change_raw_record",
      "path_dependent_classifications": []
    }
  },
  "audit_sha256": "<canonical audit hash>"
}
```

Raw hashes are exposed and independently hash-bound but never compared.

## Results

Provenance:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_installed_golden_path_provenance.py --maxfail=1
```

```text
25 passed in 0.34s
```

Final-state plus provenance:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_final_state.py tests/gateway/test_installed_golden_path_provenance.py --maxfail=1
```

```text
55 passed in 1.65s
```

Focused provenance/final-state/bootstrap/source verification:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_installed_golden_path_provenance.py tests/gateway/test_task26_final_state.py tests/gateway/test_task26_frozen_bootstrap.py tests/gateway/test_source_golden_path_verifier.py --maxfail=1
```

```text
109 passed in 5.51s
```

Bare bootstrap fixture:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_frozen_bootstrap.py --maxfail=1
```

```text
5 passed in 1.33s
```

Expanded suite:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_candidate_derivation.py tests/gateway/test_task26_final_authority.py tests/gateway/test_task26_final_state.py tests/gateway/test_task26_frozen_bootstrap.py tests/gateway/test_task26_ty_surface_gate.py tests/gateway/test_source_golden_path_verifier.py tests/gateway/test_installed_golden_path_provenance.py tests/gateway/test_commit_observer.py tests/gateway/test_dualcoach_activation_cutover.py tests/gateway/test_nutrition_coaching.py tests/gateway/test_task7_generation_hardening.py --maxfail=1
```

```text
358 passed in 8.91s
```

Ruff:

```text
All checks passed!
```

Ty:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/ty check scripts/installed_wheel_provenance.py gateway/platforms/task26_final_state.py scripts/task26_frozen_bootstrap.py scripts/task26_ty_surface_gate.py gateway/platforms/task26_candidate_derivation.py
```

```text
All checks passed!
```

## Asymmetric audit fixture

```text
schema:
task26-frozen-installed-record-verification-v2

raw_record_hash_equality_required_or_claimed:
false

original audit:
e4cbd4a759016977b10a08849c31ffa165a4b352eafc0e4d6f92c2733588f877

rehydrated audit:
3481b346ab44c23e267b46c72d355336acb65353a6570b151c433ac441659b2b
```

Tests cover:

- Different valid raw hashes.
- Equal raw hashes.
- Missing or forged audit.
- Wrong audit-to-projection binding.
- Mismatched original/rehydrated projections.
- Raw hash leaked into portable state.
- Candidate and wheel binding.
- Independently sealed original and rehydrated audits.

## Blocker

The disposable asymmetric pair and bare isolated bootstrap fixture both passed. A combined run through a real successor sealed-wheel bundle was not performed because no successor candidate may be built or sealed. No evidence, ledger, live system, commit, or push was touched.


I read this as replacing ambient Ty execution with a wheel-pinned, offline attestation chain - I’ll first locate the sealed Ty/dependency fixture and map the current gate/frozen derivation surfaces, then add hostile-environment RED tests before implementing the isolated runner.


I read this as hermetic Ty attestation implementation - inspection found the sealed Ty wheel cannot execute Ty, so proceeding would require prohibited ambient substitution or resealing.

## Hard blocker

Sealed wheel:

```text
/home/cube/.cache/task26-dependency-wheelhouse-st_01a01309/ty-0.0.21-py3-none-manylinux_2_17_x86_64.whl
sha256: 66363a9e722c30829ad6e2dbc9e55ed9f55afb0d46569152a684fb975ed816b7
size: 6562
version: 0.0.21
```

Its inventory contains only Python wrapper files:

```text
ty/__init__.py
ty/__main__.py
ty/_find_ty.py
ty/py.typed
ty-0.0.21.dist-info/*
```

It contains no:

```text
ty-0.0.21.data/scripts/ty
bin/ty
native Ty executable
```

Its wheel RECORD likewise has no executable row.

An isolated offline installation produced no `venv/bin/ty`. Running:

```bash
<private-venv>/bin/python -I -m ty --version
```

failed with:

```text
ty._find_ty.TyNotFound:
Could not find the ty binary
```

The available ambient executable is separate and not wheel-owned:

```text
.venv/bin/ty
sha256: a7c67f977d2684af6eb4c0ecc011e6e8e3227180353fd9be46bc7371a2f88d16
version: ty 0.0.21
size: 23799008
```

Using it, or the matching UV-cache executable, would directly violate the requirement to derive executable provenance from the exact sealed wheel.

All historical sealed wheelhouse copies inspected have the same malformed wheel hash. Fixing this requires producing a corrected Ty wheel containing the native `.data/scripts/ty` member and sealing its new hash. That action was explicitly prohibited.

There is also a provenance-order conflict: raw diagnostics and the final receipt are execution outputs, while canonical candidate derivation is required to be pre-execution and non-circular. They can be sealed in frozen expected state, but cannot become same-invocation candidate inputs without replacing the established pre-execution derivation contract.

No files were changed. No evidence, ledger, candidate, or live system was touched.


I read this as authorizing deterministic Ty-wheel correction and hermetic attestation tooling, while preserving pre-execution/post-execution ordering - I’ll add builder and hostile-runner RED fixtures first, then bind only builder/runner/toolchain identities into candidate derivation and keep raw diagnostics exclusively in receipt v2/frozen state.


The corrected wheel and runner are now functional under hostile ambient authority: the wheel is deterministic, installs an exact native executable offline, and receipt v2 classifies only the separately persisted raw GitLab bytes. Candidate inputs bind toolchain identities only; raw output remains post-execution.


I read this as hermetic Ty attestation implemented - deterministic corrected wheel, isolated runner, receipt v2, candidate ordering, and frozen rerun binding are now in place.

## Changed files

- `scripts/task26_build_ty_executable_wheel.py` — new
- `scripts/task26_hermetic_ty_runner.py` — new
- `scripts/task26_ty_surface_gate.py`
- `scripts/source_golden_path.py`
- `gateway/platforms/task26_candidate_derivation.py`
- `gateway/platforms/task26_final_state.py`
- `tests/gateway/test_task26_ty_wheel_builder.py` — new
- `tests/gateway/test_task26_ty_surface_gate.py`
- `tests/gateway/test_task26_candidate_derivation.py`
- `tests/gateway/test_task26_final_state.py`
- Supporting binding fixtures in source, installed-provenance, and nutrition tests

## Schemas

```text
task26-corrected-ty-wheel-build-provenance-v1
task26-hermetic-ty-execution-v1
task26-hermetic-ty-attestation-v1
task26-ty-capability-surface-receipt-v2
task26-preexecution-hermetic-ty-binding-v1
task26-sealed-hermetic-ty-attestation-v1
task26-sealed-final-state-v4
```

Candidate derivation binds only pre-execution facts:

- Builder and runner tool hashes.
- Corrected Ty wheel hash.
- Ty version.
- Binary wheel-member path and hash.

Raw diagnostics, execution provenance, and receipt hashes remain post-execution sealed-state inputs.

## RED

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_ty_wheel_builder.py --maxfail=1
```

```text
1 failed
task26_build_ty_executable_wheel.py: No such file or directory
```

## Corrected fixture hashes

```text
wrapper wheel:
66363a9e722c30829ad6e2dbc9e55ed9f55afb0d46569152a684fb975ed816b7

corrected executable wheel:
932d4552233cfbaa325ddc3db5982150a37f437cf94a332eb3869052148bfe4c

native executable / wheel member:
a7c67f977d2684af6eb4c0ecc011e6e8e3227180353fd9be46bc7371a2f88d16

builder tool:
5cb2f50db314248d1009bb002532085450adc95bf2d32678d9d4d9445b360e40

runner tool:
8ce15db3f0198148cd0fa0a94af9a32a80acd3a3a797815c474eda2408720680

gate tool:
e3660b81e34333ec48815c11b4be0c4f8801919d9e270f5ce3dfbb3d3839a66b

build provenance:
0b2fbc46eec3c4102286ff09c586d7be376308edf05422abf84d2b39465e1b78
```

Installed execution:

```text
installed RECORD:
91f32cab9639e49464cac88085b5fff9f16e28dcdcd2658e267c96d679588fcd

raw GitLab diagnostics:
fb6763da61b4dacec03193fd4bb4b206b6a400cd24ba46f1d17a68bdbc90153c

execution provenance:
c035484a922664b2ca0259ad3e6ee8f684bdfcfdc6e2a62fc0dae4a1311636cb

surface receipt v2:
215b965fc04499cd56ed4741122125af6d42661bfde26e1406417598a66e9d70
```

Hermetic diagnostic disclosure:

```text
total: 809
capability surface: 0
outside scope: 809
```

The whole file is not claimed clean.

## Verification

Focused builder/gate/derivation:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_ty_wheel_builder.py tests/gateway/test_task26_ty_surface_gate.py tests/gateway/test_task26_candidate_derivation.py --maxfail=1
```

```text
24 passed in 9.80s
```

Focused final-state/security:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_final_state.py tests/gateway/test_task26_ty_wheel_builder.py tests/gateway/test_task26_ty_surface_gate.py tests/gateway/test_task26_candidate_derivation.py --maxfail=1
```

```text
54 passed in 11.11s
```

Expanded:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_candidate_derivation.py tests/gateway/test_task26_final_authority.py tests/gateway/test_task26_final_state.py tests/gateway/test_task26_frozen_bootstrap.py tests/gateway/test_task26_ty_surface_gate.py tests/gateway/test_task26_ty_wheel_builder.py tests/gateway/test_source_golden_path_verifier.py tests/gateway/test_installed_golden_path_provenance.py tests/gateway/test_commit_observer.py tests/gateway/test_dualcoach_activation_cutover.py tests/gateway/test_nutrition_coaching.py tests/gateway/test_task7_generation_hardening.py --maxfail=1
```

```text
372 passed in 17.98s
```

Ruff:

```text
All checks passed!
```

Ty:

```text
All checks passed!
```

Tests reject:

- Non-ELF and wrong-architecture binaries.
- Wrong Ty version.
- Symlinked native executable.
- Altered wrapper members or invalid RECORD.
- Duplicate executable member.
- Altered corrected wheel.
- Wrong executable hash.
- Original wrapper substituted for corrected wheel.
- Hostile ambient `ty`, `PATH`, CWD, and `PYTHONPATH`.
- Empty fake GitLab output.
- Missing or mismatched execution provenance.

Repeated corrected-wheel builds and repeated hermetic executions reproduce wheel, raw diagnostics, and receipt bytes.

Frozen rehydration now locates the corrected Ty wheel by its candidate-bound hash, reruns the installed runner, and compares raw diagnostics, execution provenance, executable identity, and receipt against sealed expected state. Bootstrap inherits this through final-state verification.

The corrected wheel was generated only in disposable test/runtime directories and removed. No final product candidate was built or sealed, and no evidence, ledger, live system, commit, push, or download was performed.


I read this as a new external runtime authorization layer wired into real activation, capability issuance, and provider-send critical sections - I’ll first map the existing authority ledger and actual Telegram send path, then add concurrency-safe RED tests before touching production seams.


The existing authority chain is bundle-oriented and lacks source/genesis identity or locking. I’m introducing a separate external runtime authority contract rather than weakening or repurposing bundled v1; bundled authority remains historical verification only.


The external authority path is now active in source qualification, activation, capability issuance, and the real Telegram provider-send boundary. Shared authorization remains held across the awaited sender; the exclusive writer test proves revocation waits without sleeps or polling.


I read this as security blocker 2 implemented - external runtime authority now gates activation, capability issuance, and actual provider transport under flock-held snapshots.

## Changed files

- `gateway/platforms/task26_runtime_authority.py` — new, 182 LOC
- `gateway/platforms/dualcoach_activation_cutover.py`
- `gateway/platforms/nutrition_coaching.py`
- `gateway/platforms/telegram.py`
- `gateway/platforms/task26_candidate_derivation.py`
- `gateway/platforms/task26_final_state.py`
- `scripts/source_golden_path.py`
- `scripts/verify_source_golden_path.py`
- `tests/gateway/test_task26_runtime_authority.py` — new
- `tests/gateway/test_dualcoach_activation_cutover.py`
- `tests/gateway/test_nutrition_coaching.py`
- `tests/gateway/test_task26_candidate_derivation.py`
- `tests/gateway/test_task26_final_state.py`

## Schemas

```text
task26-authority-pin-v1
task26-runtime-authority-snapshot-v1
```

External authority continues using fully validated paired chains:

```text
task26-candidate-revocation-registry-v1
task26-qualification-ledger-v1
```

The external documents additionally bind identical:

```text
source_id
genesis_sha256
```

Bundled candidate authority remains historical-only through the existing authority statement. A one-event copied/self-qualified bundle root is explicitly rejected for runtime use.

## Runtime behavior

`CandidateAuthoritySource.authorize()`:

- Acquires `flock(LOCK_SH)`.
- Rereads and verifies both complete chains.
- Validates source, genesis, heads, count, current candidate, revocation state, and predecessor lineage.
- Rejects rollback and successor mismatch.
- Holds the shared lock through the yielded operation.

`append_external_authority()` acquires `LOCK_EX`. The concurrency test uses `Barrier`, `Event`, and bounded `join`; no sleeps or polling.

## Actual production seams

Activation lock:

```text
gateway/platforms/dualcoach_activation_cutover.py:117
```

Capability issuance and bound latest snapshot:

```text
gateway/platforms/nutrition_coaching.py:6548
gateway/platforms/nutrition_coaching.py:6585
```

Immediate provider transport recheck:

```text
gateway/platforms/nutrition_coaching.py:2880
gateway/platforms/telegram.py:7359
```

The Telegram callback holds the shared authority context across:

```python
await self._send_nutrition_topic(...)
```

Revocation or authority failure before provider invocation records:

```json
{
  "status": "provider_not_started",
  "provider_not_started": true
}
```

It does not invoke the sender and does not classify the attempt as unknown provider outcome.

## Source/installed evidence

Source Golden now creates a deterministic external authority fixture with:

1. Historical predecessor qualification.
2. Historical revocation.
3. Current candidate qualification.

Its independently supplied pin and authority root are outside profile, package, candidate, receipt, and wheel roots. The external root is removed after qualification.

Snapshots are bound into:

- Activation result.
- `DeliveryLaunchAuthorization`.
- Capability bindings and draft-delivery rows.
- Unknown-delivery evidence.
- Successful-lifecycle evidence.
- Source/installed verifier results.
- Cross-mode frozen candidate parity.

The independent verifier validates snapshot hash, source, candidate, and final capability agreement.

## Results

Runtime authority:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_runtime_authority.py --maxfail=1
```

```text
13 passed in 0.15s
```

Activation:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_dualcoach_activation_cutover.py --maxfail=1
```

```text
8 passed in 0.16s
```

Revocation and actual delivery Golden paths:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_nutrition_coaching.py -k 'task26_revocation_after_capability or dualcoach_golden_path' --maxfail=1
```

```text
2 passed, 174 deselected in 0.54s
```

Focused authority/activation/nutrition/Golden:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_runtime_authority.py tests/gateway/test_dualcoach_activation_cutover.py tests/gateway/test_nutrition_coaching.py tests/gateway/test_task7_generation_hardening.py tests/gateway/test_source_golden_path_verifier.py --maxfail=1
```

```text
283 passed in 5.46s
```

Final-state/Golden authority projection:

```text
91 passed in 4.11s
```

Expanded suite:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_runtime_authority.py tests/gateway/test_task26_candidate_derivation.py tests/gateway/test_task26_final_authority.py tests/gateway/test_task26_final_state.py tests/gateway/test_task26_frozen_bootstrap.py tests/gateway/test_task26_ty_surface_gate.py tests/gateway/test_task26_ty_wheel_builder.py tests/gateway/test_source_golden_path_verifier.py tests/gateway/test_installed_golden_path_provenance.py tests/gateway/test_commit_observer.py tests/gateway/test_dualcoach_activation_cutover.py tests/gateway/test_nutrition_coaching.py tests/gateway/test_task7_generation_hardening.py --maxfail=1
```

```text
387 passed in 18.03s
```

Ruff:

```text
All checks passed!
```

Ty focused scope:

```text
All checks passed!
```

Disposable source Golden plus independent verifier:

```text
1 passed, 48 deselected in 1.57s
```

## Covered failures

- Missing pin or authority files.
- Unsafe mode, symlink, or forbidden root.
- Wrong source or genesis.
- Copied one-event bundle authority.
- Stale pin heads/count.
- Chain tamper and paired-chain mismatch.
- Revoked/current-candidate mismatch.
- Activation revoked before start; customer remains disabled.
- Revocation after capability; zero sender calls.
- Exclusive revocation waits for in-flight transport.
- Snapshot tamper and coherently rehashed wrong-source snapshot.
- Cross-mode snapshot mismatch.

No final candidate was built or sealed. No evidence, ledger, live service, Telegram API, commit, or push was touched. No implementation blocker remains; live Telegram itself was intentionally not contacted, while its real callback call site is covered through the production adapter path.


I read this as read-only verification provenance - reproduce exact commands and classify the 12 diagnostics without execution.

Focused Ty PASS:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/ty check gateway/platforms/task26_runtime_authority.py gateway/platforms/dualcoach_activation_cutover.py gateway/platforms/task26_candidate_derivation.py gateway/platforms/task26_final_state.py scripts/task26_build_ty_executable_wheel.py scripts/task26_hermetic_ty_runner.py scripts/task26_ty_surface_gate.py
```

91-pass final-state/Golden authority projection:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_runtime_authority.py tests/gateway/test_task26_final_state.py tests/gateway/test_source_golden_path_verifier.py --maxfail=1
```

All 12 diagnostics from the broader `source_golden_path.py`/`verify_source_golden_path.py` Ty invocation were pre-existing `checkin_cli` environment/version-resolution issues:

- 4 unresolved imports:
  - `checkin_cli.customer_cleanup` in both scripts.
  - `checkin_cli.nutrition_onboarding_clarification_policy` in both scripts.
- 5 stale installed-package signature diagnostics in `source_golden_path.py`:
  - Unsupported `reference_date`.
  - Unsupported `expected_issue_id` twice.
  - Unsupported `expected_reconciliation_digest` twice.
- 3 stale installed-package signature diagnostics in `verify_source_golden_path.py`:
  - Missing `clarifications`.
  - Unsupported `answers`.
  - Unsupported `reference_date`.

Ty resolved those APIs against the older installed `.venv` `checkin_cli`, while the Golden Path intentionally targets the separately supplied successor source/package authority. None of the 12 diagnostics referenced `task26_runtime_authority`, authority snapshots, source/genesis fields, locking, activation integration, or transport authorization. Therefore zero of the 12 were introduced authority errors.


I read this as closing production construction bypasses rather than changing the authority primitive - I’ll enumerate every coordinator, activation CLI, and service-start constructor, add RED call-site tests, then make production mode explicit and fail-closed while preserving only explicitly marked preview/test fixtures.


Production construction is now fail-closed at all discovered call sites: Telegram loads only env/systemd credentials, activation CLI requires explicit authority arguments before preflight writes, and service launch holds external authority through `_start_service` and seals its snapshot into the launch authorization.


I read this as completing Task26 authority hardening - implementation, call-site audit, and verification are complete.

### Production call-site matrix

| Surface | Authority enforcement | Failure behavior | Snapshot binding |
|---|---|---|---|
| Telegram nutrition construction | `FileCandidateAuthoritySource`; absolute private env/systemd credentials; `runtime_required=True` | No coordinator constructed | Capability and delivery bindings |
| Telegram provider callback | Authorization spans actual provider transport | `provider_not_started`; sender not invoked | Delivery capability receipt |
| `dualcoach_admin customer activate` | Required `--task26-authority-pin` and `--task26-candidate-digest` | Rejects before preflight or mutation | Activation/bootstrap receipt |
| Tasks 21–25 service launch | Candidate must match arm receipt; authorization spans `_start_service` | Zero service starts | Launch authorization receipt |
| Source Golden fixture | Explicit external authority and `runtime_required=True` | Fails closed | Golden evidence artifacts |

Audit found no additional production constructors, activation callers, or `_start_service` callers.

### Verification

- Expanded tests: **404 passed**
- Focused authority tests: **19 passed**
- Ruff: **All checks passed**
- Focused Ty: **All checks passed**
- Manual activation help exposes both required authority arguments.
- Manual missing-argument invocation exited **2** before touching paths.
- Revoked authority tests confirm zero service starts and zero provider calls.
- The real Telegram callback Golden Path now executes with runtime authority and verifies the sealed candidate snapshot.

No live service, Telegram API, profile, candidate sealing, evidence history, commit, or push was performed.


I read this as a read-only evidence return - I’ll report the exact files, commands, outputs, and test names already recorded without running or editing anything.

## Changed files for production wiring

Production code:

```text
gateway/platforms/task26_runtime_authority.py
gateway/platforms/telegram.py
gateway/platforms/dualcoach_admin.py
gateway/platforms/dualcoach_tasks21_25_controller.py
```

Associated tests:

```text
tests/gateway/test_task26_runtime_authority.py
tests/gateway/test_dualcoach_activation_cutover.py
tests/gateway/test_dualcoach_tasks21_25_controller.py
tests/gateway/test_nutrition_coaching.py
```

## Expanded test command

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_runtime_authority.py tests/gateway/test_task26_candidate_derivation.py tests/gateway/test_task26_final_authority.py tests/gateway/test_task26_final_state.py tests/gateway/test_task26_frozen_bootstrap.py tests/gateway/test_task26_ty_surface_gate.py tests/gateway/test_task26_ty_wheel_builder.py tests/gateway/test_source_golden_path_verifier.py tests/gateway/test_installed_golden_path_provenance.py tests/gateway/test_commit_observer.py tests/gateway/test_dualcoach_activation_cutover.py tests/gateway/test_dualcoach_tasks21_25_controller.py tests/gateway/test_nutrition_coaching.py tests/gateway/test_task7_generation_hardening.py --maxfail=1
```

Captured result:

```text
........................................................................ [ 17%]
........................................................................ [ 35%]
........................................................................ [ 53%]
........................................................................ [ 71%]
........................................................................ [ 89%]
............................................                             [100%]
404 passed in 18.59s
```

## Focused authority test command

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m pytest -q tests/gateway/test_task26_runtime_authority.py tests/gateway/test_dualcoach_activation_cutover.py tests/gateway/test_dualcoach_tasks21_25_controller.py tests/gateway/test_nutrition_coaching.py -k 'nutrition_production_startup or provider_auth_preflight_recovers or task26_revok or runtime_authority or activation_requires_explicit or revoked_runtime_authority' --maxfail=1
```

Captured result:

```text
...................                                                      [100%]
19 passed, 195 deselected in 0.90s
```

## Ruff command

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/ruff check gateway/platforms/task26_runtime_authority.py gateway/platforms/telegram.py gateway/platforms/dualcoach_admin.py gateway/platforms/dualcoach_tasks21_25_controller.py gateway/platforms/dualcoach_activation_cutover.py gateway/platforms/nutrition_coaching.py gateway/platforms/task26_candidate_derivation.py gateway/platforms/task26_final_state.py scripts/source_golden_path.py scripts/verify_source_golden_path.py tests/gateway/test_task26_runtime_authority.py tests/gateway/test_dualcoach_activation_cutover.py tests/gateway/test_dualcoach_tasks21_25_controller.py tests/gateway/test_nutrition_coaching.py
```

Captured result:

```text
All checks passed!
```

## Ty command

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/ty check gateway/platforms/task26_runtime_authority.py gateway/platforms/dualcoach_tasks21_25_controller.py gateway/platforms/dualcoach_admin.py gateway/platforms/dualcoach_activation_cutover.py gateway/platforms/task26_candidate_derivation.py gateway/platforms/task26_final_state.py scripts/task26_build_ty_executable_wheel.py scripts/task26_hermetic_ty_runner.py scripts/task26_ty_surface_gate.py
```

Captured result:

```text
All checks passed!
```

## Manual CLI checks

Help command:

```bash
cd /home/cube/projects/richard/hermes-agent && .venv/bin/python -m gateway.platforms.dualcoach_admin customer activate --help | rg -- '--task26-authority-pin|--task26-candidate-digest'
```

Captured output:

```text
                                         --task26-authority-pin
                                         --task26-candidate-digest
  --task26-authority-pin TASK26_AUTHORITY_PIN
  --task26-candidate-digest TASK26_CANDIDATE_DIGEST
```

Missing-argument command:

```bash
cd /home/cube/projects/richard/hermes-agent && set +e; .venv/bin/python -m gateway.platforms.dualcoach_admin customer activate --profile-root /tmp/nonexistent --data-root /tmp/nonexistent --customer-id x --checklist-evidence /tmp/no --staff-membership-evidence /tmp/no --deployment-receipt /tmp/no --bootstrap-session x --expected-generation 1 >/tmp/task26-cli-bad.out 2>/tmp/task26-cli-bad.err; code=$?; printf 'exit=%s\n' "$code"; rg -- '--task26-authority-pin|--task26-candidate-digest' /tmp/task26-cli-bad.err; rm -f /tmp/task26-cli-bad.out /tmp/task26-cli-bad.err; test "$code" -eq 2
```

Captured output and exit:

```text
exit=2
                                         --task26-authority-pin
                                         --task26-candidate-digest
dualcoach_admin customer activate: error: the following arguments are required: --task26-authority-pin, --task26-candidate-digest
```

## Exact proving tests

| Requirement | Test |
|---|---|
| Telegram construction fails without authority configuration | `tests/gateway/test_nutrition_coaching.py::test_nutrition_production_startup_requires_external_task26_credentials` |
| Real Telegram callback executes under external authority and seals its candidate snapshot | `tests/gateway/test_nutrition_coaching.py::test_dualcoach_golden_path` |
| Revocation waits for an in-flight provider transport lock and blocks the next send | `tests/gateway/test_nutrition_coaching.py::test_runtime_revocation_waits_for_in_flight_transport_and_blocks_next_send` |
| Revoked authority causes zero service starts | `tests/gateway/test_dualcoach_tasks21_25_controller.py::test_revoked_runtime_authority_causes_zero_service_starts` |
| Missing activation authority arguments cause zero registry/session/audit mutation | `tests/gateway/test_dualcoach_activation_cutover.py::test_cli_activation_requires_explicit_task26_authority_inputs` |


I read this as implementing two production-authority blockers test-first - I’ll audit capability issuance and every Telegram startup path, add failing boundary tests, then make the smallest shared-path changes and verify without sealing or live actions.


The audit found both bypasses: the controller currently has its own ledger rewrite, and Telegram’s authority check is still lazy behind `_get_nutrition_coaching` after network startup has begun. I’m locking RED tests to those exact boundaries before replacing either path.