{"event":"repair-passed","plan":".omo/plans/dualcoach-production-readiness.md","task":"6. Add privacy readiness and migration gates","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor":"dualcoach-privacy-gates-deep","task_id":"st_019fe06b","verdict":"PASS","candidate_digest":"sha256:d0ac11ce235ec8b9cacac504f8446919087c49280efbeb41f2e6c62c6344adbd","artifact":["gateway/platforms/telegram_activation_readiness.py","gateway/platforms/telegram_room_bootstrap_cutover.py","scripts/nutrition-room-bootstrap","tests/gateway/test_telegram_activation_readiness.py","tests/gateway/test_telegram_room_bootstrap_cutover.py","agent://st_019fe06b"],"closed_findings":["RECOVERY_PROVIDER_RECEIPT_NOT_SEMANTICALLY_VALIDATED","RECOVERY_GENERATION_NOT_PHASE_SPECIFIC","SEMANTIC_BRANCH_TEST_GAPS","ACTIVE_LEDGER_DISABLED_TARGET_INCONSISTENCY"],"evidence":{"failing_first":"6 reproduced failures","focused_suite":"50 passed","recovery_probes":"6 passed","ruff":"PASS","basedpyright":"0 errors, 0 warnings, 0 notes","content_validation":"AST, whitespace, final newline, and git diff check PASS","provider_envelope":"complete observation embedded and semantically revalidated","phase_generation":"exact by target_activated versus complete recovery","rollback":"invalid authority disables target and restores AWAITING_ACTIVATION"},"cleanup":{"status":"pass","resources":"no .orig/.rej/temp artifacts; existing .pytest_cache remains; 91 unrelated dirty entries untouched; unrelated bootstrap ledger restored unchanged"},"residual":{"external_dependency":"/home/cube/.hermes/profiles/dualcoachtest/workspace/checkin_cli confirmed present"},"next":"fresh independent automated, manual, and privacy-correctness verification against final digest"}
{"event":"verification-failed","plan":".omo/plans/dualcoach-production-readiness.md","task":"6. Add privacy readiness and migration gates","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","verifier":"dualcoach-task6-final-automated-verifier","task_id":"st_019fe0a0","verdict":"FAIL","candidate_digest":"sha256:d0ac11ce235ec8b9cacac504f8446919087c49280efbeb41f2e6c62c6344adbd","artifact":["agent://st_019fe0a0"],"evidence":{"digest":"MATCH","focused_suite":"50 passed","ruff":"PASS","basedpyright":"0 errors, 504 warnings, exit 1","ast_content":"all five candidates parse, no digest drift","coverage":"all prior Specification 6 and recovery semantic branches confirmed","bootstrap_ledger_digest":"6faaadab3067bd389ee110d79e8f29eef60c442b76aa405dfd6c417bccb3830a unchanged","external_dependency":"dualcoachtest checkin_cli present"},"findings":[{"severity":"high","code":"BASEDPYRIGHT_WARNINGS","detail":"strict candidate typecheck exits 1 with 504 warnings despite zero errors"}],"cleanup":{"status":"pass","resources":"cache-disabled tests, no edits; existing dirty state preserved"},"next":"wait for manual and correctness receipts, then eliminate caused candidate warnings without suppressions and rerun final verification"}
{"event":"verification-passed","plan":".omo/plans/dualcoach-production-readiness.md","task":"6. Add privacy readiness and migration gates","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","verifier":"dualcoach-task6-final-manual-verifier","task_id":"st_019fe0a1","verdict":"PASS","candidate_digest":"sha256:d0ac11ce235ec8b9cacac504f8446919087c49280efbeb41f2e6c62c6344adbd","artifact":["agent://st_019fe0a1"],"evidence":{"cli":"valid provider receipt constructed; omission rejected; tamper rejected","safe":"preflight ready generation 11; execute ACTIVE generation 12; reconciled replay PASS","invalid_provider_provenance":"READINESS_RECEIPT_UNAVAILABLE, enabled empty, AWAITING_ACTIVATION","target_activated_wrong_generation":"READINESS_RECEIPT_UNAVAILABLE, enabled empty, AWAITING_ACTIVATION","complete_wrong_generation":"READINESS_RECEIPT_UNAVAILABLE, enabled empty, AWAITING_ACTIVATION","recovery_failure":"target disabled and session AWAITING_ACTIVATION","customer_in_staff":"CUSTOMER_IN_STAFF_GROUP; target remained disabled","legacy_enabled":"missing/stale activation receipt; target remained disabled"},"cleanup":{"status":"pass","resources":"temporary driver directories removed; no repo, .omo, Telegram, release, or real-customer effects"},"next":"wait for final correctness receipt; then repair strict BasedPyright warnings"}
{"event":"verification-failed","plan":".omo/plans/dualcoach-production-readiness.md","task":"6. Add privacy readiness and migration gates","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","verifier":"dualcoach-task6-final-correctness-reviewer","task_id":"st_019fe0a2","verdict":"FAIL","candidate_digest":"sha256:d0ac11ce235ec8b9cacac504f8446919087c49280efbeb41f2e6c62c6344adbd","artifact":["agent://st_019fe0a2"],"findings":[{"severity":"high","code":"ACTIVE_OWNER_ACCEPTS_NO_READINESS_PROOF","detail":"TelegramRoomBootstrapActivation.complete directly reaches sole ACTIVE ledger edge without durable readiness authority"},{"severity":"high","code":"ROLLBACK_UNRECOVERABLE_AWAITING_ACTIVATION","detail":"receipt failure disables target and rewrites ACTIVE to AWAITING_ACTIVATION, but normal retry requires a former-customer receipt that is no longer current"},{"severity":"medium","code":"PROVIDER_PAYLOAD_TEST_BRANCH_MISSED","detail":"provider-payload test recomputes only outer digest and fails nested integrity before semantic completeness branch"}],"evidence":{"digest":"MATCH","direct_active_probe":"no readiness receipt before or after; session reached ACTIVE","rollback_probe":"enabled empty, state AWAITING_ACTIVATION generation 13; fresh retry failed with CustomerAdminError","provider_semantic":"product validator correct when both nested and outer digests are re-signed, but one named test does not reach branch","focused_suite":"50 passed","regression_suites":"44 passed","ruff":"PASS","basedpyright":"0 errors, 0 warnings, 0 notes","content_checks":"PASS"},"cleanup":{"status":"pass","resources":"read-only audit; temp directories removed; 96 pre-existing dirty entries untouched"},"residual":{"candidate_scope":"five-file digest excludes direct activation/store dependencies that determine ACTIVE invariant","provider_attestation":"trusted local custody and digest integrity, not Telegram cryptographic attestation","receipt_hardening":"parent-chain symlink rejection and directory fsync absent but fail-closed"},"next":"require typed readiness proof at TelegramRoomBootstrapActivation.complete before ACTIVE edge; mark unrecoverable rollback honestly or restore canonical former customer; fix nested-and-outer semantic test; expand candidate digest to direct ACTIVE owner/tests; reconcile BasedPyright invocation discrepancy"}
{"event":"verification-passed","plan":".omo/plans/dualcoach-production-readiness.md","task":"6. Add privacy readiness and migration gates","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor_evidence":["agent://st_019fe06b","agent://st_019fe0c5"],"verifiers":["agent://st_019fe0da","agent://st_019fe0db","agent://st_019fe0dc"],"verdict":"PASS","candidate_digest":"sha256:2b6807d47ce61c2f7fc96561b58594230a4ad12c51bcca35243be6792c97b85f","candidate_files":["gateway/platforms/telegram_activation_readiness.py","gateway/platforms/telegram_room_bootstrap_cutover.py","gateway/platforms/telegram_room_bootstrap_activation.py","scripts/nutrition-room-bootstrap","tests/gateway/test_telegram_activation_readiness.py","tests/gateway/test_telegram_room_bootstrap_cutover.py","tests/gateway/test_telegram_room_bootstrap_activation.py"],"evidence":{"strict_basedpyright":"0 errors, 0 warnings, 0 notes","focused_suite":"74 passed","behavior_matrix":"12 passed","ruff":"PASS","build":"isolated wheel and sdist PASS","cli":"mode 755; help rc=0; isolated status rc=0; invalid input rc=2","privacy_matrix":["LEGACY_SHARED_TOPIC rejected non-mutating","CUSTOMER_DM_MISMATCH rejected non-mutating","CUSTOMER_IN_STAFF_GROUP rejected non-mutating"],"rollback_scope":"invalid target, stale generation, and matching nonexistent current/confirmation selectors are exact non-mutating; rollback starts only after complete authenticated plan and canonical ownership","delayed_recovery":"fresh same-generation authority after receipt expiry reaches ACTIVE","authority_loss":"post-enable invalid authority disables target and transitions terminal FAILED; retry denied","manual_surface":"14 isolated CLI runs under strace, zero network syscalls, no Telegram or customer effects","redaction":"PASS","architecture":"STRICT PASS; no HIGH, MEDIUM, or LOW findings","integrity":"AST, UTF-8, final newline, NUL, trailing whitespace, suppression scan, git diff --check PASS","lsp":"not run because sibling-workspace request-root restriction; exact strict BasedPyright passed"},"cleanup":{"temporary_profiles":"removed","temporary_strict_configs":"removed","build_artifacts":"removed","task_temp_roots":"none","repository_or_omo_touched_by_verifiers":false},"residual_risks":["focused tests depend on mutable profile-local checkin_cli outside candidate digest","runtime-validated underscore capabilities are internal boundaries, not malicious in-process defenses"],"commit":"none; user prohibited commits"}
{"event":"verification-failed","plan":".omo/plans/dualcoach-production-readiness.md","task":"7. Define generation state machine and schemas","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","verifier":"dualcoach-task7-type-delta-v1","task_id":"st_019fe1cf","verdict":"FAIL","candidate_digest":"sha256:bce2fc1f64f5c799eb77b346d6115dad1e833ecced28bc78c9f171ecf2ce43bf","commands":["uv run ty check gateway/platforms/nutrition_coaching.py gateway/platforms/telegram.py","git diff -U0 changed-region intersection"],"evidence":{"whole_file_unsuppressed_diagnostics":1114,"changed_region_intersections":11,"intersections":["gateway/platforms/telegram.py:10537 invalid-argument-type","gateway/platforms/telegram.py:10540 unresolved-attribute","gateway/platforms/telegram.py:10547 unresolved-attribute","gateway/platforms/telegram.py:10961 unresolved-attribute","gateway/platforms/telegram.py:10961 invalid-argument-type","gateway/platforms/telegram.py:11014 unresolved-attribute","gateway/platforms/telegram.py:11052 unresolved-attribute","gateway/platforms/telegram.py:11052 invalid-argument-type","gateway/platforms/telegram.py:11109 unresolved-attribute","gateway/platforms/telegram.py:11282 invalid-argument-type","gateway/platforms/telegram.py:13590 invalid-argument-type"],"telegram_10537_classification":"Task 7 diff, not unrelated pre-existing debt"},"cleanup":{"status":"pass","resources":"read-only verifier; no edits, suppressions, fixes, external effects, or retained temporary resources"},"next":"eliminate all changed-region diagnostics without suppressions and reverify"}
{"event":"repair-dispatched","plan":".omo/plans/dualcoach-production-readiness.md","task":"7. Define generation state machine and schemas","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor":"dualcoach-task7-type-remediation-v1","task_id":"st_019fe1d4","category":"quick","skills":["programming"],"candidate_digest_before":"sha256:bce2fc1f64f5c799eb77b346d6115dad1e833ecced28bc78c9f171ecf2ce43bf","scope":"minimal behavior-preserving fixes for the 11 Task 7 changed-region ty diagnostics","constraints":["no suppressions","no broad cleanup","preserve unrelated dirty worktree","no commit","no push","no reset","no stash","no clean","no release activation","no provider or Telegram calls","no customer delivery"],"required_evidence":["zero changed-region ty intersections","focused Task 7 test matrix","Ruff","py_compile","git diff --check","candidate hashes and digest","non-touch statement","cleanup receipt"]}
{"event":"repair-cancelled","plan":".omo/plans/dualcoach-production-readiness.md","task":"7. Define generation state machine and schemas","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor":"dualcoach-task7-type-remediation-v1","task_id":"st_019fe1d4","reason":"No patch or verification progress after explicit convergence steer; transcript remained at protocol reconnaissance.","cleanup":{"status":"pass","candidate_bytes":"unchanged"}}
{"event":"repair-cancelled","plan":".omo/plans/dualcoach-production-readiness.md","task":"7. Define generation state machine and schemas","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor":"dualcoach-task7-type-remediation-v2","task_id":"st_019fe1d7","reason":"No patch or exact blocker after inspection cutoff; transcript remained in repeated reads and diagnostics.","cleanup":{"status":"pass","candidate_bytes":"unchanged"}}
{"event":"repair-cancelled","plan":".omo/plans/dualcoach-production-readiness.md","task":"7. Define generation state machine and schemas","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor":"dualcoach-task7-type-remediation-v3","task_id":"st_019fe1da","reason":"Third materially different prescribed remediation attempt exhausted bounded inspection without a patch or exact blocker.","evidence":{"exact_concise_intersections":31,"grouped_intersections":11,"candidate_digest":"sha256:bce2fc1f64f5c799eb77b346d6115dad1e833ecced28bc78c9f171ecf2ce43bf","candidate_hashes":{"gateway/platforms/nutrition_coaching.py":"e5f92fb574800ebe0847a81e68e6fca4ce5cce75b49ef9d53f3f35cd1b4755dd","gateway/platforms/telegram.py":"b8ff10d47b486fd04360606e3e1694a2fdcb852bfd8745c00b04de5111f05cd5","tests/gateway/test_nutrition_coaching.py":"bec3de37af0485c3f44adf3010339e89f5999dc632ce97641889351bbfbcbe1d","tests/gateway/test_telegram_physique_checkin.py":"cfbdc033bdea7f09b97f37c0069bc60c2f8f65f252d3d647686c8493cd28c576","tests/gateway/test_task7_generation_hardening.py":"6f3c064a07418b4b4290f91abe3093d7636601cfad2a6342efe61cc8e962c51f"}},"cleanup":{"status":"pass","candidate_bytes":"unchanged","live_children":"none"},"blocking_condition":"The approved objective requires every implementation unit to be delegated, while the mandatory three-attempt recovery limit now requires stopping after three delegated workers produced no patch."}
{"event":"scope-directive-recorded","plan":".omo/plans/dualcoach-production-readiness.md","task":"minimum-operation v1 execution scope","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","commands":[],"artifact":[".omo/plans/dualcoach-production-readiness.md#minimum-operation-v1-scope-directive"],"decision":{"purpose":"freeze the existing DualCoach lifecycle as the minimum operational v1 baseline","not_authorized":["new customer-facing features","speculative abstractions","convenience expansion","future-feature scaffolding"],"required_scope":["existing acceptance criteria","privacy invariants","durable state","restart recovery","explicit approval","exactly-once delivery","observability","truthful cleanup"],"future_change_rule":"new features must update affected state transitions, runbooks, focused tests, candidate manifest, and release evidence"},"adversarial_classes":{"dirty_worktree":"scope-only evidence edit; product worktree untouched","stale_state":"directive written into the active approved plan and durable ledger","misleading_success_output":"directive does not mark any checkbox complete or weaken any gate","malformed_input":"not applicable: no external input parser changed","prompt_injection":"not applicable: direct user scope decision only","cancel_resume":"PASS: future continuations read the plan and ledger first","hung_or_long_commands":"not applicable: bounded evidence edit","flaky_tests":"not applicable: no test behavior changed","repeated_interruptions":"PASS: direction survives compaction and session continuation"},"cleanup":{"status":"pass","resources":"no product files, processes, credentials, customers, runtime state, or QA assets created"}}
{"event":"scope-directive-expanded","plan":".omo/plans/dualcoach-production-readiness.md","task":"minimum-operation v1 execution scope","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","commands":[],"artifact":[".omo/plans/dualcoach-production-readiness.md#per-checkbox-execution-rule",".omo/plans/dualcoach-production-readiness.md#v1-completion-and-pilot-handoff"],"decision":{"per_checkbox":["inventory reusable live implementation and evidence","name the exact unsatisfied v1 acceptance condition","apply only the smallest owning-seam delta","record optional/refactor/future work rejected from scope"],"already_satisfied":"verify without product edits","evidence_reuse":"reuse only when exact candidate and covered behavior remain unchanged","worker_boundary":"one bounded goal and one deliverable; repeated broad reconnaissance is not progress","goal_meaning":"ready for a bounded real-customer pilot, not automatic activation or delivery","post_plan":"real-customer activation requires separate explicit go/no-go and ownership"},"adversarial_classes":{"dirty_worktree":"plan and ledger only; product worktree untouched","stale_state":"future workers must inventory the live candidate before editing","misleading_success_output":"goal completion is explicitly separated from real-customer activation","malformed_input":"not applicable: no parser changed","prompt_injection":"not applicable: direct user scope decision only","cancel_resume":"PASS: detailed rules persist in authoritative plan and ledger","hung_or_long_commands":"bounded worker rule recorded","flaky_tests":"evidence reuse is candidate- and coverage-bound","repeated_interruptions":"PASS: per-checkbox decisions and pilot handoff survive continuation"},"cleanup":{"status":"pass","resources":"no product files, processes, credentials, customers, runtime state, or QA assets created"}}
{"event":"scope-inheritance-recorded","plan":".omo/plans/dualcoach-production-readiness.md","task":"minimum-operation v1 execution scope","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","commands":[],"artifact":[".omo/plans/dualcoach-production-readiness.md#todos",".omo/plans/dualcoach-production-readiness.md#final-verification-wave"],"decision":{"todos":"every Task 1-27 inherits execution constraints, minimum-operation v1 scope, and per-checkbox execution rules","final_verification":"every F1-F5 verifier judges the exact fixed v1 candidate and cannot authorize automatic activation, delivery, or feature expansion","specification_meaning":"required operating behavior only; not authorization for additional customer capability","worker_receipt":"must distinguish reused behavior, exact unsatisfied gap, minimal delta, and rejected extras"},"adversarial_classes":{"dirty_worktree":"plan and ledger only; product worktree untouched","stale_state":"inheritance is repeated at both execution entry points","misleading_success_output":"PASS is explicitly limited to bounded-pilot readiness","malformed_input":"not applicable: no runtime input changed","prompt_injection":"not applicable: direct user governance decision","cancel_resume":"PASS: partial-section readers see the directive","hung_or_long_commands":"bounded execution rule remains inherited","flaky_tests":"no test behavior changed","repeated_interruptions":"PASS: directive survives full-plan and section-local continuation"},"cleanup":{"status":"pass","resources":"no product files, runtime state, credentials, customers, or processes touched"}}
{"event":"verification-passed","plan":".omo/plans/dualcoach-production-readiness.md","task":"7. Define generation state machine and schemas","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor":"st_019fe1e6","verifiers":["st_019fe1ed","st_019fe1ee","st_019fe1ef"],"verdict":"PASS","candidate_digest":"sha256:216000505adcd309ac4dfe1a18fd33c669eb997e57fdc6105bafe9fefb7cb69f","artifact":[".omo/evidence/dualcoach-task-7.md","gateway/platforms/nutrition_coaching.py","gateway/platforms/telegram.py","tests/gateway/test_nutrition_coaching.py","tests/gateway/test_telegram_physique_checkin.py","tests/gateway/test_task7_generation_hardening.py"],"evidence":{"failing_first":"11 grouped changed-region ty diagnostics from 1114 total","final_type_delta":"0 intersections; 1073 unrelated whole-file diagnostics documented","focused_suite":"268 passed","additional_hermetic_suite":"145 passed","ruff":"PASS","py_compile":"PASS","diff_check":"PASS","manual_surface":"owner review, callback, onboarding, nc1, stale receipt, and restart paths exercised with zero real network/provider/Telegram calls and zero customer deliveries","adversarial":"CONFIRMED on exact final hash and digest","architecture":"PASS from Task 7 state-machine re-audit","suppression_scan":"no executor-added Any, cast, ignore, or suppression"},"scope":{"reused":["durable journal","authority root and marker","CAS and lineage","retry and claim semantics","generation/delivery contracts","transport receipts","restart reconciliation","callback separation"],"new_delta":["accurate local protocols","Bot and identifier narrowing","explicit owner-review send branches","payload and markup narrowing","type-only CallbackQuery import"],"rejected":["customer-facing features","speculative abstractions","convenience expansion","future scaffolding","unrelated type-debt cleanup"]},"cleanup":{"status":"PASS","temporary_helpers":"removed","temporary_drivers":"removed","network_calls":0,"customer_actions":0,"unrelated_dirty_worktree":"preserved"},"residuals":["1073 unrelated whole-file ty diagnostics","Telegram Bot API lacks provider idempotency and authoritative receipt lookup; at-most-once dispatch plus durable reconciliation remains the defensible external guarantee"],"commit":"none; user prohibited commits"}
{"event":"verification-passed","plan":".omo/plans/dualcoach-production-readiness.md","task":"8. Enqueue generation atomically with check-in completion","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor":"st_019fe1fc","verifiers":["st_019fe206","st_019fe207","st_019fe208"],"verdict":"PASS","candidate_digest":"sha256:c849dffdcf2570eb051d62d6f8bca32bac8d3d22924c49910ae0aa6e3d672550","artifact":[".omo/evidence/dualcoach-task-8.md",".omo/evidence/dualcoach-candidate-manifest.json",".omo/evidence/dualcoach-candidate-manifest.md","gateway/platforms/nutrition_coaching.py","tests/gateway/test_nutrition_coaching.py"],"evidence":{"failing_first":"post-finalization request-write crash left no generation history","crash_before_commit":"no finalized event, request, generation, provider work, or delivery","crash_after_commit":"restart reconciles prepared to committed with exactly one generation_pending job","duplicate_and_stale":"rejected with stable request and journal bytes","malformed_journal":"fails closed without side effect","type_delta":"0 Task 8-owned intersections","focused_tests":"PASS; includes 122 nutrition, 114 Telegram physique, and 37 Task 7 hardening receipts","ruff":"PASS","py_compile":"PASS","diff_check":"PASS","manual_surface":"actual coordinator restart and replay paths confirmed with zero provider and delivery calls","adversarial":"CONFIRMED on exact final product hash and manifest digest","provenance":"JSON, Markdown header, Markdown verification, and live 67-path digest agree"},"scope":{"reused":["check-in event persistence","deduplication","Task 7 state machine","digest chaining","locks","atomic replacement","approval/delivery separation"],"new_delta":["prepared/committed finalization journal","restart reconciliation","deterministic crash tests","exact journal and callback type narrowing"],"rejected":["worker redesign","speculative abstraction","customer-facing feature work","future scaffolding","unrelated refactor","whole-file type cleanup"]},"cleanup":{"status":"PASS","temporary_files":0,"runtime_artifacts":0,"network_calls":0,"customer_actions":0,"unrelated_dirty_worktree":"preserved"},"commit":"none; user prohibited commits"}
{"event":"verification-passed","plan":".omo/plans/dualcoach-production-readiness.md","task":"9. Implement the resumable generation worker","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor":"st_019fe21e","verifiers":["st_019fe22d","st_019fe22e","st_019fe22f"],"verdict":"PASS","candidate_digest":"sha256:4e7b57ef1bdee807471251486be24744efb689665d7fc6849cb09ccf2fc624fe","artifact":[".omo/evidence/dualcoach-task-9.md",".omo/evidence/dualcoach-candidate-manifest.json",".omo/evidence/dualcoach-candidate-manifest.md","gateway/platforms/nutrition_coaching.py","tests/gateway/test_nutrition_coaching.py"],"evidence":{"failing_first":["DraftGenerationWorker missing","stale worker persisted draft after lease reclaim"],"success":"one draft and one card update","correction":"at most one; invalid output creates no draft","authentication":"generation_failed with provider_authentication retry action","restart":"first expired lease reclaims; second expiry terminal","stale_claim_cas":"stale write/completion rejected without poisoning fresh claim","receipt_retention":"no manual deletion","log_privacy":"IDs and gate names only; raw customer/draft text absent","customer_delivery":0,"focused_suite":"9 passed","owning_domain":"168 passed","ruff":"PASS","py_compile":"PASS","diff_check":"PASS","symbol_type_audit":"0 Task 9-owned findings","manual_surface":"actual coordinator/worker two-claim race confirmed with fake providers and zero network"},"scope":{"reused":["Task 7 states and CAS","retry budget and receipts","Task 8 atomic pending enqueue","grounded request builder","schema and semantic validation","draft persistence","callback/provider separation"],"new_delta":["lease-bearing worker","bounded correction","retryable auth failure","card callback","privacy-safe logs","atomic persistence claim CAS","stale-worker regression"],"rejected":["Task 10 startup preflight","card UX","delivery behavior","new framework","customer features","speculative abstraction","future scaffolding","unrelated refactor","manual receipt cleanup"]},"cleanup":{"status":"PASS","temporary_resources":0,"network_calls":0,"customer_actions":0,"unrelated_dirty_worktree":"preserved"},"commit":"none; user prohibited commits"}
{"event":"verification-passed","plan":".omo/plans/dualcoach-production-readiness.md","task":"10. Implement provider authentication preflight","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor":"st_019fe244","verifiers":["st_019fe250","st_019fe251","st_019fe252"],"verdict":"PASS","candidate_digest":"sha256:215aafe7af1f2056bb137c1ecc2d3dc728bb0f36bb9e1933f2c32f943b1823cd","artifact":[".omo/evidence/dualcoach-task-10.md",".omo/evidence/dualcoach-candidate-manifest.json",".omo/evidence/dualcoach-candidate-manifest.md","gateway/platforms/nutrition_coaching.py","gateway/platforms/telegram.py","gateway/platforms/telegram_room_bootstrap_cutover.py","tests/gateway/test_nutrition_coaching.py","tests/gateway/test_telegram_room_bootstrap_cutover.py"],"evidence":{"credential_boundary":"Hermes auxiliary provider auth state and credential pool; Codex CLI credential does not substitute","startup":"invalid credential blocks before Telegram setup","activation":"invalid credential blocks before mutation","preclaim":"auth failure records retryable generation_failed without lease","reauth":"same adapter and same job/request resume without restart or duplication","stale_error_repair":"only exact auth-preflight marker clears; unrelated errors stay latched","secret_redaction":"sentinel absent from logs, cards, exceptions, evidence, and temp files","focused_suite":"216 passed","auxiliary_client":"223 passed","bootstrap_matrices":["83 passed","161 passed"],"ruff":"PASS","py_compile_compileall":"PASS","diff_whitespace":"PASS","changed_symbol_type_audit":"0 findings","manual_surface":"same-instance fail to fake-reauth recovery confirmed with zero network/provider/Telegram/customer delivery","adversarial":"original MEDIUM stale-readiness finding closed","provenance":"67-path JSON, Markdown, and raw-byte digest agree"},"scope":{"reused":["Hermes auxiliary client","credential pool","Task 9 retryable failure","stable request/job identity","startup activation and worker boundaries"],"new_delta":["startup preflight","activation preflight","preclaim preflight","redacted actionable status","same-instance owned-error recovery"],"rejected":["global auth framework","real OAuth/browser automation","Task 11 card UX","customer features","speculative abstraction","future scaffolding","broad refactor","credential fallback","manual job deletion"]},"cleanup":{"status":"PASS","temporary_homes":"removed","credential_values_exposed":0,"network_calls":0,"customer_actions":0,"unrelated_dirty_worktree":"preserved"},"commit":"none; user prohibited commits"}
{"event":"verification-passed","plan":".omo/plans/dualcoach-production-readiness.md","task":"11. Build asynchronous operator cards","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor":"st_019fe269","verifiers":["st_019fe280","st_019fe281","st_019fe282"],"verdict":"PASS","candidate_digest":"sha256:c03ceab287c445cb7c068eed109b8e925375bfbd9d55f0e58659dfba2fa02d43","artifact":[".omo/evidence/dualcoach-task-11.md",".omo/evidence/dualcoach-candidate-manifest.json",".omo/evidence/dualcoach-candidate-manifest.md","gateway/platforms/telegram.py","gateway/platforms/nutrition_coaching.py","gateway/platforms/telegram_nutrition_onboarding_runtime_authority.py","tests/gateway/test_telegram_nutrition_onboarding.py","tests/gateway/test_nutrition_onboarding_reconciliation.py"],"evidence":{"immediate_card":"check-in saved and generation pending","state_buttons":{"generation_failed":"retry","draft_created":"edit regenerate approve hold","approved":"send revoke","sent_audited":"none"},"callback_contract":"n3 action revision generation render identity; <=64 bytes","ack_order":"before reservation publication edit and background work","stale":"refresh and zero mutation","restart":"expired publication claim recovered and published once","second_render":"authoritative current draft edits existing card once","authority":"registry spec and AWAITING_ACTIVATION; cross-customer/malformed/wrong-role fail closed","focused_suites":["161 adaptive","96 group gating","174 generation","44 onboarding","21 reconciliation","13 card authority"],"type":"zero Task 11 product and reconciliation-test findings","ruff_compile_diff_build":"PASS","manual_surface":"actual projections/callbacks with fake Telegram; zero provider/network/customer delivery","adversarial":"ACK P2, publication recovery, render CAS, and authority repairs confirmed","provenance":"67-path JSON, Markdown, and raw-byte digest agree"},"scope":{"reused":["Task 7 durable projection","Task 8 pending enqueue","Task 9 worker callback","existing operator console","approval/send boundaries"],"new_delta":["immediate pending card","n3 callback binding","ACK-first","publication lease/release/recovery","authoritative second render","runtime authority contracts","realistic typed fixtures"],"rejected":["Task 12/13 behavior","new customer UX","generic card framework","content cache","speculative abstraction","future scaffolding","broad refactor","suppressions","fixed sleeps"]},"cleanup":{"status":"PASS","temporary_resources":0,"network_calls":0,"customer_actions":0,"unrelated_dirty_worktree":"preserved"},"residuals":["workspace import/plugin blockers for unavailable checkin_cli onboarding modules remain unrelated to Task 11 supported-path behavior"],"commit":"none; user prohibited commits"}
{"event":"verification-passed","plan":".omo/plans/dualcoach-production-readiness.md","task":"12. Separate approval from delivery","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor":"st_019fe2e6","verifiers":["st_019fe2ee","st_019fe2ef","st_019fe2f0"],"verdict":"PASS","candidate_digest":"sha256:016d2d504c5ac9f06699f064acf7959392fef6d1d8e7534bcaacfaba8b7a6922","artifact":[".omo/evidence/dualcoach-task-12.md",".omo/evidence/dualcoach-candidate-manifest.json",".omo/evidence/dualcoach-candidate-manifest.md","gateway/platforms/nutrition_coaching.py","gateway/platforms/physique_checkin.py","gateway/platforms/telegram.py","tests/gateway/test_nutrition_coaching.py","tests/gateway/test_telegram_physique_checkin.py"],"evidence":{"approval":"one immutable receipt; duplicate idempotent; zero provider/transport/customer delivery","send_revalidation":["operator authority","active customer and consent","latest approved draft revision","current route","prepared destination and text","outbox status"],"revoke":"approved to held; send blocked","partial_hold":"same-process and fresh-coordinator recovery converge one held row/projection","restart_authority":"canonical check-in snapshot reconstructed from generation event ID without bridge/cache","forgery":"predecessor/actor/digest/pins/receipt/outbox inconsistencies fail closed","concurrency":"send after durable hold creates no reservation/transport","owning_domain":"182 passed","callback_domain":"120 passed","ancillary":"240 passed","type":"zero Task 12 changed-symbol/test findings","ruff_compile_diff":"PASS","manual_surface":"actual NutritionCoachingCoordinator partial failure/restart; zero delivery","adversarial":"original hold atomicity and fresh-restart findings closed","provenance":"67-path JSON, Markdown, and raw-byte digest agree"},"scope":{"reused":["Task 7 contracts and receipts","Task 11 n3 CAS","active customer consent role route checks","existing outbox statuses"],"new_delta":["idempotent approval","approved revoke","prepared route/text validation","partial hold projection recovery","fresh restart canonical-event reconstruction"],"rejected":["Task 13 transport machinery","card UX","generic approval framework","compatibility shim","speculative abstraction","future scaffolding","broad refactor","manual receipt deletion","suppressions","fixed sleeps"]},"cleanup":{"status":"PASS","temporary_resources":0,"network_calls":0,"customer_actions":0,"candidate_drift":0,"external_noncandidate_churn":"preserved"},"commit":"none; user prohibited commits"}
{"event":"verification-passed","plan":".omo/plans/dualcoach-production-readiness.md","task":"13. Add the exactly-once delivery outbox","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor":"st_019fe326","verifiers":["st_019fe347","st_019fe348","st_019fe349"],"verdict":"PASS","candidate_digest":"sha256:8bb01091b49aef469bd3ba191186d826f9d3ce66923f216ace550dc0ca5db3fa","artifact":[".omo/evidence/dualcoach-task-13.md",".omo/evidence/dualcoach-candidate-manifest.json",".omo/evidence/dualcoach-candidate-manifest.md","gateway/platforms/nutrition_coaching.py","gateway/platforms/telegram.py","tests/gateway/test_nutrition_coaching.py","tests/gateway/test_task7_generation_hardening.py"],"evidence":{"guarantee":"at most one provider dispatch while outcome unresolved; no impossible provider-level exactly-once claim","states":["pending","unknown_provider_outcome","sent","sent_audited"],"idempotency":"customer key plus checkin revision plus approved draft revision","concurrency":"eight-way race one winner","restart":"pending resumes; unknown never blindly resends","receipt_crash":"unknown with one provider call","reconciliation":"exact positive evidence resolves without transport; exact negative evidence alone permits retry","audit":["chat/topic-or-DM","message ID","approved revision","payload digest"],"forgery":"malformed/partial/contradictory/stale evidence fails closed","nutrition":"150 passed","telegram":"120 passed","adaptive":"42 passed","task7":"37 passed","type":"zero Task 13 changed-symbol/test findings","quality":"zero new Any/cast/suppression/sleep; Ruff compileall diff PASS","manual_surface":"one provider fake call through complete audited lifecycle","adversarial":"dispatch CAS and unknown-outcome contract confirmed","provenance":"67-path JSON, Markdown, and raw-byte digest agree"},"scope":{"reused":["Task 7-12 delivery intent","reservation and authority","prepared route/text","receipt and audit","callback CAS","restart reconciliation"],"new_delta":["explicit unknown outcome","atomic dispatch CAS","evidence-bound reconciliation","complete sent audit pins","crash matrix","real-CAS Task 7 tests"],"rejected":["automatic unknown retry","provider exactly-once claim","Task 14 ACK work","new UX/framework","speculative abstraction","future scaffolding","broad refactor","manual receipt deletion"]},"cleanup":{"status":"PASS","temporary_resources":0,"network_calls":0,"customer_actions":0,"unrelated_dirty_worktree":"preserved"},"commit":"none; user prohibited commits"}
{"event":"verification-passed","plan":".omo/plans/dualcoach-production-readiness.md","task":"14. Make callback acknowledgement best-effort and bounded","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor":"st_019fe379","verifiers":["st_019fe390","st_019fe391","st_019fe392"],"verdict":"PASS","candidate_digest":"sha256:15b26c8f06a39f046a8d270277520dd01972f4d15ff7d77fa902087aaf5ff69e","artifact":[".omo/evidence/dualcoach-task-14.md",".omo/evidence/dualcoach-candidate-manifest.json",".omo/evidence/dualcoach-candidate-manifest.md","gateway/platforms/telegram.py","gateway/platforms/telegram_nutrition_onboarding_runtime_callback.py","tests/gateway/test_telegram_room_bootstrap_transport.py","tests/gateway/test_telegram_nutrition_onboarding.py","tests/gateway/test_telegram_nutrition_onboarding_callback_observability.py"],"evidence":{"ack":"immediate where possible; bounded two seconds; expiry/timeout best-effort","coverage":["consent","pause","start","n3","nc1","adaptive","operator","onboarding"],"response_only":"remaining direct answers are error/stale early exits with no continuation","consent":"ACK failure and success-notice edit failure cannot block reconciliation/start","cancellation":"pre-mutation cancellation commits nothing; post-commit cancellation restart-reconciles","card_projection":"durable state drives next card","logging":"gate/callback/error type only; no customer content","transport":"41 passed","onboarding":"49 passed","physique":"122 passed","operator":"13 passed","adaptive_n3_nc1":"4 passed","manual":"19 passed plus Event-controlled driver","type":"55 to 0 exact Task 14 symbol/test diagnostics; lead live ty found no former assign_role/owner-review hits","ruff_compile_diff":"PASS","adversarial":"original consent ACK and card-publication findings closed","provenance":"67-path JSON, Markdown, and raw-byte digest agree"},"scope":{"reused":["Task 11 card projection and CAS","Task 12 approval/delivery split","Task 13 outbox and reconciliation","existing callback routing"],"new_delta":["bounded ACK helper","stateful callback adoption","privacy-safe ACK logs","consent edit-failure isolation","truthful callback protocols and test doubles"],"rejected":["Task 15 ingress","ACK retry","new UX/framework","broad callback rewrite","compatibility shim","speculative abstraction","future scaffolding","suppressions","fixed sleeps","polling"]},"residual":{"whole_file_ty":"218 broad telegram.py diagnostics; none at former Task 14 sites","invite_fixture":"pre-existing expected topic 1 got 0; no Task 14 hunk intersection"},"cleanup":{"status":"PASS","temporary_resources":0,"network_calls":0,"customer_actions":0,"unrelated_dirty_worktree":"preserved"},"commit":"none; user prohibited commits"}
{"event":"verification-passed","plan":".omo/plans/dualcoach-production-readiness.md","task":"15. Preserve pending updates and make ingress observable","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor":"st_019fe3ce","verifiers":["st_019fe430","st_019fe431","st_019fe432"],"verdict":"PASS","candidate_digest":"sha256:63604403f7eb49ff849230b8b0801736fcea3f5e30e4530209f4810f527e01bf","artifact":[".omo/evidence/dualcoach-task-15.md",".omo/evidence/dualcoach-candidate-manifest.json",".omo/evidence/dualcoach-candidate-manifest.md","gateway/platforms/telegram.py","gateway/platforms/telegram_polling_receipts.py","gateway/platforms/telegram_nutrition_onboarding.py","gateway/platforms/telegram_nutrition_onboarding_runtime.py","gateway/platforms/telegram_nutrition_onboarding_runtime_callback.py","gateway/platforms/telegram_nutrition_onboarding_runtime_collection.py","tests/gateway/test_telegram_polling_receipts.py","tests/gateway/test_telegram_polling_receipts_multiprocess.py","tests/gateway/test_telegram_nutrition_onboarding.py","tests/gateway/test_nutrition_coaching.py"],"evidence":{"startup":"three polling, one webhook, one delete-webhook site all explicitly drop_pending_updates=false","polling_boundary":"next advancing getUpdates offset waits for durable update-id receipt","crash_replay":["fetch before handler","business before receipt","receipt before Telegram ack","handler exception","receipt write failure","corrupt store","cancellation"],"dedupe":"receipted replay skips business mutation then permits Telegram acknowledgement","multiprocess":"flock-serialized record/forget; crash holder releases; two writers preserve both IDs","authority":"dir-fd relative O_NOFOLLOW traversal; receipt/lock regular single-link mode 0600; no-follow atomic replace","tamper":["dangling/existing symlink","parent symlink","hardlink","FIFO","wrong mode","pre-replace symlink race"],"real_handlers":"callback and text replay use durable consumed-update authority; one canonical mutation","uncertain":"publication UNCERTAIN is never blindly retried and ingress receipt is not provider delivery evidence","stages":["ingress","authority","route","validation","persistence","publication","receipt"],"logging":"stable reason codes and update-id only; no customer answer/callback/actor/chat/message/profile/token/secret","tests":{"receipt_multiprocess_security":16,"affected_warnings_as_errors":242,"onboarding_batches":93,"bootstrap_batch":177,"adaptive_physique_operator":297,"pause":1},"type":"zero receipt source/test/multiprocess diagnostics","ruff_compile_diff":"PASS","manual":"true PTB fake-server offsets, two-process locks, real callback/text replay confirmed","adversarial":"dangling symlink HIGH and multi-process race closed","provenance":"70-path JSON, Markdown, and raw-byte digest agree"},"scope":{"reused":["Task 4-5 addresses/onboarding durable state","Task 14 ACK context","Task 7-13 CAS/idempotency/outbox","normal PTB Updater lifecycle"],"new_delta":["durable polling receipt authority","offset gate/proxy","cross-process no-follow locking","update-id ingress taxonomy","real replay recovery"],"rejected":["webhook in-flight overclaim","generic handler exactly-once","provider delivery claim","Task 16 card/navigation work","new monitoring framework","customer UX","speculative abstraction","future scaffolding","compatibility shim","Any/cast/suppression","fixed sleeps","poll loops","blind retry"]},"residual":{"resource_warning":"direct-entry bodies pass; pre-existing unclosed socket/event-loop warnings","invite_fixture":"pre-existing expected topic 1 got 0; no Task 15 hunk intersection","shared_build":"pre-existing shared outputs preserved; ownership insufficient for deletion"},"cleanup":{"status":"PASS","temporary_resources":0,"network_calls":0,"customer_actions":0,"unrelated_dirty_worktree":"preserved"},"commit":"none; user prohibited commits"}
{"event":"verification-passed","plan":".omo/plans/dualcoach-production-readiness.md","task":"16. Make cards and navigation restart-safe","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor":"st_019fe44d","verifiers":["st_019fe45d","st_019fe45e","st_019fe45f"],"verdict":"PASS","candidate_digest":"sha256:cceb2d95f7b7f71a9c44b7ded31c012356f8d7f4c26bff773ab9319c3dbc09f1","artifact":[".omo/evidence/dualcoach-task-16.md",".omo/evidence/dualcoach-candidate-manifest.json",".omo/evidence/dualcoach-candidate-manifest.md","gateway/platforms/telegram_nutrition_onboarding_publication_outbox.py","gateway/platforms/telegram_nutrition_onboarding_runtime_publication_transport.py","gateway/platforms/telegram_nutrition_onboarding_runtime_callback.py","gateway/platforms/telegram_nutrition_onboarding_runtime.py","tests/gateway/test_telegram_nutrition_onboarding.py","tests/gateway/test_telegram_nutrition_onboarding_callback_observability.py"],"evidence":{"questions":"22 onboarding fields plus separate 12-step nutrition_daily; Q7 sleep_quality a1-a5 and Q8 digestion a0-a8","navigation":"machine choice and navigation actions coexist; callbacks round-trip within 64 bytes","waiting_states":["WAITING_ADMIN","PROVISIONING","CLAIMING","ROLE_REVIEW","REGISTERING","AWAITING_CONSENT","AWAITING_ACTIVATION","onboarding questions/review","checkin","trainer","owner","operator","generation pending/leased/failed/created/approved/held/sent"],"current_cards":{"claiming":"customer 80, trainer 81","role_review":"customer 80, trainer 81, owner 999","consent":"customer 80, trainer 81, consent 96","activation":"customer 80, trainer 81"},"restart":"valid committed cards no-op; missing cards exactly one republish; concurrent recovery one winner","stale":"durable generation/revision/render/publication/route/message authority rejects old cards","publication_outbox":"signed DISPATCHING/RECEIPTED/COMMITTED primary plus independent emergency receipt ledger","integrity":"HMAC binds session/generation/payload/route/role/render/message; constant-time verification; forged/legacy rows fail closed","receipt_failure":"primary fail uses emergency; restart commits exact message without resend; dual failure remains UNCERTAIN","generation":"pending resumes immediately; active lease schedules one post-expiry recovery; disconnect cancels task; no lease theft","invite":"stale test corrected to canonical customer DM topic_id 0 only","tests":{"focused":518,"manual_question_walk":22,"automated_bounded_batches":"all relevant card/restart/Task15/invite suites passed"},"type":"zero Task16-modified production and added test symbol diagnostics; environment imports separated","ruff_compile_diff":"PASS","manual":"per-route card authority and restart matrix confirmed","adversarial":"forged receipt and post-send receipt persistence HIGH findings closed","provenance":"71-path JSON, Markdown, and raw-byte digest agree"},"scope":{"reused":["Task 5 DM routing","Task 11 card CAS/publication claims","Task 14 bounded ACK","Task 15 ingress receipt/replay","Task 7-13 generation and delivery authority"],"new_delta":["generation startup recovery planner","signed card publication receipt outbox","emergency Telegram message receipt","complete waiting-state card recovery","machine question/navigation matrix"],"rejected":["blind UNCERTAIN resend","Task 17 process-state work","Task 18 test framework","new questions/choices/UX","speculative abstraction","future scaffolding","compatibility shim","Any/cast/suppression","fixed sleeps","poll loops"]},"residual":{"pytest_mark_warning":"repository-wide -W error collection blocked by pre-existing unknown timeout mark","resource_warning":"pre-existing direct-entry socket/event-loop debt"},"cleanup":{"status":"PASS","temporary_resources":0,"network_calls":0,"customer_actions":0,"unrelated_dirty_worktree":"preserved"},"commit":"none; user prohibited commits"}
{"event":"verification-passed","plan":".omo/plans/dualcoach-production-readiness.md","task":"17. Reconcile gateway process state truthfully","session_id":"senpi:019fd78b-bc20-7f7e-baca-b4bb0dc6b301","executor":"st_019fe4b8","verifiers":["st_019fe4c9","st_019fe4ca","st_019fe4cb"],"verdict":"PASS","candidate_digest":"sha256:7a977121142e0a6d39e51e8717f8b0270c2d02f705e5a56603de68529e5781f2","artifact":[".omo/evidence/dualcoach-task-17.md",".omo/evidence/dualcoach-candidate-manifest.json",".omo/evidence/dualcoach-candidate-manifest.md","gateway/run.py","gateway/status.py","hermes_cli/gateway.py","hermes_cli/gateway_windows.py","hermes_cli/profiles.py","pyproject.toml","tests/conftest.py","tests/gateway/test_gateway_shutdown.py","tests/gateway/test_planned_stop_watcher.py","tests/gateway/test_platform_reconnect.py","tests/gateway/test_runner_fatal_adapter.py","tests/gateway/test_runner_startup_failures.py","tests/gateway/test_status.py","tests/hermes_cli/test_gateway.py","tests/hermes_cli/test_gateway_runtime_health.py","tests/hermes_cli/test_gateway_service.py","tests/hermes_cli/test_gateway_windows.py","tests/hermes_cli/test_profiles.py"],"evidence":{"identity":["pid","process start time","boot id","canonical HERMES_HOME","live command/profile"],"handles":{"linux":"pidfd","macos":"validated psutil process identity","windows":"validated process handle","systemd":"no profile authority means no numeric signal"},"states":["starting","running only with live configured connections","degraded","stopped","startup_failed"],"crash":"first status after dead SIGKILL persists stopped/unexpected_exit; idempotent","unknown":"unreadable identity reports degraded and preserves files/locks","signals":"graceful, SIGTERM, SIGINT clean; shutdown wrapper cannot self-cancel","profile_cleanup":"one stable expected-home handle through TERM/wait/KILL/close","files":"PID/runtime/lock/markers private no-follow atomic authority","connection":"Telegram failure degrades, reconnect restores running, fatal write failure stops","resources":"all runner-owned tasks joined; dispatcher lock and sockets closed; persistent lock files inactive and reacquirable","tests":{"strict_lifecycle_status_profile":487,"telegram_polling_shutdown":18,"executor_lifecycle":338,"post_cleanup_status_profile":214},"type":"zero Task17-added/modified symbol diagnostics; broad debt separated","ruff_compile_diff":"PASS","manual":"actual CLI plus localhost fake Telegram, signals, PID swaps, profile isolation confirmed","adversarial":"shutdown self-cancel, raw PID TOCTOU, unreadable proc deletion findings closed","provenance":"89-path JSON, Markdown, and raw-byte digest agree"},"scope":{"reused":["Task15 polling connection state","Task16 delayed recovery cancellation","existing CLI/process manager/locks"],"new_delta":["stable process identity and handles","tri-state process validation","truthful crash reconciliation","private authority-file I/O","complete task/resource ownership"],"rejected":["numeric validate-then-kill","Task18 framework","new daemon/systemd integration","speculative abstraction","future scaffolding","compatibility shim","Any/cast/suppression","fixed sleeps","poll loops","signals to unrelated processes"]},"residual":{"discord":"optional Discord import/Python 3.13 broad debt outside Task17","broad_ty":"pre-existing diagnostics outside exact Task17 slice"},"cleanup":{"status":"PASS","temporary_resources":0,"network_calls":"localhost fake only","customer_actions":0,"unrelated_dirty_worktree":"preserved"},"commit":"none; user prohibited commits"}

