## Summary
The plan correctly rejects free-form rewriting in favor of a finite local-variant boundary and deliberately protects the durable adaptive Topic 59 path. It is not approvable yet: its disabled daily baseline conflicts with its source removal, and it cannot guarantee one provider attempt or stable immutable output across crash, concurrency, and replay windows. Resolve those contracts and the resolved-provider Kimi guard before implementation.

## Claims
- Reviewed the immutable Planner artifact at `/home/cube/projects/richard/traning coach/.gjc/_session-019fa7fb-3be3-7000-b23f-03f6c05d81ff/plans/ralplan/019fa7fb-3be3-7000-b23f-03f6c05d81ff/stage-01-planner.md` (assignment-supplied SHA-256: `57e9aaac51a12d7e93f13bfd3bb5b9d7703f844bbad9ba2f0f992edc579e1da1`), not current product code.
- The proposed finite `variant_id` schema, strict local validator, local immutable variant table, canonical fallback, no-content telemetry, adaptive pass-through, and MIT attribution are materially stronger than the identified free-form daily insertion.
- The plan names concrete implementation points in `checkin_cli/adaptive_nutrition.py`, `gateway/platforms/telegram.py`, `듀얼코치_사용설명서.md`, and focused unit/integration/E2E seams. Those are necessary but do not yet close the findings below.

## Analysis
### Spec compliance
The plan’s central safety design is sound: the provider gets slot/variant choices rather than customer prose, and accepted output is selected from code-reviewed local strings. It correctly keeps calculations, decisions, safety, delivery state, immutable card payloads, and strict-topic delivery mechanics outside provider authority. Its planned rejection cases and no-content telemetry meet the intended privacy direction; the requested MIT notice is explicitly included.

However, the primary daily replacement contract is internally inconsistent. Step 2 removes raw `feedback` from `_nutrition_daily_text`, while the disabled regression requirement requires the current daily fixture byte-for-byte. The plan does not say whether old free-form feedback is excluded from the canonical baseline, how existing saved check-ins/replays behave, or which exact body a disabled/error path returns. A safe implementation cannot infer this without risking either retention of unsafe model prose or a silent disabled-mode behavior change.

### Architecture and failure modes
The plan correctly schedules weekly selection before `template_digest` and delivery reservation so the digest reflects the selected final body. That ordering exposes an unresolved exactly-once window: a process can fail, or a concurrent tick can race, after the provider request but before reservation. The same saved daily check-in can revisit `_render_physique_feedback_replay`. Because selection is nondeterministic and no bounded selection/attempt state is durable, the same logical artifact may make a second provider call and receive a different local variant. The plan’s “one attempt per eligible render” wording is insufficient for the requested one-attempt fail-closed behavior of a saved check-in or scheduled task.

The Kimi restriction is also not enforced at the integration boundary. Checking only configured labels before `resolve_provider_client(provider, model)` is not proof of the actual provider selected by aliases or resolver mappings. The fail-closed decision must be made against an allow-listed/resolved identity before the completion call, while keeping that identity out of telemetry.

### Strongest fair antithesis
Avoiding a new persistence record keeps the proposal smaller and protects existing adaptive lifecycle schemas. Likewise, pre-resolution label screening is simple and likely works in a direct provider configuration. But neither is sufficient for the stated cross-restart one-attempt guarantee or unconditional Kimi prohibition. The plan should prefer a narrowly bounded durable cosmetic decision/claim or deliberately canonical-only recovery over an unprovable exactly-once claim.

### Constructive synthesis
1. Define the daily canonical cutover as an exact rendering contract: legacy arbitrary feedback is never an input to new rendering; existing already-sent messages are not rewritten; disabled, rejected, timeout, and replay behavior has one named canonical body and golden fixtures. State whether a replay is canonical-only or reads a durable finite selection.
2. Give each logical daily save and weekly delivery task one durable bounded state before a provider request. A finite selected `variant_id` plus outcome/attempt marker may live in a narrowly scoped additive projection or an explicitly extended existing reservation/check-in record; it must never contain prompt/body/response. Pin the final body/digest only after this state is atomically finalized. If such state is deliberately prohibited, recovery/replay must not call the provider and must render canonical, which is the only fail-closed alternative.
3. Replace substring screening with an explicit permitted provider/model identity contract enforced after resolution and before invocation; alias-to-Kimi is denied without request or content-bearing log.
4. Add `mode: disabled|shadow|enabled` to the strict config schema. In shadow, validate one selection but always return canonical; its telemetry has a bounded, documented shadow outcome.

