I read this as research and pre-plan gap analysis - I’ll inspect the approved draft, plan, and every concrete repository/runtime path they cite, then report only evidence-backed gaps with reversible defaults or explicit owner decisions.


## Intent Classification
**Type**: Research
**Confidence**: High
**Rationale**: The task is a read-only, evidence-based audit of an approved but incomplete implementation plan.

## Pre-Analysis Findings

| # | Finding | Evidence | Blocks decision-complete plan? | Reversible default / unsafe decision |
|---|---|---|---|---|
| 1 | **Contradiction: “approved” artifacts are not finalized.** The draft remains `awaiting-approval` with null review/hash fields, while the plan is only a placeholder skeleton with no scope, todos, acceptance criteria, effort, or risk. | `.omo/drafts/nutricoach-v140-weekly-operations.md:1-22,89-94`; `.omo/plans/nutricoach-v140-weekly-operations.md:1-44` | **Yes** | Finalize the plan, calculate its digest, and complete review metadata before implementation. |
| 2 | **Repository authority is ambiguous and one cited evidence path is wrong relative to this workspace.** The draft’s `dualcoach/profile/...` paths do not exist here; the actual v1.3.2 qualification is under the isolated worktree, while production runs an installed wheel pinned by systemd. | `/home/cube/projects/richard/.worktrees/nutricoach-v111-impl/.omo/evidence/v1.3.2-daily-checkin/qualification.json:1-39`; `/home/cube/.config/systemd/user/hermes-gateway-dualcoachtest.service:7-14`; `/home/cube/.config/systemd/user/hermes-gateway-dualcoachtest.service.d/task26-authority.conf:1-6` | **Yes** | Pin the exact v1.3.2 candidate digest and derive a fresh `/home/cube/projects/richard/.worktrees/nutricoach-v140-impl` worktree from it. Treat installed wheels, not the mutable profile checkout, as the live baseline. |
| 3 | **Mandated stack and anti-scope boundaries are absent.** Existing authority mandates Python/Hermes, Pydantic schemas, customer-local JSONL, the existing scheduler/Telegram adapter, and no new memory DB, plugin topology, upstream PR, or broad redesign. | `HANDOFF.md:167-202`; `/home/cube/projects/richard/.worktrees/nutricoach-v111-impl/pyproject.toml:1-25` | **Yes** | Reuse the current stack with no new production dependency, database, generic route, upstream contribution, or AI memory/copy system. |
| 4 | **Default-OFF is underspecified against already-active v1.3.2 behavior.** The live scheduler and nutrition coaching are enabled; Monday weekly work already exists, while no typed v1.4 flag or reminder block exists. | `/home/cube/.hermes/profiles/dualcoachtest/config.yaml:641-681`; `/home/cube/.hermes/profiles/dualcoachtest/cron/jobs.json:1-27`; `checkin_cli/customer_schedule.py:208-246` in the active installed runtime | **Yes** | Add a distinct, typed `weekly_operations.enabled: false` capability gating only new v1.4 side effects. Preserve existing v1.3.2 daily launcher and owner-weekly behavior when it is absent/OFF. |
| 5 | **20:00/23:00 cannot be represented by the current reminder contract.** Reminder work becomes due after `daily_time`, and the gateway reads an untyped absolute `response_window_ends_at`; it has no recurring reminder or cutoff times. | `/home/cube/.hermes/profiles/physique-coach/workspace/checkin_cli/checkin_cli/customer_schedule.py:208-246`; `/home/cube/projects/richard/hermes-agent/gateway/platforms/telegram.py:9878-9900`; `gateway/platforms/nutrition_coaching_config.py:55-178` | **Yes** | Typed recurring KST fields: `reminder_time=20:00:00`, `missed_cutoff_time=23:00:00`; reject naive/absolute deadlines and any ordering other than reminder before cutoff. |
| 6 | **The reminder’s “valid check-in” assumption is false for the live flow.** Terminal detection accepts only a lineage rooted at `MORNING_CHECKIN`, but the live customer flow is `nutrition_daily`, which emits `NUTRITION_CHECKIN`. | `checkin_cli/store.py:70-111`; `checkin_cli/wizard.py:1008-1015`; `/home/cube/.hermes/profiles/dualcoachtest/data/customers/pilot_20260820_01/wizard/drafts/a594ba00240399c36f366e83fff8e405.json:1` | **Yes** | Correlate an accepted terminal lineage rooted in `NUTRITION_CHECKIN` for NutriCoach, preserving `MORNING_CHECKIN` only for backward compatibility. Corrections inherit the root KST day. |
| 7 | **Seven-day operations conflict with weekday-only reporting.** v1.3.2 qualification says daily check-ins run on all calendar days, but weekly adherence and missing-day calculations filter to weekdays. | v1.3.2 `qualification.json:2-8`; `checkin_cli/customer_reporting.py:409-450,617-623` | **Yes** | Add a v1.4 weekly-operations calendar-day denominator of exactly seven days. Do not globally alter the existing 28-day weekday KPI helper. |
| 8 | **The daily state machine is not decision-complete.** No contract defines cutoff races, correction timing, week-to-date completion count, current event selection, or approval-state values. The strict canonical schema has no `submitted`, `missed`, or `late_submitted` event types. | `checkin_cli/models.py:31-56,864-967`; `contracts/checkin-event.schema.json:22-47`; draft `:59-65` | **Yes** | Use a separate append-only v1.4 operational sidecar keyed by `(customer, KST day)` and pinned to canonical sequence/digest. First valid commit by 23:00 => `submitted`; no valid commit at cutoff => `missed`; first valid commit after cutoff => `late_submitted`. Corrections update the latest event reference but preserve original timeliness. |
| 9 | **“Missed” and “non-response after reminder” are conflated.** Current review creation requires `sent_audited`; an unknown/failed reminder can never produce that review, although absence of check-in remains factual. Current code also permits a second same-day attempt after a known failure under new approval. | `customer_schedule.py:1520-1690`; `tests/test_customer_schedule.py:241-370`; `customer_coaching.py:639-672` | **Yes** | Always record factual `missed` at 23:00. Create “reminded but no response” only with `sent_audited`; otherwise create a separate reminder-delivery incident. For v1.4, forbid every same-day replacement, including known no-send failure. |
| 10 | **Literal exactly-once Telegram visibility is not provided.** Existing contracts guarantee reservation-first/provider-at-most-once with terminal uncertainty. Topic publication claims before provider I/O; a crash after claim but before send permanently suppresses recovery. | `PILOT_RUNBOOK.md:146-171`; `nutrition_coaching.py:21200-21251`; `telegram.py:5180-5230` | **Yes** | Define “exactly once” as one logical reservation and at most one provider call, ending in receipt or terminal unknown. **Unsafe owner decision:** if exactly one visible Telegram message is required despite ambiguous provider outcomes, the current provider cannot satisfy it. |
| 11 | **The existing Topic-59 projector cannot implement the approved daily card.** It accepts only risk/reminder review events and emits one card per event; it has no `(customer, day)` binding or edit/update state machine. | `gateway/platforms/nutrition_coaching.py:21029-21251`; `gateway/platforms/telegram.py:5180-5230` | **Yes** | Add a distinct status projector with deterministic customer/day identity, one message binding, append-only send/edit receipts, terminal unknown handling, and no approval controls. Do not overload the existing risk-review projector. |
| 12 | **“No automatic customer delivery” conflicts textually with the approved automatic reminder.** Existing daily launchers also remain automatic baseline behavior. | Draft `:43,59-65,73-75`; active `scheduled-deliveries.jsonl:1-4` | **Yes** | Define the prohibition as no automatic coaching, plan, or weekly-summary delivery. The fixed 20:00 operational reminder is the sole new customer-message exception; existing v1.3.2 launchers remain baseline. |
| 13 | **Weekly AI behavior is unvalidated.** The current weekly source and `create_weekly_review_draft` are deterministic renderers; the plan does not define public-knowledge retrieval, numeric invariants, model failure, or fallback. | `customer_reporting.py:115-166`; `gateway/platforms/nutrition_coaching.py:3831-3890`; `HANDOFF.md:22-43` | **Yes** | Canonical calculations and decisions remain code-owned. AI may explain only locked source fields using the existing approved knowledge layer; reject invented numbers/actions and fall back to deterministic Korean text. Owner DM remains the only approval/send surface. |
| 14 | **Migration and downgrade compatibility are missing.** Adding new strict canonical event types would make v1.3.2 unable to parse the stream after rollback. Production is currently pinned to an immutable v1.3.2 runtime with a snapshot rollback receipt. | `models.py:31-56`; `deployment-receipt.json:43-57`; systemd unit `:7-14` | **Yes** | Keep v1.4 operational states in a new sidecar ignored by v1.3.2. Install with the feature OFF, perform no historical backfill, preserve old receipts, and prove rollback reads all pre-v1.4 authority unchanged. |
| 15 | **Crash recovery is specified only for existing ledgers, not the new cutoff/status/card transaction.** Atomic ordering across canonical check-in, missed-state append, Topic-59 send/edit, weekly draft, and provider receipt is absent. | `store.py:460-565`; `PILOT_RUNBOOK.md:146-171,195-203` | **Yes** | Fix lock order and inject crashes at every append/fsync/provider boundary. Final-tail repair only; interior corruption, torn pairs, or unknown provider outcome stop processing. No sleeps, blind retry, truncation, or inferred receipt. |
| 16 | **Privacy/compliance approval does not cover the new processing on evidence available.** Current consent is `privacy-v1`; global PII redaction is false; the canonical runbook requires explicit consent, provider terms, retention/deletion, backup, and legal sign-off. | live config `:306-307`; registry `:250-275`; `PILOT_RUNBOOK.md:67-94,203-228` | **Live blocker** | Closed output whitelist: status, count, approval state, approved event ID, KST day only; no customer name/address/raw values. Add every new sidecar and projection receipt to retention/deletion/backup inventory. Keep live v1.4 OFF until owner/legal approves the new purpose and staff-room visibility. |
| 17 | **Budget and expected scale are absent.** Current reality is one enabled pilot customer and a one-minute scheduler; Topic-59 draining is bounded to 16 cards. No provider-call or spend cap exists for AI weekly generation. | live registry `:250-275`; cron `:1-27`; `telegram.py:5180-5228` | **No, if defaults recorded** | v1.4 target: one live customer, seven days, no load architecture, no new paid service, synthetic proof with zero network calls. **Owner decision before live:** provider/model call and spend cap for weekly AI generation. |
| 18 | **Dirty-worktree isolation is missing.** Existing policy forbids touching unrelated local changes, and the previous release used an isolated worktree. | `HANDOFF.md:160-181`; `.omo/evidence/dualcoach-task-19-evidence.md:81-89` | **Yes** | Fresh isolated worktree; record baseline status/path digest; no reset, stash, clean, rebase, upstream PR, or unrelated commit. Candidate manifests must include only v1.4-owned paths. |
| 19 | **Agent-executable QA is absent and internally contradictory.** The draft requires F1-F5; the plan defines only F1-F4, labels F3 “Real manual QA,” and contains no commands or assertions despite its zero-human statement. | Draft `:73-76`; plan `:20-44` | **Yes** | Add F5 release/provenance audit. Replace manual acceptance with agent-driven fake-Telegram real-handler QA and read-only validation of owner-created live receipts. Human activation/send remains an external rollout gate, not a test step. |
| 20 | **Bounded live observation lacks start authority, abort conditions, and evidence shape.** The live customer and scheduler are already active, while the v1.4 capability must remain OFF until synthetic proof passes. | live registry `:250-275`; cron `:1-27`; draft `:44-45,73-76` | **Live blocker** | No automatic start. Owner selects the live seven-day window after synthetic seal, consent/legal, budget, migration, and rollback gates. Abort on privacy leak, duplicate call/message, unknown delivery, corrupt ledger, authority drift, or feature flag mismatch. |

