Long-term memory — personal + business long-term memory

The actual documents the agents read and work from, shown exactly as they are on disk — not a summary. See the progress view instead · All projects

Plan PLAN-D4C-HEALTH.md

**Owner: the staffed overseeing Claude Code senior-engineer session (“Boris”) for OpenBrain delivery D4C.**
**Purpose: build-plan/spec for the later, individually dispatched D4C health-runtime cutover; this authoring task freezes the health regression and comparison contracts and makes no code, selector, process, deployment, or traffic change.**

**Rafter requirements WITHDRAWN — Nick, 2026-09-21: “disregard rafter purge it from the system”.** All Rafter-only installs, scans, reviews, quota blockers and prerequisites below are closed by that decision, not passed. Retain past scan evidence and every unrelated security finding, independent review and functional check; do not invoke or reinstall Rafter.

# PLAN — D4C health runtime chain

**🔴🔴 THIS IS THE ONLY PLANNING DOCUMENT FOR SUBPROJECT D4C. Do not create a second D4C plan, tracker, fixture, or scratch state file — extend this one or its fenced block in the parent STATE.md, and log any scope/contract change as a dated delta in PLAN-CHANGES.md.**

> THIS AUTHORING TASK IS PLAN-ONLY. It changes no code, selector, process, deployment, or traffic. After this plan is accepted, later execution is authorised only through the individually dispatched §3b rows and their prerequisites; no prose outside those rows authorises a runtime action. D4C covers parent execution-map rows 12–14: items 1–5's narrative-only branch, item 11's deployment-freshness receipt, and the health-chain before/after gate plus rollback drill.

## 0 · Gate Zero receipts

- Failure Mode Registry loaded: `.claude/skills/plan/references/failure-registry.md`, opened 2026-08-26; 98 parseable entries. Re-derive with `python3 -c "import re;from pathlib import Path;p=Path('.claude/skills/plan/references/failure-registry.md');print(sum(1 for x in p.read_text().splitlines() if x.startswith('|') and not re.match(r'^\\|[\\s:|-]+\\|?$',x) and not x.startswith('| Failure mode')))"`.
- Canonical specs loaded: `.agents/skills/plan/SKILL.md` and its plan/failure-registry references; `RULEBOOK.md`; `FILE-STANDARD.md`; `projects/ops/PROMPT-SPEC.md` P1–P7; parent `PLAN-D4-RETIREMENT.md` in full; sibling `PLAN-D4A-CONTRACT.md` in full; the code, QA, handback, verification, and model standards inherited by the parent; and `projects/ops/agents/check_plan.py`.
- Ownership check: parent `PLAN-D4-RETIREMENT.md` §1b assigns D4C, owner Boris, and this exact path; parent §3b task 11 names this exact child-plan deliverable. The new file is an explicitly required child, not a rival parent plan, store, service, fixture, or tracker.
- Expected inputs confirmed to exist: items 1–5 at `answer_cache.py`, `answer_engine.py`, `guide_text.py`, `retriever.py`, and `skippy_answer.py`; item 11 at `projects/ops/skippy-jobs/jobs/engine-image-freshness.mjs`; its running server seam at `projects/personal/skippy-app/bridge/server.py`; its bundle seam at `projects/personal/skippy-app/fly-deploy/bundle.sh`; the parent’s frozen 20-question fixture; the existing engine test runner and named standalone suites in §3; `health_marker_filter.py`; its `_test_health_marker_filter.py` suite; D4A comparison evidence; parent state/assumptions/change ledgers; and the plan checker. Each path was independently rediscovered with `find` on 2026-08-26 rather than trusted only from the parent. V2 inspection also opened: `skippy_answer.py`'s `CLASS_STORE_SCOPE`, branch/capture/cache sequence, and `ServiceResult`; `retriever.py`'s `classify`, `_GENERAL_SOURCES`, `retrieve`, and `assemble`; `answer_cache.py`'s one `AnswerCache` plus module-level `default_cache`; `cutover_answer.py`'s two marker-filter passes; item 11's `decideAction`, `runGate`, kids gate, rate limit, rebuild, post-build check, deploy, heartbeat, and live-container verification; the bridge’s existing authenticated D4A personal route; and `bundle.sh`'s existing bridge copy and privacy gates.
- PROMPT-SPEC scan (P1–P7): P1's “narrative-only branch” is resolved by the parent’s exact eligible classes (`family` and `other`) and the existing health-class list; P2 is resolved by §3's branch order, filter enforcement, receipt, rollback verbs, and per-case outcomes; P3 does not fire because all claimed seams were opened; P4 is bounded by the explicit anti-scope; P5 is resolved by comparison/receipt evidence paths and live read-back; P6/P7 do not fire. No unresolved variable changes the data model, ownership boundary, or done-line.
- Gate Zero health-chain findings: (1) the current `other` route is a health-shaped catch-all as well as a general narrative route—`retriever.py`'s `_GENERAL_SOURCES["other"]` includes `health_context`, `lab_history_context`, and `structural_blockers`—so routing it to OpenBrain without deterministic input/output filtering could leak a raw marker or dose; (2) branching before `skippy_answer.py`'s existing class and owner gates could widen one household member’s access; (3) sharing `answer_cache.py`'s one existing cache key between health and narrative could cross-serve answers or retain pre-cutover prose; (4) item 11's live proof is hard-wired to `md5sum /app/memory/nick-full.md`, which ceases to be a valid health deployment receipt after the guide dependency leaves; (5) D4C is higher-risk than D4B because it changes the daily health answer chain, so any safety, identity, route, receipt, or silent-fallback failure triggers rollback to D4B within the parent-frozen five-minute target. Re-measure these facts with `rg -n 'CLASS_STORE_SCOPE|_GENERAL_SOURCES|class AnswerCache|default_cache|md5sum /app/memory/nick-full.md' projects/personal/health/engine/{skippy_answer.py,retriever.py,answer_cache.py} projects/ops/skippy-jobs/jobs/engine-image-freshness.mjs`.
- Deterministic safety control opened: `health_marker_filter.py` scans retrieved context and generated output for marker-number/dose shapes; `_test_health_marker_filter.py` proves the real LDL-C/ApoB leak is caught and performs a live cutover-answer check. Both files are frozen no-touch D4C contracts. Their current SHA-256 values are `ec87df197c1bf502316a3758732ec520936ae6cf267c47f52ddda7741aa38583` and `eb0bebdac50743be0f30a4958b10accf64f8a7503757563bea2e0cc20b2ae1da`; re-measure with `shasum -a 256 projects/personal/health/engine/brain-routing/health_marker_filter.py projects/personal/health/engine/brain-routing/_test_health_marker_filter.py`.
- Confirmation sheet: D4C introduces no new V1/V2/V3 fork. Parent §1a rows 1–2 already confirm all 17 staged readers and the human acceptance boundary; the parent also fixes the D4C five-minute rollback target and 24-hour/20-question soak as engineering contracts. The mandatory SURFACE row below inherits Nick’s dated confirmation; no row is unconfirmed.

## 1 · Goal and definition of done

The canonical scope is parent `PLAN-D4-RETIREMENT.md` §1b D4C, §2 U01–U05/U11/U18–U21, §3 frozen contracts/state machine, §3b tasks 11–14, and §6 E4/E6/E8/E11/E12/E14. Those parent statements remain normative.

