# Architect Stage 16 Review

## Summary
Revision 16 (`.gjc/_session-019f8455-334a-7000-99ca-318dfd0e06b1/plans/ralplan/019f8455-334a-7000-99ca-318dfd0e06b1/stage-16-revision.md`, SHA-256 `c7523fbc899907721197b6d4410e3ae5648c86748d8413feed567e2599e197ce`) preserves the sound shadow-only and separate-stream direction from normative Revisions 13–15, but it does not close the pass-15 source/delivery blockers concretely. Gate A must remain blocked until the adapter names real event types, source-day cutover is orderable, and Telegram certainty is constrained to provider capabilities.

## Claims
- Revision 16 explicitly makes Revisions 13–15 normative except where superseded, keeps Gate A shadow-only, and identifies the reviewed path above (`stage-16-revision.md:1-4`).
- The pass-15 Architect blocker was an unmapped post-cutover root silently deriving its day after a crash (`stage-15-architect.md`, SHA `761099d8ad358ee4d667e2f8053f3eddb74ab525dc62ea3e0088a83dcc9e71aa`). Revision 16's intent journal is an acceptable direction only with a reliable post-cutover classifier.
- Actual canonical enum values are `morning_checkin`, `nutrition_checkin`, `workout_record`, and `trainer_session_record`, not the names in Revision 16 (`contracts/checkin-event.schema.json:20-48`; `checkin_cli/models.py:30-51`).
- Current canonical wizard IDs are digest-derived and the Event model has no append-sequence field (`checkin_cli/wizard.py:1013-1039`; `checkin_cli/models.py:753-766`).
- Telegram strict delivery currently has only the one-call `_send_message_strict_topic` boundary (`gateway/platforms/telegram.py:3276-3283`); no Telegram message/idempotency-token absence lookup exists in the inspected gateway.

## Analysis
### Spec compliance
The new intent-first journal and mapping recovery address the failure mode found at pass 15 in principle; the atomic overlay replacement, authority mirrors, typed config fanout, exact numeric rules, and pre-/post-invocation transport split are materially stronger. However, the claimed exact source adapter cannot project the actual canonical roots, and its cutover policy cannot be evaluated against digest-derived IDs. Both defects prevent a safe Gate-A projection.

### Architecture and antithesis
A journal plus an immutable cutover watermark is preferable to sidecar-first when preserving canonical-event-first append order matters. Its advantage only holds if recovery can classify every missing mapping: an unmapped root must be either inside a frozen legacy prefix or recoverable from an intent; it must never fall through based on an unorderable ID. Likewise, Telegram's lack of message search means a conservative unknown result is preferable to an invented lookup that turns a cache miss into duplicate-send authorization.

### Constructive synthesis
Record an immutable canonical-stream cursor/prefix digest and the first post-cutover append sequence under the transition lock, then use that cursor—not a generic event ID—to classify missing mappings. Replace the root-flow table with actual enum values; explicitly decide the supported projection/migration behavior of accepted `check_in_validated` payloads and the safety treatment of `safety_flag`. For Telegram, retain only pre-call local `confirmed_not_sent`; every invocation without its single valid provider receipt remains `unknown` pending audited human reconciliation.

## Root Cause
Revision 16 calls two new contracts exact while relying on interfaces the repository/provider does not supply: renamed EventType values, an orderable source-event ID, and a Telegram lookup by idempotency token. This reintroduces silent misprojection or unsafe resend at the core authority boundaries.

## Findings
1. **HIGH (P1) — `stage-16-revision.md:7-17`:** The root table uses four nonexistent EventType values. Ordinary check-ins would be unclassified/treated unknown. Use `morning_checkin`, `nutrition_checkin`, `workout_record`, and `trainer_session_record`, then fixture every real enum value.
2. **HIGH (P1) — `stage-16-revision.md:19-27`:** `source_day_cutover_event_id` has no defined ordering relation to roots. Digest-derived wizard IDs cannot distinguish legacy roots from post-cutover roots, leaving the pass-15 silent-fallback problem unresolved. Persist and test a canonical append cursor/frozen prefix or equivalent monotonic sequence.
3. **HIGH (P1) — `stage-16-revision.md:12-13`:** `check_in_validated` is declared metadata-only, but the current EventStore emits it as an accepted event with a `check_in` payload (`checkin_cli/store.py:347-382`). Define its flow/projection or an explicit safe migration/exclusion before enabling the adapter.
4. **HIGH (P1) — `stage-16-revision.md:39-40`:** Telegram Bot API does not provide the planned message/idempotency-token absence lookup; an implementation must not infer `message_absent` from local state. Remove that replacement branch for Telegram and keep post-invocation outcomes unknown without automatic resend.

## Recommendations
1. Correct and complete the actual EventType adapter, including `check_in_validated` and `safety_flag`, before Gate A.
2. Replace the cutover event-ID comparison with an immutable ordered canonical-stream watermark and ensure recovery blocks/reconciles every post-cutover missing mapping.
3. Make Telegram replacement authorization available only for pre-invocation local validation; document an audited manual reconciliation policy for unknown sends.
4. Retain Revision 16's journal, atomic overlay, authority-mirror, config-fanout, canonical-byte, and meal-policy improvements after these corrections.

## Architectural Status
BLOCK

## Code Review Recommendation
REQUEST CHANGES

## Tradeoffs
| Option | Benefit | Risk | Decision |
|---|---|---|---|
| Intent journal + ordered source watermark | Keeps canonical-first compatibility and repairs crashes | Requires explicit cursor/recovery state | Prefer |
| Sidecar first | Simple legacy classification | Leaves harmless orphan-sidecar cleanup | Acceptable alternative |
| Telegram cache-miss lookup | Appears to permit retry | Cannot prove provider absence; risks duplicate send | Reject |
| Pre-call-only confirmed-not-sent | Never auto-retries uncertain send | Requires audited human reconciliation | Prefer |
