# Dual-coach model rerun — Revision 3

## Summary
This is a delta-minimal revision of Revision 2 (`63f00dad909cba9f25e1094fa2d204a7b8407e42d59374dda080d9c2896a7be4`). All Revision 2 content is preserved unchanged except the explicit `dual-coach-risk-v1` custody and verification contract below. It closes the pass-2 Architect P2 without changing the compatibility, ownership, confirmation, reminder, host, activation, or delivery contracts.

## Intent Diff
- Preserve every Revision 2 intent and constraint.
- Pin `dual-coach-risk-v1` to one private, per-customer authoritative artifact; only the refreshed canonical owner may approve it through the typed authority boundary; evaluation and activation consume only the verifier-returned, digest-matched policy.

## Decision Drivers
1. Revision 2’s fixed six-band table, integer sum, inclusive threshold, overrides, missing-evidence hold, candidate identity, and no-auto-delivery boundary remain the executable behavioral policy.
2. The existing registered customer runtime already resolves one private authoritative root as `data/customers/<customer_key>/nutrition-plans`, and the canonical owner is a separate refreshed full triple from Topic-59 review ingress.
3. A policy evaluator must not become its own approval authority or select an arbitrary artifact path.

## Options
- **Chosen — customer-private, owner-approved policy document.** The sole authoritative risk-policy artifact is `<CustomerRuntime.nutrition_plans_root>/dual-coach-risk-policy.json`, i.e. `<profile_root>/data/customers/<customer_key>/nutrition-plans/dual-coach-risk-policy.json`. It is a regular non-symlink private file; copies, package defaults, gateway configuration, event payloads, cards, and sessions are non-authoritative.
- **Rejected — reuse the general `policy.json` or permit a fallback/default.** That conflates the established nutrition-policy artifact with the new risk evaluator and permits unnoticed drift.
- **Rejected — evaluator- or review-ingress self-approval.** Topic-59 authenticates ingress only; it is not the canonical owner or risk-policy authority.

## In scope / out of scope
**In:** only the durable artifact, schema, owner approval, verifier, digest gate, and fail-closed behavior for `dual-coach-risk-v1`.

**Out:** every item already out of scope in Revision 2, including policy-table changes, history work, lifecycle redesign, production activation, autonomous medical advice, AI/customer auto-send, and delivery retries.

## File-level changes
- `checkin_cli/adaptive_nutrition.py`: add the sealed `DualCoachRiskPolicyV1` schema/parser and the sole `load_verified_dual_coach_risk_policy(runtime)` verifier. It resolves exactly `runtime.nutrition_plans_root / "dual-coach-risk-policy.json"`; no caller supplies a path.
- `checkin_cli/customer_admin.py`: add the typed, `profile_authority_lock`-guarded owner approval/write boundary for that artifact; direct JSON/registry editing remains prohibited.
- `checkin_cli/adaptive_nutrition.py` and its focused tests: invoke the verifier before risk evaluation and again immediately before any candidate release, adaptive activation, or delivery-adjacent transition that relies on its result.
- `tests/test_adaptive_nutrition.py`, `tests/test_customer_admin.py`, and gateway `tests/gateway/test_adaptive_nutrition.py`: add only custody/digest/fail-closed cases; retain all Revision 2 test scope unchanged.