- **HOW IT'S USED:** after D4B is proven, Nick and confirmed household users ask through the same health-chain entry point. `family` and `other` narrative questions use the D4A personal service after the existing identity, owner, classification, routing, and capture gates; health classes continue through the existing Packet/engine/harness path. **HOW WE KNOW:** C01–C13 prove branch order and route separation; the frozen 20-question comparison is accepted case by case on the real health-chain surface.
- **WHAT IT LOOKS LIKE:** the same `ServiceResult`-shaped health-chain response, with narrative answers carrying the new route/provenance receipt, health answers carrying the existing safety/routing receipt, one split cache with route-correct revisioning, and item 11 checking an immutable engine/corpus receipt instead of a guide digest. **HOW WE KNOW:** C05/C09–C16 assert the exact fields, cache separation, mismatch behavior, and live receipt.
- **WHERE IT LIVES:** items 1–5 stay within their five existing source files; item 11 owns its existing job plus only the narrow authenticated receipt route in `bridge/server.py` and receipt-copy step in `fly-deploy/bundle.sh`. D4C tests, runbook, and evidence live under the existing `projects/ops/openbrain-delivery/` tree; state lives in the existing parent state block and item-11 state file. Nick judges surfaces he uses and Chantelle judges surfaces she uses, as confirmed in §1a. **HOW WE KNOW:** file-fence scan, live health-chain read-back, and the parent fixture/evidence consumers named in §§3/5.
- **WHAT IT MUST DO:** (1) preserve the exact existing identity/firewall/classification boundary before any narrative retrieval; (2) branch only `family` and `other`; (3) leave every named health class, `daily_state`, `business`, `admin`, and `engine_self` on their current engine path; (4) enforce the unchanged deterministic health-marker filter on candidate passages and candidate output, including health-shaped questions classified `other`; (5) keep ambient capture and `ServiceResult`/receipt semantics; (6) split the existing cache by served route and use the parent-frozen personal-corpus revision only for narrative entries while retaining health invalidation; (7) remove production personal/family use of raw guide/Packet assembly without changing the raw APIs or health loaders; (8) replace item 11's guide digest with parent U11’s exact fail-closed release/code/API-schema/corpus receipt; (9) compare all 20 frozen questions old/new, preserve health behavior, obtain correctness/safety/non-hallucination acceptance only, execute rollback within five minutes, then complete the 24-hour and 20-accepted-replay soak. **HOW WE KNOW:** §2's 40-case manifest, §3b tasks, and §6 binary gates.
- **WHAT IT IS NOT:** no change to `health_marker_filter.py` or its suite because D4C must preserve the safety backstop byte-for-byte; no change to health facts, marker values, protocols, hard flags, trial history, felt-state primacy, model, or source data because those belong to the health spine and are not migration mechanics; no voice/style/polish parity work because Nick explicitly excluded it from this stage’s sign-off; no D4D cloud-client or guide-shipping migration because D4D owns those readers after D4C proves the engine route (the narrow running-engine receipt seam named below remains U11/D4C); no D4B consumer repair because D4B must arrive as an accepted prerequisite; no guide deletion because retirement follows rollback and soak; no credential action because the existing authenticated boundary is reused; no new cache/store/fixture because canonical owners already exist; no production flip before D4A/D4B evidence is accepted because D4C depends on both contracts.
- **Trip-over protocol:** record one cited handover line in the parent STATE.md to the named D4B, D4D, health-spine, or guide-records owner and return to D4C. Do not investigate, fix, delete, deploy, rotate, or widen scope.

### D4C promotion and rollback rule

`legacy → shadow → openbrain` is inherited unchanged from the parent state machine. D4C shadow never serves the candidate. Promotion is blocked by one failed marker-filter assertion, hard flag, identity/owner gate, class route, subject attribution, health regression, correlation case, receipt field, dependency failure, or silent-fallback probe. Rollback target is the recorded last-known-good D4B engine release with `PERSONAL_ENGINE_ROUTE=legacy`; cloud remains legacy. Restore and read back within five minutes, without reversing OpenBrain or health data. Candidate-only cache entries are invalidated by namespace/revision; health entries and D4B state remain untouched.

The rollback drill uses a **verifier-side receipt mismatch**, not a production fault or data mutation: the verifier supplies one deliberately wrong expected `personal_corpus_revision` and must block the otherwise healthy candidate. The timer starts when that BLOCK verdict is recorded and the rollback command is issued; it stops only when Fly status reports the recorded D4B image/release, the narrative selector reports `legacy`, the local freshness actor reports its recorded `legacy-guide` verifier adapter, the old guide-digest read-back passes, and one frozen health-only probe returns its pre-cutover `question_class`, route, status, blocking layer, and safety-screen outcomes. The drill ends with the D4B image, narrative selector on legacy, and the prior guide-digest verifier adapter restored. Only a separate, fresh-gated task 8 may re-promote the candidate and restore the receipt verifier for soak. A missed target or failed read-back blocks re-promotion.

## 1a · Critical variables — confirmation sheet source

| # | The variable, in plain words | Value chosen | Alternatives rejected | Class | HOW WE KNOW | Cost if wrong | CONFIRMED |
|---|---|---|---|---|---|---|---|
| 1 | **SURFACE — who judges the daily-use health-chain surfaces represented by D4C** | Nick judges surfaces he uses; Chantelle judges surfaces she uses. Acceptance means correct factual support, correct subject attribution, no hallucinated fact, safety, and end-to-end capability—not voice/style/polish parity | Agent acceptance of a human surface; assuming Nick covers Chantelle’s surfaces; requiring response-polish parity in D4C | V1 | Inherited verbatim from parent §1a row 1, where Nick settled the users and acceptance boundary on 2026-08-26 | The migration could be accepted by the wrong person, miss a real surface, or reopen a settled polish requirement | `CONFIRMED` — Nick, 2026-08-26, “You + Chantelle for anything she uses” and “dont need to test output as its still dogshit - just capabilities flipped now and we'll polish the way skippy respinds and gravei etc later” |

**D4C-specific critical variables: none.** The parent already freezes staged scope, sign-off criteria, eligible classes, rollout states, 24-hour/20-question soak, and five-minute D4C rollback. Re-asking would reopen settled decisions.

**Considered and ruled NOT critical:**

- Whether `other` can be health-shaped — V2, settled by opening `_GENERAL_SOURCES`: it includes health/lab context. The child therefore adds forced-`other` leak/refusal cases; it does not ask Nick to design routing.
- Branch position — engineering/safety constraint: classification and both firewalls must precede it; otherwise two plausible positions produce a security defect rather than a user preference.
- Filter behavior — already an implemented hard safety contract with a real failure history; D4C may wire it, never reinterpret it.
- Cache revision shape — inherited from parent §3; D4C only proves route separation and failure behavior.
- Rollback trigger/target — inherited parent engineering contract: any blocking safety/correctness failure, D4B release, five minutes.
- Comparison questions — already frozen by parent task 5 and D4A; D4C consumes the identical fixture and adds route expectations, never authors a rival set.
- Freshness-receipt field mechanics — V2 design against the opened job and parent deployment contract; no human-habit decision.
- Outage choice — D4C changes the engine selector under shadow/rollback, not the D4D phone maintenance decision.

## 1b · Subproject decomposition

**SINGLE SUBPROJECT:** items 1–5, item 11, the before/after comparison, and the rollback drill are one health-stage sign-off unit. The freshness receipt cannot be accepted without the exact engine/corpus it identifies; the branch cannot promote without the same comparison and rollback proof. Tasks are separately fenced lanes, not independently shippable products.

## 2 · Complete headless UX map and test manifest

