## Summary

검토 대상 Planner artifact는 `/home/cube/projects/richard/traning coach/.gjc/_session-019f8455-334a-7000-99ca-318dfd0e06b1/plans/ralplan/019f8455-334a-7000-99ca-318dfd0e06b1/stage-01-planner.md` (sha256 `8b224eceb12cef566b525b45b7b54564f41fc165b8e96c375e3ec89d61b6cafe`, stage_n `1`)입니다. 단일 고객·사람 승인·고객별 저장소라는 범위 선택은 명세와 맞지만, 트레이너 권한, 실고객 활성화 게이트, 승인 후 전송의 내구성, 웹 신뢰 경계, PII 수명주기가 구현 가능한 계약으로 내려오지 않았습니다. 이 결함을 먼저 설계에 반영해야 하므로 계획은 현재 BLOCK / REQUEST CHANGES입니다.

## Claims

- 명세의 활성 범위(외부 유료 고객 1명, 트레이너 기록, Telegram 입력, Richard 전용 내부 웹 승인, AI 자동전송 금지, 첫 4주 KPI)는 Planner의 Option B와 Phase 1–4에 반영되어 있습니다.
- 현재 고객 경계는 `CustomerSpec.telegram` 하나와 owner 주소이며, `NutritionCoachingCoordinator`는 enabled customer의 그 한 주소만 route합니다 (`customer_coaching.py:102-125`, `nutrition_coaching.py:74-98`).
- 현재 owner Telegram 기능은 초안 생성·표시까지만 하며 고객에게 최종 피드백을 보내거나 전송 감사 기록을 남기지 않습니다 (`telegram.py:4054-4089`).
- 기존 schedule claim은 파일의 create-exclusive claim일 뿐 outbound receipt 또는 uncertain-delivery reconciliation을 가지지 않습니다 (`customer_schedule.py:52-88`, `telegram.py:4471-4531`).
- 현재 provider grounding은 고객의 finalized check-in과 전체 profile을 model input으로 직렬화합니다 (`customer_grounding.py:46-67`).
- 현재 activation은 `set_customer_enabled`가 `enabled`를 직접 toggle하며, 레지스트리에 주소검증·계획승인·테스트전송·provider 검증 증거 필드가 없습니다 (`customer_admin.py:104-145`, `customer_coaching.py:102-125`).

## Analysis

### Stage 1 — Spec compliance

계획은 핵심 제품 범위를 과도한 외부 플랫폼으로 확장하지 않고, 정상일/예외일 피드백·사람 승인·첫 4주 KPI를 포함합니다. 그러나 딥인터뷰의 안전·권한·삭제·백업·수동운영 acceptance는 현재 Phase work item만으로 충족되지 않습니다.

특히 Phase 1의 트레이너 기록은 필수 actor를 추가하지만 owner/customer/trainer 주소와 권한의 불변 조건을 정의하지 않습니다. Phase 4의 onboarding 순서는 현 registry transition으로 강제할 수 없고, Phase 3의 Telegram fallback은 현재 존재하지 않는 전송 기능을 전제합니다. Phase 2/3의 “정확히 1회”는 외부 Telegram 호출에 대한 crash/timeout/ambiguous-result 모델 없이는 성립하지 않습니다.

### Stage 2 — Architecture and boundary analysis

**권한·격리.** `WORKOUT_RECORD` event type은 있지만 trainer identity/route가 없습니다. single customer pilot이라도 trainer address가 customer or owner space에 겹치거나 향후 second customer와 재사용될 때 owner/customer context가 세션에 잘못 귀속될 수 있습니다. 역할별 address registry, global space uniqueness, actor-specific wizard binding, revoke/disable semantics가 필요합니다.

**승인·전송.** UI-level CSRF/replay/idempotency cannot constitute an outbound delivery transaction. The durable unit must be an approved revision and command id—not a click or a Telegram callback. A single outbound service must atomically claim one approval revision, record delivery attempt and provider response, and block resend after unknown outcome pending reconciliation. This is also the only acceptable seam for web and Telegram recovery.

**웹 통합.** Planner가 새 route location을 추후 조사 대상으로 남긴 것은 security boundary에 부적절합니다. Existing Hermes dashboard is a large configuration/terminal/files surface; loopback mode uses an ephemeral page-injected token, and its existing auth identifies dashboard sessions rather than a specifically scoped coaching operator. The plan must choose a deployment and storage communication model before routes are written. Localhost/SSH tunnel is network exposure control, not a complete operator authorization contract.

**PII.** Provider assurance and versioned consent are stated, but there is no machine-enforced data-transfer allowlist or deletion/backup lifecycle. Current grounding includes all profile fields such as allergies, digestion, supplements, and coach notes if populated. Consent revocation, deletion-pending, queue/outbound hold, backup expiration/restore, and provider-policy evidence must be one gate queried by intake, grounding, approval, and send—not separate best-effort checks.

**Metrics.** Current reporting reconstructs health trends from accepted check-ins. It cannot determine payment/repayment, satisfaction, staff work time, feedback latency, or adjusted denominators. A customer-scoped immutable pilot ledger is required before four-week logical-AND success can be reproducible.

### Antithesis and constructive synthesis

The strongest argument for the existing plan is that a single paid customer and SSH-local web console warrant minimal new infrastructure. That is correct only if “minimal” means one narrow domain service and durable ledgers, not fewer contracts. Reusing the existing registry, event store, and dashboard is sound where their boundaries are sufficient; extending their mutable records or treating dashboard authentication and schedule claims as a delivery ledger would hide the required guarantees.

