Completes the Phase 5 curriculum-era lane checklist alongside 5.1.
English-substrate domain lanes (5.4–5.7) — extend the proven
english_fluency_ood pattern with new vocabulary domains. Same
13-construction realizer, same grammatical_coverage rubric, new
triples. All four lanes land at 100% on both splits:
5.4 elementary_mathematics_ood 117/117 public + 39/39 holdouts
domains: arithmetic, set, geometry | holdout: probability
5.5 foundational_physics_ood 117/117 + 39/39
domains: mechanics, electricity, thermodynamics | holdout: optics
5.6 foundational_biology_ood 117/117 + 39/39
domains: cell, organism, ecosystem | holdout: genetics
5.7 classical_literature_ood 117/117 + 39/39
domains: epic, tragedy, lyric | holdout: comedy
New-language lanes (5.2 Hebrew, 5.3 Koine Greek) — scoped honestly to
v1 = C01 only, script + length rubric. The realizer's
tense/aspect/quantifier/negation logic in generate/templates.py is
English-only; C02-C13 in HE/GRC requires Hebrew/Greek morphology +
rhetorical templates, named explicitly in each lane's gaps.md as the
v2 unblock path. v1 measures what infrastructure exists:
5.2 hebrew_fluency 3/3 (predicate-subject-object assembly,
Hebrew script gate)
5.3 koine_greek_fluency 3/3 (subject-object-predicate assembly,
Greek script gate)
Lane scaffolds follow the established pattern: contract.md, runner.py,
__init__.py, gaps.md, public/v1/cases.jsonl, dev/cases.jsonl,
holdouts/v1/cases.jsonl (5.4–5.7 only; HE/GRC holdouts deferred to v2
when vocabulary expands).
Generators + scorers:
scripts/generate_phase5_domain_lanes.py — 5.4–5.7 case emit
scripts/scaffold_phase5_domain_lanes.py — 5.4–5.7 contracts/runners
scripts/generate_phase5_language_lanes.py — 5.2/5.3 case emit
scripts/score_phase5_holdouts.py — parallel holdouts scoring
via multiprocessing.Pool
(mirrors the parallel-eval
pattern from evals/parallel.py)
Lanes are wired into core eval --list automatically through the
framework's lane discovery; parallel sweeps via bash background jobs
(one process per lane).
Regression clean: smoke 54, runtime 19, teaching 17, packs 6,
cognition 57, algebra 132. Cognition eval 100% across all metrics.
168 lines
5.9 KiB
Python
168 lines
5.9 KiB
Python
"""Write contract.md, runner.py, __init__.py, and gaps.md for each
|
||
Phase 5.4–5.7 domain lane.
|
||
|
||
The lane scaffolds delegate scoring to the grammatical_coverage runner
|
||
(same pattern as english_fluency_ood) so the rubric stays consistent
|
||
across lanes. Vocabulary is the only thing that changes.
|
||
|
||
Run after `generate_phase5_domain_lanes.py`.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from pathlib import Path
|
||
|
||
LANES: dict[str, dict[str, str]] = {
|
||
"elementary_mathematics_ood": {
|
||
"phase": "5.4",
|
||
"title": "Elementary mathematics fluency OOD",
|
||
"public_domains": "arithmetic, set, geometry",
|
||
"holdout_domain": "probability",
|
||
"claim": "the deterministic realizer produces grammatical English surfaces over elementary-mathematics vocabulary the seed pack does not contain",
|
||
},
|
||
"foundational_physics_ood": {
|
||
"phase": "5.5",
|
||
"title": "Foundational physics fluency OOD",
|
||
"public_domains": "mechanics, electricity, thermodynamics",
|
||
"holdout_domain": "optics",
|
||
"claim": "the deterministic realizer produces grammatical English surfaces over foundational-physics vocabulary the seed pack does not contain",
|
||
},
|
||
"foundational_biology_ood": {
|
||
"phase": "5.6",
|
||
"title": "Foundational biology fluency OOD",
|
||
"public_domains": "cell, organism, ecosystem",
|
||
"holdout_domain": "genetics",
|
||
"claim": "the deterministic realizer produces grammatical English surfaces over foundational-biology vocabulary the seed pack does not contain",
|
||
},
|
||
"classical_literature_ood": {
|
||
"phase": "5.7",
|
||
"title": "Classical literature fluency OOD",
|
||
"public_domains": "epic, tragedy, lyric",
|
||
"holdout_domain": "comedy",
|
||
"claim": "the deterministic realizer produces grammatical English surfaces over classical-literature vocabulary the seed pack does not contain",
|
||
},
|
||
}
|
||
|
||
|
||
def _contract(lane: str, spec: dict[str, str]) -> str:
|
||
return f"""# {spec['title']} eval lane (Phase {spec['phase']})
|
||
|
||
## What it measures
|
||
|
||
Whether {spec['claim']}.
|
||
|
||
The structural claim under test: fluency is mechanistic in the
|
||
realizer (templates over typed graph nodes), not lexical
|
||
(pack-bound). If the claim holds, this OOD vocabulary passes the
|
||
same syntactic gates the seed vocabulary did at v1/v2 of
|
||
`grammatical_coverage` — and the same 13 constructions covered by
|
||
the Phase 5.1 `english_fluency_ood` lane.
|
||
|
||
## Inputs
|
||
|
||
`public/v1/cases.jsonl`
|
||
: 117 cases — 13 constructions × 3 public domains ({spec['public_domains']})
|
||
× 3 lexical items per domain.
|
||
|
||
`holdouts/v1/cases.jsonl`
|
||
: 39 cases — 13 constructions × 1 held-out domain
|
||
({spec['holdout_domain']}) × 3 items.
|
||
|
||
`dev/cases.jsonl`
|
||
: 13 cases — one of each construction from the first public domain.
|
||
|
||
Each case is one PropositionGraph JSON with realised constraints,
|
||
generated by `scripts/generate_phase5_domain_lanes.py`.
|
||
|
||
## Scoring rubric
|
||
|
||
Delegated to `evals/grammatical_coverage/runner.py` so the rubric
|
||
stays consistent across all fluency-OOD lanes:
|
||
|
||
- surface satisfies `accept_surfaces` or `constraints` (must_contain,
|
||
word_order, max_words)
|
||
- surface is not in `reject_surfaces`
|
||
|
||
## Target
|
||
|
||
100% on public + holdouts. Any miss indicates a real realizer or
|
||
inflection gap and is filed in `gaps.md`.
|
||
|
||
## Provenance
|
||
|
||
Same harness as `evals/english_fluency_ood/` (Phase 5.1).
|
||
Vocabulary is the only material change between lanes.
|
||
"""
|
||
|
||
|
||
_RUNNER = '''"""Phase {phase} domain fluency OOD eval lane runner.
|
||
|
||
Verifies the deterministic realizer produces grammatical English
|
||
surfaces across the 13 grammatical-coverage constructions when the
|
||
(subject, predicate, object) vocabulary is **out of the
|
||
en_core_cognition_v1 distribution** — drawn from the {public_domains}
|
||
public domains and the held-out {holdout_domain} domain.
|
||
|
||
Scoring is delegated to the grammatical_coverage runner so the
|
||
rubric stays consistent across all fluency-OOD lanes.
|
||
|
||
Conforms to the framework interface: run_lane(cases, config=None) -> report.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from typing import Any
|
||
|
||
from evals.grammatical_coverage.runner import LaneReport, run_lane as _run
|
||
|
||
|
||
def run_lane(cases: list[dict[str, Any]], *, config: Any = None) -> LaneReport:
|
||
return _run(cases, config=config)
|
||
'''
|
||
|
||
|
||
def _gaps(lane: str, spec: dict[str, str]) -> str:
|
||
return f"""# {spec['title']} — gaps
|
||
|
||
## v1 (current)
|
||
|
||
- Constructions covered: all 13 (C01–C13) via grammatical_coverage rubric.
|
||
- Domains covered: public — {spec['public_domains']}; holdout —
|
||
{spec['holdout_domain']}.
|
||
- Predicates default to regular verbs to keep morphology gaps from
|
||
confounding the structural fluency claim.
|
||
|
||
## Known gaps for v2
|
||
|
||
The Phase 5.1 English fluency OOD lane already names three realizer
|
||
gaps that apply equally here:
|
||
|
||
G1. Irregular past tense — past_tense() handles regular -ed but not
|
||
irregular forms (e.g. "ran", "stood").
|
||
G2. Plural agreement — the realizer does not pluralise nouns or
|
||
conjugate to plural subjects.
|
||
G3. Punctuation strictness — the rubric pins comma-bounded relative
|
||
clauses exactly; small punctuation differences still fail.
|
||
|
||
These are not lane-specific. When 5.1 closes them, every domain lane
|
||
gains the same coverage for free.
|
||
|
||
## Out of scope for this lane
|
||
|
||
- Domain-specific semantic correctness (whether "ribosome assembles
|
||
protein" is *true* biology). This lane measures fluency, not
|
||
factual correctness. Truth checks live in the
|
||
`epistemic_status` surface (ADR-0021) and future curriculum
|
||
lanes.
|
||
"""
|
||
|
||
|
||
if __name__ == "__main__":
|
||
root = Path(__file__).resolve().parent.parent
|
||
for lane, spec in LANES.items():
|
||
lane_dir = root / "evals" / lane
|
||
(lane_dir / "__init__.py").write_text("")
|
||
(lane_dir / "contract.md").write_text(_contract(lane, spec))
|
||
(lane_dir / "runner.py").write_text(_RUNNER.format(**spec))
|
||
(lane_dir / "gaps.md").write_text(_gaps(lane, spec))
|
||
print(f"scaffolded: evals/{lane}/")
|