---
slug: nutricoach-v140-weekly-operations
status: complete
intent: clear
review_required: true
plan_path: .omo/plans/nutricoach-v140-weekly-operations.md
plan_sha256: 5ca170b02a4ce6b4049019541daa104e9f5f54b7fd9926b66991934bebdc7054
review_round_id: momus-03f2206858404d7c8906866f43902bbd
review_round_limit: 5
round_status: approved
pending-action: hand off .omo/plans/nutricoach-v140-weekly-operations.md
review_history:
  - round_id: momus-6156a6d6b2e5418b96a425e797768ae9
    plan_sha256: 551621c7d0e9a7f3373b28442fbfe4bab12717cd3a65b2f17251fa25f4606773
    launch_id: launch-15e9e34c1aa3483789d7f960bb115fea
    session: st_01a02ef8
    result: inconclusive
    reason: provider authentication unavailable before artifact read
  - round_id: momus-c0246b3aadb64aa88f8bad86e9242812
    plan_sha256: 551621c7d0e9a7f3373b28442fbfe4bab12717cd3a65b2f17251fa25f4606773
    launch_id: launch-4b8450dd565b4f62b1d5a3d53abbc0c3
    session: st_01a02ef9
    result: changes_requested
    accepted_blockers:
      - remove absent standalone check-in schema reference
      - replace v1.1 TTL-only verifier with v1.4 verifier
      - add executable QA invocations to F1-F5
  - round_id: momus-03f2206858404d7c8906866f43902bbd
    plan_sha256: 5ca170b02a4ce6b4049019541daa104e9f5f54b7fd9926b66991934bebdc7054
    launch_id: launch-50adf120c9aa473d9c094caa2d20590f
    session: st_01a02efe
    result: approved
    verdict: OKAY
convergence:
  substantive_rounds: 2
  blocker_ledger_frozen: true
  accepted_blockers: 3
  resolved_blockers: 3
  non_blocking_notes: 0
review:
  momus:
    status: approved
    workspace_root: /home/cube/projects/richard/traning coach
    runtime_home: null
    target: .omo/plans/nutricoach-v140-weekly-operations.md
    round_id: momus-03f2206858404d7c8906866f43902bbd
    plan_sha256: 5ca170b02a4ce6b4049019541daa104e9f5f54b7fd9926b66991934bebdc7054
    launch_id: launch-50adf120c9aa473d9c094caa2d20590f
    session: st_01a02efe
    result: OKAY
approach: Add a default-OFF v1.4.0 weekly-operations capability that keeps append-only customer events authoritative, mirrors one idempotent sanitized daily status card into operator topic 59, performs exactly one approved reminder before a durable non-response review state, produces a Monday weekly trend card, preserves owner-DM final approval, and proves the complete path with synthetic and bounded-live Golden Paths.
---

# Draft: nutricoach-v140-weekly-operations

## Components (topology ledger)
<!-- Lock the SHAPE before depth. One row per top-level component that can succeed or fail independently. -->
<!-- id | outcome (one line) | status: active|deferred | evidence path -->
1 | Append-only daily check-in and missed-state authority | active | `dualcoach/profile/checkin_cli/store.py`, `customer_schedule.py`
2 | Idempotent operator-room daily status projection | active | `gateway/platforms/telegram.py`, topic 59 config
3 | Exactly-one reminder and non-response review | active | `customer_schedule.py`, scheduled delivery ledger
4 | Weekly trend projection and owner review card | active | `customer_reporting.py`, `nutrition_coaching.py`
5 | v1.4.0 candidate, Golden Path, upgrade, rollback | active | `.omo/evidence/`, live migration receipts
6 | Monthly aggregation | deferred | no authoritative product requirement or live runtime branch

## Open assumptions (announced defaults)
<!-- Record any default you adopt instead of asking, so the user can veto it at the gate. -->
<!-- assumption | adopted default | rationale | reversible? -->
Operator-room privacy | Daily card shows submission/missed/late status, completion count, approval state, event ID; no raw meals, symptoms, free text, or full health payload | room membership may expand later | yes
Approval authority | Final approve/send remains in owner `@nutricoach_kr_bot` DM | separates visibility from authority and preserves current production boundary | yes
Weekly cadence | Monday after the prior Sunday closes; uses the existing `weekly_weekday=0` schedule | already configured and tested | yes
Customer delivery | No auto-send; owner approval remains mandatory and exactly-once | canonical contract | no
Versioning | ship as default-OFF `v1.4.0` capability | customer-facing compatible feature, not a narrow bugfix | no
Live proof | synthetic seven-day Golden Path before upgrade, then one real seven-day bounded observation | synthetic time compression cannot replace live calendar evidence | no
Source baseline | reconstruct a clean feature worktree from the exact qualified v1.3.2 active candidate plus the qualified v1.3.3 authority-isolation delta; never develop in the detached dirty worktree | live runs v1.3.2 while v1.3.3 is qualified but unregistered | yes
Exactly-once meaning | one logical reservation and at most one provider call, ending in a durable receipt or terminal unknown | Telegram cannot guarantee one visible message across an unknown provider outcome | no
Scale and spend | one live customer for seven days, one weekly AI generation plus at most one correction pass, existing provider only | bounded pilot and no new paid service | yes
Week definition | seven KST calendar days, Monday through Sunday | v1.3.2 daily launcher runs every calendar day | no

