diff options
| author | Adam Malczewski <[email protected]> | 2026-06-07 14:07:11 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-07 14:07:11 +0900 |
| commit | efddee1edd2924725a4dd240894666ede97b67b9 (patch) | |
| tree | 294bbedb837f6101a2eb9dc9d3fe4ae021d5cd69 | |
| parent | 2eed0f7ea0bf593cb99bc176d1421b09cfb1066f (diff) | |
| download | dispatch-efddee1edd2924725a4dd240894666ede97b67b9.tar.gz dispatch-efddee1edd2924725a4dd240894666ede97b67b9.zip | |
docs(harness): biome-clean rule + parallel-wave orchestration
- add .dispatch/rules/biome-clean.md (0 warnings/0 infos; no `!`/useLiteralKeys),
wired into the every-agent scoping map + canonical invocation
- package-agent: note biome zero-tolerance; verify line clarifies 0 warnings AND 0 infos
- ORCHESTRATOR: document parallel-execution waves (2a) + agent-failure recovery
patterns (5a) + concurrency caveats
| -rw-r--r-- | .dispatch/package-agent.md | 5 | ||||
| -rw-r--r-- | .dispatch/rules/biome-clean.md | 12 | ||||
| -rw-r--r-- | ORCHESTRATOR.md | 72 |
3 files changed, 82 insertions, 7 deletions
diff --git a/.dispatch/package-agent.md b/.dispatch/package-agent.md index 9a769d3..9af0485 100644 --- a/.dispatch/package-agent.md +++ b/.dispatch/package-agent.md @@ -55,6 +55,9 @@ The authoritative rules (`.dispatch/rules/*`, inlined into this prompt) govern. module wired between features. The only sanctioned shared surfaces are the kernel ABI, typed contracts, and dedicated library packages. - **Strict TS.** Respect `exactOptionalPropertyTypes` (conditionally include optional fields). +- **Biome is zero-tolerance** (`.dispatch/rules/biome-clean.md`, inlined). `bunx biome check` must + end with ZERO warnings AND ZERO infos — not merely zero errors. Fix the code; never + `// biome-ignore` or relax config. ## Verify before finishing — YOUR PACKAGE IN ISOLATION Other agents may be editing sibling packages in parallel, so never run the whole-graph build. @@ -63,7 +66,7 @@ Run, and paste the output into your report: - `bunx vitest run packages/<your-package>/src` → all pass (count must go up) - If your package uses `bun:sqlite`, use `bun test packages/<your-package>/src` instead (vitest can't load `bun:sqlite`). -- `bunx biome check packages/<your-package>` → clean +- `bunx biome check packages/<your-package>` → clean (0 warnings AND 0 infos) The orchestrator runs the authoritative full-graph `typecheck` / `test` / `check` itself. ## Report (REQUIRED) → `reports/<your-package>.md` diff --git a/.dispatch/rules/biome-clean.md b/.dispatch/rules/biome-clean.md new file mode 100644 index 0000000..4cd5e83 --- /dev/null +++ b/.dispatch/rules/biome-clean.md @@ -0,0 +1,12 @@ +# Rule: biome is zero-tolerance (0 warnings, 0 infos) + +`bunx biome check` must finish with ZERO warnings AND ZERO infos — not just zero errors. +"Clean" means there is no "Found N warnings" / "Found N infos" line at all. Fix the code; +NEVER add a `// biome-ignore` comment and NEVER relax the biome config to silence a finding. + +Two findings recur — pre-empt them: +- **No postfix non-null assertions (`value!`).** Narrow with an explicit guard + (`if (x === undefined) throw new Error(...)`) or a tiny `assertDefined` helper — this both + proves the intent and narrows the type. (Most common in tests.) +- **No `useLiteralKeys`.** Use dot access for identifier keys (`obj.foo`); reserve bracket + access for genuinely dotted / dynamic keys (`obj["a.b"]`). diff --git a/ORCHESTRATOR.md b/ORCHESTRATOR.md index a20dab9..620b983 100644 --- a/ORCHESTRATOR.md +++ b/ORCHESTRATOR.md @@ -39,8 +39,9 @@ they justify every rule below. ## 1. The golden workflow (build/modify a feature) -1. **Plan.** Decide the unit(s). Respect the dependency-topological order. One - agent owns one unit; it may ONLY edit its assigned files. +1. **Plan.** Decide the unit(s); split into dependency-topological **waves** of + disjoint units, and WIDEN each wave where you can (§2a). One agent owns one unit; + it may ONLY edit its assigned files. 2. **Overlap check FIRST (anti-synonym-drift, §5.6).** Before creating anything new, check `GLOSSARY.md` + existing code. If the request *describes* an existing concept under a new name, steer to the canonical term (e.g. @@ -51,8 +52,10 @@ they justify every rule below. existing one?" — surface it to the user; never decide granularity silently. 4. **Write the prompt** to `prompts/<unit>.md` (gitignored). See §3 for the prompt recipe. -5. **Summon the agent** via `opencode run` (see §2). Parallelize disjoint units. -6. **Verify** the report + independently re-run checks (see §4). Trust nothing +5. **Summon the wave** via `opencode run` (see §2); disjoint units run in PARALLEL + (§2a). RE-READ `.dispatch/rules/` + the §3 scoping map before each wave — assemble + from the files, not from memory. +6. **Verify** the reports + independently re-run checks (see §4). Trust nothing until you've re-run `typecheck`/`test`/`check` yourself. 7. **Resolve** any contract gaps / errors (see §5). 8. **Commit** the milestone with a clear message + test count. Update `tasks.md`. @@ -81,7 +84,7 @@ opencode run --dir /home/tradam/projects/dispatch/arch-rewrite \ -m opencode-go/mimo-v2.5-pro \ "$(cat .dispatch/package-agent.md) $(cat .dispatch/extension-agent.md) -$(cat .dispatch/rules/one-owner.md .dispatch/rules/isolation-over-dry.md .dispatch/rules/pure-core.md .dispatch/rules/no-internal-mocks.md .dispatch/rules/typed-handles.md) +$(cat .dispatch/rules/one-owner.md .dispatch/rules/isolation-over-dry.md .dispatch/rules/biome-clean.md .dispatch/rules/pure-core.md .dispatch/rules/no-internal-mocks.md .dispatch/rules/typed-handles.md) ## TASK $(cat prompts/<unit>.md)" \ @@ -132,6 +135,29 @@ log into context as a hard failure. --- +## 2a. Parallel execution — WAVES + +Throughput comes from running disjoint units at once. Organise it as waves: +- **A wave = units that (a) touch DISJOINT files and (b) have no compile-time dependency + on each other** (each imports only already-built packages + existing contracts). Launch a + wave by emitting one summon per unit as CONCURRENT tool calls (§2). Later waves depend on + earlier ones; the composition root (`packages/host-bin/`) is almost always the LAST wave. +- **Pre-author the seam to widen the wave.** Because the orchestrator OWNS contracts (§6), + author the shared contract / typed handle in `packages/kernel/src/contracts/*` FIRST, then + summon the producer AND the consumer in the SAME wave against that fixed type — neither needs + the other's implementation. Authoring the contract up front is what turns a sequential + producer→consumer chain into one parallel wave (and `lsp references` on the new symbol gives + the exact consumer set to summon). +- **Also widen by removing edges:** prefer a consumer-defined handle the producer implements, + or a generic utility over a feature-specific one, so a dependency disappears entirely. +- **One writer per file, always** — even across waves. If two units would edit the same file, + they are NOT separable; merge them into one unit or sequence them. +- **After a wave:** read every report, run the §4 checks ONCE for the whole wave, commit the + milestone (update `tasks.md`), then start the next wave. Don't open a new wave before the + prior one is green. + +--- + ## 3. The per-summon `prompts/<unit>.md` is JUST the TASK block The invariant guardrails — single-writer directory ownership, visibility, coupling, the @@ -152,7 +178,7 @@ Keep it scoped (P6): state only the project-specific, non-inferable task — the **`.dispatch/rules/` scoping map** — include ONLY the rows matching the unit (per §0 "scoped rules beat general rules"); do NOT dump every rule on every agent: -- **Every agent:** `one-owner.md`, `isolation-over-dry.md`. +- **Every agent:** `one-owner.md`, `isolation-over-dry.md`, `biome-clean.md`. - **Kernel unit:** `kernel-purity.md` + `pure-core.md` + `no-internal-mocks.md`. - **Pure-core unit:** `pure-core.md` + `no-internal-mocks.md`. - **Any extension coupling via hooks/services:** `typed-handles.md`. @@ -165,6 +191,14 @@ Keep it scoped (P6): state only the project-specific, non-inferable task — the OWN harness (`package-agent.md` + `frontend-*.md` rules) + ITS OWN scoping map — NOT these backend rules. See that repo's `ORCHESTRATOR.md`. +**Tell each agent it has company (parallel waves).** Add to each wave TASK: sibling units are +being built in OTHER packages right now; `tsc -b`/vitest/biome are whole-PROJECT, so if a check +reports errors OUTSIDE your package, that's concurrent WIP — ignore it and ensure YOUR files are +clean. The orchestrator's post-wave run (§4) is the source of truth. + +**Make agents IMPLEMENT, not deliberate.** A summoned owner must edit files + run its checks + +write its report in the one run. If a summon returns only a plan, re-summon (§5a). + --- ## 4. Verification (the orchestrator's trust protocol) @@ -200,6 +234,12 @@ git status --short # confirm the agent stayed in its lane (no out-of-scope edit - Confirm the agent touched ONLY its assigned files (one-owner rule). - For pure units, confirm tests use NO internal `vi.mock("@dispatch/*")`. +**Concurrency caveat (parallel waves):** `tsc -b`/vitest/biome are whole-project, so an agent's +OWN mid-wave check can transiently see a sibling's half-written file. Don't act on a report's +out-of-package errors; YOUR post-wave run is authoritative. Re-run a suite that depends on shared +external state before trusting it — and ALWAYS sweep leaked server/collector processes between +live runs (§8 bracket trick), since a leak silently poisons the next run's counts. + --- ## 5. Resolving errors & contract changes @@ -225,6 +265,26 @@ git status --short # confirm the agent stayed in its lane (no out-of-scope edit --- +## 5a. Agent-failure recovery patterns + +- **Plan-only / "shall I proceed?" agent.** A summon sometimes returns a PLAN and STOPS without + editing (no diff, no `reports/<unit>.md`). Detect via `git status` + the missing report. + Re-summon the SAME TASK prefixed: "IMPLEMENT THIS NOW — make all edits, run the checks, write + the report; do not stop to plan or ask." Don't hand-fix its work. +- **A behaviour change reds a SIBLING's tests (test fan-out).** When a unit's new behaviour + invalidates another unit's test ASSERTIONS, those tests belong to that OTHER owner — summon it + with a focused "fix these N failing tests to match the new behaviour" TASK (state the + behaviour). The orchestrator never edits feature tests itself. (Distinct from an INTEGRATION + bug where neither side is wrong — that's the temporary multi-knowledge agent in §5.) +- **Agent strayed out of its lane.** `git status --short` after every wave; if an agent touched a + file outside its package, keep it ONLY if it's legitimately the orchestrator's lane + (contracts / build / config / harness, §6) and note it — otherwise revert + re-summon with a + tighter scope. +- **Flaky green.** A wave that passes once but leaked a server/collector or relies on shared + external state can pass for the wrong reason; sweep (§8) and re-run before committing. + +--- + ## 6. Restrictions & invariants (NEVER violate) - **Single-writer:** never let two agents edit the same file concurrently. |
