## Summary
Revision 17 (`.gjc/_session-019f8455-334a-7000-99ca-318dfd0e06b1/plans/ralplan/019f8455-334a-7000-99ca-318dfd0e06b1/stage-17-revision.md`, SHA-256 `cad4b9a7b94798e6961cbcfe6a0a60fb0a29fc455f51899b9b7829b96b728210`) corrects the actual primary check-in wire names, introduces an ordered-cutover direction, and removes the nonexistent Telegram absence lookup. It remains non-executable: five HIGH contracts still permit a safety bypass, unrecoverable/colliding journal state, non-verifiable recovery, impossible meal targets, or a false delivered audit.

## Claims
- Stage 17 maps the actual normal check-in event wires `morning_checkin`, `nutrition_checkin`, `workout_record`, and `trainer_session_record`; these match `checkin_cli/models.py:30-51` and wizard writes at `checkin_cli/wizard.py:850-860`.
- The current generic EventStore emits `safety_flag` for chest-pain input (`checkin_cli/store.py:375-382`), while that known wire is absent from Stage 17’s adapter table (`stage-17-revision.md:9-17`).
- The legacy Event envelope has `supersedes`, but no customer/session/observation-day fields (`checkin_cli/models.py:753-779`); Revision 15 intentionally keeps day metadata external.
- The live strict topic boundary makes one `send_message` call and the customer transport produces only a message-ID receipt (`gateway/platforms/telegram.py:3276-3283`; `gateway/platforms/nutrition_coaching.py:2295-2315`).
- This is a planning-only review. No product files were changed and no tests were run, per assignment.

## Analysis
### Spec compliance
The revision correctly replaces Stage 16’s wrong normal check-in wire names and correctly removes Telegram’s unsupported idempotency-token absence lookup. Its signed calorie decision table has the correct direction for fat-loss, gain, and maintenance, and its no-replacement posture after a provider invocation is appropriately conservative.

It does not complete the requested exact contracts. First, omitting the current `safety_flag` root leaves an unsafe event outside the stated safety union. Second, the proposed strict JSONL journals cannot transition from prepared to committed/abandoned under their own `intent_id`/`epoch` conflict rule; the required canonical sequence sidecar is also not a defined durable record. Third, the source preimage asks persisted Event bytes to contain external intent fields. Fourth, independent largest-remainder allocation of calories and each macro can yield incompatible per-slot energy/macro targets. Finally, manual Telegram reconciliation is not bound to the attempted delivery.

### Antithesis and constructive synthesis
Keeping journal rows immutable prevents silent mutation and is preferable to overwriting state. That benefit requires explicit append-only transition records: a prepare row plus a distinct commit/abandon row with a monotonic transition identity and predecessor validation. A safe delivery reconciliation is similarly conservative: either validate a durable evidence tuple that binds the actual Telegram message to the exact unknown attempt or leave it unknown forever.

For meals, independent targets are useful for a compiler objective but cannot all be hard equalities without a deterministic energy source of truth. Derive each slot’s calorie target from allocated macros, or define a bounded explicit calorie slack/reconciliation pass before compilation; then define percentage deviation and target-zero behavior exactly.

## Root Cause
Stage 17 introduces new durability and allocation records but leaves their persisted identities and invariants incomplete or internally contradictory. That prevents independent recovery/rebuild from proving the same authority result.

## Findings
1. **HIGH (P1) — `stage-17-revision.md:9-17`: Map `safety_flag` into the safety hard gate.** `EventType.SAFETY_FLAG` is a current known root emitted for chest pain, not an unknown event. Define it as safety-only, union normalized signals/reasons, and block every candidate; fixture it with every EventType mapping.
2. **HIGH (P1) — `stage-17-revision.md:19-28`: Make journal state transitions append-only and recoverable.** A committed row differs from its prepared row and is prohibited by the stated dedupe/conflict rule. The same issue applies to config per-customer state; `canonical-sequence.jsonl` and frozen-prefix hashing lack row/byte contracts. Define immutable transition unions, keys, legal predecessor states, replay semantics, and a sequence row binding intent, root ID/digest, and sequence.
3. **HIGH (P1) — `stage-17-revision.md:23-26`: Define a verifiable root-intent preimage.** Canonical Event bytes cannot include the external customer/session/day intent fields stated in the digest. Define a separate canonical intent-preimage object, its relation to actual root bytes/ID, and exact recovery comparisons.
4. **HIGH (P1) — `stage-17-revision.md:43-44`: Reconcile meal-slot energy with independently rounded macro shares.** Largest remainder per target preserves daily totals but not per-slot `kcal = 4C + 4P + 9F`, so a tight compiler can be impossible. Choose a slot-energy authority/reconciliation rule and define tolerance as an exact percentage formula including target-zero behavior; pin divergent-remainder fixtures.
5. **HIGH (P1) — `stage-17-revision.md:35-38`: Require evidence that a reconciled Telegram receipt matches the delivery.** A human-found receipt needs immutable binding to canonical chat/topic, provider message ID, rendering digest, delivery/revision/attempt IDs before it can append delivered/sent audit; otherwise it remains unknown permanently.

## Recommendations
1. Amend the root table to map `safety_flag` before Gate A.
2. Replace journal `state` mutation with explicit immutable transition records, and specify the canonical sequence/frozen-prefix formats and recovery matrix.
3. Define the intent preimage separately from the legacy Event envelope and bind it cryptographically to the appended root.
4. Add a meal-slot energy reconciliation invariant and target-zero tolerance rule before compiler implementation.
5. Limit Telegram reconciliation to a verifiable evidence tuple; prohibit any transition from unknown on weaker evidence.

## Architectural Status
BLOCK

## Code Review Recommendation
REQUEST CHANGES

## Tradeoffs
- **Immutable prepare/commit transition rows — Prefer:** deterministic recovery and auditability; requires a small explicit state machine.
- **Single mutable journal row — Reject:** conflicts with append-only JSONL and cannot preserve crash evidence.
- **Independent meal calorie and macro hard targets — Reject:** can violate per-slot energy after rounding.
- **Macro-derived slot calories or explicit deterministic slack — Acceptable:** makes feasibility and tolerance auditable.
- **Human receipt without binding proof — Reject:** can falsely audit an unrelated Telegram message as delivered.
- **Bound external receipt evidence — Prefer:** preserves conservative no-resend behavior.
