{
  "schema": "nutricoach-telegram-checkin-stepper-task-10-r71b-maintenance-design-v1",
  "task_id": "st_01a05bb0",
  "generated_at": "2026-09-01T15:49:48+09:00",
  "mode": "advisory_design_only",
  "status": "DECISION_COMPLETE",
  "source_or_live_state_edits": 0,
  "only_persistent_artifact": "/home/cube/projects/richard/traning coach/.omo/evidence/nutricoach-telegram-checkin-stepper/task-10-r71b-maintenance-design.json",
  "goal": "Deploy one fresh, one-use r71 package namespace that truthfully changes the NutriCoach schedule dispatcher's latest status from the known r70 error to ok while the current KST-day Topic-59 publication is maintenance-skipped with zero Topic-59 transport, provider, or network calls and zero customer messages or updates.",
  "non_negotiable_invariants": [
    "The existing task-v15r71-candidate, candidate-r2, candidate-r3, live-transaction-preseal-v15-runtime-authority-r71, preflight-v15-runtime-authority-r71, and task-v15r71-rehearsal trees are immutable tombstones and are never deleted, renamed, chmodded, rewritten, selected, or reused.",
    "The product generation remains r71. r71b-maintenance is a package/authority namespace discriminator, not product generation r72.",
    "The eventual observer output root remains exactly observer-r71, never observer-r71b.",
    "A maintenance decision is evaluated after the normal weekly authority and exact Topic-59 projection are validated, but before Topic59PublicationLedger.claim is called and before any prepared or sending row can be appended.",
    "A maintenance success is not a delivery success: no send/edit operation, delivered/sent_audited state, provider receipt, or message_id is created or inferred.",
    "The two historical Topic-59 slots whose latest rows are sending remain byte-for-byte unchanged and are never retried, failed, reconciled, or reclassified.",
    "A malformed, stale, expired-before-first-use, replayed, wrong-candidate, wrong-config, wrong-route, wrong-customer, wrong-day, wrong-owner, wrong-mode, hardlinked, symlinked, or noncanonical maintenance artifact fails closed before publication claim and before transport.",
    "A valid current-day terminal skip audit remains effective for repeated same-day ticks even after the active hold expires; the next KST day ignores the prior-day terminal audit and follows the normal publication path.",
    "No Git, GitHub, network download, real customer action, or real Telegram send/edit is part of implementation, qualification, rehearsal, or installed QA. The live service's ordinary Telegram connectivity is not called by the held Topic-59 dispatch path and must not be confused with a provider call made by that path."
  ],
  "survey": {
    "active_plan": {
      "path": "/home/cube/projects/richard/traning coach/.omo/plans/nutricoach-telegram-checkin-stepper.md",
      "sha256": "570bf48ac63db492438f694b4319217e0ff2c984aa50e649b9c624a8a9a46c3a",
      "relevant_contract": "Todo 10 requires one exact live launcher execution, healthy cron, preserved customer state, and rollback only as a safety response; Todo 11 reserves observer-r71. The ledger records explicit user approval for a fresh r71 maintenance namespace with zero customer/provider messages."
    },
    "active_ledger": {
      "path": "/home/cube/projects/richard/traning coach/.omo/ulw-execute/ledger.jsonl",
      "sha256_at_survey": "510fe0ca99e27df94493f16be50d34c7172cc2d9e01769a28b3d924461efc674",
      "latest_relevant_events": [
        "goal-blocked-audit: NO_SAFE_PATH",
        "user-approval-received: fresh one-use r71 maintenance namespace/package",
        "recovery-design-wave-dispatched: r71b design and codemap"
      ]
    },
    "no_safe_path_evidence": [
      {
        "path": "task-10-cron-no-send-recovery-analysis.json",
        "sha256": "968a3ea4e15d149736d47c239d410ed9b88b7dbb20e0703214a2a6b19c3025d0",
        "finding": "With no current-day slot, claim unconditionally appends prepared then sending; only a genuine sent_audited receipt can return the existing no-provider noop."
      },
      {
        "path": "task-10-next-cron-no-send.json",
        "sha256": "bd07ae45e84b318e565cf09625cd8299c16ea51b72f3cf156149e93d74851af7",
        "finding": "Each independently evaluated future tick can make one current-day Topic-59 send; two historical slots are latest=sending and uncertain but are not retried."
      },
      {
        "path": "task-10-debug-cron.json",
        "sha256": "24da8510fe4bf850228a8bb5b56575d40712071a5d7e4ea9cf9b6e5f82b2747e",
        "finding": "The r70 cron failure is a handled canonical authority identity drift, not a process crash. A fresh process can reacquire pins and therefore cannot be assumed safe."
      },
      {
        "path": "task-10-debug-observer-r70.json",
        "sha256": "5f367a44f23dfa072ea1a1bb4fbdb9e216e8c832fbcc608157ad0624de4541a9",
        "finding": "observer-r70 reads a stale unsuffixed authority root; selecting the configured candidate-suffixed root changes the same snapshot from FAIL to PASS without customer input."
      },
      {
        "path": "task-10-r70-health-recovery.json",
        "sha256": "b1bbe2fec619d66570b5025d7760878ae3f0421825c50b19630065fbf8963f13",
        "finding": "The observer root-selection regression is green in current source, but copied-profile cron execution could not establish restart safety and no live restart was performed."
      }
    ],
    "runtime_path": [
      "cron.scheduler.run_one_job",
      "cron.physique_inline_card.launch_scheduled_card",
      "gateway.platforms.telegram.TelegramAdapter._send_nutrition_coaching_tick_authorized",
      "gateway.platforms.telegram_weekly_host_dispatch._run_weekly_operations_dispatch",
      "gateway.platforms.nutrition_weekly_dispatcher.dispatch_weekly_operations_tick",
      "gateway.platforms.nutrition_weekly_dispatcher._dispatch_customer",
      "gateway.platforms.nutrition_weekly_operations.Topic59DayCardProjector.publish",
      "gateway.platforms.nutrition_weekly_operations_ledger.Topic59PublicationLedger.claim",
      "gateway.platforms.nutrition_weekly_dispatcher_transport.RevalidatingTopic59Transport.send/edit"
    ],
    "observed_source_facts": [
      "nutrition_weekly_operations.py currently calls Topic59PublicationLedger.claim immediately after authority/route/projection validation and has only REFUSED, SENT, EDITED, NOOP, and INCIDENT dispositions.",
      "nutrition_weekly_operations_ledger.py appends PREPARED and SENDING whenever the current card_slot is absent; unresolved prior slots are INCIDENT and not retried.",
      "nutrition_weekly_dispatcher.py treats only REFUSED and INCIDENT as failures, so a new typed successful disposition can flow without weakening those failures.",
      "telegram.py returns SendResult(success=not failures); cron marks the job ok when the nutrition tick returns success.",
      "cron currently labels every successful nutrition tick as launch card sent, which would be untruthful for maintenance and must receive a typed maintenance-noop branch.",
      "nutricoach_v150_live_upgrade_state.py classifies cron/jobs.json and scheduled-deliveries.jsonl as volatile, while config.yaml, customers/registry.json, customer-service-state.json, and scheduled-deliveries-fence.json are stable/protected.",
      "The inherited r71 snapshot contains neither weekly-operations-topic59.jsonl nor maintenance paths. A fresh r71b package must generate a fresh authenticated inventory rather than copy the r71/r63 snapshot.",
      "Current observer source already contains the correct _day_status_days(profile) implementation that reads nutrition_coaching.weekly_operations_authority_path from config. That fix is not present in the frozen r71 candidate-r3."
    ],
    "source_hash_anchors": {
      "gateway/platforms/nutrition_weekly_operations_ledger.py": "b31d696cdbd814755a2ddba94e5007e0c84fef397813763aaa915c658a52c3b4",
      "gateway/platforms/nutrition_weekly_operations.py": "52020ac1bd42d8812f7b69d5b74be6322885f6746159298df81a750a1e39d930",
      "gateway/platforms/nutrition_weekly_dispatcher.py": "616b8b4da48d9c2c89336d9e791339c7401c354d67f38831af0f5d155a492cc8",
      "gateway/platforms/nutrition_weekly_dispatcher_transport.py": "121cd4ff9ee4859e6a54882d9234d857af5e7265e0aad5dbc2fb783801a326ec",
      "cron/physique_inline_card.py": "bdb1a34d16763c9e3cbe687a3617215e32b6c6919c9b49405d42e1ee5831ba5d",
      "cron/scheduler.py": "bfe56dcc74a08278671e3e373b0eb8ce624a093b6ed0ad365464e87b1de89709",
      "scripts/nutricoach_v150_observer_runtime.py": "96218c4405cb6ecac1711f20a7af1b38c422f4c716eafcf0e2dec8a122889689",
      "scripts/nutricoach_v150_live_upgrade_state.py": "ff7ac34f57bd870479ee2c393caa7d3a83d98ae7851a0d7fa2b7e933def36821"
    }
  },
  "options": [
    {
      "id": "A",
      "name": "Publication-boundary maintenance gate",
      "design": "Inject a profile-bound Topic59MaintenanceGate into Topic59DayCardProjector and evaluate the exact projection immediately before Topic59PublicationLedger.claim. The gate owns a separate active hold, crash-recovery marker, and terminal skip audit.",
      "coupling": "Local to the Topic-59 publisher and its construction seam; no Topic59PublicationLedger state/schema change and no provider adapter policy.",
      "testability": "High. Direct projector tests can prove claim is never invoked, and dispatcher/scheduler tests can independently prove typed success propagation.",
      "migration_cost": "Two small new runtime modules, focused publisher/dispatcher/result propagation, and sealed transaction/package changes.",
      "failure_modes": "Invalid maintenance state returns a typed refusal/incident before claim; crash recovery completes from hold.consuming.json; normal no-authority profiles remain unchanged.",
      "verdict": "RECOMMENDED"
    },
    {
      "id": "B",
      "name": "Dispatcher-level maintenance gate",
      "design": "Evaluate the hold in _dispatch_customer and skip constructing Topic59DayCardProjector when valid.",
      "coupling": "Fewer publisher changes, but policy becomes coupled to coordinator/profile construction and every direct projector caller remains a bypass unless the projector is made private.",
      "testability": "Moderate. Full dispatcher fixtures are required for the core guarantee; unit calls to Topic59DayCardProjector cannot prove the guard.",
      "migration_cost": "Initially smaller, but making all publication entry points private or duplicating checks costs more and creates long-term bypass risk.",
      "failure_modes": "A future or existing direct publisher call can reach claim without maintenance evaluation; this is unacceptable for the required universal pre-claim fence.",
      "verdict": "VIABLE_ONLY_IF_THE_PUBLISHER_IS_MADE_PRIVATE; NOT_SELECTED"
    },
    {
      "id": "C",
      "name": "Scheduler-wide disabled/noop switch",
      "design": "Treat the nutrition tick as disabled or healthy before weekly dispatch.",
      "coupling": "Very low code cost but suppresses unrelated work and cannot bind candidate/config/route/customer/day or produce a truthful Topic-59 terminal audit.",
      "testability": "Easy but misleading: scheduler ok would prove capability absence, not successful weekly maintenance handling.",
      "migration_cost": "Low.",
      "failure_modes": "False health and unbounded suppression; repeats tomorrow unless an operator reverses state.",
      "verdict": "REJECTED"
    }
  ],
  "recommendation": {
    "selected_option": "A",
    "reason": "It is the smallest architecture that makes the required guarantee at the last non-I/O boundary shared by all Topic-59 publication calls. It preserves the existing delivery ledger as truthful provider history, makes the maintenance audit independently truthful, and avoids a general feature-flag or enterprise control plane.",
    "assumed_trust_boundary": "The fresh preseal/package, its exact approval phrase, the successor systemd credential copy, and the existing Task26 runtime-authority transition are operator-sealed authority. As in the existing architecture, compromise of the profile owner UID or replacement of both sealed credentials and package authority is out of scope; ordinary profile files alone cannot create a valid hold.",
    "deliberately_not_built": [
      "No database, remote control service, feature-flag framework, key-management service, generic maintenance subsystem, customer pause integration, or Topic59 delivery-ledger state extension.",
      "No synthetic sent_audited row, fake message_id, provider receipt, or rewrite of historical incidents.",
      "No reusable hold issuer or runtime API. Only the sealed r71b live controller can materialize the one exact hold."
    ]
  },
  "fresh_namespace": {
    "product_generation": "r71",
    "package_namespace": "r71b-maintenance",
    "candidate_root": "/home/cube/projects/richard/traning coach/.omo/evidence/nutricoach-v150-combined/task-v15r71b-maintenance-candidate",
    "preseal_root": "/home/cube/.hermes/migrations/nutricoach-v1.5.0-combined/live-transaction-preseal-v15-runtime-authority-r71b-maintenance",
    "preflight_root": "/home/cube/.hermes/migrations/nutricoach-v1.5.0-combined/preflight-v15-runtime-authority-r71b-maintenance",
    "authority_id": "nutricoach-v150-v15-runtime-authority-r71b-maintenance",
    "authorization_root": "/home/cube/.hermes/migrations/nutricoach-v1.5.0-combined/live-authorization-v15/nutricoach-v150-v15-runtime-authority-r71b-maintenance",
    "execution_root": "/home/cube/.hermes/migrations/nutricoach-v1.5.0-combined/live-executions-v15/nutricoach-v150-v15-runtime-authority-r71b-maintenance",
    "rehearsal_root": "/home/cube/projects/richard/traning coach/.omo/evidence/nutricoach-v150-combined/task-v15r71b-maintenance-rehearsal",
    "successor_runtime": "/home/cube/.hermes/profiles/dualcoachtest/.strict-runtime/<new-candidate-digest-prefix>-v150/venv",
    "observer_root": "/home/cube/.hermes/migrations/nutricoach-v1.5.0-combined/observer-r71",
    "maintenance_profile_root": "/home/cube/.hermes/profiles/dualcoachtest/data/topic59-maintenance-r71b",
    "maintenance_credential_name": "nutricoach-topic59-maintenance-r71b.json",
    "approval_phrase_format": "AUTHORIZE NUTRICOACH V1.5 R71B MAINTENANCE UPGRADE <package_digest>",
    "tombstones_preserved": [
      "task-v15r71-candidate",
      "task-v15r71-candidate-r2",
      "task-v15r71-candidate-r3",
      "task-v15r71-rehearsal",
      "live-transaction-preseal-v15-runtime-authority-r71",
      "preflight-v15-runtime-authority-r71"
    ]
  },
  "typed_contract": {
    "runtime_types": [
      {
        "symbol": "Topic59MaintenanceDecisionKind",
        "members": ["ALLOW", "NOOP_MAINTENANCE", "DENY"]
      },
      {
        "symbol": "Topic59MaintenanceDecision",
        "fields": {
          "kind": "Topic59MaintenanceDecisionKind",
          "audit_digest": "str | None",
          "reason": "Topic59MaintenanceFailure | None"
        }
      },
      {
        "symbol": "Topic59MaintenanceFailure",
        "members": [
          "AUTHORITY_MISSING_FOR_TARGET_DAY",
          "AUTHORITY_CORRUPT",
          "BINDING_MISMATCH",
          "HOLD_MISSING",
          "HOLD_CORRUPT",
          "HOLD_NOT_YET_VALID",
          "HOLD_EXPIRED",
          "HOLD_REPLAYED",
          "AUDIT_CORRUPT",
          "FILESYSTEM_CONTRACT"
        ]
      },
      {
        "symbol": "Topic59PublicationDisposition",
        "new_member": "NOOP_MAINTENANCE = 'noop_maintenance'"
      },
      {
        "symbol": "Topic59PublicationResult",
        "new_field": "maintenance_audit_digest: str | None = None",
        "invariant": "NOOP_MAINTENANCE requires logical_key and maintenance_audit_digest, and requires message_id is None and reason is None."
      },
      {
        "symbol": "WeeklyOperationsDispatchResult",
        "fields": {
          "failures": "tuple[str, ...]",
          "topic59_dispositions": "tuple[Topic59PublicationDisposition, ...]"
        },
        "invariant": "maintenance_noop is true when at least one Topic-59 result is NOOP_MAINTENANCE and failures is empty."
      },
      {
        "symbol": "NutritionScheduledTickOutcome",
        "fields": {
          "disposition": "Literal['completed', 'noop_maintenance']"
        },
        "purpose": "Typed SendResult.raw_response payload used only by the scheduler bridge; it prevents a maintenance completion from being labeled sent."
      },
      {
        "symbol": "LaunchResult",
        "new_field": "maintenance_noop: bool = False",
        "invariant": "maintenance_noop and sent are mutually exclusive."
      }
    ],
    "authority_schema": {
      "model": "Topic59MaintenanceAuthorityV1",
      "strictness": "Pydantic frozen, strict, extra=forbid; canonical UTF-8 JSON plus one newline; maximum 8192 bytes.",
      "fields": {
        "schema": "Literal['nutricoach-topic59-maintenance-authority-v1']",
        "authority_id": "Literal['nutricoach-v150-v15-runtime-authority-r71b-maintenance']",
        "product_generation": "Literal['r71']",
        "package_namespace": "Literal['r71b-maintenance']",
        "package_digest": "64 lowercase hex",
        "hold_sha256": "64 lowercase hex",
        "hold": "Topic59MaintenanceHoldV1"
      },
      "authentication": "The authority document is included in the package digest and preseal manifest, copied byte-for-byte to the successor runtime-authority directory as a 0400 systemd credential, and loaded only from CREDENTIALS_DIRECTORY. Runtime suppression never trusts a profile hold without this credential."
    },
    "hold_schema": {
      "model": "Topic59MaintenanceHoldV1",
      "strictness": "Pydantic frozen, strict, extra=forbid; exact canonical bytes must hash to authority.hold_sha256.",
      "fields": {
        "schema": "Literal['nutricoach-topic59-maintenance-hold-v1']",
        "hold_id": "64 lowercase hex derived from the canonical bound fields plus a preseal nonce",
        "authority_id": "exact r71b-maintenance authority id",
        "package_digest": "exact package digest",
        "purpose": "Literal['r71_cron_health_recovery']",
        "max_consumptions": "Literal[1]",
        "candidate_digest": "exact new candidate digest",
        "config_digest": "exact successor WeeklyOperationsConfig.digest",
        "route_digest": "exact Topic59Projection.route_digest",
        "customer_identity_digest": "exact opaque current customer digest",
        "card_slot": "exact Topic59Projection.card_slot",
        "kst_day": "exact ISO KST day",
        "not_before": "aware +09:00 timestamp",
        "expires_at": "aware +09:00 timestamp"
      },
      "time_rules": [
        "not_before and expires_at must both fall on kst_day.",
        "5 minutes <= expires_at - not_before <= 30 minutes.",
        "expires_at must be no later than the next KST midnight.",
        "First consumption requires not_before <= runtime.now < expires_at. A previously written valid terminal audit remains authoritative through the rest of kst_day."
      ]
    },
    "skip_audit_schema": {
      "model": "Topic59MaintenanceSkipAuditV1",
      "path": "data/topic59-maintenance-r71b/skip-audit.json",
      "storage": "One atomically replaced, fsynced terminal document, not a row in weekly-operations-topic59.jsonl.",
      "fields": {
        "schema": "Literal['nutricoach-topic59-maintenance-skip-audit-v1']",
        "hold_id": "exact hold id",
        "hold_sha256": "exact credential-bound hold hash",
        "authority_id": "exact r71b-maintenance authority id",
        "package_digest": "exact package digest",
        "candidate_digest": "exact projection/hold candidate",
        "config_digest": "exact projection/hold config",
        "route_digest": "exact projection/hold route",
        "customer_identity_digest": "exact projection/hold customer",
        "card_slot": "exact projection/hold slot",
        "kst_day": "exact projection/hold day",
        "recorded_at": "actual aware KST runtime time, within first-use validity window",
        "terminal_state": "Literal['maintenance_skipped']",
        "disposition": "Literal['noop_maintenance']",
        "sent": "Literal[false]",
        "delivered": "Literal[false]",
        "message_id": "None only",
        "provider_receipt": "None only",
        "provider_calls": "Literal[0]",
        "network_calls": "Literal[0]",
        "row_digest": "SHA-256 of canonical fields excluding row_digest"
      },
      "forbidden_content": [
        "No card text, raw customer key, raw user/chat/topic id, provider response, or customer answer value.",
        "No operation=send/edit and no Topic59LedgerState value.",
        "No sent_audited, delivered, or message-id substitution."
      ]
    }
  },
  "filesystem_contract": {
    "paths": {
      "active": "data/topic59-maintenance-r71b/hold.json",
      "consuming": "data/topic59-maintenance-r71b/hold.consuming.json",
      "audit": "data/topic59-maintenance-r71b/skip-audit.json",
      "lock": "data/topic59-maintenance-r71b/maintenance.lock"
    },
    "directory_checks": [
      "Open the profile and data directories without following links, then create/open topic59-maintenance-r71b using a trusted parent dir_fd.",
      "The maintenance directory must be a real directory, owned by the profile uid/gid, mode 0700, and never a symlink."
    ],
    "file_checks": [
      "Use openat-style dir_fd operations with O_NOFOLLOW|O_CLOEXEC for every existing file.",
      "active, consuming, audit, and lock must be regular files, profile-owned, nlink=1; active/consuming/audit/lock modes are exactly 0600.",
      "Credential must be a regular non-symlink, nlink=1, effective-uid owned systemd credential, mode 0400, and exact canonical bytes.",
      "Reject oversized, empty, noncanonical, trailing-data, duplicate-key, unknown-field, or wrong-schema JSON.",
      "All writes use full-write loops, fsync(file), atomic same-directory replace/rename, fsync(directory), and readback verification."
    ],
    "lock_scope": "Hold maintenance.lock with flock(LOCK_EX) across audit inspection, active-to-consuming rename, audit write, and consuming unlink. The Topic-59 publication ledger lock is never acquired on a maintenance success because claim is never called."
  },
  "gate_algorithm": [
    "1. Topic59DayCardProjector.publish first performs existing weekly authority and route validation and computes the exact Topic59Projection.",
    "2. Topic59MaintenanceGate.evaluate(projection, request.runtime.now) loads and validates the sealed systemd credential and inspects the maintenance directory under the exclusive maintenance lock.",
    "3. If a valid current-day terminal audit exists and matches credential plus projection, reject any simultaneously reintroduced active hold as HOLD_REPLAYED; recover and remove only a matching crash-left consuming marker; return NOOP_MAINTENANCE without any write on ordinary repeated ticks.",
    "4. If no audit exists but hold.consuming.json exists, validate it exactly, atomically write the terminal audit, unlink consuming, fsync the directory, and return NOOP_MAINTENANCE. This is crash completion, not a second consumption.",
    "5. If a valid active hold exists, require first-use time validity, atomically rename hold.json to hold.consuming.json and fsync the directory, atomically write/fsync/readback skip-audit.json, unlink consuming and fsync the directory, then return NOOP_MAINTENANCE.",
    "6. If the credential targets the projection's KST day but no valid terminal/active/recoverable state exists, return DENY. Never fall through to claim during the authorized target day because a missing hold would otherwise send.",
    "7. If the credential and all maintenance artifacts target a prior KST day, and active/consuming are absent and the prior audit is valid, return ALLOW for the new-day projection. This is the automatic release; no operator toggle is needed.",
    "8. Only ALLOW reaches Topic59PublicationLedger.claim. NOOP_MAINTENANCE returns Topic59PublicationResult(NOOP_MAINTENANCE, logical_key, message_id=None, maintenance_audit_digest=...). DENY returns a typed REFUSED/INCIDENT result that the dispatcher records as cron error with zero transport calls."
  ],
  "one_use_expiry_replay_semantics": {
    "one_use": "Exactly one hold_id can create exactly one terminal audit. The active hold is consumed by rename, not copied; the terminal audit is never appended twice.",
    "repeat_ticks": "No active hold is needed after the first success. The valid same-day terminal audit returns the same NOOP_MAINTENANCE and audit digest on every repeated tick without changing any file.",
    "crash_recovery": "hold.consuming.json is the only recognized interrupted-consumption marker. Its exact credential hash allows completion after a crash. A partial audit cannot survive atomic replace; a complete audit plus consuming marker is finalized by unlinking the marker.",
    "physical_replay": "Reintroducing hold.json after a terminal audit is a replay and returns DENY; it is not treated as an idempotent scheduler repeat. No provider call or new audit occurs.",
    "expiry": "An active or consuming hold first observed after expires_at returns DENY and cannot create a successful audit. A terminal audit created before expiry remains effective until KST day rollover.",
    "next_day": "At a projection whose kst_day differs from the prior audit/credential day, with active and consuming absent, the gate returns ALLOW. The old audit and read-only credential remain evidence only and cannot suppress tomorrow."
  },
  "scheduler_propagation": {
    "publisher": "NOOP_MAINTENANCE is a successful Topic59PublicationDisposition and is not in the dispatcher's REFUSED/INCIDENT failure set.",
    "dispatcher": "WeeklyOperationsDispatchResult preserves failures and Topic-59 dispositions rather than reducing all success to an empty tuple.",
    "telegram_tick": "The authorized tick returns SendResult(success=True, message_id=None, raw_response=NutritionScheduledTickOutcome('noop_maintenance')) when the maintenance path is the only current Topic-59 action and no other scheduled work fails.",
    "cron_bridge": "launch_scheduled_card recognizes the typed outcome and returns LaunchResult(maintenance_noop=True, sent=False, error=None).",
    "cron_record": "run_one_job writes 'Status: maintenance no-op completed', calls mark_job_run(job_id, True, None), and never prints 'launch card sent' for this disposition.",
    "zero_call_scope": "RevalidatingTopic59Transport.send/edit is never instantiated for delivery after the gate result, Topic59PublicationLedger.claim is never called, and fake provider/socket instrumentation observes send=0, edit=0, network=0. Normal gateway Telegram polling connectivity is outside this disposition and must be reported separately rather than mislabeled as a dispatch provider call."
  },
  "live_transaction_lifecycle": {
    "preparation": [
      "The preseal command requires explicit --maintenance-kst-day, --maintenance-not-before, and --maintenance-expires-at values; no hidden wall-clock default is accepted.",
      "The preparer derives the exact successor config postimage, current-day Topic59Projection, route/customer/card-slot digests, complete no-send oracle, hold bytes, hold hash, and authority credential. All are included in sealed-target.json, package.json, package-manifest.json, and the approval phrase digest.",
      "The fresh protected inventory is captured using current code and current profile state. It is not copied from r63 or r71."
    ],
    "ordered_phases": [
      "PREFLIGHT: verify fresh r71b roots absent, immutable tombstones unchanged, exact known r70 exception/readiness rules, complete no-send oracle, protected inventory, current Topic-59 ledger hash, and hold window.",
      "RESERVED: reserve the fresh global authorization root once; old r71 approval cannot reserve this namespace.",
      "STOPPING/SNAPSHOT: stop the gateway and durably snapshot existing mutable postimages, including cron/jobs.json for recovery evidence, after the stop.",
      "INSTALLED/MIGRATED: install exact new wheels, apply normal capacity/weekly authority migration, and verify the derived successor config/route/customer/day binding still exactly matches the sealed maintenance authority.",
      "MAINTENANCE_ARMED: create data/topic59-maintenance-r71b mode 0700 and atomically write exact hold.json mode 0600; add the exact maintenance credential to successor runtime-authority and the systemd LoadCredential postimage. No audit exists yet.",
      "START_WATCH_ARMED: subscribe to the cron directory's exact replacement/write event before starting the service. Use a bounded event wait, never sleep or timing polling.",
      "STARTED/POST_FENCE: promote Task26 authority, switch systemd, start the successor, and verify candidate/runtime/capacity/inbox/credential postimages.",
      "MAINTENANCE_CONFIRMED: await a cron/jobs.json state change with a bounded timeout; require a post-start last_run_at, last_status=ok, the typed maintenance output, valid terminal audit, active/consuming absence, unchanged weekly-operations-topic59.jsonl hash, unchanged historical incident row digests, and Topic-59 provider/network calls zero.",
      "COMMITTING/COMMITTED: only after MAINTENANCE_CONFIRMED consume the fresh global authorization as SUCCEEDED and advance the phase to COMMITTED."
    ],
    "event_wait_contract": "Watch the cron directory before host.start because jobs.json is atomically replaced. Await IN_MOVED_TO/IN_CLOSE_WRITE for jobs.json with select/selector timeout no greater than 120 seconds, reopen with no-follow checks, and validate semantic state. Tests subscribe before triggering and use a bounded timeout; fixed sleeps and polling loops are forbidden.",
    "roll_forward_recovery": "If the controller dies at or after MAINTENANCE_CONFIRMED, a fresh controller verifies the exact successor, audit, cron-ok record, unchanged Topic-59 ledger, and global authority state, then completes COMMITTING/COMMITTED. It must not roll back a proven healthy maintenance completion merely because the final phase write was interrupted."
  },
  "preflight_rules": {
    "normal_gates_retained": [
      "Fresh r71b authorization/execution/successor roots absent and approval unused.",
      "Existing r71 candidates/preseal/preflight/rehearsal hashes and immutable modes unchanged.",
      "r70 authority consumed SUCCEEDED, execution COMMITTED, gateway active/running, NRestarts=0, current r70 candidate/runtime, Telegram sockets healthy, capacity five, Channel Inbox OFF, prepared invite/customer projection/draft/binding/events preserved.",
      "Fresh package/candidate/preseal verifiers pass from immutable artifacts.",
      "No unclassified protected drift and no unexpected maintenance path exists."
    ],
    "known_r70_cron_exception": {
      "accepted_dispositions": ["HEALTHY", "KNOWN_R70_CANONICAL_PIN_ERROR"],
      "exact_exception_requirements": [
        "The package binds task-10-cron-no-send-recovery-analysis.json SHA-256 968a3ea4e15d149736d47c239d410ed9b88b7dbb20e0703214a2a6b19c3025d0.",
        "There is exactly one enabled job with id 6e042d5dff68, name 'NutriCoach schedule dispatcher', schedule '* * * * *', inline_card 'nutrition-coaching-tick', delivery 'local', and state scheduled.",
        "Its latest status is error and last_error is exactly 'weekly operations failed: canonical authority identity drift'. A different error, disabled/paused job, changed identity, or changed schedule is not excepted.",
        "The running candidate is exactly r70 81a7a06ec2e7a1595784c92ab61df0df7e138d13a2620d9a917e94999e7f7a04 with NRestarts=0.",
        "The complete next-tick oracle proves all non-Topic59 provider work is zero and exactly one current-day Topic-59 projection matches the sealed hold."
      ],
      "effect": "Only the cron-latest-success prerequisite is deferred into the transaction's MAINTENANCE_CONFIRMED phase. No authority, config, service, protected-state, or no-send check is bypassed."
    },
    "historical_incident_exception": {
      "rule": "The old restart oracle's requirement uncertain_pending_delivery_count=0 is replaced only for the two exact package-bound historical card slots whose latest rows are sending with message_id absent. Their row digests and full publication-ledger file hash are sealed and must remain unchanged before, during, and after the transaction.",
      "not_allowed": "No new current-day prepared/sending incident, no old-slot retry, and no conversion to failed/unknown/sent_audited."
    },
    "observer_readiness": {
      "rule": "Preserve observer-r70 bytes and chain. Accept either an actual latest PASS or a sealed, read-only re-evaluation that uses the fixed configured-root collector and returns PASS while the old latest failure set is exactly ['first_day_status']. Any other observer failure blocks launch.",
      "reason": "This is not a false PASS append: it is a readiness proof for the already diagnosed stale-root collector. After commit, Todo 11 creates the canonical observer-r71 chain from the fixed collector."
    },
    "hold_window": "At launcher invocation, now must be within the package approval window and leave at least 3 minutes before hold expiry; otherwise stop before reservation."
  },
  "rollback_behavior": {
    "principle": "Rollback is a safety outcome, never launch success. A fresh r70 process cannot be restarted with its cron enabled because fresh pins can send.",
    "before_service_stop": "If failure occurs before stopping r70, leave the existing process and job untouched; consume no authority unless reservation already occurred.",
    "after_service_stop_before_maintenance_confirmed": [
      "Restore protected r70 bytes/runtime authority/unit/dropin and remove successor-owned runtime, active hold, consuming marker, and uncommitted temporary files.",
      "Before restarting r70, atomically place job 6e042d5dff68 into the supported paused state while preserving its truthful last_status/last_error. Record ROLLED_BACK_SAFE_CRON_PAUSED, not COMMITTED.",
      "Restart r70 only with that cron job paused. The retained original jobs.json post-stop snapshot is recovery evidence, not automatically restored while r70 remains unsafe.",
      "Consume the fresh r71b authorization as FAILED; no retry of the same namespace is allowed."
    ],
    "after_terminal_audit": [
      "Do not erase a valid skip-audit.json; it is truthful append-only evidence that the day was maintenance-skipped.",
      "If MAINTENANCE_CONFIRMED is fully verifiable, roll forward commit instead of rollback.",
      "If a separate postcommit manual-QA failure requires rollback, restore r70 with cron paused. r70 does not understand the r71b audit, so pausing is mandatory."
    ],
    "failure_receipts": "Rollback evidence must report whether audit exists, whether the job is paused, exact old incident hashes, provider/network/customer calls zero, and why success was not claimed."
  },
  "protected_and_volatile_inventory": {
    "fresh_inventory_requirement": "Generate and authenticate a fresh r71b snapshot-before.json and classifier digest. Never copy the inherited r71 snapshot because it predates the current Topic-59 ledger and maintenance contract.",
    "stable_protected": [
      "config.yaml",
      "customers/registry.json",
      "all currently classified stable customer draft/binding/event/canonical files",
      "data/owner-actions/customer-service-state.json",
      "data/scheduled-deliveries-fence.json",
      "data/weekly-operations-topic59.jsonl",
      "unit/drop-in and existing runtime-authority sources",
      "current authority registry/qualification ledger"
    ],
    "explicit_volatile": [
      "cron/jobs.json",
      "data/scheduled-deliveries.jsonl",
      "data/topic59-maintenance-r71b/hold.json",
      "data/topic59-maintenance-r71b/hold.consuming.json",
      "data/topic59-maintenance-r71b/skip-audit.json",
      "data/topic59-maintenance-r71b/maintenance.lock"
    ],
    "classification_rule": "Add the six maintenance files as exact VOLATILE_FILES entries; do not add a broad data/topic59-maintenance-* prefix. Existing .lock wildcard remains, but package verification must still enumerate the exact maintenance path set.",
    "volatile_does_not_mean_untrusted": "Maintenance files are allowed to change during the transaction but remain governed by credential digest, schema, ownership, mode, no-follow, one-use, and postcondition checks. Any other newly appearing path below topic59-maintenance-r71b is a blocker.",
    "publication_ledger_rule": "weekly-operations-topic59.jsonl stays stable/protected during this transaction. Its preflight hash and the two historical incident row digests must equal post-maintenance values. Normal future-day publication can mutate it after this transaction under the existing ledger contract."
  },
  "postcommit_release": {
    "immediate_state": [
      "hold.json absent",
      "hold.consuming.json absent",
      "one valid terminal skip-audit.json present",
      "weekly-operations-topic59.jsonl unchanged",
      "cron latest status ok with truthful maintenance-noop output",
      "fresh authorization CONSUMED/SUCCEEDED and execution COMMITTED"
    ],
    "same_day": "Every subsequent current-day tick returns NOOP_MAINTENANCE from the terminal audit before claim. It makes no provider call and does not append another audit or delivery row.",
    "credential_retention": "Keep the read-only successor maintenance credential and terminal audit through the day so repeats remain authenticated. Do not restart solely to remove a credential. The active hold has already been removed.",
    "tomorrow": "For a new KST day, the prior authority/audit binding does not match the new projection and active/consuming are absent, so the gate returns ALLOW and existing Topic59PublicationLedger behavior resumes normally. No operator resume and no config change are required.",
    "later_cleanup": "A future separately qualified package may archive the expired credential/audit after the observation window; cleanup is not required for correct next-day behavior and is not part of this recovery."
  },
  "observer_design": {
    "required_fix": "Retain the current _day_status_days(profile) behavior that parses nutrition_coaching.weekly_operations_authority_path and never hard-codes the unsuffixed predecessor root.",
    "binding": "Make observer runtime/execution/authorization/candidate values data-bound from a strict sealed observer binding rather than adding a compile-time candidate-digest cycle. The binding is generated from the committed r71b sealed target.",
    "source_inventory": [
      "scripts/nutricoach_v150_observer_contract.py",
      "scripts/nutricoach_v150_observer_runtime.py",
      "scripts/nutricoach_v150_observer_final.py",
      "scripts/nutricoach_v150_seven_day_observer.py",
      "tests/test_nutricoach_v150_seven_day_observer.py"
    ],
    "postcommit": "Todo 11 writes a fresh private observer-r71 binding and chain, updates the checksum manifest/systemd writable path under its authorized workflow, then requires one manual PASS and the next timer PASS linked by previous_row_digest. observer-r70 remains unchanged."
  },
  "files_and_symbols": {
    "new_runtime_files": [
      {
        "path": "gateway/platforms/nutrition_weekly_maintenance_contract.py",
        "symbols": [
          "Topic59MaintenanceAuthorityV1",
          "Topic59MaintenanceHoldV1",
          "Topic59MaintenanceSkipAuditV1",
          "Topic59MaintenanceDecisionKind",
          "Topic59MaintenanceDecision",
          "Topic59MaintenanceFailure"
        ]
      },
      {
        "path": "gateway/platforms/nutrition_weekly_maintenance_store.py",
        "symbols": [
          "Topic59MaintenanceGate",
          "Topic59MaintenancePaths",
          "Topic59MaintenanceGate.for_profile",
          "Topic59MaintenanceGate.evaluate",
          "_open_owned_directory",
          "_read_regular_at",
          "_atomic_write_at",
          "_fsync_directory"
        ]
      }
    ],
    "modified_runtime_files": [
      {
        "path": "gateway/platforms/nutrition_weekly_operations.py",
        "symbols": ["Topic59PublicationDisposition", "Topic59PublicationResult", "Topic59DayCardProjector.__init__", "Topic59DayCardProjector.publish"],
        "change": "Require the gate and invoke it immediately before self._ledger.claim."
      },
      {
        "path": "gateway/platforms/nutrition_weekly_operations_publication_contract.py",
        "symbols": ["Topic59IncidentReason"],
        "change": "Add narrow maintenance authority/audit rejection reasons; do not add a delivery state."
      },
      {
        "path": "gateway/platforms/nutrition_weekly_dispatcher.py",
        "symbols": ["WeeklyOperationsDispatchResult", "_dispatch_customer", "dispatch_weekly_operations_tick"],
        "change": "Construct the profile gate, preserve typed Topic-59 disposition, and continue treating refusal/incident as failure."
      },
      {
        "path": "gateway/platforms/telegram_weekly_host_dispatch.py",
        "symbols": ["_dispatch_weekly_operations_tick", "_run_weekly_operations_dispatch", "NutritionScheduledTickOutcome"],
        "change": "Propagate the typed maintenance success while preserving activation-notice failures."
      },
      {
        "path": "gateway/platforms/telegram.py",
        "symbols": ["_send_nutrition_coaching_tick_authorized"],
        "change": "Return typed noop_maintenance raw_response only when all work succeeds; do not create message_id."
      },
      {
        "path": "cron/physique_inline_card.py",
        "symbols": ["_AsyncCardResult", "LaunchResult", "launch_scheduled_card", "_ScheduledTransport"],
        "change": "Translate the typed tick outcome to maintenance_noop=True and sent=False."
      },
      {
        "path": "cron/scheduler.py",
        "symbols": ["run_one_job"],
        "change": "Mark maintenance noop ok and persist truthful output distinct from sent."
      }
    ],
    "modified_package_and_live_files": [
      "scripts/nutricoach_v150_live_upgrade_state.py",
      "scripts/nutricoach_v150_host_operations.py",
      "scripts/nutricoach_v150_concrete_host.py",
      "scripts/nutricoach_v150_sealed_target.py",
      "scripts/nutricoach_v150_sealed_controller.py",
      "scripts/nutricoach_v150_controller_worker.py",
      "scripts/nutricoach_v150_detached_bootstrap.py",
      "scripts/execute_nutricoach_v150_sealed_live.py",
      "scripts/prepare_nutricoach_v150_v15_preseal.py",
      "scripts/verify_nutricoach_v150_preseal_v15.py",
      "scripts/rehearse_nutricoach_v150_v15.py",
      "scripts/seal_nutricoach_v150_candidate.py",
      "scripts/verify_nutricoach_v150_candidate.py",
      "scripts/verify_nutricoach_v150_candidate_inputs.py"
    ],
    "script_symbol_changes": [
      "Change PRESEAL/PREFLIGHT/AUTHORITY_ID/default candidate/rehearsal constants to the exact r71b-maintenance roots.",
      "Add sealed maintenance authority generation, package binding, systemd credential postimage, active-hold creation, complete no-send preflight, event-driven cron completion watch, maintenance phase/recovery, and rollback cron pause.",
      "Add every new/changed wheel source and test to candidate_source_paths, SUCCESSOR_OVERLAY_PATHS, candidate wheel-member verification, controller closure REQUIRED set, and package manifests.",
      "Preserve old r71 package digests in supersession/tombstone evidence and reject old approval phrases before reservation."
    ],
    "observer_files": [
      "scripts/nutricoach_v150_observer_contract.py",
      "scripts/nutricoach_v150_observer_runtime.py",
      "scripts/nutricoach_v150_observer_final.py",
      "scripts/nutricoach_v150_seven_day_observer.py",
      "tests/test_nutricoach_v150_seven_day_observer.py"
    ]
  },
  "test_plan": {
    "tdd_red_first": [
      "Valid credential plus hold currently reaches Topic59PublicationLedger.claim and provider; new test must fail by replacing claim with an assertion and expecting NOOP_MAINTENANCE.",
      "Current scheduler labels a successful no-provider tick as sent; new test must fail expecting maintenance_noop=True, sent=False, and truthful cron output.",
      "Current transaction has no hold arm/consume/recovery phases and no narrow r70 cron exception; controller tests must fail before implementation.",
      "Current observer candidate closure omits the configured-root fix; closure test must fail until observer source/binding is included."
    ],
    "new_test_files": [
      "tests/gateway/test_nutrition_weekly_topic59_maintenance.py",
      "tests/gateway/test_nutrition_weekly_topic59_maintenance_failures.py",
      "tests/gateway/test_nutrition_weekly_dispatcher_maintenance.py",
      "tests/test_nutricoach_v150_r71b_maintenance_transaction.py"
    ],
    "existing_test_files_to_extend": [
      "tests/gateway/test_nutrition_weekly_operations_topic59.py",
      "tests/gateway/test_nutrition_weekly_operations_topic59_failures.py",
      "tests/gateway/test_nutrition_weekly_operations_topic59_r2_slots.py",
      "tests/gateway/test_nutrition_weekly_dispatcher_host_matrix.py",
      "tests/cron/test_physique_inline_card.py",
      "tests/cron/test_scheduler.py",
      "tests/test_nutricoach_v150_sealed_controller.py",
      "tests/test_nutricoach_v150_v15_authority_adversarial.py",
      "tests/test_nutricoach_v150_v15_safety.py",
      "tests/test_nutricoach_v150_v15_closure.py",
      "tests/test_verify_nutricoach_v150_candidate.py",
      "tests/test_nutricoach_v150_seven_day_observer.py"
    ],
    "positive_cases": [
      "Valid exact hold: claim raises if called, transport raises if called, result is NOOP_MAINTENANCE, audit terminal fields are truthful, publication ledger unchanged.",
      "Second same-day tick: identical disposition/audit digest, no file mutation, claim/provider/network zero.",
      "Crash after active-to-consuming rename: next tick completes one audit and removes consuming with no provider.",
      "Crash after audit replace before consuming unlink: next tick validates audit, removes consuming, and remains idempotent.",
      "Two concurrent ticks subscribe before trigger: one consumes, both return NOOP_MAINTENANCE, one audit, zero claim/provider.",
      "Historical two latest=sending slots remain exact bytes and are not selected or retried.",
      "Scheduler integration marks last_status ok and output says maintenance no-op completed.",
      "Tomorrow with active/consuming absent ignores prior audit and reaches normal claim; fake transport may send once in a synthetic fixture, proving automatic release."
    ],
    "negative_matrix": [
      "authority absent while a maintenance file exists",
      "malformed/noncanonical/extra-field authority or hold",
      "hold first use before not_before",
      "hold first use at/after expires_at",
      "physical hold replay after terminal audit",
      "wrong candidate digest",
      "wrong config digest",
      "wrong route digest/topic",
      "wrong customer/card_slot/day",
      "symlink at directory, hold, consuming, audit, lock, or credential",
      "wrong owner, gid, mode, nlink, file kind, oversized file",
      "tampered audit digest or false sent/delivered/message_id/provider fields",
      "audit/hold mismatch or unexpected extra maintenance path"
    ],
    "negative_expected_result": "Every negative case returns DENY/REFUSED/INCIDENT, claim=0, send=0, edit=0, network=0, no delivery-state fabrication, and scheduler error rather than false ok.",
    "transaction_cases": [
      "Known exact r70 cron error accepted only with package-bound no-send oracle; any other cron error blocks before reservation.",
      "All original stop/install/migrate/switch/reload/start/post-fence fault stages restore protected bytes and restart r70 only with cron paused.",
      "Interrupted hold writes, fsyncs, rename, audit, completion watch, phase write, authorization consume, and rollback pause are independently injected.",
      "MAINTENANCE_CONFIRMED interrupted commit rolls forward after exact verification.",
      "Postcommit rollback retains truthful audit, restores r70 authority, pauses cron, and never claims launch success."
    ],
    "nondeterminism_rules": "All async/concurrency/controller tests subscribe to the exact event before triggering, await it with a bounded timeout, inject fixed aware KST clocks, and use no sleep, polling delay, or timing luck."
  },
  "qualification_and_release_order": [
    {
      "order": 1,
      "stage": "TDD",
      "requirements": "Write and run the failing tests above; retain red output and exact source hashes. Implement the smallest gate/result/transaction changes, then make the same tests green."
    },
    {
      "order": 2,
      "stage": "Focused diagnostics and affected suites",
      "requirements": "Run LSP on every changed Python file; Ruff, ty, basedpyright, compile without suppression; run all Topic-59, weekly dispatcher, Telegram nutrition tick, cron inline-card/scheduler, transaction/controller, inventory, candidate, preseal, and observer tests once."
    },
    {
      "order": 3,
      "stage": "Full suites",
      "requirements": "Run the full profile suite under UV_OFFLINE=1 with a short isolated basetemp, the complete affected gateway/cron suite, and the complete v1.5 controller/sealer/verifier suite. Any unrelated pre-existing baseline failure is reported, never skipped or deleted."
    },
    {
      "order": 4,
      "stage": "Reproducible wheels",
      "requirements": "From two fresh clean copied inputs with SOURCE_DATE_EPOCH=1704067200 and UV_OFFLINE=1, build Hermes and profile wheels; require byte-identical pairs, ZIP CRC, RECORD hash/size checks, and exact source-member parity including both maintenance modules and propagation files. Remove ambient build/cache outputs."
    },
    {
      "order": 5,
      "stage": "Fresh candidate",
      "requirements": "Prove the r71b candidate root absent and all r71 tombstones unchanged; seal exactly task-v15r71b-maintenance-candidate once; run current-input and canonical candidate verifiers plus mutation/missing-overlay/occupied-root attacks."
    },
    {
      "order": 6,
      "stage": "Fresh preseal",
      "requirements": "Prove r71b preseal/preflight/authority/execution/runtime roots absent; require explicit hold window arguments; generate fresh protected inventory and maintenance authority; freeze the exact package; run detached bootstrap/preseal verifier from outside source."
    },
    {
      "order": 7,
      "stage": "13-case rehearsal",
      "requirements": "Retain exactly one success plus the existing twelve stop-through-post-fence rollback cases. The success case consumes the hold, runs a second same-day idempotency tick and a next-day release tick in a fake profile. Each rollback case proves zero external events, safe r70 cron pause where restart is required, exact protected restoration, and no old-incident mutation. New low-level maintenance interruption boundaries run in the controller test suite without inflating the retained top-level case count."
    },
    {
      "order": 8,
      "stage": "Installed-wheel QA",
      "requirements": "Install only the sealed wheels into a disposable venv outside source, clear PYTHONPATH, install a socket guard before product imports, verify RECORD members/origins, and execute valid hold twice plus the complete negative matrix and tomorrow release. Maintenance-day provider send/edit/network counts must all be zero."
    },
    {
      "order": 9,
      "stage": "Independent closure/integrity/privacy audits",
      "requirements": "Independently re-run candidate/preseal verifiers, exact sealed tests, protected-vs-volatile inventory attacks, hold replay/expiry attacks, historical incident hash comparison, privacy sentinel scan, and installed no-network oracle."
    },
    {
      "order": 10,
      "stage": "Live launch",
      "requirements": "Perform the immediate read-only preflight, capture exact package approval, invoke the immutable r71b launcher exactly once, await event-driven MAINTENANCE_CONFIRMED inside the transaction, inspect COMMITTED receipts without replay, and verify cron ok/audit/ledger/customer state with zero Topic-59 send/edit. No Git, network download, or customer action."
    },
    {
      "order": 11,
      "stage": "Observer r71",
      "requirements": "After committed live verification, create only observer-r71 from the fixed configured-root collector and sealed binding; require manual PASS then timer PASS linked to it. Preserve observer-r70 unchanged."
    }
  ],
  "evidence_contract": {
    "design": ".omo/evidence/nutricoach-telegram-checkin-stepper/task-10-r71b-maintenance-design.json",
    "tdd_and_implementation": ".omo/evidence/nutricoach-telegram-checkin-stepper/task-10-r71b-maintenance-tdd.json",
    "full_qualification": ".omo/evidence/nutricoach-telegram-checkin-stepper/task-10-r71b-maintenance-qualification.json",
    "candidate": ".omo/evidence/nutricoach-telegram-checkin-stepper/task-10-r71b-candidate.json",
    "preseal_and_rehearsal": ".omo/evidence/nutricoach-telegram-checkin-stepper/task-10-r71b-preseal-rehearsal.json",
    "installed_qa": ".omo/evidence/nutricoach-telegram-checkin-stepper/task-10-r71b-installed-qa.json",
    "live": ".omo/evidence/nutricoach-telegram-checkin-stepper/task-10-r71b-production.json",
    "observer": ".omo/evidence/nutricoach-telegram-checkin-stepper/task-11-r71-observer.json",
    "each_receipt_must_include": [
      "exact source/artifact/root hashes and immutable modes",
      "candidate/package/authority/hold/audit binding digests",
      "test commands, exit codes, parsed counts, diagnostics, and one-run determinism",
      "provider send/edit/network counts and customer-message/update counts",
      "publication-ledger before/after hash plus exact historical incident row digests",
      "protected/volatile inventory and unexpected-path count",
      "authorization/phase/replay disposition and rollback/pause state",
      "cleanup inventory and forbidden-effects summary"
    ]
  },
  "risks_and_controls": [
    {
      "risk": "The controller starts a network-capable successor before cron maintenance is observed.",
      "control": "Hold is atomically installed and credential-bound before service start; a target-day missing/invalid hold denies before claim. The completion watch is armed before start."
    },
    {
      "risk": "Separate hold/audit files create a crash window.",
      "control": "active -> consuming rename, atomic audit replace, and recovery from consuming eliminate the no-hold/no-audit send window."
    },
    {
      "risk": "A maintenance success is mislabeled as a message send.",
      "control": "Typed NOOP_MAINTENANCE propagates through dispatcher, Telegram tick, LaunchResult, cron output, and mark_job_run; sent remains false and message_id remains None."
    },
    {
      "risk": "The hold suppresses future legitimate work.",
      "control": "Exact candidate/config/route/customer/card-slot/day binding, short first-use expiry, active hold removal, and prior-day ALLOW semantics make tomorrow automatic."
    },
    {
      "risk": "Rollback restarts unsafe r70 and sends.",
      "control": "Any rollback requiring r70 restart atomically pauses the exact cron job first and reports non-success. A confirmed successor rolls forward instead."
    },
    {
      "risk": "Volatile classification becomes an arbitrary mutation exemption.",
      "control": "Only exact maintenance files are volatile, and their own authenticated schema/ownership/path postconditions are stricter than generic inventory handling."
    },
    {
      "risk": "Same-UID replacement of both profile state and credential authority.",
      "control": "This is the existing explicit operator-authority compromise boundary. The design does not claim cryptographic protection against a principal that can replace the sealed package, systemd credential sources, and runtime together."
    },
    {
      "risk": "The stale observer-r70 latest row blocks a package that contains the fixed collector.",
      "control": "Use a narrow sealed read-only readiness re-evaluation only for the exact diagnosed first_day_status failure, then establish the canonical observer-r71 chain after commit."
    }
  ],
  "done_definition": [
    "One fresh r71b-maintenance authority is CONSUMED/SUCCEEDED exactly once and execution is COMMITTED.",
    "Cron latest run after successor start is ok with typed/truthful NOOP_MAINTENANCE output.",
    "Current-day skip audit is valid and terminal; hold and consuming files are absent.",
    "Topic59PublicationLedger.claim, RevalidatingTopic59Transport.send/edit, provider, and dispatch-network counts are zero for the maintenance tick and its same-day repeat.",
    "weekly-operations-topic59.jsonl and the two historical latest=sending incidents are unchanged.",
    "No customer message/update or fabricated provider state exists.",
    "A synthetic next-day installed test proves normal ALLOW behavior, and live semantics require no operator resume.",
    "Observer-r71 manual PASS and timer-linked PASS complete the original plan after live commit."
  ],
  "forbidden_effects_during_this_design_task": {
    "git_or_github_actions": 0,
    "source_edits": 0,
    "test_edits": 0,
    "candidate_or_preseal_edits": 0,
    "live_profile_or_state_edits": 0,
    "service_or_timer_actions": 0,
    "cron_runs_or_job_mutations": 0,
    "observer_appends": 0,
    "network_or_provider_actions": 0,
    "customer_messages_or_updates": 0,
    "authority_reservations_or_consumptions": 0
  }
}