| Id | Entry point / state | Input | Expected behavior | Failure / edge behavior |
|---|---|---|---|---|
| C01 | `skippy_answer` narrative branch | authenticated `family` question | Existing classify, scope firewall, owner gate, route/capture run first; D4A personal service answers; no legacy Packet/guide path | Any pre-firewall retrieval or Packet call fails |
| C02 | `skippy_answer` catch-all branch | authenticated non-health `other` question | Same branch/order as C01; provenance and correlation retained | Unsupported candidate is explicit, not legacy fallback |
| C03 | Health-class route matrix | Exact health-class set: `health_labs`, `protocol_change`, `eq`, `sleep`, `skin`, `food` | A canonical JSON behavior receipt is byte-identical before/after for requester/owner/scope gates, question class, route and engine/harness selection, eligible source ids/statuses, health cache namespace/revision, safety-screen names/outcomes, result status/blocking layer, and receipt field names; generated answer prose and timing are excluded because they are stochastic/non-behavioral and the parent explicitly excludes polish parity | Any candidate personal-service call, changed canonical receipt byte, or new key added to `CLASS_STORE_SCOPE` without an explicit D4C disposition fails roster drift |
| C04 | Non-narrative route matrix | `daily_state`, `business`, `admin`, `engine_self` | Existing route and source eligibility remain unchanged | Any widening to narrative branch fails |
| C05 | Service contract/capture | family/other success, refusal, cache hit | Existing capture semantics and required `ServiceResult` fields persist; candidate route/provenance/selector/revision receipt is explicit | Missing field, changed status meaning, or capture bypass fails |
| C06 | Identity and owner gates | Nick, Chantelle, child, mismatched/adult-record probes | Existing pre-retrieval refusals remain; branch receives only a verified allowed requester | Missing identity never defaults; wrong-person retrieval fails |
| C07 | Marker filter — retrieved context | marker+number and dose passages retrieved for family/other/forced-other | Preserve the existing caller outcome exactly: drop each matching passage before synthesis; if no safe passage remains, return the existing “ask the health engine” safe answer without a model call | Any matching passage reaching the model, or whole-request refusal while safe passages remain, fails |
| C08 | Marker filter — generated output | candidate paraphrases or emits marker+number/dose | Preserve the existing output outcome exactly: block the whole generated answer and return the existing safe answer; never return/cache/evidence the generated text | Marker value in answer, logs, receipt, cache, or evidence fails |
| C09 | Marker suite immutability | pre/post D4C source tree | Both frozen SHA-256 values remain identical and `_test_health_marker_filter.py` passes | Any byte change or weakened assertion is an automatic block |
| C10 | Narrative cache revision | same family/other question across unchanged/changed personal corpus | Existing cache store uses narrative namespace + exact personal corpus revision; unchanged hits, changed misses | Revision failure bypasses narrative cache; never serves stale |
| C11 | Health cache preservation | health question across health-source changes and personal-only changes | Existing health invalidation/assertions remain; narrative entries cannot collide with health | Cross-route/identity hit or lost health invalidation fails |
| C12 | Raw guide/Packet reachability | family/other production call | No personal/family call reaches `guide_text`, family/life loaders, legacy Packet assembly, or raw guide bytes | Scanner proves a seeded positive before zero is accepted |
| C13 | Health loader reachability | every health route and forced health class | Existing health loaders, Packet grounding, safety screens, and receipts remain reachable | Removing/short-circuiting a health source fails |
| C14 | New dependency unavailable | store/embedder/model/application function fault | Map to `ServiceResult.status="refused_ungrounded"`, `blocking_layer="personal_narrative_unavailable"`, no `answer_text`, generic `refusal_text`, and a receipt containing request id, `route="personal-narrative"`, `result_class="unavailable"`, selector, and corpus revision; health path remains callable | Empty “not found,” stack/path/content, raw exception, missing receipt, or legacy answer fails |
| C15 | Item 11 receipt — valid | coherent built release after D4C | Authenticated endpoint returns exactly parent U11’s four fields with exact types; stable corpus double-read, independently derived expected values, and running-image read-back match | A guide filename/digest, extra field, or deploy exit is neither required nor accepted as proof |
| C16 | Item 11 receipt — invalid/partial | missing, stale, mixed-instance, unknown-selector, or mismatched field | Fail/UNVERIFIED; nothing deploys/promotes; disagreement cannot read as current | mtime-only, deploy-exit-only, or partial-field pass fails |
| C17 | Comparison — personal/family | D4-P01–P06 and D4-F01–F04, same old/new run window | Candidate grounded in new provenance, correct subject, no hallucination; human accepts correctness/safety only | Blank/rejected/aggregate score blocks |
| C18 | Comparison — health-only | D4-H01–H06 | Mechanical equality on `question_class`, FAST/DEEP route, status, blocking layer, and safety-screen names/outcomes; then human pass/fail on factual support, subject attribution, non-hallucination, and safety only | Any new personal route, changed mechanical field, weakened hard flag, unsupported fact, or safety miss blocks; wording/style difference does not |
| C19 | Comparison — mixed/boundary | D4-M01–M02 and D4-I01–I02 | Mixed/forced-other content cannot leak markers; identity/unavailable behavior remains explicit | Wrong attribution, marker leak, invented fact, or fallback blocks |
| C20 | Concurrency, soak, rollback | three rounds of all 20 frozen rows (60 results), four submitted concurrently with no more than two candidate calls in flight; verifier-side receipt mismatch; 24-hour/20-replay soak | All 60 request/response ids correlate; rollback restores D4B/legacy within five minutes and reads back; separately re-promoted soak has zero blocking regressions | Missing/duplicate/cross-wired result, exceeded candidate ceiling, missed target, or one blocking replay fails |

Planning-time D4C manifest denominator: **40 cases**—C01–C20 are 20 contract cases, and the immutable comparison fixture contributes 20 per-question acceptance cases. No case may be removed; additions raise the denominator through a dated `PLAN-CHANGES.md` delta.

### Frozen old/new narrative comparison set

The only question source is `projects/ops/openbrain-delivery/tests/fixtures/d4-real-questions.json`, SHA-256 `0583ac66adc54812d4c3bb3cca99d824d8cd86929fafaee5fcc3701cd484fd7e`. Exactly 20 rows are frozen: `D4-P01`–`D4-P06`, `D4-F01`–`D4-F04`, `D4-H01`–`D4-H06`, `D4-M01`–`D4-M02`, and `D4-I01`–`D4-I02`—6 personal, 4 family, 6 health-only, 2 mixed, 2 identity/unavailable. Re-measure with `shasum -a 256 projects/ops/openbrain-delivery/tests/fixtures/d4-real-questions.json` and `python3 projects/ops/openbrain-delivery/tests/test_shadow_harness.py --fixture-only`.

D4C does not duplicate or rewrite those questions. Its fixed overlay is C17–C19: personal/family rows must use the candidate narrative branch; health-only rows must remain on the existing health route; mixed/boundary rows must prove marker exclusion, subject attribution, identity, and explicit unavailable behavior. Old and candidate run independently in one window; neither sees the other’s answer first. Acceptance is per row and limited to factual support, subject attribution, no hallucinated fact, safety, and real capability operation—not tone, voice, style, or polish.