[Showing lines 48-71 of 83 (50.0KB limit). Use offset=72 to continue.]


---
status: ready
intent: clear
review_required: false
approved: true
slug: dualcoach-production-readiness
execution_repository: /home/cube/projects/richard/hermes-agent
evidence_repository: /home/cube/projects/richard/traning coach
---

# DualCoach Production Readiness Plan

## Status

- Planning date: 2026-08-06
- Execution repository: `/home/cube/projects/richard/hermes-agent`
- Evidence repository: `/home/cube/projects/richard/traning coach`
- Source retrospective: `.omo/retrospectives/dualcoach-live-qa-2026-08-06.md`
- Planning notepad: `/tmp/ulw-20260806-dualcoach-production-plan.md`
- Active execution handoff: `.omo/start-work/dualcoach-production-readiness-handoff.md`
- Current release verdict: **NO-GO**
- This artifact is a work plan only. It does not authorize a release, commit, push,
  reset, stash, clean, customer activation, or customer delivery.

## Objective

Produce one reproducible DualCoach release candidate whose complete customer lifecycle
works through the real Telegram surfaces without raw listeners, direct JSON mutation,
manual ledger deletion, direct service replay, or forced card republication:

```text
readiness/auth preflight
  -> customer onboarding and attestation
  -> owner/operator review
  -> readiness
  -> activation
  -> customer check-in
  -> automatic draft generation
  -> operator review and approval
  -> explicit customer send
  -> exactly-once receipt
  -> safe disable and cleanup
```

