docs(ADR-0172): Tier 1 brief pack — W0 through W4 with parallel waves (#378)
Coordination artifact for ADR-0172 Tier 1 dispatch. Six PRs in the ADR (W0, W0.1, W1, W2, W3, W4) collapsed into a 4-wave DAG with two concurrent briefs per wave A and B. Operators are dispatched in their own UIs by pointing at the section heading — "read §Brief A1" etc. Bundling options A/B/C inside the doc let the operator choose CI economy vs wall-clock. No runtime change. Pure docs.
This commit is contained in:
parent
b190f3b6c5
commit
2d5b119c6a
1 changed files with 502 additions and 0 deletions
502
docs/handoff/ADR-0172-TIER1-BRIEF-PACK.md
Normal file
502
docs/handoff/ADR-0172-TIER1-BRIEF-PACK.md
Normal file
|
|
@ -0,0 +1,502 @@
|
|||
# ADR-0172 Tier 1 — Brief Pack
|
||||
|
||||
**Goal:** Land the math-domain Learning Arc analog. Engine reads
|
||||
`audit_brief_11.json`, decomposes it into structural commonalities,
|
||||
emits `MathReaderRefusalShapeProposal` records (each carrying a
|
||||
`ReasoningTrace`) for HITL review.
|
||||
|
||||
**Scope:** Tier 1 only (extensional contemplation). Tier 2
|
||||
(intensional + two-arm test-and-learn) and Loop 3 (verdict feedback)
|
||||
ship later. Reference: `docs/decisions/ADR-0172-math-corpus-decomposition-mechanism.md`
|
||||
(on `origin/main`).
|
||||
|
||||
**Bundling rule:** Per Shay 2026-05-27 — during research/solutions-finding
|
||||
phases, batch chunks locally; one PR per coherent solution, not per
|
||||
file. **Each WAVE below is one PR.** Within a wave, parallel briefs
|
||||
land on the same branch.
|
||||
|
||||
---
|
||||
|
||||
## Dependency DAG
|
||||
|
||||
```
|
||||
Wave A (parallel) Wave B (parallel) Wave C Wave D
|
||||
───────────────── ──────────────── ────── ──────
|
||||
[A1] W0 ReasoningTrace ──┐
|
||||
├─→ [B1] W0.1 trace replay test
|
||||
│ ├─→ [C1] W3 ──┐
|
||||
[A2] W1 ShapeProposal ───┤ │ CLI lane ├─→ [D1] W4
|
||||
└─→ [B2] W2 Decomposer ──────┘ │ Workbench
|
||||
│ integration
|
||||
│ + e2e
|
||||
```
|
||||
|
||||
**Wave A** can launch immediately on origin/main once #377 (ADR-0170 W2) merges.
|
||||
**Wave B** launches once Wave A's branch is pushed (B1 and B2 can branch off
|
||||
A's tip in parallel).
|
||||
**Wave C** launches when Wave B's branch is pushed.
|
||||
**Wave D** launches when Wave C's branch is pushed.
|
||||
|
||||
Total wall-clock: 4 PRs if waves serialize, 2 PRs if A+B and C+D are bundled
|
||||
(see "Bundling options" at bottom).
|
||||
|
||||
---
|
||||
|
||||
## Worktree hygiene
|
||||
|
||||
Every brief opens with:
|
||||
|
||||
```bash
|
||||
cd /Users/kaizenpro/Projects/core
|
||||
git fetch origin main
|
||||
git worktree add /tmp/wt-<slug> origin/main # or off Wave-X tip for waves B/C/D
|
||||
cd /tmp/wt-<slug>
|
||||
```
|
||||
|
||||
**Never** `git add -A`. Stage explicit files only. `engine_state/*` are
|
||||
runtime artifacts — never commit.
|
||||
|
||||
---
|
||||
|
||||
## Brief A1 — W0: `ReasoningTrace` substrate
|
||||
|
||||
**Operator profile:** Opus (foundation schema; load-bearing for all
|
||||
downstream waves)
|
||||
**Branch:** `feat/adr-0172-w0-reasoning-trace`
|
||||
**Base:** `origin/main` (post-#377 merge)
|
||||
|
||||
### Outcome
|
||||
|
||||
A new module `teaching/math_reasoning_trace.py` defines:
|
||||
|
||||
```python
|
||||
@dataclass(frozen=True)
|
||||
class ReasoningStep:
|
||||
step_index: int
|
||||
step_kind: Literal[
|
||||
"observation", "grouping", "abstraction", "hypothesis",
|
||||
"test_design", "test_application", "test_result", "conclusion",
|
||||
]
|
||||
input_pointers: tuple[str, ...] # IDs of prior steps / evidence rows
|
||||
claim: str
|
||||
justification: str
|
||||
output_payload: object # JSON-serializable; type-discriminated by step_kind
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ReasoningTrace:
|
||||
trace_id: str # content hash of canonical bytes
|
||||
steps: tuple[ReasoningStep, ...]
|
||||
|
||||
def canonical_bytes(trace: ReasoningTrace) -> bytes: ...
|
||||
def compute_trace_id(steps: tuple[ReasoningStep, ...]) -> str: ...
|
||||
def build_trace(steps: list[ReasoningStep]) -> ReasoningTrace:
|
||||
"""Validates step_index continuity, sorts, computes trace_id."""
|
||||
```
|
||||
|
||||
### Hard requirements
|
||||
|
||||
- Canonical-bytes serialization: stable JSON ordering (sorted keys,
|
||||
no whitespace, UTF-8, deterministic float repr if any).
|
||||
- `compute_trace_id` = `hashlib.sha256(canonical_bytes(...)).hexdigest()`.
|
||||
- `build_trace` enforces `step_index` starts at 0, monotonic +1,
|
||||
no gaps. Raises `ValueError` on violation.
|
||||
- `output_payload` must be JSON-serializable. Validate at construction.
|
||||
- Tier 1 step_kinds used: `observation`, `grouping`, `hypothesis`,
|
||||
`conclusion`. The other four (`abstraction`, `test_design`,
|
||||
`test_application`, `test_result`) are reserved for Tier 2; the
|
||||
schema admits them but no Tier 1 code path emits them yet.
|
||||
|
||||
### Tests (`tests/test_adr_0172_w0_reasoning_trace.py`)
|
||||
|
||||
1. `test_step_index_must_start_at_zero` — passing `step_index=1` first → ValueError.
|
||||
2. `test_step_index_must_be_monotonic` — `[0, 2]` → ValueError.
|
||||
3. `test_canonical_bytes_stable_across_runs` — same steps → byte-identical.
|
||||
4. `test_trace_id_changes_when_claim_changes` — sensitivity check.
|
||||
5. `test_trace_id_invariant_to_dict_insertion_order` — payload dict key ordering doesn't shift id.
|
||||
6. `test_non_json_serializable_payload_rejected` — `set()` payload → ValueError.
|
||||
7. `test_all_eight_step_kinds_accepted` — schema admits all Literal members.
|
||||
8. `test_empty_trace_rejected` — `build_trace([])` → ValueError.
|
||||
|
||||
### Forbidden
|
||||
|
||||
- Any runtime hook into the cognitive pipeline (W0 is schema-only).
|
||||
- Importing anything from `chat/`, `field/`, `generate/`, `algebra/`.
|
||||
- Floating-point usage in canonical bytes (use int / str only).
|
||||
|
||||
### Deliverable
|
||||
|
||||
- `teaching/math_reasoning_trace.py` (new file, ≤200 lines)
|
||||
- `tests/test_adr_0172_w0_reasoning_trace.py` (new file)
|
||||
- `core test --suite teaching -q` green
|
||||
|
||||
---
|
||||
|
||||
## Brief A2 — W1: `MathReaderRefusalShapeProposal` schema
|
||||
|
||||
**Operator profile:** Sonnet (schema mirror of cognition's
|
||||
`teaching/proposals.py`; bounded scope)
|
||||
**Branch:** `feat/adr-0172-w1-shape-proposal` (separate worktree from A1)
|
||||
**Base:** `origin/main` (post-#377 merge)
|
||||
**Runs concurrent with A1** — no shared files.
|
||||
|
||||
### Outcome
|
||||
|
||||
A new module `teaching/math_contemplation_proposal.py` defines:
|
||||
|
||||
```python
|
||||
@dataclass(frozen=True)
|
||||
class MathReaderRefusalShapeProposal:
|
||||
proposal_id: str
|
||||
domain: Literal["math"]
|
||||
shape_category: ShapeCategory # from evals.refusal_taxonomy.shape_categories
|
||||
structural_commonality: str
|
||||
evidence_pointers: tuple[MathReaderRefusalEvidence, ...] # ≥2; from teaching/audit_evidence.py
|
||||
proposed_change_kind: Literal[
|
||||
"matcher_extension",
|
||||
"injector_sub_shape",
|
||||
"vocabulary_addition",
|
||||
"frame_reclassification",
|
||||
]
|
||||
proposed_change_payload: object # JSON-serializable; discriminated by change_kind
|
||||
wrong_zero_assertion: str
|
||||
replay_equivalence_hash: str
|
||||
reasoning_trace: ReasoningTrace # from W0
|
||||
|
||||
def canonical_bytes(p: MathReaderRefusalShapeProposal) -> bytes: ...
|
||||
def compute_proposal_id(...) -> str: ...
|
||||
def build_proposal(...) -> MathReaderRefusalShapeProposal:
|
||||
"""Validates evidence ≥2, payload JSON-serializable, hashes."""
|
||||
```
|
||||
|
||||
### Hard requirements
|
||||
|
||||
- `proposal_id = sha256(canonical_bytes(...))` minus the proposal_id
|
||||
field itself (chicken-and-egg: hash the content, not the id).
|
||||
- `build_proposal` enforces `len(evidence_pointers) >= 2` (raises ValueError).
|
||||
- `domain == "math"` enforced as Literal; `ShapeCategory` validated as enum member.
|
||||
- `wrong_zero_assertion` non-empty (≥40 chars, soft pin: ValueError if empty).
|
||||
- `replay_equivalence_hash` matches ADR-0057's existing replay-equivalence
|
||||
contract format — copy the convention from `teaching/proposals.py`.
|
||||
- `reasoning_trace` field is mandatory (carries W0 trace).
|
||||
|
||||
### Tests (`tests/test_adr_0172_w1_shape_proposal.py`)
|
||||
|
||||
1. `test_minimum_two_evidence_rows` — passing 1 evidence row → ValueError.
|
||||
2. `test_canonical_bytes_stable` — same input → byte-identical output.
|
||||
3. `test_proposal_id_determinism` — same content → same id.
|
||||
4. `test_change_kind_literal_enforced` — invalid `change_kind` rejected.
|
||||
5. `test_change_payload_must_be_json_serializable` — `set()` → ValueError.
|
||||
6. `test_wrong_zero_assertion_required` — empty string → ValueError.
|
||||
7. `test_reasoning_trace_required` — `None` trace → ValueError.
|
||||
8. `test_all_four_change_kinds_round_trip` — schema admits all Literal members.
|
||||
|
||||
### Cross-references the operator must read first
|
||||
|
||||
- `teaching/proposals.py` — the cognition `TeachingChainProposal` (template)
|
||||
- `teaching/audit_evidence.py` — `MathReaderRefusalEvidence` shape (ADR-0167)
|
||||
- `evals/refusal_taxonomy/shape_categories.py` — `ShapeCategory` enum
|
||||
|
||||
### Forbidden
|
||||
|
||||
- Any runtime hook into ingest, gate, vault, or solver.
|
||||
- Importing W0 from a relative path — use `from teaching.math_reasoning_trace import ReasoningTrace`.
|
||||
- Inventing a new `change_kind` not listed in the ADR.
|
||||
|
||||
### Deliverable
|
||||
|
||||
- `teaching/math_contemplation_proposal.py` (new file, ≤250 lines)
|
||||
- `tests/test_adr_0172_w1_shape_proposal.py` (new file)
|
||||
- `core test --suite teaching -q` green
|
||||
|
||||
---
|
||||
|
||||
## Brief B1 — W0.1: Trace replay-equivalence
|
||||
|
||||
**Operator profile:** Codex (mechanical determinism test)
|
||||
**Branch:** `feat/adr-0172-w0-1-trace-replay-equivalence`
|
||||
**Base:** Tip of Wave A (after A1 + A2 merge or fast-forward locally).
|
||||
**Runs concurrent with B2** — no shared files.
|
||||
|
||||
### Outcome
|
||||
|
||||
Pin the W0 contract: same input → byte-identical `ReasoningTrace`.
|
||||
|
||||
### Tests (`tests/test_adr_0172_w0_1_trace_replay_equivalence.py`)
|
||||
|
||||
1. `test_build_trace_replay_equivalence_minimal` — 2 steps, run 100 times → all identical bytes.
|
||||
2. `test_build_trace_payload_dict_key_order_invariance` — `{"a":1,"b":2}` and `{"b":2,"a":1}` payloads → same trace_id.
|
||||
3. `test_build_trace_under_process_restart` — write canonical bytes to a tmp file in one process,
|
||||
re-derive in a second process via `uv run python -c "..."`, assert byte-identical.
|
||||
4. `test_trace_id_collision_resistance` — 1000 random-but-deterministic step sequences,
|
||||
no id collisions (sanity check on hash quality).
|
||||
5. `test_canonical_bytes_no_floating_point` — assert no `float` instance appears in
|
||||
any canonical-byte payload across the test corpus (regex `[0-9]+\.[0-9]+` absent).
|
||||
|
||||
### Deliverable
|
||||
|
||||
- `tests/test_adr_0172_w0_1_trace_replay_equivalence.py` (new file)
|
||||
- No production changes. Pure pinning.
|
||||
|
||||
---
|
||||
|
||||
## Brief B2 — W2: Audit-corpus decomposer
|
||||
|
||||
**Operator profile:** Opus (load-bearing logic; the cognition decomposer
|
||||
analog. Get it right.)
|
||||
**Branch:** `feat/adr-0172-w2-decomposer`
|
||||
**Base:** Tip of Wave A.
|
||||
**Runs concurrent with B1** — no shared files.
|
||||
|
||||
### Outcome
|
||||
|
||||
A new module `teaching/math_contemplation.py` defines:
|
||||
|
||||
```python
|
||||
def decompose_audit(audit_path: Path) -> tuple[MathReaderRefusalShapeProposal, ...]:
|
||||
"""
|
||||
Read audit_brief_11.json, group refusal rows by
|
||||
(refusal_reason, missing_operator), emit one
|
||||
MathReaderRefusalShapeProposal per group with ≥2 evidence rows.
|
||||
Naive algorithm per ADR-0172 §"Six open questions" #1.
|
||||
"""
|
||||
```
|
||||
|
||||
### Algorithm (verbatim from ADR)
|
||||
|
||||
1. Parse `audit_path` (expect `evals/gsm8k_math/train_sample/v1/audit_brief_11.json`).
|
||||
2. Group rows by `(refusal_reason, missing_operator)` tuple.
|
||||
3. For each group with `≥2` rows:
|
||||
a. Build evidence list: `MathReaderRefusalEvidence` for each row (use `teaching/audit_evidence.py` helpers).
|
||||
b. Build `ReasoningTrace` with 4 steps:
|
||||
- step 0: `observation` — "N refusal rows share (refusal_reason, missing_operator)"
|
||||
- step 1: `grouping` — encode group key as payload
|
||||
- step 2: `hypothesis` — pick `proposed_change_kind` by heuristic (see below)
|
||||
- step 3: `conclusion` — restate the proposed change.
|
||||
c. Derive `proposed_change_kind` heuristic:
|
||||
- `refusal_reason == "lexicon_entry"` → `vocabulary_addition`
|
||||
- `refusal_reason == "narrowness_violation"` → `matcher_extension`
|
||||
- `refusal_reason == "frame_unrecognized"` → `frame_reclassification`
|
||||
- else → `injector_sub_shape`
|
||||
d. Build `MathReaderRefusalShapeProposal` with placeholder
|
||||
`proposed_change_payload` (a dict of the group's modal anchor shape)
|
||||
and `wrong_zero_assertion`: "Proposal is evidence-only; ratification
|
||||
handler is the wrong=0 surface, not this proposal."
|
||||
4. Sort output proposals by `proposal_id` for determinism.
|
||||
5. Return tuple.
|
||||
|
||||
### Determinism contract (CRITICAL)
|
||||
|
||||
- Group iteration order MUST be sorted by `(refusal_reason, missing_operator)`.
|
||||
- Evidence list per group MUST be sorted by `case_id`.
|
||||
- Reasoning step payload dicts MUST use sorted keys.
|
||||
- Same `audit_brief_11.json` → byte-identical proposal stream across reruns.
|
||||
|
||||
### Tests (`tests/test_adr_0172_w2_decomposer.py`)
|
||||
|
||||
1. `test_decompose_audit_emits_at_least_one_proposal` — on the real audit file.
|
||||
2. `test_decompose_audit_deterministic_across_reruns` — run 10x, assert all outputs identical.
|
||||
3. `test_decompose_audit_minimum_evidence_threshold` — groups with 1 row do NOT emit.
|
||||
4. `test_decompose_audit_change_kind_dispatch` — synthetic 4-row audit with
|
||||
one row per heuristic branch; assert each emits the expected `change_kind`.
|
||||
5. `test_decompose_audit_reasoning_trace_has_four_steps` — every emitted proposal carries a 4-step trace.
|
||||
6. `test_decompose_audit_evidence_sorted_by_case_id` — synthetic audit with out-of-order case_ids; assert sorted in output.
|
||||
7. `test_decompose_audit_proposal_ids_sorted` — output tuple is sorted by proposal_id.
|
||||
8. `test_decompose_audit_empty_file_returns_empty_tuple` — `[]` input → `()` output.
|
||||
9. `test_decompose_audit_no_runtime_mutation` — assert no file is written, no global state touched.
|
||||
|
||||
### Forbidden
|
||||
|
||||
- Auto-applying any proposal. Pure read-only decomposition.
|
||||
- Writing to `teaching/math_proposals/*` (that's W3's job).
|
||||
- Importing from `chat/`, `field/`, `generate/`, `algebra/`. Decomposer
|
||||
is teaching-layer code only.
|
||||
- Mutating the input audit file.
|
||||
|
||||
### Deliverable
|
||||
|
||||
- `teaching/math_contemplation.py` (new file, ≤350 lines)
|
||||
- `tests/test_adr_0172_w2_decomposer.py` (new file)
|
||||
- `core test --suite teaching -q` green
|
||||
|
||||
---
|
||||
|
||||
## Brief C1 — W3: `core eval math-contemplation` CLI lane
|
||||
|
||||
**Operator profile:** Sonnet (CLI plumbing, well-bounded)
|
||||
**Branch:** `feat/adr-0172-w3-cli-lane`
|
||||
**Base:** Tip of Wave B.
|
||||
|
||||
### Outcome
|
||||
|
||||
A new CLI subcommand:
|
||||
|
||||
```bash
|
||||
core eval math-contemplation [--audit-path PATH] [--output PATH]
|
||||
```
|
||||
|
||||
- Reads audit file (default: `evals/gsm8k_math/train_sample/v1/audit_brief_11.json`).
|
||||
- Calls `decompose_audit()` from W2.
|
||||
- Writes proposals to `teaching/math_proposals/proposals.jsonl` (default).
|
||||
- Prints summary: N proposals emitted, by `change_kind` breakdown.
|
||||
|
||||
### Hard requirements
|
||||
|
||||
- Output file is JSONL: one proposal per line, canonical-bytes-encoded.
|
||||
- Output is sorted by proposal_id (matches W2's order).
|
||||
- Re-running the command on the same audit overwrites with identical bytes
|
||||
(idempotent).
|
||||
- Exit code 0 on success, 1 on audit-file-not-found, 2 on parse error.
|
||||
- Output path validated (no traversal — apply `language_packs/compiler.py::_validate_pack_id` pattern).
|
||||
|
||||
### CLI wiring
|
||||
|
||||
- Locate `core/cli.py` (or wherever `core eval cognition` is registered).
|
||||
- Mirror that subcommand structure exactly.
|
||||
- Register as `core eval math-contemplation`.
|
||||
|
||||
### Tests (`tests/test_adr_0172_w3_cli_lane.py`)
|
||||
|
||||
1. `test_cli_emits_jsonl_to_default_path` — invoke via `subprocess.run`, check file exists.
|
||||
2. `test_cli_idempotent` — run twice, assert second-run file is byte-identical to first.
|
||||
3. `test_cli_rejects_path_traversal` — `--output ../../etc/passwd` → exit 2.
|
||||
4. `test_cli_missing_audit_exit_1` — bogus `--audit-path` → exit 1.
|
||||
5. `test_cli_summary_stdout_format` — assert summary line matches expected format (regex).
|
||||
|
||||
### Deliverable
|
||||
|
||||
- CLI subcommand wired in `core/cli.py` (or sibling).
|
||||
- `teaching/math_proposals/.gitkeep` (so the dir exists; proposals.jsonl is gitignored).
|
||||
- `.gitignore` entry for `teaching/math_proposals/proposals.jsonl`.
|
||||
- `tests/test_adr_0172_w3_cli_lane.py` (new file).
|
||||
- `core test --suite runtime -q` green.
|
||||
|
||||
### Forbidden
|
||||
|
||||
- Auto-applying any proposal (CLI is read+emit, no ratification side-effect).
|
||||
- Modifying the audit file.
|
||||
- Writing proposals outside `teaching/math_proposals/` (path-scoped).
|
||||
|
||||
---
|
||||
|
||||
## Brief D1 — W4: Workbench integration + e2e
|
||||
|
||||
**Operator profile:** Sonnet (UI/workbench wiring; bounded)
|
||||
**Branch:** `feat/adr-0172-w4-workbench`
|
||||
**Base:** Tip of Wave C.
|
||||
|
||||
### Outcome
|
||||
|
||||
The workbench (ADR-0160) renders math proposals alongside cognition
|
||||
proposals. The two proposal streams remain partitioned by
|
||||
`domain` discriminator.
|
||||
|
||||
### Hard requirements
|
||||
|
||||
- Workbench reads from `teaching/math_proposals/proposals.jsonl` (W3's output).
|
||||
- Math proposals render with `domain: math` badge (visible distinction
|
||||
from `domain: cognition`).
|
||||
- Operator can `ratify` / `reject` a math proposal. Ratification routes to
|
||||
the existing handler dispatch (LexicalClaim for `vocabulary_addition`,
|
||||
FrameClaim for `frame_reclassification`, etc. per ADR-0167-FOLLOWUPS §1).
|
||||
If a handler doesn't exist yet (e.g. `matcher_extension` has no handler
|
||||
on `main` yet), emit a clear "handler not yet implemented" message and
|
||||
refuse the action — do NOT silently no-op.
|
||||
- The proposal's `reasoning_trace` is rendered in expandable form (per-step claims visible).
|
||||
|
||||
### e2e test (`tests/test_adr_0172_w4_workbench_e2e.py`)
|
||||
|
||||
1. `test_workbench_loads_math_proposals_from_jsonl` — write a fixture jsonl, assert workbench reads it.
|
||||
2. `test_workbench_renders_domain_badge` — math proposal carries math badge.
|
||||
3. `test_workbench_ratify_routes_to_lexical_claim_handler` — ratifying a `vocabulary_addition` proposal calls LexicalClaim handler.
|
||||
4. `test_workbench_rejects_unhandled_change_kind_loudly` — `matcher_extension` ratify → explicit error, no silent no-op.
|
||||
5. `test_workbench_renders_reasoning_trace_steps` — all 4 trace steps visible.
|
||||
6. `test_workbench_no_cognition_math_cross_contamination` — math proposals don't appear in cognition queue and vice versa.
|
||||
|
||||
### Workbench files to inspect first
|
||||
|
||||
- `chat/workbench.py` (or wherever ADR-0160's workbench lives — grep for `cognition_proposals`)
|
||||
- ADR-0160 itself (`docs/decisions/ADR-0160-*.md`)
|
||||
- ADR-0167-FOLLOWUPS §1 for the handler dispatch table
|
||||
|
||||
### Forbidden
|
||||
|
||||
- Auto-ratifying any proposal.
|
||||
- Reading proposals from anywhere other than `teaching/math_proposals/`.
|
||||
- Writing to the cognition proposal queue from math handlers.
|
||||
|
||||
### Deliverable
|
||||
|
||||
- `chat/workbench.py` (or sibling) updated.
|
||||
- `tests/test_adr_0172_w4_workbench_e2e.py` (new file).
|
||||
- `core test --suite teaching -q` and `core test --suite runtime -q` green.
|
||||
- `core eval math-contemplation` works end-to-end and proposals appear in workbench.
|
||||
|
||||
---
|
||||
|
||||
## Bundling options (operator choice)
|
||||
|
||||
**Option 1 — Maximum parallelism (4 PRs):**
|
||||
- Wave A (PR-α): A1 + A2 bundled (W0 + W1 schemas). Two operators, one branch.
|
||||
- Wave B (PR-β): B1 + B2 bundled (W0.1 trace test + W2 decomposer). Two operators, one branch.
|
||||
- Wave C (PR-γ): C1 alone (W3 CLI).
|
||||
- Wave D (PR-δ): D1 alone (W4 workbench).
|
||||
|
||||
**Option 2 — Substrate-first (2 PRs):** (recommended for first attempt)
|
||||
- PR-α: A1 + A2 + B1 (all schema work + replay test). One operator can do all three
|
||||
sequentially since they're tight + closely coupled.
|
||||
- PR-β: B2 + C1 + D1 (decomposer + CLI + workbench). The full materialization
|
||||
of the substrate into the user-facing lane.
|
||||
|
||||
**Option 3 — All-in-one (1 PR):**
|
||||
- Single PR shipping W0 through W4. Largest reviewable surface but lowest
|
||||
CI thrash. Best if a single operator (Opus) drives the whole chunk.
|
||||
|
||||
**Shay's call:** Per "batch during research" rule (2026-05-27), Option 2 or
|
||||
Option 3 minimizes CI churn. Option 1 maximizes wall-clock if multiple
|
||||
operators are available simultaneously.
|
||||
|
||||
---
|
||||
|
||||
## Anti-regression invariants (all waves)
|
||||
|
||||
- `wrong == 0` on `core eval gsm8k_math` — unaffected (W0–W4 are
|
||||
teaching-layer evidence-only).
|
||||
- ADR-0166 — no new eval lanes. The `core eval math-contemplation`
|
||||
lane is a *teaching-corpus decomposition lane*, not a capability
|
||||
measurement lane.
|
||||
- ADR-0057 replay-equivalence — W0 traces and W2 proposals inherit
|
||||
the byte-identical-replay contract.
|
||||
- ADR-0167-FOLLOWUPS — Tier 1 proposals route to existing handler
|
||||
dispatch, do not invent new handlers.
|
||||
- `engine_state/*` — never committed.
|
||||
- Pinned-lane SHAs — Tier 1 should not require updates (no canonical
|
||||
lane changes). If a wave needs a pin update, it's a signal to
|
||||
re-scope.
|
||||
|
||||
---
|
||||
|
||||
## Memory pointers (must read before starting any wave)
|
||||
|
||||
- `feedback-batch-during-research` — bundle chunks; one PR per coherent solution
|
||||
- `feedback-no-self-dispatch-of-subagents` — Shay dispatches operators; brief author does NOT call Agent tool
|
||||
- `feedback-wrong-zero-hazard-case-0050` — the canary; every wave verifies it stays refused
|
||||
- `feedback-parallel-agent-worktrees` — each parallel brief opens with `git worktree add`
|
||||
- `feedback-cleanup-as-you-find` — any dead code revealed mid-implementation is removed in the same PR
|
||||
- `feedback-adr-cross-reference-discipline` — grep all ADRs + codebase for inner mechanisms before reinventing
|
||||
|
||||
---
|
||||
|
||||
## What ships when Tier 1 lands
|
||||
|
||||
The math-domain Learning Arc closes:
|
||||
|
||||
```
|
||||
math refusal → audit row → engine decomposes → engine PROPOSES
|
||||
shape change → HITL ratifies → handler materializes → next session
|
||||
admits what was previously refused
|
||||
```
|
||||
|
||||
That's the same loop cognition closed on 2026-05-25. Tier 2 (intensional
|
||||
+ two-arm test-and-learn) and Loop 3 (verdict feedback) extend the
|
||||
arc into structural-equivalence-class learning. Tier 1 is the
|
||||
substrate they ride on.
|
||||
Loading…
Reference in a new issue