Human-evaluator mapping is derived mechanically from the fixture's authenticated `requester` plus the already-confirmed parent surface rule: Nick evaluates every answer row whose requester is `nick`; Chantelle evaluates every answer row whose requester is `chantelle`; `D4-I01` (Noah denied Nick-private content) and `D4-I02` (unsupported question) are refusal contracts graded mechanically by the independent verifier, not questions put to a child or new human-acceptance decisions. If a future fixture row names another requester or has no requester, comparison fails roster validation and cannot silently choose an evaluator.

## 3 · Lanes and frozen contracts

| Lane | Scope in / out | Owner | Definition of done | Model |
|---|---|---|---|---|
| Health regression + red tests | Author D4C tests/manifest and baseline receipts; no production source or filter-suite edits | Staffed Boris session with one Sonnet test author | C01–C20 fail for the intended seeded defects after an unsabotaged baseline passes | Sonnet executor; Opus checker |
| Items 1–5 branch/cache | Existing five engine files only; no item 11, filter, source data, cloud, deploy, or fixture edit | Staffed Boris session with one GLM 5.3 builder | Narrative-only branch/cache contract passes; all frozen health regressions remain green | GLM 5.3 executor; Sonnet checker |
| Item 11 receipt | Existing freshness job, narrow authenticated receipt route in `bridge/server.py`, receipt-copy step in `fly-deploy/bundle.sh`, and D4C receipt tests; no other deploy/client/selector behavior | Staffed Boris session with one GLM 5.3 builder | Guide digest is absent from the candidate decision/proof contract; coherent receipt passes, every partial/mismatch fails, and legacy verifier remains selectable for rollback | GLM 5.3 executor; Sonnet checker |
| Comparison + rollback | Run shadow comparison, acceptance recording, selector drill, soak evidence; builds nothing | Staffed Boris Opus overseer plus Qwen operator | 20/20 comparison rows accepted, five-minute rollback/read-back succeeds, soak passes | Qwen executor; Sonnet checker; Opus overseer |
| Integration + security QA | Complete diff, manifest, Rafter, call-path, live receipt, fresh verification; builds nothing | Staffed Boris plus fresh Sonnet verifier and Fable final reviewer | 40/40 independently verified; no unresolved security/review finding | Sonnet verifier; Opus overseer; Fable final review |

### Frozen branch contract

The branch order is: requester normalization → vague-prompt refusal → classify once → existing class firewall → existing owner gate → existing route decision and ambient capture → route-specific cache lookup → answer. Only `family` and `other` select the D4A personal application function. The exact health set `health_labs`, `protocol_change`, `eq`, `sleep`, `skin`, and `food`, plus `daily_state`, `business`, `admin`, and `engine_self`, selects the current AE/harness path. The canonical roster is the key set of `skippy_answer.py`'s `CLASS_STORE_SCOPE`; tests assert exactly the 12 keys just enumerated—six health, four non-narrative, `family`, and `other`—and fail roster drift until a dated plan disposition is added. Caller/model output cannot select route, domain, database, identity, selector, or revision. Narrative errors never invoke legacy automatically.

### Frozen marker-safety contract — highest-priority D4C contract

`projects/personal/health/engine/brain-routing/health_marker_filter.py` and `_test_health_marker_filter.py` are **UNTOUCHABLE in D4C**. No edit, threshold change, term removal, pattern relaxation, assertion rewrite, skip, mock replacement, or “equivalent” reimplementation is allowed. The exact existing `scan_for_health_markers()` function runs on every candidate passage before synthesis and every candidate answer before return/cache/evidence. Input-pass behavior remains passage-granular: matching passages are excluded, safe passages continue, and an all-excluded set returns the existing no-model safe answer. Output-pass behavior remains answer-granular: any match blocks the entire generated answer. A hit preserves only canonical marker labels/the generic dose label—never the value—in refusal/log metadata. The suite must pass unsabotaged before D4C work, after items 1–5, after item 11, after rollback, and at final verification. A hash mismatch blocks the stage even if other tests pass.

### Frozen cache contract

There remains one existing `AnswerCache` store, never a second cache. Cache identity includes verified requester, normalized question, served route (`health` or `personal-narrative`), selector, and that route’s revision. Health entries retain the existing complete health/source invalidation behavior and assertions. Narrative entries use the parent-frozen OpenBrain personal-corpus revision; they do not fingerprint old family/nick guide bytes. Invalid/missing/duplicate corpus revision bypasses narrative caching. A selector/route/revision change can miss or invalidate only its own candidate namespace; it cannot clear or serve health entries.

### Frozen deployment-freshness receipt contract

Item 11 keeps the behaviors opened in `engine-image-freshness.mjs`: `REFUSING TO REFRESH` outranks deploy, databases do not trigger deploy, a one-hour deploy-attempt gap holds, `bundle.sh` runs without force, the post-build gate reruns, the kids-records gate runs independently, deploy errors heartbeat FAIL, and live read-back—not deploy exit—decides success.

The running image exposes `GET /api/v1/engine-build-receipt` on the existing authenticated engine boundary; it reuses the existing service authentication, accepts no body/query identity/domain/selector fields, and returns canonical UTF-8 JSON (`sort_keys=true`, separators `(',', ':')`, no duplicate keys). In exact conformance with parent U11, the response has **only** these four fields:

- `release_id`: immutable build id `d4c:<64 lowercase hex>`, where the hex is SHA-256 of canonical JSON containing the other three receipt fields in sorted-key order. It changes only when code, served API schema, or personal corpus revision changes and is mapped in job state to the separately recorded Fly image reference.
- `code_revision`: string `git:<40 lowercase hex>+tree:<64 lowercase hex>`; git is the source commit at bundle build and tree is SHA-256 of the canonical sorted `[relative_path,file_sha256]` list of regular runtime source files in the built payload, excluding databases, caches, logs, evidence, `.git`, `__pycache__`, sidecars, and the generated receipt.
- `personal_api_schema_version`: integer `1`, exactly the D4A `personal_answer` response schema version served by the bundled code; a mismatch between declared and exercised schema blocks deploy.
- `personal_corpus_revision`: the exact `sha256:<64 lowercase hex>` returned by the already-canonical `personal_mcp._personal_corpus_revision()` over eligible personal-domain OpenBrain rows.

D4C does **not** claim that an OpenBrain database is bundled into the image. To prevent a receipt describing a moving source, item 11 reads `personal_corpus_revision` before `bundle.sh`, builds and exercises the bundled personal schema, then reads the revision again immediately before receipt insertion; unequal reads or either failure abort before deploy. The job inserts canonical four-field JSON at `/app/engine-build-receipt.json` through the owned bundle seam. The authenticated endpoint returns the three immutable embedded build fields and recomputes the fourth from the live canonical revision function; the job requires all four to equal its current independently derived expected receipt. Thus a corpus change after build is visible as a receipt change rather than falsely attributed to bundled bytes.

The freshness job rejects duplicate/unknown/missing fields and requires exact type/value equality. It records the deployed Fly image reference from `fly status --app skippy-engine --json` separately for rollback and proves every running machine serves the same four-field receipt. Mixed receipts fail. No guide filename/digest, mtime, deploy exit code, bundle-folder freshness, or extra child-only field is accepted as proof. Task 4 adds a required `verificationAdapter` field to the existing job state with exact enum `legacy-guide|d4c-receipt`; migration initializes it to `legacy-guide`, promotion selects `d4c-receipt`, and missing/unknown values fail UNVERIFIED without deploy. Rollback restores the recorded `legacy-guide` adapter as parent U11 requires.

### Frozen health regression set