## Approved product decisions

### Privacy boundary

Use **customer Bot DM plus a customer-free staff review group**.

- Customer DM contains onboarding, activation notices, check-ins, and approved coaching.
- Staff-only Telegram surfaces contain owner/operator review artifacts only. Trainer collaboration is not a v1 capability.
- A Telegram forum topic is an organizational aid, not an authorization or privacy
  boundary.
- No customer joins the staff review group.
- Staff messages contain the minimum required customer data and refer to a canonical
  customer identity.
- Existing shared customer topics are migration sources only; they are not a supported
  production route.

Rejected:

- Multiple customers separated only by topics in one shared group.
- A customer-visible group containing owner/operator review material.
- Continuing the current shared-topic topology with documentation alone.

### Draft generation, approval, and delivery

Use **automatic durable draft generation after check-in**, with approval and send as
separate transitions:

```text
checkin_completed
  -> generation_pending
  -> generating
  -> draft_created
  -> approved
  -> delivery_pending
  -> sent_audited
```

- Telegram callbacks acknowledge immediately; they never wait for model generation or
  delivery.
- A durable worker owns generation and can resume after restart.
- `approved` never sends to the customer.
- Only the explicit `send_to_customer` action may create a delivery outbox entry.
- The delivery idempotency key is derived from customer, check-in revision, and approved
  draft revision.
