When accrue_realized_knowledge is on and a question turn is Determined over realized
knowledge, the user-facing surface IS that answer (generate.determine.render_determination):
'Yes — as I was told, truth is a concept.' The realizer's articulation_surface is
RETAINED as evidence — the determination is a user-facing SELECTION (like the
unknown-domain gate), not a rewrite. An Undetermined turn keeps the default
articulation surface (the honest 'I don't know'); flag-off never takes this path.
Basis is rendered honestly: SPECULATIVE grounds read 'as I was told', never 'verified'
(D0 only asserts answer=True, so the surface is an affirmation — no fabricated or
asserted-False string). Selection only: no field op, no normalization, proposes no
learning (HITL untouched).
Updates docs/runtime_contracts.md selection policy + adds the contract test in the
same PR (per the surface-contract discipline).
Wires comprehend->realize/determine into the live turn loop: a declarative turn
REALIZES a fact into the held self (session vault, SPECULATIVE/as-told); a question
turn is DETERMINED over realized knowledge (answered as-told, or refused open-world).
The first time a CORE conversation actually accumulates knowledge it can recall and
reason over — the 'one continuous life' telos made real, including across reboot
(the accrued fact is in the Shape B+ snapshot, so it survives the process ending).
Seam: all chat() returns funnel through _checkpointed_response; accrual runs there
BEFORE the checkpoint (so the fact persists this turn), gated by a new
accrue_realized_knowledge flag (default OFF — one-shot/eval runtimes don't accrue;
the production L10 process enables it with persist_session_state).
Discipline: SESSION memory, not ratified learning — proposes nothing, HITL untouched.
Realization writes go through generate.realize (INV-21 allowed writer). Additive: a
failure is a clean no-op, never crashes a turn. Slice B-1 RECORDS the outcome
(last_turn_accrual(), introspectable) and leaves the ChatResponse/surface contract
UNCHANGED; surfacing the determination is the B-2 follow-up (needs runtime_contracts
+ contract-test updates).
Tests: declarative accrues; question determines as_told; untold refuses open-world;
idempotent retell not recreated; flag-off no-ops with identical surface; and the
lived-spine proof — accrued knowledge survives reboot (determined as_told after a
fresh runtime over the same checkpoint).
A2 of the refined sequencing. Proves (deterministically, not by assertion) what a
long-running CORE life costs to persist per turn on a constrained offline device.
Measures the Shape B+ checkpoint BYTES per turn (session_state.json) over the real
turn loop — bytes, not wall-clock latency (machine-dependent → flaky). Reuses the L10
continuity corpus.
Measured cliff: save_session_state re-serializes the FULL snapshot every turn, so
per-turn bytes are O(n) in the accumulated life — 3,811 → 88,189 bytes (23x) over 24
turns, ~1.3KB/vault-entry re-written every turn. That blocks continuous-life at the edge.
The gate encodes the edge REQUIREMENT (≤16 KiB/turn regardless of session length) as
xfail(strict): it fails today (documenting the cliff), runs green in CI, and flips to
a hard failure the moment incremental/append-only persistence (O(Δ)/turn) lands —
forcing us to retire it. Plus a regression ceiling (passes today) and a determinism
check (the byte metric is reproducible → a valid gate).
The fix is algorithmic (incremental persistence, Python/Ring-2), NOT a language
rewrite. Tagged core/array_codec.py as the locked reference contract for a future
gated Ring-1 Zig byte-exact codec (ADR-0196 G0-G8) — step 3, only after the O(Δ) fix
and only if this gate proves the codec is still the bottleneck. See contract.md.
A1 of the refined sequencing — the binary-relation reader was inert w.r.t. the
yardstick (contributing 0). This adds a comprehension_relational_predicate domain:
binary-relation prose scored against hand-authored independent gold (predicate,
subject, object) triples — INV-25 independent / INV-27 reader-disjoint (the reader
never produced the gold). Index breadth 8->9, capability_score 0.937258->0.944030,
wrong_total still 0; baseline.json re-frozen to digest 1ea91c1e.
Rigor split: the index lane is POSITIVE-ONLY (clean coverage, consistent with the
other 8 lanes — mixing adversarial refuse-cases into the coverage denominator would
make 'added capability' read as a score drop). The #596 fabrication-catch lives in a
dedicated falsification test (evals/relational/v1/refusals.jsonl): the trailing-
qualifier / dangling-copula / negation / verb-form cases MUST refuse — bites if the
reader ever fabricates. Honest coverage gap recorded: overlaps_event has no copular
surface form (verb-form 'A overlaps B' refuses), so 17 positives cover 15/16 predicates.
Lookback (adversarial verify) found a comprehension-layer wrong=0 hole: an argument
slot only refused on reader._RESERVED tokens, so connective heads leaked through —
'Carol is the sibling of Dan during school.' fabricated sibling_of(carol,
dan_during_school) and realized it, while the asymmetric twin '… during the trip.'
refused (article leaked). The fabricated compound entity entered realized memory,
breaching the never-fabricate floor.
Fix: (1) argument slots must be FREE of connective tokens (a leaked connective head =
unparsed relational structure -> refuse 'extra_relational_structure'); (2) the copula
must sit STRUCTURALLY adjacent to the connective, so a dangling copula ('Monday before
Friday is.') and a period-question-as-statement ('Is Monday before Friday.') refuse
instead of fabricating a fact. determine stays sound by construction; this closes the
reader-layer hole. Bite tests added for both classes + a 'no fabricated entity enters
realized memory' assertion.
First consumer of en_core_relational_predicates_v1: a fail-closed sibling reader
that maps '<A> is [the] <connective> <B>' onto the pack's closed predicate
vocabulary (parent_of, less_than, left_of, before_event, ...), producing a standard
Comprehension. realize_comprehension consumes it unchanged; determine's guard widens
from the single 'member' predicate to a CLOSED direct-entailment set (member + the
ground binary relational predicates), keeping categorical/propositional predicates
soundly excluded.
Direct entailment only — no transitive/symmetric/rule inference (symmetric-converse
questions are a sound-but-incomplete refusal, never a faked assertion). Only the
predicate is closed-vocabulary; arguments may be OOV. The pack is loaded explicitly,
not default-mounted.
wrong=0 bites: reader refuses non-template/negated/pack-absent surfaces; determine
asserts only on direct entailment and excludes categorical predicates.
From the mandated lookback audit: three D0 refusal branches were asserted-but-unproven.
Now they bite:
- not_single_query: reachable from REAL input — a two-question prompt yields two queries.
- malformed_query: a unary `member` query (hand-built; the reader only emits arity-2).
- not_a_comprehension: a non-Comprehension/Refusal input.
No code change — determine.py already refused all three; this closes the
schema-proof-obligation gap (each would now fail if its guard were removed).
From the mandated lookback audit of the composed R0→R1→R1c→OOV surface:
- wrong=0 HAZARD (medium): realize_quantitative trusted equation admissibility it
never checked. `comprehend_quantitative` runs real check_admissibility, but the
type does not enforce it, so a future non-reader constructor could slip a
dimensionally-incoherent 'pending'/'refused' equation into the held self (then
surfaced as-told by DETERMINE). Now RE-ASSERTS admitted-status defensively ->
NotRealized("unadmitted_equation"); docstring corrected to match (no longer claims
the type guarantees it). Bite test via a hand-built pending-equation graph.
- Defensive: wrap binding_graph hashing -> NotRealized("unhashable_structure") so a
future numeric field is a clean refusal, not an uncaught TypeError mid-write.
- Coverage (the obligations now bite, not decoration): unadmitted_equation,
not_a_quant_comprehension, no_bound_fact, grounding_failed (monkeypatched probe),
cross-substrate coexistence (meaning_graph + binding_graph in one vault — recall
isolates, structure_keys differ), and the negated_relation refusal (hand-built,
since the reader encodes declarative negation in the PREDICATE not rel.negated).
- Drift: R0 idempotency test now names the actual dedup key (structure_key, not
content_hash); scope doc notes #591 made OOV placement injective (the §0/§1
non-injectivity finding describes the pre-#591 substrate).
Note: the lookback flagged negated_relation as a high reachable-untested hazard, but
verification showed the reader never sets rel.negated=True for declaratives (it
refuses "X is not a Y" or uses some_not/disjoint predicates) — so it is a defensive
branch, tested via a hand-built graph. Green: 35 realize + ruff clean.
The honest gear (roadmap Step 4). `determine(question: Comprehension | Refusal, ctx)`
answers a membership question ("Is X a Y?") ONLY from what the held self has already
REALIZED (R1a structural recall) — never from the field, an LLM, or absence.
Honesty (from the design review): every realizable record is SPECULATIVE, and
ADMISSIBLE_AS_EVIDENCE = {COHERENT}, so a determination grounded in SPECULATIVE records
carries `basis="as_told"` — "based on what I was told (unverified)", NEVER "verified".
Until COHERENT promotion exists (out of scope), D0 produces only as-told assertions or
typed `Undetermined` refusals. No estimation; no corpus mutation (teaching stays HITL
proposal-only).
Soundness (open-world, wrong=0): D0 asserts an answer ONLY on DIRECT structural
entailment by a realized fact; absence never refutes (so it never asserts a positive
answer from missing knowledge — it refuses). It asserts only `answer=True` on a direct
hit; it never asserts False. Negated questions and non-`member` queries are an explicit
`Undetermined` — D0 ships no entailment path the reader cannot exercise.
Tests (test_determine_d0.py, 8) BITE: present-but-non-entailing (a record about the
subject exists but not the asked relation) MUST refuse; the same question against a
fresh context with no realized fact flips Determined→Undetermined (the verdict is
entailment, not mere presence); the negated + unsupported-query refusals are exercised
via hand-built queries (the reader refuses them upstream, so a comprehend-based test
would pass vacuously). Independent of #593: reasons over R0/R1 `member` facts only.
Generalizes what REALIZE accepts, on the structural-key foundation from #592.
R1c — binding_graph / arithmetic realize:
- `realize_quantitative(QuantComprehension | Refusal, ctx)` realizes a comprehended
arithmetic structure (its admissibility-checked binding_graph) as a SPECULATIVE
record with `structure_kind="binding_graph"` and a span-free `structure_key` over
symbols/facts/equations. The only wrong=0 guard needed is the `Refusal` check —
factless input is already a Refusal upstream (the fact-count gate would be vacuous).
- Extracts the shared `_realize_structured` write path so meaning_graph and
binding_graph share ONE wrong=0 dedup/store point (the `.store` call stays in the
INV-21-allowlisted realize.py).
OOV — lift the in-vocab subject gate:
- R0 declined OOV subjects on the mistaken belief that OOV grounding is
non-deterministic. It is deterministic and reboot-stable, and #591 makes it
injective. Correctness rests on the structural key, not the versor, so OOV subjects
now realize normally. The "side-effect-free" comment is corrected: probe_ingest of
an OOV token mutates the shared vocab via a session-scoped `insert_transient` that
is NOT serialized into the snapshot, so reboot-stability rests on the vault record.
Honesty: the binding_graph entities (alice, the synthesized `total`) are symbolic/OOV
so the placement versor is deterministic-GIVEN-session-state, NOT subject-determined;
reboot-stability is carried by the Shape B+ snapshot of the exact bytes, and
distinctness by structural recall — never the (possibly colliding) metric. SPECULATIVE
always; versor_condition<1e-6 + exact CGA recall preserved; no parallel learning path.
Tests: test_realize_r1c_binding_graph.py (8) + test_realize_oov.py (6, incl. a
fresh-vocab reboot proving stability rests on the vault record not the transient) +
test_realize_r0.py oov test flipped to realize. Green: 35 realize + smoke locally.
R0 keyed a realized fact by its subject's field versor, which is NOT injective:
two facts about one subject embed to byte-identical versors and collide at inf on
metric recall (proven). R1 adds the missing structural key.
- RealizedRecord/metadata carry ordered `relation_arguments` (the relation-space
key R0's sorted `entity_names` discards) and a span-free `structure_key`.
- `recall_realized(ctx, subject=/predicate=/content_hash=/structure_key=/
structure_kind=/entity=)` retrieves realized facts by EXACT structural metadata
(no metric / ANN), via a new read-only `VaultStore.iter_metadata()` accessor.
- Idempotency now dedups on the span-free `structure_key`, so the same proposition
told from a different source/offset collapses (R0's span-inclusive content_hash
could not). Guarded by an ambiguous-entity-name refusal — a wrong=0 defense,
since `Entity.name` is non-unique in the model (only `entity_id` is enforced).
- `content_hash` retained for provenance + replay_hash; `vault_index` pinned to the
live deque position.
Design adversarially verified (docs/analysis/REALIZE-R1-DETERMINE-scope-2026-06-06.md);
the false "established pattern" private-access comment is removed in favor of the
public accessor. wrong=0 + versor_condition<1e-6 + exact CGA recall preserved;
vault/store.py adds only a read-only accessor (no normalization). Green: 23 realize
+ 110 invariant/vault + 90 smoke; ruff check clean.
REALIZE roadmap Step 3, slice R0: the boundary that turns comprehension from an
EVAL ARTIFACT into accumulating living knowledge. A comprehended declarative fact is
integrated into the held self as a structured vault entry (versor, metadata) — NOT a
new store — so it inherits exact cga_inner recall, EpistemicStatus stamping, and
bit-exact Shape B+ persistence for free. Scope: docs/analysis/REALIZE-scope-2026-06-06.md.
generate/realize/realize.py — realize_comprehension(Comprehension|Refusal, ctx) ->
Realized(record, created) | NotRealized(reason):
- eligibility: a Comprehension (not Refusal) with NO queries and EXACTLY ONE
non-negated relation whose subject grounds IN-VOCABULARY. Everything else is a
typed NotRealized with zero vault writes (wrong=0).
- in-vocab-subject only: OOV grounding is non-deterministic across reboots (an
empirically-confirmed substrate gap), so OOV subjects are declined in R0.
- SPECULATIVE always (COHERENT is never a default — ADR-0021); provenance via
MeaningSpan source_span + structure_canonical; content_hash + replay_hash via
canonical-JSON SHA-256 (floats forbidden).
- idempotency: dedup by content_hash within the session (exact-canonical,
span-inclusive — safe direction only, never drops a distinct fact).
- durable schema admits a 2nd substrate later via structure_kind/structure_canonical.
- stores via the existing VaultStore.store path: no new embedder, no normalization
(closure stays algebra/versor.py), no parallel learning path.
Explicitly OUT of R0: COHERENT promotion, teaching-loop proposals, trace-folding,
relation-space recall, the arithmetic/binding_graph path.
tests/test_realize_r0.py (10) — eligibility (refusal/query/multi-relation/OOV all
write nothing); record fields; idempotency (re-told fact doesn't grow the vault);
SPECULATIVE status firewall (recall(min_status=COHERENT) excludes it); the
falsifiable exit gate (told -> realize -> snapshot -> reboot -> recall: byte-exact
content_hash + score + versor bytes, speculative, versor_condition<1e-6); and
replay_hash re-derivable after reboot. Gate verified to BITE (COHERENT default,
refusal-writes, reprojection-on-load all fail it).
INV-21: generate/realize/realize.py added to ALLOWED_VAULT_WRITERS — a sanctioned
writer (same VaultStore.store path, SPECULATIVE default, nothing on Refusal).
Adversarially reviewed (3 lenses: invariants/wrong0/honesty, determinism/boundary,
scope/adjustments) — no critical/high/medium findings; low/nit honesty wrinkles
folded (state-dependent-placement wording, span-inclusive-dedup note, direct
versor-bytes gate assert, replay_hash re-derivation test). 10 R0 + 90 smoke green;
lane SHAs 8/9 (sole miss = public_demo env flake; deductive_logic + math_teaching
unchanged -> no GSM8K coupling).
Scopes REALIZE (comprehended/told structure -> the held self with an
EpistemicStatus, persisted via Shape B+, recalled exactly) — roadmap Step 3, the
boundary that turns comprehension from an eval artifact into accumulating living
knowledge; intake ("being told") lands here.
Produced by a reconnaissance -> design -> adversarial-verification pass over the
real substrate (vault, EpistemicStatus, Shape B+ persistence, teaching/intake,
comprehension output, determinism/replay). Central finding: a realized record is a
structured vault entry (versor, metadata), NOT a new store — so it inherits exact
cga_inner recall, EpistemicStatus stamping (teaching/epistemic.py already exists),
and bit-exact snapshot/restore for free.
Defines the realized-knowledge record, the told->realize->recall->survives-reboot
contract, the composition seams (verified APIs), the obligations (wrong=0,
provenance, EpistemicStatus honesty, no forbidden normalization, no parallel
learning path, determinism), slice R0 + a falsifiable exit gate, and the design
forks/risks/open-questions.
Adversarially corrected: R0 must catch embedding KeyError/empty-decomposition ->
no-op (+ OOV grounding determinism); determinism is state-restore-based not
input-pure (versor/score are session-state-dependent); MeaningSpan (not
SourceSpanLink) is the provenance API; sharpened gate arms (history-dependence +
idempotency/placement re-run).
The binding-graph's FIRST comprehension consumer (doctrine-aligned: quantities live
in binding_graph, NOT the MeaningGraph). generate/quantitative_comprehension.py
reads arithmetic prose into SymbolBinding/BoundFact/BoundEquation and runs the REAL
check_admissibility (shell -> verify -> rebuild with the actual UnitProof) — there
is NO stamped "admitted": an equation is admitted only if its operand units verify.
Then to_relational_metric projects the binding-graph to the independent
relational_metric oracle for the verdict.
Templates (digits only; non-digit quantity REFUSES):
"<X> has <N> <unit>" -> BoundFact(X = N)
"<Y> has <N> more <unit> than <X>" -> BoundEquation(Y = X + N) op=add
"<Y> has <N> fewer <unit> than <X>" -> BoundEquation(Y = X - N) op=subtract
"How many <unit> does <Y> have" -> ask Y
"How many <unit> do <X> and <Y> have"-> total = X + Y; ask total
Unit modelling (honest, not faked): a noun the closed en_units_v1 pack knows is
used verbatim (dollars -> dollar/money); an UNKNOWN sortal noun (stickers, coins)
is a count of discrete objects -> the existing 'item' lemma (dimension count). So
admissibility stays a REAL check: count+count admits, count+money (a mixed-unit
sum) REFUSES with unit_mismatch — verified to bite.
comprehension_relational_metric: 15/15 wrong=0 (full coverage). Located OUTSIDE
generate/meaning_graph (it targets binding_graph, not the MeaningGraph) so INV-28
neutrality stays intact; oracle imports none of the SUT (new INV-25 lane).
Capability index breadth 7->8, score 0.928622 -> 0.937258, wrong_total 0, digest
50e0675b…
Tests: reader templates + count/known-unit modelling + admissibility-bite (mixed
unit refuses) + non-digit refusal; end-to-end full-coverage wrong=0; arithmetic
added to the structure-preservation generative panel (projected relations+query ==
ground truth); capability breadth 7->8; INV-25 arithmetic lane. 93 targeted + 90
smoke green; lane SHAs 8/9 (sole miss = public_demo env flake; deductive_logic +
math_teaching unchanged -> no GSM8K coupling).
Addresses the review's hygiene point: the comprehension lanes deserve the same
repo-wide independent-gold + neutrality discipline as the older reasoning lanes.
INV-25 (independent gold): register the four comprehension lanes
(set_membership / syllogism / total_ordering / propositional) so their domain
oracles are statically proven to import NONE of the comprehension organ
(generate.meaning_graph reader + projectors). The gold the reader is scored
against is thereby independent of the reader — the anti-overfit firewall now covers
comprehension, not just the structured-input lanes. All four oracles are clean
(stdlib-only), so the firewall passes.
INV-28 (MeaningGraph neutrality): a new repo-wide invariant mirroring INV-26's
binding-graph neutrality — no generate/meaning_graph module imports
field/algebra/evals/vault/chat/core/sensorium or numpy. The MeaningGraph is the new
neutral meeting point where prose-read structure projects into independent oracles;
it earns the same firewall. numpy is forbidden too: Path β reads structure
SYMBOLICALLY and quantities are the binding-graph's domain, not the MeaningGraph's.
Non-vacuity test included (the predicate flags a module known to import the field
engine).
Tests-only. 56 architectural-invariant tests pass (was 53 + 3 new INV-28 +
4 INV-25 lanes wired into the existing oracle-firewall test).
Addresses the central review finding: the generative wrong=0 tests compared oracle
VERDICTS, so a misread graph that coincidentally yields the same verdict passed
silently (coincidental correctness in cleaner clothes). This adds the conjugate
check — the reader must recover the EXACT structure the prose encodes, not merely a
verdict-equivalent one.
tests/test_comprehension_structure_preserving.py:
- Structure preservation (all 4 domains): over randomly generated structures
rendered to prose that FULLY determines them, assert projected structure AND
query == ground truth exactly (order-insensitive canonicalization), or refuse.
Empirically this is strictly stronger: under a subject<->predicate premise swap,
361/400 reads are structurally wrong and 307 of those (85%) coincide in verdict
— the answer test misses all 307; the structure test catches all 361.
- Perturbation invariance: meaning-preserving surface changes (premise/clause
reordering, capitalization, extra whitespace) yield the SAME structure.
The existing answer-preservation property tests stay (verdict agreement is still a
valid, separate check — exactly the "assert structure, then separately assert
oracle agreement" the review recommends). Tests-only; no source change; capability
index unchanged. 7 new + 86 comprehension/capability targeted green.
Execution-ready brief for the next comprehension increment (user-chosen,
doctrine-aligned): read arithmetic word-problem prose into the binding_graph
quantity substrate -> project to the independent relational_metric oracle ->
wrong=0. Reuses the existing 15-case relational_metric gold lane (no gold
authoring).
Captures the full scope from this session: the oracle grammar (fact/more_than/
fewer_than/sum_of), the new number-parsing reader capability, binding_graph
construction (SymbolBinding/BoundFact/BoundEquation with REAL admissibility — a
proof obligation, not a stamp), the direct-construction recommendation (keep the
comprehension organ disjoint from the GSM8K MathProblemGraph / serving path), the
projector, wiring, the generative round-trip anti-overfit test, and the
validation gates.
Briefed rather than rushed: this is binding_graph's first comprehension consumer,
a load-bearing integration whose correctness hinges on real equation
admissibility — it deserves fresh context, per "no shortcuts on architectural
gaps".
Adds comprehension_propositional — the comprehension organ now reads the classic
propositional ARGUMENT FORMS end-to-end into the flagship deductive_logic ROBDD
oracle (the most robustly independent gold in the repo). The neutral MeaningGraph
now feeds FOUR independent oracles (set-membership, syllogism-validity,
total-ordering, propositional-entailment) from one interlingua — the Option-B
interlingua thesis validated.
reader.py: propositional templates (atoms are chunked NP ids; fits the existing
entities + n-ary relations + negation model — NO interlingua change, propositional
is not arithmetic-quantities):
- "if <P> then <Q>" -> implies(P, Q)
- "not <P>" -> asserted(P, negated=True)
- "<P> or <Q>" -> or(P, Q)
- "<P>" (single token) -> asserted(P) (bare-atom, single-token only to
keep the parse-or-refuse floor)
- "therefore <prop>" -> query of the same predicate
Relations now carry a negated flag end-to-end (asserted negation).
projectors.py: to_deductive_logic serializes propositional relations/query into
formula strings (keyword operators the oracle tokenizer accepts); returns None
(refusal) unless the comprehension is purely propositional, so categorical/ordering
comprehensions never leak into the entailment oracle.
evals: new evals/propositional_logic/v1 (12 cases — modus ponens/tollens,
hypothetical & disjunctive syllogism, the affirming-consequent / denying-antecedent
fallacies which the oracle marks "unknown"; gold = oracle verdict) + gold-only
runner + evals/comprehension/propositional_runner.py. Oracle "refused" (formula
unevaluable) is treated as a decline, never a wrong.
Scores: comprehension_propositional 12/12 wrong=0 (full coverage); no regression on
the 3 existing lanes (8/8, 7/8, 7/8). Capability index breadth 6->7, score
0.917231 -> 0.928622, wrong_total 0, digest 51df7bba…
Tests: reader propositional templates; to_deductive_logic projector tests;
end-to-end full-coverage wrong=0; propositional generative round-trip added to the
wrong=0 property suite (verified to BITE under a reversed-implies mutation);
capability breadth 6->7. 115 targeted + 87 smoke green. Lane SHAs 8/9 (sole miss =
public_demo env wall-clock flake; deductive_logic_v1 unchanged).
Recovers the multi-word-NP cases the reader previously refused, by adopting ONE
principled canonicalization contract (evals/comprehension/CANONICALIZATION.md) that
the reader AND the gold lanes both follow — so a committed answer can only match
gold or refuse, never silently mean something else.
Contract: a noun-phrase slot -> tokens lowercased, joined with "_"; a plural class
slot singularizes its head first ("metal objects"->"metal_object",
"North station"->"north_station", "Level one"->"level_one"). JOIN is chosen over
head-word-only ("metal objects"->"metal") because head-word-only is
information-destroying — it collapses "metal objects" and "metal tools" into one
false identity, itself a wrong=0 hazard.
reader.py: slot-based templates chunk multi-token NPs (_chunk / _chunk_class
replace the single-token _one / _one_class). Reserved-function-word guard fires only
INSIDE a multi-token slot (a lone "A" item is content, not the article). Still
parse-or-refuse: reserved-word leaks ("Compare beta with beta in the same order"),
non-pluralizable class heads (adjectival "trained"), and the ambiguous adjacent
two-NP subset query ("Are all <Xs> <Ys>?") all REFUSE.
gold (the contract update, logic-preserving — only term NAMES change):
- sy-v1-0008: metal/soft -> metal_object/soft_object (was head-word-only)
- to-v1-0005: red -> red_rank (was head-word-only)
- to-v1-0004: prose made internally consistent ("is after", "north station") +
north -> north_station (original prose used "North station" in the fact but
"north" in the query — a latent inconsistency)
- to-v1-0007: already conformed (level_one…), no change
Gold-only integrity runners stay 8/8 both lanes (structure+query+gold consistent).
Scores: set_membership 8/8, syllogism 6/8->7/8, total_ordering 4/8->7/8, all
wrong=0. Capability index re-frozen: score 0.814356 -> 0.917231, breadth 6,
wrong_total 0, digest 13d7db6c…
Tests: reader chunking + refusal tests; multi-word generative round-trip added to
the wrong=0 property suite (verified to BITE under a head-word-only mutation —
collapsed ids produce a wrong verdict the test catches); pinned counts updated.
100 comprehension/capability targeted + 87 smoke green.
Proves the wrong=0 invariant GENERALIZES beyond the 8-case gold lanes. Over 1000
randomly generated single-word problems across all three domains, the reader
either refuses or reproduces the EXACT verdict the independent oracle gives on the
ground-truth structure the prose encodes — it never changes the answer.
Non-circular: the generated structure S is ground truth; we render prose P(S),
then compare oracle(project(comprehend(P(S)))) to oracle(S) computed directly.
The oracle is independent of the reader, so agreement = lossless carry and refusal
= honest decline; both are wrong=0. Verified to BITE: flipping a comparator
direction makes the total_ordering case produce a reversed sort the test catches.
Single-word vocab on purpose — multi-word NPs are the known gold-canonicalization
wall the reader refuses; the generator stays in the readable regime where
faithfulness is the whole claim. Anti-overfit: random vocab proves the templates
key on function words + order, not on memorized gold content.
Phase 2a r2/r3/r4 of the redefined plan: the general comprehension reader now
reads THREE independent-gold reasoning domains end-to-end (prose -> MeaningGraph
-> projection -> independent oracle -> answer vs gold), all wrong=0, and all
three are wired into the capability index.
reader.py — new domain-agnostic templates (function words + order; parse-or-refuse):
- categorical E/I/O: "no Xs are Ys"->disjoint, "some Xs are Ys"->intersects,
"some Xs are not Ys"->some_not (A "all Xs are Ys"->subset already existed)
- "therefore <categorical>" -> conclusion QUERY (same neutral predicate vocab)
- comparative facts: "<X> [is] <comp> [than] <Y>" -> less(...), closed
less/greater comparator lexicon, elided-copula support
- sort query ("sort ascending|descending", "... order from <low> to <high>")
and compare query ("compare <X> with <Y>")
- clause-splitting on commas / leading and|or for multi-clause sentences
projectors.py — to_syllogism (premises + validity conclusion, finite-model size 3)
and to_total_ordering (less-facts + sort/compare). Both return None when nothing
is honestly askable of their oracle (caller treats as refusal).
capability_index — wire 3 comprehension lanes into ADAPTERS; re-freeze baseline
breadth 3->6, capability_score 0.919641->0.814356 (geomean falls BY DESIGN as
honest partial-coverage domains join; wrong_total stays 0). digest 0a98b9b4...
Scores: set_membership 8/8, syllogism 6/8, total_ordering 4/8 — all wrong=0.
Multi-word NP handling is DEFERRED on purpose, not missed: the gold lanes
canonicalize multi-word NPs three contradictory ways ("North station"->"north",
"Level one"->"level_one", "metal objects"->"metal"), so no single general rule is
wrong=0-safe. The reader refuses multi-word NPs until the gold lanes carry a
canonicalization contract. Every refusal is a genuine harder phenomenon
(multi-word NP, adjectival predicate, trailing tokens) — never a readable case
silently dropped.
Tests: reader templates, projector unit tests, syllogism/total_ordering
end-to-end wrong=0 with pinned counts, capability breadth 3->6. 138 targeted +
87 smoke green. Lane SHAs 8/9 (sole miss = public_demo env wall-clock flake).
Disciplined Path β (field decode α was empirically falsified). Reads S-P-O
structure SYMBOLICALLY from the token sequence via domain-agnostic templates
keyed on FUNCTION WORDS + ORDER, mints content as MeaningGraph entities/relations,
parse-or-refuse (wrong=0 at the comprehension layer).
Templates (set_membership): 'X is a Y' -> member; 'all Xs are Ys' -> subset;
'is X a Y?' / 'are all Xs Ys?' -> queries; definite-NP ('the X is a Y');
conservative singularization incl. irregulars (people->person), refusing
unknown morphology rather than guessing.
End-to-end: prose -> comprehend -> project -> INDEPENDENT set_membership oracle
-> answer vs gold. Result on the real v1 lane: 8 correct / 0 wrong / 0 refused
(full coverage, wrong=0). Cross-content generality (animals/professions/geography)
asserted. 14 reader unit tests + 3 end-to-end tests, each bites under its
violation. Additive only; invariants + capability index green.