You are running as an omo senpi-task child.
Task id: st_01a05cac.
Parent session: 01a04e1a-4e0a-7c69-845d-0b5d1e71f82d.
Root session: 01a04e1a-4e0a-7c69-845d-0b5d1e71f82d.
Depth: 1.

Task:
TASK: Fresh independent AdversarialVerify of DISPOSABLE_PACKAGE_PASS; authoritative roots remain forbidden. DELIVERABLE: `/home/cube/projects/richard/traning coach/.omo/evidence/nutricoach-telegram-checkin-stepper/task-10-r71b-disposable-package-adversarial.json`, verdict confirmed/needs-fix confidence/blocker_count/evidence/cleanup. WORKTREE exact. No Git/GitHub, source edits, live/network/customer/provider, authoritative r71b roots. Rehash complete source/test inventory from runtime/controller/package receipts and verify old r71 tombstones unchanged. Independently build clean A/B Hermes/profile wheels twice under fresh /tmp; require exact expected hashes or explain deterministic mismatch, byte-identical, ZIP CRC/all RECORD and every wheel-hosted maintenance/controller/observer source parity including dispatch_result. Seal independent disposable candidate from exact three Task10 evidence files; verify candidate input/source381/evidence3, omission/malformed/path/schema/status/hash/tamper18/consistent rewrite/old approval rejection. Prepare disposable preseal with exact Sep2 02:00-02:30 window; independently reconstruct binding inputs/scope/oracle from authoritative sources, package_binding and final package digests, hold/authority/credential/target manifests; validate quiet-path non-Topic59 due0 and old sending slots unchanged. Run installed wheels outside source/PYTHONPATH empty/socket guard: exact sealed74, maintenance61, actual disposable COMMITTED, preconfirm terminal paused rollback service running, fresh confirmed recovery real post_fence, 13+maintenance rehearsal external0. Manual Sep2 02:00/02:01 two noops/audit1/ledger unchanged/provider-network-customer0/no second write; Sep3 normal fake path1. Run source suites maintenance238/controller129/final39/candidate27 and strict diagnostics/no-excuse. Fault copies mutate wheel/RECORD/source/evidence/hold/oracle/credential/phase and require rejection. Cleanup every verifier temp. Prove authoritative candidate/preseal/preflight/auth/execution/rehearsal/observer/profile maintenance roots absent. Confirm only if exact frozen source is safe for one authoritative seal.

<Category_Context name="deep">
You are operating in DEEP mode. This is the category reserved for goal-oriented autonomous work on hairy problems that reward thorough exploration and comprehensive solutions.

The orchestrator chose this category because the task benefits from depth over speed. You should feel empowered to spend the time needed: five to fifteen minutes of silent exploration before the first edit is normal and correct. Rushing to implementation on a deep task is a failure mode, not a feature.

# How deep mode adjusts the base behavior

**Exploration budget: generous.** Read the files you need, trace dependencies both directions, fire 2-5 explore/librarian sub-agents in parallel for broader questions. Build a complete mental model before the first `apply_patch`. Exploration here is an investment, not overhead.

**Goal, not plan.** You receive a GOAL describing the desired outcome. You figure out HOW to achieve it. The orchestrator deliberately did not hand you a step-by-step plan; producing one and asking for approval is not what was asked. Execute.

**Atomic task treatment.** When the goal contains numbered steps or phases, treat them as sub-steps of ONE task and execute them all in this turn. Splitting them across turns is wrong unless they reveal an architectural blocker that requires the user's input. If the "steps" turn out to be genuinely independent tasks that should have been separate delegations, flag that in your final message and refuse the ones beyond scope.

**Root cause bias.** Prefer root-cause fixes over symptom fixes. A null check around `foo()` is a symptom fix; fixing whatever causes `foo()` to return unexpected values is the root fix. Trace at least two levels up before settling on an answer. In deep mode, you have permission (and the expectation) to do the deeper fix.

**Ambition scaled to context.** For brand-new greenfield work, be ambitious. Choose strong defaults, avoid AI-slop aesthetics, produce something you would be proud to hand to another senior engineer. For changes in an existing codebase, be surgical and respect the existing patterns; depth does not mean invasiveness.

**Completion bar: full delivery.** "Simplified version", "proof of concept", and "you can extend this later" are not acceptable deliveries for a deep task. The orchestrator routed here specifically for a complete solution. If you hit a genuine blocker (missing secret, design decision only the user can make, three materially different attempts all failed), document it and return; otherwise, finish the task.

**Status cadence: sparse.** The user is not on the other side of this conversation; the orchestrator is, and they will synthesize your progress. Send commentary only at meaningful phase transitions (starting exploration, starting implementation, starting verification, hitting a genuine blocker). Do not narrate every tool call; silence during focused work is expected.
</Category_Context>


**Inspecting environment and scripts**

I read this as an independent, disposable adversarial verification of the frozen Task 10 package - I’ll reconstruct the receipts and inputs without touching authoritative roots, exercise clean builds, installed-wheel/runtime/fault paths, clean all verifier state, and write only the requested JSON verdict.

bash

pwd; printf '\nPI env:\n'; env | sort | grep '^PI_' || true; printf '\nTop-level:\n'; find . -maxdepth 2 -mindepth 1 -printf '%y %p\n' | sort | head -300

find .omo/evidence/nutricoach-telegram-checkin-stepper -maxdepth 2 -type f -printf '%f\t%p\n' 2>/dev/null | sort | tail -300

find . -path './.git' -prune -o -type f \( -iname '*r71*' -o -iname '*task-10*' -o -iname '*package*' -o -iname '*preseal*' \) -printf '%p\n' | sort | head -500

find . -path './.git' -prune -o -type f -printf '%p\n' | sort | head -500


/home/cube/projects/richard/traning coach

PI env:
PI_CODING_AGENT=true
PI_MODEL=gpt-5.6-sol
PI_PROMPT_CACHE_SAFE_WAIT_SECONDS=270
PI_PROVIDER=openai-codex
PI_REASONING_LEVEL=medium
PI_SESSION_FILE=/home/cube/projects/richard/traning coach/.omo/senpi-task/children/st_01a05cac/sessions/st_01a05cac/2026-09-01T11-13-43-704Z_01a05cac-cd18-7bb0-ba79-d380e3b5e96d.jsonl
PI_SESSION_ID=01a05cac-cd18-7bb0-ba79-d380e3b5e96d

