Commit graph

473 commits

Author SHA1 Message Date
Shay
a58571d410 docs(audio): record teacher=scaffolding / serving-path-stays-Whisper-free boundary
Adds §9 subsection: a teacher is bootstrap scaffolding for the teaching phase,
not a production component (not ML distillation — CORE has no weights). Serving
path must never call a teacher. Production is Whisper-free conditioned on a
lawful runtime path: (A) words-as-text, or (B) matured deterministic
audio→lexeme decode. Flags the trap: teaching with a model does not auto-transfer
word-recognition into a 0-param engine. 'The teacher teaches; the lawful path
serves.'
2026-05-29 13:59:43 -07:00
Shay
c7290f5ab9 docs: start running model & dependency size tally
Living ledger of architecture/model/dependency footprint. Headline: CORE is a
0-parameter, 0-weight architecture (substrate is algebra, not weights), enforced
by the teacher versor-invariance test. Tracks: learned params (0), optional
teacher lanes (4 declared, all inert, no model size chosen), 10 Python runtime
deps (datasets dominates), 8 Rust crates, 0 weight files. Includes a Whisper
size reference for when/if a lane is wired, and an update-on-PR + changelog
discipline. Lives at docs/model_dependency_size_tally.md.
2026-05-29 13:51:30 -07:00
Shay
ae48a3cbf9 docs: audio section pipeline overview & primer
A from-the-ground-up reference for the audio modality: waveform → canonicalize
→ frames → acoustic lexer → typed AudioIR → operators/rotors → (32,) versor,
with every spec/constant grounded in the code (PR-2..PR-6 stack).