- A repeated send returns the existing pending or sent result; it never creates a second
  customer message.

Rejected:

- A button-gated long-running model call inside the callback handler.
- Approval and customer delivery in one transition.
- Manual canonical service calls as a normal operator workflow.

## Non-negotiable invariants

1. Before activation, the customer is disabled and receives no coaching delivery.
2. Before operator approval, customer delivery count is zero.
3. After approval but before explicit send, customer delivery count is zero.
4. A successful explicit send creates exactly one provider message and one durable
   `sent_audited` receipt.
5. Wrong-role, wrong-chat, wrong-topic, stale-generation, and duplicate callbacks cause
   no state mutation.
6. Telegram callback acknowledgement failure cannot roll back an already committed
   transition or prevent the next card from being published.
7. Provider authentication failure is detected before customer work begins when
   possible, and leaves a retryable durable state when it occurs later.
8. Restart at every waiting boundary preserves progress and does not duplicate delivery.
9. User-visible completion is not inferred from a provider `200 OK`; it requires a
   durable receipt and observation on the intended customer surface.
10. Production release evidence must come from the exact immutable candidate being
    reviewed.
11. The owner/operator is the sole nutrition review authority in v1. No trainer marker,
    claim, invite, card, UI, route, data access, review, readiness, activation requirement,
    or safety-hold path exists or is required.

