I read this as a read-only root-cause investigation of H2 - I’ll trace the digest inputs, compare live and Golden Path values, and identify the reachable rejection site without modifying either tree or profile.


The digest path is now isolated: the live customer and disposable Golden Path both take the same “missing epoch” fallback. I’m tracing the separate candidate capability pins and the exact validation branches to determine whether their expected per-run differences can reach finalization rejection.


I read this as a read-only H2 classification - I traced live and Golden Path epoch/capability inputs through the rejection path.

## Verdict: H2 refuted

### Feature epoch

Implementation:

- `/home/cube/projects/richard/.worktrees/nutricoach-v111-impl/gateway/platforms/telegram_nutrition_onboarding_authority.py:32`
- Installed live copy is byte-identical, SHA-256:
  `7a670aea26f55e23760308e34848aef7acfdd7e53fc9d2ebd73b43878456a4d2`

It reads only:

`<profile>/data/customers/<customer_key>/nutrition-plans/feature-epoch.json`

Live path:

`/home/cube/.hermes/profiles/dualcoachtest/data/customers/pilot_20260820_01/nutrition-plans/feature-epoch.json`

This path and its parent `nutrition-plans/` are absent. Therefore the implementation hashes the canonical fallback:

```json
{"activation":false,"analytics_shadow":false,"delivery":false,"epoch":0,"operator_candidates":false}
```

Result:

`2092cad6375cbbf617b88668a3103ad7fb07d854c20bdefa1b3b074b0ee135ac`

Golden Path fixture creation at:

`/home/cube/projects/richard/.worktrees/nutricoach-v111-impl/scripts/dualcoach_v111_disposable_fixture.py`

also creates no `disposable_001/nutrition-plans/feature-epoch.json`. It therefore produces the identical fallback digest:

`2092cad6375cbbf617b88668a3103ad7fb07d854c20bdefa1b3b074b0ee135ac`

### Capability material

Live candidate is consistently:

`9dcf52724fcc8fb9abc7d3789d765e1ec7cf54d5573ca6e1cb38be5d1f41a189`

Confirmed in:

- `/home/cube/.hermes/profiles/dualcoachtest/config.yaml:684`
- `/home/cube/.hermes/profiles/dualcoachtest/preexecution-product-binding.json`
- `/run/user/1000/credentials/hermes-gateway-dualcoachtest.service/owner-risk-acceptance.json`
- `/home/cube/.hermes/profiles/dualcoachtest/data/customers/pilot_20260820_01/nutrition-onboarding/transient/workflow.json`

The credential SHA is exactly the configured value:

`e501ba143fc22e978cae0ee99faddd43a8b5809ca714533b31d0ef4fd63b456a`

Its authorization seal is valid:

`9a69836b29be20eabb1ddb831aa97c693a0a053207552b11367daf8d51126fec`

The persisted owner-risk receipt is internally valid:

- acceptance identity stored/computed:
  `3998f193eb90b8342435d57ad2cb700906058b55916c053691b7dce4bfe2795f`
- receipt digest stored/computed:
  `4700c0dfc7f85b04a25d7f3f713b7749bc80eb004bf68998ba1e8977136963ed`

Golden Path candidate:

`66a770590a50bcbdb30ecdb646e1a795e0c828fea756577034e2ad57323c0410`

from:

- `.omo/evidence/v1.2.0-operator-notification-hotfix/golden-path-canonical/candidate-binding.json`
- `.omo/evidence/v1.2.0-operator-notification-hotfix/capability-receipt.json`

That per-candidate difference is expected. Golden Path does not provide an owner-risk capability fixture, and finalization does not compare the live candidate epoch against Golden Path. It only validates that the persisted epoch is lowercase 64-hex and that the receipt’s binding and digest are internally consistent; live passes those checks.

### Reachable rejection path

Owner approval reaches:

1. `telegram_nutrition_onboarding_runtime_callback.py:528`
2. `telegram_nutrition_onboarding_runtime.py:270-281`
3. `nutrition_onboarding_finalization.py`

A finalization `ValueError` is caught at:

`gateway/platforms/telegram_nutrition_onboarding_runtime_callback.py:544-548`

and reported as `transition_rejected`.

The downstream generic exception site is:

`dualcoach/profile/checkin_cli/nutrition_onboarding_finalization.py:292`

```python
raise ValueError(f"readiness finalization failed: {','.join(audit.reason_codes)}")
```

Neither feature epoch nor candidate capability is part of that readiness audit. The feature digest is only format-checked and written into the receipt. Thus the live/Golden capability difference cannot cause this finalization rejection. No files were modified and no Git commands were run.