docs(assessment): Phase 3 — component descent; the correction chain continues into code

Eight component cards in 20-component-cards/: the four zero-subsystem zones
(comprehend-organ, determine-phase, realize-phase, sensorium-falsification)
plus always-on-process, derivation-organs, surface-selection,
attention-allocation. Plus 05-phase3-findings.md and correction banners on
the M6 and M4 layer cards.

CORRECTIONS (C-1..C-5):
- THREE more map live-serving labels demoted to live-internal:
  comprehend-organ (a MATH SETUP ROUTER, not chat comprehension — imported
  by neither serving entrypoint), determine-phase and realize-phase (both
  behind accrue_realized_knowledge=False / idle flags; NO default-config
  serving turn touches any of the three).
- Phase 2's M6 card overstated ephemerality: Shape B+ persistence exists
  (persist_session_state, daemon-forced, "restored bit-exactly").
- Phase 2's M4 card understated the resolver: surface_resolution.py IS a
  declared-precedence resolver for the pipeline seam; only the upstream
  composer arms remain ordered branches. Third Door refines to "extend the
  existing pattern upstream."
- 34-vs-18 RESOLVED: 18 resolve_promotable_* organs existed AT the ADR-0252
  ratification commit; "34" counted modules (~32-33). No consolidation has
  occurred; the governing ADR's headline number has no stated basis.
- The 2026-07-25 verification doc's claim that accrual "is enabled by the
  production L10 process" is contradicted: CONTINUOUS_LIFE_CONFIG_FLAGS is
  exactly {persist_session_state, consolidate_determinations,
  strict_identity_continuity}.

NEW FINDINGS (F-6..F-10):
- F-6 THE CONTINUOUS LIFE MAY CONSOLIDATE AN EMPTY SET: the daemon forces
  the consolidator ON but not the accruer, and realize_comprehension — the
  only turn-path writer of realized facts — sits behind the accrual flag.
  The two halves of the lived learning loop are gated by different flags
  and only one is forced. Undocumented either way.
- F-7 ADR-0008's Allocation Physics LANDED, mutated, ungoverned: curvature
  kernel -> salience adapter -> attention threshold plan -> candidate
  intersection, with budget feedback making attention SELF-NARROWING
  across a walk. InhibitionMask is decoration. top_k=16/threshold=0.3 have
  no recorded derivation. CR-1 closes with a one-page ADR.
- F-8 two load-bearing naming traps (comprehend-organ; realize vs realizer).
- F-9 REALIZE is sound; its ceiling is the reader that feeds it (the #138
  fabrication locus — measured/pinned/held, recorded not re-discovered).
- F-10 _accrue_in_turn swallows exceptions into a no-op with no telemetry.

Phase 4 seed list consolidated: 8 hindrance candidates, 10 gap candidates,
each with its deciding authority. Method note recorded: three phases of
corrections, and nothing in the chain was caught by re-reading documents.
This commit is contained in:
Shay 2026-07-27 15:57:36 -07:00
parent 36cb29a693
commit 901f028f32
11 changed files with 363 additions and 0 deletions

View file

