# Session 2026-06-08 — Practice-time attempts vs served answers, and the servability blade **Status:** discussion / design note — **session document, not an ADR yet.** No code shipped. This records a *refinement of doctrine* reached in conversation, deliberately preserved before any new capability work so the idea cannot be silently collapsed back into a binary gate. **Headline:** `wrong=0` has been operating as a hard binary — **verified answer OR refusal** — and that binary, correct for sealed evaluation, is wrong for collaborative reasoning. The real law is **"no false presentation of epistemic status."** From that reframing fall two proposed organs: a **ProblemAttemptSession** (where typed, isolated candidate guesses are *allowed* at practice time) and a **ServabilityBlade** emitting a **ServabilityDecision** (which chooses, at serving time, among *more than two* truthfully-labeled output modes). `No serving path, algebra, versor, recall, or gate touched. This is the research` `trail — what we decided and how the conversation arrived there.` > **Amended 2026-06-08 (see [§ Amendment](#amendment-2026-06-08--reconcile-with-adr-0206--epistemic_state-do-not-build-parallel-substrate) below).** The doctrine here stands, but the original draft **under-referenced substrate that already ships the serving half of this design.** `ServabilityDecision` / `ServabilityBlade` must be built as the **activation of the already-shipped ADR-0206 response-governance bridge** (`ReachPolicy` / `govern_response` / `shape_surface`, gated STRICT-only today, already disclosing `[approximate]`), and the `epistemic_state` Literal must **reuse `core/epistemic_state.py`** — *not* a parallel object or a smaller renamed enum. Read the Amendment before building. > **Why this doc exists, and why now.** CORE is open-source research in a largely > uncharted corner of AI — a deterministic cognitive engine, not a transformer > wrapper. The *reasoning behind* a design is as load-bearing as the design. > Capturing it as a **session doc rather than an ADR** is deliberate: the idea is > a refinement, not yet a ratified architectural commitment. Writing it down now > protects the research trail and **keeps future agents (and the operator) from > collapsing the idea back into a binary gate** the next time the wrong=0 > invariant is invoked. An ADR can follow once PRA/REL exist and the blade has a > concrete consumer. --- ## TL;DR — the refinement, in four lines ```text wrong=0 ≠ binary answer/refuse wrong=0 = no false presentation of epistemic status practice / contemplation MAY explore typed, isolated candidates (even guesses) served output NEEDS a servability blade (more modes than verified | refuse) ``` 1. **The binary we inherited.** The serving contract is, today, *emit a verified answer, or refuse.* That is the classic wrong=0 path ([[project-self-check-soundness-not-correctness]]) and it is **correct for sealed eval.** 2. **The over-reach.** Read literally, that binary also forbids partial reasoning, provisional insight, surfacing multiple admissible readings, and open-ended problem-solving — none of which are false presentations of truth. It makes the engine mute unless omniscient. 3. **The reframing.** Truth discipline is **disclosure discipline**: *never hide uncertainty; never promote a candidate to a fact; never collapse a hypothesis into a verified answer; never omit the reason a conclusion is provisional.* A *labeled* provisional answer is honest, not a lie. 4. **Two layers fall out.** A **practice/attempt layer** where typed, isolated candidates may be explored, and a **served-output blade** that decides what of that internal state is truthfully emittable in the current context. --- ## 1. The distinction: practice-time attempts vs served answers This is the spine of the whole refinement. There are **two different lanes** with **two different epistemic licenses**, and the binary gate conflated them by applying the serving license everywhere. | | **Practice / contemplation** | **Serving** | |---|---|---| | purpose | explore, attempt, eliminate, learn | emit to a user / downstream | | may contain | guesses, attempts, pattern-matches, candidate eliminations, partial derivations | only what is *truthfully labelable* in context | | failure mode it guards | *getting stuck / never learning* | *misrepresenting epistemic status* | | existing substrate | sealed practice lane (ADR-0175), `comprehension_attempt`, contemplation, failure families, proposal-only learning | wrong=0 verify gate, refusal taxonomy, safety/refusal policy | | license | **guessing allowed** (typed + isolated) | **no false presentation of status** | The mistake was letting the *serving* license (prove-or-refuse) leak into the *practice* lane, which would forbid the engine from ever attempting something it cannot yet prove — i.e. forbid it from learning. And, symmetrically, letting the *practice* binary ("we either solved it or we didn't") leak into *serving*, which collapses everything that isn't a finished proof into silence. **Practice may explore. Serving must disclose. Neither may lie.** ## 2. Why candidate guesses are allowed — *when typed and isolated* A guess is dangerous only when it can be **mistaken for a fact** or **leak into ratified state**. Remove those two hazards and a guess becomes a legitimate research instrument. Two conditions make it safe: - **Typed.** A candidate is not a free-floating string asserted as an answer. It is a *typed object* carrying its own epistemic status (`inferred`, `underdetermined`, `ambiguous`, …), its basis, and its eliminations. Its type *is* its honesty: nothing about a typed candidate claims to be verified. - **Isolated.** The candidate lives in the practice/attempt lane and the proposal-only learning path ([[project-next-batch-contemplation-prototype]]: `teaching/proposals/` emits, never self-installs). It cannot reach serving, and it cannot ratify itself into corpus or packs. The fail-closed boundary already exists; the guess simply lives behind it. Under those two conditions the existing **sealed practice lane** (ADR-0175: attempt-and-eliminate, [[adr-0175-calibrated-learning-architecture]]) is already *doing this safely* — accumulating typed attempts and eliminations under a Wilson floor without ever touching the wrong=0 serving metric. The refinement is to name the principle explicitly so it is not re-litigated: **typed + isolated ⇒ a candidate guess is admissible at practice time.** ## 3. Why served output needs more than verified/refuse The same internal evidence should produce *different* emissions depending on context — and "refuse" is frequently the *worst* truthful option available. Examples where a third mode is strictly more honest *and* more useful: - **Partial progress** — *"I can establish these constraints but can't yet pin a unique answer; one variable is underdetermined."* (More useful than refusal, asserts nothing false.) - **Multiple candidates** — *"Two admissible readings: under A the answer is 12, under B it's 15; the text doesn't disambiguate."* (The honest output for genuinely ambiguous input — refusal *hides* the real finding.) - **Provisional working answer** — *"Best current setup is this; I haven't verified every assumption, so treat it as provisional."* (Honest disclosure for collaborative, low/medium-risk work.) - **Clarifying question** — *"Does 'total animals' include the dogs?"* (When the ambiguity is resolvable by the user.) The unifying rule — **the engine may emit anything it can truthfully label:** | May emit (truthfully labeled) | May **not** emit | |---|---| | verified fact **as** verified | hypothesis **as** fact | | inference **as** inference | guess **as** proof | | hypothesis **as** hypothesis | partial setup **as** complete | | partial result **as** partial | pattern-match **as** verification | | ambiguity **as** ambiguity | unreviewed proposal **as** ratified | | failure **as** failure | | The right column is the real wrong=0. The binary was needlessly suppressing the left column. ## 4. Proposed: `ProblemAttemptSession` (PRA) The practice-lane evidence object. It records the typed candidates, what's been eliminated, and what ambiguity remains — the substrate the blade later reads. (The comprehension-attempt substrate from [[project-next-batch-contemplation-prototype]] — `core/comprehension_attempt/`, setup router, failure-family registry — is the natural home; PRA firms up its *evidence shape*.) ```python @dataclass(frozen=True) class CandidateAttempt: value: str # the candidate answer/setup epistemic_state: Literal[ "verified", "inferred", "underdetermined", "ambiguous", "contradicted", "unsupported", ] basis: tuple[str, ...] # why this candidate was produced eliminated_by: tuple[str, ...] # checks that ruled it out (empty = live) @dataclass(frozen=True) class ProblemAttemptSession: problem_id: str reader: Literal["R1", "R2", "R3", "CMB"] # which setup family produced it candidates: tuple[CandidateAttempt, ...] # typed; guesses allowed here eliminated: tuple[CandidateAttempt, ...] residual_ambiguity: tuple[str, ...] # unresolved readings/variables risk_context: Literal[ "sealed_eval", "practice", "collaborative_work", "research", "tutoring", "safety_critical", "production_serving", ] # frozen, inspectable, replayable — an auditable artifact like every gate decision ``` Note what the type *guarantees*: a `CandidateAttempt` can never be mistaken for a served fact, because its `epistemic_state` travels with it and `eliminated_by` records its disqualification. This is the "typed" half of §2 made concrete. ## 5. Proposed: `ServabilityDecision` (SRV) The serving-lane policy object. It consumes a `ProblemAttemptSession` plus risk and user intent, and selects a *truthfully-labeled* output mode. > **Reuse, don't reinvent (Amendment 2026-06-08):** this *is* the ADR-0206 > `ReachPolicy` / `govern_response` decision, gated STRICT today — not a new object. > The `mode` values below map onto `ReachLevel` (`STRICT < APPROXIMATE < EXTRAPOLATE > < CREATIVE`); the `epistemic_state` field must be `core.epistemic_state.EpistemicState`, > not the Literal sketched here. Build SRV as the *activation* of that seam. See the Amendment. ```python @dataclass(frozen=True) class ServabilityDecision: mode: Literal[ "verified_answer", # proof complete — the classic wrong=0 path "provisional_working_answer", # strong-but-unratified, disclosed as such "partial_progress", # useful, can't finish "multiple_candidates", # several admissible readings survive "clarify", # ambiguity resolvable by the user "refuse_unsupported", # can't proceed without guessing "refuse_unsafe", # safety/high-risk threshold unmet "contradiction_report", # evidence conflicts ] epistemic_state: Literal[ "verified", "inferred", "underdetermined", "ambiguous", "contradicted", "unsupported", ] risk_level: Literal["low", "medium", "high", "sealed_eval"] confidence_basis: tuple[str, ...] # why we believe what we believe required_disclosures: tuple[str, ...] # caveats that MUST accompany the surface prohibited_phrases: tuple[str, ...] # claims this mode may not make servable_claims: tuple[str, ...] # what may actually be emitted ``` **Risk sets strictness, not the existence of the blade.** The *same* epistemic state yields different modes by context: ```text sealed_eval → VERIFIED_ANSWER | REFUSE only (no provisional) practice → (internal; not a served emission) collaborative_work → PROVISIONAL_WORKING_ANSWER allowed research → hypotheses / candidate paths / uncertainty valued tutoring → MULTIPLE_CANDIDATES with explanation safety_critical → strict proof/source threshold; else caveat or refuse production_serving → verified, else disclosed-provisional, else refuse ``` The answer/refuse binary is now visible as **the strict end of a spectrum** (`sealed_eval` / `safety_critical`), retained verbatim there — not the whole contract. This is what resolves the practice-vs-serving tension cleanly: serving stops being binary and becomes **controlled disclosure**. A provisional answer is truthful **iff** it carries its label: *"best current inference … not fully verified … these assumptions are load-bearing … here is what would change the answer."* ## 6. How this came from the R1 / R2 / R3 / CMB trajectory The refinement was not abstract — it was forced by where the reader/compiler work actually went. Each step produced **typed candidates and typed failures in an isolated lane**, and that accumulation is what made the binary's coarseness visible: - **R1 — reconstruction reader.** Derivation/reconstruction over GSM8K ([[project-two-disjoint-gsm8k-readers]]). Committed serving sits at a few correct / many *refused* / **zero wrong** — i.e. the binary's "refuse" branch is doing almost all the work. The reader *knew things* about the refused cases it had no way to say. - **R2 — constraint compiler.** Finite-integer linear-constraint setup compiler (ADR-0217, [[project-r2-constraint-compiler-built]]): prose → reader → `ConstraintProblem` → solver → answer-verifier with a **contradiction flag**. Here the engine started producing *structured, typed* intermediate state (underdetermined systems, contradictions) that is precisely *not* "verified answer" and *not* "nothing" — the first hard evidence that two modes were too few. The reader owns *setup*; the solver owns *solvability* — already a graded split. - **R3 — single-rate / rates-time-state.** The rate family ([[project-it-idle-integration-and-frontier]]): exact-rational time-unit conversion (R3.2), single-rate setup → `quantity = rate × time`. Gold `13/13`, reader `9/0/4`. Rate/time problems are ambiguity-rich, which is exactly where *partial progress* and *multiple candidates* become the honest outputs. - **CMB — the combined-rate ladder.** Combined rate is a *new semantic object* (two explicit rates over one shared unit, combined by an explicit `sum` / `difference` mode, then single-rate algebra over the result), with its own organ (`generate/combined_rate_comprehension/`) and ruler (`evals/combined_rate_oracle/`). Built as a staged ladder: **CMB-a** (model + gold + setup oracle — *"the ruler is defined and gold-valid"*, landed #650, [`cmb-a-combined-rate-ruler-2026-06-08`](../analysis/cmb-a-combined-rate-ruler-2026-06-08.md)) → **CMB-b** (exact solver, int-or-refuse) → **CMB-c** (reader: prose → `CombinedRateProblem | Refusal`) → **CMB-d** (router / contemplation wiring + failure-family) → **CMB-e** (capability ledger). CMB is the sharpest evidence for this whole session: its **2×2 domain-entry grid** does not produce a flat refuse — it produces *typed, graded* outcomes at the setup boundary itself: | | combination cue | no cue | |----------------|------------------------|------------------------------| | **two rates** | solved (sum/difference)| `combine_mode_ambiguous` | | **one rate** | `missing_second_rate` | `not_combined_rate_shaped` | `combine_mode_ambiguous` is explicitly *"a substantive refusal"* — the engine knows it is in combined-rate territory but cannot pick a unique mode. That is a textbook `MULTIPLE_CANDIDATES` / `clarify`, **not** the same epistemic object as `not_combined_rate_shaped` (out-of-domain, step aside to R3) or a clean solve. The binary gate has one bucket — "refuse" — for three structurally different states. CMB-a *already typed them apart*; it just has nowhere to send the distinction at serving. **The throughline:** every rung — R1, R2, R3, CMB — kept generating *typed intermediate epistemic states* (refused-but-known, underdetermined, contradicted, **substantively-ambiguous**, out-of-domain), and the typed-contemplation lane ([[project-next-batch-contemplation-prototype]]: `core/comprehension_attempt/`, failure-family registry, `teaching/proposals/` proposal-only emitter) kept *exploring typed candidates in isolation* without ever denting wrong=0 (the empirical proof of §2). The binary serving gate had nowhere to put any of it except "refuse." The ServabilityBlade is the organ that finally gives that accumulated, typed, isolated evidence a truthful way to reach the user. --- ## How it fits CORE (the ingredients already exist) The blade is the **consumer** of organs already built, not a new subsystem: epistemic states (derivation/verify), safety/normative clearance ([[safety-refusal-policy]] → `refuse_unsafe`, `required_disclosures`), setup/answer oracles (`verified` vs `underdetermined` — e.g. CMB-a's combined-rate ruler), the typed-contemplation / comprehension-attempt lane (→ the candidate evidence), proposal-only learning (`proposal` vs `ratified`), the existing [`refusal-taxonomy`](../refusal-taxonomy.md) (→ the `refuse_*` / `contradiction_report` branches), and the calibrated reliability gate (ADR-0175 Wilson floors → `risk_level` / `confidence_basis` for the provisional mode). The work is **integration + a policy object** — same character as the AGI-spine integration phase ([[milestone-agi-spine-A-to-E-complete]]). ## Why this matters for AGI-candidacy A real intelligence does not only *answer* or *refuse*. It can say, distinctly and truthfully: *I know this. I think this. I suspect this. I can prove this part. I cannot prove that part. Here are the assumptions. Here is the risk. Here is what would settle it.* That is **more** truthful than the binary, not less — the binary discards true statements about the engine's own knowledge state by collapsing them into silence. It sits under the telos ([[project-core-is-one-continuous-life]]): a continuously-learning life that *thinks with* its operator must share in-progress thought honestly, not only ratified conclusions. --- ## Amendment 2026-06-08 — reconcile with ADR-0206 + `epistemic_state` (do NOT build parallel substrate) A review of this note against the tree at `main` found it **under-references the substrate that already ships the serving half of this design.** The *doctrine* above stands; the *naming and the build plan* must reuse existing organs, not fork parallel ones (CLAUDE.md: reuse over reinvention; [[feedback-adr-cross-reference-discipline]]). Three bindings: 1. **`ServabilityDecision` / `ServabilityBlade` ⇒ advance ADR-0206 `core/response_governance/`, not a new object.** [ADR-0206](../adr/ADR-0206-response-governance-bridge.md) (the Response-Governance Bridge) already ships `ReachPolicy`, `govern_response`, and `shape_surface`, with `ReachLevel = STRICT < APPROXIMATE < EXTRAPOLATE < CREATIVE` and disclosure prefixes (`shape_surface` already emits `[approximate]`). It is gated **STRICT-only** today (`govern_response` returns `STRICT_POLICY`; `shape_surface` is the identity at STRICT) — which is *precisely* "the answer/refuse binary is the strict end of a spectrum" (§5). The SRV modes map onto `ReachLevel`; the SRV `risk → strictness` table is the policy ADR-0206 explicitly left as the future bridge. **Build SRV as the activation of that seam** — produce a widening `ReachLevel` under the reliability-gate license — not as a parallel `ServabilityDecision`. 2. **The `epistemic_state` Literals (§4/§5) ⇒ reuse `core.epistemic_state.EpistemicState`.** That ratified enum already carries the richer taxonomy (`DECODED`, `EVIDENCED_INCOMPLETE`, `INFERRED`, `UNVERIFIED_POSSIBLE`/`NOVEL`, `CONTRADICTED`, `AMBIGUOUS`, `UNDETERMINED`, … + reserved `VERIFIED`, `SCOPE_BOUNDARY`, `COMPUTATIONALLY_BOUNDED`, …), and `response_governance/policy.py` already partitions it into ACTIVE / RESERVED / RECONCILE. The six-value Literal drafted in §4/§5 is a parallel, smaller rename — **drop it and import the enum**; do not commit a new closed vocab ([[feedback-defer-substrate-vocab-commitment]]). 3. **`ProblemAttemptSession` ⇒ extend `core/comprehension_attempt/`, don't fork.** §4 already names this as the home; make it **binding**: firm up `ComprehensionAttempt`'s evidence shape rather than adding a parallel dataclass — and only extend the existing type, never shadow it. **First activation, already scoped.** The natural first widening past STRICT is the reserved `VERIFIED` state via a canonical-comparison pass — [`VERIFIED-canonical-comparison-scoping-2026-06-06`](../analysis/VERIFIED-canonical-comparison-scoping-2026-06-06.md) + ADR-0206 (`VERIFIED` is the only state that licenses widening past gold). The disciplined loop: **produce one reserved state → consume it through `govern_response`/`shape_surface` → prove the served mode on the capability-index yardstick → keep `sealed_eval` verified/refuse → repeat.** One state at a time, no bulk taxonomy expansion, no parallel policy object. > **Why the amendment, not a rewrite:** this is a session/research-trail doc; the original reasoning > is preserved intact above. The fault was a *missing cross-reference*, not a wrong idea — the > bindings here are what keep the next agent from building `ServabilityDecision`/`PRA` beside > ADR-0206 instead of inside it. ## Decision & sequencing - **Decided (doctrine, not yet ADR):** `wrong=0` ≡ **no false presentation of epistemic status** — a disclosure discipline. Serving becomes graded controlled disclosure; the answer/refuse binary is retained verbatim only at the strict end (`sealed_eval` / `safety_critical`). **This is the ADR-0206 `ReachLevel` spectrum, gated STRICT today** — see the Amendment. - **Decided:** typed + isolated candidate guesses are admissible at **practice time** (they already are, via the sealed lane + CMB; we are naming the law). - **Proposed:** `ProblemAttemptSession` (PRA) as the practice-lane evidence object; `ServabilityDecision` (SRV) as the serving-lane policy object. - **Sequencing (do not invert): PRA → REL → SRV.** The blade consumes candidate evidence, so it cannot precede the attempt layer. Data models may be drafted now (above); wiring waits. - **Preserved / not touched:** the wrong=0 verify gate, determinism/replay, the fail-closed safety/refusal path. The blade *consumes* these; it never weakens them. Any future wiring PR bundles `docs/specs/runtime_contracts.md` + contract-test updates (the surface contract changes shape), and gives the `context → admissible modes` table a meaningfully-failing test per branch (per the schema-defined-proof-obligation rule in CLAUDE.md). ## Open / next **Immediate (capability rung, unrelated to this doctrine — finish first):** the CMB ladder — **CMB-b** (exact solver, landed), **CMB-c** (reader), **CMB-d** (router/contemplation wiring), **CMB-e** (ledger) — plus the **R3-vac** oracle patch (port `_canonical_outcome` non-vacuous validation to `evals/rate_oracle`). None of these touch serving or this doctrine. **Then (this doctrine, as ADR-0206 activation — per the Amendment, reuse don't reinvent):** - **PRA** — firm the attempt evidence shape **on `core/comprehension_attempt/`** (extend `ComprehensionAttempt`: verified + eliminated candidates + residual ambiguity), reusing `core.epistemic_state.EpistemicState`. Not a new parallel dataclass. - **REL** — relevance / distractor grounding so `confidence_basis` is grounded, not asserted — consolidating the grounding that already exists (R2 referent guard, R1 distractor refusal, derivation `verify.py`, `epistemic_state_for_grounding_source`), not a greenfield organ. - **SRV** — **activate the ADR-0206 seam**: produce the reserved `VERIFIED` state (canonical comparison, scoping doc above) and let `govern_response`/`shape_surface` emit one widened `ReachLevel` for one measured case. Wire through the existing `shape_surface` (already the realizer-facing seam); unify `refuse_*` / `contradiction_report` under the existing refusal taxonomy. **Not** a parallel `ServabilityDecision`/blade. - **Yardstick gate (non-negotiable):** every widening shows a capability-index delta before it counts ([[milestone-agi-spine-A-to-E-complete]] discipline); `sealed_eval` stays verified/refuse. - **(Optional) second scorecard** — measure `over_refusal` / `mode_misclassification` as truthful- but-suboptimal, distinct from `wrong`, so over-refusal becomes visible debt. Must never alter sealed-eval scoring. - **ADR** — promote to an ADR (likely an **ADR-0206 amendment**, not a new ADR) *only* once a reserved state is produced, consumed through `govern_response`, and the `risk → ReachLevel` mapping is a closed, tested contract.