miri-task · diff
git:20260603.fb256e0 to git:20260623.6447d7a
51 added, 55 removed. Audit A to A.
---
name: miri-task
- description: CTO-orchestrated end-to-end execution of a Miri compiler task — understand and challenge scope, classify its risk tier (Trivial/Standard/Major per PRINCIPLES.md §8), then scale review to the tier: implement with TDD via the Lead Miri Engineer and validate through the full specialist panel (Major), miri-reviewer alone (Standard), or make audit + tests (Trivial). Loops until the CTO declares done with no open critical/major issues. Use when the user references a milestone, a plan file, or a free-form task. Done only when the CTO concludes done.
+ description: Fast single-agent end-to-end execution of a Miri compiler task — no subagents. You implement the feature yourself with TDD (Red-Green-Refactor), then run a self-review folding in every specialist lens (Rust idiom, Perceus/memory safety, architecture/SOLID, test coverage/honesty, compiler-design soundness, GPU), and finish with QA on your own work. Done ONLY when format, lint, build, the full test suite, and `make audit` are all green and the self-QA pass finds no open critical/major issue. Use for everyday features and fixes. For high-risk Major work or an explicit multi-perspective panel, use `miri-panel-task` instead.
---
- # Miri task — CTO-orchestrated implementation
+ # Miri task — single-agent fast path
- **You are the CTO.** You own this task from intake to sign-off. You run in the main thread because you can spawn subagents (specialists cannot spawn each other). You understand the task, challenge it where needed, organize the architects and the Lead Miri Engineer to implement it, then validate through `miri-audit` and loop until it is genuinely done. **The task is done only when you conclude it is — critical and major issues are never left open.**
+ **You do the whole task yourself, in the main thread. No subagents.** This is the fast path: one focused engineer who implements, reviews their own work through every specialist lens, QAs it, and refuses to declare done until the gate is green. It exists because delegating everyday features to a subagent panel is slow and the subagents over-report progress, miss real failures, and run out of context. You keep the context; you own the result.
- **Binding standard: `PRINCIPLES.md` at the repo root.** Read it before anything else.
+ **Binding standard: `PRINCIPLES.md` at the repo root.** Read it before writing code. Also honor `AGENTS.md`.
- ## Inputs
+ If the task is genuinely high-risk (a new `MirInstruction`/`Place`/terminator variant, a runtime ABI change, new `unsafe`, a non-trivial Perceus change, a GPU lowering change, or a cross-layer redesign — PRINCIPLES.md §8.1) and you want independent eyes, stop and tell the user to run `miri-panel-task` instead. Otherwise proceed solo.
- Argument names the task:
- - *Milestone reference* (`/miri-task 1.5`, `"Phase 2"`) → locate it in the plan file (ask which if unknown), quote its deliverables back.
- - *File path* (`/miri-task notes/tasks/feature.md`) → read it, quote acceptance criteria back.
- - *Free-form text* (`/miri-task "Implement Set.union"`) → treat the text as the spec.
+ ## Explore via the code graph FIRST (do not read file-by-file)
- If no argument is given, ask what to implement — do not guess scope.
+ Before any Grep/Glob/Read sweep, use the `code-review-graph` MCP tools — they are faster, cheaper, and give structural context a file scan cannot:
+ - `semantic_search_nodes` / `query_graph` to locate the closest analogous feature (how a similar operator lowers, how a sibling intrinsic is declared, how a method is intercepted) — instead of grepping.
+ - `get_impact_radius` + `get_affected_flows` to learn the blast radius **before** you touch anything (which visitors, call sites, tests are affected).
+ - `query_graph` pattern=`tests_for` to find existing coverage; `callers_of` / `callees_of` / `imports_of` to trace relationships.
+ - `get_review_context` for token-efficient source snippets when reviewing your own diff.
+
+ Fall back to Grep/Glob/Read only for what the graph does not cover. Reach analogous code through the graph, then read just the relevant span.
+
## Procedure
- 1. **Understand & challenge (CTO, before any code).** Restate the task and its acceptance criteria. Ask clarifying questions if scope, semantics, or success criteria are ambiguous. Challenge the request where it makes practical sense to (wrong altitude, missing error path, conflicts with an existing invariant, simpler design available). Do not start implementation until scope is confirmed.
- 2. **Classify the tier (CTO — PRINCIPLES.md §8).** Run the §8.1 Major-risk trigger checklist against the confirmed scope. State the chosen tier and the trigger that set it. The tier decides how much review the change earns (and is re-confirmed after implementation, since the real diff may trip a trigger the plan didn't):
- - **Trivial** (§8.2: typo/comment/rename/doc, ≤ 2 files, no logic, **and not under `src/mir/` / `perceus.rs` / `src/codegen/` / `src/runtime/`**) → skip the design pass and the panel. Dispatch `lead-miri-engineer` (or a `cavecrew-builder`) for the edit, then go straight to step 6 with **`make audit` + `miri-test-runner` only**.
- - **Standard** (single-stage feature/fix, no §8.1 trigger) → skip the architect design pass. Implement (step 4), then validate with **`miri-reviewer` alone** + `miri-test-runner` (not the full panel).
- - **Major** (any §8.1 trigger fires) → full path: design pass (step 3) + full `miri-audit` panel (step 5).
- When unsure between two tiers, pick the higher.
- 3. **Design pass — Major tier only (architects).** Map scope to the pipeline (lexer / parser / type checker / MIR lowering / Perceus / codegen / runtime / stdlib / GPU); name new files and confirm naming; use `miri-explorer` to locate the closest analog. Spawn `lead-compiler-architect` (and `lead-gpu-engineer` if GPU is involved) to produce a design sketch and call out soundness risks, the right lowering seam, monomorphization/residency concerns, and visitor-contract impact **before** code is written. Adjudicate their input into a design brief. (Standard/Trivial tiers skip this — map scope inline and proceed.)
- 4. **Implement (Lead Miri Engineer, TDD).** Dispatch `lead-miri-engineer` with the brief. It works one acceptance criterion at a time through **RED → GREEN → REFACTOR**, gated and logged (failing test first, confirmed failing for the right reason; minimum code to green; refactor with suite green). Every error path gets an `assert_compiler_error` / `assert_runtime_error` test. New runtime intrinsics are exported, declared in stdlib, and the runtime rebuilt. New MIR variants update every visitor. It reports the diff + RED/GREEN/REFACTOR log.
- 5. **Validate (tier-scaled).**
- - **Major** → run the `miri-audit` skill on the diff: the full panel (§9 owners) fans out, you consolidate and verify, the Lead Miri Engineer fixes every critical/major. Do not hand-roll a separate pass.
- - **Standard** → spawn `miri-reviewer` on the diff + `miri-test-runner`. Route its critical/major back to the Lead Miri Engineer. Escalate to the full panel **only** if the reviewer or the engineer's diff trips a §8.1 trigger the tier missed.
- - **Trivial** → `make audit` + `miri-test-runner` only.
- All findings use the §10 severity rubric.
- 6. **Loop (tight).** Route blockers back to the Lead Miri Engineer, re-implement, re-validate. **Re-run only what the fix touched** — `make audit` + `miri-test-runner` always; re-run a specialist (Major) or `miri-reviewer` (Standard) **only if its owned axis (§9) was changed by the fix** and the change was non-mechanical. No full re-panel for a mechanical fix. Repeat until the gate is green and no critical/major remains. If the same root cause survives three attempts, stop and ask the user — do not churn.
- 7. **Update docs / plan.** If a module's core logic changed, update its local `README.md`. If scope came from a plan file, mark items done. Record any out-of-scope discoveries as follow-ups in `notes/PLAN.md`.
- 8. **Final CTO report** (format below), naming the tier and embedding the reports from the validation pass (panel for Major, `miri-reviewer` for Standard, none for Trivial).
+ 1. **Understand & challenge.** Restate the task and its acceptance criteria. If a milestone/plan-file/free-form arg was given, quote the deliverables back. Ask clarifying questions if scope, semantics, or success criteria are ambiguous. Challenge the request where it makes practical sense (wrong altitude, missing error path, conflicts with an existing invariant, simpler design available). Don't start coding until scope is confirmed.
+ 2. **Map the change.** Use the graph to map scope to the pipeline (lexer → parser → `ast/factory.rs` → type checker → `mir/lowering/` (intercepts in `control_flow.rs`) → `mir/optimization/perceus.rs` → `codegen/cranelift/` → `runtime/{core,gpu}/` → `stdlib/**/*.mi`). Name any new files and confirm naming against the closest analog. Run `get_impact_radius` so you know every visitor/call site/test you must update in the same pass — don't discover them one breakage at a time (blast-radius first, per AGENTS.md §5).
+ 3. **Implement with TDD, gated (MANDATORY — never skipped).** Per acceptance criterion:
+ - **RED** — write the failing test first in `tests/integration/` (helpers: `assert_runs`, `assert_runs_with_output`, `assert_compiler_error`, `assert_runtime_error`, `assert_runtime_crash`). Run `cargo test --test mod "name"`. Confirm it fails for the *right* reason. If it passes immediately, the test is wrong.
+ - **GREEN** — minimum code to pass. No speculative generality, no drive-by refactors.
+ - **REFACTOR** — functions ≤ 80 lines (default ≤ 40), verbs for fns / nouns for types / predicates for bools, no duplication, exhaustive matches (no `_ =>` over Miri enums). Re-run after each step; revert any step that reddens the suite.
+ - Cover the **error path** (`assert_compiler_error` / `assert_runtime_error`) — happy-path-only is incomplete. Stdlib tests mirror the source path under `tests/stdlib/**`; **never** `panic(...)` in `src/stdlib/**`.
+ 4. **Self-review — fold in every specialist lens (do this on your own diff).** Walk each axis and fix what you find as you go:
+ - **Compiler design soundness** — is a new IR/`Place`/terminator variant the right abstraction or a special-case? Is logic at the right layer (intercept vs class-method mangling vs runtime intrinsic)? Does it compose with existing lowering? Generic/value-generic handling without signature collisions?
+ - **Visitor completeness** (§5.4) — new MIR/`Place` variant? `grep`/graph every match arm and visitor (`perceus.rs`, codegen, analyses) and update all. No `_ =>` masking a gap.
+ - **Perceus / memory safety** (§5.1) — new managed temp, field projection, or method-dispatch intercept? `Copy` of a managed `Place` with empty projection gets IncRef; field-projected copies do NOT (guard `emit_temp_drop` on `projection.is_empty()`). Missed IncRef = UAF; spurious DecRef = double-free.
+ - **Runtime/stdlib ABI as a trust boundary** (§5.2) — new intrinsic = three coordinated edits: export in `src/runtime/{core,gpu}/`, declare with the `runtime` keyword in the right `.mi`, rebuild (`cd src/runtime/core && cargo build --release`). Rust signature MUST match the Cranelift ABI for the declared param types (a width/pointer mismatch is corruption). Check `out`-param stack-slot copy-in/copy-out and `#[repr(C)]` layout.
+ - **Bounds / overflow / hostile input** — index validated before the runtime touches the buffer; size/offset arithmetic can't wrap (`checked_*`/`saturating_*`); no `unwrap()`/`expect()`/`panic!` reachable from a crafted `.mi` source (that's a DoS — propagate via `Result<T, MiriError>`).
+ - **Stdlib independence** (§1.1, §5.3) — never hardcode a stdlib type name (`"List"`, `"Set"`, …) in compiler dispatch; reach types via the type table. Highest-priority architecture rule.
+ - **Architecture / SOLID** (§1–§2) — layer direction (no codegen types leaking into mir/type_checker), SRP (no `foo_and_bar`, no God object), OCP (`if backend == "..."` only in the dispatcher), real DRY duplication.
+ - **Rust idiom & perf** (§3, §6) — no needless `clone()`/`to_string()` on managed/hot-path values, iterator chains over manual index loops, `?` over long-hand `match`, no avoidable O(n²) or hashing in tight loops, `&str`/`impl Iterator` returns where they save callers a copy.
+ - **GPU** (only if WGSL / `src/runtime/gpu/` / residency / `gpu for|fn|let|var` is touched) — upload/readback byte counts vs buffer size, `GpuLaunchDesc` field widths in lockstep, dispatch grid vs the `SwitchInt` bounds guard, scalar-width portability and feature gating.
+ 5. **Mechanical-transform safety.** After any dedent, `sed`/`perl`, `git checkout`, mass import removal, or bulk rename: re-read the touched files and rebuild. Confirm no string literal was broken, no trailing code lost, and no load-bearing import removed (a removed import can break transitive resolution and redden unrelated tests). Scope mechanical edits narrowly to the exact symbol/type being changed — broad sweeps cause whack-a-mole regressions.
+ 6. **Adversarial self-QA.** Switch hats and try to break your own work. For each suspect path write a minimal `.mi` snippet you predict fails (empty collection, single element, nested generics, boundary index, overflow input, multiple moves, mixed residency). Run it. Audit your own tests for green-washing: an `assert_runs(...)` with no output/state assertion proves compilation not behavior; a test that was green before the feature existed proves nothing; a name describing implementation (`test_lower_call_intercept`) not behavior (`test_list_push_extends_length`) is a finding. Add the missing assertions/edge cases.
+ 7. **Run the gate yourself — report exact counts.** In order: `make format` (empty diff) → `make lint` (clean) → `make build` → `make test` (`cargo test --test mod`, capture exact pass/fail/ignored) → `make audit` (clean for touched files: unwrap/expect, stdlib-name leaks, `_ =>` over Miri enums, oversized functions, banners, comment rot). **Do not infer success — read the actual output.** If any earlier subagent or note called a failure "pre-existing" or "out of scope", re-run that test yourself before trusting it.
+ 8. **Loop tight.** Fix → re-run only what the fix touched (`make audit` + the affected tests always; full suite before declaring done). If the same root cause survives three attempts, stop and surface it to the user — don't churn.
+ 9. **Docs / plan.** If a module's core logic changed, update its local `README.md`. If scope came from a plan file, mark items done. Record out-of-scope discoveries as `notes/PLAN.md` follow-ups (and TODO comments with context at the code site) — never silently widen scope.
+ 10. **Final report** (format below).
## Final report format
```
- # Miri Task — CTO Report — <task>
+ # Miri Task — <task>
Status: DONE | NOT DONE (blockers open)
- Tier: Trivial | Standard | Major (trigger: <the §8.1 trigger, or "none">)
Scope delivered: <bullets>
- Gate: format <clean> | lint <clean> | build <clean> | test <was N → now M passing> | audit <clean>
-
- ## Design (Major tier only)
- <compiler-architect verdict + key decisions; GPU-architect input if any>
+ Gate: format <clean> | lint <clean> | build <clean> | test <was N → now M passing / K ignored> | audit <clean>
## Implementation
<diff summary + RED/GREEN/REFACTOR log per criterion>
- ## Validation
- # Major tier — panel roll-up:
- Lead Software Architect: <grades + headline>
- Lead Security Engineer: <headline + count, all fixed>
- Lead QA Engineer: <coverage verdict>
- Lead Rust Engineer: <headline + count>
- Lead Compiler Architect: <SOUND | SOUND-WITH-RISKS | UNSOUND>
- Lead GPU Engineer: <headline, or N/A>
- # Standard tier — miri-reviewer headline + count. Trivial — make audit + test result.
+ ## Self-review (lenses applied)
+ Design <ok/notes> · Visitors <ok> · Perceus <ok> · ABI <ok> · Bounds <ok> · Stdlib-indep <ok> · Arch/SOLID <ok> · Rust <ok> · GPU <ok/N/A>
- ## Consolidated findings & resolution
- 1. [severity] <finding> — fixed/deferred(reason)
- ...
+ ## Self-QA
+ <edge cases exercised + any green-washing fixed>
- ## Decisions for the user to review
- ## Follow-ups discovered but explicitly NOT done (recorded in notes/PLAN.md)
+ ## Follow-ups recorded but NOT done (in notes/PLAN.md)
```
## Hard rules
- - **Done only when the CTO concludes done.** Critical and major issues are never left undone; minor may be deferred only with explicit reason + recorded follow-up.
- - **Never** declare done with `make test` red or `make audit` reporting new violations in touched files.
- - **Classify the tier first (§8) and match review to it** — full panel for Major, `miri-reviewer` for Standard, neither for Trivial. Do not run the full panel on a Standard/Trivial change; do not skip it on a Major one. When unsure, pick the higher tier.
- - **Never** skip the TDD RED/GREEN/REFACTOR gate per criterion, regardless of tier.
- - **Never** skip the design pass on a **Major**-tier change, or `miri-audit` as its validation pass — that is where the full panel runs.
- - **Never** widen scope beyond what was confirmed — record discoveries as follow-ups instead.
- - Only the `lead-miri-engineer` edits source; architects, specialists, and you are read-only.
- - **Never commit, stage, push, or otherwise touch git.** No `git add`, `git commit`, `git push`, `git stash`, branch creation, or rebases — not by you and not by any subagent. Leave all changes in the working tree for the user to review and commit themselves. If a subagent is dispatched, instruct it explicitly not to run any git write commands.
- - Never hardcode stdlib type names in the compiler. Always `cargo test --test mod` — never `--test integration`.
+ - **Done only when format, lint, build, the full `cargo test --test mod` suite, and `make audit` are all green, and the self-QA pass leaves no open critical/major.** Run the gate yourself and report exact counts — never claim DONE on inference.
+ - **Never** skip the TDD RED/GREEN/REFACTOR gate per criterion.
+ - **Never** use `unwrap()`/`expect()`/`panic!` in library code — propagate via `Result<T, MiriError>`. Never `panic(...)` in `src/stdlib/**`.
+ - **Never** hardcode a stdlib type name in compiler dispatch. Always `cargo test --test mod` — never `--test integration`.
+ - **Never** widen scope beyond what was confirmed — record discoveries as follow-ups.
+ - **Never commit, stage, push, or touch git** (`git add`/`commit`/`push`/`stash`, branch creation, rebase). Leave all changes in the working tree for the user to review and commit.
+ - If the change trips a §8.1 Major-risk trigger and warrants independent review, recommend `miri-panel-task`.