@ -0,0 +1,68 @@
# Phase 3 — Findings, Corrections, and the Phase 4 Handoff
**Executor:** Fable 5, 2026-07-27. **Verified against:** `forgejo/main` @ `8927c563`.
**Deliverable:** eight component cards in `20-component-cards/` — the four ⚑ zero-subsystem zones (`comprehend-organ`, `determine-phase`, `realize-phase`, `sensorium-falsification`) plus `always-on-process`, `derivation-organs`, `surface-selection`, `attention-allocation`.
The assessment's correction chain continued into its third phase, in the same direction every time: **documents (including this assessment's own earlier phases) overstate or understate; code decides.** Phase 2 corrected Phase 0; Phase 3 corrects Phase 2 twice and the system map three more times.
---
## 1. Corrections
**C-1 — Three map `live-serving` labels demoted to `live-internal`.** `comprehend-organ` (`core/comprehension_attempt/` — imported by neither serving entrypoint; its consumers are the flag-gated ask path, proposal review, and eval lanes), `determine-phase`, and `realize-phase` (both reachable only through `_accrue_in_turn` / `idle_tick`, gated by flags that default False). **No default-config serving turn touches any of the three.** The map called all three live-serving; the serving path they were presumed to sit on runs through `proof_chain`/`curriculum_surface`/the realizer instead.
**C-2 — Phase 2's M6 card overstated ephemerality.** "T1 vault and field discarded on exit by design" is the *default-config* posture. Under the daemon, `persist_session_state=True` activates **Shape B+** persistence ("restored bit-exactly", `chat/always_on.py:9`; sites at `chat/runtime.py:893952`). The residency mechanism exists, is opt-in, and is daemon-forced; what remains open is its exact coverage and horizon proof. Banner added to the M6 card.
**C-3 — Phase 2's M4 card understated the resolver.** `core/cognition/surface_resolution.py` (494 lines) *is* a declared-precedence resolver for the pipeline seam (served-bytes-wins base selection, canonical-first truth path, abstention, hedge admissibility, substrate folds). The accretion concern survives only for the upstream composer arms in `chat/runtime.py`. The Third-Door candidate refines from "create a resolver" to "extend the existing resolver's pattern upstream." Banner added to the M4 card.
**C-4 — The 34-vs-18 organ discrepancy is resolved: basis mismatch, not paydown.** At the ADR-0252 ratification commit itself (`1ccef491`) the tree already had exactly **18** `resolve_promotable_*` entry organs across 33 tree entries. "34" plausibly counted modules (~3233 including support modules), never entry organs. Consequences: no consolidation has occurred since ratification, and the governing ADR's headline number has no stated basis — a one-sentence amendment fixes it.
**C-5 — A prior verification document is contradicted at this SHA.** `architecture-assessment-verification-2026-07-25.md` §2 claims `accrue_realized_knowledge` "is enabled by the production L10 process." `CONTINUOUS_LIFE_CONFIG_FLAGS` is exactly `{persist_session_state, consolidate_determinations, strict_identity_continuity}` — accrual is **not** in it.
---
## 2. New findings
**F-6 — The continuous life may consolidate an empty set.** The daemon forces the *consolidator* on (`consolidate_determinations`) but not the *accruer* (`accrue_realized_knowledge`) — and `realize_comprehension`, the only turn-path writer of realized facts, sits behind the accrual flag. As coded, the always-on life's Step-D learning loop may have nothing to work on unless facts are seeded some other way. Either the flag set is incomplete or the dormancy is intended; **neither reading is documented.** This is the sharpest single new finding of Phase 3: the two halves of the lived learning loop are gated by different flags and only one is forced.
**F-7 — The allocation layer landed, mutated, without governance.** ADR-0008's Allocation Physics is live in composed form: physics curvature kernel → generation-facing `SalienceOperator``AttentionOperator` scalar-threshold plan → candidate intersection in the walk, with the salience `budget` fed back so attention *self-narrows* across a walk (`stream.py:637`). `InhibitionMask` is decoration (imported by `__init__` only, never constructed on any path). The tuned constants (`top_k=16`, `threshold=0.3`) have no recorded derivation. CR-1's ruling question is now precise: own the flag, the two constants, the feedback loop, and the mask's disposition — a one-page ADR.
**F-8 — Two naming traps are load-bearing.** `comprehend-organ` is a *math setup router*, not the chat comprehension organ (that is `generate/meaning_graph/reader.py` — the two-grammars reader, 19 constructions, fabricating on 22, measured/pinned/held). `generate/realize/` (knowledge realization) vs `generate/realizer.py` (surface realization) are unrelated mechanisms with confusable names. Both traps would misdirect a grep-first investigation; both cards carry permanent disambiguation.
**F-9 — REALIZE is sound; its ceiling is its feeder.** The realize phase holds whatever the reader hands it, at honest SPECULATIVE standing, with full derivation provenance. The truth-defect class is entirely upstream in the reading — consistent with fix-upstream doctrine and with holding the #138 fixes for a serving-truth ADR. A defensive option for that ADR: refuse to *hold* a reading whose construction lies outside the reader's verified inventory, converting inventory truth into a mechanical gate at the holding boundary.
**F-10 — A silent-failure pinhole in a typed layer.** `_accrue_in_turn` wraps the reader/DETERMINE/REALIZE chain in a broad guard that converts any exception into a no-op accrual with no telemetry. Honest as a backstop; invisible as a failure signal.
---
## 3. Phase 4 seed list (consolidated from Phases 23)
**Hindrance-audit candidates (`31-hindrance-audit.md`):**
1. Wilson/replay independence in license counting — possible `wrong-solution` in the counting basis; 21/25 bands affected (Phase 2).
2. `DriveGradientMap` constructed-never-read; `InhibitionMask` exported-never-constructed — deletion candidates (mastery step 2).
3. The empty-string refusal at the public `str` boundary — truth constructed, then discarded (M4/surface-selection).
4. Composer-arm precedence: extend `surface_resolution`'s declared-precedence pattern upstream (refined Third Door).
5. The F-6 flag-set incoherence (consolidator without accruer).
6. Tuned constants without derivation at the semantic center (`top_k=16`, `threshold=0.3`, `admissibility_margin=0.4` has a recorded derivation — the contrast is instructive).
7. M2 lacking formation's trust-boundary table (F-3).
8. ADR/code contradictions: unowned daemon vs ADR-0146's Shape-A rejection; ADR-0252's unreproducible "34"; the 2026-07-25 doc's accrual claim (C-5).
**Gap-register candidates (`30-gap-register.md`):**
1. The #138 fabrications — pre-labeled *measured & pinned, fix held for ADR + ratification*.
2. Reader inventory 19-wide vs writer 1739 (close fabrications before widening, per standing ruling).
3. No suite runs any `l10`/`always_on` pin; no soak artifact; no nightly (and the local-first/Mac-runner doctrine makes "nightly" itself need a ruling).
4. Non-text ingest uncovered; sensorium's 59 modules disconnected; no entry criterion.
5. No flag-default register (F-1: 17 flags, only deduction ON, no document states the set — now nuanced by the daemon's forced trio).
6. No orphaned-pin meta-check (F-2 — the mechanism by which M6's harness went unscheduled).
7. Curriculum query-scoping (the ADR-0264 §4.1 blocker); the absent curriculum serve ledger.
8. CR-2 agenda/drive: mechanisms without a chooser (confirmed at component depth); CR-3 efferent ruling; CR-4 temporal stance.
9. ADR-0252 §5 experiment unrun — the top open item, now with stakes note: GSM8K's demotion mispriced the experiment, but the paradigm governs *all* future comprehension.
10. The Candidate Register items needing one-line rulings vs real design work — separate them.
**Verification obligations for Phase 4:** the registers decide nothing — every entry carries evidence pointers and names its deciding authority (ruling vs ADR vs mechanical fix). Rank by leverage, not ease, per the AGENTS.md protocol. Where a hindrance names a better home, name the evidence too.
---
## 4. Note on method, for the record
Three phases in, the correction ledger reads: Phase 0 inherited a stale map claim (always-on "unbuilt"); Phase 2 caught it by reading code, then itself overstated ephemerality and understated the resolver; Phase 3 caught both by reading deeper, and demoted three more map labels. **Nothing in this chain was caught by re-reading documents.** The assessment's value is exactly proportional to how much code each phase actually read — which is the empirical vindication, inside the assessment itself, of `AGENTS.md` protocol step 1 and the mastery framework's demand that constraints trace to verifiable ground.

View file

@ -76,6 +76,8 @@ Three distinct surfaces exist for three distinct invariants, and conflating them
## Judgment
> **Phase 3 refinement (C-3, `05-phase3-findings.md`):** "no single place states the precedence order" is half-wrong — `core/cognition/surface_resolution.py::resolve_surface` (494 lines) is a declared-precedence resolver for the pipeline seam. The accretion concern survives only for the upstream composer arms in `chat/runtime.py`; the Third-Door candidate refines to *extending the existing resolver's pattern upstream*. Full arm inventory: `20-component-cards/surface-selection.md`.
**Fitness: `strained`.** M4's *architecture* is among the strongest in CORE — the selection-not-rewrite discipline, the three-surface separation, the fail-closed typing, the atomic enum/UI coupling. The strain is that its surface-selection policy has accreted one arm per capability (determination, estimate, unknown-domain, deduction, curriculum, hedge, register decoration, logos-morph override), each individually contracted, with no single place that states the precedence order as an executable rule. `runtime_contracts.md` documents it in prose across several sections; `chat/runtime.py` implements it across 3364 lines. That is the classic shape of a trade-off being split rather than dissolved — and a Third Door candidate for Phase 4 (a declarative resolution table with the precedence pinned, rather than ordered branches).
**Honest wrinkles:**

View file

@ -11,6 +11,8 @@
---
> **Phase 3 correction (C-2, `05-phase3-findings.md`):** this card's "T1 vault and field excitation are discarded on exit by design" describes the **default config only**. The daemon forces `persist_session_state=True` (Shape B+ — "restored bit-exactly"), so residency machinery exists and is daemon-forced; open items are its exact coverage (`chat/runtime.py:893952`) and horizon proof. The daemon's forced flag set is exactly `{persist_session_state, consolidate_determinations, strict_identity_continuity}` — see `20-component-cards/always-on-process.md`.
## ⚠️ Correction to Phase 0 Finding 0-C and to the system map
**Phase 0 recorded that the L11 always-on process is unbuilt. That is wrong, and the error is instructive.**

View file

@ -0,0 +1,43 @@
# always-on-process — `chat/always_on.py`, `chat/always_on_daemon.py`, `engine_state/`, `evals/l10_*`
**Kind:** component (M6's built half) · **Parent:** M6 · **Assessor:** Fable 5 (Phase 3)
**Verified at:** `8927c563` (2026-07-27)
**Liveness:** `live-internal` (CLI-reachable, suite-orphaned) · **Fitness:** `strained` (proof debt, not design debt) · **Topology role:** runtime boundary
> The process that runs the continuous-life heartbeat. Its design center is a single sentence from the daemon module: a restart is *the same life or it stops — never a silent fork*.
## What it is / What it does
`run_continuous(runtime, heartbeats, …)` — each beat advances `idle_tick` (continuous learning), records closure + learning evidence, self-checkpoints on real work, checkpoints once at exit; `heartbeats=None` runs unbounded until `stop`, which is checked before each beat *and* interrupts the inter-beat wait. `run_daemon` wraps it with a single-instance `fcntl.flock` lock — kernel-released on process death, so no stale-lock window and no PID-reuse ambiguity; the lock file is deliberately never unlinked (unlinking would let a peer flock a different inode). `lived_life.json` feeds the Workbench Lived Life surface. Landed 2026-06-14 (`18e25580`, `efd280d4`).
**The forced flag set (exact, from `CONTINUOUS_LIFE_CONFIG_FLAGS`):**
```python
{"persist_session_state": True, # Shape B+ — persist the lived session across reboot
"consolidate_determinations": True, # Step D — learn from determined facts each beat
"strict_identity_continuity": True} # load-time identity guard — same life or refuse
```
## Correction to the Phase 2 M6 card (Shape B+)
The M6 layer card carried forward "T1 vault and field excitation are discarded on exit **by design** (ADR-0146)." That is the **default-config** posture only. Under the daemon, `persist_session_state=True` activates Shape B+ persistence — `chat/always_on.py:9`: the lived state is "restored bit-exactly" — with opt-in persistence sites in `chat/runtime.py:893952`. So the residency question the M6 card called "the highest-value M6 question" (*should the process hold vault/field?*) is already partially answered in code: **the mechanism exists, is opt-in, and is daemon-forced.** What remains open is exactly what Shape B+ covers (session context vs full T1 vault vs field excitation — the persistence sites need a Phase-4 read) and whether it is *proven* at horizon.
## What the soak would prove if run (`evals/l10_always_on`)
- **H1 closure** — every observed idle beat is a valid versor, with an explicit vacuity guard: a run where the field never existed cannot pass "by saying nothing."
- **H2 bounded idle** — a no-work idle beat adds nothing to the vault (no idle resource leak); flagged consolidation writes are exempt.
- **H3 convergence** — a saturated idle life *settles and stays settled*, with a `min_converged_tail` so "settled" is observed, not assumed.
- **H4 reboot-resume** — a mid-soak reboot resumes the SAME life; post-reboot closure holds on every segment.
Each predicate has `*_holds` and `*_bites` test pairs (mutated evidence must fail). This is exemplary falsification design. **No recorded artifact exists; no suite runs any of it** — the long horizon is `python -m evals.l10_always_on`'s job, per its own docstring "run on demand / nightly," and no nightly exists.
## Judgment
**Fitness: `strained` — proof debt on a sound design.** The lock discipline, the never-silent-fork rule, the vacuity-guarded predicates, and the bites-pairs are all careful work. What is missing is entirely evidentiary: a recorded soak artifact, a scheduled runner, and an ADR that owns the daemon (ADR-0146 rejected Shape A; the daemon is unowned by any ratifying decision).
**Honest wrinkles:**
- The flag set forces the *consolidator* on but not the *accruer* (`accrue_realized_knowledge` absent) — see the determine-phase card: the continuous life may be consolidating an empty set. Unresolved.
- `strict_identity_continuity=True` under the daemon vs `False` default means identity-continuity refusal behavior differs between the daemon and every other entrypoint — correct by design, but nowhere stated outside the flag dict.
- The soak evals' own docstring designates a nightly cadence that has never been provisioned. Given the local-first CI doctrine (Mac runner, queue waits while asleep), a nightly soak is architecturally awkward — which may be *why* it never ran. That tension deserves a ruling, not silence.
**Open questions:** run the soak, record the artifact (→ the still-owed ADR-0146 Phase-4 spike); which suite owns `l10`/`always_on` pins (→ Phase 4); daemon's ratifying ADR (→ ruling); exact Shape B+ coverage (→ Phase 4 read of `runtime.py:893952`).

View file

@ -0,0 +1,35 @@
# attention-allocation — the live CR-1 mechanism
**Kind:** component (mechanism spanning `generate/salience.py`, `generate/attention.py`, `core/physics/{salience,attention,inhibition}.py`, `generate/stream.py`) · **Parent:** unowned (CR-1) — de facto M3 · **Assessor:** Fable 5 (Phase 3)
**Verified at:** `8927c563` (2026-07-27)
**Liveness:** `live-serving` (default ON) · **Fitness:** `strained` — sound mechanism, absent governance · **Topology role:** runtime boundary
> The mechanism that decides what CORE is allowed to consider at each generation step. It gates every token walk, owns the measured hot path (~73% of turn time through `cga_inner`), and is the only default-ON serving mechanism in the tree with no owning ADR, no zone, and no stage in any ratified articulation. This card gives it the identity it has been operating without.
## What it is / What it does (372 lines total, all read)
**`generate/salience.py` (62)** — `SalienceOperator.compute(field, vocab, top_k=16) → SalienceMap{indices, scores, budget}`. The docstring states the lineage plainly: "generation-facing salience from **ADR-0008 field curvature**… the score is now a local curvature magnitude from `core.physics.salience` rather than normalized proximity to the query field." So the mind-physics blueprint's Allocation Physics **did land**, mutated: the physics curvature kernel (`core/physics/salience.py`, 139 lines) is *composed* — imported as `CurvatureSalienceOperator` — by a thin generation-facing adapter. Not a duplicate (Phase 2's correction, confirmed by read).
**`generate/attention.py` (43)** — `AttentionOperator(inhibition_threshold).plan(salience, vocab) → allowed_indices`. Inhibition is a **scalar threshold** (default 0.3), not the blueprint's mask.
**Wiring (`generate/stream.py:255331`)** — `_attention_candidates` runs salience→attention when `use_salience` (default **True**); the walk intersects `language_candidates ∩ salience_candidates` (`:329`), and when language candidates are absent, salience candidates alone gate the step (`:331`). At `:637` the salience `budget` is fed back as the next `salience_top_k` — attention narrows itself as the walk proceeds.
**The decoration:** `core/physics/inhibition.py` (54 lines, `InhibitionOperator`/`InhibitionMask`) is imported only by `core/physics/__init__.py` and one parity test. No serving or eval path constructs a mask. By the sabotage test: **decoration** — the blueprint's third operator exists as an exported symbol and nothing more.
## Contract & evidence
- Live and load-bearing — code-read + config — `use_salience=True` default (`core/config.py:35`); deleting `_attention_candidates` would change every walk's candidate set — would-fail-if-absent: **yes**.
- Deterministic — pure functions of field state and vocab; parity-pinned (`tests/test_salience_vectorize_parity.py` pins the vectorized rewrite against the original nested loop).
- Behavioral pin — `tests/test_salience.py` exercises compute+plan; suite membership not individually confirmed (flagged, like most non-lane pins in this assessment).
- Interaction contract with admissibility: salience/attention prune *candidates*; admissibility (threshold/margin/rotor, ADR-0024/0025/0026) then judges them. Two allocation stages, only the second governed by ADRs.
## Judgment
**Fitness: `strained` — the gap is governance, and it is now fully characterized.** Mechanism: sound, deterministic, composed cleanly over the physics kernel. Governance: ADR-0008 is a *draft blueprint's* operator spec, never ratified as owning this serving behavior; no ratified articulation names an attention stage; the config knobs (`salience_top_k=16`, `inhibition_threshold=0.3`) are tuned constants with no recorded derivation — precisely the "threshold tuned for good-enough" the mastery framework's Pillar I forbids, sitting at the semantic center of generation.
**Honest wrinkles:**
- The budget feedback loop (`:637`) means attention is *self-narrowing* across a walk — a real cognitive-model property (fatiguing focus? commitment?) that no document names, let alone justifies.
- The hot-path cost (~73% of turn time) is this mechanism's nearest-neighbour/salience search — so CORE's compute profile is dominated by a mechanism whose parameters no decision governs.
- CR-1's ruling question is now precise: not "is attention a layer" in the abstract, but **who owns `use_salience`, the two constants, the budget feedback, and the InhibitionMask disposition** (ratify the mask's deletion, or build it). A one-page ADR closes all four.
**Open questions:** the CR-1 ADR (→ ruling); derive or empirically justify `top_k=16` / `threshold=0.3` (→ Phase 4); delete or build `InhibitionMask` (→ ruling; deletion is the mastery-framework default).

View file

@ -0,0 +1,28 @@
# comprehend-organ — `core/comprehension_attempt/`
**Kind:** zone→component descent · **Parent:** M3 · **Assessor:** Fable 5 (Phase 3)
**Verified at:** `8927c563` (2026-07-27)
**Liveness:** `live-internal` (**demoted** from the map's `live-serving`) · **Fitness:** `fit`, misleadingly named · **Topology role:** runtime boundary (off the chat serving path)
> The deterministic multi-organ setup router (N3): when several comprehension organs each attempt a problem setup, admit a setup only when exactly one organ produced an admissible one — or the admitting organs agree by signature. Never pick among disagreeing readings. Its philosophical role is refusal-preserving arbitration: routing must not become a place where a guess can hide.
## What it is / What it does
Six modules, 754 lines: `router.py` (77 — the N3 router), `classify.py` (159 — `classify_cmb/r1/r2/r3`), `failure_family.py` (250), `proposal.py` (148 — comprehension-failure proposals), `model.py` (63 — `ComprehensionAttempt`), `__init__.py`. Routing rule, verbatim from the module doc: exactly one `setup_correct` → routed; zero → `all_refused` (classified downstream); ≥2 agreeing signatures → routed; ≥2 differing → `ambiguous` (refuse — never pick). Cross-organ signatures are produced by different functions and never coincide, so two admitting organs resolve to `ambiguous` in practice. The router never solves and never emits `setup_wrong` — that is an eval-only outcome.
## The liveness demotion, with evidence
`comprehension_attempt` is imported by **neither** `chat/runtime.py` nor `core/cognition/pipeline.py`. Its non-test callers are `core/epistemic_disclosure/limitation.py` (→ `chat/ask_runtime.py`, behind `ask_serving_enabled=False`), `core/proposal_review/queue.py`, `core/epistemic_questions/delivery.py`, and `evals/constraint_oracle/verified_producer.py`. Nothing on the default serving path reaches it. The map's `live-serving` label is therefore wrong at this SHA: **`live-internal`** (eval lanes + flag-gated ask path + proposal machinery).
## Contract & evidence
- Refuse-on-ambiguity is the load-bearing invariant — pins: router tests (`tests/test_cmb_router_contemplation.py`, `tests/test_failure_family.py`, `tests/test_failure_proposal.py`) — present in the tree; suite membership not individually confirmed.
- wrong=0 posture: against gold the routed setup must match; the router structurally cannot emit a wrong setup, only a refusal or a routed one.
## Judgment
**Fitness: `fit` — but the zone name is a trap.** This is a *math setup* router over the GSM8K-era R1/R2/CMB organs, not "the comprehension organ" of the chat path. Chat comprehension lives in `generate/meaning_graph/reader.py` (see the realize-phase card). A future reader who greps "comprehend-organ" expecting the thing that reads user English will land in the wrong subsystem. Recommend the zone be renamed (e.g. `setup-router`) or its card carry this disambiguation permanently.
**Honest wrinkles:** the design is deliberately boring and correct — no dynamic scoring, no priority heuristics. Its consumers are all flag-gated or eval-side, so this machinery currently arbitrates for paths that mostly do not serve.
**Open questions:** should `epistemic_questions`/`disclosure` consumers ever reach serving, the router becomes serving-path arbitration — does it then need a suite-pinned invariant? (→ Phase 4)

View file

@ -0,0 +1,39 @@
# derivation-organs — `generate/derivation/`
**Kind:** component group · **Parent:** M3 (gsm8k-math zone) · **Assessor:** Fable 5 (Phase 3)
**Verified at:** `8927c563` (2026-07-27)
**Liveness:** `live-internal` (math lanes; not on the chat serving path) · **Fitness:** `superseded-in-place` (by ADR-0252 ruling) · **Topology role:** runtime boundary (math reader)
> The "novice surface piles" of ADR-0252's diagnosis: per-shape derivation organs that turn recognized problem statements into typed solver state. Ruled superseded by the structure-mapping paradigm — and ruled to keep serving until a proven replacement exists.
## The 34-vs-18 discrepancy — RESOLVED (basis mismatch, not paydown)
Phase 2 flagged that ADR-0252's "34 bespoke surface organs" did not reproduce (18 found). Verified against the tree **at the ratification commit itself** (`1ccef491`):
| Measure | At ratification | Now (`8927c563`) |
|---|---|---|
| `def resolve_promotable_*` entry organs | **18** | **18** |
| `generate/derivation/` tree entries | 33 | 32 (`.py` files) |
The count was 18 entry organs *on the day ADR-0252 was ratified*. So "34" never counted `resolve_promotable_*` functions — its plausible basis is the module count (~3233: the 18 entry organs plus support modules — `accumulate`, `clauses`, `comparatives`, `compose`, `extract`, `verify`, `calendar_grounding`, …), or an earlier-generation organ inventory. Two consequences:
1. **No consolidation has occurred since ratification** (18 → 18; one module removed). The debt is *not* being paid down — Phase 2's alternative hypothesis is eliminated.
2. **The governing ADR's central quantitative claim is unreproducible as stated.** The diagnosis stands regardless of whether the pile is 18 or 34 — but a ratified document whose headline number has no stated basis is exactly the documentation-debt class Finding F-4 tracks. The fix is one sentence in an ADR-0252 amendment stating the basis.
## What it is / What it does
32 modules, 6,765 lines. Each entry organ (`resolve_promotable_affine_fraction_delta`, `…goal_residual`, `…temporal_tariff`, etc.) recognizes one problem *shape* and publishes pre-composed candidates that the registry gates; support modules provide clause extraction, comparatives, composition, and verification. Governed by ADR-0251's standing prohibition: **no new bespoke per-case regex work** — new shape coverage that does not generalize is refused as debt (ADR-0252 §4: generalization ratio > 1 or it is a surface pile).
## Contract & evidence
- Misparse rate must be zero on the adversarial suite (refusal may be arbitrarily high — the safe failure mode) — contract: `runtime_contracts.md` §Adversarial suite; the `subtle_in_grammar` family (4 cases, all correct) proves the gate is not satisfied by refusing everything.
- GSM8K lane shape `wrong == 0` with outcome-accounting completeness — pinned lane `math_teaching_corpus_v1` in `CLAIMS.md`; `math` suite exists.
- Serving isolation: these organs feed math lanes; the chat serving path does not import them (deduction and curriculum serve through `proof_chain`/`curriculum_surface`, verified in Phase 2).
## Judgment
**Fitness: `superseded-in-place`** — the ruling is explicit and this card does not relitigate it. The schema's liveness ⊥ fitness separation exists for exactly this state.
**Honest wrinkles:** the replacement is gated on the ADR-0252 §5 SME experiment, which has never returned a verdict — so "superseded" currently has no successor timeline at all; the organs are condemned and load-bearing indefinitely. GSM8K's demotion to diagnostic makes this pile low-urgency, which is presumably why the experiment stalled — but the *paradigm* the experiment validates governs all future comprehension, not just math. The stakes are mispriced by the demotion.
**Open questions:** amend ADR-0252 with the organ-count basis (→ ruling, one sentence); run §5 (→ ruling; the assessment's top open item).

View file

@ -0,0 +1,41 @@
# determine-phase — `generate/determine/`
**Kind:** zone→component descent · **Parent:** M3 (serve seam → M4) · **Assessor:** Fable 5 (Phase 3)
**Verified at:** `8927c563` (2026-07-27)
**Liveness:** `live-internal`, flag-gated (**demoted** from the map's `live-serving`) · **Fitness:** `fit` · **Topology role:** runtime boundary
> The open-world DETERMINE gear: answer a question *from what the engine has realized in this conversation*, affirmatively or not at all. INV-30 is its constitution — it constructs only `Determined(answer=True)` or refuses; absence never refutes. It is the closest thing CORE has to "thinking with what it just learned," and it is off by default.
## What it is / What it does
Eight modules, 1071 lines: `determine.py` (the gear), `consolidate.py` (Step D — one semi-naive layer of member/subset closure per idle tick, every hop verified by the proof_chain ROBDD before `realize_derived` writes it back; `member ∘ member` structurally unreachable; four declared strict-order predicates in `TRANSITIVE_PREDICATES`), `estimate.py` + `estimation_license.py` (Step E — converse-guess under an earned SERVE license, always disclosed `[approximate]`), `derived_close_proposals.py` (PR-2 bridge — eligible derived facts emitted as proposal-only artifacts), `render.py` (42 — honest rendering: SPECULATIVE grounds read "as I was told", never "verified").
## The gating map (all call sites verified)
| Entry | Caller | Gate | Default | Daemon forces? |
|---|---|---|---|---|
| `determine()` / `render_determination` | `chat/runtime.py:1364,1303` via `_accrue_in_turn` / `_surface_determination` | `accrue_realized_knowledge` | **False** | **No** |
| `consolidate_once` | `chat/runtime.py:1041` via `idle_tick` | `consolidate_determinations` | False | **Yes** |
| `estimate_converse` + `serve_license` | `chat/runtime.py:1420` | `estimation_enabled` | False | No |
| derived-close proposal emission | `chat/runtime.py:1054` via `idle_tick` | `review_derived_close_proposals` | False | No |
A default-config serving turn **never** reaches this package. The map's `live-serving` label is wrong at this SHA: `live-internal`, flag-gated, exercised by lanes (`evals/close_derived_climb`, `evals/determination_closure`, `evals/determination_estimation`).
## Two discrepancies this table surfaces
1. **The daemon enables the consolidator but not the accruer.** `CONTINUOUS_LIFE_CONFIG_FLAGS` forces `consolidate_determinations=True` but leaves `accrue_realized_knowledge=False` — yet `realize_comprehension` (the only turn-path writer of realized facts) sits behind the *accrual* flag. Under the continuous-life config as coded, the idle consolidator may have nothing to consolidate unless realized facts arrive some other way. Either the flag set is incomplete, or consolidation under the daemon is deliberately dormant-until-seeded. **Unresolved; needs a ruling or a test that seeds through the lived path.**
2. **A prior verification document is contradicted at this SHA.** `docs/research/architecture-assessment-verification-2026-07-25.md` §2 states `accrue_realized_knowledge` "is enabled by the production L10 process." The daemon's flag set does not include it. Either the doc anticipated a change that never landed, or the flag was later removed. Doc/code discrepancy — record, don't guess.
## Contract & evidence
- INV-30 (True-or-refuse; three visible `Determined` construction sites; typed rejection of forged `ClosedFrame`) — pin: `tests/test_architectural_invariants.py`.
- Derived facts stay SPECULATIVE (sound inference never upgrades premise standing); replayable `Derivation` provenance (premise `structure_key`s + rule + `entailed` verdict) — contract: `runtime_contracts.md` §Idle consolidation.
- wrong=0 by proof-gating: only `ENTAILED` conclusions are written — lane: `evals/close_derived_climb` (fixed-point climb, monotone, saturated tick consolidates 0).
## Judgment
**Fitness: `fit`.** The gear is small, typed, proof-gated, and honestly rendered. The INV-30/INV-31 firewall against closed-world machinery is among the cleanest boundaries in the repository.
**Honest wrinkles:** the entire "think with what you learned this session" capability — arguably the most *alive*-feeling behavior CORE has — is dark on every default path and only partially lit by the daemon. The `_accrue_in_turn` docstring calls DETERMINE and the readers "total (typed results, no raises)" while wrapping them in a broad defensive guard; the guard is honest backstop, but any exception it eats disappears silently into a no-op accrual (`_last_turn_accrual=None`) with no telemetry of the swallow. Flagged for Phase 4 as a small silent-failure surface inside an otherwise typed layer.
**Open questions:** the daemon flag-set completeness (→ ruling); should accrual-swallowed exceptions be counted in telemetry? (→ Phase 4)

View file

@ -0,0 +1,37 @@
# realize-phase — `generate/realize/` (and the reader that feeds it)
**Kind:** zone→component descent · **Parent:** M3 · **Assessor:** Fable 5 (Phase 3)
**Verified at:** `8927c563` (2026-07-27)
**Liveness:** `live-internal`, flag-gated (**demoted** from the map's `live-serving`) · **Fitness:** `fit` (the phase) — with its *feeder* under held fabrication findings · **Topology role:** runtime boundary
> REALIZE — "integrate comprehended structure into the held self" (roadmap Step 3). If M1 is knowledge at rest and DETERMINE is answering from it, REALIZE is the moment comprehension becomes *held*: a reading of the user's words is written into session memory as a typed, SPECULATIVE, as-told record. It is the exact point where a misreading becomes a belief — which is why the fabrication findings matter most here.
## Disambiguation (a naming trap, recorded permanently)
`generate/realize/` (**knowledge** realization — this card) and `generate/realizer.py` (**surface** realization — the articulation renderer, M4) are unrelated mechanisms with confusable names. The map's `realize-phase` zone is the former. Any future search for "realizer" work must state which one it means.
## What it is / What it does
Four modules, 645 lines: `realize.py` (425 — `realize_comprehension`, `realize_derived`, `Realized`/`NotRealized`/`RealizedRecord`, `Derivation`), `quantitative.py` (135 — `realize_quantitative`), `recall.py` (62 — `recall_realized`, DETERMINE's read path), `__init__.py`. Writes go through the INV-21-allowlisted vault writer; records carry `epistemic_status="speculative"` and derived records carry full `Derivation` provenance so replay re-derives and re-verifies.
Call graph (verified): `chat/runtime.py:1367` `_accrue_in_turn``realize_comprehension` (gate: `accrue_realized_knowledge=False` default, **not** daemon-forced); `generate/determine/consolidate.py:44``realize_derived` (gate: `consolidate_determinations`, daemon-forced); `derived_close_proposals.py:25``recall_realized`. Same demotion as determine-phase: no default serving turn reaches this package.
## The feeder — where the fabrication findings live
`_accrue_in_turn` comprehends via `generate/meaning_graph/reader.py::comprehend` and `generate/meaning_graph/relational.py::comprehend_relational`**this is the two-grammars reader**: 19 constructions against the writer's 1739, overlap 6, and **fabricates on 22 more** (`every dog is a mammal` → `member(every_dog, mammal)`; `Given: furthermore; p implies q; p.``asserted(furthermore)` recited back as a served premise). Those findings are **measured and pinned in PR #138, held for ADR + ratification** — recorded here because REALIZE is where a fabricated reading would become a held belief, *not* re-discovered, *not* fixed.
The architecture note that follows from this placement: REALIZE itself is sound — it faithfully holds whatever the reader hands it, at honest SPECULATIVE standing. The truth defect class is entirely upstream (the reading), which is consistent with the project's fix-upstream doctrine and with holding the fixes for a serving-truth ADR.
## Contract & evidence
- INV-21 (allowlisted writer), INV-22/23 (SPECULATIVE default), INV-29 (only `vault/store.py` transitions status) — pins: `tests/test_architectural_invariants.py`.
- Inline realization behavior — `tests/test_inline_realization.py` ("comprehensible declarative accrues; question determines; off-by-default leaves the turn untouched").
- Predicate-generality — `relational.py:8`: the spine consumes relational comprehension unchanged; `realize_comprehension` is predicate-general (no per-predicate special case in the writer).
## Judgment
**Fitness: `fit`.** Small, typed, provenance-complete, honestly gated. The one structural risk is inherited, not local: the phase will hold whatever it is fed, so its integrity ceiling *is* the reader's fidelity — 19-wide today, fabricating on 22.
**Honest wrinkles:** as with determine-phase, the most life-like capability in the system defaults dark. `realize_quantitative` was not traced to a live caller in this pass (likely lane-side); unverified — Phase 4 should not count it live without a pointer.
**Open questions:** when the #138 fabrication ADR lands, should REALIZE gain a defensive assertion (refuse to hold a reading whose construction is outside the reader's verified inventory)? That would convert reader-inventory truth into a mechanical gate at the holding boundary. (→ Phase 4 / the fabrication ADR)

View file

@ -0,0 +1,24 @@
# sensorium-falsification — `sensorium/environment/`
**Kind:** zone→component descent · **Parent:** M2 · **Assessor:** Fable 5 (Phase 3)
**Verified at:** `8927c563` (2026-07-27)
**Liveness:** `live-internal` (confirmed) · **Fitness:** `fit` · **Topology role:** deterministic replay surface (not a fusion layer, not a world model)
> Expected-versus-actual environmental falsification: the discipline of saying, before looking, what the world should show — and then checking. Its philosophical role is to keep afferent claims falsifiable without smuggling in a mutable world model, probabilistic confidence, or a learning path. It is deliberately the *narrowest possible* honest instrument.
## What it is / What it does
Four modules, 852 lines: `falsification.py` (compares already-compiled afferent units by merge key), `frame.py` (`ObservationFrame` / `ExpectedObservationFrame`), `scenario.py` (338 — scenario construction), `harness.py` (54). The module docstring states its non-goals in the first sentence: it does not compile raw signals, decode motor commands, fuse modalities, mutate Vault state, or create a world model. Verdict set is closed at two values — `SUPPORTED` (every expected slot matched by merge key, nothing unexpected) / `FALSIFIED` (anything missing, changed, or unexpected). Checksums via `sha256_json`. Neither verdict promotes anything to reviewed memory or mutates packs, vault, identity, or policy.
## Contract & evidence
- ADR-0211 contract frozen in `runtime_contracts.md`, including the forbidden list: no raw pixels/PCM/event streams/byte payloads/actuator traces in traces; no motor/efferent units in v1; no learned latents as substrate; no probabilistic confidence or tolerance thresholds in verdicts; no `generate/*` dependencies; no `ModalityRegistry.decode`.
- The `sensorium` suite (21 files) runs — the zone's tests are scheduled, unlike M6's. would-fail-if-absent: yes.
## Judgment
**Fitness: `fit`.** This is what a v1 should look like: closed verdicts, explicit non-goals in the first paragraph, checksummed evidence, and a hard wall against becoming a world model by accretion. When the sensorium track eventually approaches serving (M2's open entry-criterion question), this bench is the pattern the rest of the afferent stack should be held to.
**Honest wrinkles:** the map filed this zone under layer "L12" — a stratum that exists in no ratified document (flagged in the M2 card; taxonomy should either mint L12 deliberately or drop it). The bench compares *already-compiled* units, so its guarantees are conditional on the sensorium compiler's honesty — which is unmapped territory (the broader 59-module `sensorium/` package remains the largest built-and-disconnected mass in the tree). Zero-subsystem status in the map was an artifact of the final mapping wave, not of emptiness.
**Open questions:** none blocking; inherits M2's "entry criterion for serving" ruling.

View file

@ -0,0 +1,44 @@
# surface-selection — the arms and the resolver
**Kind:** component (mechanism spanning `chat/runtime.py` + `core/cognition/surface_resolution.py`) · **Parent:** M4 · **Assessor:** Fable 5 (Phase 3)
**Verified at:** `8927c563` (2026-07-27)
**Liveness:** `live-serving` · **Fitness:** `strained` — refined from Phase 2 · **Topology role:** runtime boundary
> The mechanism that decides which of several candidate surfaces the user actually reads. Every truth property CORE claims converges here.
## Correction/refinement to the Phase 2 M4 card
Phase 2 recorded "no single place states the precedence order as an executable rule." **Partially wrong.** `core/cognition/surface_resolution.py` (494 lines) *is* a declared-precedence resolver — `resolve_surface` plus `_base_runtime_surface` ("select the runtime-owned base surface by declared precedence": served `response_surface` always wins; then `pre_decoration_surface`; then `canonical_surface`), `_truth_path_base` (canonical-first, the register-invariant identity folded into `trace_hash` — deliberately the *reverse* preference of the served base, each serving its own invariant), `_abstention_resolution`, `_grounded_open_hedge_resolution` (with an explicit admissibility predicate), and `_substrate_supreme`. The historical note in its docstring says why it exists: "historically these mutated one string in evaluation order."
**What remains true:** the resolver governs the *pipeline seam* (base/truth-path/abstention/hedge/fold axes). The **composer arms** upstream in `ChatRuntime.respond` are still ordered branches, verified at their call sites:
| Arm | Site | Gate |
|---|---|---|
| deduction_grounded_surface | `chat/runtime.py:1834` | `deduction_serving_enabled` (**ON**, ratified) |
| curriculum_grounded_surface | `:1850` | `curriculum_serving_enabled` (OFF) |
| pack_grounded_comparison | `:1871` | pack-grounding conditions |
| narrative_grounded_surface | `:1898` | — |
| example_grounded_surface | `:1915` | — |
| pack relation-confirmation | `:1936` | — |
| determination override (Step B-2) | `_surface_determination``:1303` | `accrue_realized_knowledge` (OFF) |
| disclosed estimate (Step E) | `_surface_estimate``:13121340` | `estimation_enabled` (OFF) + earned SERVE license |
| unknown-domain gate stub | `:188` `_UNKNOWN_DOMAIN_SURFACE` | gate fires |
| grounded-open hedge (ADR-0254) | via resolver admissibility | — |
| register decoration (ADR-0071/0077) | post-selection | never moves `trace_hash` |
| logos-morph override | pipeline `:526` | answer-authority seam |
So the true architecture is **two strata**: ordered composer branches choose the *candidate*; the declared-precedence resolver reconciles *runtime vs pipeline vs abstention vs hedge*. The Phase 2 Third-Door candidate refines to: **extend the resolver's declared-precedence pattern upstream to the composer stratum**, rather than "create a resolver" — half the work is already done and proves the pattern fits this codebase.
## Contract & evidence
- Served-bytes-wins and its rationale are documented *with the falsifiable contract that catches regression*: preferring canonical would strip the register axis while `trace_hash` stays green — "the register-tour claims are the falsifiable contract that catches it" (`surface_resolution.py:113116`). This is the sabotage test applied prospectively, in-code — worth naming as a model.
- Estimate arm: `govern_response` returns STRICT for an unlicensed class → surface unchanged; `shape_surface` guarantees the `[approximate]` prefix because a converse guess is `UNVERIFIED_POSSIBLE`, never in APPROXIMATE's admissible set — "a wrong estimate is always a DISCLOSED wrong" (`:13121340`).
- Selection-not-rewrite: determination and gate arms `replace(response, surface=…)`, retaining articulation/walk surfaces as evidence.
## Judgment
**Fitness: `strained`** — but more tractably than Phase 2 suggested. The resolver stratum is well-designed and self-documenting; the composer stratum is where arms accrete. With only deduction ON today, the *live* branch complexity is modest; the strain is prospective (each new capability adds an arm ahead of any declared order).
**Honest wrinkles:** the composer arms and the resolver are in different packages with different owners (`chat/` vs `core/cognition/`), so nothing structurally prevents a new arm from bypassing the resolver's disciplines. The M4 empty-string refusal wrinkle (typed refusal discarded at the public `str` boundary) sits in this same mechanism and remains the sharpest single dishonesty on the serving path — not because anything lies, but because the truth that exists goes unserved.
**Open questions:** declarative composer-arm precedence (→ Phase 4 Third-Door, refined); materialise `refusal_reason` (→ ruling, plumbing already landed).