feat(evals): grammar round-trip instrument — CORE cannot read its own writing (0/280) #130
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/grammar-roundtrip-instrument"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Phase 1 of the plan of record (#128, corrected by #129). New files only — no serving code, no corpus, no pin touched. Rebased onto
041c6202, so the diff is +1436/−0 across 9 files.What this is
The arc's claim is that CORE has two grammars — one for reading, one for writing — and they were never checked against each other. That claim was unfalsifiable because there was no instrument. This is the instrument.
Three measurements, deliberately reported separately:
read(write(g)): take a graph, write it to English, read it back, compare propositions.write(read(s)): take a sentence, read it, write it back, compare strings.evals/grammar_roundtrip/projection.pyexists becauseMeaningGraphandPropositionGraphare not type-compatible (n-aryRelationwith source spans vs. SPOGraphNodewith discourse edges). Both project into aCanonicalPropositionfrozenset. The lane keeps its own local copy of_QUANTIFIER_PREDICATEso it never consumes the thing it measures;test_quantifier_map_matches_readerpins the copy to the original.Baseline, measured on this branch
graph_casesg_write_rateg_read_rateg_propositions_expectedg_args_rate/g_predicates_rate/g_exact_ratesurface_casess_read_rates_renderable_rates_surface_match_ratenegative_casesreject_ratereject_rateis not trivially green. The same reader accepts 8/8 positives and refuses 16/16 negatives — it discriminates. If it simply refused everything,s_read_ratewould be 0.0, not 1.0. The negatives reuse the positives' own vocabulary (pinned bytest_shuffled_negatives_reuse_positive_vocabulary), so rejection is about structure, not unknown words. Shuffles use a fixed rotation rather than a PRNG, soreject_rateis byte-reproducible.The defect it caught without being asked to
s_surface_match_rate = 0.0surfaced a live, user-visible defect on a ratified flag-ON band.generate/proof_chain/render.py::_categorical_clauseformats"all {s} are {p}"with the singular subject:CORE currently serves "all dog are mammal" — 4 of the 47 ratified
deduction_servecorpus cases.wrong=0is intact: every verdict is still correct. Only the prose is wrong, which is exactly the class of defect a verdict-only gate cannot see. Pinned concretely bytest_the_categorical_render_defect_concretelyso the fix in Phase 2B has to move a number.What this does NOT prove
Round-trip agreement is mutual intelligibility, not English quality. A writer and a reader that share the same bug agree perfectly.
contract.mdsays this in the lane's own words. Round-trip is necessary and not sufficient — grammaticality still needs a grammar, which is Phase 2 onward.Mutation guarantees
A pin that cannot fail is worthless. Each of these goes red under the mutation named:
test_reject_rate_goes_red_when_the_reader_accepts_everything— monkeypatchescomprehendto always succeed ⇒reject_rate1.0 → 0.0.test_the_categorical_render_defect_concretely— fixing the renderer without updating the pin ⇒ red (intentional; Phase 2B must touch it).test_quantifier_map_matches_reader— the lane's local map drifting fromreader.py⇒ red.test_positive_surfaces_are_all_inside_the_reader_envelope— adding a positive the reader can't read ⇒ red, sos_read_ratecan't be gamed by corpus choice.scripts/measure_grammar_seam.pyreproduces every §1 number in the plan (tables,agreement,readers,served,roundtrip).[Verification]: in-worktree on CPython 3.12.13 with
uv sync --locked, after rebase onto041c6202—uv run core test --suite smoke -q621 passed;uv run core test --suite deductive -q364 passed (349 + 15 new, also run by the pre-push gate);scripts/verify_lane_shas.py11/11 match pinned SHAs. No serving module, corpus, or pin modified — the only non-new-file change is one line addingtests/test_grammar_roundtrip.pyto thedeductivesuite tuple incore/cli_test.py.