### Scope-Creep Risks

- Preserve dormant legacy `monthly_day` fields; do not remove or redesign them. Assert zero monthly tasks/messages instead (`customer_schedule.py:17-19,208-246`; `tests/test_customer_schedule.py:196-207`).
- Do not turn status projection into a dashboard, customer calendar, analytics warehouse, or general notification framework.
- Do not backfill the current incomplete live draft or fabricate seven historical customer check-ins.
- Do not refactor the existing adaptive approval lifecycle, generic Telegram routing, or 28-day KPI model.

## Questions for User

These are unsafe owner gates, not reasons to reopen approved product behavior:

1. Does “exactly once” mean the reversible default of one logical attempt/provider-at-most-once with terminal unknown, or a literal guarantee of one visible Telegram message? The latter is unsupported by the current provider.
2. Has owner/legal approved pseudonymous daily status visibility in Topic 59, the reminder purpose, AI weekly processing, and retention/backup deletion for v1.4? Until then, live enablement must remain blocked.
3. What is the maximum live weekly-AI provider call/spend allowance? Default: current provider only, one customer, one bounded week, no retries that generate new content.

## Identified Risks

- **Wrong source edited or packaged:** Pin the active v1.3.2 candidate and use a fresh isolated worktree.
- **Reminder sent immediately after 08:00:** Require typed recurring 20:00/23:00 KST gates.
- **Every nutrition check-in falsely classified missing:** Fix terminal lineage to include `NUTRITION_CHECKIN`.
- **Rollback cannot read strict events:** Keep v1.4 derived states in a sidecar.
- **Topic card lost or duplicated after crash:** Durable reservation/receipt/unknown states; never claim literal provider exactly-once.
- **Health-data exposure:** Closed renderer, adversarial leak tests, redacted evidence, legal gate.
- **Scope inflation:** One customer, seven days, existing stack, no monthly/dashboard/new infrastructure.