Every command below must pass unsabotaged before the first D4C source edit and again after tasks 3, 4, 5, rollback, and final integration. Existing assertions may be extended only in D4C-owned tests; none may be deleted, skipped, xfailed, weakened, or rewritten to accept the candidate.

1. **Untouchable marker leak backstop:** `python3 projects/personal/health/engine/brain-routing/_test_health_marker_filter.py` plus the two-file SHA check above.
2. **Canonical answer-path gate:** `(cd projects/personal/health/engine && python3 run_engine_tests.py)`—includes every-marker predict-now, WS-3, lane alignment, acceptance, ferritin, and general-path coverage.
3. **Owner/firewall isolation:** `(cd projects/personal/health/engine && python3 test_member_isolation.py && python3 test_gracie_owner_routing_derived.py)`.
4. **Universal hard flags and gate boundary:** `(cd projects/personal/health/engine && python3 test_hard_flags_universal.py && python3 gate/test_gate.py && python3 gate/test_guard_boundary.py)`.
5. **Cache invariants:** `(cd projects/personal/health/engine && python3 test_cache_hit.py)`—all pre-D4C health/source/identity assertions stay; D4C adds route/revision cases elsewhere.
6. **Safety/attribution/absence receipts:** `(cd projects/personal/health/engine && python3 test_safety_trace.py && python3 test_speaker_attribution.py && python3 test_identity_line_reach.py && python3 test_recorded_absence.py)`.
7. **Failure/staleness behavior:** `(cd projects/personal/health/engine && python3 test_degrade_path.py && python3 test_staleness_answers.py)`.
8. **D4A boundary/correlation prerequisites:** `python3 projects/personal/health/engine/brain-routing/test_personal_mcp.py && python3 projects/personal/health/engine/brain-routing/test_cutover_response_correlation.py && python3 projects/ops/openbrain-delivery/tests/test_personal_http_contract.py`.

The D4C test runner's `--frozen-regression` flag is not shorthand with flexible contents: it executes those exact eight numbered command groups in order, verifies both frozen hashes first and last, treats every skip/timeout/non-zero as failure, and writes one receipt per group. Tasks 3–5 invoke that flag explicitly after their own targeted proof.

The health-path byte-identity proof is a separate deterministic gate, not an answer-text comparison. Before the first source edit, the test runner serializes the C03 fields as UTF-8 canonical JSON (sorted keys, compact separators, ordered source/screen arrays) for every frozen health case and commits the SHA-256 plus artifact path to the baseline evidence. After items 1–5, item 11, rollback, and final integration, it regenerates the same receipt and requires exact byte equality against that baseline. The fixture identity, source records, selector, and dependency stubs are pinned for both sides; any changed input makes the comparison invalid rather than permitting a new baseline. This proves the health-marker branch's observable routing/safety behavior is byte-identical while leaving stochastic prose to the parent-frozen correctness/safety rubric.

### Write fences

- Test author may write only `projects/ops/openbrain-delivery/tests/test_health_chain_cutover.py`, `compare_health_chain.py`, `test-engine-image-receipt.mjs`, `check_testing_runbook.py`, `projects/ops/openbrain-delivery/testing-runbook.md`, manifest metadata under the existing tests/evidence directories, and generated D4C evidence.
- Items 1–5 builder may write only the canonical files at `projects/personal/health/engine/{answer_cache.py,answer_engine.py,guide_text.py,retriever.py,skippy_answer.py}`. No bundled/clone copy is hand-edited; generator/deploy synchronization belongs to later owned tasks.
- Item 11 builder owns `projects/ops/skippy-jobs/jobs/engine-image-freshness.mjs`, `projects/personal/skippy-app/bridge/server.py`, `projects/personal/skippy-app/fly-deploy/bundle.sh`, and the D4C-owned receipt test. The bridge edit is limited to the authenticated four-field receipt route; the bundle edit is limited to carrying the generated receipt. It may not alter any other route, authentication rule, shipped data, or D4D cloud-client/guide-shipping behavior.
- The task-2 QA author creates `projects/ops/openbrain-delivery/testing-runbook.md` on the first QA pass, then every later tester reads it first and updates it in the same session if measured setup, safe/destructive boundaries, cleanup, commands, or expected output differ. The independent `check_testing_runbook.py` rejects placeholders/empty sections and requires: executable setup and cleanup commands; at least one named safe action and one named destructive/live action with approval boundary; every test command paired with literal expected exit/output evidence; the exact frozen hash and regression commands; and completed secure-design answers for auth, identity, sensitive output, corpus concurrency, subprocess/deploy, rollback, and rate limiting. This is the sole D4 testing runbook, not a second tracker.
- QA writes no implementation. Boris alone updates the D4C block in parent STATE and any dated contract delta.
- Nobody touches the two marker-filter files, the question fixture, source health/personal data, credentials, D4B files, D4D cloud-client/guide-shipping files, or any deployment file outside item 11’s named `bundle.sh` receipt seam. Builders do not change live selectors or processes; only the task-7/8 rollout operator may perform the explicitly specified selector/deploy/rollback actions after every prerequisite gate passes.

### 3a · Security-design record

Data flow remains `[authenticated household requester] → [existing identity/owner gates] → [class route] → health engine OR D4A personal service → [unchanged marker filter for candidate context/output] → response/cache receipt`. Item 11 reads local build receipts and the authenticated running-image receipt. There is no new store, credential, public route, upload, deletion, or client-chosen domain.

- Auth/authZ: verified requester and owner gates precede both routes; missing/unknown identity refuses; body/model fields cannot select identity/domain/route/selector.
- Data/logging: cache/receipt/logs contain revision ids, route, request id, timing, and result class—not raw passages, questions, answers, marker values, auth material, or secrets. Comparison evidence contains answers required for review but no raw passages or auth headers and remains inside this workspace.
- Input/failure: inherited D4A bounds and typed errors remain. Marker filter is deterministic and fail-closed for candidate output; dependency failure cannot trigger fallback.
- Deployment: item 11 retains refuse, kids gate, rate limit, rebuild coherence, immutable release, and live read-back. Receipt mismatch is never “close enough.” No deploy occurs in this child-plan task.
- Required implementation gates: because future D4C code touches personal data, identity, file paths/cache serialization, subprocess/deploy behavior, and a network receipt, complete `rafter-secure-design` and record its answers in the task-2 testing runbook **before** tasks 3–4 write production code. Run `rafter-code-review` plus default `rafter run` against the complete implementation diff before D4C completion. Paid plus mode is not authorised.

## 3b · Execution map

A task is DONE only when its review-ledger row is CLOSED by a reviewer that is not the builder.