## Known evidence and blockers

The 2026-08-06 live QA proved substantial behavior but is not release evidence:

- The customer completed 22 onboarding fields and a 12-step check-in.
- The historical run used a trainer review workflow and is not v1 evidence.
- Its trainer-specific approval and wrong-role results are retained only as superseded
  historical context, not as release proof.
- One customer coaching message was eventually observed on the customer handset.
- The operator Telegram button path did not complete end-to-end.
- Owner readiness, activation, generation, and delivery required manual canonical
  recovery at multiple points.
- Shared topics exposed customer content to every group member with access.
- Startup polling, ForceReply anchoring, callback acknowledgement, DM topic
  normalization, Q7 navigation, provider credentials, generation claims, and delivery
  draining all failed during the run.
- Current execution worktree is dirty: 27 tracked files changed with 12,596 additions and
  742 deletions, plus 73 untracked files at planning time.

No evidence from that run may be promoted to a production PASS unless the same behavior
is reproduced from the immutable candidate through the normal surface.

### Historical evidence labels

The following prior artifacts contain trainer setup, routes, claims, cards, or review
branches. They remain append-only historical records, but are superseded and must not be
used as v1 release proof: Task 4 and Task 5 evidence, Task 15 and Task 16 receipts,
Task 18 Golden Path evidence, Task 21 topology evidence, and the existing Task22 receipt
and focused JUnit. The artifacts are not deleted or rewritten in this scope. Any later
release evidence must use the owner/operator-only authority, the frozen-session journaled
reconciliation, and the amended automation matrix.

## Retrospective blocker traceability

| 2026-08-06 blocker | Preventive implementation | Proof gate |
| --- | --- | --- |
| Polling startup discarded pending updates | Specifications 15 and 19 | PTB startup contract and restart matrix |
| Q1 ForceReply lacked the proven user anchor | Specifications 5 and 16 | Full DM onboarding and all-question render walkthrough |
| Shared customer topic exposed content to all group members | Specifications 4 through 6 | Privacy readiness matrix and isolated DM rehearsal |
| Hermes auxiliary OAuth expired during reconciliation/generation | Specifications 9 and 10 | Startup/activation/worker preflight and reauthentication-resume tests |
| Callback acknowledgement expired after a committed transition | Specifications 11 and 14 | Immediate-ACK and expired-query transition tests |
| OWNER DM supplied `message_thread_id=None` | Specifications 4, 5, and 19 | Canonical DM topic-0 and callback context matrix |
| Q7 navigation displaced choices `1` through `5` | Specifications 16, 18, and 23 | Full-question automated walkthrough and handset capture |
| Feature epoch and activation notice drain were hidden manual prerequisites | Specifications 6, 21, and 23 | Readiness preflight and intervention-free activation rehearsal |
| Operator button route did not finish end-to-end | Specifications 11, 12, 14, and 24 | Real staff-card generation, approval, and send |
| Generation claim required manual deletion after provider failure | Specifications 9, 10, and 19 | Lease expiry, auth failure, and restart recovery tests |
| Canonical service replay and forced card publication substituted for UI success | Specifications 2, 3, 18, 22, and 24 | Golden Path shortcut prohibition and fresh no-intervention rehearsal |
| Delivery completion was reported before a durable receipt existed | Specifications 13, 24, 26, and 27 | One provider message, one `sent_audited` receipt, and customer observation |
| Gateway metadata reported `running` for an absent PID and orphan followers remained | Specifications 17 and 25 | Process-state QA and post-disable cleanup audit |