## Directives for the Planner

### Core Directives

- MUST: Resolve all findings marked **Yes** in the detailed plan before review.
- MUST: Separate code-complete acceptance, synthetic release qualification, owner-authorized live observation, and rollout approval.
- MUST: Define exact schemas, deterministic keys, lock order, state transitions, cutoff races, failure states, and rollback compatibility.
- MUST: Preserve the approved decision set unchanged.
- MUST NOT: Add monthly aggregation, automatic coaching delivery, automatic activation, historical fabrication, new infrastructure, or generic Telegram routes.
- MUST NOT: mutate v1.0-v1.3.2 receipts, live ledgers during automated QA, or unrelated dirty-worktree bytes.
- PATTERN: Follow `PILOT_RUNBOOK.md:146-171,195-211` for reservation, uncertainty, restart, and rollback.
- PATTERN: Follow `store.py:70-111,323-356` for canonical lineage and lock-scoped checks.
- TOOL: Use `lsp_find_references` for `build_due_customer_tasks`, `current_terminal_morning_response`, `build_weekly_summary`, `DualCoachReviewService`, and `NutritionCoachingConfig` before assigning edits.

### QA/Acceptance Criteria Directives

- MUST: Create `dualcoach/profile/tests/test_weekly_operations.py` and `tests/gateway/test_nutricoach_weekly_operations.py`.
- MUST: Use injected clocks, multiprocessing barriers, and awaited exact events; no sleeps or timing polling.
- MUST: Run from `/home/cube/projects/richard/.worktrees/nutricoach-v140-impl`:

