* docs: consolidate governance anchors and clean up test registries * refactor(cli): decompose cli into dedicated modules * test: fix broken test baselines and formatting * docs: add domain boundary READMEs for governance anchors * test: update baseline for determination lane * test: fix capability_pass expectation * test: fix CORE_SHOWCASE_SKIP_BUDGET enforcement * chore: cleanup CLI extraction and unreachable code
6.1 KiB
DCS-S1 Finding — Injector Contract Is the Substrate Bottleneck
Date: 2026-05-27
Status: Finding; no implementation. Routes work to ADR-0170.
Parent: docs/handoff/WAVE-NEXT-REVISED.md
Result: DCS-S1 (proper-noun possession sub-shape expansion) cannot
ship meaningful lift on current GSM8K without first widening the
inject_from_match return-type contract. Same schema gap A3
(multiplicative) and A4 (temporal) identified.
What was investigated
The Wave-Next-Revised plan named DCS-S1 as the next tractable
sub-shape: extend the existing v1 inject_discrete_count_statement
injector to cover more of the 21 discrete_count_statement refusals
on the GSM8K train_sample.
The hypothesis: most DCS refusals are proper-noun possessions whose extraction fails for one of a few narrowable reasons (verb whitelist, clause-split markers, single-quantity rule). Loosening the matcher + extending the injector to cover those would lift several cases.
What the data actually shows
All 21 DCS-refused cases were enumerated and the triggering statements inspected. The structural breakdown:
| Sub-shape pattern in DCS-refused statements | Count |
|---|---|
Acquisition verb (collected, donated, bought) — not in possession whitelist |
~5 |
Multi-clause / enumeration (and, then, ,) |
~8 |
Pronoun subject (he, she, they) |
~4 |
Comparative reference (twice as many, half of) |
~3 |
Anonymous subject (There are, The guests) |
~3 |
| Other (modal verbs, copula, multi-verb) | ~4 |
(Buckets overlap — many cases hit multiple narrowness rules.)
Critical observation: of the 21 cases, zero are pure S1-only blockers. Every single one has additional blockers downstream in the same problem. Even if the DCS injector admitted the first sentence, sentences 2/3/4 carry their own refusals.
Concrete trace — case gsm8k-train-sample-v1-0023:
S1: "Nicole collected 400 Pokemon cards."
→ would inject Nicole=400 if `collected` were in possession verbs
S2: "Cindy collected twice as many, and Rex collected half of Nicole and Cindy's combined total."
→ multi-clause + comparative reference; will refuse on current rules
S3: question with `If Rex divided...` conditional prefix
→ conditional prefix recovery exists but answer still requires S2's admission
Admitting S1 alone does not close the case. The bottleneck moves from S1 to S2; no admission-lift is delivered.
The architectural blocker
To admit "Nicole collected 400 Pokemon cards" as initial state, three
edits would be needed:
- Add
collectedto_POSSESSION_VERBS(matcher narrowness ingenerate/recognizer_match.py) - Extend
_locate_possession_verbin the injector - Add
collect, collects, collectedtoCandidateInitial.__post_init__whitelist ingenerate/math_candidate_parser.py
ADR-0131.G.1 explicitly removed collected/bought/saved/buys/makes
from initial-anchor extraction — they were routed exclusively to
ADD_VERBS (operation extraction) to avoid branch disagreement when
the same sentence could produce both CandidateInitial(Sam=5) AND
CandidateOperation(Sam, add, 5).
The solver "defaults from zero for operations" so
Sam collected 5 apples. How many does Sam have? → 0 + 5 = 5. That
discipline is load-bearing for wrong=0 in the regex path.
The right architectural fix is not to break ADR-0131.G.1. It's to teach
the DCS injector to emit CandidateOperation(add) for acquisition
verbs — the same kind of state-introducing operation the parser
already emits for them.
But: inject_from_match's return type is
tuple[CandidateInitial, ...]. It cannot emit CandidateOperation.
Widening the contract is the prerequisite.
The pattern — fourth time this gap appears
Wave-Next surfaced four schema gaps. All four trace back to the same
substrate-level constraint: the recognizer-injector path can only
emit CandidateInitial.
| Brief | What needed emission | Available type | Blocker |
|---|---|---|---|
| A2 rate_with_currency | CandidateRate (carries Rate(value, num_unit, den_unit)) |
None — Rate not in SentenceChoice union |
Schema gap (PR #369) |
| A3 multiplicative_aggregation | CandidateInitial(outer × inner) OR CandidateOperation(multiply) |
CandidateInitial works for product semantics; but other cases need composition |
Half-blocked |
| A4 temporal_aggregation | CandidateOperation(apply_rate, ...) |
apply_rate primitive doesn't exist |
Algebra-level gap |
| DCS-S1 | CandidateOperation(add) for acquisition verbs |
Injector returns only CandidateInitial |
Schema gap (this finding) |
This is no longer four separate sub-shape problems. It's one substrate bottleneck affecting all four categories. The right artifact is a contract-widening ADR — see ADR-0170.
What this PR ships
- This finding doc (
docs/handoff/DCS-S1-FINDING.md) docs/adr/ADR-0170-injector-contract-widening.md— the scoping ADR that names the contract change and the four categories it unblocks
What this PR does NOT ship:
- Any DCS-S1 implementation (it's blocked on ADR-0170)
- Any matcher/extractor edits
- Any test changes
- Any pack changes
Recommended next move
ADR-0170 ratification, then a small focused PR implementing the contract widening (no behavior change, type-only). Then a follow-up wave (DCS-S1 acquisition, A1 currency, A2 rate, A3 multiplicative, A4 temporal) can ship in parallel — each as a focused injector PR against the widened contract.
That's the actual lift-per-risk path. Until ADR-0170 lands, no
recognizer-injector work other than CandidateInitial-only narrow
possession can ship cleanly.
Cross-references
- WAVE-NEXT-REVISED — parent plan; needs an update pointing to ADR-0170 as the prerequisite
- ADR-0170 — the scoping ADR this finding routes to
- PR #369 (A2) — first observation of the gap; documents
Rateextension steps - ADR-0131.G.1 — the original branch-disagreement discipline that forces acquisition verbs to be operations, not initials
- ADR-0167-FOLLOWUPS §7 — Wave-Next findings backlog