## Root Cause
The plan treats rendering as the unit of idempotency even though daily check-ins and scheduled weekly tasks are durable logical artifacts. A provider-chosen variant is nondeterministic across render attempts, but the plan has no durable decision or pre-call claim that binds that choice to the artifact. This also leaves the canonical cutover ambiguous when retiring the existing feedback source.

## Findings
1. **HIGH — `/home/cube/projects/richard/hermes-agent/gateway/platforms/telegram.py:_nutrition_daily_text`, `_saved_physique_coaching_feedback`, `_render_physique_callback_prompt`, `_render_physique_feedback_replay` (current free-form path cited in artifact at lines 5878–5898):** The plan both removes `feedback` and requires disabled output to match the current fixture without defining the deterministic canonical baseline or legacy/replay policy. **Impact:** unsafe text may survive, or disabled/replay output changes silently. **Fix:** specify the one canonical body and explicit legacy cutover; golden-test disabled, error, and replay output separately. Reported as P1.
2. **HIGH — `/home/cube/projects/richard/hermes-agent/gateway/platforms/telegram.py:_maybe_apply_korean_expression_variant`, `_send_nutrition_coaching_tick`, `_render_physique_feedback_replay`, `reserve_customer_task_delivery`:** Selection is before durable weekly reservation and not durably bound to daily replay, so crash/concurrency/replay can make multiple nondeterministic calls/variants for one logical artifact. **Impact:** violation of one-attempt fail-closed semantics and potentially divergent digest-pinned/delivered bodies. **Fix:** durable finite variant/attempt claim before calling the provider, or canonical-only recovery/replay; test crash-before-reservation, concurrent tick, and replay. Reported as P1.
3. **HIGH — `/home/cube/projects/richard/hermes-agent/gateway/platforms/telegram.py:_request_korean_expression_selection`, `agent.auxiliary_client.resolve_provider_client`:** A pre-resolution `"kimi"` substring check cannot reject a benign configured alias resolved to Kimi. **Impact:** prohibited provider can receive a request despite the no-Kimi contract. **Fix:** permit only known safe resolved identities or verify the resolved identity before invoking, with an alias-to-Kimi zero-call test. Reported as P1.
4. **MEDIUM — `/home/cube/projects/richard/hermes-agent/gateway/platforms/telegram.py:TelegramAdapter.__init__`, `_maybe_apply_korean_expression_variant`:** The rollout requires shadow observation, but the strict config schema has no representable shadow mode and rejects unknown keys. **Impact:** rollout is not implementable as specified and encourages an undocumented bypass. **Fix:** add documented `disabled|shadow|enabled` mode and canonical-body shadow tests. Reported as P2.

## Recommendations
1. Resolve findings 1 and 2 as release blockers; amend the plan with exact canonical cutover and logical-artifact idempotency semantics before code work.
2. Amend provider integration to enforce a resolved/allow-listed identity and add the adversarial alias test.
3. Make shadow a first-class strict configuration mode and document its enum-only telemetry result.
4. Retain the plan’s finite local variants, strict parser, no-content telemetry, adaptive zero-slot pass-through, and complete MIT notice; they are the correct foundation once blockers are closed.

## Architectural Status
BLOCK

## Code Review Recommendation
REQUEST CHANGES

## Tradeoffs
| Option | Benefits | Costs / required constraint |
|---|---|---|
| Durable finite `variant_id`/attempt projection keyed to saved check-in or delivery task | Stable replay, cross-restart one-attempt evidence, final digest/body reproducibility | Small additive persistence/schema work; contains only enum/outcome, never content |
| Canonical-only recovery and replay with no durable cosmetic state | No new persistence; strongest fail-closed recovery | Successful initial cosmetic selection is not replay-stable; must be explicitly accepted and never re-called |
| Keep selection ephemeral per render (current plan) | Smallest change | Cannot meet one-attempt or immutable artifact guarantees; reject |
| Pre-resolution substring Kimi screen (current plan) | Simple direct-config implementation | Alias/resolver bypass; reject |
| Resolved identity allow-list | Enforces no-Kimi independent of alias | Requires provider adapter identity contract and a focused alias test |