```text
.venv/bin/python -m pytest -q \
  dualcoach/profile/tests/test_weekly_operations.py \
  dualcoach/profile/tests/test_customer_schedule.py \
  dualcoach/profile/tests/test_customer_reporting.py
```

Expected: exit `0`, no failures/errors.

```text
.venv/bin/python -m pytest -q \
  tests/gateway/test_nutricoach_weekly_operations.py \
  tests/gateway/test_telegram_physique_checkin.py \
  -k "weekly_operations or dual_coach_reminder or dual_coach_review_runtime"
```

Expected: exit `0`, no failures/errors.

- MUST: Add an agent-executable verifier:

```text
.venv/bin/python scripts/verify_nutricoach_v140_weekly_operations.py --mode synthetic-seven-day
```

Expected JSON assertions:

```json
{
  "status": "PASS",
  "period": ["2026-08-17", "2026-08-23"],
  "submitted_days": 4,
  "late_submitted_days": 1,
  "missed_days": 2,
  "completed_days": 5,
  "adherence_percent": 71.43,
  "reminder_customer_calls": 4,
  "duplicate_reminder_calls": 0,
  "topic59_logical_cards": 7,
  "monthly_tasks": 0,
  "automatic_coaching_customer_calls": 0,
  "privacy_leaks": 0,
  "monday_owner_cards": 1
}
```

