|
| 1 | +--- |
| 2 | +type: design |
| 3 | +title: "ADR-007 — The Harness Spine: decide → execute → verify as the agent's one pipeline" |
| 4 | +description: "Ports the engine Spine (ADR-002, spine.rs: immutable LatentView → priority-folded Deciders → discrete LatentDecision → Executor) into the harness, where the same logic had scattered (persona tags in an interceptor, hygiene inline in the agency tick, recall ad-hoc) — and adds the stage ADR-006 made law: a VERIFIER that re-checks the executor's own claim. One tiny fold (TurnView → Deciders → Decisions → Executors → Verifiers → SpineReceipts), three stock deciders realized (persona_tags post-turn, hygiene on the KAIROS tick, ranked-recall pre-turn), receipts on every decision. The gateway's post-turn persona shift and the agency tick's hygiene now run THROUGH the spine; a VERIFIED persona shift emits a live {persona, changed:true} SSE event so the UI chip updates mid-conversation. Additive: nothing changes unless a caller routes through run_spine." |
| 5 | +tags: [design, adr, spine, decide-execute, verify, harness, personality, memory, hygiene, recall, sse, receipts] |
| 6 | +timestamp: 2026-07-07T00:00:00Z |
| 7 | +resource: shannon-prime-lattice/papers/PPT-LAT-ADR-007-HARNESS-SPINE.md |
| 8 | +sp_status: "REALIZED (offline-GREEN): spine + persona/hygiene deciders wired (gateway post-turn, agency tick); recall decider built, wiring opt-in" |
| 9 | +sp_gate: "G-PK2-SPINE (offline) + G-PK2-SSE-V2 (persona-change event) — harness tests/" |
| 10 | +sp_commit: "opens on harness cf42f99 (wave 2); builds on ADR-002 (engine Spine) + ADR-006 (verify law)" |
| 11 | +sp_repro: "python tests/g_pk2_spine_offline.py" |
| 12 | +--- |
| 13 | + |
| 14 | +# ADR-007 — The Harness Spine |
| 15 | + |
| 16 | +**Status: REALIZED (offline-GREEN) for the persona + hygiene seams; recall decider built, wiring |
| 17 | +opt-in.** Builds on **ADR-002** (the engine Spine) and **ADR-006** (verify-before-accept). |
| 18 | + |
| 19 | +## 1. Context |
| 20 | + |
| 21 | +The engine's `spine.rs` proved the shape (G-SPINE-ONECONFIG, byte-for-byte with inline): an |
| 22 | +immutable **LatentView** folded through priority-ordered **Deciders** into a discrete |
| 23 | +**LatentDecision**, applied by an **Executor** the deciders cannot touch — a compiler-enforced |
| 24 | +boundary that collapsed a ~1500-line env-branch ladder. The harness, meanwhile, accreted the |
| 25 | +same decision logic in scattered forms: persona tags parsed in `PersonalityStateInterceptor`, |
| 26 | +registry hygiene inline in the agency tick, recall ad-hoc per call-site. Scattered decisions |
| 27 | +can't be receipted, prioritized, or verified uniformly. |
| 28 | + |
| 29 | +## 2. Decision — one tiny fold, plus the Verifier stage |
| 30 | + |
| 31 | +`harness/control/spine.py`: |
| 32 | + |
| 33 | + TurnView (frozen: phase pre|post|tick, user_text, reply) |
| 34 | + → Decider.decide(view) -> [Decision(kind, payload)] # pure, CANNOT side-effect |
| 35 | + → executors[kind](decision) -> result # the only side-effecting stage |
| 36 | + → verifiers[kind](decision, result) -> bool # ADR-006: check the claim |
| 37 | + → SpineReceipt(kind, decider, ok, verified, result, ms) # every decision auditable |
| 38 | + |
| 39 | +It is a fold, not a framework: ~150 lines, no registry, no inheritance tax. The **Verifier** is |
| 40 | +the stage the engine Spine doesn't have yet — the executor's success is re-checked against the |
| 41 | +world (re-read persona.md; re-run verify_registry), and a failed check is an honest |
| 42 | +`VERIFY_FAIL` receipt, never a silent lie. This is ADR-006's law made structural. |
| 43 | + |
| 44 | +## 3. The stock deciders (realized) |
| 45 | + |
| 46 | +- **persona_tags (post-turn, prio 30):** reply carries `[MOOD:]/[VOICE:]/[TRAIT:±]` → |
| 47 | + `persona_shift` decision → executor = the existing `apply_personality_tags` (PF-B3 — reused, |
| 48 | + not rebuilt) → verifier re-parses persona.md and confirms the tagged mood/voice actually |
| 49 | + landed. Wired into the gateway: after the streamed answer, a VERIFIED shift emits a final |
| 50 | + `{"persona": state, "changed": true}` SSE event — the UI chip updates mid-conversation. |
| 51 | +- **hygiene (tick, prio 40):** `verify_registry` says NEEDS COMPACTION → `compact_registry` |
| 52 | + decision → verifier re-runs the report and confirms clean. The agency tick now routes through |
| 53 | + `run_tick()` (receipts in the on_round stream) instead of inline calls. |
| 54 | +- **recall (pre-turn, prio 20, opt-in):** ranked token-overlap memory search |
| 55 | + (`search_memories_ranked`, new) over the user's message → `inject_recall` decision carrying |
| 56 | + the top facts. The executor is a marker (prompt assembly is the caller's); wiring into the |
| 57 | + gateway prompt is deliberately opt-in — the engine's L5 path stays authoritative when armed. |
| 58 | + |
| 59 | +## 4. Memory expansion riding this ADR |
| 60 | + |
| 61 | +`search_memories(query)` (ranked, scales past the `list_memories` dump) + `memory_stats()` |
| 62 | +(count / provenance mix / minted fraction). Tool tiering respects the banked ≤6-tools rule: |
| 63 | +the HOT chat set stays `[list, count, remember, forget]`; provenance/search/stats live in the |
| 64 | +OKFS extra tier (`load_tools` on demand). |
| 65 | + |
| 66 | +## 5. SSE additions riding this ADR |
| 67 | + |
| 68 | +- `{"hb": ts}` keep-alive every 5s while the agent computes (a long prefill no longer looks |
| 69 | + dead); pure-delta clients never see it. |
| 70 | +- `{"persona": state, "changed": true}` on a verified mid-conversation persona shift. |
| 71 | +- Console `index.html` now renders tool cards (`{tool}`), the personality chip (`{persona}`), |
| 72 | + and pulses on heartbeats — the operator can watch the organism think. |
| 73 | + |
| 74 | +## 6. Honest scope / next |
| 75 | + |
| 76 | +Persona + hygiene seams are spine-routed and gated offline; recall wiring is opt-in and ungated |
| 77 | +live (faithfulness interactions with the engine L5 path need their own gate before default-on). |
| 78 | +The engine Spine and the harness Spine are mirrors, not one implementation — unifying them |
| 79 | +(e.g. the harness posting decisions to an engine `/v1/spine` surface) is future work, as is |
| 80 | +promoting more seams (task-loop step policy, tool-set selection, NIGHTSHIFT admission) into |
| 81 | +deciders. The fold is deliberately boring; the value is receipts + the verify stage everywhere. |
0 commit comments