Nine ADRs (0254, 0256-0263) were merged into main and left stamped Proposed. Two carried an explicit ratify-on-merge predicate their own merge had already discharged, and ADR-0256 governs deduction_serving_enabled, which was ratified True on 2026-07-24 and is serving live traffic. So the governance record asserted "not yet decided" about a decision already in force. That is the asymmetry the assessment arc (#113) found one file over in workbench/api.py: the honest path degrades, the stale record lies. An unwritten ADR is a visible gap; a Proposed one that is actually in force is a false statement. Each stamp records the ACTUAL ratifying act -- "Accepted, ratified by Joshua Shay via <merge> (<sha>, <date>)" -- derived from the commit that added the file and verified an ancestor of main, not assumed. Merge authority is Shay's alone (AGENTS.md: no merge automation), so the merge IS the ratifying act. No ADR content changed. No flag changed. ADR-0262's stamp says so explicitly: accepting it does NOT enable curriculum_serving_enabled, which stays False pending ratified volume -- eleven bands re-measured today, still 24x-73x short. tests/test_adr_status_governance.py pins two independent invariants in the smoke (pre-push) suite: 1. A default-ON flag is not governed by a Proposed ADR. The flag -> ADR mapping is DERIVED by walking core/config.py for `<name>: bool = True` and reading ADR refs from the preceding comment block -- not a hand-written table, which would be the same second-copy-of-a-closed-set defect ADR-0256's arc fixed. 2. A ratify-on-merge predicate cannot coexist with Proposed. Self-discharging: the file being on main IS the merge having happened. Plus a vacuity guard, because a derivation that parses zero flags would make every other assertion pass on an empty set. Registered two orphans found in passing: test_adr_index.py (5) and test_ratification_ceremony.py (14) landed in #113 in NO curated suite, so 19 tests -- including the one mechanism that can move curriculum volume -- ran only under `full`, which gates nothing. Fifth instance of this shape. Deliberately NOT fixed, recorded in the research doc: the 312-file corpus has 27 unparseable status lines and draft/ratified/active variants. A closed-vocab assertion would fail on ~35 pre-existing files and get muted, and a muted gate reads as coverage. [Verification]: smoke 555 passed in 137.73s (236 baseline + 314 + 5, +1.2s); governance pin 314 passed in 1.18s standalone and MUTATION-CHECKED -- reverting ADR-0256 to Proposed fails both invariants independently (2 failed/312 passed); orphans 19 passed; ruff clean. Canonical Python 3.12.13, uv sync --locked.
8.7 KiB
ADR-0258 — Member-chain band (Band v3-MEM): singular membership + universal premises
- Status: Accepted — ratified by Joshua Shay via the PR #108 merge (
dd2245a7, 2026-07-24) - Date: 2026-07-23
- Relates to: ADR-0257 (Band v2-EN — this is its scope-out #1), ADR-0256 (earned license), ADR-0201 (ROBDD keystone), ADR-0175/0199 (calibrated learning / arena), ADR-0253 (dual-pack serve boundary — grc/he)
1. Context
ADR-0257 §6.1 reserved the classic instantiation syllogism as the next band:
"Socrates is a man. All men are mortal. Therefore Socrates is mortal."
Band v2-EN refuses it (membership_shape_out_of_band — an is a|an clause
announces internal structure the opaque band must not flatten), Band v1b's
categorical decider has no notion of an individual (its terms are classes),
and the v1 propositional reader declines multi-word names. The eval lane pins
the gap: ds-en-0022 is gold-declined purely for want of a reading band.
The engine underneath was never the limit.
2. Decision
Add a dedicated member-argument reader + per-individual propositional
lowering (generate/proof_chain/member.py), used ONLY by the deduction
serving path as a fallback tier strictly AFTER Bands v1 / v1b / v2-EN (so
every previously-served argument is byte-identical; this band only widens):
- Closed sentence grammar (function-word dispatch, refusal-first):
- Singular fact —
<NAME> is [not] [a|an] <CLASS>(contractions expanded, plus the sententialit is not the case that <singular>prefix).<NAME>and<CLASS>are opaque token runs;isonly (no tense in v1). - Universal —
all|every|each <C1> are|is [a|an] <C2>(affirmative A-form) andno <C1> are|is [a|an] <C2>(negative E-form). - Conclusion — final sentence, sole
therefore-led, singular form only.
- Singular fact —
- Per-individual propositional lowering: collect the named individuals
(subjects of singular sentences, conclusion included); mint one opaque atom
per (individual, class) pair; each universal instantiates at EVERY named
individual —
A(C1,C2)⇒mem(i,C1) -> mem(i,C2),E(C1,C2)⇒mem(i,C1) -> ~mem(i,C2)for eachi; singular facts are literals. The same verified ROBDD engine decides; deterministic templates render the verdict over the user's own sentences (generate/proof_chain/render.py::render_entailment_member). - Number linking (the one semantic identification this band performs):
a universal's class word is usually plural ("all men") while the singular
fact uses the singular ("a man"). Two attested class tokens are identified
iff related by a closed morphology table — a curated irregular/invariant
table (men↔man, people↔person, children↔child, …; invariants like sheep,
species, news map only to themselves) consulted FIRST, then the three
regular suffix rules (
+s,+esafter sibilants,y↔ies). Table priority kills the over-link hazards (specie/species, new/news); anything the closed relation cannot relate stays distinct — under-linking costs coverage (honest UNKNOWN), never soundness. Linking is per-token, so multi-token classes ("guard dog"↔"guard dogs") link on the head noun. - Four new shape-bands —
en_member_single(exactly 1 universal),en_member_chain(≥2 universals),en_member_negative(any E-form),en_member_atomic(0 universals); priority negative > chain > single > atomic — each earning its own SERVE license through the ADR-0199 arena at n=720/band wrong=0, sealed into the same ratified ledger (unlicensed ⇒ automatically hedged, per ADR-0256).
3. Why the lowering is sound (the load-bearing argument)
- Universal instantiation is sound. Every first-order model of
∀x (C1(x) → C2(x))satisfies its instantiation at each named individual, so any model of the premises is a model of the lowered premise set. An ENTAILED/REFUTED/inconsistent verdict over the lowered set therefore holds in every model of the original premises — served at full strength. Both verdicts survive even if two distinct names co-refer: adding equality facts only ADDS premises, and entailment is monotone. - For this closed fragment the lowering is also complete. With premises restricted to singular literals and A/E universals (Boolean reading, no existential import) and a singular conclusion, a propositional countermodel lifts to a first-order countermodel whose domain is exactly the named individuals — every universal holds because every element is a named individual whose instantiation holds. So UNKNOWN means genuinely not forced within the disclosed reading — it is never an artifact of instantiating too little.
- UNKNOWN is still the one guarded verdict. Two readings could settle what the lowering leaves open: distinct names might co-refer, and class words the closed relation didn't link might be the same class. The UNKNOWN surface therefore scopes itself — "Reading each name as one individual and each class word at face value…" — same discipline as v2-EN's indivisible-clause scoping (ADR-0257 §3).
- Existential forms refuse out of band.
some/most/any/…-led sentences assert anonymous witnesses that per-individual lowering cannot represent —quantifier_out_of_band, typed. Pure categorical arguments stay with Band v1b (tried first, unchanged).
Structural guards (closed refusal vocabulary, all typed): quantifier_out_of_band,
bare_plural_out_of_band ("Dogs are loyal" — implicit genericity is a reading
this band refuses to guess), definite_description_out_of_band ("is the …" is
identity, not membership), relative_clause_out_of_band (that/which/who
inside a name or class), universal_conclusion_out_of_band (categorical
conclusions belong to v1b), mixed_structure_out_of_band (if/or/either/and
— conditional-membership fusion is a future band), internal_negation_unread,
structural_leak, sentence_shape_out_of_band, plus the v2-EN sentence
discipline (question_sentence, no_conclusion, multiple_conclusions,
conclusion_not_last, no_premises, empty_side, empty) and the honesty
caps (too_many_premises at 16, too_many_atoms at 24 minted pairs — refuse,
never truncate).
4. What the earned licenses certify
Same posture as ADR-0257 §4: the license certifies READER fidelity per shape
(the engine cannot be wrong; the reader can hand it the wrong problem). The
arena corpus is synthetic names × a class lexicon chosen to exercise every
row-type of the morphology table (irregular, invariant, +s, +es, y↔ies);
gold is authored by construction and cross-checked against the truth-table
oracle over the template's INTENDED instantiated formulas — no reader in the
loop (INV-25). The hand-authored real-English eval lane
(evals/deduction_serve/v2_member/, content disjoint from the synthetic
lexicon) keeps the structural-fidelity claim honest against natural prose,
including the promoted ds-en-0022 (declined → entailed: this band's designed
acceptance case).
5. Tri-language posture
Unchanged from ADR-0257 §5 — with one addition: the number-linking table is
CORE's first morphology table, and it is exactly the artifact class the
tri-language doctrine says must eventually enter through pack ratification
(ADR-0253). English needs ~30 closed rows; Greek/Hebrew declension is where a
curated morphology pack stops being optional. When a grc_*/he_* member
band is built, the table moves from module constants to a ratified pack; no
premature parameterization now.
6. Scope-outs (deliberate)
- Conditional–membership fusion ("If Socrates is a man then …") —
refuses
mixed_structure_out_of_band; a future band composes the v2-EN connective grammar with this band's sentence readings. - Existential premises/conclusions (
some …) — needs witness semantics; pure categoricalsomestays with Band v1b. - Tense (
was/were) and verb predicates ("Socrates runs") — refuse; verb morphology is ADR-0257 scope-out #2's territory. - Identity / definite descriptions / co-reference — refuse
(
definite_description_out_of_band); an equality-aware band is future work. - Flag posture unchanged: rides
deduction_serving_enabled(default off); no new flag.
7. Verification
uv run core test --suite deductive -q— reader contract, surfaces, license, all three lane splits, e2e throughChatRuntime.- Practice arena: 13 bands × 720 = 9,360 cases, wrong=0 required for every
band; ledger re-sealed (
chat/data/deduction_serve_ledger.json). - Eval lane: v1 28/28, v2_en 26/26 (ds-en-0022 promoted), v2_member new —
wrong=0; report re-pinned (
scripts/verify_lane_shas.py).