- MUST: Include edge proofs for 19:59/20:00, 22:59/23:00, check-in/cutoff concurrency, correction after cutoff, reminder unknown, card send/edit unknown, restart after every durable transition, stale authority, wrong topic/user, duplicate cron ticks, and corrupted/torn rows.
- MUST: Prove default-OFF produces zero new v1.4 rows, reminders, Topic-59 calls, or activation changes while preserving v1.3.2 behavior.
- MUST: Prove synthetic qualification seal is a mandatory predecessor of live-observation authorization.
- MUST: Rehearse upgrade and rollback only on an isolated profile copy; assert pre-v1.4 event/sequence/receipt byte digests remain unchanged and v1.3.2 ignores preserved v1.4 sidecars.
- MUST: Store evidence at:
  - `.omo/evidence/v1.4.0-weekly-operations/default-off.json`
  - `.omo/evidence/v1.4.0-weekly-operations/synthetic-seven-day.json`
  - `.omo/evidence/v1.4.0-weekly-operations/failure-matrix.json`
  - `.omo/evidence/v1.4.0-weekly-operations/privacy.json`
  - `.omo/evidence/v1.4.0-weekly-operations/migration-rollback.json`
  - `.omo/evidence/v1.4.0-weekly-operations/bounded-live-observation.json`
- MUST: Make F3 agent-executed local real-handler QA; F5 must independently audit candidate provenance, privacy, migration/rollback, synthetic-before-live ordering, and cleanup.
- MUST NOT: Require a user to click, visually inspect, wait seven days during a test command, or manually validate output. The live receipt audit may read owner-produced immutable evidence but must not trigger live actions.

## Recommended Approach

First make the plan authoritative: pin the v1.3.2 candidate, adopt a rollback-safe operational sidecar and typed default-OFF timing config, then specify the complete status/reminder/card state machines. Qualify the full seven-day path with injected time and fake Telegram before allowing a separately owner-gated, one-customer live observation.


I read this as final synthesis - I’ll provide the concise blocker/default ledger from collected evidence only.

## Intent Classification
**Type**: Research
**Confidence**: High

## Blocker / Default Ledger