Top-level:
d ./.agents
d ./.agents/skills
d ./.claude
d ./.claude/skills
d ./.gjc
d ./.gjc/_session-019f844a-6ff5-7000-b142-110ba6444221
d ./.gjc/_session-019f844f-81d2-7000-ab7e-4329cb7690ac
d ./.gjc/_session-019f8451-ff60-7000-afae-4f0f55ce5a6a
d ./.gjc/_session-019f8454-b4f5-7000-896e-8d6ccff8d05d
d ./.gjc/_session-019f8455-0033-7000-ba00-d152b30850b2
d ./.gjc/_session-019f8455-334a-7000-99ca-318dfd0e06b1
d ./.gjc/_session-019f846c-99b3-7000-a2ad-2f8d6c734baf
d ./.gjc/_session-019f846e-663a-7000-bfa0-ff47de5897c3
d ./.gjc/_session-019f846f-0695-7000-93c7-15f5a8d4db04
d ./.gjc/_session-019f847e-310a-7000-8b8f-0160eb64fc2e
d ./.gjc/_session-019f847e-310c-7000-a618-40508740047a
d ./.gjc/_session-019f847e-310d-7000-8d31-c3861af794b1
d ./.gjc/_session-019f8496-8107-7000-b332-505142857084
d ./.gjc/_session-019f8496-ef43-7000-a011-4f9a29086de2
d ./.gjc/_session-019f8498-6619-7000-9eed-b7afb65c350f
d ./.gjc/_session-019f8498-9da6-7000-917e-e3ac5623d916
d ./.gjc/_session-019f849e-f00d-7000-a9ed-e5ef0674b723
d ./.gjc/_session-019f849f-1bd1-7000-9fda-4455eae5634f
d ./.gjc/_session-019f84a4-1492-7000-bd87-1631888b7753
d ./.gjc/_session-019f84a4-3b42-7000-934d-8fa7510ba3ca
d ./.gjc/_session-019f84a9-cc49-7000-ab9e-babf6a31cdca
d ./.gjc/_session-019f84a9-f883-7000-9d80-7659247fb6e9
d ./.gjc/_session-019f84af-1e26-7000-9f7e-e32b43723eb4
d ./.gjc/_session-019f84af-3d2d-7000-80d0-b76bdf8a5abc
d ./.gjc/_session-019f84b8-512c-7000-88c9-98e669659d58
d ./.gjc/_session-019f84ba-3eec-7000-ba03-1ca9a4315ae4
d ./.gjc/_session-019f84be-0f4e-7000-a1d6-418c0f0ca3e5
d ./.gjc/_session-019f84be-4e97-7000-b9ff-3d81b62dabb0
d ./.gjc/_session-019f84be-88ca-7000-9d18-01e667a32b74
d ./.gjc/_session-019f84be-f5c4-7000-aa65-0d33737b3595
d ./.gjc/_session-019f84bf-15ea-7000-8bbf-a1018af6784e
d ./.gjc/_session-019f84c0-ec00-7000-a553-e90f2ce695e1
d ./.gjc/_session-019f84c1-adc9-7000-b1fe-6faf55651b2f
d ./.gjc/_session-019f84c2-21af-7000-bd30-169efd195ea5
d ./.gjc/_session-019f84d0-0a19-7000-b79c-8d54963df49a
d ./.gjc/_session-019f84d1-3224-7000-a210-d8eb957e981e
d ./.gjc/_session-019f84d9-47e0-7000-8cdc-870c0bb4c4e3
d ./.gjc/_session-019f84e7-7875-7000-8e8e-4aadb3075e71
d ./.gjc/_session-019f84ec-df5b-7000-bc05-42bac86fd5fa
d ./.gjc/_session-019f84ed-02db-7000-a066-7d5a23c938d3
d ./.gjc/_session-019f84f0-06d0-7000-81fd-b85809e204fc
d ./.gjc/_session-019f84f9-8613-7000-a9a7-539d034e8ebe
d ./.gjc/_session-019f84ff-d662-7000-add2-4c3ecdef326f
d ./.gjc/_session-019f84ff-f945-7000-9531-daa2c97fcf20
d ./.gjc/_session-019f850d-c4ca-7000-9557-b26ac0632807
d ./.gjc/_session-019f8510-3989-7000-bb31-68b78e635a2b
d ./.gjc/_session-019f8510-6bb6-7000-9bb4-4751f34ce713
d ./.gjc/_session-019f8512-28e1-7000-9629-51fc31c4990a
d ./.gjc/_session-019f8513-4fa2-7000-b2cc-13fb22e0e461
d ./.gjc/_session-019f8514-63cf-7000-bbf9-367b801f205b
d ./.gjc/_session-019f8516-752f-7000-8cfd-8def3814bb27
d ./.gjc/_session-019f8517-59a4-7000-a7e4-2e362ccdb21b
d ./.gjc/_session-019f8518-dc3d-7000-a5ca-df57d336fdf6
d ./.gjc/_session-019f851b-eee8-7000-b8ff-0bed2a788e98
d ./.gjc/_session-019f851c-26c9-7000-a761-1aeee89fd274
d ./.gjc/_session-019f851e-b70f-7000-b8ec-025d59e54b5a
d ./.gjc/_session-019f851e-e5ae-7000-93c0-01da3cb419fb
d ./.gjc/_session-019f8523-2088-7000-84b9-de6e6ccef8fd
d ./.gjc/_session-019f852d-4d09-7000-8061-eb8c95003419
d ./.gjc/_session-019f852d-77e7-7000-8d08-a5747f3cfc55
d ./.gjc/_session-019f8531-7966-7000-88f0-3cf2a6708ab7
d ./.gjc/_session-019f853b-a8ef-7000-bfb1-663fd45657ff
d ./.gjc/_session-019f853b-ea5c-7000-9255-a4250b1d2a3c
d ./.gjc/_session-019f853f-6742-7000-b185-04a645802d80
d ./.gjc/_session-019f854b-87ff-7000-9c4a-036dec32cacf
d ./.gjc/_session-019f854d-e437-7000-a230-a5dd5f898334
d ./.gjc/_session-019f854e-163c-7000-8979-0ca2afb3d3e9
d ./.gjc/_session-019f855f-f2ad-7000-a074-23d46faeb661
d ./.gjc/_session-019f8564-5d6a-7000-8b1c-ea6db89d900b
d ./.gjc/_session-019f8564-5d6c-7000-8e72-3c352105d273
d ./.gjc/_session-019f8564-5d6d-7000-a1d3-5723c2d6f3d3
d ./.gjc/_session-019f8564-5d6e-7000-a324-d3b8c3494f98
d ./.gjc/_session-019f8581-8483-7000-af8f-628ccf77b077
d ./.gjc/_session-019f8586-6869-7000-b74a-6310c8c86b6c
d ./.gjc/_session-019f8586-686b-7000-b518-84d7d8ff0781
d ./.gjc/_session-019f8586-686c-7000-82a4-a6d98295ebff
d ./.gjc/_session-019f8592-1b6f-7000-b460-4797db0ee3aa
d ./.gjc/_session-019f8592-1b70-7000-84bb-439181f1e36c
d ./.gjc/_session-019f8596-eb19-7000-9b1c-4f2c4190520b
d ./.gjc/_session-019f8596-eb1a-7000-a566-3609dee2dafd
d ./.gjc/_session-019f8713-7df5-7000-8cb2-9b7a7f76fcd0
d ./.gjc/_session-019f8714-ef9a-7000-aea9-3f84e2e15db8
d ./.gjc/_session-019f8714-ef9c-7000-a4df-4e0cf928167b
d ./.gjc/_session-019f871c-d413-7000-a5a6-61c85031a996
d ./.gjc/_session-019f871c-d414-7000-8c2b-ff84c2fd3b2f
d ./.gjc/_session-019f871d-03ea-7000-9704-b60d4ef6cee5
d ./.gjc/_session-019f8723-42c6-7000-9bd3-ac8c3721066e
d ./.gjc/_session-019f8723-42c7-7000-85c8-825fe5c20d1d
d ./.gjc/_session-019f8723-42c8-7000-b253-4e8de96ab83b
d ./.gjc/_session-019f872f-a3a8-7000-bb33-f2f1bc6397e5
d ./.gjc/_session-019f872f-a3a9-7000-be10-ac92be0082dc
d ./.gjc/_session-019f872f-a3aa-7000-99ea-644af541a95c
d ./.gjc/_session-019f874b-c534-7000-aec5-9f0348afece8
d ./.gjc/_session-019f874b-c535-7000-b084-c9bb835d77c5
d ./.gjc/_session-019f874b-f873-7000-b478-2671e836988f
d ./.gjc/_session-019f8752-9b68-7000-9756-824f26cae00c
d ./.gjc/_session-019f8752-9b6a-7000-a3aa-2799c368ae2a
d ./.gjc/_session-019f8752-9b6b-7000-856a-c93022c4ea7b
d ./.gjc/_session-019f8752-9b6c-7000-97dd-8cc0ff829f53
d ./.gjc/_session-019f8769-5072-7000-bec2-fce3ff761b5c
d ./.gjc/_session-019f8769-5074-7000-b29a-e8847893f89b
d ./.gjc/_session-019f8779-10c4-7000-bc9c-f2f1e29bac3f
d ./.gjc/_session-019f877b-6529-7000-9432-a4e7fb655950
d ./.gjc/_session-019f877b-652b-7000-834a-d4522f3441c9
d ./.gjc/_session-019f8786-05e4-7000-947d-eb1bbba30b91
d ./.gjc/_session-019f8786-05e5-7000-98f4-548447c3cffd
d ./.gjc/_session-019f8786-31d4-7000-87fc-2997db44fe07
d ./.gjc/_session-019f878d-2fd0-7000-9e72-045d79351a31
d ./.gjc/_session-019f878d-2fd1-7000-8d37-d58f210e51ad
d ./.gjc/_session-019f878d-2fd2-7000-a070-fe84bb44e04a
d ./.gjc/_session-019f878d-2fd3-7000-9ccd-534d0d181011
d ./.gjc/_session-019f879d-2951-7000-9038-7e0d84c27039
d ./.gjc/_session-019f879d-2952-7000-822b-b4a9df8de764
d ./.gjc/_session-019f879d-2958-7000-b917-045f619db07f
d ./.gjc/_session-019f87b4-1247-7000-a6d4-aa6cf36d77b6
d ./.gjc/_session-019f87b4-1248-7000-a86f-96f17e989530
d ./.gjc/_session-019f87b4-5026-7000-b34e-86d6e07defad
d ./.gjc/_session-019f87bb-275a-7000-8f63-2e80735e6fd3
d ./.gjc/_session-019f87bb-275b-7000-984c-e75e01da23a7
d ./.gjc/_session-019f87bb-275c-7000-b868-885114e1f443
d ./.gjc/_session-019f87bb-275c-7001-a977-9f7b3038cc46
d ./.gjc/_session-019f87bc-8f5d-7000-99a2-c12596d21f5e
d ./.gjc/_session-019f87bc-8f5e-7000-99d8-b5a100cbe379
d ./.gjc/_session-019f87bc-8f5f-7000-8f77-ecbd64384497
d ./.gjc/_session-019f87d0-50f0-7000-806b-f3d749905b55
d ./.gjc/_session-019f87d0-50f1-7000-aae0-846ea0e5eab7
d ./.gjc/_session-019f87d0-7e16-7000-b275-5578f27c19c0
d ./.gjc/_session-019f87d5-d23e-7000-9adb-090b7ce63fa5
d ./.gjc/_session-019f87d5-d23f-7000-9f9c-52b64f2de7ae
d ./.gjc/_session-019f87d5-d240-7000-a099-df842b50c5a7
d ./.gjc/_session-019f87d7-6f6a-7000-a693-3388f66df98f
d ./.gjc/_session-019f87e9-a7e4-7000-b7f0-b89d2eb1a7c0
d ./.gjc/_session-019f87e9-a7e6-7000-8332-815acb1dd5da
d ./.gjc/_session-019f87e9-d929-7000-8e7d-602b8f4ed548
d ./.gjc/_session-019f87ef-db86-7000-8c16-1d894f9c7acb
d ./.gjc/_session-019f87fb-93c3-7000-b2c6-f73dfd592ebe
d ./.gjc/_session-019f87fb-93c5-7000-95e5-cb35ee2e247e
d ./.gjc/_session-019f87fb-cc85-7000-9a1b-2663f8a6ed75
d ./.gjc/_session-019f8803-503a-7000-9c1b-6c648dfd0659
d ./.gjc/_session-019f88b1-ab57-7000-a257-aeb8b71dfc4a
d ./.gjc/_session-019f88b7-44e1-7000-ba2b-1445abbd07a5
d ./.gjc/_session-019f88b7-44e2-7000-bc5b-d102c91eeef2
d ./.gjc/_session-019f893f-3c5e-7000-8f47-b6ea2ae0efc5
d ./.gjc/_session-019f8940-a5c4-7000-9f57-48f903c83356
d ./.gjc/_session-019f8a0b-1004-7000-9378-64e564e07da4
d ./.gjc/_session-019f8a0b-1005-7000-b9ac-a5d91c61caec
d ./.gjc/_session-019f8a12-5114-7000-8cbc-14c1cadb302f
d ./.gjc/_session-019f8a14-f5d3-7000-999d-c3edb2d128ca
d ./.gjc/_session-019f8a17-d2d4-7000-9dc6-9563d8c8db1c
d ./.gjc/_session-019f8a17-d2d6-7000-8c7a-aa4399f5afe6
d ./.gjc/_session-019f8a25-ddbf-7000-9426-4b70e4208bfe
d ./.gjc/_session-019f8a26-02aa-7000-84a7-42e4dffad244
d ./.gjc/_session-019f8a2e-f95b-7000-9b0a-3a648d9838e7
d ./.gjc/_session-019f8a31-53d6-7000-a852-282f02bb67fc
d ./.gjc/_session-019f8a6e-0532-7000-835d-a50a50448363
d ./.gjc/_session-019f8a6e-0534-7000-96b9-81faa1247bed
d ./.gjc/_session-019f8a6e-0535-7000-a2ba-085b098c58f8
d ./.gjc/_session-019f8a6e-0535-7001-95d3-84f4b4714576
d ./.gjc/_session-019f8a75-3cc7-7000-a572-d717471ae4ba
d ./.gjc/_session-019f8a86-1a08-7000-a2a2-ac2d7ac2244a
d ./.gjc/_session-019f8a8a-49f1-7000-b94c-ad4cd6de6c8b
d ./.gjc/_session-019f8a8c-92d3-7000-bf47-d3d0d950ab4f
d ./.gjc/_session-019f8a8c-92d4-7000-819e-002459ddf81b
d ./.gjc/_session-019f8a8c-92d5-7000-ac1c-b8febb54c96b
d ./.gjc/_session-019f8a8c-92d6-7000-b7ec-00449e377d22
d ./.gjc/_session-019f8a97-5b48-7000-b92b-85c26386560c
d ./.gjc/_session-019f8a97-5b49-7000-9a31-3e9734a91607
d ./.gjc/_session-019f8a97-5b4a-7000-b374-d5b7c7fd09ea
d ./.gjc/_session-019f8a98-296e-7000-bb58-a53da1a9b4f4
d ./.gjc/_session-019f8a99-a552-7000-82c9-6f2da16399b5
d ./.gjc/_session-019f8aa4-0c18-7000-9112-11d236c55c87
d ./.gjc/_session-019f8aa9-dec0-7000-a624-b9c6dab7f25f
d ./.gjc/_session-019f8aaf-7471-7000-a4ae-9cb0452213b0
d ./.gjc/_session-019f8ab6-8684-7000-8200-80fe927b9fe8
d ./.gjc/_session-019f8ac3-9d98-7000-b5d2-f2729b3141c0
d ./.gjc/_session-019f8c62-34ad-7000-b03a-267277e0029f
d ./.gjc/_session-019f8c8d-92c5-7000-8312-314df6db30c5
d ./.gjc/_session-019f8cae-1404-7000-84e1-66a8a87e43a6
d ./.gjc/_session-019f8cb0-21c1-7000-9db2-157d185758b4
d ./.gjc/_session-019f8cb2-0cea-7000-9e16-1c16c2cc5d36
d ./.gjc/_session-019f8cc3-e112-7000-a6c4-10ab726b485c
d ./.gjc/_session-019f8cc8-9187-7000-abb1-f6737c323185
d ./.gjc/_session-019f8cd4-dfa3-7000-a706-572c100a9130
d ./.gjc/_session-019f8cd5-0ae5-7000-838d-49a52f2cb994
d ./.gjc/_session-019f8ce1-190f-7000-9cf6-ca1150590904
d ./.gjc/_session-019f8ce1-3e7b-7000-9b1f-c3c6061b37ba
d ./.gjc/_session-019f8ce7-5acf-7000-9f10-bb14e7e26768
d ./.gjc/_session-019f8ce7-8b84-7000-8044-dc1152d4d194
d ./.gjc/_session-019f8cee-8052-7000-8d4b-66a3193dfcba
d ./.gjc/_session-019f8cee-9d85-7000-8a20-0c28b4bf2117
d ./.gjc/_session-019f8cf6-ba52-7000-9787-ccf301770a94
d ./.gjc/_session-019f8cf6-cfef-7000-956d-fcd56f5fcbee
d ./.gjc/_session-019f8cfc-a3b8-7000-bc3d-28edb9a6b16a
d ./.gjc/_session-019f8cfc-c7bf-7000-962b-b066954d95fc
d ./.gjc/_session-019f8d11-c3bb-7000-b826-36abf0415618
d ./.gjc/_session-019f8d11-c3bd-7000-a554-5a4a4cbf8b40
d ./.gjc/_session-019f8d11-c3be-7000-8a45-c6800870cce6
d ./.gjc/_session-019f8d11-c3bf-7000-89b4-f7a669d8565c
d ./.gjc/_session-019f8d18-2d0e-7000-92c1-14d332ea2ddc
d ./.gjc/_session-019f8d18-4948-7000-92d0-02e1defb1a96
d ./.gjc/_session-019f8d1c-b18f-7000-aa26-938af71c8588
d ./.gjc/_session-019f8d1d-298f-7000-a7c8-bf4e4a4b66d3
d ./.gjc/_session-019f8d20-3a21-7000-9aef-b0562592dd50
d ./.gjc/_session-019f8d20-3a23-7000-983f-76c6745edf21
d ./.gjc/_session-019f8d20-3a24-7000-b6ca-d2cf76bbab35
d ./.gjc/_session-019f8dbd-be46-7000-8707-234c259959ee
d ./.gjc/_session-019f8dc9-a497-7000-a3b6-9aa0eb615854
d ./.gjc/_session-019f8dce-52f0-7000-8192-a2a6df3da0a2
d ./.gjc/_session-019f8dce-741f-7000-a204-c930a0078e63
d ./.gjc/_session-019f8dd6-e9d9-7000-98ba-a54476d46a39
d ./.gjc/_session-019f8dd6-e9da-7000-b7d0-bf0d7f3b9ffc
d ./.gjc/_session-019f8dd6-e9db-7000-a371-e352525b400f
d ./.gjc/_session-019f8deb-7655-7000-9b86-1c5e7aaef2a5
d ./.gjc/_session-019f8deb-9515-7000-b610-64c6937b7863
d ./.gjc/_session-019f8df5-20ff-7000-9c29-82807dd152cd
d ./.gjc/_session-019f8e08-5ba8-7000-bec1-378bb50f3890
d ./.gjc/_session-019f8e08-5baa-7000-98d7-d9fbb93985b0
d ./.gjc/_session-019f8e17-4e66-7000-b55a-24ed13d78256
d ./.gjc/_session-019f8e1a-68c5-7000-9fd9-5336f37a88df
d ./.gjc/_session-019f8e29-9a75-7000-b704-bab8747efae0
d ./.gjc/_session-019f8e2a-d9a2-7000-9628-868f8065616b
d ./.gjc/_session-019f8e2a-fe86-7000-87da-514a49176f29
d ./.gjc/_session-019f8e36-38d8-7000-a8e7-c3969e9b4b91
d ./.gjc/_session-019f8e5c-e4d2-7000-8dd1-01914a05052e
d ./.gjc/_session-019f8e66-2266-7000-b044-51d63bfc7b0f
d ./.gjc/_session-019f8e7a-ede0-7000-a279-4bc5688ba6c2
d ./.gjc/_session-019f8e7e-aa2c-7000-98f6-41c5e0a434e9
d ./.gjc/_session-019f8e7e-aa2d-7000-a701-d86e5672da13
d ./.gjc/_session-019f8e7e-aa2e-7000-9699-def89a0fc207
d ./.gjc/_session-019f8e98-9090-7000-83c5-51ed9572e2c3
d ./.gjc/_session-019f8e9d-5c53-7000-af04-995cffb1a60a
d ./.gjc/_session-019f8ea3-fe17-7000-9b1f-5f0682b70f6d
d ./.gjc/_session-019f8ea4-2060-7000-89df-01e9bcaa73e4
d ./.gjc/_session-019f8ea9-9125-7000-9f8f-567e1d1077ad
d ./.gjc/_session-019f8ea9-9127-7000-a7c9-0bb6a24e536b
d ./.gjc/_session-019f8ecc-f8d4-7000-b742-f77d9a5fa901
d ./.gjc/_session-019f8ecd-17fb-7000-9d46-8e1dbaf354e1
d ./.gjc/_session-019f8ed7-99a7-7000-9a5b-92a7983b72f9
d ./.gjc/_session-019f8edf-788f-7000-bfe9-53655c5ccd6d
d ./.gjc/_session-019f8ee1-c16c-7000-a302-e21334c38fce
d ./.gjc/_session-019f8eed-90c6-7000-ba2f-031f9e320b8f
d ./.gjc/_session-019f8ef2-db01-7000-a39d-7e925e854273
d ./.gjc/_session-019f8ef2-fe64-7000-887c-0d2610a1621f
d ./.gjc/_session-019f8efa-6d0c-7000-8dd2-985f92babff0
d ./.gjc/_session-019f8f06-4df7-7000-8470-11ec6fda6323
d ./.gjc/_session-019f8f06-4df9-7000-bf26-4a502c9bca6d
d ./.gjc/_session-019f8f0a-c772-7000-8634-9e53548d498e
d ./.gjc/_session-019f8f0a-c774-7000-bb5c-40b2a266d43c
d ./.gjc/_session-019f8f3c-849e-7000-889a-7ddf11766ec5
d ./.gjc/_session-019f8f3c-84a0-7000-9235-b1e42262acdc
d ./.gjc/_session-019f8f41-08d3-7000-b347-4f3d5bf0f6fe
d ./.gjc/_session-019f8f41-08d4-7000-a168-f468eee9dd00
d ./.gjc/_session-019f8f41-7d45-7000-85e1-e8e6dc9766aa
d ./.gjc/_session-019f8f41-97b9-7000-9cee-42bbec6f9c6f
d ./.gjc/_session-019f8f45-f776-7000-8bfb-85121eba37de
d ./.gjc/_session-019f8f45-f778-7000-8204-db520d45636f
d ./.gjc/_session-019f8f46-650d-7000-86e9-0fc04279fe50
d ./.gjc/_session-019f8f46-b1db-7000-ae06-13465cc2861a
d ./.gjc/_session-019f8f47-0f60-7000-a92e-8094d3cea3a5
d ./.gjc/_session-019f8f49-a933-7000-a7eb-73f9967a803b
d ./.gjc/_session-019f8f49-fa20-7000-b7d5-3759a546997e
d ./.gjc/_session-019f8f4a-9e0f-7000-ae42-fc6a18db945c
d ./.gjc/_session-019f9237-cbdd-7000-a9f4-075f7456ff2c
d ./.gjc/_session-019f923a-832e-7000-b0d7-467d0643ffef
d ./.gjc/_session-019f924a-f47a-7000-80f4-e2fdda7e7fa8
d ./.gjc/_session-019f9250-06f0-7000-80ad-971f8d013407
d ./.gjc/_session-019f9255-7fd4-7000-bf79-5b50bc26969d
d ./.gjc/_session-019f9257-7689-7000-a31b-53b281b4dd80
d ./.gjc/_session-019f925e-2a2b-7000-a50d-55a8f971cdcd
d ./.gjc/_session-019f925e-2a2c-7000-9d88-0a0fcc13f613
d ./.gjc/_session-019f925e-2a2e-7000-b01e-1f3c93d7d03b
d ./.gjc/_session-019f9285-7c72-7000-aef3-fc95e41fa862
d ./.gjc/_session-019f928f-6aea-7000-bb23-e554bacd5550
d ./.gjc/_session-019f92a2-80d4-7000-bbd8-aba414beda2b
d ./.gjc/_session-019f931a-7a4e-7000-9865-de9f946edb47
d ./.gjc/_session-019f931a-ac40-7000-89f3-37491bdf3100
d ./.gjc/_session-019f9326-c32e-7000-988c-dcc71fe8cee5
d ./.gjc/_session-019f9326-c32f-7000-b201-23f550a6e32b
d ./.gjc/_session-019f9326-c330-7000-aafb-5fd64fc317cb
d ./.gjc/_session-019f9345-c232-7000-b59d-61c590d6381f
d ./.gjc/_session-019f9347-b8dc-7000-8105-80d2568d2948
d ./.gjc/_session-019f934a-0a8e-7000-9107-e7ac491f8545
d ./.gjc/_session-019f9b7d-d7aa-7000-8b65-884fed9cc271
d ./.gjc/_session-019f9b7e-58f4-7000-9d18-6cccb34dd121
d ./.gjc/_session-019f9b81-fb08-7000-81fd-0df8e38766d6
d ./.gjc/_session-019f9b82-4166-7000-86c7-fac81110b8ef
d ./.gjc/_session-019f9b88-2f84-7000-8010-af0a3851e4a4
d ./.gjc/_session-019f9b88-5f52-7000-84be-38d38d4959a6
d ./.gjc/_session-019f9b8c-a191-7000-a41d-9809d4ed9945
d ./.gjc/_session-019f9b97-2050-7000-b02f-d52b94be21f0
d ./.gjc/_session-019f9b97-9b08-7000-a676-24ceff0829d4
d ./.gjc/_session-019f9b97-9b0c-7000-a05f-2d258241524b
d ./.gjc/_session-019f9bae-a554-7000-8ed9-cd43e9f75072
d ./.gjc/_session-019f9bc0-1632-7000-ad6b-327349bf9e30
d ./.gjc/_session-019f9bc0-49dc-7000-bf2c-66a952bbef94


