core/docs/handoff/CLEANUP-C4-compositions-compile.md
Shay 89defef30b chore(audit): substrate cleanup — dead spike, gitignore, deprecation, reader diagnosis
C1: delete generate/math_versor_arithmetic.py and its 3 tests (ADR-0139
add-only arithmetic spike; no runtime consumers, no pipeline wiring,
follow-on lift paused per module docstring).

C3: gitignore engine_state runtime artifacts (manifest.json,
recognizers.jsonl, discovery_candidates.jsonl). Module code
(engine_state/__init__.py) remains tracked; generated checkpoint
files should not be.

C5: document reader zero-delta root cause in train_sample/v1/README.md.
Both Phase 2 (whole-problem) and Phase 1 (question-only) reader paths are
called but inert because all 47 refusals are statement-level NO_INJECTOR
gaps, not question-sentence gaps. Reader unblocks when injector coverage
expands (C2 work). report.json use_reader flag corrected to reflect last run.

C6: add deprecation header to generate/math_parser.py pointing at
generate.math_candidate_graph.parse_and_solve as the live path.

C2/C4 briefs: docs/handoff/CLEANUP-C2-run-lane-migration.md and
docs/handoff/CLEANUP-C4-compositions-compile.md added as operator
dispatch docs for the medium-scope wiring tasks.
2026-05-28 07:00:33 -07:00

4.2 KiB
Raw Blame History

C4 — Compile and commit compositions.jsonl for the math pack

Classification: Half-built producer/consumer loop (audit finding C4)
Risk: Low — purely additive, wrong == 0 guaranteed by registry design
Scope: language_packs/data/en_core_math_v1/, language_packs/compile_compositions.py


Problem

language_packs/data/en_core_math_v1/compositions/multiplicative_composition.jsonl was ratified via ADR-0169 and is present on disk. But language_packs/data/en_core_math_v1/compositions.jsonl (the compiled artifact that the runtime reads) does not exist.

The consumer chain is:

compositions/multiplicative_composition.jsonl   ← ratified source (EXISTS)
    ↓  compile_compositions.py
compositions.jsonl                              ← compiled registry (MISSING)
    ↓  comprehension/composition_registry.py::load_composition_registry()
    ↓  recognizer_anchor_inject.py (line 157159)
InjectorEmission[]                              ← runtime output (always empty)

load_composition_registry() handles the missing file gracefully — it returns an empty registry when compositions.jsonl is absent and manifest.json does not declare composition_checksum. So the system is stable; the ratified claims simply have no effect on runtime decisions.


What to do

Step 1 — Run the compile step

uv run python -c "
from pathlib import Path
from language_packs.compile_compositions import compile_pack_compositions

pack = Path('language_packs/data/en_core_math_v1')
result = compile_pack_compositions(pack)
print('written to:', result.output_path)
print('sha256:', result.sha256)
print('entries:', result.entry_count)
"

Verify entry_count > 0 (at least the multiplicative_composition entries).

Step 2 — Update manifest.json with composition_checksum

The manifest checksum enforces that the committed compiled artifact matches what compile_compositions.py would produce from the source files. Once the compiled artifact is committed, manifest.json should be updated to declare composition_checksum so any future drift raises CompositionRegistryLoadError at load time (defense in depth).

sha=$(sha256sum language_packs/data/en_core_math_v1/compositions.jsonl | cut -d' ' -f1)
# or on macOS:
sha=$(shasum -a 256 language_packs/data/en_core_math_v1/compositions.jsonl | cut -d' ' -f1)

Then add "composition_checksum": "<sha>" to manifest.json.

Step 3 — Verify the registry is non-empty at runtime

uv run python -c "
from generate.comprehension.composition_registry import load_composition_registry
r = load_composition_registry()
print('empty:', r.is_empty())
print('categories:', list(r.by_category.keys()))
"

Expected: empty: False, at least multiplicative_composition in categories.

Step 4 — Run packs + smoke suites

uv run core test --suite packs -q
uv run core test --suite smoke -q

Step 5 — Commit

language_packs/data/en_core_math_v1/compositions.jsonl   (new)
language_packs/data/en_core_math_v1/manifest.json        (updated: composition_checksum)

Commit message:

feat(packs): compile multiplicative_composition registry for math pack

Runs compile_compositions.py to produce compositions.jsonl from the
ratified multiplicative_composition.jsonl source. Updates manifest.json
with composition_checksum. load_composition_registry() now returns a
non-empty registry; recognizer_anchor_inject.py can emit InjectorEmission
for composition-shape matches. Closes the producer/consumer gap from
ADR-0169.

Invariant gates

  • wrong == 0 is preserved by the registry's refusal-preferring discipline: is_falsified returns () immediately; is_affirmed gates every emission.
  • The WrongCompositionCategory check at load time prevents any unsafe category from being accepted even if the source file is mutated.
  • The manifest checksum (after Step 2) provides ongoing compile-drift detection.

Relation to other findings

  • C2 (run_lane migration): C4 should land at the same time or before C2 so the candidate-graph path immediately sees a non-empty composition registry.
  • C5 (reader zero-delta): the reader's zero-delta is unrelated to compositions — it is a statement-level injector gap. C4 does not fix C5.