Strengthen Option B with these layers:

1. **Registry/activation boundary:** versioned actor addresses (customer, trainer, owner), address uniqueness, active/withdrawn state, and a fail-closed activation assertion that references approved consent/provider/address/plan/test-send evidence.
2. **Customer data boundary:** append-only customer events for check-ins and trainer records; separate append-only decision/outbound ledger rather than overloading health-checkin events or mutable registry config.
3. **Decision/outbound boundary:** immutable draft revision with evidence snapshot hash; approval binds exact revision; outbound command has unique approval-revision id and state `approved → sending → accepted | unknown | failed | cancelled`. Only `accepted` carries provider message id. `unknown` cannot be auto-resent.
4. **Operator boundary:** either a loopback sidecar controlled by a dedicated service credential/Unix socket, or a profile-scoped dashboard router with an explicit allowlisted owner principal. It must have a documented tunnel, strict Origin/CSRF/no-cache/referrer behavior, redacted audit events, and no route parameter or log PII.
5. **Privacy/measurement boundary:** provider field-level allowlist and policy-evidence reference; retention/deletion/backup restore state; pilot ledger defining eligibility, waivers, payments, survey timestamp, timers, and `inconclusive` behavior.

## Root Cause

The plan correctly names the safety properties but treats several of them as screen/API features rather than cross-channel durable domain invariants. Existing code provides isolated check-in storage and draft generation, but not a trainer role model, activation evidence state, audited final-send operation, scoped operator console, or lifecycle/KPI ledger. Reusing those incomplete boundaries without first introducing the missing domain contracts would turn fail-closed requirements into manual convention.

## Findings

1. **HIGH — Planner:65-66 — Trainer authorization boundary absent.** `CustomerSpec` and `NutritionCoachingCoordinator` only model customer/owner routing. Define versioned trainer identity/address and role; validate disjointness and use exact actor-specific session routing plus revoke/correction rules.
2. **HIGH — Planner:123 — Activation gate is not enforceable.** Current `set_customer_enabled` directly toggles enabled and the registry lacks the proposed evidence. Add immutable gate evidence references and refuse enable until consent/provider/address/plan/test-send conditions validate.
3. **HIGH — Planner:89-104 — Exactly-once claim lacks a durable outbound protocol.** A CSRF token/idempotency key does not resolve crash/timeout ambiguity. Add an approval-revision-bound command/outbox with durable state, provider receipt, and reconciliation-before-resend; both channels must invoke it.
4. **HIGH — Planner:104-108 — Claimed Telegram send fallback does not exist.** Current path edits the owner’s draft card only. Add an owner-authorized Telegram approval/send command using the shared service or explicitly treat web outage as a held/manual-contact recovery state with reconciliation.
5. **HIGH — Planner:93-107 — Web trust boundary is undecided.** “Investigate then choose route module” is insufficient for health PII. Commit to sidecar or dashboard integration, precise principal/session/tunnel semantics, CSRF/Origin/cache/referrer/log policy, storage seam, and failure-deny tests.
6. **HIGH — Planner:90 — PII lifecycle/provider minimization is not executable.** Add a field allowlist, consent history, deletion state queried by all flows, encrypted-backup/restore purge contract, provider-policy evidence record, and queued-send/revoke/delete tests.
7. **MEDIUM — Planner:120-127 — Pilot success ledger is unspecified.** Add a customer-scoped append-only KPI ledger, denominator/waiver/time-capture/payment/survey definitions and an `inconclusive` state for missing evidence.

## Recommendations

1. Revise Phase 1 before implementation: add explicit actor-address and activation-state schemas plus tests for all customer/trainer/owner collision, revocation, and unauthorized-route cases.
2. Insert a dedicated decision/outbound service and append-only ledger between Phases 1 and 2. Define API inputs/outputs and all states before adding UI; test duplicate click, concurrent channel attempts, process crash before/after provider response, timeout/unknown response, and manual reconciliation.
3. Replace Phase 3’s unspecified route placeholder with one selected architecture, exact service lifecycle, authenticated owner identity, and secure web policy. Do not mount PII routes on a broad dashboard without a profile/principal/route scope proof.
4. Make Phase 0/4 activation a code-enforced transition backed by immutable evidence, not an operator checklist. Keep the launch block fail-closed.
5. Add privacy lifecycle and KPI ledger modules to Phase file lists, then implement their retention/deletion, restore, data-minimization, and reproducibility tests.
6. Retain existing isolated data roots, exact `(user_id, chat_id, topic_id)` customer routing, KST scheduling, and approved-knowledge retrieval as reuse seams; do not create a parallel generic chat ingress.

## Architectural Status

BLOCK

## Code Review Recommendation

REQUEST CHANGES

## Tradeoffs

| Option | Benefits | Risks / required constraint |
|---|---|---|
| Dedicated loopback coaching sidecar + Unix-socket/domain service | Small PII surface and clear process ownership | Must add service lifecycle, dedicated session authentication, and SSH-tunnel runbook |
| Profile-scoped Hermes dashboard router + same domain service | Reuses mature Host/Origin/auth middleware and asset conventions | Must explicitly enforce coaching-owner principal, profile isolation, narrow API prefix, and avoid inheriting broad dashboard privilege |
| Direct Telegram-only manual delivery | Lowest code change | Cannot satisfy centralized approval, final-send audit, or robust duplicate reconciliation; unsuitable as the claimed fallback |

Verification not run: this is a read-only plan review; implementation, tests, and formatting were intentionally not executed.