| Priority | Blocking gap | Concrete evidence | Decision-complete? | Reversible default / unsafe owner decision |
|---|---|---|---|---|
| P0 | **Plan is still a skeleton and approval metadata conflicts with “approved.”** | `.omo/plans/nutricoach-v140-weekly-operations.md:1-44`; `.omo/drafts/nutricoach-v140-weekly-operations.md:1-22,89-94` | **Blocked** | Complete scope, todos, dependencies, acceptance criteria, digest, and review metadata before implementation. |
| P0 | **Execution authority is ambiguous.** Draft-relative source paths are absent here; production runs an installed v1.3.2 wheel, while qualification lives in another worktree. | `/home/cube/projects/richard/.worktrees/nutricoach-v111-impl/.omo/evidence/v1.3.2-daily-checkin/qualification.json`; `/home/cube/.config/systemd/user/hermes-gateway-dualcoachtest.service:7-14`; `...service.d/task26-authority.conf:1-6` | **Blocked** | Pin candidate `6c9c4394...`, then use a fresh `/home/cube/projects/richard/.worktrees/nutricoach-v140-impl`. Preserve mandated Python/Hermes/Pydantic/JSONL/Telegram stack; no new DB/plugin/upstream work. |
| P0 | **Default-OFF boundary is undefined against active v1.3.2 scheduling.** Nutrition coaching, cron, and existing weekly work are already enabled. | `/home/cube/.hermes/profiles/dualcoachtest/config.yaml:641-681`; `cron/jobs.json:1-27`; active `checkin_cli/customer_schedule.py:208-246` | **Blocked** | Add typed `weekly_operations.enabled: false`, gating only new v1.4 effects. Preserve existing v1.3.2 daily launcher and owner-weekly behavior. |
| P0 | **Current config cannot express recurring 20:00 reminder and 23:00 cutoff.** Reminder becomes eligible after `daily_time`; gateway accepts only an absolute deadline. | `checkin_cli/customer_schedule.py:208-246`; `gateway/platforms/telegram.py:9878-9900`; `gateway/platforms/nutrition_coaching_config.py:55-178` | **Blocked** | Typed KST fields `reminder_time=20:00:00`, `missed_cutoff_time=23:00:00`; reject naive/absolute deadlines and invalid ordering. |
| P0 | **Live NutriCoach submissions are invisible to current reminder correlation.** Terminal detection requires a `MORNING_CHECKIN` root, while `nutrition_daily` emits `NUTRITION_CHECKIN`. | `checkin_cli/store.py:70-111`; `checkin_cli/wizard.py:1008-1015`; live draft `data/customers/pilot_20260820_01/wizard/drafts/a594ba00240399c36f366e83fff8e405.json` | **Blocked** | Treat accepted `NUTRITION_CHECKIN` correction lineages as NutriCoach responses; retain morning compatibility. |
| P0 | **`submitted`/`missed`/`late_submitted` semantics and cutoff races are unspecified.** Strict canonical schemas contain no such event types. | `checkin_cli/models.py:31-56,864-967`; `contracts/checkin-event.schema.json:22-47`; draft `:59-65` | **Blocked** | Use a rollback-safe append-only v1.4 sidecar pinned to canonical sequence/digest. By 23:00 => `submitted`; absent at cutoff => `missed`; first valid submission after cutoff => `late_submitted`. Corrections preserve original timeliness. |
| P0 | **Seven-day operation conflicts with weekday-only adherence.** | v1.3.2 `qualification.json` (`daily_checkin_days=all_calendar_days`); `customer_reporting.py:409-450,617-623` | **Blocked** | Weekly operations use exactly seven calendar days. Do not alter the existing weekday-based 28-day KPI helper. |
| P0 | **Reminder success and factual absence are conflated.** Review currently requires `sent_audited`; known failure may be retried under new approval. | `customer_schedule.py:1520-1690`; `tests/test_customer_schedule.py:241-370`; `customer_coaching.py:639-672` | **Blocked** | Record `missed` independently at 23:00. Create “reminded/no response” only for `sent_audited`; otherwise create a delivery incident. Never replace a same-day v1.4 reminder attempt. |
| P0 | **Literal exactly-once Telegram visibility is unsupported.** Current contract is provider-at-most-once with terminal uncertainty; Topic-59 publication claims before I/O and can lose a card after a crash. | `PILOT_RUNBOOK.md:146-171`; `nutrition_coaching.py:21200-21251`; `telegram.py:5180-5230` | **Blocked** | Define exactly-once as one logical reservation and at most one provider call, ending in receipt or terminal unknown. **Unsafe owner decision:** literal one-visible-message guarantee requires a different provider contract. |
| P0 | **Existing Topic-59 service cannot provide one mutable daily card.** It supports only risk/reminder event cards, not `(customer, day)` bindings or state edits. | `gateway/platforms/nutrition_coaching.py:21029-21251`; `gateway/platforms/telegram.py:5180-5230` | **Blocked** | Add a separate status projector with deterministic customer/day key, send/edit receipts, terminal unknown state, and no approval buttons. |
| P1 | **“No automatic customer delivery” conflicts with the automatic reminder.** | Draft `:43,59-65,73-75`; live `data/scheduled-deliveries.jsonl:1-4` | **Blocked** | Define prohibition as no automatic coaching/plan/weekly-summary delivery. The approved static reminder is the sole new operational exception; existing launchers remain baseline. |
| P1 | **Weekly AI grounding and failure behavior are undefined.** Current weekly source is deterministic, not a specified knowledge-grounded AI pipeline. | `customer_reporting.py:115-166`; `gateway/platforms/nutrition_coaching.py:3831-3890`; `HANDOFF.md:22-43` | **Blocked** | Code locks all facts, numbers, decisions, and actions. AI explains only approved source fields; invalid/model-outage output falls back to deterministic Korean text. Owner DM remains authoritative. |
| P1 | **Migration, downgrade, and crash recovery are absent.** Adding strict canonical types would break v1.3.2 readers. | `models.py:31-56`; v1.3.2 `deployment-receipt.json:43-57`; `store.py:460-565`; `PILOT_RUNBOOK.md:195-203` | **Blocked** | Separate sidecar, feature OFF during install, no backfill, immutable pre/post digests, crash injection at every append/fsync/provider boundary, trusted snapshot rollback, and v1.3.2 reader proof. |
| P1 | **Privacy/compliance approval is unproven.** Existing consent is `privacy-v1`; global PII redaction is false; new staff-room processing and sidecars are not inventoried. | live `config.yaml:306-307`; registry consent around `:250-275`; `PILOT_RUNBOOK.md:67-94,203-228` | **Live blocked** | Closed card whitelist only; no customer name/address/raw values. Add sidecars to retention/deletion/backup inventory. **Unsafe owner/legal decision:** approve Topic-59 visibility, reminder purpose, AI processing, provider terms, and retention before live enablement. |
| P1 | **Budget and scale are unspecified.** Current proof surface is one enabled customer, one-minute scheduler, and 16-card drain limit. | live registry `:250-275`; `cron/jobs.json:1-27`; `telegram.py:5180-5228` | **Closed by default** | Exactly one live customer for seven days, no load redesign, no new paid service, zero network in synthetic QA. **Owner decision:** weekly-AI call/spend cap before live. |
| P1 | **Dirty-worktree isolation is missing.** | `HANDOFF.md:160-181`; `.omo/evidence/dualcoach-task-19-evidence.md:81-89` | **Blocked** | Fresh isolated worktree; baseline status digest; no reset, stash, clean, rebase, unrelated commit, or upstream PR. |
| P1 | **QA is non-executable and internally inconsistent.** Draft requires F1-F5; plan has F1-F4 and “Real manual QA.” | Draft `:73-76`; plan `:20-44` | **Blocked** | Add F5 provenance/privacy/migration audit. F3 becomes agent-driven fake-Telegram real-handler QA. Live actions remain owner gates; agents only validate immutable receipts. |
| P2 | **Monthly scope could creep into schema cleanup.** Legacy `monthly_day` remains required although monthly scheduling is dormant. | `customer_schedule.py:17-19,208-246`; `tests/test_customer_schedule.py:196-207` | **Not blocked** | Preserve legacy fields; assert zero monthly tasks, rows, or messages. Do not redesign/remove monthly schema. |
| P2 | **Live observation has no start authority or abort criteria.** Existing customer and scheduler are active. | live registry `:250-275`; `cron/jobs.json:1-27`; draft `:44-45,73-76` | **Live blocked** | Owner chooses the seven-day start only after synthetic seal, legal, budget, migration, and rollback gates. Abort on privacy leak, duplicate, unknown delivery, corruption, or authority drift. |

## Required Agent-Executable Acceptance

1. **Default OFF:** zero new v1.4 rows, reminders, Topic-59 calls, monthly work, or activation changes.
2. **Synthetic week:** `2026-08-17` through `2026-08-23`; final counts:
   - submitted `4`
   - late submitted `1`
   - missed `2`
   - completed `5/7`
   - adherence `71.43%`
   - reminders `4`, duplicate calls `0`
   - logical Topic-59 cards `7`
   - Monday owner cards `1`
   - automatic coaching customer calls `0`
   - privacy leaks `0`
3. **Edges:** 19:59/20:00, 22:59/23:00, cutoff/check-in race, late correction, reminder/card unknown, restart at every durable boundary, stale authority, wrong topic/user, duplicate ticks, torn/interior corruption.
4. **Migration/rollback:** byte-identical v1.3.2 authority and receipts; v1.3.2 reads successfully with preserved v1.4 sidecar; provider calls remain zero during rehearsal.
5. **Ordering:** synthetic seal must cryptographically precede live-observation authorization.

No monthly aggregation, automatic coaching delivery, automatic activation, fabricated history, new database, generic route, or unrelated refactor belongs in v1.4.0.