Type /wavves at the start of a task. It routes to the right leaf skill,
like /poteto-mode in pstack.
| Piece | Where | Role |
|---|---|---|
| Moderator (O0) | operator-facing thread | charters, dispatches, reconciles |
| Home | wavves/ |
hydration contract across rotations |
| Lane | wavves/lanes/<date>_<label>/ |
one bounded workstream |
| Charter | lanes/.../waveset.md |
scope, locks, waves, gates |
| Dispatch | lanes/.../dispatch-w{N}.md |
per-wave paste block for background runners |
| Registry | wavves/registry.yml |
every lane and its status (active_dispatch, conflicts_with, …) |
| Rotation | wavves/rotations/ |
handoffs with term identity |
| Gates | lanes/.../gate-captures/ |
runnable evidence (JSON + log) |
| skill | use it when |
|---|---|
/wavves |
default entry. routes by playbook |
/wavves-init |
home setup only |
/charter |
charter a lane only |
/mod-check |
adversarial sanity-check of a landed spec or plan |
/mod-decide |
lock open product/design calls after a check return |
/layover |
workspace preflight audit (cloud stays per-repo) |
/set-key |
Terminal.app paste helper for a server-only env secret |
/shrug |
alias for emoji shrug; bare → AUTH-10 proceed; with closed all-standing phrase → proceed-all-standing |
/mod-rotate |
rotation only |
/mod-kick |
cross-environment kick exit (publish + paste); not rotate |
| playbook | leaf skill | for |
|---|---|---|
| bootstrap | /wavves-init |
first time, repair home |
| charter-lane | /charter |
bug fix, audit, refactor, flaky CI, overnight lane |
| check | /mod-check |
adversarial review of a landed spec or plan before build |
| decide | /mod-decide |
lock open calls before BUILD charter |
| layover | /layover |
preflight multi-repo workspace (audit; cloud stays per-repo) |
| set-key | /set-key |
Terminal.app paste helper for a server-only env secret |
| paragraph-tunnel | dispatch STEPS | mid-render structural gate for outbound paragraph |
| proof-before-accept | dispatch STEPS | named proof job before ACCEPT |
| rotate | /mod-rotate |
hand off to fresh thread (same O0 family) |
| kick | /mod-kick |
hand to another environment / machine / readback elsewhere |
| pickup | hydrate | resume from rotation paste; same-turn yield vs return_to_O0 remeasure (rotate-hydrate only) |
| proceed | hydrate + execute | proceed as recommended, /wavves proceed; all-standing on closed phrases only; bare /shrug stays AUTH-10 |
default: /wavves set up in this repo, then audit our README for drift.
read-only, no commits.
spec check: /mod-check review docs/superpowers/specs/2026-07-08-example.md
before we write the implementation plan. adversarial parallel
wave. read-only. landing_commit_hash <hash>.
decide: /mod-decide navigate open calls from the check return.
one decision at a time. write decisions/*.md. no BUILD yet.
layover: /layover audit ~/my.code-workspace. read-only.
rotate: /wavves rotate this thread. write a handoff for active lanes.
kick: /wavves kick this stream to another environment. ask kick target.
pickup: /wavves hydrate from the rotation paste and tell me what's active.
proceed: /wavves proceed as recommended after mod-check or mod-decide return.
all-standing: /wavves proceed all standing
(or: all still standing / queue all standing and move)
shrug: /shrug
(bare → AUTH-10 proceed; add a closed all-standing phrase to widen)
setup only: /wavves-init set up wavves in this repo. do not commit.
charter only: /charter migrate every callsite to the async config store.
check only: /mod-check the landed spec. GO / REVISE / BLOCK with named gaps.
decide only: /mod-decide lock the open calls. emit Locked decisions paste.
set-key only: /set-key open Terminal.app paste helper for a server-only
env secret. never put the secret in chat.
rotate only: /mod-rotate token velocity is too high. give me the one-line paste.
kick only: /mod-kick publish allowlist and give me the paste for another environment.
When work starts as a written spec, do not jump straight to /charter. Use
three skills in order. The moderator (O0) stays operator-facing the whole way.
spec landed
→ /mod-check adversarial parallel wave → GO | REVISE | BLOCK
→ /mod-decide lock open product/design calls → decisions/*.md
→ /charter BUILD with Locked decisions pasted into waveset.md
| Step | Skill | You get | Stop if |
|---|---|---|---|
| 1. Check | /mod-check |
verdict + named gaps + settled technical findings | BLOCK or REVISE until the artifact is fixed |
| 2. Decide | /mod-decide |
one-at-a-time picks, decisions/*.md, Locked decisions paste |
any fork a build agent would have to invent is still open |
| 3. Charter | /charter |
BUILD lane, waves, gated acceptance | locks missing or two disjoint features stuffed into one lane |
After mod-decide, O0 syncs locks to waveset.md, active dispatch-w{N}.md,
and registry.yml before W2 dispatch. Each dispatch carries an authority
precedence block (locks → waveset → findings marked STALE).
Mod-check verdicts may include scoped blockers:
verdict: REVISE
blocks_w2: false
blocks_w4: true
recommended_actions:
- action: commit
files: [wavves/lanes/...]
- action: dispatch
wave: w2
- action: operator_gate
id: approve-quarantine-manifestUse /wavves proceed to execute recommended_actions in order. Closed
all-standing phrases route to proceed-all-standing. Bare shrug or bare
/shrug stays AUTH-10 proceed only.
What belongs in decide vs what is already locked grounding
- Decide (product / design forks): gesture choice, which data source is authoritative, v1 share scope, whether to replace a shipped behavior.
- Grounding (already verified; do not rediscover): measured facts from the check (e.g. point-in-polygon renders nothing; Vercel body cap rules out a naive server route). Confirm them into the Locked / Grounding paste; do not re-debate them unless new evidence appears.
Practical paste after a check return
/mod-decide You are O0. Do not charter BUILD yet.
Check landed at <hash>. Navigate the open product decisions listed in the
return. One decision at a time: options in one line each, wait for my pick,
write decisions/<CODE>-<slug>.md, append to a Locked decisions draft.
Do not reopen settled technical findings. When I say locks are complete,
emit the Locked decisions paste and the /charter invocation(s). One feature
per BUILD lane when scopes are disjoint.
Practical paste once locks exist
/charter BUILD lane for <feature>.
repo_state_verified_against: <check landing hash>
type: execution
Locked decisions (do NOT reopen):
<paste from /mod-decide>
Grounding (already verified; do not rediscover):
<paste from /mod-decide>
Wave shape: discovery → build → gated integration → gated acceptance.
No commits/deploy without my ask. Escalate any lock conflict to O0.
Anti-patterns
| Temptation | Why not |
|---|---|
/charter while forks are still open |
build agents pick for you and fight the check |
/mod-check again to "make the decisions" |
check reviews; decide locks |
| One mega-charter for two disjoint features | file ownership and risk diverge; split lanes |
| Asking Mod to "just start building" mid-decide | O0's job is lock first, dispatch second |
The walkthroughs below go deeper on other mechanics. For the check → decide → BUILD path, the section above is the guide.
- A. Feature build with real parallelism
- B. Flaky test stabilization with proof
- C. Performance sprint with before/after numbers
- D. A migration that outlives one chat session
Shows: file-ownership discipline, why two waves can run in parallel safely and why a third wave (integration) has to be serialized.
/wavves add a CSV export button to the reports page. build the endpoint and the
button in parallel, keep them disjoint. gate on a real downloaded file that
matches the table.
/wavves reads wavves/ (exists already), matches charter-lane, reads
/charter in full, then charters lane EXP at
wavves/lanes/20260708_reports-csv-export/.
Wave 1, discovery (fast model, read-only). Two subagents in parallel:
EXP-W1areads the reports page, the table's data source and any existing export patterns elsewhere in the codebase. Writesfindings/EXP-reports-page.md.EXP-W1b(the adversarial member) hunts for gotchas: the table only renders page 1 while the export needs every row, the API route needs the same auth check as the page, a CSV library is already a dependency so nothing new to install. Writesfindings/EXP-risks.md.
Wave 2, build (balanced model, disjoint new files, parallel).
EXP-W2aowns a new file, the export API route, streaming CSV from the same query the table already uses (so the export can't drift from what the user sees).EXP-W2bowns a new file, the export button component, plus a short wiring note on how it mounts.
Neither subagent touches the reports page file itself. That's the whole point of the split: two new files with zero overlap can run in parallel with no collision risk. If both agents needed to edit the same file (say, both patching the reports page directly), that would not be a safe parallel wave. It would be one serialized editor instead, which is exactly what wave 3 is for.
Wave 3, integration (single serialized editor, GATED on O0 approval). One agent, no parallelism, mounts the new button into the reports page and wires the new route into the router config. This is the only wave allowed to touch that shared file.
Wave 4, acceptance (GATED, high-reasoning, no authorship of the build). Downloads the CSV from the real running app, not a mock, then diffs it row-by-row against the table's live data. Capture:
{
"gate": "EXP-ACCEPT",
"pass_metric": "csv_row_count == table_row_count AND mismatched_rows == 0",
"measured": {
"table_row_count": 248,
"csv_row_count": 248,
"mismatched_rows": 0,
"download_latency_ms": 812
},
"verdict": "PASS",
"command": "node scripts/verify-csv-export.js --url http://localhost:3000/reports"
}Registry entry after reconciliation:
EXP:
label: reports-csv-export
home: wavves/lanes/20260708_reports-csv-export/
waves: [EXP-W1a, EXP-W1b, EXP-W2a, EXP-W2b, EXP-INT, EXP-ACCEPT]
status: completed
note: >
CSV export on reports page. Backend route and button built as disjoint
new files in parallel. Integration wired the single mount point.
Acceptance verified a real download against 248 live rows, 0 mismatches.Shows: gates measure before and after with the same harness, so "looks stable now" is never the verdict. A failed gate is reported as failed, not softened.
/wavves three tests in checkout.spec.ts flake on main, maybe 1 in 5 runs.
charter a lane to characterize them, fix root causes and prove stability,
not just "looks fixed".
Lane FLK at wavves/lanes/20260708_checkout-flakes/.
Wave 1, discovery (fast model). Before touching anything, rerun each named test 20 times in isolation to get a real baseline, not an impression:
test runs failures rate
checkout > applies discount 20 4 20%
checkout > handles retry 20 6 30%
checkout > final total 20 1 5%
Root cause traced in findings/FLK-baseline.md: a shared test helper races a
debounced UI update on a setTimeout. The retry test additionally leaks
mock state left over from the discount test.
Wave 2, build (balanced model, disjoint files, parallel). One subagent fixes the timing race in the shared helper. A second isolates the mock leak inside the retry test's own file. Different files, so they run in parallel. If the fix for both bugs lived in the same helper file, this would collapse to one subagent, not two racing to edit the same file.
Wave 3, acceptance (GATED, high-reasoning, no authorship of the fix). Reruns the exact same 20x-per-test harness used for the baseline, so the before/after comparison is apples-to-apples:
{
"gate": "FLK-ACCEPT",
"pass_metric": "failure_rate == 0 across 20 runs per test",
"baseline": {"applies_discount": "4/20", "handles_retry": "6/20", "final_total": "1/20"},
"measured": {"applies_discount": "0/20", "handles_retry": "0/20", "final_total": "0/20"},
"verdict": "PASS",
"command": "npx jest checkout.spec.ts --testNamePattern='applies discount|handles retry|final total' --repeat 20"
}If the rerun had come back 2/20 where 0/20 was required, the verdict is FAIL with the named test. The wave repeats once against the charter's remediation-loop cap (default 2) before escalating to the operator. It does not quietly call the result "mostly fixed."
Shows: model routing with a real cost rationale plus a trace harness reused unchanged for baseline and acceptance so the improvement number is trustworthy.
/wavves the /dashboard route takes about 4 seconds to load. charter a lane to
find the real bottlenecks and fix them, with before/after numbers.
Lane PERF at wavves/lanes/20260708_dashboard-load/.
Wave 1, discovery (fast model, profiling). One subagent captures a
cold-load trace and finds three independent bottlenecks in
findings/PERF-trace.md:
getWidgetsForUser()issues 47 sequential queries (N+1).- The hero image is a 2.1MB PNG with no responsive sizes.
- The full charting library ships in the main bundle even though only 2 of its 12 chart types are used.
Baseline captured once, as measured numbers, not three separate impressions:
{"p95_load_ms": 4180, "main_bundle_kb": 1840, "db_query_count": 52}Wave 2, build (balanced model, three disjoint fixes, parallel). Each subagent owns one unrelated file: the query batching fix, the image pipeline, the chart bundle split. Independent files, so all three run at once.
Wave 3, acceptance (GATED, high-reasoning). Reruns the identical trace tool used for the baseline, not a different one:
{
"gate": "PERF-ACCEPT",
"pass_metric": "p95_load_ms < 2000",
"baseline": {"p95_load_ms": 4180, "main_bundle_kb": 1840, "db_query_count": 52},
"measured": {"p95_load_ms": 1340, "main_bundle_kb": 620, "db_query_count": 3},
"verdict": "PASS",
"command": "node scripts/trace-dashboard.js --runs 10 --url http://localhost:3000/dashboard"
}Model routing for this lane, from waveset.md:
role model tier reason
discovery (trace) fast read one trace, categorize bottlenecks
build (3x) balanced bounded, disjoint fixes, local validation
acceptance gate high-reasoning judges whether 3 fixes together clear the bar
The discovery and build roles don't need an expensive model to read a trace or apply a scoped fix. Judging whether the combined result clears the bar, on the other hand, is exactly the kind of call reserved for the high-reasoning tier.
Shows: the standing home and rotation file are the real state-transfer mechanism, not a chat summary. A successor verifies claims before trusting them.
/wavves migrate every caller from the sync ConfigStore to the async
ConfigStoreAsync. behavior must stay identical. this will take a while.
Lane MIG at wavves/lanes/20260708_config-async/.
Wave 1, discovery (fast model). Finds all 34 call sites across 12 files,
listed with file:line in findings/MIG-callsites.md.
Wave 2, build (balanced model, four disjoint file groups, parallel). The 34 callsites split into 4 non-overlapping file groups, one subagent per group, each migrating its group and ending typecheck-clean.
Partway through wave 2, the operator's thread has been running long enough that context is heavy:
/wavves rotate this thread. write a handoff for active lanes.
/mod-rotate writes rotations/rotation-r01-20260708-1940.md. Section 0
assigns the successor identity first, O0.R2, never self-chosen. The file
records:
- Positions landed so far (none yet committed, per the runner git ban and no operator commit ask).
- Active dispatches:
MIG-W2aandMIG-W2breturned (two file groups migrated, typecheck clean);MIG-W2candMIG-W2dstill running, with the pickup action "check status; if dead, re-dispatch against the same file group, do not reassign to a sibling." - Uncommitted local state: two migrated files sitting in the working tree.
- The one-line paste:
/wavves hydrate as O0.R2 from <repo>/wavves/INDEX.md (current rotation:
rotations/rotation-r01-20260708-1940.md) and ack per the rotation contract,
stating your assigned identity, before acting.
The operator pastes that into a fresh chat. The new thread:
- Reads
wavves/INDEX.md, finds the newest rotation file, acks: "I am O0.R2, hydrated from rotation-r01-20260708-1940.md." - Verifies the claimed positions before trusting them: opens the two "migrated" files and confirms they match what the rotation file claimed. A discrepancy here becomes a recorded gap, not a silently executed pickup.
- Checks on
MIG-W2candMIG-W2d. One finished while the rotation file was being written, a normal race; O0.R2 reconciles that return and keeps waiting on the other without double-dispatching it. - Once wave 2 fully lands, O0.R2 runs wave 3 (integration, gated) and wave 4 (acceptance: the full test suite, same command as the pre-migration run, same pass/fail count expected).
Nothing about picking up this lane required re-reading the original chat. Every fact the successor needed to act correctly was already on disk.
wavves/
INDEX.md
AGENTS.md
registry.yml
step-log.md
rotations/
rotation-r01-YYYYMMDD-HHMM.md
lanes/
20260708_reports-csv-export/
README.md
waveset.md
dispatch.md
findings/
gate-captures/
decisions/
20260708_checkout-flakes/
...
20260708_dashboard-load/
...
20260708_config-async/
...
Inspect a gate by opening the JSON under gate-captures/, reading the paired
log and checking the verdict in findings/. A chat summary is not a gate
capture; if the JSON is missing or hand-authored, the gate is not accepted.