<analysis>
**Literal Request**: Diagnose a TypeScript (v14) type failure in `/home/cube/projects/richard/hermes-agent/gateway/platforms/nutrition_coaching.py`, separate failures caused by new capability identity changes from pre-existing/dirty monolith diagnostics, compare against v13 sealed evidence, identify changed symbols/call sites, both by root cause with file/line evidence, and recommend a test/type gate.
**Actual Need**: A precise, actionable triage of the type errors: which are introduced by the new capability identity refactor vs. which are pre-existing monolith debt, so the team can decide on minimal encapsulation without suppressing errors, and can verify no regression.
**Success Looks Like**: Root-cause-grouped counts with exact file/line evidence, a clear flag on each group (new-vs-preexisting), smallest-preservation recommendation, and a concrete test/type gate command.
</analysis>

Wait - the file is nutrition_coaching.py. But the task says "v14 Ty fail" - that's suspicious. Let me check whether these are Python or TypeScript files. The extension `.py` suggests Python, but "Ty fail" might imply TypeScript. Let me explore first.


The bash broker only supports gh/curl, so I'll use grep/read for analysis. Let me gather the ty.log structure and v13 manifest in parallel.


The ty.log spans the whole monolith (lines 95-21613). Now I need to isolate the capability-identity code. Let me locate the capability classes and store in both current source and the v13 sealed source


The v13 seal contains only the 4 `task26_*` modules under `gateway/platforms/`, not `nutrition_coaching.py`. That's a key signal. Let me inspect what v13 sealed and how earlier type gates handled the monolith.


The v13 seal only includes the `checkin_cli` wheels/4 task26 modules — `nutrition_coaching.py` was not part of the sealed surface. So the v14 gate is the first to type-check the monolith. Let me map the ty.log error rules and the capability store structure in the current file


Let me map the capability-identity surface precisely and inspect the ty.log errors at those call sites


The capability-identity surface is clear: `DeliveryLaunchAuthorization`, `DraftDeliveryCapability`, `DeliveryDispatchClaim` (lines 591-636), plus `validate_delivery_transport` (2642), `claim_delivery_transport` (2805), `record_customer_surface_receipt` (2831), `issue_delivery_capability` (6436). Let me find how the `ty` gate is configured and which tests cover this surface


Now let me get the summary from the tail of ty.log and confirm the capability-surface diagnostic set precisely


Let me confirm the rules at the capability-store errors (6908/6909) and the schedule-reference errors (9646/9647), and tally the diagnostic clusters from the full `--> ` map


Let me precisely enumerate the capability-surface line diagnostics in ty.log to finalize the count


I have everything needed. Here is the read-only diagnosis.

<analysis>

**Scope note and evidence chain.** The v13→v14 comparison can't be a source diff — the v13 seal (`source-provenance.json`) covers only the four `task26_*` modules and the `checkin_cli` wheel; `nutrition_coaching.py` was never a sealed type surface. `static.log` in v13 says only "All checks passed!", i.e. v13's gate never scanned the monolith. So v14 is the first gate to type-check the whole 21k-line file, and all 527 diagnostics surfaced together. I therefore classified by (a) the gate's own FAIL-CLOSED reason ("unresolved and invalid capability payload/store types") and (b) symbol ownership of each diagnostic in ty.log.

**Capability-identity surface.** The v14 addition is a small, well-localized set: `DeliveryLaunchAuthorization` (591), `DraftDeliveryCapability` (622), `DeliveryDispatchClaim` (632), plus `validate_delivery_transport` (2642), `claim_delivery_transport` (2805), `record_customer_surface_receipt` (2831), `issue_delivery_capability` (6436), and the ledger reads in `_prepare_delivery_locked` (6906). Everything here carries the exact `task26`-style identity fields (`candidate_digest` … `profile_authorization_digest`, `hermes_wheel_sha256`, `profile_wheel_sha256`, …) and the `draft-delivery-capability-v1` dict schema the bindings-consume code validates.

**What actually emits errors:** only two functions in that surface produce ty diagnostics, and both do so for the *same* root cause — reading the persistable `delivery_capability` / `approved_card` payload off a ledger row typed as `object` without a narrowing helper:

- `validate_delivery_transport` — **32**: 2718:57 (`not-subscriptable`, `capability["expires_at"]`), 2743-2749+2753 (7 × `invalid-argument-type`, `capability.get(...)`), 2754/2759-2768 (11 lines × 2 = 22, `capability["bindings"].get(...)` = `invalid-argument-type` + `unresolved-attribute`), 2771 (2).
- `_prepare_delivery_locked` — **2**: 6908:31, 6909:31 (`invalid-argument-type`, `capability.get("schema"/"status")`).

The three capability classes, `issue_delivery_capability`, `claim_delivery_transport`, and `record_customer_surface_receipt` emit **zero** diagnostics — `record_customer_surface_receipt` already uses the correct pattern (`cast(dict[str, object], …)` + explicit `None` guards at 2854-2866 and 2869-2871). That is direct proof the fix pattern works on byte-identical payload reads.

Two adjacent authorizer errors (9646:13, 9647:65) are schedule-confirmation reference reads over a fallback-imported `checkin_cli` type; they share root cause (i) below, not the delivery payload surface.

**Everything else is pre-existing monolith debt (≈491).** Two dominant root causes:

1. **Modular-feature fallback shadowing** (defs 95-167, `AdaptiveEventStore = None` …): ~44 direct errors, plus cascading `unresolved-attribute`/`invalid-argument-type` at every call site that touches a fallback-imported symbol (3365, 3646, 4943, 6530, 6656, 9646-9647, …).
2. **Untyped ledger/dict access** (`.get()`/`[]` on `object` without narrowing): the remaining bulk across 3338 → 21613 (e.g. 3338 `set_customer_ai_consent`, terminal error 21613 passing `object` as `customer_transport` to `create_production_operator_console_server`).

Both predate the capability-identity change and would be present regardless of it.

**Counts by root cause (sum = 527, matches "Found 527 diagnostics"):**

| Root cause | Count | Lines |
|---|---|---|
| New capability-delivery payload reads (untyped `object` access) | 34 | 2718, 2743-2771; 6908-6909 |
| Schedule-reference authorizer (fallback import) | 2 | 9646-9647 |
| Pre-existing: import-fallback shadowing | ~44 direct + cascade | 95-167 (+3365,3646,4943,6530,6656,10092) |
| Pre-existing: untyped ledger/dict access | ~447 | 3338 → 21613 |

**Smallest fix that preserves behavior and doesn't weaken the gate.** The 34 are caused solely by missing structured narrowing on `delivery`/`approved_card`/`capability` in the boolean guard chain. Apply the exact helper already proven in `record_customer_surface_receipt` (`cast(dict[str, object], …)` + `None` guards distributed through the existing `or …` chain, plus a `capability["bindings"]` narrow). The dict schema and bindings contract stay byte-identical, so the 122 passing tests and ledger receipts are unchanged. For a more durable fix aligned with v13's design, extract the typed identity (`DeliveryLaunchAuthorization`, `DraftDeliveryCapability`, `DeliveryDispatchClaim` + pure issue/validate helpers) into a focused, type-clean module authored like the four `task26_*` modules, and have the monolith import from it.

The honest gate conclusion: whole-file scanning is what produced 491 unrelated diagnostics. The correct typed gate for this change is **scoped to the capability surface** (focused module + the four methods) at 0 diagnostics, with 491 recorded as a pre-existing monolith baseline — not achieved via `# type: ignore` or excludes, which would violate the fail-closed policy. See the recommended verification below.

</analysis>