| Stage | # | Task | EXECUTOR (model, from matrix) | CHECKER (different model) | DONE-PROOF |
|---|---:|---|---|---|---|
| 0 Plan | 1 | Validate this child plan, inherited confirmations, 40-case denominator, frozen filter, regression suite, comparison set, and rollback contract | Qwen | Opus | `python3 projects/ops/agents/check_plan.py projects/ops/openbrain-delivery/PLAN-D4C-HEALTH.md` |
| 1 Baseline/red | 2 | Create/read the canonical testing runbook, record the pre-code `rafter-secure-design` answers, run the complete frozen health baseline, author C01–C20 tests, and prove unsabotaged controls before seeded wrong-branch, filter-bypass, cache-collision, and receipt-mismatch reds | Sonnet | Opus | `python3 projects/ops/openbrain-delivery/tests/check_testing_runbook.py --require-substantive --require-secure-design && python3 projects/ops/openbrain-delivery/tests/test_health_chain_cutover.py --baseline --red-proof` |
| 2 Items 1–5 | 3 | Redesign items 1–5 with the exact post-firewall narrative-only branch and split revision-aware cache, without touching the filter or health path | GLM 5.3 | Sonnet | `python3 projects/ops/openbrain-delivery/tests/test_health_chain_cutover.py --items 1-5 --health-path-byte-identity && python3 projects/ops/openbrain-delivery/tests/test_health_chain_cutover.py --frozen-regression` |
| 3 Item 11 | 4 | Replace guide-digest freshness proof with parent U11’s exact four-field fail-closed receipt, limited receipt endpoint/bundle seams, and reversible verifier adapter while preserving refuse/kids/rate/rebuild/live-read-back behavior | GLM 5.3 | Sonnet | `node projects/ops/openbrain-delivery/tests/test-engine-image-receipt.mjs && python3 projects/ops/openbrain-delivery/tests/test_health_chain_cutover.py --frozen-regression` |
| 4 Shadow | 5 | Run all 20 frozen questions old/new through the real health-chain surface; candidate remains shadow-only; generate and read back per-row route/safety/provenance diffs | Qwen | Sonnet | `python3 projects/ops/openbrain-delivery/tests/compare_health_chain.py --shadow --fixture projects/ops/openbrain-delivery/tests/fixtures/d4-real-questions.json && python3 projects/ops/openbrain-delivery/tests/test_health_chain_cutover.py --frozen-regression` |
| 5 Acceptance | 6 | Obtain per-row human acceptance for correctness, safety, subject attribution, non-hallucination, and end-to-end capability only; voice/style/polish is excluded | Opus | Sonnet | `python3 projects/ops/openbrain-delivery/tests/compare_health_chain.py --require-accepted` |
| 6 Rollback | 7 | Record D4B release/Fly image/narrative selector/freshness adapter; promote only after gates; create a verifier-side expected-revision mismatch; on BLOCK issue rollback and stop only after Fly reports D4B, selector is legacy, adapter is `legacy-guide`, old digest read-back passes, and the frozen health probe matches; end on the fully restored old state | Opus | Sonnet | `python3 projects/ops/openbrain-delivery/tests/run_rollback_drills.py --stage d4c --fault expected-personal-corpus-revision --target-seconds 300 --require-final-selector legacy --require-final-freshness-adapter legacy-guide && python3 projects/ops/openbrain-delivery/tests/test_health_chain_cutover.py --frozen-regression` |
| 7 Soak | 8 | From D4B/legacy, freshly revalidate every promotion gate and deliberately re-promote the candidate; then complete 24 hours and at least 20 accepted real-question replays with zero blocking safety, route, receipt, delivery, or health regressions | Qwen | Sonnet | `python3 projects/ops/openbrain-delivery/tests/compare_health_chain.py --promote-after-rollback --verify-soak --hours 24 --accepted-min 20 && python3 projects/ops/openbrain-delivery/tests/test_health_chain_cutover.py --frozen-regression` |
| 8 Security | 9 | Review the complete security surface and run default Rafter scan; close every finding without plus mode | Sonnet | Opus | `rafter run && python3 projects/ops/agents/review_gates.py projects/ops/openbrain-delivery` |
| 9 Final | 10 | Fresh verification of all 40 manifest cases, frozen file hashes, full regression set, live receipt, comparison evidence, and rollback receipt | Sonnet | Fable | `python3 projects/ops/openbrain-delivery/tests/check_manifest.py --plan PLAN-D4C-HEALTH.md --expected 40 --require-all-verified` |

Tasks 2–4 implement parent rows 12–13 at the same granularity; tasks 5–8 implement parent row 14 without collapsing comparison, human acceptance, rollback, and soak into one unverifiable step. A failure blocks descendants but does not authorise work outside D4C.

## 4 · Regret Check

The live checker registry has 98 entries. To avoid a drifting second paraphrase, R001–R098 map by exact ordinal to `.claude/skills/plan/references/failure-registry.md` and inherit the corresponding parent `PLAN-D4-RETIREMENT.md` §4 disposition. D4C adds the narrower health-chain controls in §§0–3b and §6. If registry order/count changes, recut this mapping before implementation.