## Execution constraints

- Work only in `/home/cube/projects/richard/hermes-agent`.
- Preserve unrelated user and agent changes.
- Do not run `git commit`, `git push`, `git reset`, `git stash`, or `git clean`.
- Use a dedicated test profile and synthetic customer identities.
- Keep all real customers disabled throughout implementation and QA.
- External authentication and Telegram actions require the normal approval and
  device-code procedures.
- Every behavior change is test-first.
- Tests must use events and bounded timeouts; fixed sleeps and timing-luck polling are
  forbidden.
- Each phase must finish with its listed evidence before the next phase begins.

### Minimum-operation v1 scope directive

The remaining work freezes the existing DualCoach lifecycle as a minimum operational
v1 baseline. It is production hardening, not a mandate to add customer-facing features.

- Implement only the smallest change required by the existing acceptance criteria and
  non-negotiable invariants.
- Do not add speculative abstractions, convenience features, future-feature scaffolding,
  or unrelated UX expansion.
- Do not skip or weaken a top-level checkbox; narrow its implementation to the
  operational behavior needed for privacy, durable state, restart recovery, explicit
  approval, exactly-once delivery, observability, and truthful cleanup.
- The immutable candidate manifest, Golden Path, Recovery Runbook, automated gates, and
  rehearsal evidence together define the v1 operating contract.
- After v1, every new feature must update the affected state transitions, runbooks,
  focused tests, candidate manifest, and release evidence instead of weakening this
  baseline.
- When scope is ambiguous, preserving the v1 invariants outranks adding capability.

#### Per-checkbox execution rule

Before editing for each remaining specification, the executor must record:

1. the existing implementation and evidence that can be reused;
2. the exact unsatisfied v1 acceptance condition;
3. the smallest product or test delta needed to close that condition;
4. optional capability, refactoring, and future work explicitly rejected from scope.

Apply these decisions as follows:

- If the live candidate already satisfies an acceptance condition, make no product edit;
  verify it through the required automated, manual, adversarial, and cleanup gates.
- If a condition has a confirmed gap, change only the owning seam and its focused tests.
- Do not rewrite stable behavior, create parallel infrastructure, or add a feature merely
  to make verification easier.
- Every DoneClaim and ledger receipt must distinguish reused behavior from new changes
  and list the rejected out-of-scope work.
- Candidate identity changes only when candidate bytes change. Reuse valid evidence when
  its exact candidate and covered behavior remain unchanged; rerun gates affected by a
  changed digest.
- Workers receive one bounded goal and one deliverable. Once the owning seam is known,
  repeated broad reconnaissance is not completion progress.

#### v1 completion and pilot handoff

- Completing this plan means **ready for a bounded real-customer pilot**, not automatic
  customer activation or delivery.
- Final evidence must leave rehearsal customers disabled, runtime state truthful, and
  the release candidate reproducible.
- The final verdict must include a short normal-surface launch sequence: production
  preflight, explicit go/no-go approval, one selected pilot customer, onboarding link,
  customer check-in, operator approval, explicit send, receipt observation, monitoring,
  and rollback/disable ownership.
- Real-customer activation remains a separate explicit post-plan operation.
- Optional trainer collaboration is deferred to a later version and is not represented by
  v1 scaffolding, configuration, UI, data access, or acceptance criteria.

---

## Foundation

### Specification 1 — Build the immutable-candidate manifest

Inventory every tracked and untracked DualCoach file in the current worktree and classify
it as:

- product implementation;
- automated test;
- migration/configuration;
- diagnostic-only instrumentation;
- temporary recovery code;
- unrelated change.

Primary inputs:

- `gateway/platforms/telegram.py`
- `gateway/platforms/telegram_nutrition_onboarding_*.py`
- `gateway/platforms/telegram_room_bootstrap*.py`
- `gateway/platforms/telegram_activation_notice.py`
- `gateway/platforms/physique_checkin.py`
- `checkin_cli/customer_admin.py`
- `checkin_cli/nutrition_onboarding*.py`
- `tests/gateway/test_telegram_nutrition_*.py`
- `tests/gateway/test_telegram_*checkin*.py`
- `tests/gateway/test_telegram_*callback*.py`
- `tests/checkin_cli/test_*nutrition*.py`

Deliverables:

- `.omo/evidence/dualcoach-candidate-manifest.md`
- Machine-readable file list with path, Git status, classification, owner, and reason.
- Explicit list of diagnostic/recovery files to remove before release review.

Acceptance:

- Manifest counts reconcile with `git status --porcelain --untracked-files=all`.
- Every untracked DualCoach implementation and test file is represented.
- Unrelated files are identified but not modified.
- Candidate identity is a content digest over the manifest and listed file bytes, not an
  unrequested Git commit.

### Specification 2 — Write the Golden Path contract

Create `docs/runbooks/dualcoach-golden-path.md`.

For every lifecycle step record:

- actor and canonical role;
- customer DM or staff-only surface;
- exact user action;
- expected durable state and receipts;
- expected Telegram artifact;
- evidence required to advance;
- failure condition;
- permitted retry behavior.

The Golden Path must not contain:

- raw `getUpdates` listeners;
- direct JSON edits;
- manual claim deletion;
- direct service replay;
- forced card publication;
- manual delivery drains.

Acceptance:

- The runbook covers every state from readiness preflight to cleanup.
- Every transition names one authoritative state store and one user-visible artifact.
- Approval and send are distinct entries.

### Specification 3 — Write the Recovery Runbook

Create `docs/runbooks/dualcoach-recovery.md`.

Define supported recovery for:

- expired Hermes OAuth;
- pending update at gateway startup;
- stale or expired callback;
- committed transition with failed callback acknowledgement;
- orphan generation claim;
- provider success before receipt persistence;
- gateway restart during onboarding, review, generation, or delivery;
- activation notice reservation without dispatch;
- stale gateway-state metadata.

Each recovery procedure must state:

- detection evidence;
- safe automated recovery;
- operator action, if unavoidable;
- idempotency boundary;
- prohibited direct mutation;
- success and rollback evidence.

Acceptance:

- No procedure depends on editing durable JSON by hand.
- Every automated recovery has a regression test assigned in a later phase.
- Recovery cannot create customer delivery before explicit approved send.

---

## Privacy and Routing

### Specification 4 — Introduce explicit customer and staff addresses

Replace overloaded group-topic addressing with distinct typed concepts:

- customer private-delivery address;
- owner/operator review address.

Parse and validate these at configuration boundaries. A customer address must be a
private chat. A staff address must reject customer membership as a readiness failure.

Likely touchpoints:

- `gateway/platforms/telegram.py`
- Telegram nutrition onboarding authority/address modules
- room bootstrap configuration and ledger projection
- customer registry and activation readiness validation

Acceptance:

- A group/topic cannot be configured as a production customer-delivery address.
- A customer cannot be activated while present in the configured staff group.
- Existing shared-topic test data is recognized as legacy and fails production readiness
  with an actionable migration message.
- Tests cover DM topic normalization to canonical `0`.

### Specification 5 — Migrate bootstrap and onboarding to customer DM

Preserve canonical identity and consent while moving customer-facing publication,
ForceReply, activation notice, check-in, and coaching delivery to the customer DM.

Keep owner/operator artifacts in the staff-only route. Store no customer phone-specific
state; use Telegram user/chat identity and canonical customer key. Trainer setup, UI, and
data access are prohibited in v1.

Acceptance:

- Onboarding Q1 through Q22 works in DM without forum thread IDs.
- ForceReply is anchored to a customer-authored message when available.
- Direct typed answers remain supported and safe.
- Only the owner/operator can answer or review nutrition onboarding from the staff surface.
- Staff cards never appear in the customer DM.
- No trainer marker, claim, invite, card, UI, route, or data-access path is configured.

### Specification 6 — Add privacy readiness and migration gates

Extend readiness/activation checks so activation is rejected when:

- the customer DM binding is absent or mismatched;
- the customer is a member of the staff-only group;
- staff review routing is absent;
- a legacy shared-topic route remains active;
- privacy consent or identity authority is stale.

Acceptance:

- Gate failures leave the customer disabled.
- Error output names the exact corrective action without exposing sensitive customer
  content.
- A migration test proves legacy shared-topic records cannot silently activate.

---

## Durable Generation and Review

### Specification 7 — Define the generation state machine and schemas

Create typed durable records for:

- `generation_pending`;
- `generating`;
- `draft_created`;
- `generation_failed`;
- `approved`;
- `delivery_pending`;
- `sent_audited`.

Each record must bind:

- customer key;
- check-in event/revision;
- draft revision;
- model/provider contract version;
- current owner/operator review actor and authority digest when the record is a review
  transition; worker identity remains separate for generation;
- predecessor digest;
- timestamps and bounded error metadata;
- idempotency key.

Acceptance:

- Invalid or skipped transitions are rejected.
- A new check-in cannot reuse an older approved draft.
- A stale operator card cannot approve or send a newer draft.
- State projection is deterministic from the event/receipt history.

### Specification 8 — Enqueue generation atomically with check-in completion

When a check-in becomes final, persist the finalized check-in and one generation job in
the same durable transaction or recoverable journal boundary.

Acceptance:

- Crash before commit leaves neither finalized check-in nor job.
- Crash after commit leaves one recoverable job.
- Duplicate finalization creates no second job.
- Customer delivery remains zero.

### Specification 9 — Implement the resumable generation worker

Move model calls out of Telegram callbacks. The worker must:

1. claim one pending job with a lease;
2. verify provider readiness and current revision;
3. build grounded model input;
4. validate schema and semantic grounding;
5. permit at most one bounded correction attempt;
6. persist a new draft revision;
7. update the staff operator card;
8. release or expire the claim safely on failure.

Acceptance:

- Restart resumes an expired claim.
- Invalid model output creates no draft.
- Authentication failure becomes `generation_failed` with a retry action.
- No manual receipt deletion is required.
- Logs contain IDs and gate names, not raw customer answers.

### Specification 10 — Implement provider authentication preflight

Run preflight:

- at gateway startup;
- before customer activation;
- before claiming a generation job.

Check the credential store actually used by the Hermes auxiliary provider, not only the
Codex CLI credential.

Acceptance:

- An invalidated credential is detected before activation.
- The operator receives an actionable reauthentication status.
- Reauthentication resumes the existing job rather than creating a new request.
- No secrets or OAuth tokens enter logs, cards, or evidence artifacts.

### Specification 11 — Build asynchronous operator cards

