Implements the 4-phase documentation reorganization master plan. - Consolidation: Merged brief/, handoff/, planning/, and decisions/ into briefs/, handoffs/, plans/, and adr/ respectively (101 ADRs relocated) - Root Cleanup: Relocated HANDOFF-gpt55-*.md and key top-level docs (runtime_contracts.md, etc.) to canonical folders. Added superseded alerts. - Indices & Navigation: Created docs/README.md navigation document, docs/sessions/README.md index, docs/adr/README.md index - Note: Also includes prior commit adding ADR-0200+ corpus hygiene governance (ADR-0225, dependency map, backfilled cross-references)
5.8 KiB
Matcher Extensions Milestone — ME-1 through ME-5
Date: 2026-05-27 Author: Shay Stack: PRs #398 → #400 → #401 → #402 → #403 → #404 Status: All five PRs open and stacked; matcher half of the math composition compounding loop is operational end-to-end.
What landed
The matcher-extension wave delivers a runtime consumer for every entry
in SAFE_COMPOSITION_CATEGORIES. When a recognizer match publishes a
composition_shape key in parsed_anchors AND the
composition_registry carries an affirms entry for that shape,
inject_from_match emits a pre-composed CandidateInitial whose
value is the arithmetically composed quantity.
| PR | Wave | Scope | New tests |
|---|---|---|---|
| #398 | CW-1 + CW-2 | Consumption infrastructure: compile_frames, compile_compositions, frame_registry, composition_registry, manifest checksum extensions, inject_from_match consult | 38 |
| #400 | ME-1 | Currency-per-unit composition (multiplicative; Maria canary; Option A subject binding) | 21 |
| #401 | ME-2 | Cross-sentence subject binding (case 0019 real; threads prior_subject through match() + math_candidate_graph) | 19 |
| #402 | ME-3 | Additive composition (two-quantity same-unit "and" connective) | 15 |
| #403 | ME-4 | Subtractive composition (initial-then-removal; non-negative remainder discipline) | 17 |
| #404 | ME-5 | Integration smoke across all three SAFE categories + milestone | 4 |
Total new tests: 114, all green.
Packs suite: 127 passed.
core eval gsm8k_math --split public: 150/150, wrong=0.
Architecture
audit refusal
→ core eval math-contemplation (decomposer dispatch)
→ MathCompositionClaimProposal
→ HITL ratify via apply_composition_claim()
→ compositions/{category}.jsonl append
→ pack-compile (CW-2) → compositions.jsonl + manifest.composition_checksum
│
▼
load_composition_registry()
│
─── runtime path ─────────────────┼────────────────────────────────
▼
recognizer matches statement
→ matcher extension (ME-1..ME-4) publishes composition_shape +
composed_initial in parsed_anchors
→ inject_from_match per-category injector returns ()
→ _consult_composition_registry sees composition_shape
→ registry: affirms entry for the shape
→ CandidateInitial admitted
→ candidate graph admits the statement
→ previously-refused audit case admits
SAFE_COMPOSITION_CATEGORIES — matcher coverage matrix
| Category | Surface pattern | Matcher | Dispatch via spec | Subject binding |
|---|---|---|---|---|
multiplicative_composition |
bound(count) × bound(unit_cost) |
_match_rate_with_currency |
anchor_kind=\"currency_per_unit_composition\" |
Option A (ME-1) + Option C (ME-2 via prior_subject) |
additive_composition |
bound(qty_a) + bound(qty_b) |
_match_multiplicative_aggregation |
anchor_kind=\"additive_quantity_composition\" |
Option A only |
subtractive_composition |
bound(initial) − bound(removed) |
_match_multiplicative_aggregation |
anchor_kind=\"subtractive_quantity_composition\" |
Option A only |
Invariants preserved across the entire stack
wrong == 0oncore eval gsm8k_math --split public(150/150)- Case 0050 hazard pin (parametrized over all three allowlist categories)
- ADR-0166 — no new eval lanes
- ADR-0167 partition — no cognition imports in any new module
- ADR-0169 mutation boundary — registry is a gate, never an arithmetic primitive; matcher owns the math
- All matcher detection paths byte-identical (regression pins per PR)
engine_state/*never committedSAFE_COMPOSITION_CATEGORIESenforced at write AND load- Polarity
falsifieshonored uniformly across all matchers - Refusal-preferring: pronoun / determiner / cross-unit / unobserved / unknown verb / zero count / negative remainder all refuse
Scope boundary — what does NOT fire yet
The wiring is end-to-end correct (verified by ME-5's integration
test that stages a synthetic pack and admits all three canaries).
Live train_sample admission requires operator-seeded
ratifications:
- A
RatifiedRecognizerproposal in the proposal log carrying:shape_category = RATE_WITH_CURRENCY(orMULTIPLICATIVE_AGGREGATION)canonical_pattern.anchor_kind = "currency_per_unit_composition"(oradditive_quantity_composition/subtractive_quantity_composition)- the right
observed_*sets
- A composition_registry entry compiled into the canonical pack:
surface_pattern = "bound(count) × bound(unit_cost)"(or the additive / subtractive shapes)composition_categoryin the allowlistpolarity = "affirms"
These are operator decisions, not automated. When seeded, the live train_sample run admits the 20 audit cases (12 quantity_extraction + 8 multi_quantity_composition) covered by this wave.
Recommended next dispatch
RAT-1: Operator-workflow PR / runbook that seeds the necessary
RecognizerSpec proposals + composition_registry entries to fire the
live eval-delta truth test. With RAT-1 merged, train_sample moves
from 3/47 → ≥4/46 (with case 0050 still refused, wrong=0
preserved). The flywheel produces its first ratify → admit event
on the canonical pack.
Memory pointers
- milestone-me1-me5-matcher-extensions-complete — this milestone
- project-ratification-consumption-gap-2026-05-27 — original finding
- feedback-ratify-vs-consume-loop-closure — general pattern
- milestone-adr-0172-tier1-2026-05-27 — Tier 1 parent
- adr-0167-audit-as-evidence-wave — parent corridor
- feedback-wrong-zero-hazard-case-0050 — preserved across the stack