core/docs/assessment/20-component-cards/surface-selection.md
Shay 901f028f32 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.
2026-07-27 15:57:36 -07:00

4.8 KiB
Raw Blame History

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).