<results>
<files>
- /home/cube/projects/richard/hermes-agent/gateway/platforms/nutrition_coaching.py (monolith; capability classes 591-636; validate 2642-2803; claim 2805-2830; record 2831-2929; issue 6436-6507; prepare 6906-6914)
- /home/cube/projects/richard/hermes-agent/pyproject.toml (`[tool.ty]` python-version 3.13; `ty==0.0.21`; only `unknown-argument=warn`, `redundant-cast=ignore`)
- /home/cube/projects/richard/traning coach/.omo/evidence/task26/task26-capability-record-bootstrap-fail-closed-st_01a01574-v14/FAIL-CLOSED.json
- /home/cube/projects/richard/traning coach/.omo/evidence/task26/task26-capability-record-bootstrap-fail-closed-st_01a01574-v14/receipts/ty.log ("Found 527 diagnostics"; capability lines 675-1131, 1251, 1275)
- /home/cube/projects/richard/traning coach/.omo/evidence/task26/task26-capability-record-bootstrap-fail-closed-st_01a01574-v14/receipts/lead-tests.log (122 passed)
- /home/cube/projects/richard/traning coach/.omo/evidence/task26/task26-full-derivation-installed-st_01a01574-v13/receipts/static.log (v13 gate = focused modules only)
- /home/cube/projects/richard/traning coach/.omo/evidence/task26/task26-full-derivation-installed-st_01a01574-v13/source-golden-bundle/source-provenance.json (v13 seal excludes nutrition_coaching.py)
- /home/cube/projects/richard/hermes-agent/tests/gateway/test_nutrition_coaching.py (capability surface tests, incl. 2155, 6432-6511, 6667, 6740, 7119)
- /home/cube/projects/richard/hermes-agent/tests/gateway/test_dualcoach_tasks21_25_controller.py:372 (test_issue_delivery_capability_derives_state_and_never_invokes_provider)
</files>

<answer>
The v14 gate is the first to type-check the whole monolith; `ty` reports "Found 527 diagnostics", and because v13 never sealed `nutrition_coaching.py`, none of these can be diffed against a sealed v13 baseline. Classifying by rule and symbol, the **new capability-identity change introduces only 34 diagnostics**, confined to two functions that read the `delivery_capability`/`approved_card` payloads off an `object`-typed ledger row: `validate_delivery_transport` (2718-2771, 32 errors) and `_prepare_delivery_locked` (6908-6909, 2 errors). The capability classes (591-636), `issue_delivery_capability`, `claim_delivery_transport`, and `record_customer_surface_receipt` are already type-clean — because `record_customer_surface_receipt` uses the `cast(dict[str, object], …)` + `is None` narrowing helper at 2854-2871. The remaining ~491 are pre-existing monolith debt (import-fallback `= None` shadowing from 95-167 plus untyped ledger/dict access spanning 3338→21613) present regardless of this change; 2 more (9646/9647) are a schedule-reference read over a fallback-imported type.

Smallest no-regression fix: reuse the exact narrowing helper already in `record_customer_surface_receipt` to narrow `capability`, `approved_card`, and `capability["bindings"]` inside `validate_delivery_transport`'s `or`-chain and the `_prepare_delivery_locked` guards. This deletes all 34 diagnostics with no behavior change (dict schema and bindings contract are untouched; the 122 passing tests stay green). A more durable alignment with v13's design is to extract the typed capability identity into a focused, type-clean module authored like the four `task26_*` modules and imported by the monolith. For the gate: scope the Ty check to the capability surface (focused module + the four capability methods) at 0 diagnostics and record the 491 as a pre-existing baseline; do not use `# type: ignore` or excludes, which would violate the fail-closed policy.
</answer>

<next_steps>
1. Behavioral gate — the required verification for any of the above fixes: run `pytest` on the capability tests (`tests/gateway/test_nutrition_coaching.py` validate/issue cases at 2155, 6432-6511, 6667, 6740, 7119 and `test_dualcoach_tasks21_25_controller.py::test_issue_delivery_capability_derives_state_and_never_invokes_provider`) and confirm the full suite stays "122 passed". Add one test that round-trips the identity: `issue_delivery_capability` → persisted `delivery_capability` row → re-read → `validate_delivery_transport` succeeds, guarding the dict contract against the type refactor.
2. Type gate — scoped run of `ty` over the extracted capability module (target 0 diagnostics), matching `[tool.ty]` python-version 3.13; keep the whole-file 491 as a documented pre-existing baseline rather than scanning the monolith wholesale.
3. Minimal edit (if not extracting) — apply the `cast(dict[str, object], …)` + `None`-guard narrowing to `validate_delivery_transport` (2718-2771) and `_prepare_delivery_locked` (6908-6909), mirroring 2854-2871, then re-run the type gate and the behavioral gate.
</next_steps>
</results>