core/docs/handoff/POST-RAT1-PARALLEL-BRIEFS.md
Shay 85b8f0cd11 docs(post-rat1): four parallel dispatch briefs (B/C/D/E)
After RAT-1's architecture audit exposed five systematically
underbuilt components, A (the 4 missing injectors) is being taken by
this agent. The other four are parallel-safe and each gets its own
dispatch brief:

  B (Opus)   — contemplation produces ratifiable claims (medium)
  C (Sonnet) — comprehension reader audit + decision (small→medium)
  D (Sonnet) — core teaching coverage CLI (small)
  E (Codex)  — lexical ratification auto-compile (tiny)

Each brief carries: operator profile, branch name, base, dispatch
line, reads required FIRST, outcome inventory, hard requirements,
tests, truth test. Anti-regression invariants enumerated. All
parallel-safe — no shared file conflicts.

The dispatch DAG names ALL FIVE pieces with A in-flight as a peer.
2026-05-27 20:24:39 -07:00

304 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Post-RAT-1 Parallel Briefs (B, C, D, E)
**Date:** 2026-05-27
**Author:** Shay
**Context:** Following the architecture audit (RAT-1 / PR #406), five components are structurally underbuilt. **A (the 4 missing injectors) is in flight as its own PR by Opus**. The remaining four are parallel-safe and each can be dispatched to its own operator.
Each brief below is self-contained, copy-paste-runnable.
---
## Brief B — Make math contemplation produce **ratifiable** claims
**Operator profile:** Opus (load-bearing — the claim shape is what an operator ratifies; getting it wrong is operator-burden risk)
**Branch:** `feat/contemplation-ratifiable-claims`
**Base:** `origin/main`
**Estimated effort:** medium
### Why
Currently `core eval math-contemplation` produces proposals whose `proposed_change_payload` is:
```json
{"evidence_count": 8, "group_key": {...}, "modal_sub_type": "composition"}
```
This is evidence aggregation, not a ratifiable claim. The operator has to **design the claim from scratch** (pick a `surface_pattern`, pick a `composition_category`, pick a `polarity`) before calling `apply_composition_claim()`. The "operator just reviews" framing is misleading.
### Outcome
Make `teaching/math_contemplation.py::decompose_audit` (and the dispatcher in `teaching/math_contemplation_proposal.py`) emit proposals where `proposed_change_payload` carries:
```json
{
"surface_pattern": "bound(count) × bound(unit_cost)",
"composition_category": "multiplicative_composition",
"polarity": "affirms",
"evidence_count": 8,
"group_key": {...},
"modal_sub_type": "composition"
}
```
— directly ratifiable by `apply_composition_claim()` with no operator-side design step.
For `proposed_change_kind == "composition_reclassification"`, dispatch by `missing_operator`:
- `quantity_extraction``multiplicative_composition` + `bound(count) × bound(unit_cost)` (currency-per-unit shape)
- `multi_quantity_composition``additive_composition` + `bound(qty_a) + bound(qty_b)` (default; operator may edit)
For `frame_reclassification`, `matcher_extension`, `injector_sub_shape` — keep current payload (those are still upstream of ratifiable claims).
### Reads required FIRST
- `teaching/math_contemplation.py::decompose_audit`
- `teaching/math_contemplation_proposal.py` (proposal schema)
- `teaching/math_composition_proposal.py::SAFE_COMPOSITION_CATEGORIES`
- `teaching/math_composition_ratification.py::apply_composition_claim` signature
### Hard requirements
- Backward-compatible JSONL: existing tests that read evidence_count + group_key + modal_sub_type must still pass
- Only `composition_reclassification` proposals get the enriched payload in v1 (frame/matcher/injector deferred)
- `polarity` is always `"affirms"` (the audit row signals a real refusal — the operator can override to `"falsifies"` if needed)
- `surface_pattern` must be in the operator's expected vocabulary (mirror the three SAFE patterns)
- An end-to-end test that runs `core eval math-contemplation` then immediately feeds the first composition proposal into `apply_composition_claim()` without any field synthesis
### Tests
- `tests/test_contemplation_ratifiable_payload.py`:
- 5+ test cases: each refusal pair yields a payload whose fields satisfy `apply_composition_claim`'s preconditions
- Round-trip: proposal payload → ratification → no exception
- Schema regression: existing fields still present
- `tests/test_adr_0172_w2_decomposer.py` — update existing assertions
### Truth test
After this PR + a fresh `core eval math-contemplation`, the operator workflow becomes:
```
core eval math-contemplation
core teaching review <composition-proposal-id> --accept --review-date YYYY-MM-DD
```
**without manually constructing a `MathReaderRefusalEvidence` or picking a category.**
---
## Brief C — Comprehension reader audit + decision
**Operator profile:** Sonnet (investigation + documentation; minor wiring if needed)
**Branch:** `docs/comprehension-reader-audit`
**Base:** `origin/main`
**Estimated effort:** small (investigation) — could escalate to medium if "operationalize" is chosen
### Why
The comprehension reader (`generate/comprehension/lifecycle.py` — `begin_sentence`, `apply_word`, `end_sentence`, `finalize`, `ProblemReadingState`, `EntityRef`, Phase 1/2 of ADR-0164) is substantial code that **admits zero cases in the math eval**.
Direct measurement:
```
core eval gsm8k_math --split public --use-reader → 150/150 wrong=0 (same as without)
train_sample --use-reader → 3/47/0 (same as without)
```
The reader exists but contributes nothing observable. Two possible truths:
1. **It's load-bearing for something we don't measure** (cognition lane? semantic recall? answer rendering?)
2. **It's a parallel R&D track that needs honest naming** as not-yet-operational on math
### Outcome (investigation phase)
Produce `docs/handoff/COMPREHENSION-READER-AUDIT.md` answering:
1. Where in the live code path does `_try_comprehension_reader` actually run? Trace every caller.
2. When `comprehension_reader_questions=True`, what specifically does the reader admit on the cognition eval lane (not just math)?
3. Is the all-or-nothing discipline (one refusing sentence kills the whole reader path) the bottleneck on math? Or is the reader itself refusing on simple shapes?
4. Are there ADR-0164 Phase 1/2 promises that aren't being honored?
5. List 3 options:
- **Operationalize**: change all-or-nothing → per-sentence so reader can contribute partial admissions
- **Relabel**: honest doc update naming reader as "cognition track, not math substrate" (if true)
- **Retire**: if the reader path duplicates capability that the regex/recognizer paths already provide
### Hard requirements
- No code changes in the investigation phase — pure read + doc
- Audit must distinguish reader-on-math vs reader-on-cognition usage
- Recommendation must be falsifiable (provide a measurable test for each option)
- If "operationalize" is chosen, ship as separate PR after operator approval
### Tests
- None in audit phase. Implementation phase (if approved): operationalize path requires its own test plan.
### Truth test
After this brief: the project has a deliberate answer to "what does the comprehension reader do today, and what should it do?" Right now nobody knows. That's the bug being closed.
---
## Brief D — `core teaching coverage` CLI
**Operator profile:** Sonnet (tight-scope CLI; mechanical aggregation)
**Branch:** `feat/teaching-coverage-cli`
**Base:** `origin/main`
**Estimated effort:** small
### Why
There's no automated way to answer "given the current ratified state, what % of train_sample admits / refuses / wrong-counts by ShapeCategory?" We only see deltas by running the eval manually and eyeballing report.json. Flying blind on operator dispatch decisions.
### Outcome
New CLI: `core teaching coverage [--lane gsm8k_math] [--split train_sample] [--use-reader] [--json]`
Behavior:
1. Run the lane's runner if its report.json is stale (or always, if `--run`)
2. Read the per-case verdict + refusal reasons
3. Bin by:
- `correct / refused / wrong`
- Within refused: by `(refusal_mode, ShapeCategory)` — using the same categorization the position paper §4 table uses
4. Emit a clean histogram with deltas vs the **last committed** report.json
Example output:
```
Lane: gsm8k_math/train_sample/v1 (use_reader=true)
Counts: correct=3 refused=47 wrong=0 (Δ from prior: 0 / 0 / 0)
Refusal taxonomy:
21 recognizer_empty_injection(discrete_count_statement)
10 no_admissible_candidate
5 recognizer_empty_injection(multiplicative_aggregation)
4 recognizer_empty_injection(currency_amount)
3 recognizer_empty_injection(rate_with_currency)
2 recognizer_empty_injection(temporal_aggregation)
2 recognizer_empty_injection(descriptive_setup_no_quantity)
Wrong=0: ✓
Case 0050 hazard pin: refused ✓
```
### Reads required FIRST
- `evals/gsm8k_math/train_sample/v1/runner.py`
- `evals/gsm8k_math/train_sample/v1/report.json` schema
- `core/cli.py` existing teaching subcommands
- `evals/refusal_taxonomy/shape_categories.py`
### Hard requirements
- Read-only (no eval lane mutation)
- Delta comparison against the most recent **committed** report.json (uses `git show HEAD:evals/.../report.json` — if absent, no delta)
- `--json` for CI integration
- `--lane` defaults to `gsm8k_math`; `--split` defaults to `train_sample`
- Refusal taxonomy is regex-pulled from `report.json[per_case][].reason` — no hardcoded category list
- Exit code 0 on success regardless of counts (it's a report, not a gate)
### Tests
- `tests/test_teaching_coverage_cli.py`:
- Fixture report.json with known counts → expected histogram
- Delta path: stage old + new report → expected delta
- `--json` schema
- Empty/malformed report.json → clear error
### Truth test
After dispatch: every operator can run `core teaching coverage` after any ratification to see exactly which refusal modes their work moved (or didn't).
---
## Brief E — Lexical ratification auto-compile
**Operator profile:** Codex (tiny mechanical; mirror RAT-1's pattern)
**Branch:** `feat/lexical-ratification-auto-compile`
**Base:** `origin/main`
**Estimated effort:** tiny
### Why
RAT-1 (PR #406) added `compile_pack()` auto-call at the end of `apply_frame_claim` + `apply_composition_claim` so source-file writes immediately reach the runtime. **`apply_lexical_claim` was deliberately skipped** because the existing `language_packs/compiler.py` already compiles `lexicon.jsonl`. But the lexicon compiler runs at pack-build time, not after a runtime ratification.
So today: `core teaching` ratifies a LexicalClaim → writes `lexicon/{category}.jsonl` → the **next runtime turn doesn't see it** because nothing triggers re-compile + manifest update.
### Outcome
Extend `teaching/math_lexical_ratification.py::apply_lexical_claim` to call `compile_pack()` at the end of a successful ratification — same pattern RAT-1 used for frame + composition.
Plus: ensure `compile_pack()` regenerates the lexicon compiled artifact `lexicon.jsonl` AND updates `manifest.checksum`. Currently RAT-1's `compile_pack` only handles frames + compositions; this brief extends it.
### Reads required FIRST
- `teaching/math_lexical_ratification.py::apply_lexical_claim`
- `language_packs/compile_pack.py` (the RAT-1 helper)
- `language_packs/compiler.py::_load_pack_cached` (existing lexicon compile)
- `generate/comprehension/lexicon.py::load_lexicon` (the runtime consumer)
### Hard requirements
- `wrong == 0` preserved (no test moves wrong)
- The existing lexicon checksum SCHEME stays the same — just regenerated more frequently
- Mirror RAT-1's `tests/test_math_{frame,composition}_ratification.py` update — `test_lexicon_checksum_preserved_by_lexical_ratification` (manifest may change; lexicon checksum re-derives from compiled bytes)
- Idempotent: running ratification twice doesn't bump checksum unless source bytes changed
- Existing `core teaching compile-pack` command should pick up lexical changes too — extend the receipt to include `lexicon_checksum` + `lexicon_bytes_written`
### Tests
- `tests/test_lexical_ratification_auto_compile.py`:
- Ratify a LexicalClaim → compile fires → lexicon registry reload sees the new entry
- Idempotent: second ratify with same evidence → no compile mutation
- Lexicon-checksum-preserved-across-ratify (with new bytes)
### Truth test
After this PR: a LexicalClaim ratification reaches the runtime within one turn, matching the frame + composition discipline RAT-1 established.
---
## Dispatch DAG
```
RAT-1 (PR #406) — base for all four briefs
├──── A (Opus, in-flight) — 4 missing injectors
├──── B (Opus) — contemplation ratifiable claims
├──── C (Sonnet) — comprehension reader audit
├──── D (Sonnet) — coverage CLI
└──── E (Codex) — lexical auto-compile (tiny)
```
All four briefs are parallel-safe — no shared file conflicts. Each touches different modules.
## Anti-regression invariants (all four)
- `wrong == 0` on `core eval gsm8k_math --split public` preserved (150/150)
- Case 0050 hazard pin holds
- `engine_state/*` never committed
- ADR-0166 — no new eval lanes
## Memory pointers
- [[milestone-me1-me5-matcher-extensions-complete]] — the wave that exposed the gaps
- [[project-ratification-consumption-gap-2026-05-27]] — the original finding
- [[feedback-ratify-vs-consume-loop-closure]] — the general pattern
---
## Copy-paste dispatch (per brief)
```text
# Brief B
Read docs/handoff/POST-RAT1-PARALLEL-BRIEFS.md §"Brief B".
git fetch origin main && git worktree add /tmp/wt-brief-b origin/main && cd /tmp/wt-brief-b && git checkout -b feat/contemplation-ratifiable-claims
# Brief C
Read docs/handoff/POST-RAT1-PARALLEL-BRIEFS.md §"Brief C".
git fetch origin main && git worktree add /tmp/wt-brief-c origin/main && cd /tmp/wt-brief-c && git checkout -b docs/comprehension-reader-audit
# Brief D
Read docs/handoff/POST-RAT1-PARALLEL-BRIEFS.md §"Brief D".
git fetch origin main && git worktree add /tmp/wt-brief-d origin/main && cd /tmp/wt-brief-d && git checkout -b feat/teaching-coverage-cli
# Brief E
Read docs/handoff/POST-RAT1-PARALLEL-BRIEFS.md §"Brief E".
git fetch origin main && git worktree add /tmp/wt-brief-e origin/main && cd /tmp/wt-brief-e && git checkout -b feat/lexical-ratification-auto-compile
```