## Findings (cited - path:lines)
`HANDOFF.md:22,31,53,89,190` requires connected trend detection, daily versus weekly coaching, customer isolation, append-only corrections, and weekly review source.
`.gjc/.../stage-01-planner.md:34,53,70,80,111` requires one reminder followed by non-response review.
`.omo/evidence/dualcoach-golden-path-contract.md:33-34,93` proves one check-in and atomic enqueue, not seven-day weekly operation.
`.omo/evidence/v1.3.2-daily-checkin/qualification.json` is daily-checkin scoped and contains no weekly end-to-end receipt.
`dualcoach/profile/checkin_cli/customer_schedule.py:1519-1720` implements exactly-once reminder mechanics and terminal uncertainty.
`dualcoach/profile/checkin_cli/customer_reporting.py:409-479` implements weekly missing-day, adherence, and trend projections.
`gateway/platforms/telegram.py:10594-10649` implements weekly summary and owner draft creation.
Live `config.yaml` has no `missing_checkin_reminder`; the capability is not armed.
Live customer has no completed canonical check-in event yet; trend ledgers are empty until `체크인 저장`.
Metis found that reminder correlation recognizes `MORNING_CHECKIN` but the live NutriCoach path emits `NUTRITION_CHECKIN`; v1.4 must accept the latter's active correction lineage without changing legacy compatibility.
Metis found the current weekly helper counts weekdays while the approved operation is seven calendar days; the existing 28-day KPI helper must remain unchanged.
Metis found Topic 59 has append-only risk/review publication but no deterministic mutable `(customer, KST day)` status-card binding.
Metis found the live runtime is candidate `6c9c4394…` (v1.3.2); candidate `9ac3ffc2…` (v1.3.3) is qualified but explicitly not deployed.

## Decisions (with rationale)
Treat Telegram as a projection, never the database; JSONL append-only event ledgers remain sole authority.
Publish exactly one operator-room card per customer/day using a deterministic projection key; state transitions update that card while ledger history remains append-only.
Represent `submitted`, `missed`, and `late_submitted` as durable machine states so weekly counts do not infer operational facts from Telegram messages.
Keep raw check-in answers and approval controls out of the room; weekly aggregates may expose only bounded metrics.
Reuse reservation/receipt/fence semantics for reminders and room projections; unknown provider outcome is terminal and never blindly retried.
Exclude monthly aggregation and automatic plan activation/delivery from v1.4.0.
Use one reminder at 20:00 KST and create the durable `missed`/operator-review state at 23:00 KST when no correlated valid check-in exists.
Store v1.4 status transitions in a versioned append-only sidecar pinned to canonical sequence/digest; do not add strict event variants that older readers cannot parse.
Classify a first valid check-in by 23:00 as `submitted`, absence at the cutoff as `missed`, and the first valid post-cutoff check-in as `late_submitted`; later corrections preserve the original timeliness class.
Record `missed` independently of reminder delivery. Only `sent_audited` may add the `reminded_no_response` reason; unknown/failure becomes a delivery incident and never opens a same-day replacement attempt.
The approved static reminder is the sole new automatic customer-message exception; coaching, plan, and weekly-summary delivery remain owner-approved.

## Scope IN
Default-OFF capability/schema/config.
Daily submitted/missed/late status projection to `뉴트리코치 운영방` topic 59.
One reminder, durable reminder fact, and non-response review.
Append-only canonical check-in/missed-state persistence and corrections.
Monday weekly missing-day/adherence/weight-trend summary.
AI weekly draft grounded in canonical events and 최코치 public-knowledge rules.
Owner-DM review/approve/send exactly-once.
Synthetic seven-day Golden Path, restart/duplicate/unknown tests, F1-F5, live upgrade/rollback, seven-day bounded observation.

## Scope OUT (Must NOT have)
Monthly summaries.
Raw meals, symptoms, free-text notes, or detailed health payloads in the operator room.
Final approval buttons in the operator room.
Automatic plan activation or customer delivery.
Human 최코치 Telegram account access.
Backfilling fabricated historical customer check-ins.
Mutation of v1.0-v1.3.2 receipts or released candidates.

## Open questions
None. The owner selected recommendation A: 20:00 KST reminder and 23:00 KST missed cutoff.

## Approval gate
status: approved
Approved decision set: default-OFF v1.4.0; sanitized topic-59 daily projection; owner-DM approval; Monday weekly summary; 20:00 reminder; 23:00 missed cutoff; no monthly aggregation or automatic customer delivery.
Approval received: `ㅇㅇ`.
Next action: complete `.omo/plans/nutricoach-v140-weekly-operations.md` and run fresh Momus review rounds up to five.
<!-- When exploration is exhausted and unknowns are answered, set status: awaiting-approval. -->
<!-- That durable record is the loop guard: on a later turn read it and resume at the gate instead of re-running exploration. -->