**Identifying project root and scripts**

find /home/cube/projects/richard/.worktrees -maxdepth 2 -type d -printf '%p\n' 2>/dev/null | sort | grep -E 'nutricoach|telegram|r71' | tail -100; printf '\nLocal likely source dirs:\n'; find . -maxdepth 2 -type d \( -name gateway -o -name scripts -o -name tests \) -printf '%p\n' | sort | head -100


weekly operations failed: canonical authority identity drift

installed-suite harness initially lacked complete frozen source dependencies; corrected by using the clean build input copy; no product/source/live mutation from those attempts

persistent-server stale missing-new-module diagnostic; fresh basedpyright PASS

disposable-only full qualification; no authoritative seal

candidate overlay omitted imported nutrition_weekly_dispatch_result.py and wheel verifier did not cover all wheel-hosted maintenance sources

overlay closure added the source; wheel/source and physical-inventory checks split into a 65-pure-LOC verifier module and now verify every wheel-hosted Python source with a repository counterpart

test_successor_overlay_contains_every_maintenance_runtime_import failed on omitted dispatch result


source-only and disposable qualification; no authoritative seal or live action

binding inputs -> PACKAGE_BINDING_DIGEST -> hold/authority exact bytes -> FINAL_PACKAGE_DIGEST

Topic59MaintenanceHoldV1 rejected package_binding_digest and nested maintenance scope because inherited source still required flat package_digest fields

PASS for new/refactored derivation and candidate files

V14 frozen dependency snapshot inventory drift occurs before the supplied registry-shape mutation is evaluated

preparer does not yet derive and seal the exact successor config/projection/route/customer/slot and complete no-send oracle from explicit maintenance window arguments

live controller does not yet transactionally arm hold/credential, subscribe before start, or verify MAINTENANCE_CONFIRMED before commit

rollback does not yet pause the provider-capable scheduler before predecessor restart

disposable twin wheels, disposable candidate/preseal, 13-case maintenance rehearsal, and installed-wheel two-noop/tomorrow QA were not completed


