core/docs/decisions/ADR-0172-math-corpus-decomposition-mechanism.md
Shay eeeec80127
docs(ADR-0172): math-domain corpus-decomposition mechanism (Learning Arc analog) (#376)
* docs(ADR-0172): math-domain corpus-decomposition mechanism (Learning Arc analog)

Scoping ADR for the math-domain analog of cognition's
`teaching/contemplation.py` corpus-decomposition loop (Learning Arc
milestone 2026-05-25).

## What this ADR scopes

A mechanism that reads the math audit corpus and emits
`MathReaderRefusalShapeProposal` records — structural commonalities
across N refusal cases, paired with the candidate mechanism change
that would resolve them (matcher extension, injector sub-shape,
vocabulary addition, frame reclassification).

Today the operator does this decomposition by hand (reads
audit_brief_11.md, identifies the commonality across 21 DCS
refusals, scopes the matcher/injector extension, files a focused PR).
ADR-0172 shifts the decomposition to the engine, with HITL
ratification preserved.

## Sequencing — explicit

ADR-0172 ships AFTER ADR-0170 (injector contract widening),
ADR-0168 (FrameClaim handler), and ADR-0169 (CompositionClaim
handler — reserved). Without those substrates, the decomposer can
identify patterns but cannot route them to a ratification handler
that knows how to materialize them. Cognition's learning arc
followed this same sequencing: substrate first, then decomposer.

## Why this matters

ADR-0167 LexicalClaim shipped the math-domain wire from refusal →
evidence → operator-ratification. ADR-0172 closes the gap to the
engine-decomposes loop — the moment cognition's learning arc
qualitatively shifted from "engine refuses + operator authors" to
"engine teaches itself through reviewed correction."

The Learning Arc memory entry (2026-05-25) names that moment as
when measurable progress accelerated. ADR-0172 makes the math-domain
trajectory toward the same loop explicit in the queue.

## Hard invariants preserved

- wrong=0 by construction (proposals are evidence-only)
- ADR-0166: no new eval lanes
- No teaching-store / pack mutation
- No non-deterministic mechanism (rule-based grouping, not learned
  classification)
- Cross-domain partition (ADR-0167 W2-C) preserves cognition
  contemplation behavior

No code, no test, no eval, no pack change in this PR.

## Cross-references

- ADR-0056/0057 — cognition contemplation/proposal substrate (template)
- ADR-0167 + FOLLOWUPS §1 — parent evidence wire
- ADR-0168 + ADR-0168.1 — FrameClaim (ratification target)
- ADR-0169 (reserved) — CompositionClaim (ratification target)
- ADR-0170 — injector contract widening (substrate prerequisite)
- Memory: Learning Arc Milestone 2026-05-25 — the moment to recreate
- Thesis: decoding, not generating — the principle preserved

* amend(ADR-0172): add Tier 2 — intensional contemplation with test-and-learn loop

Per operator feedback during ADR-0172 review: the corpus-decomposition
mechanism should not only emit explicit rules (extensional) but also
develop inference (intensional) — recognizing structural equivalence
classes across surface variations without enumerating them.

## Tier 2 — intensional contemplation

Engine recognizes that 'Sam has 5 apples' and 'Sam collected 5 apples'
carry the same canonical proposition structure, without an explicit
verb-list extension. Emits MathReaderInferenceProposal records that
name structural equivalence classes rather than enumerable rules.

This is the thesis word the original draft missed: rationalization.
Tier 1 ratifies rules; Tier 2 ratifies inference.

## Test-and-learn loop

Tier 2 proposals carry held-out test evidence:
1. Decomposer surfaces hypothesis
2. Held-out subset of corpus reserved
3. Bridge applied to held-out cases; admissibility gates run
4. Outcome scored (positive / negative / neutral)
5. Negative-evidence proposals auto-rejected before HITL
6. Operator reviews proposal + test result, not bare claim

This makes Tier 2 thesis-coherent: engine decodes a structural
pattern, tests it against unseen corpus cases, surfaces the test
result. Wrong=0 cannot leak through — held-out test failures reject
internally.

## Updated implementation outline

Tier 1 wave: W1-W4 (schema, decomposer, CLI, workbench integration)
Tier 2 wave: W5-W9 (schema, equivalence-class recognizer, test-and-learn
loop, HITL integration, bridge application path)

## Hard invariants preserved at both tiers

- wrong=0 by construction (Tier 1: evidence-only proposals; Tier 2:
  held-out test rejects wrong-admitting bridges internally)
- ADR-0166: no new eval lanes
- No non-deterministic mechanism (rule-based grouping + deterministic
  test-and-learn, not learned classification)
- Cross-domain partition preserves cognition contemplation behavior

* amend(ADR-0172): split Tier 2 test-and-learn into two-arm confirmation

Per operator feedback during ADR-0172 review: 'confirm against known
facts/prior solutions' is the missing arm. The Tier 2 test-and-learn
loop now has BOTH:

- Arm 1 (negative / wrong=0 on held-out refusals) — already drafted
- Arm 2 (positive / known-good preservation) — NEW

Arm 2 inherits ADR-0057's replay-equivalence contract: any
inferential bridge that would change a currently-correct outcome is
REJECTED INTERNALLY before reaching HITL, even if the new outcome is
defensible. Existing truth survives; new truth is gated.

Both arms must PASS or be neutral. Either arm rejecting → proposal
does not reach the operator. This makes the engine's reasoning
provably conservative: it confirms against truth it already knows AND
truth it hasn't yet decided.

The 5-step proposal lifecycle is updated to reflect both arms +
test-set partition + per-case verdict tables in the emitted proposal.

No code change. No runtime effect.

* amend(ADR-0172): add foundational reasoning-articulation substrate

Per operator feedback: for the engine to infer/test/learn from
feedback, it must first be able to ARTICULATE its own reasoning in a
structured, persistent, replayable form.

Articulation is the project thesis's 5th anchor ("listen → comprehend
→ recall → think → articulate → learn from reviewed correction →
replay"). Today CORE articulates SURFACE (templated realizer output)
but does not articulate REASONING — the inference chain that took the
engine from refusal corpus to hypothesis to proposal.

Without reasoning-articulation, none of the three loops can work:
- Loop 1 (self-test) has nothing to record about what it tested or why
- Loop 2 (HITL review) sees a black-box conclusion, not inference chain
- Loop 3 (feedback) has no specific step the operator can target with
  a rejection rationale

## Substrate: ReasoningTrace schema

Every proposal carries a typed, content-addressable
ReasoningTrace recording each inference step:

  ReasoningStep:
    step_kind: observation | grouping | abstraction | hypothesis |
               test_design | test_application | test_result | conclusion
    input_pointers: prior steps + evidence rows
    claim: human-readable assertion at this step
    justification: why the engine made the claim
    output_payload: type-discriminated by step_kind

The trace is byte-identical across replays of the same corpus +
verdict history. Inherits CORE's existing determinism discipline.

## Sequencing

Articulation ships FIRST (new W0 wave) — it is the prerequisite for
Tier 1 and Tier 2 and Loop 3. Each downstream wave emits or consumes
ReasoningTraces.

## Hard invariants preserved

- Deterministic-replay (trace byte-identical under same inputs)
- ADR-0057 replay-equivalence (trace IDs stable across reruns)
- No non-determinism added (rule-based step emission, not learning)
- ADR-0166: no new eval lanes

No code, no test, no eval, no pack change in this PR.
2026-05-27 11:43:53 -07:00

29 KiB
Raw Blame History

ADR-0172 — Math-Domain Corpus-Decomposition Mechanism (Learning-Arc Analog)

Status: Proposed (scoping ADR; no runtime change in this PR) Date: 2026-05-27 Author: Shay Parent: ADR-0167 (audit-as-teaching-evidence) Related: ADR-0055/0056/0057 (cognition contemplation/teaching-chain proposal corridor), ADR-0168 (FrameClaim), ADR-0169 (CompositionClaim — reserved), ADR-0170 (injector contract widening), Learning Arc milestone 2026-05-25 Gating rule: ADR-0166


Context

The cognition learning arc (teaching/contemplation.py + teaching/proposals.py, completed 2026-05-25) closed this loop:

refusal → audit row → contemplation decomposes corpus →
engine PROPOSES teaching chain → operator ratifies → corpus extends →
next session admits what was previously refused

The load-bearing word is PROPOSES. The engine reads its own cognition corpus, decomposes it into discovery candidates with polarity / domains / evidence / sub-questions, and emits TeachingChainProposal records for HITL review. The operator's cognitive load is review, not invention. That was the moment the project shifted from "engine refuses + operator authors" to "engine teaches itself through reviewed correction."

The math domain has the same shape of data:

  • evals/gsm8k_math/train_sample/v1/audit_brief_11.json — 47 refusals grouped by refusal_reason × missing_operator
  • Structural commonalities are visible in the taxonomy: 21 cases hit discrete_count_statement with similar narrowness-violation patterns; 9 hit pre_frame_filler_sentence; 8 hit multi_quantity_composition; etc.
  • ADR-0167 wires refusal evidence into the existing contemplation corridor as MathReaderRefusalEvidence

What math does not have is the analog of cognition's contemplation decomposition: a mechanism that reads the refusal corpus and emits structural proposals (matcher extensions, injector sub-shapes, possession-verb additions, narrowness-rule relaxations).

Today the operator does this work by hand: read audit_brief_11.md, identify the structural commonality across N refusals, scope the matcher/injector extension, file a focused PR. That works but it's operator-as-decomposer, not engine-as-decomposer.

Foundational substrate — reasoning articulation

Before Tier 1 ships any proposal, the engine must be able to articulate its own reasoning in a structured, persistent, replayable form. Articulation isn't surface output (the realizer already does that); it's the chain of inferences that took the engine from refusal corpus to hypothesis to proposal.

The project thesis names articulation as the fifth step in the anchor sequence — listen → comprehend → recall → think → articulate → learn from reviewed correction → replay deterministically. Today CORE articulates surface (templated sentences via the realizer). It does not yet articulate reasoning.

Without reasoning-articulation, the three loops cannot work:

  • Loop 1 (self-test) has nothing to record about what it tested, what intermediate claims it made, or why
  • Loop 2 (HITL) reviews a black-box conclusion ("propose X") rather than the chain of inferences that produced X
  • Loop 3 (feedback) has no specific reasoning step the operator can target with a rejection rationale; "rejected because step 3 was unsound" requires reasoning step 3 to exist as a record

ReasoningTrace schema

Every proposal the decomposer emits carries a ReasoningTrace — a typed, content-addressable record of the inference steps that formed it.

ReasoningTrace:
  trace_id: str  # content hash of the step sequence
  steps: tuple[ReasoningStep, ...]

ReasoningStep:
  step_index: int
  step_kind: Literal[
    "observation",    # raw evidence pulled from the corpus
    "grouping",       # structural clustering of observations
    "abstraction",    # equivalence-class claim
    "hypothesis",     # candidate canonicalization / rule
    "test_design",    # what would falsify the hypothesis
    "test_application",  # bridge applied to held-out / known-good
    "test_result",    # scored outcome
    "conclusion",     # the proposal that emerges
  ]
  input_pointers: tuple[str, ...]  # IDs of prior steps / evidence rows
  claim: str  # human-readable assertion at this step
  justification: str  # why the engine made this claim
  output_payload: object  # type-discriminated by step_kind

Each step is content-addressable. The trace is byte-identical across replays of the same corpus + verdict history. Proposals carry the trace verbatim; operator reviews the trace, not the conclusion alone.

Why this is a substrate, not a Loop 4

Loops 1/2/3 each consume the reasoning trace:

  • Loop 1 emits a hypothesis step + test-design step + test-result steps as part of self-checking
  • Loop 2 (HITL review) displays the trace as the artifact under review
  • Loop 3 (feedback) attaches operator verdicts to specific step indices, so "rejected because step 3 was unsound" becomes machine-readable

Without the trace substrate, none of the loops have anything to operate on. The trace is the what gets articulated; the loops are what happens with the articulation.

Articulation requirements for Tier 1 and Tier 2

Tier 1 (extensional) emits traces with observation → grouping → hypothesis → conclusion steps. No tests are run; the proposal is a named rule, justified by structural commonality.

Tier 2 (intensional + test-and-learn) emits traces that include test_design → test_application → test_result steps for both arms. The trace is the full record of what was tested, against what subset, with what outcome, before the conclusion was reached.

Replay-equivalence under articulation

The reasoning trace is part of the proposal's deterministic-replay contract (ADR-0057). Same corpus + same verdict index + same decomposer code → byte-identical reasoning traces. This means:

  • An old proposal can be re-derived from scratch and the trace must match byte-for-byte
  • Operator verdicts pinned to specific step indices remain valid across replays because the step indices themselves are stable
  • A future decomposer change that breaks trace-byte-identity is detected by the existing replay-equivalence gate

The articulation substrate inherits CORE's existing determinism discipline — it does not introduce new non-determinism surface.


Decision — two tiers

Specify a math-domain corpus-decomposition mechanism that operates at two distinct rungs of engine-developed structural understanding.

Tier 1 — Extensional contemplation (rule-proposal)

Produce MathReaderRefusalShapeProposal records from the audit corpus. Each proposal:

  • Names a structural commonality across ≥2 refusal cases
  • Names the candidate mechanism change that would resolve the commonality (matcher extension, injector sub-shape, vocabulary addition)
  • Carries the audit-row evidence pointers (case IDs, refusal reasons, parsed_anchors)
  • Routes to HITL review through the existing teaching/proposals.py ratification flow
  • Is evidence-only: never auto-applied; ratification requires explicit operator action

This is the math-domain analog of cognition's teaching/contemplation.py::contemplate(). It does not duplicate the cognition mechanism; it sits alongside it, partitioned by candidate.domain == "math" (the discriminator W2-C shipped in #351).

Tier 1 emits rules: "extend possession_verbs to include collected", "add crayons to observed_counted_nouns", "widen DCS clause-split exception for trailing 'of'-clauses." Each proposal materializes as discrete code/pack changes after HITL approval.

Tier 2 — Intensional contemplation (inference)

Produce MathReaderInferenceProposal records that name a learned structural equivalence across surface variations — not an explicit rule, but a contemplated recognition that N sentences with surface differences carry the same canonical proposition structure.

For example, Tier 2 would surface a proposal like:

inference_id: math.inferential.acquisition_to_initial_state
structural_claim:
  "<ProperNoun> <verb-of-coming-to-possess> <count> <noun>"
  is canonically equivalent to
  "<ProperNoun> has <count> <noun>"
  for the purpose of initial-state extraction.
evidence_pointers: (5+ refusal cases across `collected`, `acquired`,
                    `received`, `bought` — verb varies, structure is
                    invariant)
ratification_effect:
  Add an *inferential bridge* in the reader/injector such that any
  sentence matching the structural claim canonicalizes to the
  reference form before extraction — without listing the specific
  verbs.
wrong_zero_assertion:
  Canonicalization preserves admissibility gates downstream; the
  bridge only changes what reaches the gate, not whether the gate
  fires. Multi-branch decision rule still refuses on disagreement
  between bridged and unbridged extraction.

Tier 2 is qualitatively different from Tier 1: it operates on structural equivalence classes rather than on enumerable rules. It is what makes capability scale — instead of authoring N FrameClaim handlers for N verb categories, the engine recognizes the verb-category dimension itself as a structural axis and proposes a canonicalization bridge that handles the whole axis at once.

This is what the project thesis ("decoding ... capacity to find, comprehend, and rationalize") asks for. Tier 2 IS rationalization: recognizing canonical form within surface variation.

Tier 2 test-and-learn loop — two-arm confirmation

Tier 2 does not emit raw inferential claims. It emits claims paired with empirical test evidence, deterministically generated by the engine before HITL review. The test has two arms — both must hold for a proposal to surface to the operator:

Arm 1 — Negative check (held-out wrong=0): does the hypothesis admit cases the engine has never seen without raising wrong>0?

Arm 2 — Positive check (known-fact preservation): does the hypothesis change ANY currently-correct outcome? Cases that admit correctly today MUST continue to admit with the same answer under the bridged extraction. A hypothesis that would alter a known-good outcome — even to a different-but-defensible value — is rejected. The engine confirms against prior solutions, not just against unseen data.

This is the mechanism that lets the engine confirm against known facts. ADR-0057's replay-equivalence contract is the inherited substrate: the engine's inferential bridges must pass the same replay-equivalence check ratified teaching chains pass.

For each proposed MathReaderInferenceProposal:

  1. Hypothesis emission. The decomposer surfaces a structural equivalence class from the refusal corpus.
  2. Test-set partition.
    • Held-out subset (e.g. 30% of the refusal corpus) — reserved from the evidence pointers that formed the hypothesis. Drives Arm 1.
    • Known-good set — every case currently in the admitted-with- correct-answer state across the canonical lanes. Drives Arm 2.
  3. Inferential application. The hypothesis is applied to both sets: bridged extraction → existing admissibility gates (_initial_admissible, roundtrip_admissible, multi-branch decision rule) → solver → verifier.
  4. Two-arm outcome scoring.
    • Arm 1 (held-out):
      • Bridge admits cases at the same answer as ground-truth → positive evidence
      • Bridge admits cases at a different answer than ground-truth → REJECTED INTERNALLY (would raise wrong>0)
      • Bridge produces no admissions → neutral evidence
    • Arm 2 (known-good):
      • Every currently-correct case still correct under the bridge → PASS
      • Any currently-correct case changes answer (even to a defensible value) → REJECTED INTERNALLY (would violate replay-equivalence)
    • Both arms must PASS or be neutral. Either arm rejecting → proposal does not reach HITL.
  5. Proposal-with-evidence emission. The proposal carries the structural claim AND both arms' test results AND the replay-equivalence hash AND the case-by-case verdict tables. HITL review verifies an empirically-tested hypothesis, not a bare claim.

The two-arm structure is what makes Tier 2 thesis-coherent. The engine isn't generating a hypothesis and asking the operator to bless it — it is decoding a structural pattern, testing against both unseen refusals and prior known-good outcomes, and presenting the operator with the test results as part of the proposal. The operator adjudicates the tests + the interpretation, not a bare claim.

This is also the wrong=0 safety net for Tier 2: any inferential bridge that produces a wrong admission in either arm is rejected internally before reaching HITL. The operator only ever sees proposals whose both arms confirm. Wrong>0 hazards cannot leak through Tier 2; nor can replay-equivalence violations of prior ratified work.

Tier 2 feedback-incorporation loop (Loop 3)

The two-arm self-test (Loop 1) plus HITL ratification (Loop 2) is not the full thesis loop. The project's anchor sequence — listen → comprehend → recall → think → articulate → learn from reviewed correction → replay deterministically — names a third loop: learn from the operator's verdict itself.

The engine must index every operator decision on a proposal and incorporate it into future decomposition. The verdict carries provenance:

ProposalVerdict:
  proposal_id: str
  proposal_shape_signature: str  # structural feature hash
  decision: Literal["ratify", "reject", "refine"]
  reviewer: str
  decided_at: str  # ISO timestamp
  reason: str | None  # optional free-text rationale
  refinement_payload: object | None  # when decision == "refine"

When the decomposer surfaces a new candidate proposal, it consults the verdict index:

  • Approved shape signatures — reinforce: similar future shapes surface with higher confidence
  • Rejected shape signatures — de-prioritize or suppress: future shapes structurally similar to a known-rejection do not re-surface unless the structural-similarity threshold is breached (configured per category)
  • Refined shape signatures — capture the gap between proposed and accepted; future decomposition tightens toward the refined form

Concrete example. The decomposer proposes:

"Extend possession verbs to include {collected, donated, gained}"

The operator ratifies {collected, donated} and rejects gained with reason: "gained is a delta-of-attribute (weight, age), not an acquisition-result; admitting it as initial possession risks wrong>0 on questions that ask total state."

Loop 3 indexes this as:

approved_shape: ACQUISITION_RESULT_VERB
  members: {collected, donated}
  signature: structural hash of (verb_class="acquisition", produces="possession")

rejected_shape: DELTA_OF_ATTRIBUTE_VERB
  members: {gained}
  signature: structural hash of (verb_class="delta", produces="state_change_not_possession")
  rejection_reason: encoded as structural feature

Next time the corpus contains acquired (acquisition-result shape), the decomposer surfaces it with higher confidence. If the corpus contains lost (delta-of-attribute shape), the decomposer flags it as structurally similar to a known-rejection and either de-prioritizes or suppresses.

This is not gradient descent. It is structured feedback memory: deterministic, replayable, auditable. Operator verdicts have full provenance; the index is content-addressable; the decomposer's consultation of the index is itself recorded in the proposal's provenance trail.

Why Loop 3 is load-bearing for the thesis

Without Loop 3, every session starts from zero on proposal-shape quality. Operators repeatedly reject the same shapes because the engine never learns the rejection structure. Over time, operator review becomes mechanical: the same kinds of bad proposals keep arriving. That violates the "learn from reviewed correction" anchor.

With Loop 3, the engine's proposal quality compounds. Each ratified proposal teaches it what good shapes look like for this corpus; each rejection teaches it what shapes the operator considers wrong-class. Operator effort over time shifts from "reject the same five things again" toward "review novel shapes the engine hasn't seen before." That is the thesis loop running.

Tier 2 wave update — Loop 3 deliverables

The wave outline below adds dedicated PRs for Loop 3 mechanics (verdict schema, structural-feature indexing, decomposer consultation). These ship as part of Tier 2, after Loop 1 and Loop 2 are operational — the verdict signal needs proposals to exist before it has anything to index.

Why both tiers, not just Tier 2

Tier 1 is concrete and tractable today. Tier 2 requires Tier 1's infrastructure (evidence pipeline, HITL queue, ratification handlers) to land first. Cognition followed this pattern: explicit teaching chains shipped before the contemplation-decomposer that proposes them. The mechanism needs somewhere to land; that has to be built first.

Tier 1 also produces real lift along the way — each ratified proposal lifts GSM8K cases. Tier 2's lift is harder to predict and more architecturally ambitious. Shipping Tier 1 first means the project always has visible progress even if Tier 2 takes longer to design.

Why this is not already what ADR-0167 ships

ADR-0167 LexicalClaim (shipped) handles one-word ratifications: the operator sees a lexicon_entry refusal and approves a pack addition. The engine doesn't propose the word; the operator picks it.

FrameClaim (ADR-0168, queued) and CompositionClaim (ADR-0169, reserved) handle structural pattern ratifications but still require the operator to choose which pattern from the audit data.

ADR-0172 is the rung above: the engine reads the audit corpus, recognizes a structural pattern across N refusals, and proposes the pattern itself. The operator's role shifts from "find the pattern, choose the category, ratify the claim" to "review the engine's proposed pattern, accept or reject."

This is exactly the rung the cognition learning arc occupied when it graduated from per-claim ratification to corpus-decomposition proposal.

Why this matters for capability

Without ADR-0172, every math sub-shape PR costs:

  • Operator time to read 21 refusal reasons and find the commonality
  • Operator design judgment to scope the matcher/injector extension
  • One focused PR per sub-shape, hand-authored

With ADR-0172, the engine surfaces candidate sub-shapes from the audit data. The operator reviews ~5 proposals per session instead of authoring ~5 sub-shape PRs. The proposals carry their own evidence, so review is structural verification rather than data archaeology.

This compounds: as the corpus grows (each refused case is a data point), the proposal mechanism gets more signal. Cognition saw this empirically — the learning arc accelerated after the first few ratifications because the corpus had more structural redundancy for the decomposer to recognize.

Provisional MathReaderRefusalShapeProposal shape

MathReaderRefusalShapeProposal:
  proposal_id: str  # deterministic hash of evidence + proposed change
  domain: Literal["math"]  # ADR-0167 W2-C discriminator
  shape_category: ShapeCategory  # which recognizer / refusal class
  structural_commonality: str  # human-readable description
  evidence_pointers: tuple[MathReaderRefusalEvidence, ...]  # ≥2 cases
  proposed_change_kind: Literal[
    "matcher_extension",     # widen narrowness rule
    "injector_sub_shape",    # new emission pattern in injector
    "vocabulary_addition",   # lexicon/pack entry (subsumes LexicalClaim)
    "frame_reclassification" # verb category change (subsumes FrameClaim)
  ]
  proposed_change_payload: object  # type-discriminated by kind
  wrong_zero_assertion: str  # explicit reasoning for why the change preserves wrong=0
  replay_equivalence_hash: str  # ADR-0057 contract

Each proposed_change_kind maps to a downstream ratification handler (the W2-D-shaped artifacts ADR-0167 et seq. produce). The proposal itself is purely descriptive — it does not modify anything.

Six open questions (must resolve in implementation ADR/PR)

  1. Decomposition algorithm: how does the engine recognize structural commonality? Naive approach: group audit rows by (refusal_reason, missing_operator) and emit one proposal per group above a minimum-evidence threshold (e.g. ≥3 cases). Deeper approach: cluster on extracted-anchor shape (e.g. all "proper noun + acquisition verb + integer + observed_noun" cases form one group regardless of which case_id they belong to).

    Recommendation: start naive. The cognition decomposer started that way too. Deeper clustering can ship later if the naive proposals don't carry enough signal.

  2. Minimum evidence threshold: how many refusals must share a pattern before a proposal is emitted? Cognition uses 2+; that's probably right here too. Lower threshold = more noise; higher = misses real patterns.

  3. De-duplication: how does the mechanism avoid re-proposing a pattern the operator already rejected? Cognition tracks rejected proposals; the same record needs to exist for math. Likely parallel to ADR-0167 W2-B's claim_signature mechanism.

  4. Wrong=0 evidence in the proposal: each proposal must carry an explicit wrong_zero_assertion — a written claim about why the proposed change preserves the invariant. This is the structural analog of cognition's "polarity + evidence" fields. The operator's review focuses on validating this assertion.

  5. Cross-domain partition: per ADR-0167 W2-C, the contemplation queue is partitioned by domain. ADR-0172 emits only math-domain proposals; the cognition contemplation continues to emit only cognition-domain proposals. The wire is parallel, not unified.

  6. Frequency: when does the decomposer run? On every audit regeneration? On operator command? On a CLI lane (core eval math-contemplation)? Cognition runs on-demand via CLI. That's the right starting pattern.

ADR-0166 three-question test

  • Q1 — Capability: A corpus-decomposition mechanism for the math domain, parallel to cognition's teaching/contemplation.py. The capability is mechanism, not measurement — it does not directly lift any GSM8K case but it changes who decomposes the corpus (operator → engine).
  • Q2 — Lane: Existing audit_brief_11.json is the input data. No new canonical lanes (ADR-0166 still gates). A new test lane in tests/test_math_contemplation_decomposition.py would pin proposal-emission for known refusal shapes.
  • Q3 — Invariant: wrong == 0 preserved by construction — proposals are evidence-only. The wrong=0 surface is the ratification handler (W2-D-shaped artifacts already exist for LexicalClaim; FrameClaim/CompositionClaim queued). ADR-0172 does not introduce new admission paths.

Sequencing — explicitly post-FrameClaim/CompositionClaim

ADR-0172 ships AFTER:

  • ADR-0170 (injector contract widening) — provides the substrate for sub-shape ratification handlers to emit CandidateOperation.
  • ADR-0168 (FrameClaim handler) — provides one of the ratification targets a math proposal can emit toward.
  • ADR-0169 (CompositionClaim handler — reserved) — second ratification target.

Without those substrates, ADR-0172 has nothing to propose against. The decomposer can identify patterns but can't route them to a ratification handler that knows how to materialize them. Sequencing matters here precisely the same way it mattered for cognition: the substrate (claim types, ratification handlers) had to land before the decomposer could pay off.

Implementation outline (subsequent PRs, not this one)

Substrate wave (ships first — required by Tiers 1 & 2 + Loop 3)

  • W0ReasoningTrace + ReasoningStep schemas in teaching/math_reasoning_trace.py, canonical-bytes serialization, content-addressable trace IDs, deterministic step-sequence ordering
  • W0.1 — Trace replay-equivalence test: same corpus + same verdict history → byte-identical trace

Tier 1 wave

  • W1 — Schema: teaching/math_contemplation_proposal.py with MathReaderRefusalShapeProposal dataclass (carries ReasoningTrace)
    • canonical-bytes serialization
  • W2 — Decomposer: decompose_audit(audit_path) -> tuple[MathReaderRefusalShapeProposal, ...] with naive grouping by (refusal_reason, missing_operator) and min-2 evidence threshold
  • W3 — CLI lane: core eval math-contemplation runs the decomposer and emits proposals to teaching/math_proposals/proposals.jsonl
  • W4 — Integration: workbench (ADR-0160) renders math proposals alongside cognition proposals; e2e test

Tier 2 wave (sequenced after Tier 1)

  • W5 — Schema: MathReaderInferenceProposal dataclass with evidence + both-arm test-result fields
  • W6 — Structural-equivalence-class recognizer: clusters refusal cases by parsed-anchor shape, surfaces candidate canonicalization bridges
  • W7 — Two-arm test-and-learn loop: held-out subset (Arm 1) + known-good preservation (Arm 2); both must PASS or be neutral
  • W8 — HITL integration: proposals reach the workbench only if both arms confirm; otherwise auto-rejected internally
  • W9 — Inferential-bridge application path: how a ratified bridge materializes in the reader/injector (likely a canonicalization pre-pass before extraction)

Loop 3 wave (feedback-incorporation; sequenced after Tier 2 W8)

  • W10ProposalVerdict schema + persistent index in teaching/math_proposal_verdicts/index.jsonl
  • W11 — Structural-feature hash for proposal shapes; verdict indexer hooks the existing ratification flow so every approve/reject/refine writes to the index
  • W12 — Decomposer consultation: pre-emission check against the verdict index; rejected-shape similarity threshold (configurable per category)
  • W13 — Operator-facing rationale capture: when a verdict is "reject" or "refine", the operator's stated reason is encoded as a structural feature attached to the rejection signature
  • W14 — Replay-equivalence test for Loop 3: same audit corpus + same verdict history → byte-identical future proposal stream

Each impl PR is small, focused, regression-tested. Cognition's parallel machinery is the template for Tier 1; Tier 2 is genuinely novel and will need its own design ADR before W5 ships.

What ADR-0172 does NOT do

  • It does not propose any non-deterministic mechanism (decomposition is rule-based grouping, not learned classification).
  • It does not add new eval lanes (ADR-0166 still gates).
  • It does not weaken wrong=0 — proposals are evidence-only, never auto-applied.
  • It does not change cognition's contemplation behavior (parallel wire, partitioned by domain discriminator).
  • It does not mandate that any specific proposal ship — operator retains full HITL authority.

Relationship to the Learning Arc

The Learning Arc milestone (2026-05-25) closed the cognition loop: refusal → audit → engine-decomposes → proposes → HITL → ratified corpus → next session admits.

ADR-0167 LexicalClaim partially closes the math loop: refusal → audit → engine-emits-evidence → operator-decomposes → operator-picks → HITL → ratified pack → next session admits.

ADR-0172 closes the gap: refusal → audit → engine-decomposes → proposes → HITL → ratified mechanism → next session admits.

That is the math-domain Learning Arc. The thesis test (thesis-decoding-not-generating) holds: the engine is decoding the structure of its own failures, not generating new content.

Cross-references

  • ADR-0055 — four-tier inter-session memory (the substrate this proposal-mechanism extends)
  • ADR-0056 — cognition contemplation loop (the direct template)
  • ADR-0057 — replay-equivalence contract math proposals must inherit
  • ADR-0167 — the parent evidence-wire ADR
  • ADR-0167-FOLLOWUPS §1 — the sub-type handlers ADR-0172 proposes against
  • ADR-0168 + ADR-0168.1 — FrameClaim scoping (one of the ratification targets)
  • ADR-0170 — the substrate widening that unblocks injector-extension proposals
  • [Memory: Learning Arc Milestone 2026-05-25] — the moment the cognition learning arc closed; this ADR is the math-domain analog
  • [Thesis: decoding, not generating] — the principle this mechanism preserves