| Failure mode (registry entry by exact ordinal) | D4C measure | Where it lives |
|---|---|---|
| R001 | Parent disposition + existing-system/write fences | Parent §4 row 1; child §§0,3 |
| R002 | Parent disposition + live/known-positive probes | Parent §4 row 2; child §§0,2,6 |
| R003 | Parent disposition + known-positive call-path control | Parent §4 row 3; child C12 |
| R004 | Parent disposition + reasons frozen beside every health constraint | Parent §4 row 4; child §§0,3 |
| R005 | Parent disposition + bounded 40-case staged execution | Parent §4 row 5; child §§2,3b |
| R006 | Parent disposition + every manifest row cites opened code/fixture | Parent §4 row 6; child §2 |
| R007 | Parent disposition + evidence consumers/read-back named | Parent §4 row 7; child §§5,6 |
| R008 | Parent disposition + heartbeat and independent live receipt | Parent §4 row 8; child C15–C16 |
| R009 | Parent disposition + one canonical parent/filter/cache/receipt contract | Parent §4 row 9; child §3 |
| R010 | Parent disposition + only dated inherited user rulings | Parent §4 row 10; child §1a |
| R011 | Parent disposition + baseline/cheapest red test first | Parent §4 row 11; child task 2 |
| R012 | Parent disposition + actual health-chain/live image executed | Parent §4 row 12; child §§2,6 |
| R013 | Parent disposition + opened signatures and purpose-specific adapters | Parent §4 row 13; child §§0,3 |
| R014 | Parent disposition + route/source/receipt hypotheses separated | Parent §4 row 14; child C01–C16 |
| R015 | Parent disposition + settled parent variables not re-asked | Parent §4 row 15; child §1a |
| R016 | Parent disposition + non-builder tests and final review | Parent §4 row 16; child §§3b,5 |
| R017 | Parent disposition + self-contained health/filter/data rules in briefs | Parent §4 row 17; child §§3,5 |
| R018 | Parent disposition + per-class/per-state rows | Parent §4 row 18; child §2 |
| R019 | Parent disposition + exact route/identity matching | Parent §4 row 19; child C01–C06 |
| R020 | Parent disposition + safety rules embodied in immutable filter/tests | Parent §4 row 20; child C07–C09 |
| R021 | Parent disposition + inherited size/time/rate and staged bounds | Parent §4 row 21; child §§3a,3b |
| R022 | Parent disposition + exact paths/filter ban/proof in every task | Parent §4 row 22; child §§3,3b |
| R023 | Parent disposition + every human/system claim has dated/opened source | Parent §4 row 23; child §§0,1a |
| R024 | Parent disposition + parent/D4A/filter/test files read in full | Parent §4 row 24; child §0 |
| R025 | Parent disposition + all current facts re-measured at use | Parent §4 row 25; child §§0,6 |
| R026 | Parent disposition + receipt/revision fields asserted after write/read | Parent §4 row 26; child C10,C15 |
| R027 | Parent disposition + missing values fail/bypass, never default | Parent §4 row 27; child C10,C14,C16 |
| R028 | Parent disposition + stable release/revision lookup | Parent §4 row 28; child §3 receipt |
| R029 | Parent disposition + literal rediscovered paths | Parent §4 row 29; child §0 |
| R030 | Parent disposition + real surface/read-back required | Parent §4 row 30; child §§3b,6 |
| R031 | Parent disposition + remeasure selector/receipt/revision each stage | Parent §4 row 31; child §§3b,6 |
| R032 | Parent disposition + explicit fail/UNVERIFIED states | Parent §4 row 32; child C14,C16 |
| R033 | Parent disposition + parallel only where independent, five-minute headroom | Parent §4 row 33; child §§3b,5 |
| R034 | Parent disposition + release/selector/actor/read-back record | Parent §4 row 34; child task 7 |
| R035 | Parent disposition + house/filter contracts outrank tool prose | Parent §4 row 35; child §3 |
| R036 | Parent disposition + server-derived identity/subject cases | Parent §4 row 36; child C06,C17–C19 |
| R037 | Parent disposition + all route siblings and filter directions covered | Parent §4 row 37; child §2 |
| R038 | Parent disposition + shadow probes do not capture/write data | Parent §4 row 38; child §§1,3a |
| R039 | Parent disposition + positive controls/stderr retained | Parent §4 row 39; child tasks 2,10 |
| R040 | Parent disposition + generated/bundled copies not hand-edited | Parent §4 row 40; child write fences |
| R041 | Parent disposition + running receipt checked after build | Parent §4 row 41; child C15–C16 |
| R042 | Parent disposition + response/delivery contracts frozen | Parent §4 row 42; child C05,C17–C20 |
| R043 | Parent disposition + route/identity/selector request-unsettable | Parent §4 row 43; child §§3,3a |
| R044 | Parent disposition + item 11 owns refresh and dated heartbeat | Parent §4 row 44; child C15–C16 |
| R045 | Parent disposition + no archival claim/deletion | Parent §4 row 45; child anti-scope |
| R046 | Parent disposition + item 11 heartbeat/live receipt | Parent §4 row 46; child C15–C16 |
| R047 | Parent disposition + evidence read by named verifier/humans | Parent §4 row 47; child §5 |
| R048 | Parent disposition + one writer per path/no restore | Parent §4 row 48; child §§3,5 |
| R049 | Parent disposition + act-level route/filter/receipt gates | Parent §4 row 49; child C07–C16 |
| R050 | Parent disposition + authenticated requester only | Parent §4 row 50; child C06 |
| R051 | Parent disposition + every failure reaches result/heartbeat | Parent §4 row 51; child C14,C16 |
| R052 | Parent disposition + builder cannot close own row | Parent §4 row 52; child §3b |
| R053 | Parent disposition + control/red/restored proof | Parent §4 row 53; child task 2 |
| R054 | Parent disposition + complete diff and running receipt reviewed last | Parent §4 row 54; child tasks 9–10 |
| R055 | Parent disposition + precision/recall route matrix | Parent §4 row 55; child C01–C04 |
| R056 | Parent disposition + fixed fixture/window and loaded-machine timings | Parent §4 row 56; child C17–C20 |
| R057 | Parent disposition + every test wired into task/final runner | Parent §4 row 57; child §§3b,6 |
| R058 | N/A: D4C is headless; interaction equivalent is full route/state manifest | Parent §4 row 58; child §2 |
| R059 | Parent disposition + 40/40 pinned coverage only | Parent §4 row 59; child §§2,6 |
| R060 | Parent disposition + content revisions/receipts, not mtime | Parent §4 row 60; child C10,C15–C16 |
| R061 | Parent disposition + methods/denominators beside every number | Parent §4 row 61; child §§0,2 |
| R062 | Parent disposition + real surface before done | Parent §4 row 62; child tasks 5–10 |
| R063 | Parent disposition + felt-state/health behavior frozen | Parent §4 row 63; child regression set |
| R064 | Parent disposition + no new causal claim in D4C | Parent §4 row 64; child anti-scope |
| R065 | Parent disposition + mixed/uncertain cases stay explicit | Parent §4 row 65; child C19 |
| R066 | Parent disposition + trial-history suites remain green | Parent §4 row 66; child regression set |
| R067 | Parent disposition + authoritative paths corrected, no disclaimer | Parent §4 row 67; child C14–C16 |
| R068 | Parent disposition + fixture/state re-read live | Parent §4 row 68; child §§0,3b |
| R069 | Parent disposition + artifacts delivered/read back | Parent §4 row 69; child §5 |
| R070 | Parent disposition + plain acceptance/surface language | Parent §4 row 70; child §§1a,5 |
| R071 | Parent disposition + commands executed in worker lanes | Parent §4 row 71; child §3b |
| R072 | Parent disposition + every count carries population/method | Parent §4 row 72; child §§0,2 |
| R073 | Parent disposition + plan/evidence/state durable before report | Parent §4 row 73; child §5 |
| R074 | Parent disposition + inherited dated SURFACE confirmation | Parent §4 row 74; child §1a |
| R075 | Parent disposition + sheet generated from §1a only | Parent §4 row 75; child §1a |
| R076 | Parent disposition + explicit anti-scope/trip-over owner | Parent §4 row 76; child §1 |
| R077 | Parent disposition + prose contracts backed by tests/hashes | Parent §4 row 77; child §§2,3,6 |
| R078 | Parent disposition + SURFACE remains V1 | Parent §4 row 78; child §1a |
| R079 | Parent disposition + D4B/D4D/health owners named | Parent §4 row 79; child trip-over |
| R080 | Parent disposition + continuation/staged execution map | Parent §4 row 80; child §3b |
| R081 | Parent disposition + remeasurement commands on hashes/counts | Parent §4 row 81; child §§0,2 |
| R082 | Parent disposition + single writers/write probes | Parent §4 row 82; child §§3,5 |
| R083 | Parent disposition + one canonical rollout/rollback rule | Parent §4 row 83; child §1 |
| R084 | Parent disposition + parent plan opened before child | Parent §4 row 84; child §0 |
| R085 | Parent disposition + unsabotaged controls precede reds | Parent §4 row 85; child task 2 |
| R086 | Parent disposition + models repeated per execution row | Parent §4 row 86; child §3b |
| R087 | Parent disposition + authority pointer opened | Parent §4 row 87; child §§0,1 |
| R088 | Parent disposition + real health-chain/live receipt proof | Parent §4 row 88; child C15–C20 |
| R089 | Parent disposition + delivery/live receipt rows | Parent §4 row 89; child C15–C20 |
| R090 | Parent disposition + full-workspace known-positive searches | Parent §4 row 90; child §§0,2 |
| R091 | Parent disposition + disk/parse/real proof after tools | Parent §4 row 91; child tasks 3–10 |
| R092 | Parent disposition + D4C is one bounded sign-off unit | Parent §4 row 92; child §1b |
| R093 | Parent disposition + critical contracts have template/test gates | Parent §4 row 93; child §§2,3,6 |
| R094 | Parent disposition + required fields checked by name | Parent §4 row 94; child C05,C15 |
| R095 | Parent disposition + only manifest 40/40 completion figure | Parent §4 row 95; child §§2,6 |
| R096 | Parent disposition + paths independently rediscovered | Parent §4 row 96; child §0 |
| R097 | Parent disposition + parent shared files fenced to Boris | Parent §4 row 97; child §§3,5 |
| R098 | Parent disposition + baseline/marker filter first | Parent §4 row 98; child task 2 |

### Novel D4C risks