explicit KST maintenance-window parser with no wall-clock fallback

sanitized preflight/no-send-oracle derivation and two-stage r71b package derivation

exact authority credential, hold, LoadCredential postimage, cron snapshot, and safe paused-r70 rollback fence

pre-start inotify cron watch, durable typed maintenance output before jobs.json success, semantic cron/audit/ledger/zero-call confirmation

sealed-controller phase integration through MAINTENANCE_ARMED, START_WATCH_ARMED, STARTED, MAINTENANCE_CONFIRMED, and COMMITTED

independent r71b binding/hold/authority/final-package replay verifier and detached-closure source coverage


wrong supplementary gid 125 returned noop_maintenance and consumed the hold

OwnedMaintenanceDirectory carries the profile uid/gid; lock, active, consuming and audit opens validate both exactly

wrong gid returns deny/filesystem_contract with byte-identical artifact snapshot, claim/send/edit/network zero

active, lock and audit symlink/hardlink/mode/file-kind/gid/owner

simultaneous active+consuming, partial temp and partial audit

complete for all 11 runtime propagation files and every retained changed/new strict test/support file

PASS all 11 runtime files and retained changed/new tests/support

PASS all typed runtime and retained changed/new tests/support

0 errors, 0 warnings, 0 notes across all typed runtime and retained changed/new tests/support

All established changed files and six of seven strict new test/support files report no diagnostics. The persistent server retained a stale pre-merge snapshot for nutrition_weekly_maintenance_adversarial_support.py; document symbols showed current local HoldBinding while diagnostics referenced the deleted split import. Fresh basedpyright over the exact current file set is the clean equivalent.

PASS: no violations in 11 strict core/test files

PASS: no Any/cast/ignore/noqa/broad catch/sleep/skip/xfail in maintenance core or strict tests

All four adversarial blockers are closed in source with no package or live effects.

PASS: canonical frozen Pydantic authority/hold/audit documents

PASS: 52 deterministic rejection cases plus valid, crash, concurrency and next-day controls

PASS: ownership and filesystem checks remain at the openat boundary

PASS: wrong lock gid, every negative class, zero-call publication and truthful cron status are locked

No new production parameter object is a throwaway wrapper

Only contract-required durable write readback remains


**Inspecting script names for package recreation**

ROOT='/home/cube/projects/richard/.worktrees/nutricoach-v150-combined'; find "$ROOT/scripts" -maxdepth 1 -type f -printf '%f\n' | sort | grep -E 'nutricoach_v150|seal_nutricoach' | tail -120; printf '\nTests:\n'; find "$ROOT/tests" -type f -printf '%P\n' | sort | grep -E 'nutricoach_v150|maintenance|sealed|rehearsal' | tail -200

ROOT='/home/cube/projects/richard/.worktrees/nutricoach-v150-combined'; rg -n "DISPOSABLE_PACKAGE_PASS|source_suites|sealed_controller_safety|actual_disposable|MAINTENANCE_CONFIRMED|task10_evidence" "$ROOT/scripts" "$ROOT/tests" | head -400

ROOT='/home/cube/projects/richard/.worktrees/nutricoach-v150-combined'; find "$ROOT/.omo/evidence/nutricoach-v150-combined" -maxdepth 2 -mindepth 1 -type d -printf '%p\n' | sort | tail -120

ROOT='/home/cube/projects/richard/.worktrees/nutricoach-v150-combined'; python - <<'PY'
import hashlib, pathlib
r=pathlib.Path('/home/cube/projects/richard/.worktrees/nutricoach-v150-combined')
for p in sorted((r/'scripts').glob('*r71b*'))+sorted((r/'tests').rglob('*r71b*')):
 if p.is_file(): print(hashlib.sha256(p.read_bytes()).hexdigest(), p.relative_to(r))
PY


execute_nutricoach_v150_live_upgrade.py
execute_nutricoach_v150_sealed_live.py
nutricoach_v150_candidate_cli.py
nutricoach_v150_candidate_source_inventory.py
nutricoach_v150_candidate_wheel_sources.py
nutricoach_v150_concrete_host.py
nutricoach_v150_controller_worker.py
nutricoach_v150_customer_ux_smoke.py
nutricoach_v150_detached_bootstrap.py
nutricoach_v150_host_operations.py
nutricoach_v150_live_authority.py
nutricoach_v150_live_models.py
nutricoach_v150_live_transaction.py
nutricoach_v150_live_upgrade_boundary.py
nutricoach_v150_live_upgrade_common.py
nutricoach_v150_live_upgrade_state.py
nutricoach_v150_observer_contract.py
nutricoach_v150_observer_final.py
nutricoach_v150_observer_runtime.py
nutricoach_v150_phase_journal.py
nutricoach_v150_prepare_helpers.py
nutricoach_v150_r71b_cron_watch.py
nutricoach_v150_r71b_maintenance_confirmation.py
nutricoach_v150_r71b_maintenance_host.py
nutricoach_v150_r71b_maintenance_transaction.py
nutricoach_v150_r71b_package.py
nutricoach_v150_r71b_preparation.py
nutricoach_v150_r71b_preseal_arguments.py
nutricoach_v150_r71b_preseal_verifier.py
nutricoach_v150_r71b_sealed_host.py
nutricoach_v150_r71b_task10_evidence.py
nutricoach_v150_recovery_rehearsal.py
nutricoach_v150_rollback_guard.py
nutricoach_v150_runtime_ops.py
nutricoach_v150_sealed_authority.py
nutricoach_v150_sealed_controller.py
nutricoach_v150_sealed_target.py
nutricoach_v150_seven_day_observer.py
nutricoach_v150_weekly_authority.py
nutricoach_v150_weekly_startup_smoke.py
prepare_nutricoach_v150_live_upgrade.py
prepare_nutricoach_v150_v14_preseal.py
prepare_nutricoach_v150_v15_preseal.py
qualify_nutricoach_v150_ux_source.py
recover_nutricoach_v150_v10_lifecycle.py
rehearse_nutricoach_v150_v14.py
rehearse_nutricoach_v150_v15.py
run_nutricoach_v150_telegram_stepper_qa.py
seal_nutricoach_v150_candidate.py
verify_nutricoach_v150_candidate.py
verify_nutricoach_v150_candidate_inputs.py
verify_nutricoach_v150_preseal_v10.py
verify_nutricoach_v150_preseal_v11.py
verify_nutricoach_v150_preseal_v12.py
verify_nutricoach_v150_preseal_v13.py
verify_nutricoach_v150_preseal_v14.py
verify_nutricoach_v150_preseal_v15.py
verify_nutricoach_v150_preseal_v3.py
verify_nutricoach_v150_preseal_v4.py
verify_nutricoach_v150_preseal_v5.py
verify_nutricoach_v150_preseal_v6.py
verify_nutricoach_v150_preseal_v7.py
verify_nutricoach_v150_preseal_v8.py
verify_nutricoach_v150_preseal_v9.py

Tests:
cron/test_physique_inline_card_maintenance.py
gateway/nutrition_weekly_maintenance_adversarial_support.py
gateway/nutrition_weekly_maintenance_fs_mutations.py
gateway/nutrition_weekly_maintenance_support.py
gateway/test_nutrition_weekly_dispatcher_maintenance.py
gateway/test_nutrition_weekly_maintenance_digest.py
gateway/test_nutrition_weekly_topic59_maintenance.py
gateway/test_nutrition_weekly_topic59_maintenance_failures.py
nutricoach_v150_transaction_support.py
test_nutricoach_v150_live_binding.py
test_nutricoach_v150_live_upgrade.py
test_nutricoach_v150_preseal_v13.py
test_nutricoach_v150_preseal_v14.py
test_nutricoach_v150_r71b_candidate_evidence.py
test_nutricoach_v150_r71b_confirmation.py
test_nutricoach_v150_r71b_controller_source.py
test_nutricoach_v150_r71b_cron_watch.py
test_nutricoach_v150_r71b_disposable_lifecycle.py
test_nutricoach_v150_r71b_maintenance_host.py
test_nutricoach_v150_r71b_package_digest.py
test_nutricoach_v150_r71b_preparation.py
test_nutricoach_v150_r71b_preseal_arguments.py
test_nutricoach_v150_r71b_preseal_verifier.py
test_nutricoach_v150_r71b_sealed_host.py
test_nutricoach_v150_sealed_controller.py
test_nutricoach_v150_seven_day_observer.py
test_nutricoach_v150_transaction_controller.py
test_nutricoach_v150_v14_safety.py
test_nutricoach_v150_v15_authority_adversarial.py
test_nutricoach_v150_v15_closure.py
test_nutricoach_v150_v15_safety.py
test_nutricoach_v150_v3_hardening.py
test_nutricoach_v150_weekly_authority.py
test_verify_nutricoach_v150_candidate.py