## Sequencing and dependencies
1. Preserve Revision 2 sequencing steps 1–3 and 5–6 unchanged.
2. Replace only the `dual-coach-risk-v1` artifact clause in Revision 2 step 4 with this custody gate before its existing table/formula evaluation: the document schema is exactly `dual_coach_risk_policy_v1` with required keys `schema_version`, `policy_id`, `version`, `policy`, `policy_digest`, `document_digest`, `approved`, `approved_by`, `approved_at_kst`, `customer_key`, `owner_digest`, `registry_digest`, `activation_receipt_digest`, and `authority_digest`; `policy_id` is exactly `dual-coach-risk-v1`; `policy` contains the already-fixed six normalization bands, integer-sum threshold `4`, hard overrides, and missing-evidence reason. `policy_digest` is SHA-256 of canonical JSON of `policy`; `document_digest` is SHA-256 of canonical JSON of the complete document excluding `document_digest`.
3. The authoritative owner and sole approving authority is the refreshed `CustomerRegistry.owner` full `(user_id, chat_id, topic_id)` triple, not the Topic-59 review triple unless they are independently identical. The typed approval boundary requires `approved=true`, `approved_by` exactly equal to that full owner triple, a KST approval timestamp, and matching current customer/owner/registry/activation/authority pins; it writes/fsyncs the verified private artifact under the existing authority lock. The evaluator, gateway, scheduler, and candidate producer cannot approve, substitute, or relocate it.
4. `load_verified_dual_coach_risk_policy(runtime)` is the only verifier and returns an immutable policy only after checking private regular-file/no-symlink location and mode, exact key set/schema/policy ID, typed table values, canonical `policy_digest` and `document_digest`, owner identity, approval flag/time, customer binding, and freshly loaded registry/activation/authority pin equality. It uses constant-time digest comparison. The risk evaluator calls it before normalizing any check-in; every activation/delivery-adjacent transition re-verifies the exact policy version/digest immediately before append/reservation. Candidate and lifecycle rows persist precisely the verifier-returned version and `policy_digest`; a stored value must equal the fresh verifier result.
5. Missing, malformed, disabled, ambiguous, unapproved, unauthorized, stale-pinned, relocated, or digest-mismatched artifact is terminal `risk_evidence_unavailable`: perform no normal score evaluation, adaptive activation, delivery, provider call, or fallback/default selection. Create exactly one held review candidate using the existing Revision 2 candidate preimage with fixed policy version/digest sentinels `unavailable`; this is the sole permitted missing-policy representation and remains deduped. A mismatch found after a prior candidate/activation pin is a stop/reconciliation-required condition, never recency resolution or automatic release.

## Acceptance criteria
1. All eight Revision 2 acceptance criteria remain unchanged.
2. The only risk-policy source accepted by evaluation/activation is the private per-customer `nutrition-plans/dual-coach-risk-policy.json` document matching `dual_coach_risk_policy_v1` and `dual-coach-risk-v1`.
3. Approval is accepted only from the refreshed canonical owner full triple through the typed locked boundary; Topic-59 review identity, evaluator, gateway, scheduler, event/card/session data, and a copied/default artifact cannot self-approve or override it.
4. Before evaluation and immediately before dependent activation/delivery transitions, the sole verifier must match canonical `policy_digest`, `document_digest`, owner approval, and live customer/registry/activation/authority pins. Any failure creates only the held, deduped `risk_evidence_unavailable` candidate and blocks activation, delivery, and provider calls.

## Verification
No commands, tests, formatters, implementation, fixtures, migration, activation, or provider actions are run in this planning pass. After implementation, retain every Revision 2 command and add focused tests for valid owner-approved policy; wrong path/symlink/mode; key/schema/policy-ID/table failure; altered policy/document digest; wrong review-versus-owner approver; stale owner/registry/activation/authority pins before evaluation and before activation; unavailable sentinel dedupe; and zero activation/delivery/provider calls on each failure.

## Escalation/Risk Gate
Retain every Revision 2 gate. Stop before evaluation, fixture generation, activation, host enablement, or rollout when the sole verifier cannot prove the exact authoritative artifact, canonical owner approval, both digests, and current pins. Do not repair, default, copy, or accept a policy artifact; escalate a verifier/authority contradiction to architecture.

## Verification Plan
| Layer | Proof |
|---|---|
| Revision 2 layers | Run every unchanged Revision 2 history, ownership, capability, risk, reminder, and gateway proof. |
| Risk custody | Valid owner-approved document succeeds; every path/schema/owner/pin/digest mismatch fails closed before evaluation and again before dependent activation/delivery; unavailable sentinel is one held candidate and provider count stays zero. |

## Risks and mitigations
- **Risk policy drift or self-approval.** One private runtime path, exact schema, canonical owner-only typed approval, sealed verifier, dual canonical digests, live-pin equality, and pre-evaluation/pre-activation gates prevent substitution.
- **Policy verification failure suppresses a needed automated action.** The bounded held `risk_evidence_unavailable` review preserves operator visibility while blocking unsafe activation/delivery; no fallback is permitted.
- All remaining Revision 2 risks and mitigations are unchanged.