On check-in completion publish an operator card immediately:

```text
Check-in saved
Draft generation pending
```

Update or replace it as the durable state changes. Buttons by state:

- `generation_failed`: retry;
- `draft_created`: edit, regenerate, approve, approval_hold;
- `approved`: send to customer, revoke approval;
- `sent_audited`: no active buttons.

Callback data must bind action, request/draft revision, card generation, and a unique
render identity while remaining within Telegram's byte limit.

Acceptance:

- Every callback is acknowledged before long-running work begins.
- A stale card produces a clear refresh message and no mutation.
- Card recreation after restart retains the same durable revision semantics.
- No content-derived cache workaround substitutes for server-side revision validation.

### Specification 12 — Separate approval from delivery

`approve` persists an immutable operator approval receipt and transitions only to
`approved`.

`send_to_customer` revalidates:

- operator authority;
- customer active state;
- latest approved draft revision;
- current delivery route;
- absence or status of the idempotent outbox entry.

Acceptance:

- Approval produces zero customer messages and zero provider delivery attempts.
- Send cannot use a draft that changed after approval.
- Revoking approval before send prevents delivery.
- Wrong-role and wrong-route actions fail closed.

### Specification 13 — Add the exactly-once delivery outbox

Use an idempotency key derived from:

```text
customer_key + checkin_revision + approved_draft_revision
```

Represent pending, unknown-provider-outcome, and sent states explicitly. Do not retry an
unknown provider outcome until receipt reconciliation determines whether Telegram
accepted it.

Acceptance:

- Duplicate button presses create one outbox entry.
- Restart before send resumes one entry.
- Restart after provider success but before local receipt performs reconciliation and
  never blindly sends again.
- `sent_audited` includes provider chat/topic-or-DM, message ID, approved revision, and
  canonical payload digest.

---

## Telegram Reliability

### Specification 14 — Make callback acknowledgement best-effort and bounded

Commit state transitions independently from `query.answer()`. Acknowledgement occurs
immediately where possible; an expired query is logged as an acknowledgement failure,
not a workflow failure.

Acceptance:

- `BadRequest: Query is too old` cannot undo a committed transition.
- The next card is published from durable state even if acknowledgement fails.
- Tests use events rather than sleeps.

### Specification 15 — Preserve pending updates and make ingress observable

Keep polling startup non-destructive and add structured, privacy-safe stage logging:

```text
ingress -> authority -> route -> validation -> persistence -> publication -> receipt
```

Acceptance:

- Startup never uses `drop_pending_updates=True` for production polling.
- A captured-but-unacknowledged update survives restart.
- Every silent rejection has a reason code keyed by update ID.
- Logs do not contain customer answer text.

### Specification 16 — Make cards and navigation restart-safe

Unify card generation rules for onboarding, check-in, owner/operator review, and
operator delivery surfaces. Trainer cards and routes do not exist in v1.

Acceptance:

- Choice buttons and navigation buttons coexist.
- Q7 and every other choice question retain all choices.
- Old cards are rejected by durable generation, not by client-cache assumptions.
- A restart at each waiting state republishes or resumes exactly one current card.

### Specification 17 — Reconcile gateway process state truthfully

Make gateway state metadata reflect the actual process and connection:

- absent PID cannot remain `running`;
- shutdown markers are authoritative;
- no orphan log followers or session-owned monitors remain;
- other profiles remain untouched.

Acceptance:

- Start, graceful stop, signal stop, and stale-PID startup tests pass.
- Manual QA confirms CLI status matches actual PID and Telegram connection.

---

## Automated Verification

### Specification 18 — Build one executable Golden Path scenario

Create a deterministic integration scenario that drives the real application handlers
and durable stores:

```text
preflight -> onboarding and attestation -> owner/operator review -> readiness
-> activation -> check-in -> automatic draft -> approve -> explicit send -> receipt -> disable
```

Use a fake Telegram provider only at the HTTP boundary and a contract-preserving model
provider. Do not mock the state machine or route/authority logic being asserted.

Acceptance:

- State and visible card assertions exist at every boundary.
- Delivery is zero until explicit send and one afterward.
- The test fails if any manual recovery hook is invoked.

### Specification 19 — Add negative and restart matrices

Cover:

- wrong actor;
- wrong chat;
- wrong topic;
- stale revision;
- duplicate callback;
- callback expiry;
- provider auth failure;
- invalid model output;
- generation-worker crash;
- gateway restart in every waiting state;
- owner/operator review restart and card recovery;
- provider success before receipt persistence;
- duplicate explicit send.

Acceptance:

- The exact matrix includes owner/operator Revise, Reject, wrong-actor, stale-card, and
  duplicate-callback review branches, and each case names the invariant it protects.
- Existing reliability, restart, unknown-outcome, and exactly-once cases remain covered;
  removing trainer branches must not reduce matrix coverage.
- Every async test subscribes before triggering and uses a bounded timeout.
- No fixed sleeps or polling delays.

### Specification 20 — Run candidate-level quality gates

Run from the immutable candidate:

- LSP diagnostics on every changed Python module;
- Ruff for changed Python code;
- compileall for changed Python modules;
- focused onboarding/check-in/operator/delivery tests;
- full `tests/gateway`;
- project-wide build/type checks that cover touched packages;
- JUnit output retained under `.omo/evidence/`.

Acceptance:

- Commands exit zero.
- Failures caused by the candidate are fixed.
- Pre-existing unrelated failures are recorded, not suppressed.
- Evidence records candidate digest, command, exit code, counts, and timestamp.

---

## Real-Surface QA

### Specification 21 — Prepare an isolated live rehearsal

Create fresh synthetic identities and routes:

- one customer DM;
- one owner/operator;
- one customer-free staff review group with no trainer membership or route;
- one dedicated test profile and bot.

Before starting:

- provider auth preflight passes;
- candidate digest matches automated-test evidence;
- all other profiles are recorded and left untouched;
- customer is disabled;
- delivery outbox is empty.

### Specification 22 — Run onboarding and owner/operator review without intervention

Reuse the current synthetic session's committed Q1 through Q22 answers and attestation.
A supported journaled reconciliation must move its frozen `trainer_review` projection to
`owner_review` without re-answering, while preserving the answers, attestation, consent,
and zero downstream state.

Drive through real Telegram:

- the existing customer attestation and finalized questionnaire record;
- one owner/operator review card and Approve happy path;
- restart while awaiting the owner/operator action;
- owner Revise and Reject behavior through the exact automated matrix, not live clicks;
- wrong-actor, stale-card, and duplicate-callback behavior through the exact automated
  matrix.

Capture:

- customer DM and owner/operator handset screenshots;
- owner/operator callback update IDs;
- journaled reconciliation, restart, and owner/operator decision receipts;
- zero activation, generation, and coaching delivery.

No trainer marker, claim, invite, card, UI, route, data access, review, readiness,
activation requirement, or safety-hold path may be configured or exercised in v1. Any raw
listener, service replay, direct mutation, or forced republication fails the rehearsal.

### Specification 23 — Run activation and customer check-in

Activate the synthetic rehearsal customer only after owner/operator readiness passes.
No real customer is activated. Verify:

- activation notice reaches the customer DM;
- all 12 check-in questions render correctly;
- Q7 has choices `1` through `5` plus navigation;
- final save creates one check-in event and one generation job;
- restart during the check-in preserves answers;
- no coaching delivery occurs.

### Specification 24 — Run operator review and exactly-once delivery

Through the real staff Telegram card:

1. observe automatic generation pending;
2. observe draft created;
3. regenerate and edit;
4. approve;
5. prove customer delivery remains zero;
6. explicitly send;
7. observe the customer DM message;
8. prove one provider message and one `sent_audited` receipt;
9. repeat send, stale card, and wrong-role actions;
10. restart before and after the send boundary.

Acceptance:

- Every action uses Telegram, not direct service calls.
- Operator route uses the configured effective user/chat/message context.
- Owner/operator is the sole nutrition approval authority for the generated draft.
- Customer observes exactly one message.
- Negative actions create no second receipt or provider message.

### Specification 25 — Disable and clean the rehearsal

Use the canonical disable transaction. Verify:

- customer registry is disabled;
- scheduled jobs cannot deliver;
- bootstrap/activation projection is coherent;
- test gateway is stopped;
- gateway state reports stopped;
- no orphan monitors/processes remain;
- temporary credentials and evidence containing customer data are removed;
- other profiles retain their original PIDs and state;
- no trainer marker, claim, invite, card, route, observer, or temporary trainer artifact
  remains.

---

## Release Review

### Specification 26 — Run the multi-lane release review

Run independent reviewers for:

- objective and constraint coverage;
- code quality and maintainability;
- security, privacy, and authority;
- hands-on real-surface QA;
- context and evidence provenance;
- owner/operator-only authority and trainer-free v1 scope.

Every reviewer must receive:

- candidate manifest and digest;
- Golden Path and Recovery Runbook;
- automated evidence;
- live rehearsal evidence;
- durable receipts and cleanup evidence.

Acceptance:

- All reviewers return PASS.
- Missing, inconclusive, timed-out, or unverified lanes count as failure.
- Findings are fixed and the affected gates rerun against a new candidate digest.

### Specification 27 — Issue the release verdict

Release is permitted only when all previous tasks pass.

The release report must state:

- exact candidate digest;
- privacy architecture;
- all automated commands and results;
- real-surface evidence for the customer and owner/operator only;
- exactly-once delivery proof;
- recovery scenarios exercised;
- cleanup state;
- reviewer verdicts;
- residual risks;
- pilot scope and rollback criteria.

Initial rollout:

- one explicitly consenting pilot customer;
- no shared customer group;
- daily operator review;
- immediate disable on authorization, duplication, or delivery anomaly;
- expansion only after the defined observation window is clean.

## Todos

Every task below inherits **Execution constraints**, **Minimum-operation v1 scope
directive**, and **Per-checkbox execution rule**. A task's specification defines the
required operating behavior; it does not authorize customer-facing feature expansion,
speculative architecture, convenience work, or future scaffolding. The executor must
reuse already-correct live behavior, identify only the unsatisfied v1 gap, and record
the minimal delta plus rejected extras in its DoneClaim and ledger receipt.

