From 3aade62192727d3fb997dd227ad0ce47985cb37d Mon Sep 17 00:00:00 2001 From: Shay Date: Sun, 24 May 2026 16:27:27 -0700 Subject: [PATCH] =?UTF-8?q?docs(runtime):=20scope=20L10=20=E2=80=94=20runt?= =?UTF-8?q?ime=20model=20for=20forever-running=20CORE=20(#236)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Names the missing prerequisite that recognizer-storage v2 and substrate-liveness-audit v2 both flagged: the process shape in which the engine accumulates capability over its lifetime, survives reboot as recovery, and presents a narrow async HITL ratification entrypoint. Cross-reference discipline applied up-front (per feedback-adr-cross-reference-discipline memory entry — fourth iteration; this time grep BEFORE draft). Existing ADRs identified as load-bearing: ADR-0040 (telemetry sink, persistent audit trail), ADR-0041/0042 (operator surface + audit-tour), ADR-0055 (four-tier memory: T1 session vault → T4 ratified packs; explicitly names "what survives across all sessions and reboots"), ADR-0056/0080 (contemplation loop), ADR-0057 (proposal review machinery this scope must build on), ADR-0014 (vault promotion gate, currently dormant — L2 audit will verify), ADR-0027/0029/0033 (identity/ safety/ethics packs, currently startup-loaded). Current state honestly mapped: every entry is a one-shot CLI command via argparse in core/cli.py; ChatRuntime is per-invocation; no long-lived process exists. Four sub-questions framed: 1. Process shape — long-lived daemon vs. hybrid (state externalized + restored) vs. one-shot CLI with audit-trail-as-lifetime. 2. State partitioning — session-state (ephemeral) / engine-state (live, persistent across reboot) / substrate-state (cold, persistent). 3. Reboot recovery — what verifies, what reloads vs. rederives, what records. 4. HITL async entrypoint — queue shape, backpressure, operator interaction model. Cross-references shelved project-engine-identity-candidate (DNA- analog EngineIdentity) as potential primitive if sub-question 3 demands cross-reboot identity verification. Does NOT un-shelve it; flags trigger. Explicit rejections: database persistence (per ADR-0055 north-star); network primary entrypoint (per user-circumstances memory entry, always-on-internet unsafe to assume); multi-tenant; re-architecting ChatRuntime. Constraints inherited from CLAUDE.md: deterministic replay, no hidden state, HITL is narrow entrypoint, reboot is recovery not control flow, append-only artifacts stay append-only, no drift repair / hot-path normalization. This is a scope, not a decision. Spike/ADR decides; audit findings (L4-L9) inform. --- docs/decisions/L10-runtime-model-scope.md | 380 ++++++++++++++++++++++ 1 file changed, 380 insertions(+) create mode 100644 docs/decisions/L10-runtime-model-scope.md diff --git a/docs/decisions/L10-runtime-model-scope.md b/docs/decisions/L10-runtime-model-scope.md new file mode 100644 index 00000000..a4440ea5 --- /dev/null +++ b/docs/decisions/L10-runtime-model-scope.md @@ -0,0 +1,380 @@ +# Scope: L10 — Runtime Model (Process Lifecycle for Forever-Running CORE) + +**Status:** Draft v1 / scope-only (not a decision yet — prerequisite for one) +**Date:** 2026-05-24 +**Author:** CORE agents +**Anchor:** [thesis-decoding-not-generating](../../../.claude/projects/-Users-kaizenpro-Projects-core/memory/thesis-decoding-not-generating.md) (memory) +**Discipline:** [feedback-adr-cross-reference-discipline](../../../.claude/projects/-Users-kaizenpro-Projects-core/memory/feedback-adr-cross-reference-discipline.md) (memory) +**Companions:** [substrate-liveness-audit-scope](./substrate-liveness-audit-scope.md), [recognizer-storage-scope](./recognizer-storage-scope.md), [teaching-derived-recognition-scope](./teaching-derived-recognition-scope.md) +**Shelved-but-relevant:** [project-engine-identity-candidate](../../../.claude/projects/-Users-kaizenpro-Projects-core/memory/project-engine-identity-candidate.md) (memory) — DNA-analog `EngineIdentity` concept; may become load-bearing under this scope's decisions + +--- + +## Why this document exists + +CORE's recent scope work (recognizer-storage v2; substrate-liveness-audit +v2) repeatedly named a load-bearing prerequisite that has no scope or +ADR of its own: **the runtime model**. Several decisions are gated on +it: + +- The recognizer-storage scope explicitly states: "this scope is gated + on the runtime-model scope existing and committing to forever-running." +- The substrate-liveness-audit scope names L10 (runtime model) and L11 + (forever-running engine) as not-audit-targets because they have no + design yet — the audit's job is to surface need for them. +- The forever-running engine vision ("listen, comprehend, recall, think, + articulate, learn from reviewed correction, replay deterministically + — with capability compounding across turns and surviving reboot as + recovery, not as control flow") is the destination CORE is being built + toward, but the *process shape* in which that vision is realized is + unspecified. + +CORE today is session-bounded: every `core` CLI invocation builds a +fresh `ChatRuntime`, packs are loaded fresh, the engine has no +long-lived process. The thesis demands the engine *accumulate +capability over its lifetime*; the current process shape doesn't have +a lifetime in any meaningful sense. + +This scope defines the question. The answer belongs to the ADR that +follows, and to the substrate-liveness-audit findings that will +inform what's actually load-bearing. + +--- + +## Cross-reference audit (applying the discipline up front) + +Per [[feedback-adr-cross-reference-discipline]], the runtime-model +question must be drafted *against* the existing ADRs and code that +already touch lifecycle, persistence, and process shape — not in a +vacuum. + +### Existing ADRs touching lifecycle / persistence / process shape + +| ADR | Subject | Relevance | +|---|---|---| +| ADR-0040 | Telemetry sink (JSONL) | Persistent turn-event audit trail; survives across sessions; load-bearing for any audit-based "what happened" recovery. | +| ADR-0041 | CLI verdicts + fan-out | Operator readout surface; relevant to HITL entry shape. | +| ADR-0042 | Audit-tour demo | Four-scene reproducibility tour; demonstrates that telemetry IS the cross-session record. | +| ADR-0055 | Inter-session memory | **Most directly relevant.** Defines four-tier memory: T1 session vault (ephemeral-ish), T2 turn-event JSONL (audit trail, persistent), T3 reviewed teaching corpus (persistent, append-only), T4 ratified packs (long-term substrate). Explicitly names "what survives across all sessions and reboots." | +| ADR-0056 / ADR-0080 | Contemplation loop | Async-feeling work (enriching discovery candidates) — needs a process model to know when/where it runs. | +| ADR-0057 | Teaching-chain proposal review | Append-only proposal log; HITL review surface; the existing HITL machinery this scope must build on. | +| ADR-0014 | Train/learning loop (`VaultPromotionPolicy`) | Promotion gate, currently dormant; L2 audit will verify. Live promotion is part of "live mode." | +| ADR-0027 | Identity packs | Loaded at startup; mutation = restart today. Persistent identity continuity is open. | +| ADR-0029 | Safety packs | Same — startup-loaded, fail-closed; mutation = restart. | +| ADR-0033 | Ethics packs | Same shape. | + +### Existing code shape (session-bounded reality today) + +- **All entrypoints are `argparse`-based CLI commands in `core/cli.py`.** + `cmd_chat`, `cmd_test`, `cmd_check`, `cmd_trace`, `cmd_oov`, + `cmd_capability_*` (many), `cmd_pack_*`, `cmd_teaching_*`. Every + command is one-shot; the process exits when the command returns. +- **No `cmd_serve` / `cmd_daemon` / long-lived process exists.** There + is no current "forever" entrypoint. +- **`ChatRuntime` (`chat/runtime.py:418`)** is per-invocation. State + on it (manifold, session thread, contemplation state, recognizer + registry) does not survive process exit. +- **Persistent state today:** vault store (on-disk, reloaded each + invocation), teaching corpus (append-only JSONL on disk), telemetry + sink (JSONL on disk, ADR-0040), packs (on-disk with manifests), + proposal log (when written, append-only, ADR-0057). +- **Ephemeral state today:** ChatRuntime instance, field manifold, + session_thread context, contemplation working state, recognizer + registry (no persistence layer yet), HITL queue (no in-memory + representation yet). +- **HITL today** is operator-runs-CLI-commands. There is no async + queue the operator reviews while the engine continues running — + because the engine doesn't continue running. + +### Existing HITL machinery this scope must build on + +Per [[feedback-adr-cross-reference-discipline]] and the recognizer- +storage v2 self-review (which previously missed this): the HITL path +is *not* greenfield. ADR-0057 establishes the shape: + +- **`teaching/review.py`** — `ReviewOutcome` enum, `review_correction()` +- **`teaching/store.py`** — `PackMutationProposal`, `TeachingStore`, + append-only proposal log discipline +- **Automated gate:** replay-equivalence (ADR-0057's load-bearing + innovation) +- **Operator review surface:** today, CLI commands (`cmd_teaching_*`) +- **Append-only proposal log:** persistent across sessions + +L10 must reuse this machinery; the *new* concern is making it +asynchronous (operator reviews while engine runs) rather than +synchronous (operator review is a CLI command between engine +invocations). + +--- + +## The runtime-model question + +> **What process shape allows CORE to accumulate capability over its +> lifetime, survive reboot as recovery rather than as control flow, +> and present a narrow async HITL ratification entrypoint that is +> never bypassed and never required for runtime continuation?** + +Four sub-questions, each load-bearing: + +### Sub-question 1 — Process shape + +Three candidates, evaluated against current state: + +- **A. Long-lived daemon (`cmd_serve`).** One process; CLI commands + become clients of the daemon via local IPC. Most thesis-aligned + (engine has a lifetime). Largest delta from today's code shape; + requires concurrency model decisions, signal handling, supervision. +- **B. Hybrid (engine state externalized; CLI commands restore it).** + Engine state serialized to disk on every "logical action" boundary; + any CLI invocation can restore the latest state and continue. No + long-lived process needed; lifetime is the lifetime of the + serialized state on disk. Smaller code delta; serialization + discipline becomes load-bearing. +- **C. Continue with one-shot CLI; teach the audit/recovery layer + to be the lifetime.** Every invocation is a fresh process, but + every turn appends to a deterministic audit trail (ADR-0040 + + ADR-0055 T2) from which the *next* invocation reconstructs + capability. The audit trail IS the engine's lifetime. Smallest + delta; pushes the cost of "always on" into "always rebuild from + audit." + +Honest assessment of trade-offs is the spike/ADR's job, not the +scope's. Scope names the three candidates. + +### Sub-question 2 — State partitioning + +Three state classes the runtime-model must distinguish: + +- **Session-state (ephemeral, per-turn-window):** anaphora context, + current intent, immediate field excitation. May be lost on reboot + without architectural concern. +- **Engine-state (live, persistent across reboot):** the recognizer + registry, the contemplation working set, the HITL ratification + queue. *Expensive to rebuild from primitives;* MUST persist; reboot + reloads, does not re-derive. +- **Substrate-state (cold, persistent across reboot):** ratified packs, + ratified teaching corpus, vault store, telemetry JSONL, proposal + log. Already on disk today; the discipline question is when each + is updated and how reboot validates consistency. + +The scope's commitment is to **naming the three classes**; the ADR +decides what concrete state objects fall in which class. + +### Sub-question 3 — Reboot recovery + +Three questions reboot recovery must answer: + +- **What does reboot verify?** Pack manifest checksums (already do); + vault integrity (does); reviewed corpus consistency (does); engine- + state integrity (does NOT today — engine state doesn't survive). If + any verification fails, what happens? (Refuse to start, fall back, + surface to HITL?) +- **What does reboot reload vs. rederive?** Substrate-state reloads; + engine-state reloads if Process Shape A or B, or rederives from + audit if C; session-state is always rederived (it's per-turn). +- **What does reboot record?** A `reboot_event` analog of `TurnEvent`, + written to the audit trail, that lets future audit reconstruct the + fact that this engine instance lost and regained its lifetime here. + +The shelved [[project-engine-identity-candidate]] (`EngineIdentity` +content-derived hash) is one candidate mechanism for verifying engine +identity continuity across reboot — explicitly NOT committed by this +scope; flagged here so the ADR knows the candidate exists. + +### Sub-question 4 — HITL async entrypoint + +Today: operator runs CLI commands. There is no async queue. ADR-0057 +establishes the proposal-log shape but the operator interacts with it +through `cmd_teaching_*` commands. + +For forever-running, the HITL queue is async by definition: + +- **What is the queue's persistent representation?** Likely an + extension of the ADR-0057 append-only proposal log, possibly with a + "review state" axis (pending / under-review / accepted / rejected / + expired). +- **How does the operator interact with it?** Continued CLI commands + (Process Shape A/B/C compatible) vs. a TUI / web surface (larger + delta; out of scope for this ADR most likely). +- **What does the engine do while a proposal is pending HITL?** + Continue serving turns normally; the proposal is not blocking. This + matches the [[feedback-adr-cross-reference-discipline]] commitment + ("HITL is the narrow entrypoint, never bypassed, never required for + runtime continuation"). +- **How are proposal queues bounded?** Already named in recognizer- + storage v2 as a load-bearing constraint: backpressure (queue cap? + rate limit? operator alert?). The drop-off sibling ADR will specify + for deprecation; this scope must specify the *generic* shape that + drop-off and discovery-promotion and pack-mutation all share. + +--- + +## Constraints (non-negotiable) + +From CLAUDE.md and the existing thesis: + +1. **Deterministic replay.** Whatever the runtime model, given the + same teaching corpus + same input stream + same ratified substrate, + the engine must produce the same turn outputs and the same + trace_hashes. Process shape MUST NOT introduce non-determinism + (no wall-clock timestamps in deterministic payloads, no parallelism + without explicit ordering, no race-condition surface in the turn + loop). +2. **No hidden state.** Engine-state that persists across reboot MUST + be auditable: serialized in a human-and-machine-readable form, + checksummable, reproducible from the audit trail when possible. +3. **HITL is the narrow entrypoint.** No autonomous mutation of + ratified state. No path that lets the engine modify packs, + teaching corpus, or recognizer registry without operator + ratification. The forever-running engine's autonomy ends at + "propose"; ratification is always operator. +4. **Reboot is recovery, not control flow.** No CLI command, no test, + no operator action should require a reboot. Reboot is a hardware- + event analog; the engine survives it but does not depend on it. +5. **Existing append-only artifacts stay append-only.** Telemetry + JSONL, teaching corpus, proposal log — these are audit substrate + and must remain append-only across this scope's decisions. +6. **No drift repair, no hot-path normalization in the new code.** + Per CLAUDE.md normalization rules — runtime-model code is a + forbidden site for these patterns. + +--- + +## What this scope explicitly rejects + +- **A runtime-model that requires re-architecting `ChatRuntime`.** + The session-bounded `ChatRuntime` is the unit of work; whatever + shape the runtime model takes, `ChatRuntime` should remain + recognizable. +- **Database persistence for engine state.** Per ADR-0055 north-star: + "not in a database/embedding store." Engine state persists as files + (JSONL, pack manifest, vault store), not in a DBMS. +- **Network surface as a primary entrypoint.** This scope assumes + local-only operation (the user's circumstances make + always-on-internet unsafe to assume; per [[user-circumstances]]). + A network surface may come later but is not in scope. +- **Multi-tenant or multi-instance concerns.** Single engine instance + on a single machine. Sharing substrate across instances is a + separate scope (or a feature of [[project-engine-identity-candidate]] + if it ever un-shelves). + +--- + +## What this scope does NOT commit + +- **Process Shape A vs. B vs. C.** Spike/ADR decides. The audit (L4-L9 + findings, especially L7/L8) will inform which is least disruptive. +- **HITL surface beyond CLI.** A TUI or web surface may eventually + exist; this scope doesn't decide. +- **EngineIdentity adoption.** Shelved candidate; ADR may un-shelve + it if reboot-recovery sub-question demands it. +- **Concurrency model.** If Shape A wins, the daemon's concurrency + model (threads? async? per-turn process?) is an implementation + detail of the ADR, not the scope. +- **Specific persistence format for engine-state.** JSONL extension? + Custom binary? Pack-style? Implementation detail. +- **Migration path from current session-bounded shape.** ADR + specifies; scope notes that migration MUST be incremental (no big- + bang switchover that breaks `core chat`). + +--- + +## Determinism requirements (non-negotiable) + +The runtime model must preserve: + +1. **Byte-identical replay.** Same substrate + same input stream ⇒ + same turn outputs. Process shape MUST NOT introduce wall-clock, + PID, or other process-bound entropy into deterministic payloads. +2. **Reboot-equivalent state.** State after `(boot, run N turns, + reboot, reload)` is byte-identical to state after `(boot, run N + turns)` minus process-memory artifacts. (Reboot loses + session-state; engine-state and substrate-state are restored.) +3. **HITL ratification trace.** Every ratification produces an + append-only log entry with deterministic content; the log is the + audit trail for engine-state mutations. + +--- + +## Risks the spike / first ADR must surface + +- **Shape-A concurrency complexity.** A long-lived daemon introduces + signal handling, supervision, possibly inter-process concurrency. + CLAUDE.md's "Do not add hidden background execution" is at risk; + daemon design must make all concurrency explicit and auditable. +- **Shape-B serialization correctness.** Every engine-state object + must round-trip serialization byte-identically. One drifted + serializer breaks reboot recovery silently. +- **Shape-C rebuild cost.** If the audit trail grows to N turns, + rebuilding capability on every CLI invocation is O(N). May be fine + for small N, untenable for large. +- **HITL queue starvation.** If the operator goes offline for an + extended period, proposals accumulate. The recognizer-storage v2 + scope flagged this as load-bearing for drop-off; it's load-bearing + for every proposal kind. The ADR must specify backpressure + generically. +- **Pack-mutation during running engine.** If Shape A or B is chosen, + a ratified pack mutation while the engine is running raises + questions: hot-reload? Refuse-and-restart? Queue-until-quiescent? + Each option has different operator-experience implications. +- **Audit-trail compaction.** If telemetry JSONL grows unbounded, + reboot recovery (under Shape C) becomes slower over time. Compaction + / snapshotting is the natural answer but introduces a new mutation + axis on append-only state. ADR specifies or defers. +- **State-class boundary mistakes.** Putting engine-state in + session-state's bucket loses learning on reboot; putting session- + state in engine-state's bucket bloats persistence and breaks + determinism. The state-partitioning sub-question is high-leverage. + +--- + +## Open questions for the audit and follow-up scopes to inform + +- **What does the substrate-liveness audit (L4-L9) find about state + that wants to be persistent but currently isn't?** Each closure gap + the audit surfaces is potential engine-state for this scope to + classify. Specifically: + - L4 (Recognition) — recognizer registry persistence (already + scoped in recognizer-storage; cross-references here). + - L7 (Teaching loop) — proposal log liveness; HITL queue persistence. + - L8 (Inter-session memory + contemplation) — Tier 1/2/3 transitions; + contemplation working set. +- **Should the runtime-model ADR un-shelve `EngineIdentity`?** If + Sub-question 3 (reboot recovery) commits to verifying engine + identity continuity across reboot, the shelved candidate likely + becomes the right primitive. Trigger: sub-question 3 commits to + cross-reboot identity verification. +- **Does Process Shape A require a new top-level package + (`core/server/` or `core/daemon/`)?** Implementation-detail + question, but if yes, the substrate-liveness audit will need to + add a layer (L10b? a daemon layer?) to its map. +- **How does the runtime model interact with the audit's "live mode" + framing?** The substrate-liveness-audit scope frames "live mode" as + the destination state; the runtime model is the mechanism. They + must be drafted together as the ADR cluster lands. + +--- + +## Summary + +L10 — the runtime model — is the missing prerequisite for forever- +running CORE. Several recent scopes (recognizer-storage, +substrate-liveness-audit) flagged it as gated work without it +existing. + +This scope frames the question against four sub-questions: process +shape (daemon / hybrid / one-shot-with-replay), state partitioning +(session / engine / substrate), reboot recovery (verify what, reload +vs. rederive, record what), and HITL async entrypoint (queue shape ++ backpressure). It explicitly cross-references the ADR-0040/0041/ +0042/0055/0056/0057 cluster that already implements parts of the +answer, and the recognizer-storage scope that depends on this scope's +decisions. + +It rejects database persistence, network primary entrypoints, +multi-tenant concerns, and re-architecting `ChatRuntime`. It commits +no specific shape; the spike/ADR decides, informed by audit findings. + +The scope's commitment is to **the question framed against existing +machinery**. Answers belong to the spike and the ADR that follows. +Audit findings (L4-L9) refine the question over time.