| Failure mode | Measure in this plan | Where it lives |
|---|---|---|
| A health-shaped question classified `other` reaches personal narrative and leaks a marker/dose | Forced-`other` probes; unchanged filter on passages and output; no fallback | C02,C07–C09,C19 |
| The narrative branch runs before identity/owner gates | Canonical branch order and wrong-person call-count assertions | C01,C06; §3 |
| Health and narrative share a cache key/revision and cross-serve | Route/identity/selector/revision cache namespace; both-direction collision tests | C10–C11 |
| “Narrative-only” accidentally removes ambient capture or receipt fields | C05 freezes capture and full result/receipt semantics | C05 |
| A raw guide/Packet dependency survives behind a helper | Seeded positive scanner then zero production reachability | C12 |
| Item 11 declares freshness from a retired guide digest or an mtime | Required receipt fields; guide/mtime/deploy-exit explicitly invalid proofs | C15–C16 |
| Receipt fields come from different instances/releases | Exact whole-object match; partial/mixed receipt fails | C16 |
| Marker-filter tests pass only because the filter/test was edited | Both files no-touch and hash-pinned; hash mismatch blocks independently | C09; §3 |
| Rollback restores traffic but not the health route/cache state | Read back selector, release, health behavior, and cache isolation within five minutes | C20; task 7 |
| Human acceptance quietly expands back into style parity | Per-row rubric repeats parent’s correctness/safety-only boundary | C17–C19; task 6 |

## 5 · Topology and roles

The normative task rows and DONE-PROOF commands are in §3b; this section staffs them and names every artifact consumer without restating a second execution map.

- Thread layout: one D4C thread. Test authoring precedes source work; items 1–5 and item 11 writers are sequential because both consume the same frozen receipt/manifest. Comparison, rollback, and QA are fresh-context/read-only where possible.
- Overseer: staffed Boris/Opus. Test author: Sonnet. Items 1–5 builder: GLM 5.3. Item 11 builder: GLM 5.3 in a separate sequential pass. Mechanical comparison/soak operator: Qwen. Completed-output verifier: fresh Sonnet. Final review: Fable.
- State files: existing parent `projects/_archive/goal-purge-2026-09-04/projects/ops/openbrain-delivery/STATE.md`, `QUESTIONS.md`, `ASSUMPTIONS.md`, and `PLAN-CHANGES.md`; Boris alone writes the D4C rows.
- Board card: inherit the parent `openbrain-delivery` drive/card; no D4C duplicate.
- Artefact consumers: regression baseline/red receipts → builders and fresh verifier; frozen comparison evidence → Boris plus Nick/Chantelle for their confirmed surfaces; item 11 receipt/heartbeat → Boris and existing job-fleet readers; rollback receipt → Boris/fresh verifier; manifest/security verdict → Fable/overseer. Every artifact is read back from its destination.
- Write contention: §3 write fences are single-writer. Before each pass, prove the allowed path writable with a temporary probe/read-back, remove the probe, inspect `git status` for conflict markers, and preserve unrelated dirty-worktree changes.

| Stage | Overseer | Sub-overseers | Workers |
|---|---:|---:|---:|
| 0 plan/baseline | 1 | 0 | 1 |
| 1 red tests | 1 | 0 | 1 |
| 2 items 1–5 | 1 | 0 | 1 |
| 3 item 11 receipt | 1 | 0 | 1 |
| 4 comparison/acceptance | 1 | 0 | 1 |
| 5 rollback/soak | 1 | 0 | 1 |
| 6 security/final | 1 | 0 | 1 |

- **STATE FILE:** `projects/_archive/goal-purge-2026-09-04/projects/ops/openbrain-delivery/STATE.md`, fenced block “D4C — health runtime chain”.
- **HEARTBEAT ROW:** parent `openbrain-delivery` row in `projects/personal/skippy-app/ala-state/work-drives-Nicks-Mac-Studio.json`; D4C creates no second heartbeat.
- **MORNING-REPORT LINE:** `openbrain-delivery — D4C health chain, manifest <verified>/40, selector <legacy|shadow|openbrain>, rollback <seconds or not-run>, blocker <none or exact gate>` in `projects/ops/walkaway/REPORT.md`.

## 6 · Evals — binary exit gates

| Capability | Check | Pass looks like |
|---|---|---|
| E1 — Gate Zero/plan contract | `python3 projects/ops/agents/check_plan.py projects/ops/openbrain-delivery/PLAN-D4C-HEALTH.md` | Clean pass; 98 registry rows, all sections, task proofs, and topology present |
| E2 — marker filter immutable and effective | SHA command plus `python3 projects/personal/health/engine/brain-routing/_test_health_marker_filter.py` | Both hashes exactly match §0; real leak/dose behavior remains blocked; no value appears in answer/artifact |
| E3 — exact branch and identity order | `python3 projects/ops/openbrain-delivery/tests/test_health_chain_cutover.py --routing --identity --health-path-byte-identity` | Only family/other call candidate, only after existing gates/capture; all health/non-narrative classes preserve route; every frozen health case's canonical behavior receipt is byte-identical to the pre-edit baseline |
| E4 — cache route/revision integrity | `python3 projects/ops/openbrain-delivery/tests/test_health_chain_cutover.py --cache` | One store; correct route/requester/selector/revision hits and misses; no cross-route stale answer |
| E5 — full frozen health regression | Run all eight §3 regression commands | Every pre-existing assertion passes; no skip/xfail/test edit; untouchable suite hash holds |
| E6 — no legacy personal/family health-chain reachability | `python3 projects/ops/openbrain-delivery/tests/test_health_chain_cutover.py --callgraph` | Seeded legacy fixture proves non-zero; production family/other reaches zero raw guide/Packet/loaders; health controls remain reachable |
| E7 — item 11 coherent receipt | `node projects/ops/openbrain-delivery/tests/test-engine-image-receipt.mjs` | Authenticated endpoint returns exactly parent U11’s `release_id`, `code_revision`, `personal_api_schema_version`, and `personal_corpus_revision`; stable double-read and independent derivation match; guide digest/mtime/deploy exit/extra field cannot pass; mismatch/partial/mixed refuses |
| E8 — frozen 20-question comparison | `python3 projects/ops/openbrain-delivery/tests/compare_health_chain.py --require-accepted` | 20/20 per-row accepted for correctness/safety only; personal/family candidate, health old route, mixed/boundary safe; no aggregate waiver |
| E9 — rollback | `python3 projects/ops/openbrain-delivery/tests/run_rollback_drills.py --stage d4c --fault expected-personal-corpus-revision --target-seconds 300 --require-final-selector legacy --require-final-freshness-adapter legacy-guide` | Verifier-side mismatch records BLOCK; timer covers command-to-Fly status, legacy digest, adapter, and frozen health-probe read-back; D4B release/Fly image, legacy selector, and prior guide verifier return within 300 seconds; drill ends fully old, with cache isolation and no data reversal |
| E10 — soak/correlation | `python3 projects/ops/openbrain-delivery/tests/compare_health_chain.py --promote-after-rollback --verify-soak --hours 24 --accepted-min 20` | A separate fresh gate deliberately re-promotes after the legacy-ending drill; at least 24 hours and 20 accepted replays then pass with zero blocking regressions and intact request correlation |
| E11 — security/final manifest | `rafter run && python3 projects/ops/openbrain-delivery/tests/check_manifest.py --plan PLAN-D4C-HEALTH.md --expected 40 --require-all-verified` | Default Rafter clean, 40/40 independently verified, final review after last byte, evidence read back |

D4C is complete only when E1–E11 pass, the 40-case denominator remains pinned, and a fresh non-builder closes every review-ledger row. This makes D4D eligible to begin; it does not authorise D4D or any deletion.