- [x] 1. Build the immutable-candidate manifest
  - Recommended task executor category: `unspecified-high`
  - Dependencies: none.
  - References: Foundation, Specification 1.
  - Acceptance: reconcile every tracked/untracked file and produce the candidate digest.
  - Agent-executed QA: compare manifest counts and digests with Git and filesystem output.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 2. Write the Golden Path contract
  - Recommended task executor category: `writing`
  - Dependencies: 1.
  - References: Foundation, Specification 2.
  - Acceptance: cover every actor, surface, state, visible artifact, and evidence gate.
  - Agent-executed QA: lint the runbook for missing lifecycle states and prohibited shortcuts.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 3. Write the Recovery Runbook
  - Recommended task executor category: `writing`
  - Dependencies: 1-2.
  - References: Foundation, Specification 3.
  - Acceptance: cover every known 2026-08-06 failure without direct durable-state edits.
  - Agent-executed QA: map each retrospective blocker to one recovery procedure and test.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 4. Introduce explicit customer and staff addresses
  - Recommended task executor category: `deep`
  - Dependencies: 1-3.
  - References: Privacy and Routing, Specification 4.
  - Acceptance: typed customer DM and owner/operator staff addresses reject shared-topic production routing and expose no trainer address.
  - Agent-executed QA: failing-first parser, migration, authority, and no-trainer-surface tests plus LSP diagnostics.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 5. Migrate bootstrap and onboarding to customer DM
  - Recommended task executor category: `deep`
  - Dependencies: 4.
  - References: Privacy and Routing, Specification 5.
  - Acceptance: all customer-facing onboarding surfaces use DM, owner/operator cards stay staff-only, and no trainer setup, UI, route, or data access exists.
  - Agent-executed QA: real-handler onboarding scenario, wrong-surface negatives, owner/operator authority, and DM topic-0 tests.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 6. Add privacy readiness and migration gates
  - Recommended task executor category: `unspecified-high`
  - Dependencies: 4-5.
  - References: Privacy and Routing, Specification 6.
  - Acceptance: unsafe topology or trainer authority setup fails activation and leaves the customer disabled.
  - Agent-executed QA: privacy gate matrix covering legacy, mismatched, customer-in-staff, and no-trainer cases.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 7. Define the generation state machine and schemas
  - Recommended task executor category: `ultrabrain`
  - Dependencies: 1-3.
  - References: Durable Generation and Review, Specification 7.
  - Acceptance: typed records reject invalid, skipped, stale, and cross-revision transitions.
  - Agent-executed QA: exhaustive state-transition tests and schema round trips.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 8. Enqueue generation atomically with check-in completion
  - Recommended task executor category: `deep`
  - Dependencies: 7.
  - References: Durable Generation and Review, Specification 8.
  - Acceptance: one final check-in creates one recoverable generation job.
  - Agent-executed QA: crash-boundary and duplicate-finalization tests without sleeps.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 9. Implement the resumable generation worker
  - Recommended task executor category: `deep`
  - Dependencies: 7-8.
  - References: Durable Generation and Review, Specification 9.
  - Acceptance: generation resumes safely and invalid/auth-failed output creates no draft.
  - Agent-executed QA: event-driven worker success, correction, crash, expiry, and retry tests.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 10. Implement provider authentication preflight
  - Recommended task executor category: `unspecified-high`
  - Dependencies: 7,9.
  - References: Durable Generation and Review, Specification 10.
  - Acceptance: the actual Hermes auxiliary credential is checked before activation and generation.
  - Agent-executed QA: valid, expired, reauthenticated, and secret-redaction tests.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 11. Build asynchronous operator cards
  - Recommended task executor category: `unspecified-high`
  - Dependencies: 7-10.
  - References: Durable Generation and Review, Specification 11.
  - Acceptance: cards mirror durable state and callbacks ACK before background work.
  - Agent-executed QA: callback-byte, stale-card, recreation, and immediate-ACK tests.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 12. Separate approval from delivery
  - Recommended task executor category: `deep`
  - Dependencies: 7,11.
  - References: Durable Generation and Review, Specification 12.
  - Acceptance: approval alone creates no customer delivery and send revalidates the approved revision.
  - Agent-executed QA: approval-zero-delivery, revoke, stale revision, and wrong-role tests.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 13. Add the exactly-once delivery outbox
  - Recommended task executor category: `ultrabrain`
  - Dependencies: 7,12.
  - References: Durable Generation and Review, Specification 13.
  - Acceptance: duplicate/restart/unknown-outcome paths produce at most one provider message.
  - Agent-executed QA: deterministic outbox crash matrix and receipt reconciliation tests.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 14. Make callback acknowledgement best-effort and bounded
  - Recommended task executor category: `unspecified-high`
  - Dependencies: 11-13.
  - References: Telegram Reliability, Specification 14.
  - Acceptance: expired callback ACK cannot undo or hide committed work.
  - Agent-executed QA: immediate and expired ACK tests using events and bounded timeouts.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 15. Preserve pending updates and make ingress observable
  - Recommended task executor category: `unspecified-high`
  - Dependencies: 4,14.
  - References: Telegram Reliability, Specification 15.
  - Acceptance: pending updates survive startup and every rejection has a privacy-safe reason code.
  - Agent-executed QA: real PTB startup contract plus structured-log redaction tests.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 16. Make cards and navigation restart-safe
  - Evidence: `.omo/evidence/dualcoach-task-16.md`; candidate rebaseline approval remains required.
  - Recommended task executor category: `unspecified-high`
  - Dependencies: 5,11,14-15.
  - References: Telegram Reliability, Specification 16.
  - Acceptance: all choices/navigation survive render, one current owner/operator card resumes after restart, and no trainer card or route is required.
  - Agent-executed QA: all-question render walkthrough, owner/operator restart-state card tests, and no-trainer-surface checks.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 17. Reconcile gateway process state truthfully
  - Recommended task executor category: `unspecified-high`
  - Dependencies: 15.
  - References: Telegram Reliability, Specification 17.
  - Acceptance: state metadata, process existence, and Telegram connection agree.
  - Agent-executed QA: start/stop/signal/stale-PID tests and CLI manual QA.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 18. Build one executable Golden Path scenario
  - Recommended task executor category: `deep`
  - Dependencies: 4-17.
  - References: Automated Verification, Specification 18.
  - Acceptance: one owner/operator-only scenario covers every lifecycle state with delivery 0 before send and 1 after.
  - Agent-executed QA: run the scenario once and retain JUnit evidence labeled as owner/operator-only.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 19. Add negative and restart matrices
  - Recommended task executor category: `deep`
  - Dependencies: 4-18.
  - References: Automated Verification, Specification 19.
  - Acceptance: every named invariant, including owner Revise, Reject, wrong-actor, stale, and duplicate review branches, has deterministic negative and restart coverage.
  - Agent-executed QA: execute the complete amended matrix once without fixed sleeps and retain the trainer-free scope label.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 20. Run candidate-level quality gates
  - Recommended task executor category: `unspecified-high`
  - Dependencies: 1,18-19.
  - References: Automated Verification, Specification 20.
  - Acceptance: diagnostics, lint, compile, focused tests, full Gateway, and build/type gates pass.
  - Agent-executed QA: retain command, exit code, counts, timestamp, JUnit, and candidate digest.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 21. Prepare an isolated live rehearsal
  - Recommended task executor category: `unspecified-high`
  - Dependencies: 2-3,6,10,20.
  - References: Real-Surface QA, Specification 21.
  - Acceptance: fresh customer DM and owner/operator staff topology pass preflight with delivery empty and no trainer setup or authority artifact.
  - Agent-executed QA: verify identities, memberships, routes, digest, frozen gateway state, and baseline runtime state.
  - Commit: none; the user prohibited commits in this workflow.

- [x] 22. Run onboarding and owner/operator review without intervention
  - Recommended task executor category: `unspecified-high`
  - Dependencies: 21.
  - References: Real-Surface QA, Specification 22.
  - Acceptance: the existing synthetic session is reconciled from frozen `trainer_review` to `owner_review` without re-answering; one real owner/operator Approve path and restart pass without recovery shortcuts.
  - Agent-executed QA: retain customer and owner/operator screenshots and receipts; verify owner Revise, Reject, wrong-actor, stale, and duplicate branches in the exact automated matrix.
  - Commit: none; the user prohibited commits in this workflow.

- [ ] 23. Run activation and customer check-in
  - Recommended task executor category: `unspecified-high`
  - Dependencies: 22.
  - References: Real-Surface QA, Specification 23.
  - Acceptance: synthetic activation and the 12-question check-in complete in DM with one generation job after owner/operator readiness; no real customer activation.
  - Agent-executed QA: capture customer screen, durable event, Q7 controls, restart recovery, and delivery 0 before Task24.
  - Commit: none; the user prohibited commits in this workflow.

- [ ] 24. Run operator review and exactly-once delivery
  - Recommended task executor category: `unspecified-high`
  - Dependencies: 23.
  - References: Real-Surface QA, Specification 24.
  - Acceptance: actual owner/operator staff buttons create, approve, and send one synthetic customer message and one receipt.
  - Agent-executed QA: owner/operator handset happy path plus duplicate, stale, wrong-role, and restart delivery checks. No direct service delivery and no real-customer activation.
  - Commit: none; the user prohibited commits in this workflow.

- [ ] 25. Disable and clean the rehearsal
  - Recommended task executor category: `unspecified-high`
  - Dependencies: 24.
  - References: Real-Surface QA, Specification 25.
  - Acceptance: customer disabled, no future jobs, truthful stopped runtime, no orphan artifacts, and no trainer setup or authority artifacts.
  - Agent-executed QA: restart after disable and prove no delivery while other profiles remain unchanged.
  - Commit: none; the user prohibited commits in this workflow.

- [ ] 26. Run the multi-lane release review
  - Recommended task executor category: `unspecified-high`
  - Dependencies: 1-25.
  - References: Release Review, Specification 26.
  - Acceptance: objective, quality, security, owner/operator hands-on QA, and provenance lanes all return PASS.
  - Agent-executed QA: reconcile every finding to a fixed candidate, revalidate trainer-free scope, and rerun affected gates.
  - Commit: none; the user prohibited commits in this workflow.

- [ ] 27. Issue the release verdict
  - Recommended task executor category: `unspecified-high`
  - Dependencies: 26.
  - References: Release Review, Specification 27.
  - Acceptance: release report contains every named evidence item and authorizes only the limited pilot.
  - Agent-executed QA: run the completion audit and reject release on any missing or inconclusive evidence.
  - Commit: none; the user prohibited commits in this workflow.

## Final verification wave

Every final verifier inherits the same minimum-operation v1 directive and must judge the
exact fixed candidate. PASS means the existing lifecycle is ready for the bounded pilot
handoff defined above; it never authorizes automatic customer activation, delivery, or
new feature scope.

- [ ] F1. Verify objective and invariant coverage
  - Check every revised objective clause and invariant, including owner/operator sole authority and trainer-free v1, against a task, acceptance criterion, and evidence path.

- [ ] F2. Verify privacy and authority architecture
  - Confirm customer DM isolation, customer-free owner/operator staff membership, wrong-role fail-closed evidence, and no trainer marker, claim, invite, card, route, or data access.

- [ ] F3. Verify reliability and exactly-once behavior
  - Confirm owner/operator review restart, stale, duplicate, wrong-actor, unknown-outcome, and one-receipt evidence from the candidate.

- [ ] F4. Verify real-surface evidence
  - Confirm the customer and owner/operator used the intended Telegram surfaces for one real happy path and the customer observed exactly one synthetic delivery only after explicit send.

- [ ] F5. Verify cleanup and release provenance
  - Confirm disabled customer, truthful runtime state, no orphan or trainer artifacts, exact candidate digest, migrated-session receipt, and all reviewer PASS receipts.

## Completion audit

The worker may mark this plan complete only when:

- Tasks 1 through 27 are complete;
- all listed acceptance criteria have evidence;
- no normal-path step used a recovery shortcut;
- all todo items are completed or explicitly dropped with reasons;
- customer delivery was observed on the intended DM;
- exactly-once evidence is retained;
- the rehearsal customer is disabled and runtime cleanup is truthful;
- no trainer setup or authority artifact remains in the v1 rehearsal;
- every release reviewer passed.

Anything less remains **NO-GO**.