Includes the three-way clarification of learned models: embeddings (never),
audio specs (CORE's own DSP, not any model), text transcript (Whisper/NeMo as
typed labels only). Documents the substrate-vs-evidence split, the verbatim
teacher policy, current inert/gated status, and the 'scrutinise the consumer'
flag. Cross-links ADR-0180/0181 + spec + eval-plan. Lives at
docs/audio_pipeline_overview.md.
2026-05-29 13:47:31 -07:00
Shay
47a406b590
docs(adr-0163-f2): clarify refuse is maturity-relative — confusers are solvable coverage targets that graduate (#478)
A confuser's `expected: refuse` does not mean unanswerable. Every confuser carries
its true gold (`answer_numeric`) and is a solvable coverage target; `refuse` means
"the reader can't yet comprehend this category, so refusing is the honest outcome —
committing a WRONG value is the defect." Example: 0001 "buys a toy for 30 coins …
how many left?" is plain 50-30=20; it is refuse only because today's reader takes
`buys` as a gain.

Adds §2.1 (graduation protocol): when a general mechanism reads a category correctly
(validated on train_sample + the category, wrong=0 preserved), those cases graduate
refuse -> solve and committing their gold becomes a win. Reframes the `spurious`
verdict as "solved-before-graduation" (a graduation signal, with pair-consistency as
the genuine-reading-vs-surface-match discriminator), not automatically a defect.
Notes that no v1 category is degenerate, and how a truly-unanswerable case would be
labelled (answer_numeric: null + degenerate: true) so the two senses of "refuse"
stay distinguishable.

Spec only; no corpus/runner change (today's commits are wrong-reading, so spurious
stays flagged until a category genuinely graduates).
2026-05-29 13:23:02 -07:00
Shay
a8f9e3685d
docs(adr-0182): scope cross-composer disagreement pooling for distractor refusal (#474)
The confuser probe's two distractor-quantity wrongs (0014 ->300, 0016 ->3840)
have no clean tight fix: the `for` cue licenses both the 0014 distractor product
and the correct train-0021 product, and a target+foreign-unit refusal rule breaks
the canonical train-0003 boxes x erasers product. Telling a real multiplier from a
distractor by cue is the cue-precision problem ADR-0177 measured as not-yet-solvable
-- a tight rule here would be a reactive surface patch (the overfitting trap).

This ADR scopes the general, non-reactive alternative: let the wrong=0 DISAGREEMENT
rule do the refusing. Pool self-verifying candidates across composers so a blunt
product reading and a competing additive reading of the same problem disagree ->
refuse; legitimate products (0021/0003) have no competing reading, so they still
commit -- the structural property that distinguishes them, expressed without a cue.

Scoping surfaced two things a one-line plan would have missed:
- Completeness FORCES the distractor into every reading, so naive pooling changes
  nothing. The mechanism needs a narrow, commit-INELIGIBLE completeness exemption
  for isolated-foreign quantities -- it can only buy a refusal, never an answer, so
  the commit-path completeness guarantee (ADR-0175's 9->2 multi-step fix) is intact.
- MS-1 Target exposes the union of body unit-shapes, NOT the question's asked-for
  unit (verified). The exemption is therefore keyed to a reading's used-operand
  units, not an asked unit that does not exist.
- 0016's distractor sits in the anchor-position clause, so it needs distractor-aware
  anchor selection too: 0014 is the guaranteed win (wrong 5->4); 0016 lands (->3)
  only when anchor-skip is built. Doc declines to claim both before that is proven.

Spec only, no code. Sealed lane; serving 3/47/0 untouched.
2026-05-29 13:21:36 -07:00
Shay
62d9db7a7c docs(adr-0180): amend §1.5.3/§2.2 per T-1..T-4 findings
§1.5.3: content-addressed re-sort obligation is vacuous at compute_trace_hash
(folds vault_hits count, not contents); amend to apply at recall() result set
+ any future contents-bearing hash.

§2.2: Merge Kernel must content-address equal-score recall ties (multivector +
provenance bytes), not arrival/deque-index order — the general-path analog of
ADR-0181 §2.2's audio merge key.

Both sharpen the substrate ahead of the vault.rs LocalArena/SemilatticeDelta
refactor; neither blocks it. Sourced: docs/audit/ADR-0180-t1-t4-findings.md.
2026-05-29 12:20:54 -07:00
Shay
d95f8a99e0
docs: session wrap-up (comprehension chaining + overfitting discipline) + CLAUDE.md substrate (#472)
- New session record SESSION-2026-05-29-comprehension-and-overfitting-discipline.md:
  the reconciliation wave, CP-1/CP-2a (no cue reliable yet -> structure-first),
  GB-3a referent guard, GB-3b.1 accumulation (practice 0->55), the GB-3b.2
  overfitting course-correction (96/150 synthetic vs 1/50 real -> torn down), and
  the confuser corpus (baseline: 7 defects surfaced). Serving 3/47/0 throughout.
- Lands the prior dangling SESSION-2026-05-29-multistep-build-arc.md (was untracked).
- CLAUDE.md "Current Key Modules": adds the sealed GSM8K comprehension substrate
  (core/reliability_gate, generate/derivation, generate/cue_precision,
  evals/gsm8k_math {train_sample,practice,confusers}, the lane-SHA gate).
2026-05-29 11:18:27 -07:00
Shay
a67b475e59
docs(adr-0173): accept workbench ratification trust boundary (W0); queue reconciled W3 corridor brief (#469)
Flip ADR-0173 Proposed -> Accepted. This is the W0 gate for the
workbench-UI ratification wave: it amends ADR-0160's read-only stance
narrowly to admit operator-driven invocation of the three existing,
replay-gated Tier 1.5 handlers (apply_lexical_claim, apply_frame_claim,
apply_composition_claim) as a local keyboard accelerator over ADR-0161
Surface C. No UI code; implementation remains gated to the W1..W4
acceptance gates in the ADR.

Also lands the reconciled W3 ratification-corridor brief. It supersedes
the stale W3 section of WORKBENCH-UI-WAVE-BRIEF-PACK.md, which assumed a
'frontend zero' state (W1/W2 already merged via #295/#299/#329/#327/
#328/#303) and prescribed a Zustand store this repo never adopted. The
reconciled brief names the load-bearing facts the old one glossed:
- /ratify is advisory-only today (routes, never applies); W3's core
  backend task is the advisory->in-process flip.
- live proposals carry shape_category='uncategorized', so the safe
  category/polarity must be operator-supplied and allowlist-gated, not
  hard-coded -- the exact silent-wrong-category path case 0050 guards.

Verification this session: read-only workbench v1 confirmed working
(API serves real deterministic data, honest 404s, traversal rejected,
ratify advisory/no-mutation; 31 python + 104 UI tests green; pnpm build
green).

No runtime/algebra/eval paths touched. Docs only.
2026-05-29 11:14:25 -07:00
Shay
31d9cb429d
docs(adr-0163-f2): confuser corpus spec — a discrimination probe, not a coverage target (#468)
Follow-on to ADR-0163 §F that corrects the metric exposed by the overfitting
finding (96/150 synthetic flips vs 1/50 real; the 0002 cable/fraction problem read
as accumulation -> 996). Specs a small, hand-curated, real-sourced set of hard
negatives + near-miss confusers (disguised-polarity verbs, pseudo-accumulation
fractions, multi-referent/multi-actor, distractor quantities, temporal/question-
scope, comparative-referent, unit confusers) with minimal-pair construction.

Scored the opposite way from a coverage lane: success = wrong=0 on confusers +
pair-consistency + honest refusal frontier, NEVER solved-count. Held-out by
contract (not a training-to-fit target); the CP ledger consumes the wrong attempts
as the hard negatives the templated corpus lacked. Guardrails forbid reactive vocab
growth and template expansion.
2026-05-29 11:13:53 -07:00
Shay
274c81ea37
docs(adr-0178-gb3b): scope referent-aware accumulation chaining (#464)
Grounded scope for GB-3b, the next Gap B move. Measured opportunity: 46/150
additive practice cases are sum-of-all==gold, all currently refusing, all the
single-referent accumulation shape ('X has N. He buys M more.' -> N+M). They
refuse correctly (GB-3a's multi-clause guard / the Alice+Bob hazard); the safe
ones differ by referent identity + a change-verb cue, which GB-3b reads.

Scope covers: the reading (anchor + change steps), the wrong=0-critical referent
model (minimal no-new-actor guard; cross-references ADR-0164.2/.3 + ADR-0174's
multi-actor hazard; deliberately does NOT resurrect the retired gender-blind
resolver), the proof-carrying wrong=0 obligations, the cue-precision coupling
(change cues should finally be reliable, closing CP-2a), the increments, and
honest flip expectations (big chunk in practice-additive; modest train_sample;
serving stays 3/47/0 until ratification).
2026-05-29 10:41:54 -07:00
Shay
cecf7b82cc
test(adr-0180): T-1..T-4 Delta-CRDT pre-refactor obligations (Python, green) (#463)
ADR-0180 §1.5.4 + CLAUDE.md work-sequencing item 5 require these four
properties green on main before any core-rs/src/vault.rs change. They are
also the foundation ADR-0181 PR-5 (audio Delta-CRDT wiring) rides on.

  T-1  set-equality of vault writes under shuffled ingest (+ idempotent
       re-ingest at the content-addressed layer)
  T-2  trace-hash invariance to vault order, + recall result-set invariance
       to insertion order (the genuinely-failable half)
  T-3  versor_apply non-commutativity (negative guard)
  T-4  ProjectionHead.project purity across calls and threads

Findings (docs/audit/ADR-0180-t1-t4-findings.md):
- compute_trace_hash folds only vault_hits (a count), NOT vault contents, so
  ADR-0180 §1.5.3's "re-sort vault state in content-addressed order" is
  currently vacuous at the trace-hash layer; the live order-invariance
  obligation is at recall() (result-set + count). Recommend amending §1.5.3.
- equal-score recall ties are index-sensitive; the Merge Kernel needs a
  content-addressed tiebreak (mirrors ADR-0181 §2.2 merge key). Recommend
  amending §2.2.
- append is genuinely semilattice-eligible; versor_apply is non-commutative.

7 passed; smoke suite green. No runtime/core mutation — tests + audit only.
2026-05-29 10:40:52 -07:00
Shay
7451e7cd74
feat(adr-0177-cp2a): cue-precision ledger training + measurement (+ unit hygiene) (#461)
CP-2a populates the CP-1 ledger from gold-labelled candidate readings and reports
per-pattern reliability — the measurement the cue-precision thesis rests on. Plus
the function-word unit filter, whose value this measurement makes concrete (clean
unit_shape labelling).

What landed (all sealed; serving 3/47/0 byte-identical):
- generate/cue_precision/trainer.py — train_from_cases(cases, enumerators): folds
  gold-labelled candidate chains into the ledger via record_case. Decoupled (the
  candidate enumerators are injected, so the package still imports nothing from
  search). candidates_for dedupes a reading shared by two enumerators.
- generate/derivation/multistep.py — extracted the enumeration half of search_chain
  into public candidate_chains(problem_text); search_chain now delegates (verified
  byte-identical: ms3 tests + practice counts unchanged). CP-2 needs the readings
  the search weighs, not just the one it resolves.
- generate/derivation/extract.py — function-word unit filter (_NON_UNIT_WORDS):
  blanks spurious function-word units ($0.75 each -> "", 3/4 of -> "") that
  corrupt same-unit detection and unit_shape. Closed lexeme set, ADR-0165-safe.
- evals/gsm8k_math/practice/v1/cue_precision_report.py — trains over 200 sealed
  cases (50 train_sample + 150 ADR-0163-F additive) with the real enumerators and
  prints the per-pattern reliability table.
- tests/test_adr_0177_cp2a_training.py — trainer obligations (credit/dedupe/
  determinism/empty) via synthetic enumerators; real-measurement well-formedness;
  search_chain parity.

Load-bearing finding (recorded in ADR-0177): over 200 cases EVERY (cue,op,unit_shape)
pattern floors at ~0.0 reliability (best: for-multiply-cross_unit 0.0116 at 2/34).
The blunt product/sum-of-all readings are almost always wrong vs gold, so the
conservative floor correctly trusts nothing. => CP-2b (trust reliable cues) is
blocked on candidate GENERATION, not the ledger: candidate readings must get less
crude (clause/referent structure, ADR-0178 GB-3b) before any cue earns reliability.
Cue-precision and compositional structure are coupled; structure comes first.

Verification: 107 targeted tests green (CP-2a/CP-1/extract/ms3/GB-1/2/3/MS-1/2) +
architectural invariants; serving CLAIMS.md sha unchanged; practice 4/1/45 and
0/1/149 unchanged. Inert: trains/reports only, consulted by no search/gate.
2026-05-29 10:21:58 -07:00
Shay
fd96074230
docs(adr-0181): propose CORE-native audio compiler over Delta-CRDT substrate (#462)
Maps the AssetOverflow audio-compiler proposal onto the existing
sensorium ProjectionHead boundary (ADR-0013) and the Delta-CRDT
sharded substrate (ADR-0180).

Core mapping decision: the audio chunk boundary IS the CRDT delta
boundary. In-chunk rotor composition (compile_events) is the explicit
serialization barrier ADR-0180 §1.5.2 requires for non-commutative
versor_apply; the resulting AudioCompilationUnit is the order-invariant
delta written at the only semilattice-eligible layer (vault/store).
The compiler's checksum chain supplies the content-addressed merge key
(canonical, ir, projection sha256) that ADR-0180 §1.5.3 demands, making
idempotence structural and the sequential==concurrent trace-hash proof
checkable.

Adds:
- docs/decisions/ADR-0181-audio-compiler-delta-crdt.md (decision + mapping)
- docs/plans/audio-compiler-spec.md (typed AudioIR, operator table,
  manifest, numeric determinism, delta interface)
- docs/plans/audio-compiler-eval-plan.md (corpus, gates, A-1..A-6 CRDT
  proof obligations, teacher-migration policy)

Docs only; no runtime/core mutation. PR-2..PR-6 substrate work sequenced
in the ADR, with PR-5 gated on ADR-0180 §1.5.4 (T-1..T-4) green on main.
2026-05-29 10:19:54 -07:00
Shay
b1416814ea
docs(adr-0180): propose CRDT-sharded vault concurrency substrate (#457)
* docs(handoff): parallel-work plan post-GB-3a (CP-1 / scale / EX-3 tracks)

Three disjoint-file tracks dispatchable in parallel with Claude's serial Gap-B
line; records the hard constraint that GB-3b/4/5 are serial on compose.py.

* docs(adr-0180): propose CRDT-sharded vault concurrency substrate

Drafts ADR-0180 (Proposed) for a Delta-CRDT sharded substrate to support
forthcoming multimodal ingestion (vision, kinematics) without serializing
on a global Vault lock.

§1.5 grounds the proof obligation against the existing single-threaded
Python ingest path (sensorium → ingest/gate → field → vault/store →
compute_trace_hash) and enumerates four pre-refactor test obligations
(T-1..T-4) that must be green on main before any change to
core-rs/src/vault.rs lands, per CLAUDE.md work-sequencing item 5.

§1.5.5 explicitly fences out: approximate recall (exact CGA recall is
non-negotiable), hidden background execution (Merge Kernel must be
explicitly mounted with telemetry), and MLX/UMA hardware optimization
(deferred to a follow-up ADR; CPU-only Rust path lands first).

Proposed only — no code changes to core-rs, sensorium, or field.
2026-05-29 09:42:01 -07:00
Shay
5c1e9e7fe4
feat(adr-0178-gb3a): clause-scoped referent guard — refuse cross-clause aggregation (#456)
The mandated lookback review before GB-3 (CLAUDE.md §Lookback Review Discipline)
confirmed the audit's hazards H1/H2/H3 were LIVE: compose_sequential summed
same-unit quantities from the whole problem, merging unrelated referents/scopes
and admitting wrong structures whose value happened to ground:
  H1 (second actor's apples)      -> 6+4+2  = 12
  H2 (comparative on other actor) -> (6+4)*2 = 20
  H3 (later depletion event)      -> 6+4+3  = 13

Root cause is the audit's G1/D2 drift: GB-2a re-extracts from the whole text and
ignores GB-1's clause structure. The fix is the GB-3 increment — make the composer
clause-scoped (consume segment_clauses), refusing when the licensed structure spans
clauses, because this slice cannot model referents:
  - quantities must live in exactly ONE clause (0 or >1 -> refuse);
  - a comparative outside that clause -> refuse (unmodelled referent binding).

All three hazards now refuse; all 7 GB-2 single-clause structures preserved
(list-sum, three-item, sum-then-scale, and the mixed-unit/disagreement/too-few
refusals). tests/test_adr_0178_gb3_referent_guard.py would fail against the
pre-guard code (12/20/13), so the obligation is proven, not decorative.

Scope/safety:
- compose_sequential is sealed substrate, not wired to a scorer -> serving
  byte-identical 3/47/0 (lane-SHA 8/8, generate_claims --check OK); practice
  unchanged 4/1/45. No new test failures (2 pre-existing on main).
- ADR-0178 amended: GB-2 relabelled GB-2a (list slice, drift G1 recorded);
  GB-3 split into GB-3a (this referent guard, landed) and GB-3b (constructive
  cross-clause chaining, next).
2026-05-29 09:15:52 -07:00
Shay
38ef66c2a9 docs(backlog): capture everyday-atoms grounding pack idea (closed #449)
#449 shipped an inert, duplicated, unvalidated pack off-brief; closed it but kept
the on-thesis idea (ground the nouns GSM8K problems use) with the real scope it
would need to be beneficial.
2026-05-29 08:55:08 -07:00
Shay
65d857e72a
feat(adr-0179): integrate EX-1/EX-4/EX-5 extraction richness (sealed lane) (#455)
Reconciles ChatGPT's four independently-branched extraction PRs (#451/#452/
#453/#454) into one coherent generate/derivation/extract.py. They each rewrote
the same file + same new test off main, so they conflicted pairwise and needed
integration, not a merge.

Integrated (span-tracked, most-specific-pass-first so numbers are never double
counted):
- EX-1 word-numbers (#452): reuses WORD_NUMBERS; tens-one hyphen compounds;
  factor-bearing half/third/quarter excluded.
- EX-4 list-unit inheritance (#451): bare numeric list with one trailing unit.
- EX-5 sentence-final numbers (#454): bare final number with empty unit.

Deferred: EX-3 multi-word units (#453). Its greedy lowercase span reads
"6 apples and 4 apples" as unit "apples and", regressing GB-2's
test_same_unit_list_sums, and still can't recover real multi-word units from
0024-class text ("jumping jacks on"). Needs a tighter rule; see
docs/handoff/AUDIT-ADR-0179-EX-RECONCILE.md.

Verification (sealed lane only; chat/ does not import this module):
- Serving frozen: lane-SHA 8/8 match, generate_claims --check OK -> 3/47/0
  byte-identical, wrong=0 held.
- Sealed practice improved 4/2/44 -> 4/1/45: case 0025 flips wrong->refused.
  EX-1 reads "three", so completeness sees a quantity the 6x50 chain omits and
  refuses the spurious 300 (gold 1200) instead of committing it.
- No new test failures (3 pre-existing on main).

Also fixes stale test drift from EX-2 (#447): TestDecimalGroundingGapIsDeferred
asserted decimals still refuse, but #447 made $0.75-class resolve to 864.
Renamed to TestDecimalGroundingResolves and updated to assert the flip.

Honest scope note: EX-4 does NOT unblock real case 0024 (its PR test used a
fabricated bare-list paraphrase). TestRealCase0024StillBlocked pins the true
boundary.
2026-05-29 08:43:03 -07:00
Shay
e7032f9e0a
audit: ADR-0178 GB-1/GB-2 lookback (findings only — no code change) (#450)
* add audit report

* docs(audit): expand ADR-0178 GB-1/GB-2 lookback report
2026-05-29 08:42:58 -07:00
Shay
fbcefba00c
docs(adr-0179): scope extraction richness — the prerequisite that unblocks coverage (#446)
The recurring wall every recent measurement hit: the structure machinery (MS-3,
GB-1, GB-2) is built but STARVED by thin extraction. extract.py's digit+single-word
regex loses word-numbers ('three'), multi-word units ('jumping jacks'), currency/
decimals, sentence-final numbers, and mis-attributes units ('36 on Tuesday'->'on',
which blocks GB-2 same-unit list-sum on 0024).

Two layers, very different risk:
(A) sealed derivation extractor (extract.py) — safe to enrich (over-extraction is
caught by the gate's completeness+grounding+uniqueness; refuse-preferring). Bulk
lives here.
(B) shared grounding primitive (_value_grounds/_tokens) — wrong=0-sensitive (serving
round-trip uses it). EXACTLY ONE change: bare-decimal grounding ('N.M' grounds when
digit-runs N,M appear — symmetric with existing .NN/N/M logic), wrong=0-gated by
serving 3/47/0 byte-identical (lane-SHA gate). _value_grounds already handles /bin/zsh.75
but the extractor strips the $ -> bare 0.75 fails; that's the 0003 gap.

Reuses en_numerics_v1 + WORD_NUMBERS (word-numbers) + existing currency/fraction/
compound grounding (ADR-0128/0131.G.3) — extends, never reinvents. Lexeme-level
(ADR-0165). Sub-phases EX-1 word-numbers, EX-2 currency/decimal + grounding fix,
EX-3 multi-word units, EX-4 list-unit inheritance (unblocks 0024), EX-5 sentence-
final, EX-6 measure.

Honest payoff: unblocks BUILT capability — uniform units -> GB-2 list-sum fires
(0024); decimals -> MS-3 product flips (0003); word-numbers -> comparatives resolve;
new gold-matching chains -> feed cue-precision (0177's bottleneck). Flip-curve
should finally move on extraction-blocked cases; op-ambiguity + scale still gate the
rest. wrong=0 obligations: serving byte-identical after the grounding fix; over-
extraction refuse-preferring; determinism.
2026-05-29 08:42:54 -07:00
Shay
8807d29f50 docs(handoff): remote-work brief for ChatGPT connector (audit GB-1/GB-2 + ADR-0179 sealed extraction) 2026-05-28 17:44:48 -07:00
Shay
5dacc6625e
Merge pull request #443 from AssetOverflow/docs/adr-0178-compositional-structure
ADR-0178 (Proposed): Compositional Structure — comprehension-guided multi-step (Gap B)
2026-05-28 17:15:52 -07:00
Shay
9a7f9f6a66 docs(adr-0178): scope Gap B — comprehension-guided compositional structure
The actual coverage lever (ADR-0177 established cue-precision is its gate+prune,
not the unlock). Gap B = which quantities group via which ops in what order.

The reframe that resolves the rich-search-vs-uniqueness tension: structure-from-
READING, not enumeration. The text encodes its own structure — every gold case
fits a sequential clause-by-clause read (0021 one clause 15x10x3; 0003 48 ->x24
->x0.75; 0024 sum ->x3; 0033 seq chain + branch). So Gap B is comprehension: read
the problem, build the derivation structure as you read, hold alternatives on
ambiguity, reevaluate on lookback. This IS the project's original 'word-to-word
with lookback + problem-solving throughout' articulation, and the synthesis of
reader (0174) + solver/gate (0176) + learning (0177) + packs.

Decision: a comprehension-guided sequential composer — clause-local bounded
sub-derivations combined across clauses via relational cues (per/each/of->multiply,
and-list->sum, comparative->scale, more/older->add, fewer/less->subtract), held-
hypothesis on ambiguity + eliminate/reevaluate (REPOINT ADR-0174's inert reader
substrate from parse to STRUCTURE — where it finally becomes load-bearing), scored
by the 0176 self-verification gate + uniqueness, guided by 0177 cue-precision.
Locality bounds the search; relational cues constrain the cross-clause op so
uniqueness can RESOLVE (not just refuse). Coverage rises only as far as the reading
constrains structure; irreducible ambiguity refuses (wrong=0).

wrong=0 obligations: per-step self-verification, irreducible-ambiguity-refuses,
completeness+uniqueness over the whole structure, no-spurious-structure, determinism,
sealed. Honest hard parts: relational-cue precision (co-dependent with 0177 +
data-starved), clause segmentation, referent binding, branch/DAG (0033 quantity
reuse, GB-5), scale. This is the comprehension core — largest remaining capability;
serving lift materialises here, incrementally. Sub-phases GB-1..GB-6.
2026-05-28 17:06:35 -07:00
Shay
b57e5dca9a docs(adr-0177): scope cue-precision learning (the self-supervised half)
The lever MS-1->MS-3 proved: learn which (cue->op) readings are reliable from
practice eliminations, closing ADR-0175's self-verification 'necessary-not-
sufficient' gap before Phase 5.

Mechanism: per-(cue, op, unit_shape) reliability ledger (reuses ADR-0175 ClassTally
+ conservative_floor), fed by gold-labelling search candidate chains. Three uses:
U1 self-verification TRUST (near-term value: makes the Phase 5 proposal gate honest;
cold ledger => refuse, no junk proposals), U2 search guidance, U3 disagreement
resolution (coverage lever, hard-gated: margin+theta, ties refuse).

Load-bearing honesty (the bottleneck): a pattern earns POSITIVE signal only from a
gold-MATCHING chain; current blunt shapes match gold for ~4/50 cases, so the ledger
is starved (all-blame) AND structure failures (Gap B) pollute cue->op credit (a
correct op penalised for a product-of-ALL structure error). Plus data starvation
(50 cases << N_min). So cue-precision is COUPLED to richer guided shapes (Gap B) +
scale; it co-evolves (Gap B supplies gold-matching candidates -> cue-precision earns
signal -> prunes Gap B's search). It is the TRUST substrate + pruning engine, NOT
the coverage unlock by itself.

Recommended sequencing: CP-1/CP-2 (mechanism + self-verification trust, near-term
correctness value) now; richer guided shapes (Gap B) next as the flip lever; scale
makes it compound. wrong=0 obligations: cold=>no regression, ties refuse, theta-gated
serving, credit-noise can't flip serving (floor+N_min+margin+ratification+gold-tether),
determinism. Sub-phases CP-1..CP-4.
2026-05-28 17:00:33 -07:00
Shay
68e6cbd4ef docs(adr-0176): scope multi-step grounded composition with question-targeting
The dominant remaining lever for serving lift (79% need mul, median 3 steps;
single-step search + completeness flips only 0021). Grounded in gold step
structures: derivations are CHAINS with intermediate results as operands;
quantities come from body AND question (0033's '25'); several need comparatives
(half/N-times).

Decision: bounded, deterministic, TARGET-GUIDED multi-step grounded derivation
search, gated by ADR-0175's strengthened self-verification (grounding ∧ cue ∧
unit ∧ completeness) + uniqueness + a new question-target match. Sealed practice.

Two new ideas beyond 0175: question-targeting (turn the question into a target =
search-pruning + stopping criterion) and multi-step chaining (intermediates as
derived operands). Sub-phases MS-1..MS-5, wrong=0-first (gate/target before broad
search). Invariant #2 extended to chains. Honest hard part: search explosion +
uniqueness refuses most -> target-pruning + cue-guidance + depth-bound are the
tractability levers; low coverage initially; comparatives pack is a prerequisite;
serving lift still waits on 0175 Phase 5 ratification. Reuses solver +
question extraction + round-trip primitives.
2026-05-28 16:00:00 -07:00
Shay
dd6064065f
Merge pull request #431 from AssetOverflow/feat/adr-0175-calibrated-learning
ADR-0175 (Proposed): Calibrated Attempt-and-Eliminate Learning — two regimes under wrong=0
2026-05-28 15:43:15 -07:00
Shay
5ecfda3fab docs(adr-0175): record Phases 1-3b lookback review
Solid: 4 invariants proven by failing-under-violation tests; 84 green; seal
verified. No live hazards (9 search wrongs are sealed eliminations).
Drift: (1) 3a gate is PARTIAL vs spec — round-trip + no-contradiction not wired;
3b's necessary-not-sufficient finding follows -> a self-verification-strengthening
phase must precede Phase 5. (2) class taxonomy: Phase 2 uses gold operation-class
not capability-axis. (3) minor defensive-branch test gaps (no risk).
2026-05-28 15:34:21 -07:00
Shay
13d016c90b docs(adr-0175): pre-implementation audit — correct reuse overclaims, record findings
Lookback/cross-reference audit before any code. No hard blockers. Corrects 3
overclaims of reuse and records the audit:
- reliability ledger is NEW (calibration/ is a grid-search param tuner, not a ledger)
- 0174 eliminate/reevaluate/contemplate is reading-coupled -> 'repoint to solving'
  needs generalization, not drop-in reuse
- teaching corridor evidence (MathReaderRefusalEvidence) is reader-refusal-coupled
  -> solver-practice proposals need a new evidence type
Constraints recorded: wrong=0 pinned on serving lane by ~25 tests + train_sample
runner -> practice MUST be a separate lane (phasing updated). Alignments noted:
ADR-0165 (lexemes-not-grammar) fulfilled by thin-front-end/thick-solver split;
INV-07 governance = no-self-authorization pre-wired; MAX_TOTAL_BRANCHES precedent
for bounded deterministic search; seal exists.
2026-05-28 14:55:53 -07:00
Shay
e3c28773ff docs(adr-0175): pin conservative_floor (Wilson lower bound) + N_min
Resolves Open Question #1. conservative_floor(s,k) = one-sided Wilson lower
bound over COMMITTED trials (k=correct+wrong; refusals excluded so coverage
never penalizes reliability). Constants: z=2.576 (single global pessimism
knob), N_min=10. Range [0,1) — never returns exactly 1.0. float64 rounded
half-to-even to 1e-9 for cross-backend replay. z (estimator skepticism) and
per-class theta (action's required reliability, human-set) are independent
dials; engine touches neither. Worked cost-to-clear table + asymmetry example
included.
2026-05-28 14:51:50 -07:00
Shay
8c2e469be0 docs(adr-0175): calibrated attempt-and-eliminate learning architecture
Proposed ADR + session derivation doc capturing the 2026-05-28 design
discussion that took GSM8K Phase 5b from 'build another matcher' to a
self-calibrating problem solver.

Session doc (docs/sessions/SESSION-2026-05-28-...): the full journey —
problem (per-shape matchers can't compound; 79% need mul, 0% single-step),
dead-ends (brute-force spurious matches; 0021 is the only single-sentence
case and it's idiosyncratic), and the four pivots that converged on the
solution.

ADR-0175 (Proposed): the decision —
- two regimes: serving (wrong=0, unchanged) vs sealed practice
  (attempt-and-eliminate; wrong is the learning signal)
- proof-carrying seal: practice never writes serving; ratification only
- deterministic attempt/refuse gate: reliability(C) / theta_required >= 1
  (NOT RL; regimes collapse the reward side so only reliability is quantified)
- per-class calibration ledger of replayable COUNTS + conservative lower
  bound; human-set theta ceilings raised only on evidence
- checkability ladder (gold > convergent self-verification > consistency-only),
  privilege proportional to reversibility; provenance + gold tether against
  correlated self-delusion
- diagnostic refusal routes skill vs knowledge vs ambiguity; three
  compounding stores (vault/packs/pruning); self-proving acquisition narrows
  human input without bypassing the gate
- five proof-obligation invariants (wrong=0 on serving, no spurious banking,
  determinism, no self-authorization, retractability)

Supersedes the matcher-oriented ADR-0174 5b sub-phases; repoints the
0174 eliminate/reevaluate/contemplate substrate from reading to solving.
Open question: shape of conservative_floor + N_min.
2026-05-28 14:45:17 -07:00
Shay
5830c1fb8c docs(adr-0174): write Phase 5b scope — operation-capability buildout
Grounded in a ground-truth measurement of the 47 train_sample refusals
against GSM8K's own <<a*b=c>> calculator annotations:
- 37/47 (79%) use multiplication; 43/47 use mul-or-div; 0/47 single-step
- multiplication is the foundational general capability (breadth = the
  anti-overfitting signal), but necessary-not-sufficient: no case flips
  from an operation matcher alone

Solver already supports {add,subtract,transfer,multiply,divide,apply_rate,
compare_additive,compare_multiplicative}; the gap is the reader->injector->
Operation front-end (matcher extracts 0 anchors on real sentences).

Sub-phase sequence (biggest-chunk-first, measure-the-flip-gated):
- 5b.1 single-sentence multiplicative aggregate (cleanest proof, ~2-4)
- 5b.2 shallow 2-3 step composition (25/47, the real chunk)
- 5b.3 deep multi-step 4-7 (22/47) under held-hypothesis elimination
Generality guard: flipped cases must hold under ADR-0114a perturbation/OOD.
Explicitly NOT widening discrete_count injector (overfitting + wrong=0 hazard).
2026-05-28 13:48:58 -07:00
Shay
3fd317290b feat(adr-0174-phase5a): retire inert GSM8K scoring-path reader
The recognizer/candidate-graph path is the single canonical reader.
Retires the flag-gated incremental-reader dispatch that admitted 0/50 on
train_sample and only added a dead fall-through:

- remove _try_comprehension_reader, _try_reader_for_question, _tokenize_sentence
  and both dispatch blocks from generate/math_candidate_graph.py
- delete generate/comprehension/lifecycle_runtime_adapter.py (402 LOC,
  used only by the question-reader dispatch)
- drop the comprehension_reader_questions config flag and the parse_and_solve
  / _score_one_candidate_graph config threading
- remove the --use-reader runner plumbing + flag-ON/OFF delta report from
  the train_sample runner; refresh report.json (drops stale use_reader field
  and a stale refusal-reason; verdicts unchanged at 3/47/0)
- remove the now-dead use_reader field from teaching/coverage.py
  CoverageReport + the core teaching coverage CLI flag
- delete tests/test_reader_coexistence.py (flag-ON/OFF premise dissolved);
  fix 3 ADR-0174 build_report calls and 2 subprocess invocations

lifecycle.py and audit.py are KEPT — they are load-bearing for the ADR-0172
math-contemplation teaching corridor (audit_problem -> teaching/math_*),
which a pre-deletion trace surfaced. The parent ADR's plan to delete
lifecycle.py was wrong; only its GSM8K scoring dispatch was inert.

Net -1,038 LOC (code + tests). Behavior-preserving:
- train_sample 3/47/0, byte-identical verdicts to pre-5a baseline
- determinism holds; smoke/packs/runtime/cognition/teaching lanes green
- contemplation corridor + lifecycle/audit tests pass

Pre-existing (NOT introduced here; reproduce on base with changes stashed):
5 out-of-curated-lane stale committed-artifact / stale-assertion failures
(test_math_evidence_e2e, test_adr_0126_runner_wiring, G3/coverage_probe
report-match, test_refusal_taxonomy_lane rebuild).
2026-05-28 13:38:44 -07:00
Shay
62a3e23318 docs(adr-0174): amend Phase 5 scope — invert premise, split 5a/5b
Pre-implementation investigation (lookback discipline) found the original
Phase 5 text inverted against shipped code:
- math_parser.py already out of runtime + candidate-graph scoring path
- lifecycle.py admits 0/50 (inert parallel parser, not the reader to promote)
- correct>=25 is a semantic gate structural collapse cannot meet

Decision (Invert + split): recognizer/candidate-graph path is the canonical
reader; lifecycle.py is retired. Phase 5a = structural retirement (net -LOC,
3/47/0 byte-identical, wrong=0). Phase 5b = semantic narrowness removal (the
real lift, own sub-phases, per-layer wrong=0 obligations).
2026-05-28 13:19:30 -07:00
Shay
619cd62227 fix(adr-0174-phase3a): multi-actor pronoun hazard defense + test backfills + ADR amendment
All findings from the 2026-05-28 Phase 1-3a lookback review addressed
in one commit on the Phase 3a branch:

Wrong=0 hazard defense (the load-bearing fix):
- generate/math_candidate_graph.py: Phase 3a wiring now collects the
  set of distinct proper-noun subjects seen in prior context. When
  more than one exists, refuses with no_antecedent_ambiguous trace
  event rather than guessing the most-recent (which was gender-blind
  single-binding — wrong attribution in multi-actor problems).
- Refusals from the statement loop now preserve _statement_trace via
  reader_trace in CandidateGraphResult (pre-existing latent issue:
  Phase 2/3 trace events were dropped on early statement refusal).
- New tests assert: ambiguous case refuses with correct trace; single-
  actor case still resolves normally.

Test coverage backfills (closes the 13 untested predicate-name gaps):
- TestCheckConstraintsInitialPredicateNames — 3 tests asserting the
  exact predicate name on initial.value_grounds / initial.unit_grounds
  / initial.entity_grounds failure paths.
- TestCheckConstraintsOperationPredicateNames — 3 tests asserting
  operation.verb_grounds / operation.value_grounds / operation.unit_grounds
  failure-predicate-name parity.
- TestCheckConstraintsComposedInitialPath — 4 tests for the RAT-1
  composed_initial path which was entirely untested in Phase 2
  (parity manually verified during lookback review; now automated).

ADR amendment (honest doc vs impl drift):
- docs/decisions/ADR-0174-held-hypothesis-comprehension.md: appended
  'Implementation Notes' section documenting:
  - reevaluate signature differs from spec text (shipped is more
    composable; treat as amended)
  - Phase 2 wires per-candidate, not per-token (per-token is Phase 5)
  - Lookback recompute is candidate-level, not token-level
  - Hypothesis.constraint_state is never populated by Phase 2
  - Multi-actor pronoun hazard defense rationale
  - Honest LOC accounting: Phases 1-3a net +1,500 lines (Phase 5
    delivers the projected net removal)
  - Test coverage backfill summary

Cosmetic:
- lookback.py:297 unreachable raise — added # type: ignore[unreachable]
  with comment explaining defensive future-proofing for Phase 3b.

Acceptance verified:
- 124/124 Phase 1+2+3a + reader tests pass (was 95/95 before backfills)
- Smoke 67/67, packs 141/141
- train_sample 3/47/0 preserved (wrong=0 invariant held)
- Multi-actor hazard live-tested: parse_and_solve refuses the
  Alice/Bob/She case with no_antecedent_ambiguous trace event

See CLAUDE.md §Lookback Review Discipline and memory
feedback-lookback-review-discipline for the doctrine that surfaced
all of these issues at the right time.
2026-05-28 10:49:20 -07:00
Shay
5d1f1001f4 feat(adr-0174-phase3a): lookback re-evaluation operator + pronoun resolution substrate
ADR-0174 Phase 3a — substrate for held-hypothesis lookback.
Score unchanged at 3/47/0 (this PR is correctly-engineered
infrastructure; eval impact gated on ADR-0163.x recognizer expansion
documented in the follow-up brief).

Adds generate/comprehension/lookback.py:
- VALID_REFINEMENT_KINDS, VALID_UNRESOLVED_SLOTS — closed sets
  contracted with reader_trace consumer
- PronounResolution refinement dataclass (pronoun + resolved_to +
  evidence_source, all validated)
- Refinement Union (Phase 3b will widen with CompoundClauseExpansion)
- ReevaluateResult dataclass with admit/eliminate consistency
- reevaluate(hypothesis, refinement) operator — applies refinement,
  re-runs check_constraints, returns refined Hypothesis or None.
- _rebuild_candidate_with_resolved_actor — rebuilds
  CandidateOperation / CandidateInitial replacing the semantic actor
  field (op.actor / initial.entity) while preserving matched_actor_token
  / matched_entity_token as the pronoun (so grounding still passes
  against the held statement's source span).

Modifies generate/recognizer_match.py:
- _try_extract_discrete_count_anchor: pronoun-subject statements now
  emit anchors with subject_role=<pronoun> + requires_pronoun_resolution
  marker, rather than refusing at the _REFUSED_SUBJECT_TOKENS check.
  The other narrowness layers (clause split, verb whitelist) still
  refuse; only the pronoun layer changes.

Modifies generate/math_candidate_graph.py:
- After inject_from_match, when any parsed_anchor carries
  requires_pronoun_resolution, the candidates are held as Hypothesis
  objects with unresolved=('actor_pronoun',). The lookback path then
  resolves via the existing _discourse_prior_subjects map and runs
  PronounResolution refinements through reevaluate.  Resolved
  hypotheses flow into per_sentence_choices as if the regex parser
  had produced them; unresolved hypotheses drop cleanly (refusal-
  preferring).  Emits 'lookback' JSON trace events with
  outcome ∈ {admitted, eliminated, no_antecedent}.

Tests:
- tests/test_adr_0174_phase3_lookback.py — 17 acceptance tests
  covering operator semantics on Operation/Initial, dataclass
  invariants, closed-set constants, end-to-end wiring on synthetic
  problems, and wrong=0 preservation on train_sample.

Phase 3.1 follow-up brief:
- docs/handoff/PHASE-3.1-FOLLOWUP-RECOGNIZER-EXPANSION.md documents
  the empirical finding that the train_sample bottleneck is
  verb-coverage (recognizer scope, ADR-0163.x) not lookback
  (ADR-0174 scope). 11 verbs identified for HITL contemplation pass.
  Recommends sequencing: Phase 3a now (substrate), ADR-0163.x verb
  expansion next, Phase 3b after coverage matures.

Acceptance verified:
- 17/17 Phase 3a tests pass
- 95/95 existing tests pass (Phase 1 + Phase 2 + brief_11 + reader_phase2)
- Smoke 67/67, packs 141/141, lanes 8/8
- wrong=0 preserved, score unchanged 3/47/0 (intentional per brief)

Stacks on Phase 2 (PR #420). Rebases onto main after #416 + #420 land.
2026-05-28 10:49:20 -07:00
Shay
36cf14c436 docs(handoff): phase 3b+4 skeleton pack — tests + en_core_names_v1 starter
Self-contained skeleton dispatch under docs/handoff/phase-3b-4-skeleton/.
Nothing is collected by pytest, nothing is loaded by runtime.
Implementer moves files to live locations when wiring.

Contents:

  README.md
    Implementer workflow, target locations per file, pack notes.

  test_adr_0174_phase3b_compound_clause.py
    13 acceptance tests covering: pure conjunctive lists (2-clause
    proper noun, 5-clause pronoun w/ single antecedent), refusal
    discipline (mixed-verb, multiplicative-tail, non-whitelisted-verb,
    partial-grounding), HYPOTHESIS_CAP raise to 8, pronoun + multi-
    actor defense preservation, wrong=0 + case-0050 canary. All
    @pytest.mark.skip until implementation lands; imports inside
    test bodies so collection succeeds before target modules exist.

  test_adr_0174_phase4_contemplate.py
    16 acceptance tests covering: contemplate() primitive contract
    (empty/single-survivor noop), Resolution dataclass invariants
    (kind/source closed sets), gendered-pronoun resolution (the
    killer use case — 4 tests covering she/he/same-gender/unknown-
    name), evidence-source precedence (vault>pack>audit_history),
    determinism, trace event shape, wrong=0 + case-0050 canary.

  en_core_names_v1/gender.jsonl
    59 unambiguously-gendered English first names (30 female,
    29 male), alphabetically sorted, JSONL format with schema
    {name: str, gender: 'female'|'male'}. Covers names appearing
    in train_sample/v1 GSM8K problems (Alice, Bob, Daniel,
    Malcolm, Erica, Jan, Tina, etc.) plus common English
    first-name baseline.

  en_core_names_v1/manifest.json
    Pack metadata with sha256 checksum (verified against gender.jsonl
    bytes), entry count, schema declaration, ambiguity discipline
    (Jordan/Alex/Casey/Pat/Taylor/Morgan/Sam/Chris/Robin/Riley
    explicitly excluded), expansion pathway through HITL corridor,
    wrong=0 protection contract for the contemplate adapter.

Pack integrity verified:
  checksum match: True
  entry count match: True (59/59)
  no duplicates
  alphabetically sorted (deterministic diff)

References: docs/handoff/ADR-0174-PHASE-3B-4-COMBINED-SCOPE.md,
ADR-0174 (held-hypothesis comprehension), CLAUDE.md §Semantic Pack
Discipline.
2026-05-28 10:01:05 -07:00
Shay
6b946ec873 docs(handoff): ADR-0174 Phase 3b + Phase 4 combined scope
Phase 3b (compound-clause held hypotheses) is prerequisite for Phase
4 (in-loop contemplate) to have anything to operate on. Combined
scope rather than separate briefs because:

- Phase 3b alone: 0 lift on train_sample (multi-actor defense
  refuses, solver gaps prevent admission)
- Phase 3b + Phase 4: 2-4 case lift via gendered-pronoun resolution
- Phase 3b + 4 + solver multi-qty (separate ADR): 6-8 case lift

First concrete Phase 4 use case: gendered pronoun resolution via a
new en_core_names_v1 pack. Turns the multi-actor defense from
refuse-on-ambiguity into admit-via-evidence when an unambiguous
gendered name exists for one antecedent.

Architecture overview, Phase 3b extractor design, Phase 4
contemplate adapters (vault > packs > audit_history), wrong=0
hazard surfaces, sequencing (3b then 4 stacked), truth tests, and
deliberately-excluded scope (solver work, verb expansion, per-token
apply_word integration — all separate ADRs).

HYPOTHESIS_CAP raise from 4 to 8 needed for Phase 3b (case 0040
has 5 anchors). Documented in scope.

References: ADR-0174 (held-hypothesis comprehension), CLAUDE.md
§Lookback Review Discipline, memories for multi-actor pronoun
hazard and case-0050.
2026-05-28 09:54:45 -07:00
Shay
796b446b49 docs(handoff): require multi-actor pronoun safety test in VE-A/B acceptance
Adds second mandatory hazard test to VE-A/B acceptance criteria:
multi-actor pronoun ambiguity must trigger no_antecedent_ambiguous
refusal per ADR-0174 Phase 3a defense.

Verb expansion widens the cases that reach Phase 3a lookback wiring;
without this test the multi-actor wrong=0 hazard could fire silently
in production. Surfaced by 2026-05-28 Phase 1-3a lookback review.

References: project-adr-0174-multi-actor-pronoun-hazard memory,
CLAUDE.md §Lookback Review Discipline.
2026-05-28 09:19:46 -07:00
Shay
23bc789e06 docs(handoff): verb-coverage expansion dispatch pack (VE-A/B/C)
Operationalises the recommendation from PHASE-3.1-FOLLOWUP-RECOGNIZER-EXPANSION.md
into three independent dispatchable PRs:

- VE-A: acquisition widening (gain, earn, save, accumulate, acquire) — Opus
- VE-B: new depletion class (donate, give, lose, spend, eat) — Opus
- VE-C: refusal evidence for non-arithmetic verbs (instrumentation only) — Sonnet

Each PR includes:
- Hazard pinning: explicit case 0050 test must pass after widening
- Lift evidence: at least one train_sample case moves refused → correct
- Phase 3a substrate fires: the lifted case shows a 'lookback' trace event
- wrong=0 preserved across train_sample AND case 0050

Operator decisions needed before dispatch: which specific lemmas to
admit per class, whether to introduce the depletion class at all, and
whether to ship VE-C as evidence groundwork.

Verb classification rationale per lemma documented in the brief.
Hazard surfaces called out per lemma (delta-of-attribute for 'gained',
direction inversion for 'lost', monetary-vs-time ambiguity for 'saved').

No timelines; operator dispatches when ready.
2026-05-28 08:56:46 -07:00
Shay
f90f0cf471 docs(adr-0174): held-hypothesis comprehension with lookback and in-loop contemplation (proposed)
Extends ADR-0164's incremental comprehension reader from single-committed
state to held-hypothesis state, adding lookback re-evaluation and in-loop
contemplation. Diagnoses why the ADR-0164 reader is wired but inert
(all-or-nothing refusal at first unknown token / unexpected category).

Architecture: apply_word produces ProblemReadingState.open_hypotheses
(small ranked set, HYPOTHESIS_CAP=4 initial). Three operators per token:
EMIT (extend compatible hypotheses), ELIMINATE (constraint violations
remove hypotheses immediately), HOLD (uncommitted hypotheses survive at
lower confidence). At finalize(), |survivors|=0 refuses, |survivors|=1
admits, |survivors|>=2 invokes in-loop contemplate() over vault + packs
+ audit history. Ambiguity contemplation cannot resolve refuses cleanly,
preserving wrong=0.

Collapses three parallel parsing systems into one held-hypothesis
reader: removes regex parser runtime path (math_parser.py),
per-category injector dispatch table (recognizer_anchor_inject._INJECTORS),
and duplicate per-sentence-choices scaffolding. Net ~1,900 lines
removed; reader grows by ~600 for hypothesis state + reevaluate +
contemplate.

Preserves ADR-0164 lexicon and category set, ADR-0165 regex scope,
ADR-0150/0152/0155/0161 HITL corridor, binding graph + solver
substrate, capability-axis lanes, replay-equivalence gate. Trust
boundary for in-loop contemplation: read-only over vault/packs/audit;
ratification still rides offline HITL.

Status: Proposed. Six phases (no timelines) gated on wrong=0 and
capability-axis 100% at each transition. Five open questions resolved
before Phase 1 PR.
2026-05-28 07:56:57 -07:00
Shay
89defef30b chore(audit): substrate cleanup — dead spike, gitignore, deprecation, reader diagnosis
C1: delete generate/math_versor_arithmetic.py and its 3 tests (ADR-0139
add-only arithmetic spike; no runtime consumers, no pipeline wiring,
follow-on lift paused per module docstring).

C3: gitignore engine_state runtime artifacts (manifest.json,
recognizers.jsonl, discovery_candidates.jsonl). Module code
(engine_state/__init__.py) remains tracked; generated checkpoint
files should not be.

C5: document reader zero-delta root cause in train_sample/v1/README.md.
Both Phase 2 (whole-problem) and Phase 1 (question-only) reader paths are
called but inert because all 47 refusals are statement-level NO_INJECTOR
gaps, not question-sentence gaps. Reader unblocks when injector coverage
expands (C2 work). report.json use_reader flag corrected to reflect last run.

C6: add deprecation header to generate/math_parser.py pointing at
generate.math_candidate_graph.parse_and_solve as the live path.

C2/C4 briefs: docs/handoff/CLEANUP-C2-run-lane-migration.md and
docs/handoff/CLEANUP-C4-compositions-compile.md added as operator
dispatch docs for the medium-scope wiring tasks.
2026-05-28 07:00:33 -07:00
Shay
fd6a544341
Merge pull request #414 from AssetOverflow/docs/epistemic-state-math-audit-plan 2026-05-28 04:21:29 -07:00
Shay
e0380ee91d docs(epistemic): align audit terminology with runtime enum 2026-05-28 04:17:19 -07:00
Shay
ec460c9068 docs(epistemic): add prior ADR compatibility gate 2026-05-28 04:13:05 -07:00
Shay
ee381f8e7e docs(epistemic): complete phase 1 state separation 2026-05-28 04:05:01 -07:00
Shay
48eb68d5d7 docs(epistemic): add math audit findings and taxonomy plan 2026-05-28 04:03:28 -07:00
Shay
be85c66801 docs(brief-C): comprehension reader audit — zero eval delta diagnosis + next steps
Phase 1 and Phase 2 of the ADR-0164 reader are correctly implemented but
contribute zero eval admissions today. The bottleneck is lexicon coverage
(unknown verbs/nouns) and explicit Phase 2.1 scope gates (fractions), not
the all-or-nothing dispatch policy.

Produces COMPREHENSION-READER-AUDIT.md answering the five Brief C questions:
call trace, cognition-lane usage (none), bottleneck analysis, ADR promise
audit, and three falsifiable options (operationalize/relabel/retire).
Recommendation: relabel (status update) now; lexicon expansion next as the
highest-leverage first step toward actual eval lift.

Also updates ADR-0164 status from "Proposed" to "Partially implemented" with
a Current Status table and next-lift-path summary.
2026-05-27 20:45:31 -07:00
Shay
85b8f0cd11 docs(post-rat1): four parallel dispatch briefs (B/C/D/E)
After RAT-1's architecture audit exposed five systematically
underbuilt components, A (the 4 missing injectors) is being taken by
this agent. The other four are parallel-safe and each gets its own
dispatch brief:

  B (Opus)   — contemplation produces ratifiable claims (medium)
  C (Sonnet) — comprehension reader audit + decision (small→medium)
  D (Sonnet) — core teaching coverage CLI (small)
  E (Codex)  — lexical ratification auto-compile (tiny)

Each brief carries: operator profile, branch name, base, dispatch
line, reads required FIRST, outcome inventory, hard requirements,
tests, truth test. Anti-regression invariants enumerated. All
parallel-safe — no shared file conflicts.

The dispatch DAG names ALL FIVE pieces with A in-flight as a peer.
2026-05-27 20:24:39 -07:00
Shay
3e196df097
Merge pull request #404 from AssetOverflow/feat/matcher-extension-me5-integration
feat(matcher-extension/ME-5): integration smoke + ME-1..ME-5 milestone
2026-05-27 19:33:41 -07:00
Shay
613a8e93da
Update position_paper.md 2026-05-27 18:27:18 -07:00
Shay
9b8f6bb991 feat(matcher-extension/ME-5): integration smoke + ME-1..ME-5 milestone
Final PR of the matcher-extension wave. Ships:

1. tests/test_me5_all_categories_integration.py — 4 new tests:
   - test_all_three_canaries_admit_through_full_pipeline: stages a
     pack with all three SAFE_COMPOSITION_CATEGORIES entries +
     ratifies, runs Maria/Sam/Tom canaries through matcher →
     inject_from_match, asserts admission for all three
   - test_partial_pack_only_admits_present_categories: refusal-
     preferring when only one category is ratified
   - test_all_safe_categories_have_extension_admission: pins that
     SAFE_COMPOSITION_CATEGORIES is exactly the three covered
     categories (breaks if future ADR widens without matcher)
   - test_falsifies_uniformly_suppresses_across_categories:
     polarity discipline holds across all three matchers

2. docs/handoff/ME1-ME5-MILESTONE.md — wave milestone doc:
   - architecture diagram (audit → ratify → compile → load →
     match → consult → admit)
   - SAFE_COMPOSITION_CATEGORIES coverage matrix
   - invariants preserved across the entire stack
   - scope boundary (what does NOT fire yet — RAT-1 follow-up)
   - recommended next dispatch

3. Test registration in core/cli.py packs suite.

Across the full ME-1..ME-5 stack:
- 5 stacked PRs (#400/#401/#402/#403/#404)
- 1 foundation PR (#398 — consumption wiring)
- 114 new tests, all green
- packs suite 127 passed
- core eval gsm8k_math --split public → 150/150, wrong=0
- All three SAFE_COMPOSITION_CATEGORIES have matcher extensions

Anti-regression invariants preserved across the entire stack:
- wrong == 0 on public split
- Case 0050 hazard pin (parametrized over all three categories)
- ADR-0166 — no new eval lanes
- ADR-0167 partition — no cognition imports
- ADR-0169 mutation boundary — registry is a gate, not arithmetic
- All matcher detection paths byte-identical
- engine_state/* never committed
- SAFE_COMPOSITION_CATEGORIES enforced at write AND load
- polarity falsifies honored uniformly

Live train_sample admission requires operator-seeded ratifications
(RAT-1 follow-up). Wiring is end-to-end correct, verified by ME-5
integration tests.

Memory: milestone-me1-me5-matcher-extensions-complete saved.

Stacks on PR #403 (base: feat/matcher-extension-subtractive).
2026-05-27 17:35:10 -07:00
Shay
b6f7ea8d00 docs: add one-mutation-path invariant, non-hardening invariant, and fabrication loop to position paper 2026-05-27 17:18:44 -07:00
Shay
6d9ff8119f docs(paper+license): refresh ahead of going public
Two pre-public-release refreshes:

1. docs/position_paper.md §4 — refresh refusal taxonomy

The previous table listed an older taxonomy (fraction_operand /
compound_comparative / etc.) that does not match the current
candidate-graph eval output. Replaced with the actual taxonomy
emitted by the train_sample runner — refusals are categorized by
shape (recognized_but_uninjectable + per-ShapeCategory) which ties
directly to the architecture's recognizer/injector concepts.

Also refreshed §5 "Honest Gaps" to describe the active frontier in
terms of injector coverage (the registry-driven composition path)
rather than parser-level grammar extensions. The 47/50 refusal
count, 3/50 correct count, and wrong=0 invariant are unchanged.

2. COMMERCIAL_LICENSE.md — enumerate subsystems explicitly

The previous "vault memory / versor engine / epistemic teaching
loop / ingest / admissibility gate / holonomy encoder" listing
predated the math-domain composition wave. Expanded the list to
cover the full current architecture:

- versor engine + Cl(4,1) algebra
- vault + exact CGA recall
- ingest gate
- admissibility gate + Forward Semantic Control
- holonomy encoder
- epistemic teaching loop (ADR-0055..0057)
- contemplation loop + decomposer (ADR-0080, ADR-0172)
- math-domain ratification handlers (ADR-0167..0169)
- composition-pattern registry + registry-driven injector
- audit-as-teaching-evidence corridor
- identity + safety pack subsystems
- language-pack compiler + verified manifest checksums
- Logos articulation + three-language vocabulary manifold
- Rust algebra backend
- any derived or successor implementation

Explicit "enumerated subsystems are illustrative, not limiting"
clause covers any future module + ADR-ratified contract under the
same terms. New subsystems are covered automatically.

LICENSE (the non-commercial form) is unchanged — it already covers
"Software" broadly. CLAIMS.md is auto-generated and was verified
current (regeneration produces no diff).
2026-05-27 16:59:18 -07:00
Shay
af3bcbcbf6 docs: update authorship to Josh Shay / ACB Content across license and position paper 2026-05-27 16:48:22 -07:00
Shay
c5a3463178 docs: position paper, non-commercial license, and commercial licensing terms 2026-05-27 16:48:22 -07:00
Shay
7a0b1ed931
docs(matcher-extension): dispatch pack (ME-1) (#399)
Follow-up to PR #398 — lights up the dormant consumption path by
extending _match_rate_with_currency to publish composition_shape +
pre-composed CandidateInitial in parsed_anchors.

Scope: one matcher extension (_match_rate_with_currency) for the
currency-per-unit composition shape ("$X each"). Other composition
shapes (multi-quantity, additive, subtractive) deferred to ME-3/4/5
follow-ups.

Subject binding decision pinned: Option A (refuse when same-sentence
subject is absent). Forbids Option B (placeholder subject —
fabricates attribution). Defers Option C (cross-sentence subject)
to its own ME-2 brief.

Honest consequence: case 0019 stays refused in THIS PR (requires
Option C). Truth-test #1 replaced with a synthetic "Maria bought 3
vet appointments at $400 each" canary that has same-sentence
subject. The flywheel turns one revolution: ratify → compile →
load → consume → admit, end-to-end on the synthetic canary.

Operator profile: Opus (load-bearing wrong=0; pre-composed
CandidateInitial; case 0050 mandatory pin).

Test surface enumerated (4 test files, 12+ tests):
- test_matcher_extension_currency_per_unit (8 narrowness tests)
- test_matcher_extension_case_0050_hazard_pin (mandatory)
- test_matcher_extension_end_to_end_admission (truth test)
- test_matcher_extension_train_sample_baseline_preserved
- test_matcher_extension_public_split_preserved

6-row truth test pinned. Anti-regression invariants enumerated.
Forbidden surface includes Option B + new SAFE category entries +
solver mutation.

Recommended next dispatch sequence: ME-1 → ME-2 (case 0019) →
ME-3/4/5 (remaining composition shapes).
2026-05-27 16:17:30 -07:00
Shay
ffa04f775b
docs(consumption-wiring): operator dispatch pack (CW-1 + CW-2) (#397)
Production-line dispatch form of the consumption-wiring brief in
PR #396. One bundled PR recommended (CW-1 + CW-2 share pack-compile
+ manifest extension + case 0050 pin). Split only if CI cycle time
forces.

CW-1 — Frame consumption:
  language_packs/compile_frames.py + generate/comprehension/frame_registry.py
  + reader wire + manifest frame_checksum extension.

CW-2 — Composition consumption:
  language_packs/compile_compositions.py +
  generate/comprehension/composition_registry.py + injector wire in
  generate/recognizer_anchor_inject.py + manifest
  composition_checksum extension. SAFE_COMPOSITION_CATEGORIES
  enforced at load (defense in depth); polarity "falsifies"
  suppresses injection (not silently "affirms").

Truth test pinned as binding (6-row table). PR is not done unless
case 0019 admits, case 0050 stays refused, train_sample moves from
3/47 → ≥4/46, wrong==0 holds, public split unchanged (150/150),
empty-registry runtime byte-identical to today.

Operator profile: Opus (load-bearing wrong=0 surface; case 0050
mandatory pin; same rigor as CC-2).
2026-05-27 16:16:41 -07:00
Shay
a105eb5f20
docs(consumption-wiring): brief for closing Frame + Composition loop halves (#396)
Names the structural gap discovered in the first end-to-end
CompositionClaim ratification (2026-05-27 post-#393):
ratification handler writes JSONL artifacts cleanly, but no runtime
code reads compositions/*.jsonl or frames/*.jsonl. Two of three
sub-types ship the ratification half of the loop without the
consumption half.

State:
  lexicon/      writer ✓  reader ✓  (LexicalClaim — closed)
  frames/       writer ✓  reader ✗  (FrameClaim   — half-open)
  compositions/ writer ✓  reader ✗  (CompositionClaim — half-open)

Proposes one bundled PR (CW-1 + CW-2) mirroring the proven
generate/comprehension/lexicon.py::load_lexicon pattern:

  CW-1 — Frame consumption: pack-compile frames/*.jsonl into a
         runtime-loadable artifact; new load_frame_registry()
         loader; reader wire.
  CW-2 — Composition consumption: pack-compile compositions/*.jsonl;
         new load_composition_registry(); injector wire in
         generate/recognizer_anchor_inject.py.

Hard requirements: SAFE_COMPOSITION_CATEGORIES allowlist enforced
at both write and load (defense in depth); polarity "falsifies"
honored; manifest checksum extended per CLAUDE.md "Semantic Pack
Discipline"; empty-registry runtime byte-identical to today.

Truth-test pinned: success is the EVAL DELTA, not the artifact
append. PR is "done" when case 0019 (the canary I ratified) admits
under train_sample, train_sample moves from 3 correct / 47 refused
to ≥4 correct / 46 refused, case 0050 stays refused, wrong==0 holds.

This brief is orthogonal to the workbench UI wave (W1..W4); both
can ship in parallel. Recommended operator: Opus (load-bearing
wrong=0 surface; same rigor as CC-2).
2026-05-27 16:14:50 -07:00
Shay
3c9e7e2ce3
docs(workbench-ui): wave brief pack (W1..W4) (#395)
Production-line brief pack for the workbench-UI implementation wave.
Five briefs in five PRs, gated on ADR-0173 (PR #394) landing first.

Dependency DAG:
  ADR-0173 → W1 → { W2 ‖ W4a ‖ W4b }
                → W3 (after W2 + #393 CompositionClaim handler)

Operator profiles assigned per [[feedback-parallel-dispatch-pattern]]:
  W1  Codex   — Vite/TS/Tailwind/shadcn scaffold from ADR-0162 spec
  W2  Sonnet  — read surfaces (ProposalQueue/Card/Detail + StableJsonViewer)
  W3  Opus    — ratification corridor (load-bearing wrong=0; case 0050 pin)
  W4a Sonnet  — replay surfaces (TraceDrawer/ReplayTheater/Diff)
  W4b Sonnet  — eval surfaces (EvalCenter/LaneList/FailureViewer)

Each brief carries: dispatch line, reads-required-first list,
outcome inventory, hard requirements, tests, deliverables, forbidden
surface. Anti-regression invariants enumerated (wrong=0, ADR-0166
no-new-lanes, partition, case 0050, 127.0.0.1, no remote runtime).

Includes copy-paste dispatch sequence and a `status` zsh trap for
single-line PR monitoring during the wave.

Pain-point retirement matrix maps each of the five scoping-brief
operator pain points to the wave PR that retires it.
2026-05-27 15:35:05 -07:00
Shay
b37aadc972
docs(ADR-0173): Workbench Ratification Trust Boundary (W0) (#394)
W0 of the workbench-UI wave per WORKBENCH-UI-WAVE-SCOPING.md.
Pure docs PR; no UI code.

Decision: the workbench is a local keyboard accelerator for the
existing local-CLI ratification surface (ADR-0161 Surface C), not a
fourth ratification surface and not a new trust boundary. Every
workbench-driven ratification action invokes the same Python
entrypoint as the corresponding CLI invocation, with identical
preconditions, exceptions, and append-only JSONL effects.

Amends ADR-0160 v1 read-only stance narrowly: admits driving the
three Tier 1.5 handlers (apply_lexical_claim, apply_frame_claim,
apply_composition_claim) and the existing core teaching review path
through the workbench API. Honors ADR-0161's surface set unchanged
(workbench is part of Surface C, not a new surface). Honors ADR-0162
no-go list and pins the keyboard contract referenced in §7.

Five open questions from the scoping brief resolved:
  Q1 in-process via existing Python entrypoints
  Q2 single-operator (multi-operator deferred)
  Q3 same chat/telemetry.py JSONL sink, new event kinds
     (operator_ratify / operator_reject / operator_defer /
     operator_navigate); no parallel log
  Q4 fonts and icons bundled locally; no CDN
  Q5 dist/ gitignored; CI verifies build, does not commit artifact

Ratification record extended with ratifier_kind: "workbench" — audit
forensic discriminant only, not a permission gate. proposal_id + to
remain the only load-bearing replay fields (ADR-0161 §5 unchanged).

Compatibility audit covers ADR-0146, 0150, 0152, 0160, 0161, 0162,
0167, 0168/0168.1, 0169/0169.1, 0172. Forbidden surface enumerated:
no remote operator, no CORS relaxation, no new mutation paths, no
auto-ratify, no batch ratification, no engine_state writes outside
the existing checkpoint path, no parallel workbench-events log, no
mobile/responsive form factors (ratification stays on Surfaces A+B
for mobile per ADR-0161).

Acceptance gates pinned per W1..W4 of the scoping brief.
2026-05-27 15:34:43 -07:00
Shay
76051d6ac5
docs(workbench-ui): scoping brief for UI wave (W0..W4) (#392)
Names the wave shape before any implementation. Audits what doctrine
has already settled (ADR-0160 stack pins + read-only trust boundary;
ADR-0162 design system + 15-component must-ship list + no-go list),
catalogs the current state (backend complete, frontend zero), surfaces
the five operator pain points sourced from the 2026-05-27 demo and the
CompositionClaim brief pack, and proposes a five-wave sequence:

  W0 (docs)  — Trust-boundary ratchet ADR (ADR-0173 working title)
               admitting operator ratification through the workbench,
               scoped to existing Tier 1.5 handlers (Lexical / Frame /
               Composition) and pinning the keyboard contract.
  W1 (base)  — workbench-ui/ scaffold per ADR-0162 Branch 1.
  W2 (read)  — ProposalQueue + ProposalCard + ProposalDetailPanel.
  W3 (act)   — RatificationCommandPanel + handler dispatch (the
               throughput multiplier).
  W4 (verify)— TraceDrawer + ReplayTheater + EvalCenter.

Guardrails enumerated: CLAUDE.md docs discipline, ADR-0162 no-go list,
determinism, trust boundary, wrong==0, case 0050 hazard pin,
keyboard-first, accessibility, local-first, no engine_state writes
outside the checkpoint path.

Open questions (in-process vs out-of-process ratification, single- vs
multi-operator, telemetry path, font/icon bundling, build artifact
location) listed for W0 resolution. No code in this brief.
2026-05-27 15:09:58 -07:00
Shay
b51d204898
docs(ADR-0169): CompositionClaim ratification doctrine + adapter (#391)
PR-α of the CompositionClaim wave (CC-1 brief in
docs/handoff/COMPOSITIONCLAIM-BRIEF-PACK.md). Pure docs; no runtime
mutation. Authors two ADRs mirroring ADR-0168 / ADR-0168.1 structure:

- ADR-0169 — CompositionClaim ratification doctrine (parent ADR-0167)
- ADR-0169.1 — MathCompositionClaimProposal adapter (parent ADR-0169)

CompositionClaim is the next sub-type from ADR-0167 FOLLOWUPS §1 and
the highest-leverage missing handler: 20 of 47 audit refusals in
evals/gsm8k_math/train_sample/v1/audit_brief_11.json
(quantity_extraction = 12 + multi_quantity_composition = 8; corrects
the §1 hint's 8+11 = 19 to the audited 20).

Initial SAFE_COMPOSITION_CATEGORIES allowlist:
  - multiplicative_composition
  - additive_composition
  - subtractive_composition

Distributive / ratio / comparative / percentage / unit-conversion /
time / chained compositions are explicitly deferred.

Case 0050 hazard pin is mandated in the acceptance gates section.
Prior-ADR compatibility audit covers ADR-0056, 0057, 0114a, 0164,
0165, 0166, 0167, 0168, 0172. ADR-0057 evidence floor preserved via
the adapter (ADR-0169.1) — audit evidence stays source="math_audit",
never laundered as source="corpus".

Mutation boundary limits accepted proposals to appending reviewed
composition-pattern artifacts under
language_packs/data/en_core_math_v1/compositions/{category}.jsonl;
solver, parser, decomposer, frame-opener, and lexical surfaces remain
untouched.
2026-05-27 14:47:35 -07:00
Shay
5adbfa9df9
docs(compositionclaim): brief pack — ADR-0169 doctrine + handler + heuristic tightening (#390)
Three briefs in two PRs:
- CC-1 (PR-α): ADR-0169 + ADR-0169.1 doctrine docs only
- CC-2 + CC-3 (PR-β bundled): handler impl + new
  composition_reclassification change_kind + decomposer heuristic
  tightening

Covers 20 of 47 audit refusals (quantity_extraction 12 +
multi_quantity_composition 8) — the highest-leverage missing handler.
Also retires the over-aggressive frame_reclassification routes from
PR #386 surfaced by the 2026-05-27 end-to-end workbench demo.
2026-05-27 14:46:24 -07:00
Shay
73e52a128b
docs(tier1.5+tier2): FrameClaim handler + Tier 2 W5 schema brief pack (#387)
* docs(tier1.5+tier2): FrameClaim handler + Tier 2 W5 schema brief pack

Two parallel briefs ready for dispatch:
- F1: FrameClaim ratification handler (Opus) — implements ADR-0168 +
  ADR-0168.1; turns 2 of 8 Tier 1 proposals into real GSM8K
  admissions on ratify
- T2-W5: MathReaderInferenceProposal schema (Sonnet) — Tier 2 substrate
  with two-arm test-and-learn type contract

Zero file overlap between briefs; safe to dispatch concurrently. W6+
deferred until FrameClaim is live (Arm 2 known-good preservation needs
a working handler to verify against).

* docs(briefs): correct pack + workbench paths in Tier 1.5/Tier 2 brief

Operator dispatching F1 (PR #389) discovered:
- Pack path is language_packs/data/en_core_math_v1/, not packs/en_core_math_v1/
- Workbench dispatch table lives in workbench/readers.py, not workbench/api.py

Both operators landed on the correct locations regardless. Folding the
corrections into #387 directly so future operators reading the brief
get the real paths.
2026-05-27 14:05:53 -07:00
Shay
3aea5a1fa8
docs(ADR-0172): fix evidence-module path in Tier 1 brief pack (#381)
The brief pack referenced `teaching/audit_evidence.py` in 3 spots
(A2 schema field, A2 read-required list, B2 algorithm step 3a). The
actual module on main is `teaching/math_evidence.py` (carries
`MathReaderRefusalEvidence` per ADR-0167).

Sonnet (A2 / PR #380) discovered the discrepancy and correctly used
the real module. This patch corrects the brief so Wave B operators
(B1 / B2) do not hit the same gap on dispatch.

No runtime change. Pure docs.
2026-05-27 12:18:19 -07:00
Shay
2d5b119c6a
docs(ADR-0172): Tier 1 brief pack — W0 through W4 with parallel waves (#378)
Coordination artifact for ADR-0172 Tier 1 dispatch. Six PRs in the
ADR (W0, W0.1, W1, W2, W3, W4) collapsed into a 4-wave DAG with two
concurrent briefs per wave A and B.

Operators are dispatched in their own UIs by pointing at the
section heading — "read §Brief A1" etc. Bundling options A/B/C
inside the doc let the operator choose CI economy vs wall-clock.

No runtime change. Pure docs.
2026-05-27 12:07:59 -07:00
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
Shay
ecc0072ea1
chore: remove stub injector + superseded docs (cleanup-as-you-find) (#373)
Three concrete cleanup items from the day's work, per the
cleanup-as-you-find memory principle.

## 1. Remove inject_rate_with_currency stub

PR #369 (A2 rate_with_currency) shipped a function that always returns
() with an extensive docstring documenting the Rate-not-in-SentenceChoice
schema gap. The function is dead at runtime — `_INJECTORS.get(category)`
returning None has the same downstream behavior as the function
returning (). The 16 tests pinned the empty-tuple return; the case-0050
hazard pin is duplicated in test_recognizer_skip_wrong_zero.py and
test_brief_11b_step2_lexicon.py.

The schema gap is now properly documented in ADR-0170 (PR #372). A
dispatch-table comment at the removal site retains the at-code pointer
to that ADR for anyone wiring a new injector.

Removed:
- `inject_rate_with_currency` function in generate/recognizer_anchor_inject.py
- Its `_INJECTORS` dispatch table entry
- Its `__all__` export
- tests/test_injector_rate_with_currency.py (371 lines, 16 tests)

## 2. Remove docs/handoff/GPT55-MOBILE-DISPATCH.md

Single-session travel-time scaffolding. The 5 tasks it named are
complete or superseded by ADR-0170's findings. Pure historical artifact.

## 3. Remove docs/handoff/WAVE-NEXT-INJECTORS.md

Superseded by docs/handoff/WAVE-NEXT-REVISED.md, which captures
everything load-bearing from the original brief in its A1–A4 findings
table. The "kept for history" justification didn't survive scrutiny:
the document was misframed (over-promised lift; misframed schema work
as injector work). Lessons captured in REVISED + ADR-0170.

Updated cross-references:
- WAVE-NEXT-REVISED.md: removed the "supersedes ... kept for history"
  pointer; tightened cross-reference list
- ADR-0167-FOLLOWUPS.md §7: rewrote pointer to name ADR-0170 + REVISED
  as the live plan rather than "the original is retained"

## Test plan

- 219 tests passed across G.2/G.4/G.5/S1/Brief 11/B1/B11A/wiring/partition/DCS-D.2
- evals/gsm8k_math/train_sample/v1/report.json untouched (regen
  surfaces a separate stale-baseline test issue — out of cleanup scope)
- No runtime behavior change

## Net impact

- 5 files removed (~1200 lines)
- 1 file modified for explanatory comment (~30 lines)
- 2 doc files updated to remove dangling cross-references
- 0 behavioral change
2026-05-27 11:08:14 -07:00
Shay
ce6b2f5173
docs(ADR-0170): injector contract widening + DCS-S1 schema-gap finding (#372)
DCS-S1 (proper-noun possession sub-shape expansion) investigation
revealed that the recognizer-injector path's `CandidateInitial`-only
return type is a substrate-level constraint blocking four Wave-Next
sub-shape categories — not just one.

## Two artifacts

1. **`docs/handoff/DCS-S1-FINDING.md`** — investigation result. Of
   the 21 DCS-refused GSM8K cases, zero are pure S1-only blockers.
   Acquisition-verb expansion (`collected`, etc.) conflicts with
   ADR-0131.G.1's branch-disagreement discipline. The right fix is
   the DCS injector emitting `CandidateOperation(add)`, but the
   `inject_from_match` return type doesn't allow that.

2. **`docs/decisions/ADR-0170-injector-contract-widening.md`** —
   scoping ADR. Names the contract change, the four categories it
   unblocks (DCS-S1 acquisition, A1 currency, A3 multiplicative,
   A4 temporal), the three load-bearing rules it must preserve
   (ADR-0131.G.1, SentenceChoice union, admissibility gates), and
   a 5-step implementation outline.

## Pattern recognised

Wave-Next surfaced four schema gaps. All four trace to the same
constraint: per-category injectors can only emit `CandidateInitial`.
The right next-capability work is ADR-0170 ratification, then a
small no-behavior-change PR widening the contract, then per-injector
follow-up PRs against the widened contract.

That is the actual lift-per-risk path for GSM8K Round-1 closure.

## Test plan

Docs-only. No code, no test, no eval, no pack change.

## Cross-references

- ADR-0163.D.2 — original parsed_anchors → solver-state ADR
- ADR-0131.G.1 — branch-disagreement discipline ADR-0170 preserves
- ADR-0167 — parallel teaching-corridor mechanism (independent)
- ADR-0167-FOLLOWUPS §7 — Wave-Next findings backlog
- WAVE-NEXT-REVISED — parent plan; ADR-0170 is the upstream blocker
- PR #369 — A2's schema-refusal artifact (first observation of gap)
2026-05-27 10:51:46 -07:00
Shay
abf2fd6bc0
docs(wave-next): revised plan after A1-A4 findings + schema-gap backlog (#371)
The Wave-Next injector dispatch (A1-A4) surfaced findings that
invalidate three of the four briefs' lift assumptions:

- A1 currency_amount — sandbox-blocked; real lift potential intact
- A2 rate_with_currency — schema gap (Rate not in SentenceChoice
  union); PR #369 documents the gap with concrete 4-step plan
- A3 multiplicative_aggregation — Operation(multiply) spec wrong;
  correct emission is CandidateInitial(outer×inner); zero GSM8K cases
  match canonical narrow form anyway
- A4 temporal_aggregation — needs apply_rate primitive not in algebra

Three of four are schema-extension ADRs masquerading as injector work.
Only A1 is a true injector + sandbox-fix scenario.

Deliverables:

1. `docs/handoff/WAVE-NEXT-REVISED.md` (new) — supersedes
   WAVE-NEXT-INJECTORS.md. Pivots to DCS sub-shape expansion as the
   actually-tractable next wave (21-case bucket, existing v1 injector,
   #366 spec on main). Captures the three schema gaps + A1's
   preserved lift potential for separate ADR work.

2. `docs/handoff/ADR-0167-FOLLOWUPS.md` §7 (new) — points to the
   revised plan and summarises the four findings inline.

WAVE-NEXT-INJECTORS.md retained for history.

No code change. No runtime effect. Docs-only.
2026-05-27 10:28:15 -07:00
Shay
4beda0bfd7
docs(handoff): Wave-Next injector briefs — A1-A4 + B1 + D1 + optional audit (#367)
Six dispatchable briefs covering the next-progress path on GSM8K
(correct from 3 → 10+, ADR-0163 Round-1 gate).

Wave A — four parallel recognizer-injector PRs:
- A1 currency_amount → Sonnet (2-4 cases lift)
- A2 rate_with_currency → Opus (schema decision required)
- A3 multiplicative_aggregation → Sonnet (first CandidateOperation)
- A4 temporal_aggregation → Sonnet (structural sanity)

Wave B — orchestrator-handled inline:
- B1 lexical-entry closure for 3 remaining cases

Wave D — sequential after A2 lands:
- D1 ADR-0169 CompositionClaim scoping → Opus

Optional background:
- Gemini recognizer registry audit (GPT-5.5 Task 3 unclaimed)

Dispatch gated on the #362→#366 cascade fully merging. Codex is
offline (rate limits); allocation reflects Sonnet + Opus + Gemini.

Each brief carries explicit case 0050 hazard pins, narrow-form
constraints, wrong=0 verification commands, and report-back questions.
2026-05-27 09:51:40 -07:00
Shay
81423df85f
docs(handoff): reconcile discrete_count_statement injector spec (#366) 2026-05-27 09:51:30 -07:00
Shay
fd9c36049c
docs(ADR-0168.1): choose math FrameClaim proposal adapter (#365) 2026-05-27 09:50:33 -07:00
Shay
cb94049679
docs(ADR-0168): scope FrameClaim ratification doctrine after compatibility audit (#364)
* docs(ADR-0168): scope FrameClaim ratification doctrine

* docs(ADR-0168): add prior ADR compatibility audit
2026-05-27 09:48:51 -07:00
Shay
dbeb1b2f00
fix(ADR-0167): replace brittle partition git-status assertion with behavioral invariant (#362)
* fix(tests): replace brittle git-status partition assertion with behavioral invariant

* docs(ADR-0167): record closure of brittle partition git-status assertion

* fixup: restore FOLLOWUPS §6 (holonomy ablation) — unresolved, just shipped in #360
2026-05-27 09:31:13 -07:00
Shay
1534046638
docs(handoff): GPT-5.5 mobile/connector dispatch — 5 in-flight spec tasks (#361)
Five docs-only tasks GPT-5.5 can pick up via the GitHub connector while
the operator travels. Every task is read-only execution: spec / audit /
ADR drafting, never code or test changes. Risk profile: zero.

Tasks (each opens one PR):

1. ADR-0168 FrameClaim scoping draft (highest priority — next gate
   after the LexicalClaim slice)
2. discrete_count_statement injector specification audit (highest-
   leverage: 21/47 GSM8K refusals are this category)
3. Ratified-recognizer registry audit (informs Task 2 and future
   injector work)
4. FOLLOWUPS §6 holonomy ablation test specification
5. Cognition contemplation partition fix specification (FOLLOWUPS §5a)

Each task carries:
- Files to read first (with paths)
- Deliverable shape (what the output doc must contain)
- PR body requirements
- Explicit out-of-scope list

Hard constraints enforced for the mobile-connector mode:
- One PR per task; explicit file staging; never git add -A
- Markdown-only (CLAUDE.md §Documentation Discipline)
- No code edits — flag in PR body if a task starts needing one
- No engine_state/ commits
- Cite filenames + line numbers; verify before committing

If all five complete, GPT-5.5 opens a meta-PR linking them into
ADR-0167-FOLLOWUPS.

No code change. No runtime effect. Docs-only.
2026-05-27 09:12:13 -07:00
Shay
1cc05d9cce
docs: schema-defined proof obligations doctrine + convergence-site invariant + FOLLOWUPS §6 (#360)
Three small surgical anchors capturing the verified architectural
insight surfaced during the ADR-0167 wave (no new ADR — the gap claim
that prompted this resolved on verification; what remains is a sharper
residual question worth memorialising).

1. CLAUDE.md — new "Schema-Defined Proof Obligations" section between
   Documentation Discipline and Validation Through CLI.  Generalises
   the wrong=0 invariant pattern: schema types that name structural
   properties are real only when an executing test can meaningfully
   fail under the violations it is written to catch.  Three-step rule
   for treating a schema as load-bearing.

2. language_packs/compiler.py — ARCHITECTURAL INVARIANT comment on
   _apply_mounted_primary_domain_resonance naming it as the single
   convergence-decision site for DEPTH_ROOT/DEPTH_RELATION packs.
   Anchors the doctrine at the code site so any future modification
   trips on the reference to the holonomy proof's coverage gap.

3. docs/handoff/ADR-0167-FOLLOWUPS.md §6 — captures the structural-vs-
   blend convergence isolation question.  HolonomyAlignmentCase IS
   executed today (we verified), but the existing test doesn't
   distinguish structurally-derived convergence from blend-induced
   convergence.  Ablation test or reframed claim — both acceptable
   resolutions.

Verified before commit:
- All 13 architectural references in the Gemini analysis resolve
  exactly: triliteral 0.30, root 0.40, prefix 0.03/(idx+1), stem 0.24,
  _INFLECTION_PRIORITY case-near-last, _apply_mounted_primary_domain_resonance
  with 40% English-prototype blend, HolonomyAlignmentCase defined
  AND executed
- tests/test_alignment_graph.py: 8 passed (no behavioural change)
- Documentation discipline (#355) honoured: pure Markdown, no HTML

No code behaviour changes.  No runtime effect.  Drops the larger
ADR-0168-PROPOSAL idea — the gap claim that prompted it dissolved
under verification.
2026-05-27 07:52:20 -07:00
Shay
a7d1547fbb
docs(ADR-0167): follow-ups queue — 5 named items deferred from LexicalClaim slice (#358)
Captures the named follow-ups that surfaced during the ADR-0167 wave so
they don't drift. Five items, each with scope / why-deferred /
breadcrumbs / acceptance criterion:

1. Frame-opener sub-types (FrameClaim / CompositionClaim / ReferenceClaim
   / SlotClaim) — four additional handlers, each its own ADR
2. Partition test architectural fix — current git-status-at-test-runtime
   assertion is structurally brittle (3 options outlined)
3. Two pre-existing main failures (test_unparseable_statement,
   test_audit_real_corpus_runs_clean) — fix or quarantine, don't ignore
4. Workbench v1 math-candidate rendering — ADR-0167 §Q4
5. Cross-domain partition risks Gemini flagged (contemplation pack
   indexing, replay gate default)

Includes leverage-based sequencing recommendation (no timelines per
project convention).

Docs-only. No code, no test, no eval, no pack change.
2026-05-27 07:39:22 -07:00
Shay
94fca8ea5d
docs: Brief 11 EOD status footer + 2026-05-27 session narrative (#356)
Two docs-only updates capturing the day's work:

1. Appended a "Status update — 2026-05-27 EOD" footer to the Brief 11
   handoff doc with the completion table (11A/11B-step-1/11B-step-2
   docs+lexicon/11D merged; 11C absorbed into W3-A; 11D candidate E ADR
   merged) and the current post-#348 baseline taxonomy.

2. New session doc SESSION-2026-05-27-adr-0167-parallel-dispatch.md
   alongside the existing SESSION-2026-05-26-comprehension-reader.md.
   Captures the architectural pivot (audit-as-teaching-evidence vs the
   rejected refusal-class dispatch table), the parallel-dispatch
   experiment (5 operators / 3 waves / 6 PRs), what worked, what
   surfaced as load-bearing (case 0050 hazard), and what's deferred.

No code changes. No runtime effect.
2026-05-27 07:21:01 -07:00
Shay
05aaff224e
feat(ADR-0167/W2-C): domain discriminator + cross-domain audit (#351)
* feat(ADR-0167/W1-A): MathReaderRefusalEvidence schema + canonical-bytes

Foundation type for routing comprehension-reader refusals into the
teaching corridor.  Frozen dataclass with sha256 evidence_hash computed
from deterministic canonical bytes (mirrors state.to_canonical_bytes
pattern).  Includes SUB_TYPE_FOR_OPERATOR mapping table covering all 13
missing_operator values in the current audit artifact.

Wave 1 only — no runtime mutation, no teaching-store integration, no
admission path.  Downstream W2-A/B/C/D type-import from this module.

* feat(ADR-0167/W2-C): domain discriminator + cross-domain audit

- Links to the audit doc: docs/handoff/ADR-0167-W2C-cross-domain-audit.md
- Inventory details: 5 construction sites, 8 consumption sites
- Verification: 0 cognition test files were modified; all tests are green
- Downstream partition work flagged: contemplation indexing (in teaching/contemplation.py) and replay gate (in teaching/proposals.py)
2026-05-27 06:44:29 -07:00
Shay
4f0815ef9a
docs(ADR-0167): audit-as-teaching-evidence (math reader → contemplation wire) (#349)
* docs(ADR-0167): audit-as-teaching-evidence (math reader → contemplation wire)

Scoping ADR for Brief 11D Candidate E. Routes math-reader refusal audit
rows into the existing contemplation/HITL teaching corridor as a new
candidate source (`MathReaderRefusalEvidence`).

Key decisions:
- Evidence-only — never directly admits a math fact; only ratification
  through HITL queue can change runtime behaviour
- Five sub-types proposed (Lexical / Frame / Composition / Reference /
  Slot claims) mapping to the audit taxonomy
- Scope first to LexicalClaim — lowest-risk, highest-count
- Six open questions called out for the implementation ADR

ADR-0166 three-question test passes; implementation passes only when
the six open questions are answered with LexicalClaim-first scope.

No code in this PR.

* docs(ADR-0167): parallel work plan — 6-PR/3-wave dispatch across 5 model operators
2026-05-27 06:21:43 -07:00
Shay
bb8ea3bbf9
docs(brief-11/11D): next-capability proposal — comparison + recommendation (#346)
Closes the Brief 11 sequence with a decision artifact (not a roadmap)
selecting the next capability after GSM8K Phase 2 reader closure.

Four candidates compared against ADR-0166's three-question test:
- A. Continued GSM8K operator closure
- B. Cross-domain reader generalization
- C. Tool-use trace integration
- D. Workbench demo hardening

Recommendation: continued GSM8K operator closure, starting with the
`lexicon_entry` row of the Brief 11B audit. The only candidate that
passes Q1/Q2/Q3 cleanly today and has an explicit Round-3 finish line.

Docs-only. No code, no test, no eval, no pack change.
2026-05-27 05:59:10 -07:00
Shay
60043973b0
feat(comprehension/10): Phase 2 statement-frame reader (ADR-0164.4) (#335)
Extend the comprehension reader from question-only scope to whole-
problem scope. Phase 1 (Brief 8 / #326) implemented question_frame;
this brief implements initial_state_frame, operation_frame, and
descriptive_frame, plus finalize() projection into a strict
ADR-0115 MathProblemGraph.

Architecturally correct under ADR-0164.3; not yet productive on
GSM8K train_sample. Below-floor measurement documented; specific
bottlenecks tabled for Phase 2.1 follow-up.

What landed

- Frame-opener dispatch in lifecycle.py for the three new statement
  frames, plus rule handlers (_rule_op_*, _rule_preframe_*,
  _rule_descriptive_*).
- finalize(state) -> MathProblemGraph | ReaderRefusal: pure
  projection with closure checks (entity registry non-empty,
  unknown target bound, every op/initial references a known entity,
  Decimal precision projects losslessly).
- _classify extended to 3-tuple (category, surface, decimal_value)
  with possessive strip retry. Brief 8.2's sentence-initial
  lookup-first + gender-skip preserved AND extended to mid-sentence
  (gender is enrichment everywhere, never admission).
- Whole-problem coexistence dispatch in math_candidate_graph.py
  (config.comprehension_reader_questions=True): reader attempts the
  whole problem; on any ReaderRefusal falls through to existing
  regex parser. All-or-nothing per the brief.
- Lexicon expansion (carried into renamed proper_noun_gender_*
  files): +2 accumulation_verb (adopt, invest), +2 currency_unit_noun
  (dollar, cent), +6 capacity_verb (fill, lift, play, work, finish,
  drive), +5 female names (allison, brooke, jan, marion, sidney),
  +14 male names (bart, fernando, georgie, jake, jed, jeremie, jose,
  orlando, rex, rudolph, steve, troy, xavier, yun), +numerous
  count_unit_noun, drain_token, time_unit_noun.
- ADR-0164.4-phase2-statement-frame-reader.md — the architectural
  rationale and acceptance contract.

Measurement (reader_phase2_delta.json):

  flag-OFF: correct=3 refused=47 wrong=0
  flag-ON:  correct=3 refused=47 wrong=0
  delta:    0/0/0

Below the brief's floor of correct >= 4. Architecture is sound — the
reader admits cases as graphs when the structure resolves, refuses
cleanly otherwise, preserves wrong=0 across both flag states.

Bottleneck table (from per-case attribution):

  count  refusal_class           dominant cause
  -----  ----------------------  ------------------------------------
  18     incomplete_operation    multi-quantity ops; no-quantity op
  11     unknown_word            "hundred", "presently", "one-hour",
                                 non-math verbs (compound numerics,
                                 lexicon gaps)
  6      unexpected_category     fraction / percentage literals;
                                 multi-subject sentences
  6      unresolved_pronoun      "them", "their", "his" with no
                                 compatible entity
  5      unattached_quantity     quantity never bound to a unit
  1      no_question_target     question parsed but slot never set

Closing the gate to mixed-bounded [4, 24] is Phase 2.1 scope: extend
composition rules for multi-quantity ops, add fraction/percentage
primitives (per ADR-0164.1 amendment), expand lexicon for the
remaining unknown_word cases, extend pronoun resolution.

Invariants preserved

- wrong = 0 in both flag states ✓
- flag-OFF byte-identical to today ✓
- determinism (50/50 identical runs) ✓
- Capability axes G1-G5, S1 unchanged ✓
- Reader tests: 19 (Phase 2) + 18 (Phase 1, post-update) + 53 (pack)
  + 76 (lexicon + primitives) = 166 specific to this change; all pass
- core test --suite smoke -q: 67 passed

Rebase note

This PR was authored against an older base; rebased onto current
main to incorporate #333 (Brief 8.2 universal proper_noun_token
primitive) and #334 (ADR-0166 measurement discipline). The rebase
required:
- Lexicon files renamed proper_noun_entity_* -> proper_noun_gender_*
  (with the Phase 2 additions merged into the gender_* files)
- Compiled lexicon.jsonl unchanged from #333's 207-entry state
  (Phase 2's per-category additions are runtime-visible via the
  source loader, not via the compiled file)
- _classify reconciled with Brief 8.2's sentence-initial dispatch +
  Phase 2's 3-tuple decimal-value return
- All dispatch tables and category checks updated to reference
  proper_noun_token (singular) instead of proper_noun_entity_{f,m}
- Three Phase 1 test expectations updated to reflect Phase 2
  behavior (proper noun at position 0 now opens statement pre-frame
  instead of refusing; pronoun resolution applies per ADR-0164.2)

Per ADR-0166's three-question test, this PR is honest measurement:
capability exists, at least one case admits, lane distinguishes
presence from absence — which the bottleneck table demonstrates.

Refs ADR-0164.3 §Phasing Phase 2, ADR-0164.1 amendment (Brief 8.2),
ADR-0166 §"Mixed (notable but not blocking)" — except here, below
floor.
2026-05-27 05:03:56 -07:00
Shay
33c2b10fbf
docs(handoff): Brief 11 — Phase 2 reader closure + capability snapshot sequencing (#342)
* docs(handoff): Brief 11 reader closure and snapshot plan

* docs(handoff): Brief 11 — Phase 2 reader closure + capability snapshot sequencing
2026-05-27 05:03:40 -07:00
Shay
834d1ae577
docs(ADR-0166): measurement-capability sequencing discipline (#334)
Add the fourth governing principle to the family of structural-
invariant ADRs (alongside ADR-0114a anti-overfitting, ADR-0165 regex
scope rule, CLAUDE.md versor invariant). The rule, stated negatively:
do not author eval lanes ahead of the operators those lanes test, and
do not expand the eval surface ahead of the capability that produces
signal on it.

Three-question test for new eval lanes:

  1. Does the capability this lane probes exist on main today?
  2. Has at least one case admitted end-to-end through that capability?
  3. Will running this lane distinguish capability-presence from
     capability-absence?

A "no" on any defers the lane until the capability lands. Tier 3 TBD
rows are data debt; running existing lanes to populate them is
permitted (snapshot of current capability) but is NOT a substitute for
capability work.

Why now: a strategic-analysis exchange this session proposed authoring
spatial_geometry_ood, historical_sequence_ood, and other new lanes
while GSM8K-math sits at 3/47/0 and the comprehension reader (ADR-0164)
is mid-build. The proposal's "most impactful next commit is to run all
Tier 3 lanes" framing would have generated noise (lanes refusing
uniformly because their underlying operators don't exist) rather than
the diagnostic signal that justifies prioritization. ADR-0166 mechanizes
the constraint that prevents that pattern.

Session log SESSION-2026-05-27-tier3-sequencing.md captures the
narrative: what the analysis got right (geometry-first as strategic
bet, sequencing instincts), what it missed (GSM8K-math treated as
solved; comprehension reader pivot not in context), and the honest
re-sequence (Brief 10 first; Tier 3 snapshot in parallel; cross-domain
transfer after verifying whether the reader IS the requested
structural-pattern recognizer under a different name).

The session also surfaced a mid-flight diagnostic from PR #332: the
actual GSM8K bottleneck is the ADR-0163 recognizer injector emitting
incomplete graphs, which the reader correctly refuses to admit
(wrong=0 by construction via the new guard). Brief 10 (Phase 2 reader)
dominates here because it replaces the inadequate injector surface
entirely.

No code changes. ADRs only.

Refs ADR-0114a, ADR-0165, CLAUDE.md §"Non-Negotiable Field Invariant".
2026-05-26 22:19:40 -07:00
Shay
2fcd22c319
docs(ADR-0164.2): pronoun/entity resolution policy (#319)
Proposed sub-ADR under ADR-0164 resolving Open question #3.

- Reviews existing _resolve_question_entity heuristic in
  generate/math_candidate_parser.py: refuse-on-ambiguity is correct,
  but flat-document whitelist scan misses recency, kinship entities,
  group antecedents from conjunction, and names absent from the
  closed name lists.
- Specifies EntityRegistry as a field on ProblemReadingState
  (ADR-0164.3 companion): append-only entries with canonical name,
  inferred gender + source, mention positions, and relational anchor
  for kinship entities.
- Two refusal-first ambiguity rules: ambiguous_pronoun_referent (R1,
  recency tiebreaker within RECENCY_GAP_MIN refuses) and
  unresolved_pronoun (R2).
- Worked walk-through on five GSM8K train_sample cases (0001 Tina,
  0010 Yun/Marion, 0027 Malcolm, 0017 Jason/Eric, 0033 Rachel + kin).
- Three policy-vs-heuristic disagreements (D1 Jason/Eric him; D2
  Georgie he via single-salient back-fill; D3 Aaron/Carson they via
  GROUP entry) all turn refusals into correct resolutions, plus one
  counter-direction D4 where new policy is principled-conservative.
- Preserves wrong = 0 by construction at every branch.
2026-05-26 19:32:19 -07:00
Shay
3b8f441ae0
docs(ADR-0164.1): lexical primitive set scope (#318)
Closes ADR-0164 §Open question #1. Enumerates the 8-primitive seed
registry for en_core_math_v1 (decimal-currency, currency, percentage,
fraction, time-amount, numeric, ordinal, mass-noun-token), fixes the
record schema (name/pattern/emits/extracted_fields/provenance/priority),
documents pairwise overlap precedence with rationale, and records 4
rejected temptations (rate phrases, compound entities, question stems,
compound numerics) so the ADR-0165 grammar/lexeme boundary doesn't get
relitigated by future authors.
2026-05-26 19:27:30 -07:00
Shay
20f3a5d586
docs(ADR-0164.3): cross-sentence reading state (#320)
Two-level state model for the incremental comprehension reader:
ProblemReadingState (outer, problem-scoped) carries the entity registry,
accumulated initial possessions, accumulated operations, the unknown
target slot, and the pronoun resolution history. SentenceReadingState
(inner, sentence-scoped) carries the current frame, expectation,
pending quantities, pending entity reference, pending verb, lookback
window, and the partial frame payload under construction.

Lifecycle API (signatures only): begin_sentence, apply_word,
end_sentence. All three pure / deterministic / no I/O. apply_word
reads from problem_state for pronoun resolution per ADR-0164.2 but
does not mutate it; only end_sentence produces a new
ProblemReadingState that folds in the just-closed sentence's
contribution.

Closed READER_REFUSAL_REASONS vocabulary across three lifetime
groupings (token-level, sentence-level, problem-level), mirroring
ADR-0134's admissibility-reason discipline.

Canonical-bytes serialization for both state levels matches existing
trace_hash and MathProblemGraph.canonical_bytes discipline.
Sorted-keys JSON, compact separators, Decimal-as-string for
precision, optional-None fields omitted.

Worked example: gsm8k-train-sample-v1-0001. Sentence 1 ("Tina makes
$18.00 an hour.") admits as a rate apply_rate operation; sentences 2
and 3 refuse at the leading "If" with unexpected_category
(conditional_frame is Phase-1 out-of-scope). The example demonstrates
the state model — that even when the reader refuses, the state at
the moment of refusal is what makes the refusal honest, typed, and
file-able as a teaching candidate.

Termination predicate is_terminable + finalize specified pure: a
ProblemReadingState becomes a strict ADR-0115 MathProblemGraph only
when entity registry is non-empty, unknown_target_slot is bound,
every accumulated op/initial references a known entity, and every
partial payload projects losslessly into the strict types.

Naming reconciliation: ADR-0164's sketched ComprehensionState is the
inner level under this ADR (SentenceReadingState). Brief 5 will
produce both types.

No code. ADR doc only.

Refs ADR-0164 §Open question #4.
2026-05-26 19:25:59 -07:00
Shay
e705f27d2e
docs(ADR-0164,0165): incremental comprehension reader + regex scope rule (#317)
Replace the regex sentence-template front-end of the math admissibility
layer with an incremental compositional reader. Lock the architectural
boundary that regex is permitted only at the lexeme level, never as
sentence-structure templates.

ADR-0164 (Proposed) — Incremental Comprehension Reader. Word-by-word
state accumulation over a closed set of semantic categories, with the
operational lexicon living as a pack-shaped data artifact under
language_packs/data/en_core_math_v1/. Reader output type matches the
existing regex parser's output, so the binding-graph admissibility
(ADR-0132/0133/0134/0135), the solver (ADR-0116), and the verifier
(ADR-0117) stay unchanged. wrong=0 is preserved by construction —
the reader produces inputs to the existing admissibility gate, not a
bypass around it. Phased coexistence with the regex layer during
transition; regex sentence templates removed in Phase 3.

ADR-0165 (Proposed) — Regex Scope Rule. Structural invariant: regex
matches one piece of orthographic material with a closed rule
(currency literal, fraction literal, percentage, time-amount, closed
unit-noun sets), never a sentence shape. Lexeme-primitive registry is
closed and grown through the same contemplation -> proposal -> HITL
review corridor that grows vocabulary (ADR-0150 / 0152 / 0155 / 0161).
The engine acquires new recognition tools through reviewed teaching,
not through operator edits to parser code.

ADR-0163's diagnosis (front-end is the bottleneck) is reaffirmed.
Its Phase B-E prescription (regex DerivedRecognizers via
recognizer_match.py) is partially superseded by ADR-0164. ADR-0136
and its S-family (S.1 / S.2 / S.3 / S.4) have the same disposition:
regex sentence-template prescription superseded; empirical refusal
taxonomies and closed-set vocabulary preserved as lexicon seed.
The HITL corridor architecture is preserved; what flows through it
changes from regex recognizers to lexicon entries, categories, and
lexeme primitives.

Session log SESSION-2026-05-26-comprehension-reader.md captures the
narrative of how this decision emerged from the post-D.2 train-sample
baseline review (correct=3 refused=47 wrong=0, 34/47 refusals at the
question gate).

No runtime code changes. ADRs only.
2026-05-26 19:23:05 -07:00
Shay
0b4a87beae
docs(plan): add CORE general advancement path (#314) 2026-05-26 18:32:08 -07:00
Shay
da70919f94
feat(ADR-0163.D.2): parsed_anchors → MathProblemGraph state — discrete_count_statement injection v1 (#315)
First PR plumbing recognizer parsed_anchors into the candidate-graph as
typed CandidateInitial primitives. Scope limited to discrete_count_statement;
other five round-2 categories route to the round-2 skip-only fallback until
follow-up D.2.x PRs.

Five-layer wrong=0 safety net:
1. Matcher narrowness — _try_extract_discrete_count_anchor refuses on any
   ambiguity (multi-subject, pronoun subject, non-possession verb,
   multi-count, clause-split, unobserved counted_noun, unobserved
   count_kind).
2. Extraction correctness — refusal-preferring; populated parsed_anchors
   only when ALL narrowness rules hold.
3. Injection correctness — _initial_admissible gates every constructed
   CandidateInitial; failure to ground returns () (under-admit).
4. Replay gate — propose-time admissibility_replay_gate auto-rejects any
   matcher change that would lift GSM8K wrong count.
5. Multi-branch decision rule — injected candidate disagreeing with
   another branch triggers refuse path.

Re-baseline (GSM8K train_sample v1):
- Old (#309 alone): correct=3 refused=47 wrong=0
- New (#309 + D.2 v1): correct=3 refused=47 wrong=0
- Empirical lift in v1 = 0 cases; framework operational. No GSM8K
  train_sample case has a discrete_count statement that simultaneously
  meets all narrowness rules AND is missed by the existing parser.
  Bottleneck moves to other recognizer categories (D.2.2+).

Validation:
- tests/test_adr_0163_d2_discrete_count_injection.py: 34 passed
- tests/test_recognizer_match.py + test_candidate_graph_recognizer_wiring
  + test_admissibility_replay_gate: 27 passed
- adr_0131_* (G1..G5 + S1 wrong=0 invariant): 222 passed / 2 pre-existing
  report-comparison failures / 3 skipped — byte-identical to pre-D.2
- Solver code: unchanged

Operator caveat: round-1's ratified discrete_count_statement spec is
unchanged. Matcher behavior on the spec's canonical_pattern has been
extended from detection-only to populated parsed_anchors. Re-ratification
is not required; if policy requires it on matcher-behavior changes, the
registry digest provides byte-stable provenance.
2026-05-26 18:32:05 -07:00
Shay
72fac59029
feat(ADR-0161.3): submission-time invariants — duplicate + dependent_on_pending auto-reject (#313)
Adds two pre-gate checks to propose_from_candidate that fire after the
Step 2 capacity check and before the replay gate.  No log entry is
written on either refusal — the append-only invariant holds.

Check order at function entry (ADR-0161 §3):
  1. Capacity (Step 2)          → RefusedAtCapacity
  2. Duplicate                  → RefusedAsDuplicate
  3. Dependent_on_pending       → RefusedAsDependent
  4. Replay gate                → auto-reject on regression

New frozen dataclasses:

  @dataclass(frozen=True, slots=True)
  class RefusedAsDuplicate:
      proposal_id: str
      existing_state: str        # covers all states: pending/accepted/rejected/withdrawn
      reason: str = "duplicate"

  @dataclass(frozen=True, slots=True)
  class RefusedAsDependent:
      candidate_id: str
      dependent_on: tuple[str, ...]       # pending proposal_ids that block
      overlapping_lemmas: tuple[str, ...] # normalised lemmas that triggered
      reason: str = "dependent_on_pending"

Lemma-overlap rule: case-insensitive exact-match on strip().lower().
Conservative — over-reject rather than admit-with-hidden-dependency.
False positives are recoverable (re-emit after blocker is ratified);
false negatives silently couple ratification choices.

CLI surfaces both outcomes in cmd_teaching_propose and
cmd_teaching_propose_from_exemplars (exit code 1).

Step 2 backpressure tests updated: made pre-populated candidates use
unique objects to avoid triggering the new dependency check, and
updated idempotency assertions to reflect the new RefusedAsDuplicate
return for re-submitted content.

Co-references: ADR-0161 §3, Step 1 PR #296, Step 2 PR #311,
ADR-0057, ADR-0151.
2026-05-26 16:46:25 -07:00
Shay
76032db9a0
feat(ADR-0161.2): HITL queue backpressure — pending-count cap + queue_full reports (#311) 2026-05-26 16:16:08 -07:00
Shay
47c0a03d3b
feat(ADR-0163.B.2): four new exemplar corpora — discrete_count_statement, multiplicative_aggregation, currency_amount, plus temporal_aggregation v2 widening (#306)
Phase B round 2.  Categorizing the post-#304 GSM8K train_sample's
still-refused 47 set surfaced three coherent sub-shapes in the previously
UNCATEGORIZED tail plus five ratified-but-narrowness-blocked temporal
cases; this PR ships the operator-authored exemplar seeds + Phase A
categorizer extension that prove the corridor scales beyond round 1.

Exemplar corpora (70 new exemplars across 4 files):
- discrete_count_statement_v1.jsonl (20)
- multiplicative_aggregation_v1.jsonl (20)
- currency_amount_v1.jsonl (20)
- temporal_aggregation_v2.jsonl (10, widening)

Each corpus carries ≥3 verbatim train-sample citations, ≥12 (≥5 for v2)
novel operator-authored statements, and ≥1–3 edge cases.  Statements are
disjoint across all 7 round-1 + round-2 corpora; tests enforce.

Phase A categorizer (evals/refusal_taxonomy/shape_categories.py)
extends ShapeCategory with three new members and inserts their rule
predicates AFTER the existing more-specific categories:
- rate_with_currency before currency_amount
- multiplicative_aggregation before discrete_count_statement
Each new rule predicate cites ≥3 train_sample case_ids in its docstring
(ADR-0163 §Risks).  No LLM, no embedding, no learned classifier.

Refusal-taxonomy histogram empirical signal (public 50 sample):
- pre-round-2: 14 UNCATEGORIZED (categorized_rate 0.72)
- post-round-2: 1 UNCATEGORIZED (categorized_rate 0.98)

The single residual is case 0044 ("10% simple interest" — percentage
without change verb), an honest tail outside the three round-2 shapes.

wrong=0 holds on capability axes G1..G5 + S1; no runtime code shipped.
Smoke suite green (67/67).

Cross-refs: ADR-0163, #297 (Phase A), #298 (Phase B round 1),
#301 (Phase C), #302 (Phase D), #304 (round-1 ratify), #305 (session
recap).

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 14:36:59 -07:00
Shay
65ccb8eeee
docs(session): 2026-05-26 corridor closure — first GSM8K lift + workbench operational (#305)
Captures today's end-to-end closure of the math architecture corridor
(ADR-0163 Phase A → B → C → D + operator ratification, 15 PRs, first
non-zero GSM8K correct count: 0 → 3 with wrong = 0 preserved) and the
workbench surface (W-026 API + ADR-0162 design system + W-027 shell +
W-028 chat surface) becoming operational end-to-end.

Added:
- docs/sessions/SESSION-2026-05-26-corridor-closure.md — full session
  ledger, per-fork accomplishments, three lifted GSM8K cases,
  unexpected-positive observation about skip-only wiring, deferred
  work, architectural state at close.

Updated:
- docs/master-plan-post-substrate-audit.md — 2026-05-26 amendment
  banner pointing to the session recap; historical 2026-05-24 plan
  preserved below.
- docs/PROGRESS.md — appended a new section capturing the day's 15
  PRs by fork (math, workbench, HITL), the first-lift counts, and
  what stays open.
- docs/decisions/ADR-0163-gsm8k-path-to-mastery.md — Round 1
  amendment with the actual lift evidence, the three lifted cases,
  the capability-axis preservation, and the unexpected-positive note
  about skip-only wiring doing more than projected.

Scope: docs-only.  No runtime, no tests, no code changes.
2026-05-26 13:49:08 -07:00
Shay
a612038d41
feat(W-028): chat surface + trace drawer (#303) 2026-05-26 13:22:11 -07:00
Shay
e9b7eb0b1f
feat(ADR-0163.D): wire ratified RecognizerSpecs into math_candidate_graph admissibility surface (#302)
* chore(ADR-0163.C): land three Phase C pending proposals in live log

Phase C (#301) shipped the CLI but its PR dry-run wrote to a tmp log
path.  This commit moves the three Phase C proposals into the live
teaching/proposals/proposals.jsonl so the Phase B→C audit trail is
visible in the proposal log and the proposals are ready for the
operator to ratify after Phase D ships.

Proposals (all state=pending, kind="exemplar_corpus"):
- 59223f13722f906a1cf9b65d9b01c990 — descriptive_setup_no_quantity
- 46ce297f797ff16da12db5de422ca3c9 — rate_with_currency
- a3b892546977c5f0f64c578d6052adbd — temporal_aggregation

Produced by `core teaching propose-from-exemplars --all` against the
live Phase B corpora.  No ratification (ADR-0161 §5 — only the repo
owner ratifies).  The Phase D admissibility-replay gate confirmed
replay_equivalent=true, wrong_count_delta=0 for all three.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(ADR-0163.D): wire ratified RecognizerSpecs into math_candidate_graph admissibility surface

Phase D is the first PR to extend the math admission surface.  The
audit (#294) said the gap was admission, not operators, algebra,
substrate, or packs.  Phase A measured the refusal taxonomy.  Phase B
authored seeds.  Phase C synthesized recognizers.  Phase D wires
those recognizers into generate/math_candidate_graph.py.

Modules
- generate/recognizer_registry.py — pure projection over the proposal
  log.  Only proposals with source.kind="exemplar_corpus" AND
  review_state="accepted" enter the tuple.  Sorted by
  (review_date, proposal_id).  In-process cache keyed on log
  (mtime, sha256) — no filesystem cache (ADR-0161 §1).  Malformed
  accepted specs raise RegistryLoadError citing the offending
  proposal_id; silent drops are forbidden.
- generate/recognizer_match.py — per-category rules-only matchers
  (no LLM, no embedding, no learned classifier).  Honors the Phase C
  synthesizer's narrowness rule: out-of-corpus currency symbols,
  window units, and per-unit values do NOT match.  Three matchers:
  _match_descriptive_setup_no_quantity (zero-quantity surface),
  _match_temporal_aggregation (event_count_per_window with
  observed_window_units/quantifiers honored), _match_rate_with_currency
  (currency_per_unit_rate with observed currency/per-unit/amount-kind
  honored).
- generate/math_candidate_graph.py — narrowest-edit guard at the
  per-statement choice loop.  Before the existing
  "no admissible candidate for statement" refusal, consult the
  ratified registry.  Recognized statements are dropped from
  per_sentence_choices (zero math state) so the Cartesian product is
  identical to "this statement was never there."  Empty registry is
  a no-op — backward compatibility preserved byte-identically.
  Downstream consumption of parsed_anchors (turning recognized
  rate/temporal surfaces into solver state that produces concrete
  answers) is Phase E follow-up.

Tests (32 new)
- tests/_phase_d_fixture.py — synthetic in-memory ratified registry
  built from the three Phase C pending proposals' content.  Per
  ADR-0161 §5 the agent does NOT ratify the live log; the synthetic
  registry round-trips the real RecognizerSpec bytes the operator
  will ratify after Phase D ships.
- tests/test_recognizer_registry.py (9) — empty/pending/wrong-kind
  filtering, sort order, malformed-spec rejection, cache hit +
  invalidation, live-log Phase C audit check.
- tests/test_recognizer_match.py (14) — per-category positive cases,
  narrowness (out-of-corpus surface forms rejected), no-LLM import
  check.
- tests/test_candidate_graph_recognizer_wiring.py (7) — empty registry
  preserves existing refusal; synthetic registry: recognized
  statements no longer trigger per-statement refusal;
  wrong_count_delta == 0 on GSM8K train_sample; capability axes G1..
  G5+S1 wrong=0 unchanged; per-category admission counts on the
  refused-set; unrecognized statements still refuse with the
  existing reason.
- tests/test_phase_d_replay_evidence.py (2) — full admissibility
  replay gate under synthetic registry: replay_equivalent=true,
  wrong_count_delta=0, every capability axis wrong=0; each
  ratified recognizer admits >= 1 train_sample statement (wiring
  is consequential).

Per-category fixture-based admission counts (synthetic registry vs
GSM8K train_sample refused-set sentences):
- descriptive_setup_no_quantity: 40
- rate_with_currency:             2
- temporal_aggregation:           7

Narrowness-invariant negative case results (matcher correctly
returns None on out-of-corpus / load-bearing-math surfaces):
- rate_with_currency:           "She paid $5 for the book." (no per-unit)
- temporal_aggregation:         "On Saturday she went to the store." (single day token)
- descriptive_setup_no_quantity: "There are some kids in camp." (indefinite quantifier)

Candidates for Phase B round 2 (3 of 20 temporal seeds match the
spec's structural commitment but not my surface regex — author_notes
explicitly flagged these as schema-gap edge cases):
- ta-v1-0004 "Mark does a gig every other day for 2 weeks."
- ta-v1-0012 "Robin walks 4 dogs every other day around the park."
- ta-v1-0019 "The pump fills the tank with 80 gallons over 6 hours."

Three landed wirings DO NOT shift the GSM8K train_sample baseline
counts under fixture (correct=3, wrong=0, refused=47 unchanged) —
Phase D's narrow wiring is wrong=0 safe by construction; lift to
"correct" requires Phase E's downstream parser-side consumption of
parsed_anchors.  Capability axes G1..G5+S1 wrong=0 unchanged.

Cross-refs: ADR-0163 (Phase D), ADR-0057 (proposal review),
ADR-0151 (auto-proposal), ADR-0161 §5 (ratification boundary),
Phase A PR #297, Phase B PR #298, Phase C PR #301.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 13:11:47 -07:00
Shay
cdead696ed
feat(W-027): Workbench frontend shell — five-region grid + ten empty routes + live StatusFooter (ADR-0160 / ADR-0162) (#299)
- Five-region CSS grid shell (TopBar, LeftNav, Main, StatusFooter; Inspector collapsed)
- Ten placeholder routes with EmptyState cli/string variants and ApiErrorBoundary
- Extended EmptyState API: nextAction accepts string (button) | { kind: "cli", command }
- Updated CommandPalette: real fuzzy search over three commands (Chat, Proposals, Evals)
  with ↑/↓/Enter keyboard nav and useInRouterContext degradation for Branch 1 preview
- TanStack Query hooks for all W-026 endpoints; 30s polling on runtime/status
- TypeScript mirror of workbench/schemas.py at src/types/api.ts
- StatusFooter: mutation_mode badge, git_revision (copy on click), checkpoint_revision
  with amber warning + ADR-0157/ADR-0158 expansion note
- TopBar: CORE Workbench wordmark, ⌘K palette trigger, connection pill
- ApiErrorBoundary (class component) catches WorkbenchApiError → ErrorState
- scripts/dump-api-schemas.py: AST-based Python dataclass field extractor
- workbench-ui/api-schema-snapshot.json: checked-in drift sentinel
- 51 tests across 10 files (0 failures); enum-coverage 4/4; clean vite build
2026-05-26 12:09:12 -07:00
Shay
1bff5689db
feat(ADR-0163.B.1): exemplar corpora — descriptive_setup_no_quantity, temporal_aggregation, rate_with_currency (#298)
Round 1 of ADR-0163 Phase B: hand-author seed exemplars for the top three
refusal shape categories surfaced by the Phase A histogram. These corpora
are INPUT to the Phase C contemplation runner, which will derive
DerivedRecognizer proposals from them; this PR ships no recognizer logic,
no proposal logging, and no runtime change.

Per-category breakdown:
- descriptive_setup_no_quantity_v1.jsonl — 20 exemplars (5 train + 12 novel + 3 edge)
- temporal_aggregation_v1.jsonl          — 20 exemplars (4 train + 13 novel + 3 edge)
- rate_with_currency_v1.jsonl            — 20 exemplars (3 train + 14 novel + 3 edge)

Train-sample citations resolve against
evals/gsm8k_math/train_sample/v1/report.json (the 50-case sample only;
public/holdout/full splits NOT mined per ADR-0163 §Constraints).

Each file is sorted by exemplar_id, byte-canonical, and disjoint from the
others. Statements are surface-preserved verbatim from the train sample
where cited.

Validation:
- tests/test_admissibility_exemplars.py: 20/20 passed (schema, enum
  binding, per-category quantity_anchor dispatch, cross-file disjointness,
  >=3 train-sample citations per category, sort/byte-canonical determinism,
  read-only import invariant)
- tests/test_adr_0131_*.py: 224 passed / 3 skipped — capability axes
  G1..G5 + S1 remain wrong=0
- core test --suite smoke: 67 passed
- core eval refusal_taxonomy: case_digest unchanged
  (d030f826cb0f4088771d90c52c8be2ff75054ab27c7d47eae8dbfe1225b2eea1)
- Phase A categorize() agrees with the file's category for all 60
  statements (sanity check; not pinned in tests since the rules-only
  categorizer is coarser than the recognizer Phase C will derive)

Author notes on quantity_anchor annotation calls flagged for operator
review are embedded in provenance.author_note where ambiguous (notably:
'in N minutes' / 'over N hours' window framings collapsed to
window_quantifier='per', 'every other day' approximated as 'every',
day-of-week labels not captured in the schema, 'for one X' / slash-form
per-unit framings, non-USD currencies, and discrete-occurrence per_unit
values like 'event' and 'session').

Refs: ADR-0163 §Phase B; depends on the Phase A lane shipped in #297.
Cross-refs: ADR-0057 (proposal review), ADR-0149/0154 (recognizer
pipeline), ADR-0161 (HITL queue), [[thesis-decoding-not-generating]].
2026-05-26 11:52:23 -07:00
Shay
ec5d6f5ac7
feat(ADR-0161.1): core teaching queue list|show — read-only queue projection (#296)
* docs(math): ADR-0163 — path to GSM8K mastery via candidate-graph admissibility (proposed)

Audit reframes the math roadmap entirely.

State of main: every named math capability axis (G1..G5, S1) passes
at 100% with wrong=0 on its controlled lane.  binding_graph,
math_versor_arithmetic, math_symbolic_equivalence, math_parser,
math_candidate_parser, math_solver, math_verifier, math_realizer,
math_problem_graph — all landed.  The worktrees on disk are stale
forks.

State of GSM8K (50-case train sample): correct=0, refused=50, wrong=0.
Every refusal reason is identical: "candidate_graph: no admissible
candidate for statement: <STATEMENT>".

The reframe: the gap is NOT in operator algebra, NOT in binding graph
internals, NOT in symbolic equivalence.  The gap is in
generate/math_candidate_graph.py — the admissibility surface that
turns a natural-language statement into a candidate the downstream
pipeline can consume.  The capability axes pass at 100% because they
test statement shapes the candidate-graph already admits.  GSM8K
refuses at 100% because its statements span shapes the candidate-graph
has never been taught.

Six-phase plan to lift GSM8K under the thesis "decodes, not generates":

A. Refusal taxonomy (measure before building)
B. Exemplar corpora per shape category (≤20 statements each, ≤3 per round)
C. Contemplation runner ingests exemplars; emits DerivedRecognizer
   proposals
D. Operator ratifies through ADR-0161 HITL queue (no new surface)
E. Re-baseline GSM8K train sample.  Round 1 exit: correct ≥ 10, wrong = 0.
   Round 2: ≥ 25.  Round 3: ≥ 35.
F. Scale to public/v1 (200 cases, target correct ≥ 100), then
   holdout (measurement-only — never tune against).

Three non-negotiables:
- wrong = 0 at every phase.  Auto-rejected by replay gate, not by
  operator vigilance.
- No hand-rolled recognizers in generate/.  Every recognizer lands
  via contemplation → proposal → review corridor.
- Active corpus mutation only via accept_proposal.

Status: proposed.  Implementation lands as three PRs starting with
Phase A scaffolding.

Scope discipline: docs-only.  No code, no eval changes, no corpus
mutation.

* feat(ADR-0161.1): core teaching queue list|show — read-only queue projection

* fix(ADR-0161.1): restore gap-queue CLI + rename new commands to hitl-queue + R1..R5 refinements
2026-05-26 11:42:51 -07:00
Shay
e89463a975
feat(workbench-ui): design system v1 scaffold (ADR-0162 Branch 1) (#295)
* feat(workbench-ui): design system v1 scaffold

* fix(workbench): close R1 (GroundingSource enum coverage) + R4 (digest test)

R1 — Promote GroundingSource to a typed Literal in core/epistemic_state.py
so it has the same single-source-of-truth shape as ReviewState.  The
existing epistemic_state_for_grounding_source() function already
enumerates the six labels (pack, teaching, vault, partial, oov, none);
this codifies them.

scripts/dump-enums.py now snapshots GroundingSource via the existing
literal_values helper.  workbench-ui's enumCoverage.test.ts gains a
fourth assertion that the badge mapping matches the Python source
1:1.  Adding a grounding-source value on the Python side without
updating the badge fails the build-time test loud — same discipline
as the other three enums.

R4 — Add an explicit DigestBadge test to StableJsonViewer.test.tsx:
asserts the badge text matches the SHA-256 prefix of the source bytes,
and clicking the badge copies the FULL digest (not the truncated
prefix).  Recomputes the expected digest via crypto.subtle to avoid
hard-coding a hex string that could drift.

R2 (component-level reduced-motion enforcement), R3 (EmptyState
copy-CLI affordance), and R5 (`uv run core` packaging paper cut) are
deferred — R2/R3 become meaningful with W-027/W-029, R5 is a
packaging-layer concern outside this PR's scope.

Validation:
- pnpm test: 19 passed (was 17, +1 enum coverage, +1 digest test)
- pnpm build: clean
- pnpm test:enum-coverage: 4 passed
- core test --suite smoke -q: 67 passed
2026-05-26 11:33:27 -07:00