/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_preparation.py:43:from scripts.nutricoach_v150_r71b_task10_evidence import (
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_preparation.py:47:    load_candidate_task10_evidence,
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_preparation.py:48:    task10_evidence_spec,
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_preparation.py:233:        r70_evidence = load_candidate_task10_evidence(
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_preparation.py:236:            task10_evidence_spec("r70_error"),
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_preparation.py:238:        observer = load_candidate_task10_evidence(
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_preparation.py:241:            task10_evidence_spec("observer"),
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_preparation.py:243:        fixed_collector = load_candidate_task10_evidence(
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_preparation.py:246:            task10_evidence_spec("health_recovery"),
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_preparation.py:249:        raise MaintenancePreparationError("task10_evidence") from error
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_preparation.py:264:        "task10_evidence_provenance": candidate_task10_provenance((
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:101:def task10_evidence_spec(name: str) -> Task10EvidenceSpec:
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:105:        raise Task10EvidenceError("task10_evidence_name")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:109:def validate_task10_evidence_source(
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:115:        raise Task10EvidenceError("task10_evidence_path")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:117:    payload = _read_exact_regular(path, 0o664, "task10_evidence_file")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:119:        raise Task10EvidenceError("task10_evidence_sha256")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:120:    document = _parse_object(payload, "task10_evidence_json")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:126:        raise Task10EvidenceError("task10_evidence_identity")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:131:def validate_fixed_task10_evidence_sources(
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:139:        raise Task10EvidenceError("task10_evidence_count")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:141:        validate_task10_evidence_source(path, spec)
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:146:def write_candidate_task10_evidence(
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:164:def load_candidate_task10_evidence(
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:171:    payload = _read_exact_regular(path, 0o444, "candidate_task10_evidence_file")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:172:    document = _parse_object(payload, "candidate_task10_evidence_json")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:174:        raise Task10EvidenceError("candidate_task10_evidence_canonical")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:183:        raise Task10EvidenceError("candidate_task10_evidence_provenance")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:186:        raise Task10EvidenceError("candidate_task10_evidence_document")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:187:    source = validate_task10_evidence_source(spec.source_path, spec)
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:189:        raise Task10EvidenceError("candidate_task10_evidence_substitution")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:200:def verify_candidate_task10_evidence(
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:206:        raise Task10EvidenceError("candidate_task10_evidence_paths")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:208:        load_candidate_task10_evidence(candidate_root, paths[spec.input_name], spec)
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:239:        raise Task10EvidenceError("task10_evidence_parent")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:306:            raise Task10EvidenceError("task10_evidence_duplicate_key")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_task10_evidence.py:323:            raise Task10EvidenceError("task10_evidence_name")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/verify_nutricoach_v150_candidate_inputs.py:45:    "scripts/nutricoach_v150_r71b_task10_evidence.py",
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/verify_nutricoach_v150_candidate.py:42:from scripts.nutricoach_v150_r71b_task10_evidence import (
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/verify_nutricoach_v150_candidate.py:44:    verify_candidate_task10_evidence,
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/verify_nutricoach_v150_candidate.py:168:        _ = verify_candidate_task10_evidence(root, _R71B_EVIDENCE_INPUTS)
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/seal_nutricoach_v150_candidate.py:24:from scripts.nutricoach_v150_r71b_task10_evidence import (
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/seal_nutricoach_v150_candidate.py:26:    validate_fixed_task10_evidence_sources,
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/seal_nutricoach_v150_candidate.py:27:    write_candidate_task10_evidence,
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/seal_nutricoach_v150_candidate.py:79:    r70_error, observer, health_recovery = validate_fixed_task10_evidence_sources(
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/seal_nutricoach_v150_candidate.py:103:        write_candidate_task10_evidence(destination, evidence)
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_sealed_host.py:136:        self._journal.advance("MAINTENANCE_CONFIRMED")
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_controller_source.py:208:    controller.recover(MaintenancePhase.MAINTENANCE_CONFIRMED)
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_candidate_evidence.py:11:from scripts.nutricoach_v150_r71b_task10_evidence import (
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_candidate_evidence.py:14:    load_candidate_task10_evidence,
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_candidate_evidence.py:15:    task10_evidence_spec,
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_candidate_evidence.py:16:    validate_fixed_task10_evidence_sources,
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_candidate_evidence.py:17:    verify_candidate_task10_evidence,
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_candidate_evidence.py:30:    arguments.r70_error_evidence = task10_evidence_spec("r70_error").source_path
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_candidate_evidence.py:31:    arguments.observer_evidence = task10_evidence_spec("observer").source_path
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_candidate_evidence.py:32:    arguments.fixed_collector_evidence = task10_evidence_spec(
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_candidate_evidence.py:51:    copies = verify_candidate_task10_evidence(candidate, _INPUTS)
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_candidate_evidence.py:82:    with pytest.raises(Task10EvidenceError, match="task10_evidence_path"):
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_candidate_evidence.py:113:        _ = load_candidate_task10_evidence(
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_candidate_evidence.py:116:            task10_evidence_spec("observer"),
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_candidate_evidence.py:122:    evidence = validate_fixed_task10_evidence_sources(
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_candidate_evidence.py:123:        task10_evidence_spec("r70_error").source_path,
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_candidate_evidence.py:124:        task10_evidence_spec("observer").source_path,
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_candidate_evidence.py:125:        task10_evidence_spec("health_recovery").source_path,
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_sealed_controller.py:197:    if phase == "MAINTENANCE_CONFIRMED":
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_sealed_controller.py:212:        maintenance.recover(MaintenancePhase.MAINTENANCE_CONFIRMED)
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_sealed_host.py:121:    assert adapter.phase() == "MAINTENANCE_CONFIRMED"
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_maintenance_transaction.py:43:    MAINTENANCE_CONFIRMED = "MAINTENANCE_CONFIRMED"
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_maintenance_transaction.py:96:        if error is not None and self._controller.phase is not MaintenancePhase.MAINTENANCE_CONFIRMED:
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_maintenance_transaction.py:143:            self.phase = MaintenancePhase.MAINTENANCE_CONFIRMED
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/scripts/nutricoach_v150_r71b_maintenance_transaction.py:150:            case MaintenancePhase.MAINTENANCE_CONFIRMED:
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_disposable_lifecycle.py:287:    assert journal.phase() == "MAINTENANCE_CONFIRMED"
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_preparation.py:23:from scripts.nutricoach_v150_r71b_task10_evidence import task10_evidence_spec
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_preparation.py:221:    arguments.r70_error_evidence = task10_evidence_spec("r70_error").source_path
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_preparation.py:222:    arguments.observer_evidence = task10_evidence_spec("observer").source_path
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_preparation.py:223:    arguments.fixed_collector_evidence = task10_evidence_spec(
/home/cube/projects/richard/.worktrees/nutricoach-v150-combined/tests/test_nutricoach_v150_r71b_preparation.py:239:    assert collected.evidence["r70_error_evidence_sha256"] == task10_evidence_spec(


cf430b22a9953c9ddce694feab3e2a13b17088bdd1979f38674a6da37ea9107f scripts/nutricoach_v150_r71b_cron_watch.py
378645bd580aef806072890d9d27e32e40a897fd13aa732e8fdf257d6315ec98 scripts/nutricoach_v150_r71b_maintenance_confirmation.py
c986ddefb826e041479898a6a682adfd02ca4ba7f29e35a51b97aee7517c2d65 scripts/nutricoach_v150_r71b_maintenance_host.py
b98d8853499ecd118b0e6b5e21e28fd9221965174231495f4dcf8c1366c6cb4d scripts/nutricoach_v150_r71b_maintenance_transaction.py
a2a5a3e965819d5172847d7c7d8d8fb69dabb0683afb0f484bf1268bdc1bbcfd scripts/nutricoach_v150_r71b_package.py
06200716372e3362e4506c7f12f5b4770360b9dcaf0689d14ad04b32a198d486 scripts/nutricoach_v150_r71b_preparation.py
b4d5f0e1b00db655b7b77cb8ac791ad5d5f5eb8021b4994761b586218126c3cb scripts/nutricoach_v150_r71b_preseal_arguments.py
6afe99f194f937d885f7ca1eaf660b902394e2e6c0747dd1f8f9ef2620b250f3 scripts/nutricoach_v150_r71b_preseal_verifier.py
89b91acd7a7f3760f1f7457d57a6165dd65a0cbcd91a978e6e7533ba2297dece scripts/nutricoach_v150_r71b_sealed_host.py
95450b846fc50f30e8259af625fe108c520a9688774610563351638334372432 scripts/nutricoach_v150_r71b_task10_evidence.py
04f65d6e1156b4e6687d9b338b1950d15f50a097373d895b2a8f9dfc82c050d1 tests/test_nutricoach_v150_r71b_candidate_evidence.py
f19e9be0f681b1d870daf699a8d2f1edcc55a41d1b5754f2225ae4f5f6c14134 tests/test_nutricoach_v150_r71b_confirmation.py
e76e47ed44ec28ca66560cbc8e992394f4289141aaa8e9ca9edd2a75153bbce4 tests/test_nutricoach_v150_r71b_controller_source.py
1816f344ad44f7e746fe94951613f019ba042056791c4b5ec177f5e695e39c0f tests/test_nutricoach_v150_r71b_cron_watch.py
6a37e61b62611c384bbb696e6706b2496e4667eab8ba49e6a8588c471a031e21 tests/test_nutricoach_v150_r71b_disposable_lifecycle.py
718bffa6b0260386306804885aa03ecc357de7b18ed2dbd72ab8281c122ea3ef tests/test_nutricoach_v150_r71b_maintenance_host.py
8964a6c2fba78388adf9de1180242300978a9f2b2c819ef4a2fd3d2342d968b6 tests/test_nutricoach_v150_r71b_package_digest.py
f08d02efc0fe79540433bdff7bc75e24f52b667f0b996e22b09c9b4c6b8e3baa tests/test_nutricoach_v150_r71b_preparation.py
93c9028c6ed98d3ff042f056ca023ecea22e63e7f36a6bc10b08c4a0730bf316 tests/test_nutricoach_v150_r71b_preseal_arguments.py
f812d078f88e5521f82c1e486a1fb1eed682e4fae1a0ce590e3cd4c4ddb9946b tests/test_nutricoach_v150_r71b_preseal_verifier.py
ceb86a30f00bef5ceb2245e0d6f0db3401920e871ff302565d1097bdbdbfb480 tests/test_nutricoach_v150_r71b_sealed_host.py


**Investigating missing worktree recreation**


#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.12,<3.14"
# dependencies = ["pydantic>=2,<3"]
# ///

# ─── How to run ───
#   uv run scripts/seal_nutricoach_v150_candidate.py --help
# ──────────────────

"""Materialize the immutable NutriCoach v1.5 combined candidate seal."""

from __future__ import annotations

import shutil
import sys
from dataclasses import dataclass
from pathlib import Path
from typing import override

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from scripts.nutricoach_v150_candidate_cli import CliNamespace, candidate_parser
from scripts.nutricoach_v150_r71b_task10_evidence import (
    ValidatedTask10Evidence,
    validate_fixed_task10_evidence_sources,
    write_candidate_task10_evidence,
)
from scripts.nutricoach_v150_candidate_source_inventory import (
    CANDIDATE_REQUIRED_SOURCE_PATHS,
)
from scripts.verify_nutricoach_v150_candidate_inputs import (
    R71B_MAINTENANCE_OVERLAY_PATHS,
)
from scripts.verify_nutricoach_v140_candidate_core import (
    JsonValue,
    canonical,
    inventory_digest,
    load_json,
    require_list,
    require_object,
    require_string,
    sha256_bytes,
    sha256_file,
)

@dataclass(frozen=True, slots=True)
class CandidateSealError(RuntimeError):
    reason: str

    @override
    def __str__(self) -> str:
        return self.reason

def _inventory(root: Path, paths: list[Path]) -> list[dict[str, JsonValue]]:
    return [
        {"path": path.relative_to(root).as_posix(), "sha256": sha256_file(path)}
        for path in sorted(paths)
    ]

def _copy(source: Path, destination: Path) -> Path:
    _ = destination.parent.mkdir(parents=True, exist_ok=True)
    _ = shutil.copy2(source, destination)
    return destination

def _v17_input(v17: Path, direct_name: str, sealed_name: str) -> Path:
    direct = v17 / direct_name
    if direct.is_file():
        return direct
    return v17 / "inputs" / sealed_name

def r71b_evidence_inputs(args: CliNamespace) -> dict[str, ValidatedTask10Evidence]:
    """Validate and map only the three fixed Task10 sources into candidate inputs."""
    r70_error, observer, health_recovery = validate_fixed_task10_evidence_sources(
        args.r70_error_evidence,
        args.observer_evidence,
        args.fixed_collector_evidence,
    )
    return {
        "inputs/r70-canonical-authority-drift.json": r70_error,
        "inputs/r71b-observer-final.json": observer,
        "inputs/r71b-fixed-collector.json": health_recovery,
    }

def copy_r71b_evidence(args: CliNamespace, successor: Path) -> list[Path]:
    """Produce canonical candidate copies with exact Task10 source provenance."""
    return _write_r71b_evidence(r71b_evidence_inputs(args), successor)

def _write_r71b_evidence(
    evidence_inputs: dict[str, ValidatedTask10Evidence],
    successor: Path,
) -> list[Path]:
    copies: list[Path] = []
    for relative, evidence in evidence_inputs.items():
        destination = successor / relative
        write_candidate_task10_evidence(destination, evidence)
        copies.append(destination)
    return copies

def candidate_source_paths(
    base_manifest: dict[str, JsonValue], v17: Path
) -> list[Path]:
    source_root = Path(__file__).resolve().parents[1]
    paths: set[Path] = set()
    for raw in require_list(
        base_manifest.get("source_inventory"), "base source inventory"
    ):
        entry = require_object(raw, "base source inventory")
        relative = Path(require_string(entry.get("path"), "base source path"))
        paths.add(Path(*relative.parts[2:]))
    patch_manifest = _v17_input(v17, "patch-tree.sha256", "v17-patch-tree.sha256")
    for line in patch_manifest.read_text(encoding="utf-8").splitlines():
        _, absolute = line.split("  ", maxsplit=1)
        parts = Path(absolute).parts
        patch_index = parts.index("patch-tree")
        paths.add(Path(*parts[patch_index + 1 :]))
    paths.update(Path(relative) for relative in CANDIDATE_REQUIRED_SOURCE_PATHS)
    missing = sorted(str(path) for path in paths if not (source_root / path).is_file())
    if missing:
        raise FileNotFoundError(f"candidate source members missing: {missing}")
    paths.update(Path(relative) for relative in R71B_MAINTENANCE_OVERLAY_PATHS)
    return sorted(paths)

def main() -> int:
    args = candidate_parser().parse_args(namespace=CliNamespace())
    source_root = Path(__file__).resolve().parents[1]
    successor = args.successor.resolve()
    if successor.exists() or successor.is_symlink():
        raise CandidateSealError("successor_exists")
    evidence_inputs = r71b_evidence_inputs(args)
    _ = successor.mkdir(parents=True)

    base_manifest = require_object(load_json(args.base), "base manifest")
    source_files = [
        _copy(source_root / relative, successor / "snapshot/source" / relative)
        for relative in candidate_source_paths(base_manifest, args.v17_evidence)
    ]
    input_sources = {
        "inputs/base-manifest.json": args.base,
        "inputs/v17-evidence-files.sha256": _v17_input(
            args.v17_evidence,
            "evidence-files.sha256",
            "v17-evidence-files.sha256",
        ),
        "inputs/v17-exact-source-set.sha256": _v17_input(
            args.v17_evidence,
            "exact-current-source-set.final.sha256",
            "v17-exact-source-set.sha256",
        ),
        "inputs/v17-patch-tree.sha256": _v17_input(
            args.v17_evidence,
            "patch-tree.sha256",
            "v17-patch-tree.sha256",
        ),
        "inputs/v17-sandbox.diff": _v17_input(
            args.v17_evidence,
            "sandbox.diff",
            "v17-sandbox.diff",
        ),
        "inputs/successor-overlay.sha256": args.successor_overlay,
    }
    input_files = [
        _copy(source, successor / relative)
        for relative, source in input_sources.items()
    ]
    # These Task10 reports are copied while the candidate is sealed, so
    # preseal consumes candidate-bound evidence rather than injected files.
    r71b_evidence_files = _write_r71b_evidence(evidence_inputs, successor)
    input_files.extend(r71b_evidence_files)
    wheel_sources = {
        "artifacts/build-1/hermes_agent-0.17.0-py3-none-any.whl": args.build_1_hermes,
        "artifacts/build-1/physique_checkin_cli-0.1.0-py3-none-any.whl": args.build_1_profile,
        "artifacts/build-2/hermes_agent-0.17.0-py3-none-any.whl": args.build_2_hermes,
        "artifacts/build-2/physique_checkin_cli-0.1.0-py3-none-any.whl": args.build_2_profile,
    }
    wheel_files = [
        _copy(source, successor / relative)
        for relative, source in wheel_sources.items()
    ]
    receipt_files = [
        _copy(path, successor / "receipts" / path.relative_to(args.receipts_root))
        for path in sorted(args.receipts_root.rglob("*"))
        if path.is_file()
    ]

    source_inventory = _inventory(successor, source_files)
    input_inventory = _inventory(successor, input_files)
    wheel_inventory = _inventory(successor, wheel_files)
    evidence_inventory = _inventory(successor, receipt_files)
    hermes_digest = sha256_file(wheel_files[0])
    profile_digest = sha256_file(wheel_files[1])
    interpreter = Path(sys.executable).resolve()
    derivation_inputs: dict[str, JsonValue] = {
        "base_candidate_digest": require_string(
            require_object(base_manifest["identities"], "base identities").get(
                "candidate_digest"
            ),
            "base candidate digest",
        ),
        "base_manifest_sha256": sha256_file(args.base),
        "evidence_digest": inventory_digest(evidence_inventory),
        "hermes_wheel_sha256": hermes_digest,
        "interpreter_sha256": sha256_file(interpreter),
        "profile_wheel_sha256": profile_digest,
        "r71b_evidence_digest": inventory_digest(
            _inventory(successor, r71b_evidence_files)
        ),
        "source_tree_digest": inventory_digest(source_inventory),
        "successor_overlay_sha256": sha256_file(args.successor_overlay),
        "v17_evidence_manifest_sha256": sha256_file(
            _v17_input(
                args.v17_evidence,
                "evidence-files.sha256",
                "v17-evidence-files.sha256",
            )
        ),
        "v17_patch_tree_sha256": sha256_file(
            _v17_input(
                args.v17_evidence,
                "patch-tree.sha256",
                "v17-patch-tree.sha256",
            )
        ),
        "v17_sandbox_diff_sha256": sha256_file(
            _v17_input(
                args.v17_evidence,
                "sandbox.diff",
                "v17-sandbox.diff",
            )
        ),
        "v17_source_set_sha256": sha256_file(
            _v17_input(
                args.v17_evidence,
                "exact-current-source-set.final.sha256",
                "v17-exact-source-set.sha256",
            )
        ),
    }
    candidate_digest = sha256_bytes(canonical(derivation_inputs))
    source_values: list[JsonValue] = list(source_inventory)
    input_values: list[JsonValue] = list(input_inventory)
    wheel_values: list[JsonValue] = list(wheel_inventory)
    evidence_values: list[JsonValue] = list(evidence_inventory)
    manifest: dict[str, JsonValue] = {
        "schema": "nutricoach-v150-combined-candidate-manifest-v1",
        "status": "QUALIFIED_PENDING_LIVE_AUTHORIZATION",
        "candidate_digest": candidate_digest,
        "capabilities": {
            "nutricoach_channel_inbox_v1": {
                "compiled": True,
                "configured": False,
                "authorized": False,
            },
            "nutricoach_multi_customer_v1": {
                "compiled": True,
                "configured": False,
                "authorized": False,
                "authorized_capacity": 0,
                "post_migration_capacity": 5,
            },
        },
        "derivation_inputs": derivation_inputs,
        "source_inventory": source_values,
        "input_inventory": input_values,
        "wheel_inventory": wheel_values,
        "evidence_inventory": evidence_values,
        "builds": [
            {
                "hermes": wheel_inventory[0]["path"],
                "profile": wheel_inventory[1]["path"],
            },
            {
                "hermes": wheel_inventory[2]["path"],
                "profile": wheel_inventory[3]["path"],
            },
        ],
        "interpreter": {
            "path": str(interpreter),
            "sha256": sha256_file(interpreter),
            "version": sys.version,
        },
    }
    _ = (successor / "manifest.json").write_bytes(canonical(manifest) + b"\n")
    qualification: dict[str, JsonValue] = {
        "candidate_digest": candidate_digest,
        "status": "QUALIFIED_PENDING_LIVE_AUTHORIZATION",
    }
    _ = (successor / "qualification.json").write_bytes(canonical(qualification) + b"\n")
    for path in successor.rglob("*"):
        if path.is_file() and not path.is_symlink():
            if path.suffix in {".pyc", ".pyo"} or "__pycache__" in path.parts:
                raise CandidateSealError("candidate_bytecode")
            path.chmod(0o444)
    for path in sorted(
        (entry for entry in successor.rglob("*") if entry.is_dir()),
        reverse=True,
    ):
        path.chmod(0o555)
    successor.chmod(0o555)
    print(candidate_digest)
    return 0

if __name__ == "__main__":
    raise SystemExit(main())


#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.12,<3.14"
# dependencies = ["pydantic>=2,<3"]
# ///

# ─── How to run ───
#   uv run scripts/verify_nutricoach_v150_candidate.py --base BASE.json \
#     --successor CANDIDATE_DIR --manifest CANDIDATE_DIR/manifest.json
# ──────────────────

"""Verify the immutable NutriCoach v1.5 combined candidate."""

from __future__ import annotations

import argparse
import json
import sys
import zipfile
from pathlib import Path
from typing import Final

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from scripts.verify_nutricoach_v140_candidate_core import (
    CandidateContractError,
    JsonValue,
    canonical,
    inventory_digest,
    load_json,
    require_digest,
    require_object,
    require_string,
    sha256_bytes,
    sha256_file,
    verify_hash_entries,
)
from scripts.nutricoach_v150_candidate_wheel_sources import (
    verify_candidate_file_set,
    verify_wheel_sources,
)
from scripts.nutricoach_v150_r71b_task10_evidence import (
    Task10EvidenceError,
    verify_candidate_task10_evidence,
)
from scripts.verify_nutricoach_v150_candidate_inputs import verify_v17_overlay

_V17_EVIDENCE_MANIFEST_SHA256: Final = (
    "17e1909289829d035305703cb8a0e1b5313de21ad7a7ecb825cb7093f71d4389"
)
_V17_SANDBOX_DIFF_SHA256: Final = (
    "e2aa170a245054abf92cadc34663f9820f88023d597d72be1becb9978043e9b8"
)
_V17_SOURCE_SET_SHA256: Final = (
    "e163bf25d4d56dea9ce0d495446f4bbf9b1061c8ed0d602c885b68b1bb1c15cb"
)
_R71B_EVIDENCE_INPUTS: Final = {
    "r70_error": "inputs/r70-canonical-authority-drift.json",
    "observer": "inputs/r71b-observer-final.json",
    "health_recovery": "inputs/r71b-fixed-collector.json",
}
_R71B_EVIDENCE_INPUT_PATHS: Final = frozenset(_R71B_EVIDENCE_INPUTS.values())

def _parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description=__doc__)
    _ = parser.add_argument("--base", required=True, type=Path)
    _ = parser.add_argument("--successor", required=True, type=Path)
    _ = parser.add_argument("--manifest", required=True, type=Path)
    return parser

class CliNamespace(argparse.Namespace):
    """Mutable argparse destination with statically known path fields."""

    def __init__(self) -> None:
        super().__init__()
        self.base: Path = Path()
        self.successor: Path = Path()
        self.manifest: Path = Path()

def verify_capabilities(manifest: dict[str, JsonValue]) -> None:
    capabilities = require_object(manifest.get("capabilities"), "capabilities")
    channel = require_object(
        capabilities.get("nutricoach_channel_inbox_v1"), "channel inbox"
    )
    multi = require_object(
        capabilities.get("nutricoach_multi_customer_v1"), "multi customer"
    )
    if channel != {"compiled": True, "configured": False, "authorized": False}:
        raise CandidateContractError("Channel Inbox is not compiled default-OFF")
    if multi != {
        "compiled": True,
        "configured": False,
        "authorized": False,
        "authorized_capacity": 0,
        "post_migration_capacity": 5,
    }:
        raise CandidateContractError("multi-customer capability contract is invalid")

def r71b_evidence_digest(entries: list[dict[str, JsonValue]]) -> str:
    """Return the digest of the three Task10 reports required by r71b preseal."""
    evidence = [
        entry
        for entry in entries
        if require_string(entry.get("path"), "input path")
        in _R71B_EVIDENCE_INPUT_PATHS
    ]
    paths = {
        require_string(entry.get("path"), "r71b evidence path")
        for entry in evidence
    }
    if paths != set(_R71B_EVIDENCE_INPUT_PATHS):
        raise CandidateContractError("r71b maintenance evidence input set is invalid")
    return inventory_digest(evidence)

def _verify_authority_receipt(
    root: Path,
    wheel_entries: list[dict[str, JsonValue]],
) -> None:
    receipt = require_object(
        load_json(root / "receipts/authority-verification.json"),
        "authority verification receipt",
    )
    wheel_builds = require_object(
        receipt.get("wheel_builds"),
        "authority verification wheels",
    )
    expected_hermes = sha256_file(
        root / require_string(wheel_entries[0].get("path"), "receipt Hermes wheel")
    )
    expected_profile = sha256_file(
        root / require_string(wheel_entries[1].get("path"), "receipt profile wheel")
    )
    if (
        receipt.get("status") != "PASS"
        or receipt.get("external_events") != 0
        or wheel_builds.get("reproducible") is not True
        or wheel_builds.get("hermes_sha256") != expected_hermes
        or wheel_builds.get("profile_sha256") != expected_profile
    ):
        raise CandidateContractError("authority verification receipt is stale")

def verify(base_path: Path, root: Path, manifest_path: Path) -> str:
    manifest = require_object(load_json(manifest_path), "manifest")
    if manifest.get("schema") != "nutricoach-v150-combined-candidate-manifest-v1":
        raise CandidateContractError("candidate manifest schema is invalid")
    if manifest.get("status") != "QUALIFIED_PENDING_LIVE_AUTHORIZATION":
        raise CandidateContractError("candidate status is not qualified")
    verify_capabilities(manifest)
    source_entries = verify_hash_entries(
        root, manifest.get("source_inventory"), "source_inventory"
    )
    input_entries = verify_hash_entries(
        root, manifest.get("input_inventory"), "input_inventory"
    )
    wheel_entries = verify_hash_entries(
        root, manifest.get("wheel_inventory"), "wheel_inventory"
    )
    evidence_entries = verify_hash_entries(
        root, manifest.get("evidence_inventory"), "evidence_inventory"
    )
    try:
        _ = verify_candidate_task10_evidence(root, _R71B_EVIDENCE_INPUTS)
    except Task10EvidenceError as error:
        raise CandidateContractError("r71b Task10 evidence is invalid") from error
    _verify_authority_receipt(root, wheel_entries)
    verify_candidate_file_set(root, manifest)
    verify_v17_overlay(root, source_entries)

    derivation = require_object(manifest.get("derivation_inputs"), "derivation_inputs")
    base = require_object(load_json(base_path), "base manifest")
    base_identities = require_object(base.get("identities"), "base identities")
    expected: dict[str, JsonValue] = {
        "base_candidate_digest": require_digest(
            base_identities.get("candidate_digest"), "base candidate digest"
        ),
        "base_manifest_sha256": sha256_file(base_path),
        "evidence_digest": inventory_digest(evidence_entries),
        "hermes_wheel_sha256": sha256_file(
            root / require_string(wheel_entries[0].get("path"), "build-1 Hermes")
        ),
        "interpreter_sha256": sha256_file(Path(sys.executable).resolve()),
        "profile_wheel_sha256": sha256_file(
            root / require_string(wheel_entries[1].get("path"), "build-1 profile")
        ),
        "r71b_evidence_digest": r71b_evidence_digest(input_entries),
        "source_tree_digest": inventory_digest(source_entries),
        "successor_overlay_sha256": sha256_file(
            root / "inputs/successor-overlay.sha256"
        ),
        "v17_evidence_manifest_sha256": sha256_file(
            root / "inputs/v17-evidence-files.sha256"
        ),
        "v17_patch_tree_sha256": sha256_file(root / "inputs/v17-patch-tree.sha256"),
        "v17_sandbox_diff_sha256": sha256_file(root / "inputs/v17-sandbox.diff"),
        "v17_source_set_sha256": sha256_file(
            root / "inputs/v17-exact-source-set.sha256"
        ),
    }
    if derivation != expected:
        raise CandidateContractError("canonical product derivation inputs differ")
    if (
        expected["v17_evidence_manifest_sha256"] != _V17_EVIDENCE_MANIFEST_SHA256
        or expected["v17_sandbox_diff_sha256"] != _V17_SANDBOX_DIFF_SHA256
        or expected["v17_source_set_sha256"] != _V17_SOURCE_SET_SHA256
    ):
        raise CandidateContractError("immutable v17 qualification input mismatch")
    candidate = sha256_bytes(canonical(derivation))
    claimed = require_digest(manifest.get("candidate_digest"), "candidate digest")
    component_digests = {
        require_digest(expected["hermes_wheel_sha256"], "derived Hermes wheel digest"),
        require_digest(
            expected["profile_wheel_sha256"], "derived profile wheel digest"
        ),
        require_digest(expected["source_tree_digest"], "derived source digest"),
    }
    if candidate != claimed or candidate in component_digests:
        raise CandidateContractError("full-product candidate identity is invalid")
    if sha256_file(root / "inputs/base-manifest.json") != sha256_file(base_path):
        raise CandidateContractError("snapshot base manifest mismatch")
    if len(wheel_entries) != 4:
        raise CandidateContractError("exactly two detached wheel pairs are required")
    wheels = [
        root / require_string(entry.get("path"), "wheel path")
        for entry in wheel_entries
    ]
    if sha256_file(wheels[0]) != sha256_file(wheels[2]):
        raise CandidateContractError("Hermes wheel builds are not reproducible")
    if sha256_file(wheels[1]) != sha256_file(wheels[3]):
        raise CandidateContractError("profile wheel builds are not reproducible")
    source_root = Path(__file__).resolve().parents[1]
    for entry in source_entries:
        relative = Path(require_string(entry.get("path"), "source path"))
        product_relative = Path(*relative.parts[2:])
        if sha256_file(source_root / product_relative) != require_digest(
            entry.get("sha256"), "source hash"
        ):
            raise CandidateContractError(f"working source mismatch: {product_relative}")
    verify_wheel_sources(source_root, wheels[0], wheels[1])
    verify_wheel_sources(source_root, wheels[2], wheels[3])
    qualification = require_object(
        load_json(root / "qualification.json"), "qualification"
    )
    if qualification != {
        "candidate_digest": candidate,
        "status": "QUALIFIED_PENDING_LIVE_AUTHORIZATION",
    }:
        raise CandidateContractError("qualification binding is invalid")
    return candidate

def main() -> int:
    args = _parser().parse_args(namespace=CliNamespace())
    try:
        candidate = verify(args.base, args.successor, args.manifest)
    except (CandidateContractError, OSError, ValueError, zipfile.BadZipFile) as error:
        print(f"NUTRICOACH_V150_CANDIDATE_FAIL:{error}")
        return 1
    print(json.dumps({"candidate_digest": candidate}, sort_keys=True))
    print("NUTRICOACH_V150_CANDIDATE_PASS")
    return 0

if __name__ == "__main__":
    raise SystemExit(main())


"""Real disposable r71b maintenance lifecycle contracts."""

from __future__ import annotations

import hashlib
import json
import os
from datetime import date, datetime
from pathlib import Path

import pytest
from pydantic import JsonValue, TypeAdapter

from gateway.platforms.nutrition_weekly_maintenance_contract import (
    Topic59MaintenanceScopeV1,
    canonical_json,
)
from scripts import (
    nutricoach_v150_r71b_maintenance_transaction as transaction,
)
from scripts import nutricoach_v150_r71b_sealed_host as sealed_host
from scripts.nutricoach_v150_concrete_host import ConcreteLiveHost
from scripts.nutricoach_v150_phase_journal import PhaseJournal
from scripts.nutricoach_v150_r71b_package import R71bPackageArtifacts, derive_r71b_package
from scripts.nutricoach_v150_sealed_authority import GlobalLedger
from scripts.nutricoach_v150_sealed_controller import execute_disposable, recover_pending
from scripts.nutricoach_v150_sealed_target import DisposableService
from tests.test_nutricoach_v150_sealed_controller import target_fixture

_OBJECT = TypeAdapter(dict[str, JsonValue])

def _artifacts(candidate_digest: str) -> R71bPackageArtifacts:
    scope = Topic59MaintenanceScopeV1(
        candidate_digest=candidate_digest,
        config_digest="2" * 64,
        route_digest="3" * 64,
        customer_identity_digest="4" * 64,
        card_slot="5" * 64,
        kst_day=date(2026, 9, 1),
        not_before=datetime.fromisoformat("2026-09-01T16:00:00+09:00"),
        expires_at=datetime.fromisoformat("2026-09-01T16:10:00+09:00"),
    )
    binding: dict[str, JsonValue] = _OBJECT.validate_python({
        "schema": "nutricoach-v150-r71b-package-binding-inputs-v1",
        "product_generation": "r71",
        "package_namespace": "r71b-maintenance",
        "authority_id": "nutricoach-v150-v15-runtime-authority-r71b-maintenance",
        "paths": {"observer_root": "/tmp/observer-r71"},
        "candidate": {"candidate_digest": candidate_digest},
        "wheels": [],
        "controller": {"files": {}},
        "protected_inventory": {"explicit_maintenance_volatile_paths": []},
        "dependency_snapshot": {"dependency_snapshot_sha256": "6" * 64},
        "authority_baseline": {"candidate_digest": "7" * 64},
        "target_binding_base": {"profile_root": "/tmp/profile"},
        "service_preparation": {"ActiveState": "active"},
        "maintenance_scope": scope.model_dump(mode="json", by_alias=True),
        "maintenance_scope_path": "maintenance/maintenance-scope.json",
        "maintenance_scope_file_sha256": "8" * 64,
        "maintenance_scope_digest": "9" * 64,
        "no_send_oracle": {"schema": "nutricoach-r71b-no-send-oracle-v1"},
        "no_send_oracle_path": "maintenance/no-send-oracle.json",
        "no_send_oracle_file_sha256": "a" * 64,
        "diagnosed_blocker_evidence": [],
    })
    return derive_r71b_package(binding, scope)

def _r70_job(*, status: str, error: str | None) -> dict[str, JsonValue]:
    return {
        "id": transaction.KNOWN_R70_CRON_JOB_ID,
        "name": transaction.KNOWN_R70_CRON_JOB_NAME,
        "schedule_display": transaction.KNOWN_R70_CRON_SCHEDULE,
        "inline_card": "nutrition-coaching-tick",
        "deliver": "local",
        "enabled": True,
        "state": "scheduled",
        "last_status": status,
        "last_error": error,
        "last_run_at": "2026-09-01T16:01:00+09:00",
    }

def _write_audit(path: Path, artifacts: R71bPackageArtifacts) -> None:
    hold = artifacts.hold
    audit: dict[str, JsonValue] = {
        "schema": "nutricoach-topic59-maintenance-skip-audit-v1",
        "hold_id": hold.hold_id,
        "hold_sha256": artifacts.hold_sha256,
        "authority_id": artifacts.authority.authority_id,
        "package_binding_digest": artifacts.package_binding_digest,
        "candidate_digest": hold.candidate_digest,
        "config_digest": hold.config_digest,
        "route_digest": hold.route_digest,
        "customer_identity_digest": hold.customer_identity_digest,
        "card_slot": hold.card_slot,
        "kst_day": hold.kst_day.isoformat(),
        "recorded_at": "2026-09-01T16:01:00+09:00",
        "terminal_state": "maintenance_skipped",
        "disposition": "noop_maintenance",
        "sent": False,
        "delivered": False,
        "message_id": None,
        "provider_receipt": None,
        "provider_calls": 0,
        "network_calls": 0,
    }
    audit["row_digest"] = hashlib.sha256(canonical_json(audit)).hexdigest()
    _ = path.write_bytes(canonical_json(audit) + b"\n")

def test_disposable_maintenance_reaches_committed_with_successor_postimage(
    tmp_path: Path,
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    # Given
    _ = target_fixture(tmp_path)
    service = DisposableService()
    host = ConcreteLiveHost.disposable(tmp_path, service)
    artifacts = _artifacts(host.candidate_digest)
    profile = host.paths.profile
    cron = profile / "cron/jobs.json"
    cron.parent.mkdir()
    initial_error = transaction.KNOWN_R70_CRON_ERROR
    _ = cron.write_text(
        json.dumps({"jobs": [_r70_job(status="error", error=initial_error)]}),
        encoding="utf-8",
    )
    ledger = profile / "data/weekly-operations-topic59.jsonl"
    _ = ledger.write_bytes(b"historical sending rows\n")
    evidence = tmp_path / "task-10-cron-no-send-recovery-analysis.json"
    _ = evidence.write_bytes(b"accepted r70 exception\n")
    r70_candidate = tmp_path / "r70-candidate"
    _ = r70_candidate.write_text("b" * 64 + "\n", encoding="utf-8")
    authority = tmp_path / "maintenance-authority.json"
    _ = authority.write_bytes(artifacts.authority_bytes)
    binding: dict[str, JsonValue] = {
        "maintenance_authority_path": str(authority),
        "maintenance_authority_sha256": artifacts.authority_sha256,
        "package_binding_digest": artifacts.package_binding_digest,
        "candidate_digest": host.candidate_digest,
        "maintenance_ledger_path": str(ledger),
        "maintenance_ledger_sha256": hashlib.sha256(ledger.read_bytes()).hexdigest(),
        "maintenance_output_directory": str(profile / "cron/output" / transaction.KNOWN_R70_CRON_JOB_ID),
        "r70_error_evidence_path": str(evidence),
        "r70_error_evidence_sha256": hashlib.sha256(evidence.read_bytes()).hexdigest(),
        "authority_baseline": {"candidate_path": str(r70_candidate)},
        "package_digest": artifacts.final_package_digest,
    }
    evidence_sha = hashlib.sha256(evidence.read_bytes()).hexdigest()
    for module in (transaction, sealed_host):
        monkeypatch.setattr(module, "KNOWN_R70_CRON_ERROR_EVIDENCE_SHA256", evidence_sha)
        monkeypatch.setattr(module, "KNOWN_R70_RUNTIME_CANDIDATE_DIGEST", "b" * 64)

    original_start = host.start

    def start_and_complete_maintenance() -> None:
        original_start()
        maintenance_root = profile / "data/topic59-maintenance-r71b"
        (profile / "cron/output" / transaction.KNOWN_R70_CRON_JOB_ID).mkdir(
            parents=True,
            exist_ok=True,
        )
        output = profile / "cron/output" / transaction.KNOWN_R70_CRON_JOB_ID / "r71b.md"
        _ = output.write_text("Status: maintenance no-op completed\n", encoding="utf-8")
        (maintenance_root / "hold.json").unlink()
        _write_audit(maintenance_root / "skip-audit.json", artifacts)
        replacement = cron.with_suffix(".next")
        _ = replacement.write_text(
            json.dumps({"jobs": [_r70_job(status="ok", error=None)]}),
            encoding="utf-8",
        )
        os.replace(replacement, cron)

    monkeypatch.setattr(host, "start", start_and_complete_maintenance)
    approval = "AUTHORIZE NUTRICOACH V1.5 R71B MAINTENANCE UPGRADE " + artifacts.final_package_digest

    # When
    _ = execute_disposable(
        approval,
        tmp_path,
        host,
        expected_approval=approval,
        maintenance_binding=binding,
    )

    # Then
    assert PhaseJournal(host.paths.execution_root / "phase.json").phase() == "COMMITTED"
    assert host.ledger_consumed()
    assert service.running
    credential = host.paths.successor_runtime.parent / "runtime-authority/nutricoach-topic59-maintenance-r71b.json"
    assert credential.read_bytes() == artifacts.authority_bytes
    assert host.verify_exact_postimages()
    assert not host.provider_events
    assert not host.network_events

def test_fresh_confirmed_recovery_loads_durable_successor_postimages(
    tmp_path: Path,
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    # Given: an actual disposable successor reaches durable confirmation before
    # process death, so the recovery host has no in-memory postimage map.
    _ = target_fixture(tmp_path)
    service = DisposableService()
    host = ConcreteLiveHost.disposable(tmp_path, service)
    artifacts = _artifacts(host.candidate_digest)
    profile = host.paths.profile
    cron = profile / "cron/jobs.json"
    cron.parent.mkdir()
    _ = cron.write_text(
        json.dumps({"jobs": [_r70_job(
            status="error", error=transaction.KNOWN_R70_CRON_ERROR,
        )]}),
        encoding="utf-8",
    )
    ledger_path = profile / "data/weekly-operations-topic59.jsonl"
    _ = ledger_path.write_bytes(b"historical sending rows\n")
    evidence = tmp_path / "task-10-cron-no-send-recovery-analysis.json"
    _ = evidence.write_bytes(b"accepted r70 exception\n")
    r70_candidate = tmp_path / "r70-candidate"
    _ = r70_candidate.write_text("b" * 64 + "\n", encoding="utf-8")
    authority = tmp_path / "maintenance-authority.json"
    _ = authority.write_bytes(artifacts.authority_bytes)
    binding: dict[str, JsonValue] = {
        "maintenance_authority_path": str(authority),
        "maintenance_authority_sha256": artifacts.authority_sha256,
        "package_binding_digest": artifacts.package_binding_digest,
        "candidate_digest": host.candidate_digest,
        "maintenance_ledger_path": str(ledger_path),
        "maintenance_ledger_sha256": hashlib.sha256(ledger_path.read_bytes()).hexdigest(),
        "maintenance_output_directory": str(
            profile / "cron/output" / transaction.KNOWN_R70_CRON_JOB_ID
        ),
        "r70_error_evidence_path": str(evidence),
        "r70_error_evidence_sha256": hashlib.sha256(evidence.read_bytes()).hexdigest(),
        "authority_baseline": {"candidate_path": str(r70_candidate)},
        "package_digest": artifacts.final_package_digest,
    }
    evidence_sha = hashlib.sha256(evidence.read_bytes()).hexdigest()
    for module in (transaction, sealed_host):
        monkeypatch.setattr(module, "KNOWN_R70_CRON_ERROR_EVIDENCE_SHA256", evidence_sha)
        monkeypatch.setattr(module, "KNOWN_R70_RUNTIME_CANDIDATE_DIGEST", "b" * 64)
    authorization = GlobalLedger(host.paths.ledger_root, host.candidate_digest)
    authorization.reserve()
    journal = PhaseJournal(host.paths.execution_root / "phase.json")
    host.capture_preflight()
    host.verify_preflight()
    host.write_recovery_manifest()
    host.stop()
    host.record_snapshot()
    host.stopped_probe()
    host.install()
    host.off_smoke()
    host.migration_dry_run()
    host.migration_apply()
    host.weekly_startup_smoke()
    host.promote_runtime_authority()
    maintenance = sealed_host.build_r71b_maintenance_controller(host, binding, journal)
    approval = (
        "AUTHORIZE NUTRICOACH V1.5 R71B MAINTENANCE UPGRADE "
        + artifacts.final_package_digest
    )
    maintenance.arm(approval)
    host.switch_systemd()
    host.reload()
    original_start = host.start

    def start_and_confirm() -> None:
        original_start()
        root = profile / "data/topic59-maintenance-r71b"
        output = profile / "cron/output" / transaction.KNOWN_R70_CRON_JOB_ID / "r71b.md"
        output.parent.mkdir(parents=True, exist_ok=True)
        _ = output.write_text("Status: maintenance no-op completed\n", encoding="utf-8")
        (root / "hold.json").unlink()
        _write_audit(root / "skip-audit.json", artifacts)
        replacement = cron.with_suffix(".next")
        _ = replacement.write_text(
            json.dumps({"jobs": [_r70_job(status="ok", error=None)]}),
            encoding="utf-8",
        )
        os.replace(replacement, cron)

    monkeypatch.setattr(host, "start", start_and_confirm)
    maintenance.complete_start()
    assert journal.phase() == "MAINTENANCE_CONFIRMED"
    assert host.verify_exact_postimages()

    # When: a fresh host reconstructs the postimage map from disk and performs
    # the real post-fence rather than a mocked substitute.
    recovered_service = DisposableService()
    recovered = ConcreteLiveHost.disposable(tmp_path, recovered_service)
    recover_pending(recovered, binding)

    # Then
    assert journal.phase() == "COMMITTED"
    assert authorization.outcome() == "SUCCEEDED"
    assert recovered_service.running
    assert recovered.verify_exact_postimages()
    assert not recovered.provider_events
    assert not recovered.network_events

def test_preconfirmation_start_fault_restores_and_pauses_the_predecessor(
    tmp_path: Path,
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    # Given
    paths = target_fixture(tmp_path)
    service = DisposableService()
    host = ConcreteLiveHost.disposable(
        tmp_path,
        service,
        fault=RuntimeError("start"),
        fault_stage="start",
    )
    artifacts = _artifacts(host.candidate_digest)
    profile = host.paths.profile
    cron = profile / "cron/jobs.json"
    cron.parent.mkdir()
    _ = cron.write_text(
        json.dumps({"jobs": [_r70_job(
            status="error", error=transaction.KNOWN_R70_CRON_ERROR,
        )]}),
        encoding="utf-8",
    )
    before = tuple(path.read_bytes() for path in paths)
    ledger_path = profile / "data/weekly-operations-topic59.jsonl"
    _ = ledger_path.write_bytes(b"historical sending rows\n")
    evidence = tmp_path / "task-10-cron-no-send-recovery-analysis.json"
    _ = evidence.write_bytes(b"accepted r70 exception\n")
    r70_candidate = tmp_path / "r70-candidate"
    _ = r70_candidate.write_text("b" * 64 + "\n", encoding="utf-8")
    authority = tmp_path / "maintenance-authority.json"
    _ = authority.write_bytes(artifacts.authority_bytes)
    binding: dict[str, JsonValue] = {
        "maintenance_authority_path": str(authority),
        "maintenance_authority_sha256": artifacts.authority_sha256,
        "package_binding_digest": artifacts.package_binding_digest,
        "candidate_digest": host.candidate_digest,
        "maintenance_ledger_path": str(ledger_path),
        "maintenance_ledger_sha256": hashlib.sha256(ledger_path.read_bytes()).hexdigest(),
        "maintenance_output_directory": str(
            profile / "cron/output" / transaction.KNOWN_R70_CRON_JOB_ID
        ),
        "r70_error_evidence_path": str(evidence),
        "r70_error_evidence_sha256": hashlib.sha256(evidence.read_bytes()).hexdigest(),
        "authority_baseline": {"candidate_path": str(r70_candidate)},
        "package_digest": artifacts.final_package_digest,
    }
    evidence_sha = hashlib.sha256(evidence.read_bytes()).hexdigest()
    for module in (transaction, sealed_host):
        monkeypatch.setattr(module, "KNOWN_R70_CRON_ERROR_EVIDENCE_SHA256", evidence_sha)
        monkeypatch.setattr(module, "KNOWN_R70_RUNTIME_CANDIDATE_DIGEST", "b" * 64)
    approval = (
        "AUTHORIZE NUTRICOACH V1.5 R71B MAINTENANCE UPGRADE "
        + artifacts.final_package_digest
    )

    # When / Then
    with pytest.raises(RuntimeError, match="start") as failure:
        _ = execute_disposable(
            approval,
            tmp_path,
            host,
            expected_approval=approval,
            maintenance_binding=binding,
        )
    assert not getattr(failure.value, "__notes__", ()), failure.value.__notes__

    cron_document = _OBJECT.validate_json(cron.read_bytes())
    jobs = cron_document.get("jobs")
    assert isinstance(jobs, list) and len(jobs) == 1 and isinstance(jobs[0], dict)
    paused = jobs[0]
    assert paused["enabled"] is False
    assert paused["state"] == "paused"
    assert paused["last_error"] == transaction.KNOWN_R70_CRON_ERROR
    assert PhaseJournal(host.paths.execution_root / "phase.json").phase() == (
        "ROLLED_BACK_SAFE_CRON_PAUSED"
    )
    assert service.running
    assert service.observe()["NRestarts"] == "0"
    assert tuple(path.read_bytes() for path in paths) == before
    assert not host.provider_events
    assert not host.network_events