Collapses the duplicated closed English tables into generate/lexicon.py.
Measured on main @ 0948f7cd: the same facts were encoded up to five times
across the reading and writing paths, each copy written independently as a
successive deduction band landed.
The 2A/2B split is decided empirically per #129 — make the change, run the
11 pinned lanes, let byte-identity rule. Result: 11/11 byte-identical, so
this entire unit is 2A and nothing spilled into the authorization-gated 2B.
Collapsed to one object:
- connectives 3 identical copies (member, verb, cond_member)
- predicate display 2 identical 26-entry copies (semantic_templates,
templates)
- be-form inventory 5 copies, not the 2 §1.3 counted. The structural
test found realizer_guard._BE_AUX and
chat/runtime._BE_FORMS, which a COPULA-shaped grep
could never see.
Derived rather than duplicated, so they can no longer drift:
- STRUCTURAL = CONNECTIVES | {therefore}
- QUANTIFIER_TOKENS = QUANTIFIER_LEAD | QUANTIFIER_NON_LEAD
- NEGATION_BEARING_WITH_NOT = NEGATION_BEARING | {not}
- READER_IRREGULAR_SINGULARS = IRREGULAR_SINGULARS restricted to 8 keys
§1.3 re-measured while doing this, and it overstated the disease (plan
§1.9). Almost nothing contradicts:
- the "3 divergent plural tables" are 1 pluralizer + 2 singularizers,
i.e. inverse directions; comparing them as copies is a category error
- reader's 8 singulars are a STRICT SUBSET of member's 29 with the
difference in reader's favour empty, so its values are all correct and
only its coverage is short
- the "3 divergent quantifier sets" are 3 distinct facts; every/each lead
a clause but take singular nouns, so their absence from
PLURAL_QUANTIFIERS is correct
- english's negation set is a subset of member's, and the difference is
principled: v2-EN normalizes "<copula> not", v3-MEM refuses it
Exactly one genuine contradiction exists in the whole inventory:
discourse_planner maps is_defined_as -> "is" where the others map it to
"is defined as". Preserved as a register choice, pinned by test.
Found while reading, pinned as current behaviour for 2B to flip:
reader._singularize does NOT refuse uncovered plurals despite a comment
claiming it does — it falls through to a bare -s strip, so news -> new and
species -> specy, exactly the corruptions member.py's table comment says
its table exists to prevent.
Two 2A exit criteria were unmeasurable as written and are replaced:
- "Jaccard -> 1.00" cannot work. measure_grammar_seam.py scans source
literals, so unifying a fact removes it from those files and Jaccard
FELL, 0.083 -> 0.023 — the success direction reported by a metric
shaped to read like failure. Replaced with an object-identity count:
3 distinct objects behind 8 names, from 8-behind-8. Value comparison
cannot tell a shared object from two equal copies.
- "one table per fact" presumed §1.3's inventory was right. The report now
separates must-be-one-object (all UNIFIED) from related-but-distinct
(6 relations, all HOLD).
ADR-0258 §5 already decided morphology's destination is a ratified pack,
triggered by a grc/he member band. No such band exists, so the promotion is
correctly deferred and lexicon.py is a staging area, not a rival home — no
new ADR. Destination measured for whoever picks it up: packs/en/morphology
.jsonl has 9 records and zero irregular plurals, features.number has no
consumer, and _pack_morph_roots_for reads a top-level "root" key that 0 of
31 records across all four packs define, so it returns {} every call.
[Verification]: in-worktree on CPython 3.12.13, uv sync --locked —
smoke 621 unchanged; deductive 383 (364 + 19 new);
scripts/verify_lane_shas.py 11/11 byte-identical.
80 lines
2.9 KiB
Python
80 lines
2.9 KiB
Python
"""Intent-aware semantic templates for the realizer.
|
|
|
|
Maps (IntentTag, relation_predicate) pairs to deterministic surface
|
|
templates that use the seed pack's relation predicates (defines, means,
|
|
grounds, supports, contrasts_with, corrects).
|
|
|
|
Design constraints:
|
|
- No LLM fallback
|
|
- No random template selection
|
|
- Deterministic: same (intent, predicate, subject, object) -> same surface
|
|
- Uses seed pack vocabulary directly
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from generate.lexicon import PREDICATE_DISPLAY
|
|
from generate.intent import IntentTag
|
|
|
|
|
|
_INTENT_TEMPLATES: dict[IntentTag, str] = {
|
|
IntentTag.DEFINITION: "{subject} is defined as {obj}",
|
|
IntentTag.CAUSE: "{subject} is grounded in {obj}",
|
|
IntentTag.PROCEDURE: "first, {obj}; then, {subject} follows",
|
|
IntentTag.COMPARISON: "{subject} and {secondary} are distinguished: {subject} {predicate_h} {secondary}",
|
|
IntentTag.CORRECTION: "correction: {subject} {predicate_h} {obj}",
|
|
IntentTag.RECALL: "recalling {subject}: {obj}",
|
|
IntentTag.VERIFICATION: "{subject} is verified: {obj}",
|
|
IntentTag.UNKNOWN: "{subject} {predicate_h} {obj}",
|
|
}
|
|
|
|
_PREDICATE_HUMANIZE: dict[str, str] = PREDICATE_DISPLAY
|
|
|
|
|
|
def humanize_predicate(predicate: str) -> str:
|
|
return _PREDICATE_HUMANIZE.get(predicate, predicate.replace("_", " "))
|
|
|
|
|
|
def render_semantic(
|
|
intent: IntentTag,
|
|
subject: str,
|
|
predicate: str,
|
|
obj: str,
|
|
secondary: str | None = None,
|
|
language: str | None = None,
|
|
root: str | None = None,
|
|
) -> str:
|
|
"""Render a semantic surface from intent, subject, predicate, and object.
|
|
|
|
When language + root are supplied (from enriched PropositionGraph nodes
|
|
carrying 3-core-language depth), the surface incorporates etymological
|
|
precision for Hebrew (root density) and Koine Greek (Logos precision).
|
|
English base remains unchanged.
|
|
"""
|
|
template = _INTENT_TEMPLATES.get(intent, _INTENT_TEMPLATES[IntentTag.UNKNOWN])
|
|
predicate_h = humanize_predicate(predicate)
|
|
obj_display = obj if obj not in ("<pending>", "<prior>") else "..."
|
|
|
|
# Masterful 3-language depth framing on the articulation side.
|
|
# Depth travels with the shared GraphNode from resolve_entry grounding.
|
|
if language and root and language != "en":
|
|
if language == "he":
|
|
depth_note = f" (Hebrew root: {root})"
|
|
elif language in ("grc", "el"):
|
|
depth_note = f" (Koine Greek: {root})"
|
|
else:
|
|
depth_note = f" ({language} root: {root})"
|
|
|
|
# For definition-style intents, highlight the term itself.
|
|
# For others, qualify the object referent.
|
|
if intent in (IntentTag.DEFINITION, IntentTag.RECALL, IntentTag.VERIFICATION):
|
|
subject = f"{subject}{depth_note}"
|
|
else:
|
|
obj_display = f"{obj_display}{depth_note}"
|
|
|
|
return template.format(
|
|
subject=subject,
|
|
predicate_h=predicate_h,
|
|
obj=obj_display,
|
|
secondary=secondary or obj_display,
|
|
)
|