From ae84ce8641b9c43dba4de6f1635a359e0b92c30a Mon Sep 17 00:00:00 2001 From: Shay Date: Sat, 30 May 2026 19:12:45 -0700 Subject: [PATCH 01/12] feat(language): add en core syntax pack manifest --- .../data/en_core_syntax_v1/manifest.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 language_packs/data/en_core_syntax_v1/manifest.json diff --git a/language_packs/data/en_core_syntax_v1/manifest.json b/language_packs/data/en_core_syntax_v1/manifest.json new file mode 100644 index 00000000..78baf751 --- /dev/null +++ b/language_packs/data/en_core_syntax_v1/manifest.json @@ -0,0 +1,16 @@ +{ + "pack_id": "en_core_syntax_v1", + "language": "en", + "role": "operational_base", + "script": "Latin", + "normalization_policy": "unitize_versor", + "source_manifest": "en_core_syntax_v1.lexicon.jsonl", + "determinism_class": "D0", + "checksum": "20154c1a29b8e11b5e2c59d728469f7d8989ea740ab9561c36e7f7f6f835e48c", + "version": "1.0.0", + "gate_engaged": true, + "oov_policy": "tagged_fallback", + "definitional_layer": true, + "provenance": "foundation-curriculum:reviewed:2026-05-30", + "glosses_checksum": "6acad97aec04704a5f174eb5d33b30434b67c8fad4efdc97a4e8334b532b7641" +} From 212b078f720959cb679795b0f94e9591a4f0a4f4 Mon Sep 17 00:00:00 2001 From: Shay Date: Sat, 30 May 2026 19:13:40 -0700 Subject: [PATCH 02/12] feat(language): add en core syntax lexicon --- .../data/en_core_syntax_v1/lexicon.jsonl | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 language_packs/data/en_core_syntax_v1/lexicon.jsonl diff --git a/language_packs/data/en_core_syntax_v1/lexicon.jsonl b/language_packs/data/en_core_syntax_v1/lexicon.jsonl new file mode 100644 index 00000000..2cee8693 --- /dev/null +++ b/language_packs/data/en_core_syntax_v1/lexicon.jsonl @@ -0,0 +1,24 @@ +{"entry_id":"en-core-syntax-001","surface":"subject","lemma":"subject","language":"en","pos":"NOUN","semantic_domains":["syntax.role.subject","claim.argument.subject","grammar.core"],"morphology_tags":["noun","syntactic_role"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-002","surface":"predicate","lemma":"predicate","language":"en","pos":"NOUN","semantic_domains":["syntax.role.predicate","claim.relation.predicate","grammar.core"],"morphology_tags":["noun","syntactic_role"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-003","surface":"agent","lemma":"agent","language":"en","pos":"NOUN","semantic_domains":["syntax.role.agent","event.participant.actor","claim.argument.agent"],"morphology_tags":["noun","semantic_role"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-004","surface":"patient","lemma":"patient","language":"en","pos":"NOUN","semantic_domains":["syntax.role.patient","event.participant.undergoer","claim.argument.patient"],"morphology_tags":["noun","semantic_role"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-005","surface":"object","lemma":"object","language":"en","pos":"NOUN","semantic_domains":["syntax.role.object","event.participant.object","claim.argument.object"],"morphology_tags":["noun","syntactic_role"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-006","surface":"modifier","lemma":"modifier","language":"en","pos":"NOUN","semantic_domains":["syntax.role.modifier","claim.qualifier","grammar.attachment"],"morphology_tags":["noun","syntactic_role"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-007","surface":"clause","lemma":"clause","language":"en","pos":"NOUN","semantic_domains":["syntax.unit.clause","claim.boundary.clause","grammar.unit"],"morphology_tags":["noun","syntax_unit"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-008","surface":"sentence","lemma":"sentence","language":"en","pos":"NOUN","semantic_domains":["syntax.unit.sentence","claim.surface.sentence","grammar.unit"],"morphology_tags":["noun","syntax_unit"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-009","surface":"phrase","lemma":"phrase","language":"en","pos":"NOUN","semantic_domains":["syntax.unit.phrase","grammar.unit","claim.fragment"],"morphology_tags":["noun","syntax_unit"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-010","surface":"antecedent","lemma":"antecedent","language":"en","pos":"NOUN","semantic_domains":["syntax.condition.antecedent","logic.condition.input","claim.condition.antecedent"],"morphology_tags":["noun","conditional_role"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-011","surface":"consequent","lemma":"consequent","language":"en","pos":"NOUN","semantic_domains":["syntax.condition.consequent","logic.condition.output","claim.condition.consequent"],"morphology_tags":["noun","conditional_role"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-012","surface":"referent","lemma":"referent","language":"en","pos":"NOUN","semantic_domains":["syntax.reference.referent","semantic.entity.reference","claim.argument.referent"],"morphology_tags":["noun","reference_role"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-013","surface":"anaphor","lemma":"anaphor","language":"en","pos":"NOUN","semantic_domains":["syntax.reference.anaphor","discourse.backreference","claim.reference.surface"],"morphology_tags":["noun","reference_role"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-014","surface":"qualifier","lemma":"qualifier","language":"en","pos":"NOUN","semantic_domains":["claim.qualifier","syntax.modifier","semantic.constraint"],"morphology_tags":["noun","claim_term"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-015","surface":"scope","lemma":"scope","language":"en","pos":"NOUN","semantic_domains":["claim.scope","logic.scope","syntax.boundary.scope"],"morphology_tags":["noun","claim_term"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-016","surface":"polarity","lemma":"polarity","language":"en","pos":"NOUN","semantic_domains":["claim.polarity","logic.truth_orientation","syntax.negation.axis"],"morphology_tags":["noun","claim_term"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-017","surface":"coordination","lemma":"coordination","language":"en","pos":"NOUN","semantic_domains":["syntax.coordination","logic.composition","claim.join"],"morphology_tags":["noun","composition_term"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-018","surface":"conjunction","lemma":"conjunction","language":"en","pos":"NOUN","semantic_domains":["syntax.coordination.conjunction","logic.conjunction","claim.join.and"],"morphology_tags":["noun","logical_operator"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-019","surface":"disjunction","lemma":"disjunction","language":"en","pos":"NOUN","semantic_domains":["syntax.coordination.disjunction","logic.disjunction","claim.join.or"],"morphology_tags":["noun","logical_operator"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-020","surface":"negation","lemma":"negation","language":"en","pos":"NOUN","semantic_domains":["syntax.negation","logic.negation","claim.polarity.negative"],"morphology_tags":["noun","logical_operator"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-021","surface":"exception","lemma":"exception","language":"en","pos":"NOUN","semantic_domains":["syntax.exception","logic.exception","claim.scope.exception"],"morphology_tags":["noun","logical_operator"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-022","surface":"comparison","lemma":"comparison","language":"en","pos":"NOUN","semantic_domains":["syntax.comparison","comparative.relation","claim.comparison"],"morphology_tags":["noun","relation_term"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-023","surface":"attachment","lemma":"attachment","language":"en","pos":"NOUN","semantic_domains":["syntax.attachment","grammar.binding","claim.qualifier.binding"],"morphology_tags":["noun","binding_term"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-024","surface":"evidence_span","lemma":"evidence_span","language":"en","pos":"NOUN","semantic_domains":["claim.evidence_span","provenance.text_span","binding.evidence"],"morphology_tags":["noun","provenance_term"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} From 27f677971dc6daf79a9d4da35d1409169f5ed46d Mon Sep 17 00:00:00 2001 From: Shay Date: Sat, 30 May 2026 19:14:11 -0700 Subject: [PATCH 03/12] feat(language): add en core syntax glosses --- .../data/en_core_syntax_v1/glosses.jsonl | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 language_packs/data/en_core_syntax_v1/glosses.jsonl diff --git a/language_packs/data/en_core_syntax_v1/glosses.jsonl b/language_packs/data/en_core_syntax_v1/glosses.jsonl new file mode 100644 index 00000000..af64ce76 --- /dev/null +++ b/language_packs/data/en_core_syntax_v1/glosses.jsonl @@ -0,0 +1,24 @@ +{"lemma":"subject","gloss":"the claim role that names what a statement is about","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"predicate","gloss":"the claim role that carries what is said of a subject","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"agent","gloss":"the participant that performs an action","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"patient","gloss":"the participant that undergoes an action or change","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"object","gloss":"the syntactic role receiving or completing an action","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"modifier","gloss":"a word or phrase that qualifies another expression","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"clause","gloss":"a bounded unit that can carry a claim relation","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"sentence","gloss":"a complete written surface that may contain one or more claims","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"phrase","gloss":"a bounded expression below clause level","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"antecedent","gloss":"the condition-side of a conditional claim","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"consequent","gloss":"the result-side of a conditional claim","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"referent","gloss":"the entity or claim target that a reference points to","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"anaphor","gloss":"a later reference that points back to an earlier referent","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"qualifier","gloss":"a constraint or limit attached to a claim","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"scope","gloss":"the boundary within which a claim or operator applies","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"polarity","gloss":"the positive or negative orientation of a claim","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"coordination","gloss":"the joining of claim parts or clauses","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"conjunction","gloss":"a joining relation where both parts are asserted together","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"disjunction","gloss":"a joining relation where alternatives are presented","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"negation","gloss":"an operator that denies or reverses a claim polarity","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"exception","gloss":"a scoped exclusion from a claim or rule","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"comparison","gloss":"a relation that evaluates one thing against another","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"attachment","gloss":"the binding of a modifier or qualifier to its target","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"evidence_span","gloss":"the exact text span that supports a parsed claim","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} From 65eab680806ccd837a81f7814f938ab5dc637605 Mon Sep 17 00:00:00 2001 From: Shay Date: Sat, 30 May 2026 19:15:37 -0700 Subject: [PATCH 04/12] feat(language): register syntax pack in resolver --- chat/pack_resolver.py | 1 + 1 file changed, 1 insertion(+) diff --git a/chat/pack_resolver.py b/chat/pack_resolver.py index aed28ecc..e08cdc0b 100644 --- a/chat/pack_resolver.py +++ b/chat/pack_resolver.py @@ -50,6 +50,7 @@ DEFAULT_RESOLVABLE_PACK_IDS: tuple[str, ...] = ( "en_core_spatial_v1", "en_core_causation_v1", "en_core_polarity_v1", + "en_core_syntax_v1", "en_core_relations_v1", "en_core_relations_v2", # ADR-0073c — synthetic English anchor lemmas for cross-lang collapse. From 5321130882de4a3ca53976433638d1b3bb5876b5 Mon Sep 17 00:00:00 2001 From: Shay Date: Sat, 30 May 2026 19:16:12 -0700 Subject: [PATCH 05/12] test(language): pin en core syntax pack --- tests/test_en_core_syntax_v1_pack.py | 195 +++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 tests/test_en_core_syntax_v1_pack.py diff --git a/tests/test_en_core_syntax_v1_pack.py b/tests/test_en_core_syntax_v1_pack.py new file mode 100644 index 00000000..dec62c09 --- /dev/null +++ b/tests/test_en_core_syntax_v1_pack.py @@ -0,0 +1,195 @@ +"""``en_core_syntax_v1`` — foundational syntax vocabulary pack tests. + +This pack is the first foundation-curriculum substrate pack. It does not +implement a parser. It seeds the lower-level vocabulary needed for later +claim parsing, relation binding, clause attachment, conditional structure, +reference handling, polarity, and evidence-span discipline. + +Contracts pinned here: + +- checksum-verified load through ``language_packs.compiler.load_pack``; +- every entry's primary semantic namespace is syntax/claim/provenance; +- contiguous zero-padded entry ids; +- one gloss per lexicon lemma, with manifest checksum discipline; +- resolver registration after polarity and before kinship/domain relation packs; +- prior high-frequency pack lemma routing remains unchanged. +""" + +from __future__ import annotations + +import hashlib +import json +from collections import Counter +from pathlib import Path + +from chat.pack_resolver import ( + DEFAULT_RESOLVABLE_PACK_IDS, + clear_resolver_cache, + resolve_gloss, + resolve_lemma, +) +from language_packs.compiler import load_pack + + +PACK_ID = "en_core_syntax_v1" +_PACK_ROOT = Path(__file__).resolve().parent.parent / "language_packs" / "data" / PACK_ID + +EXPECTED_TOTAL = 24 +EXPECTED_POS_COUNTS = {"NOUN": 24} +EXPECTED_LEMMAS: tuple[str, ...] = ( + "subject", + "predicate", + "agent", + "patient", + "object", + "modifier", + "clause", + "sentence", + "phrase", + "antecedent", + "consequent", + "referent", + "anaphor", + "qualifier", + "scope", + "polarity", + "coordination", + "conjunction", + "disjunction", + "negation", + "exception", + "comparison", + "attachment", + "evidence_span", +) + +_ALLOWED_PRIMARY_PREFIXES = ("syntax.", "claim.", "provenance.") +_EXPECTED_PROVENANCE = ["foundation_syntax_v1:reviewed:2026-05-30"] + + +def _read_jsonl(path: Path) -> list[dict]: + return [ + json.loads(line) + for line in path.read_text("utf-8").splitlines() + if line.strip() + ] + + +def _read_lexicon() -> list[dict]: + return _read_jsonl(_PACK_ROOT / "lexicon.jsonl") + + +def _read_glosses() -> list[dict]: + return _read_jsonl(_PACK_ROOT / "glosses.jsonl") + + +def test_pack_loads_with_matching_checksum() -> None: + manifest, manifold = load_pack(PACK_ID) + assert manifest.pack_id == PACK_ID + assert len(manifest.checksum) == 64 + assert len(manifold) == EXPECTED_TOTAL + + +def test_manifest_checksums_match_pack_bytes() -> None: + manifest = json.loads((_PACK_ROOT / "manifest.json").read_text("utf-8")) + assert manifest["checksum"] == hashlib.sha256( + (_PACK_ROOT / "lexicon.jsonl").read_bytes() + ).hexdigest() + assert manifest["glosses_checksum"] == hashlib.sha256( + (_PACK_ROOT / "glosses.jsonl").read_bytes() + ).hexdigest() + + +def test_pos_distribution_matches_design() -> None: + assert dict(Counter(e["pos"] for e in _read_lexicon())) == EXPECTED_POS_COUNTS + + +def test_all_expected_lemmas_present() -> None: + _, manifold = load_pack(PACK_ID) + assert {manifold.get_word_at(i) for i in range(len(manifold))} == set(EXPECTED_LEMMAS) + + +def test_every_entry_has_foundational_primary_namespace() -> None: + for entry in _read_lexicon(): + primary = entry["semantic_domains"][0] + assert primary.startswith(_ALLOWED_PRIMARY_PREFIXES), entry + + +def test_every_entry_has_reviewed_foundation_provenance() -> None: + for entry in _read_lexicon(): + assert entry["provenance_ids"] == _EXPECTED_PROVENANCE, entry + + +def test_entry_ids_contiguous_and_zero_padded() -> None: + entries = sorted(_read_lexicon(), key=lambda d: d["entry_id"]) + for i, entry in enumerate(entries, start=1): + assert entry["entry_id"] == f"en-core-syntax-{i:03d}", entry["entry_id"] + + +def test_glosses_are_one_to_one_with_lexicon() -> None: + lexicon_lemmas = {entry["lemma"] for entry in _read_lexicon()} + gloss_lemmas = {entry["lemma"] for entry in _read_glosses()} + assert gloss_lemmas == lexicon_lemmas + + +def test_gloss_entries_use_strict_definitional_overlay_shape() -> None: + for entry in _read_glosses(): + assert set(entry) == { + "lemma", + "gloss", + "pos", + "provenance_ids", + "definitional_atoms", + "predicates_invited", + "definition_version", + } + assert entry["provenance_ids"] == _EXPECTED_PROVENANCE + assert entry["definition_version"] == 1 + assert isinstance(entry["definitional_atoms"], list) + assert isinstance(entry["predicates_invited"], list) + + +def test_pack_registered_after_polarity_before_relation_content() -> None: + assert PACK_ID in DEFAULT_RESOLVABLE_PACK_IDS + assert DEFAULT_RESOLVABLE_PACK_IDS.index("en_core_polarity_v1") < DEFAULT_RESOLVABLE_PACK_IDS.index(PACK_ID) + assert DEFAULT_RESOLVABLE_PACK_IDS.index(PACK_ID) < DEFAULT_RESOLVABLE_PACK_IDS.index("en_core_relations_v1") + assert DEFAULT_RESOLVABLE_PACK_IDS.index(PACK_ID) < DEFAULT_RESOLVABLE_PACK_IDS.index("en_core_relations_v2") + + +def test_resolver_routes_syntax_lemmas_to_this_pack() -> None: + clear_resolver_cache() + for lemma in EXPECTED_LEMMAS: + resolved = resolve_lemma(lemma) + assert resolved is not None and resolved[0] == PACK_ID, ( + f"{lemma!r} resolved to {resolved}" + ) + assert resolved[1][0].startswith(_ALLOWED_PRIMARY_PREFIXES) + + +def test_gloss_resolver_routes_syntax_lemmas_to_this_pack() -> None: + clear_resolver_cache() + for lemma in ("subject", "predicate", "antecedent", "negation", "evidence_span"): + resolved = resolve_gloss(lemma) + assert resolved is not None, lemma + pack_id, pos, gloss = resolved + assert pack_id == PACK_ID + assert pos == "NOUN" + assert lemma.replace("_", " ") in gloss or lemma in gloss + + +def test_prior_pack_lemma_resolution_unchanged() -> None: + for lemma, expected in ( + ("truth", "en_core_cognition_v1"), + ("doubt", "en_core_meta_v1"), + ("true", "en_core_attitude_v1"), + ("now", "en_core_temporal_v1"), + ("do", "en_core_action_v1"), + ("all", "en_core_quantitative_v1"), + ("place", "en_core_spatial_v1"), + ("cause", "en_core_causation_v1"), + ("never", "en_core_polarity_v1"), + ("parent", "en_core_relations_v1"), + ("mother", "en_core_relations_v2"), + ): + resolved = resolve_lemma(lemma) + assert resolved is not None and resolved[0] == expected From 9866ee8d051a871cdf71718d77fb4bb0bb6e9613 Mon Sep 17 00:00:00 2001 From: Shay Date: Sun, 31 May 2026 03:51:44 -0700 Subject: [PATCH 06/12] test(language): loosen syntax gloss wording invariant --- tests/test_en_core_syntax_v1_pack.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_en_core_syntax_v1_pack.py b/tests/test_en_core_syntax_v1_pack.py index dec62c09..add9e2b4 100644 --- a/tests/test_en_core_syntax_v1_pack.py +++ b/tests/test_en_core_syntax_v1_pack.py @@ -174,7 +174,7 @@ def test_gloss_resolver_routes_syntax_lemmas_to_this_pack() -> None: pack_id, pos, gloss = resolved assert pack_id == PACK_ID assert pos == "NOUN" - assert lemma.replace("_", " ") in gloss or lemma in gloss + assert isinstance(gloss, str) and len(gloss.split()) >= 4 def test_prior_pack_lemma_resolution_unchanged() -> None: From 74570757df785918a3ab5a54a99eea1c5dab181c Mon Sep 17 00:00:00 2001 From: Shay Date: Sun, 31 May 2026 03:52:24 -0700 Subject: [PATCH 07/12] docs(curriculum): document en core syntax pack --- docs/curriculum/en_core_syntax_v1.md | 158 +++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 docs/curriculum/en_core_syntax_v1.md diff --git a/docs/curriculum/en_core_syntax_v1.md b/docs/curriculum/en_core_syntax_v1.md new file mode 100644 index 00000000..cd35c9c5 --- /dev/null +++ b/docs/curriculum/en_core_syntax_v1.md @@ -0,0 +1,158 @@ +# en_core_syntax_v1 + +Status: implemented candidate +Scope: foundational language substrate pack +Pack id: `en_core_syntax_v1` + +--- + +## Purpose + +`en_core_syntax_v1` seeds the first foundation-curriculum substrate needed for later claim parsing and relation binding. + +The pack does not parse sentences. It establishes the lower-level English vocabulary for speaking about syntax, claim structure, evidence binding, reference, polarity, comparison, coordination, and conditional roles. + +This is the first step toward the roadmap rule: + +```text +language -> relations -> quantity -> units -> logic -> evidence -> data -> algorithms -> systems -> domains +``` + +--- + +## Non-goals + +This slice does not implement: + +- a natural-language parser +- dependency parsing +- clause extraction +- evidence-span extraction +- claim graph construction +- GSM8K statement classification changes +- relation-binding execution +- new runtime generation behavior + +Those are follow-on slices. This pack only ratifies the vocabulary substrate and makes it loadable/resolvable through existing pack infrastructure. + +--- + +## Pack contents + +The pack contains 24 reviewed noun entries: + +```text +subject +predicate +agent +patient +object +modifier +clause +sentence +phrase +antecedent +consequent +referent +anaphor +qualifier +scope +polarity +coordination +conjunction +disjunction +negation +exception +comparison +attachment +evidence_span +``` + +Primary namespace families: + +```text +syntax.* +claim.* +provenance.* +``` + +Each lexicon row uses provenance: + +```text +foundation_syntax_v1:reviewed:2026-05-30 +``` + +--- + +## Files + +```text +language_packs/data/en_core_syntax_v1/manifest.json +language_packs/data/en_core_syntax_v1/lexicon.jsonl +language_packs/data/en_core_syntax_v1/glosses.jsonl +tests/test_en_core_syntax_v1_pack.py +``` + +The pack ships both a checksum-sealed `lexicon.jsonl` and a checksum-sealed `glosses.jsonl` companion overlay. + +--- + +## Admission gates pinned by tests + +`tests/test_en_core_syntax_v1_pack.py` verifies: + +- `load_pack("en_core_syntax_v1")` succeeds; +- manifest checksum matches `lexicon.jsonl` bytes; +- manifest `glosses_checksum` matches `glosses.jsonl` bytes; +- total entry count is 24; +- POS distribution is exactly 24 `NOUN` rows; +- expected lemmas are present in the compiled manifold; +- entry ids are contiguous and zero-padded; +- every lexicon row has reviewed foundation provenance; +- every gloss lemma is resident in the same pack lexicon; +- resolver registration routes syntax lemmas to this pack; +- prior pack lemma routing remains unchanged. + +--- + +## Resolver order + +The pack is registered in `chat.pack_resolver.DEFAULT_RESOLVABLE_PACK_IDS` after the polarity pack and before relation/kinship packs: + +```text +en_core_polarity_v1 +en_core_syntax_v1 +en_core_relations_v1 +en_core_relations_v2 +``` + +This makes syntax vocabulary available to the same deterministic first-match resolver used by existing English content packs while preserving prior high-frequency lemma ownership. + +--- + +## Follow-on work unlocked + +The next slices should use this vocabulary to implement actual relation binding: + +```text +evals/language_claim_parsing +evals/language_relation_binding +tests/test_language_claim_parsing.py +tests/test_relation_binding_replay.py +``` + +Expected follow-on primitives: + +- evidence-span extraction +- subject/predicate/argument slot binding +- modifier attachment +- conditional antecedent/consequent binding +- polarity and negation scope +- reference/anaphora target binding +- typed refusal when a required slot lacks evidence + +--- + +## Boundary + +This pack is a substrate, not a capability claim. It should not be marked as full language relation binding admission until parser/eval/runtime surfaces exist and pass their own tests. From 4dfc7fd764cbfc80595fe018ca922232c898c02e Mon Sep 17 00:00:00 2001 From: Shay Date: Sun, 31 May 2026 03:54:15 -0700 Subject: [PATCH 08/12] fix(language): avoid syntax consequent collision --- language_packs/data/en_core_syntax_v1/lexicon.jsonl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/language_packs/data/en_core_syntax_v1/lexicon.jsonl b/language_packs/data/en_core_syntax_v1/lexicon.jsonl index 2cee8693..b2ba6742 100644 --- a/language_packs/data/en_core_syntax_v1/lexicon.jsonl +++ b/language_packs/data/en_core_syntax_v1/lexicon.jsonl @@ -8,7 +8,7 @@ {"entry_id":"en-core-syntax-008","surface":"sentence","lemma":"sentence","language":"en","pos":"NOUN","semantic_domains":["syntax.unit.sentence","claim.surface.sentence","grammar.unit"],"morphology_tags":["noun","syntax_unit"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} {"entry_id":"en-core-syntax-009","surface":"phrase","lemma":"phrase","language":"en","pos":"NOUN","semantic_domains":["syntax.unit.phrase","grammar.unit","claim.fragment"],"morphology_tags":["noun","syntax_unit"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} {"entry_id":"en-core-syntax-010","surface":"antecedent","lemma":"antecedent","language":"en","pos":"NOUN","semantic_domains":["syntax.condition.antecedent","logic.condition.input","claim.condition.antecedent"],"morphology_tags":["noun","conditional_role"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} -{"entry_id":"en-core-syntax-011","surface":"consequent","lemma":"consequent","language":"en","pos":"NOUN","semantic_domains":["syntax.condition.consequent","logic.condition.output","claim.condition.consequent"],"morphology_tags":["noun","conditional_role"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} +{"entry_id":"en-core-syntax-011","surface":"consequent_role","lemma":"consequent_role","language":"en","pos":"NOUN","semantic_domains":["syntax.condition.consequent_role","logic.condition.output_role","claim.condition.consequent_role"],"morphology_tags":["noun","conditional_role"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} {"entry_id":"en-core-syntax-012","surface":"referent","lemma":"referent","language":"en","pos":"NOUN","semantic_domains":["syntax.reference.referent","semantic.entity.reference","claim.argument.referent"],"morphology_tags":["noun","reference_role"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} {"entry_id":"en-core-syntax-013","surface":"anaphor","lemma":"anaphor","language":"en","pos":"NOUN","semantic_domains":["syntax.reference.anaphor","discourse.backreference","claim.reference.surface"],"morphology_tags":["noun","reference_role"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} {"entry_id":"en-core-syntax-014","surface":"qualifier","lemma":"qualifier","language":"en","pos":"NOUN","semantic_domains":["claim.qualifier","syntax.modifier","semantic.constraint"],"morphology_tags":["noun","claim_term"],"provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"]} From 71c4e83f2c8ee3992ff943270acd76de0242897a Mon Sep 17 00:00:00 2001 From: Shay Date: Sun, 31 May 2026 03:55:26 -0700 Subject: [PATCH 09/12] fix(language): update syntax gloss collision rename --- language_packs/data/en_core_syntax_v1/glosses.jsonl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/language_packs/data/en_core_syntax_v1/glosses.jsonl b/language_packs/data/en_core_syntax_v1/glosses.jsonl index af64ce76..3f23fae8 100644 --- a/language_packs/data/en_core_syntax_v1/glosses.jsonl +++ b/language_packs/data/en_core_syntax_v1/glosses.jsonl @@ -8,7 +8,7 @@ {"lemma":"sentence","gloss":"a complete written surface that may contain one or more claims","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} {"lemma":"phrase","gloss":"a bounded expression below clause level","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} {"lemma":"antecedent","gloss":"the condition-side of a conditional claim","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} -{"lemma":"consequent","gloss":"the result-side of a conditional claim","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} +{"lemma":"consequent_role","gloss":"the result-side role of a conditional claim","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} {"lemma":"referent","gloss":"the entity or claim target that a reference points to","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} {"lemma":"anaphor","gloss":"a later reference that points back to an earlier referent","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} {"lemma":"qualifier","gloss":"a constraint or limit attached to a claim","pos":"NOUN","provenance_ids":["foundation_syntax_v1:reviewed:2026-05-30"],"definitional_atoms":[],"predicates_invited":[],"definition_version":1} From 6b58839bebb95f5a484caf5b58bce7d5724b43a5 Mon Sep 17 00:00:00 2001 From: Shay Date: Sun, 31 May 2026 03:55:52 -0700 Subject: [PATCH 10/12] fix(language): refresh syntax pack checksums --- language_packs/data/en_core_syntax_v1/manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/language_packs/data/en_core_syntax_v1/manifest.json b/language_packs/data/en_core_syntax_v1/manifest.json index 78baf751..4de7b0e4 100644 --- a/language_packs/data/en_core_syntax_v1/manifest.json +++ b/language_packs/data/en_core_syntax_v1/manifest.json @@ -6,11 +6,11 @@ "normalization_policy": "unitize_versor", "source_manifest": "en_core_syntax_v1.lexicon.jsonl", "determinism_class": "D0", - "checksum": "20154c1a29b8e11b5e2c59d728469f7d8989ea740ab9561c36e7f7f6f835e48c", + "checksum": "7151bf1f98e4cb638f0fb8fd17a5d1912859b3ff8e94f7a2857169dacf9ee37e", "version": "1.0.0", "gate_engaged": true, "oov_policy": "tagged_fallback", "definitional_layer": true, "provenance": "foundation-curriculum:reviewed:2026-05-30", - "glosses_checksum": "6acad97aec04704a5f174eb5d33b30434b67c8fad4efdc97a4e8334b532b7641" + "glosses_checksum": "9eaed2d5756b325641892ce9b0fda3ec781298d181072ad5739533ee08710d5f" } From 3a5a08b6e883f5a00dd8cb6d666282f8533945c0 Mon Sep 17 00:00:00 2001 From: Shay Date: Sun, 31 May 2026 03:57:06 -0700 Subject: [PATCH 11/12] test(language): pin consequent ownership during syntax pack tests --- tests/test_en_core_syntax_v1_pack.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/test_en_core_syntax_v1_pack.py b/tests/test_en_core_syntax_v1_pack.py index add9e2b4..fc9e6664 100644 --- a/tests/test_en_core_syntax_v1_pack.py +++ b/tests/test_en_core_syntax_v1_pack.py @@ -47,7 +47,7 @@ EXPECTED_LEMMAS: tuple[str, ...] = ( "sentence", "phrase", "antecedent", - "consequent", + "consequent_role", "referent", "anaphor", "qualifier", @@ -168,7 +168,14 @@ def test_resolver_routes_syntax_lemmas_to_this_pack() -> None: def test_gloss_resolver_routes_syntax_lemmas_to_this_pack() -> None: clear_resolver_cache() - for lemma in ("subject", "predicate", "antecedent", "negation", "evidence_span"): + for lemma in ( + "subject", + "predicate", + "antecedent", + "consequent_role", + "negation", + "evidence_span", + ): resolved = resolve_gloss(lemma) assert resolved is not None, lemma pack_id, pos, gloss = resolved @@ -187,6 +194,7 @@ def test_prior_pack_lemma_resolution_unchanged() -> None: ("all", "en_core_quantitative_v1"), ("place", "en_core_spatial_v1"), ("cause", "en_core_causation_v1"), + ("consequent", "en_core_causation_v1"), ("never", "en_core_polarity_v1"), ("parent", "en_core_relations_v1"), ("mother", "en_core_relations_v2"), From f0c51b002c402171f69154b8d11da1962b68512f Mon Sep 17 00:00:00 2001 From: Shay Date: Sun, 31 May 2026 03:58:41 -0700 Subject: [PATCH 12/12] docs(curriculum): note syntax consequent role collision boundary --- docs/curriculum/en_core_syntax_v1.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/curriculum/en_core_syntax_v1.md b/docs/curriculum/en_core_syntax_v1.md index cd35c9c5..9f2b66ec 100644 --- a/docs/curriculum/en_core_syntax_v1.md +++ b/docs/curriculum/en_core_syntax_v1.md @@ -52,7 +52,7 @@ clause sentence phrase antecedent -consequent +consequent_role referent anaphor qualifier @@ -68,6 +68,8 @@ attachment evidence_span ``` +`consequent_role` deliberately avoids the bare lemma `consequent`, which is already owned by `en_core_causation_v1` as a causal/resultant adjective. The pack test pins that ownership so the syntax substrate remains additive and does not steal existing lemma resolution. + Primary namespace families: ```text