| name | fwd:steps-run |
| description | Voer een stappenplan van /fwd:steps-plan uit — attended, precies één stap per beurt. Per stap; falende test eerst (rood), minimale implementatie langs de Lazy Ladder (groen), volledige gate, vers oordeel door een read-only reviewer-subagent, en een stap-rapport van ±15 regels met "Stap N/M"-teller — daarna stopt de beurt en beslist de gebruiker (ok = commit & door, auto = autonoom afmaken, m = meer detail, stop = pauze, vrije tekst = correctie/vraag/planwijziging). Elke 4 goedgekeurde stappen een tussenbalans door twee doubt-subagents. Use when the user runs /fwd:steps-run <slug>, zegt "volgende stap", "ga door met het stappenplan", of "hervat <slug>". Zonder argument: lijst alle stappenplannen. Niet voor onbeheerd werk — dat is fwd:mission-run. |
fwd:steps-run
Eén stap per beurt, bewijs vóór uitleg, commit pas na akkoord. Jij (de hoofdsessie) schrijft de code zélf — er is geen coder-subagent, zodat de uitleg uit eerste hand komt. Het onafhankelijke oordeel komt per stap van fwd-skills:fwd-steps-reviewer (read-only, verse context); de tussenbalans elke 4 stappen van fwd-skills:fwd-steps-doubt.
Werken in een worktree. Het werk gebeurt in een eigen worktree op .trees/steps/<slug>/ — dezelfde isolatie als missions, maar jij schrijft de code nog steeds zelf. setup-worktree.sh (stap 0) zet je hoofd-checkout terug op de base-branch (meteen vrij voor parallel werk) en materialiseert de worktree. Vanaf dat moment is het geprinte pad <WT> je werkmap: lezen/schrijven in <WT>/…, gate-commando's met cd "<WT>" && …, en <WT> als repo-root aan elke subagent.
Attended-principe. De gebruiker zit erbij en beslist op elk gate-moment.
- Nooit voorbij het gate-moment bouwen. Na het stap-rapport stopt de beurt — geen "alvast beginnen" aan de volgende stap.
- Geen
AskUserQuestion op gates. Het gate-protocol is plain text (ok / m / stop / vrije tekst).
- Nooit pushen, nooit PRs openen. Committen op de plan-branch gebeurt alleen via
record-step.sh, na akkoord.
- Nooit groen faken. Een test verzwakken, een assert verwijderen of een gate omzeilen om "door te komen" is uitgesloten — vastlopen wordt eerlijk gerapporteerd.
De bash / Claude / subagent-splitsing:
- Bash-scripts — deterministische state, git, exit codes. Draai ze; vertrouw hun uitvoer.
- Jij — code schrijven, tests schrijven, uitleggen, wegen wat de reviewer vindt.
- Subagents — het onafhankelijke oordeel. Jij vult het "Review (vers)"-blok nooit zelf in; zonder reviewer-run geen stap-rapport.
Status (sessiestart)
!bash "${CLAUDE_SKILL_DIR}/scripts/status.sh" "$ARGUMENTS"
Flow
Zonder slug — presenteer de lijst hierboven als nette tabel (slug, voortgang, branch, worktree, titel) en stop. De gebruiker kiest.
Met slug — interpreteer de status-injectie hierboven:
0. Worktree opzetten + preflight
Eerst de worktree. Materialiseer (of hervat) de worktree en verhuis het werk erheen:
WT="$(bash "${CLAUDE_SKILL_DIR}/scripts/setup-worktree.sh" <slug>)"
Zet de hoofd-checkout terug op de base-branch (meteen vrij voor parallel werk), maakt/hergebruikt .trees/steps/<slug>/, kopieert ongetrackte gitignore'de .env* mee en print het absolute pad. Vanaf nu is <WT> je werkmap: lezen/schrijven in <WT>/…, gate-commando's met cd "<WT>" && …, en <WT> als repo-root aan elke subagent. Faalt het script:
| Signaal | Actie |
|---|
no-plan | Nog geen steps/<slug>-branch → eerst /fwd:steps-plan. Stop. |
dirty-main | De hoofd-checkout staat op steps/<slug> met ongecommitte wijzigingen die het script niet veilig kan verplaatsen. Meld het exacte commando en stop; de gebruiker commit/stasht zelf. |
Dan de preflight (uit de statusregels hierboven; her-draai gerust status.sh <slug> nu de worktree bestaat voor een verse dirty_tree/next_*):
| Signaal | Actie |
|---|
corrupt-state (exit 3) | Meld het; toon het pad. Stop — niet zelf repareren zonder de gebruiker. |
pending_autonomous_commit=yes | Een autonome run brak af met opgestapeld, ongecommit werk. Zie Hervatten van een onderbroken autonome run hieronder. |
dirty_tree=yes (en pending_autonomous_commit=no) | Zie Hervatten met een klaarstaande stap hieronder. |
status=done | Alles is af — verwijs naar het eindrapport / de merge-keuze en stop. |
next=none | Alle stappen done/skipped maar status niet done → draai het eindrapport (stap 9). |
Hervatten met een klaarstaande stap. Een vuile worktree met pending_autonomous_commit=no hoort bij één scenario: een eerdere sessie bouwde de eerstvolgende todo-stap in de worktree en stopte vóór het akkoord. Check of de dirty_files bij die stap passen. Zo ja: her-draai de gate (cd "<WT>") én de reviewer (de tree kan intussen aangeraakt zijn) en toon het stap-rapport opnieuw, gemarkeerd met "(stond al klaar)". Zo nee: meld eerlijk wat er ligt, geef opties (wegcommitten buiten het plan om / stashen / inspecteren) en stop.
Hervatten van een onderbroken autonome run. Meldt status.sh pending_autonomous_commit=yes, dan ligt er opgestapeld, ongecommit werk van een autonome run (auto) die naar attended brak. De done-maar-ongecommitte stappen staan al op done in state.json (via --no-commit) — herbouw ze nooit. Bied twee wegen: afronden → draai meteen de autonome eindreview (sectie 9a) over het opgestapelde werk; na ok landt het als één commit via finalize-autonomous.sh. Doorgaan → hervat de autonome loop (sectie 6a) vanaf de eerstvolgende todo-stap. Break-out-finalize-guard: committeer dit opgestapelde werk nooit via het gewone attended record-step.sh van een losse stap — dat doet git add -A en zou álle opgestapelde stappen in één stap-commit vegen met de verkeerde message. Vóór een attended ok op een nieuwe stap moet het opgestapelde autonome werk eerst gefinaliseerd zijn.
1. Brief
Lees uit <WT>/.claude/steps/<slug>/: plan.md (DoD, eindbeeld, seams) en de stap uit de status-injectie (next_*). Lees élk rule-bestand uit next_rules vóór je één regel code schrijft — regels zijn bindend en vuren niet vanzelf bij nieuwe bestanden.
2. Rood
Schrijf de falende test(s) voor het gedrag van deze stap — 1-3 tests, uitsluitend op de in plan.md afgesproken seams. Draai ze gericht; leg de letterlijke falende uitvoer vast voor het rapport. Testkwaliteit:
- Verwachte waarden komen uit een onafhankelijke bron (de spec, het eindbeeld, een uitgewerkt voorbeeld) — nooit narekenen zoals de productiecode het doet (schijntest).
- Publieke interface, geen interne details — de test overleeft een refactor.
- Alleen de tests van déze stap — geen tests vooruit schrijven voor latere stappen.
Bij next_criterion_type=command (vooraf zo gemarkeerd in het plan): sla rood over en noteer dat in het rapport; het bewijs is straks het commando met zijn verwachte resultaat.
3. Groen — de ponytail-discipline
Éérst begrijpen, dan pas lui zijn: lees alles wat de stap raakt en trace de echte flow. Klim daarna de Lazy Ladder en stop bij de eerste trede die houdt:
- Moet dit bestaan? Speculatieve behoefte → schrappen, meld het in één regel (YAGNI).
- Bestaat het al in deze codebase? Een helper, util, type of patroon een paar bestanden verderop → hergebruiken. Herimplementeren wat er al ligt is de meest voorkomende slop.
- Doet de stdlib het? Gebruik hem.
- Dekt een native platformfeature het?
<input type="date"> boven een picker-library, CSS boven JS, DB-constraint boven app-code.
- Lost een al-geïnstalleerde dependency het op? Gebruik die. Nooit een nieuwe toevoegen voor wat een paar regels kan.
- Kan het in één regel? Eén regel.
- Pas dan: het minimum dat werkt.
Regels bij het klimmen:
- Bugfix = oorzaak, niet symptoom. Grep élke aanroeper van de functie die je gaat aanraken. De luie fix ís de oorzaak-fix: één guard in de gedeelde functie is een kleinere diff dan een guard in elke aanroeper.
- Geen ongevraagde abstracties: geen interface met één implementatie, geen factory voor één product, geen config voor een waarde die nooit verandert. Geen scaffolding "voor later" — later kan zijn eigen scaffolding bouwen.
- Saai boven slim. Slim is wat iemand om 3 uur 's nachts moet ontcijferen. Weghalen boven toevoegen. Zo min mogelijk bestanden; de kortste wérkende diff wint — maar de kleinste wijziging op de verkeerde plek is geen luiheid, dat is een tweede bug.
- Twee stdlib-opties, even groot? Pak de op edge-cases correcte. Lui = minder code schrijven, niet het wankelere algoritme kiezen.
- Bewuste versimpeling → comment mét plafond en upgrade-pad, op de plek zelf en zelfstandig leesbaar, bijv.
# bewust: globale lock — per-account locks zodra doorvoer knelt. Registreer hem straks óók als deferral bij het akkoord ({"note": …, "when": …}).
- Safety floor — nooit wegversimpelen: inputvalidatie op trust boundaries, error handling die dataverlies voorkomt, security, accessibility-basics, en alles wat de gebruiker expliciet vroeg.
- Comments en commit message zelfstandig leesbaar: leg wat/waarom uit in gewone taal; nooit stap-nummers, de slug of plan-verwijzingen in code, comments, docstrings of commit messages.
Draai daarna de volledige gate in de worktree (cd "<WT>" && <gate=> uit de injectie) tot alles groen is — niet alleen de nieuwe tests; de gate is de regressiedetectie.
4. Vers oordeel
Spawn de reviewer via de Agent tool, subagent_type: fwd-skills:fwd-steps-reviewer. De prompt bevat alleen: het worktree-pad <WT> (dáár staat de code, dat is z'n repo-root), de stap-titel + het gedrag, het klaar-criterium, het gate-commando en de rule-paden. Niet de diff, niet je code, niet je redenering — de reviewer trekt alles zelf op (rtk git diff); dat bespaart tokens en voorkomt doorvertel-bias.
Verwerk het JSON-verdict:
gate.passed=false → terug naar stap 3; fix, en daarna de reviewer opnieuw.
test_quality of een rule passed=false → fixen vóór het rapport (dit zijn geen meningen) — tenzij het oordeel aantoonbaar onjuist is; dan gemotiveerd als open punt in het rapport.
- Over-engineering-vondsten waar je het mee eens bent → direct toepassen, gate opnieuw, in het rapport als "toegepast".
- Vondsten waar je het niet mee eens bent → open in het rapport, met één regel waarom niet.
5. Stap-rapport → stop de beurt
Render exact dit sjabloon (±15 regels, Nederlands, technische termen Engels, geen code-snippets — die zitten achter m):
── Stap <N>/<M> — <titel> ──────────────────────────────
Wat kan er nu: <het gedrag in 1-2 zinnen gewone taal>
Waarom zo: <kernkeuze(s); benoem hergebruik; indien van toepassing:
"bewust simpel gehouden: <wat> — uitbreiden zodra <wanneer>">
Bewijs: rood ✗ <letterlijke falende testregel van vóór de implementatie>
groen ✓ <n> nieuwe test(s); gate <X/X> groen (reviewer herdraaide hem)
Review (vers): rules <✓ | ✗: wat> · over-engineering: <geen | <n> vondsten, toegepast/open>
<de narrative-zin van de reviewer>
Bestanden: <pad> (+<regels>) · <pad> (+<regels>)
Zelf zien: <één copy-paste commando>
Volgende: stap <N+1>/<M> — <titel> (of: dit was de laatste stap)
── ok = commit & door · auto = autonoom afmaken · m = meer detail · stop = pauze · of typ correctie/vraag ──
Stop hier. De volgende beurt is aan de gebruiker.
6. Gate-protocol (de reactie van de gebruiker)
-
ok / y — commit en door (in de worktree — record-step.sh commit met git add -A op de plan-branch):
echo '{"deferrals":[…]}' | ( cd "<WT>" && bash "${CLAUDE_SKILL_DIR}/scripts/record-step.sh" <slug> <step-id> "<conventional message>" )
De message beschrijft het gedrag (feat(auth): wachtwoord-reset e-mail met 1u-expiry) — zonder stap-codes. Lees de uitvoer:
interim_review=due → draai de tussenbalans (volgende sectie) en stop de beurt.
status=done → draai het eindrapport (sectie 9) in deze beurt.
- anders → begin de volgende stap (terug naar stap 1) en eindig bij háár rapport.
-
auto / autonoom (geldig overal waar ok mag) — rond de resterende stappen autonoom af: geen stop per stap, maar wél per stap dezelfde rood → groen → volledige gate → verse reviewer, en de doubt-tussenbalans elke 4. Er wordt niets gecommit tot de eindreview aan het eind. De loop, de break-out-condities en het commit-gate staan in Autonome modus hieronder.
-
m (more) — uitgebreide uitleg van dezelfde stap: per bestand de kernwijziging mét snippet, de volledige reviewer-bevindingen, overwogen alternatieven en waarom het deze vorm werd. Sluit weer af met de gate-voetregel; niet committen.
-
stop — niets committen. Meld: het werk van de klaarstaande stap staat in de working tree; hervatten kan altijd met /fwd:steps-run <slug> (de stap wordt dan her-geverifieerd en opnieuw gepresenteerd).
-
Vrije tekst — classificeer:
- Correctie → toepassen, gate én reviewer opnieuw, kort delta-rapport (alleen wat veranderde + vers oordeel), opnieuw wachten.
- Vraag → beantwoorden zonder iets te wijzigen; meld dat de stap nog klaarstaat voor
ok.
- Planwijziging ("voeg een stap toe", "schrap S12", "splits S9") → werk
plan.md + state.json bij; de teller herrekent zichzelf (afgeleid uit de statussen). Ligt er geen onafgeronde stap-code in de tree → commit de planwijziging direct (chore(steps): plan bijgesteld — <wat>); anders gaat hij mee met de eerstvolgende ok-commit. Meld de nieuwe telling expliciet.
6a. Autonome modus (auto)
Antwoordt de gebruiker auto (of autonoom) op een gate, dan maak je de resterende stappen af zónder de beurt per stap te stoppen. Elke stap krijgt exact dezelfde rigor als attended — brief, rood, groen, volledige gate én het verse oordeel — alleen stopt de beurt niet bij het stap-rapport en wordt er niets op de branch gecommit tot de eindreview. Het werk stapelt ongecommit op in de worktree.
De loop, per resterende stap:
- Snapshot vóór.
SNAP_VOOR="$( cd "<WT>" && bash "${CLAUDE_SKILL_DIR}/scripts/snapshot-worktree.sh" <slug> )" — legt de huidige (opgestapelde) worktree vast als isolatie-ref, zonder iets te muteren.
- Bouw de stap — brief, rood, groen, en de volledige gate in de worktree — precies als de attended stappen 1–3.
- Snapshot ná.
SNAP_NA="$( cd "<WT>" && bash "${CLAUDE_SKILL_DIR}/scripts/snapshot-worktree.sh" <slug> )".
- Vers oordeel met range. Spawn de reviewer als in stap 4, maar geef in de prompt de diff-range
SNAP_VOOR SNAP_NA in plaats van de default HEAD: omdat er niets gecommit is, zou HEAD de hele opgestapelde berg tonen; de twee snapshots isoleren precies déze stap (inclusief nieuwe untracked bestanden). Omdat de snapshot-ná vóór record-step.sh valt, bevat die range geen .claude/steps/**-churn — de orchestratie-state wordt pas ná de snapshot getikt, dus de reviewer ziet alleen de deliverable. Verwerk het verdict als in stap 4.
- Registreer zonder commit.
record-step.sh --no-commit <slug> <step-id> "<message>" — markeert de stap done, tikt plan.md, zet approved_mode=autonomous, en commit niet.
- Lees de uitvoer.
interim_review=due → draai de tussenbalans (sectie 7); de doubt-agents diffen zelf ongecommit-inclusief tegen de base-branch (zie hun instructies), dus je hoeft geen snapshot mee te geven. Bij verdict "niets aanpassen" ga je automatisch door; een concreet voorstel is een break-out. status=done → de eindreview (sectie 9a). Anders → volgende stap.
Break-out naar attended — de beurt stopt, er wordt niets gecommit, de gebruiker beslist — bij:
- een vastgelopen stap: niet groen te krijgen zonder de test te verzwakken of buiten de stap te treden (sectie 8);
- een gate die rood blijft na een redelijke fix-poging;
- een reviewer-FAIL (gate, test-quality of een rule) die niet vanzelf oplost;
- een doubt-agent die een concreet voorstel doet in de tussenbalans.
Bij een break-out toon je het gewone "vastgelopen"-rapport (sectie 8) of de tussenbalans (sectie 7) — met wat er ligt en de opties — en staat de beurt weer bij de gebruiker. Het opgestapelde werk blijft ongecommit in de worktree; hervatten kan altijd (sectie 0, Hervatten van een onderbroken autonome run). Nooit groen faken geldt onverkort: een autonome run die vastloopt rapporteert dat eerlijk en stopt — hij verzwakt nooit een test of slaat een gate over om "door te komen".
7. Tussenbalans (elke 4 goedgekeurde stappen)
Getriggerd door interim_review=due uit record-step.sh. Spawn beide doubt-agents parallel (één bericht, twee Agent-calls, subagent_type: fwd-skills:fwd-steps-doubt). Elke prompt bevat alleen: het worktree-pad <WT> als repo-root, de slug, welke stappen zojuist zijn goedgekeurd, en één vraag verbatim:
What are you least confident about right now?
What's the biggest thing I'm missing about the situation right now? What don't I realize?
De agents denken en antwoorden caveman-stijl (ultrakort, met bewijs-verwijzingen). Jij consolideert — nadrukkelijk níet in caveman-stijl: helder Nederlands, volle zinnen, geen jargon, de bewijs-verwijzingen vertaald naar gewone taal. Kies een verdict: onderbouwd "niets aanpassen", of een concreet voorstel (stap toevoegen/bijstellen, deferral naar voren halen, eindbeeld herijken).
── Tussenbalans na stap <N>/<M> ────────────────────────
Minst zeker over: <2-3 volle zinnen, met concrete verwijzing>
Grootste blinde vlek: <2-3 volle zinnen, met concrete verwijzing>
Verdict: <wat dit betekent en wat ik voorstel — of waarom
er niets hoeft te veranderen>
── ok = door met stap <N+1>/<M> · of typ wat je hiervan vindt ──
Stop de beurt — de tussenbalans verdient een eigen leesmoment. Vrije tekst hierop volgt het gate-protocol (een voorstel overnemen = meestal een planwijziging).
8. Vastlopen binnen een stap
Krijg je het niet groen zonder de test te verzwakken of buiten de stap te treden: stop met bouwen en rapporteer eerlijk in plaats van het stap-rapport — wat je hebt geprobeerd, waar het precies klemt, en 2-3 concrete opties (een richting die jij voorstelt / de stap herformuleren / het plan bijstellen). Gate open; de gebruiker kiest. Geen circuit breaker — er zit een mens bij.
9. Eindrapport (na de laatste ok)
record-step.sh heeft status=done gezet. Render:
── Klaar: <M>/<M> stappen ──────────────────────────────
Beloofd vs. gebouwd:
<het eindbeeld-anker uit plan.md naast wat er nu staat — 2-3 regels;
wijkt het af, zeg dan precies waar>
Zelf draaien:
1. <commando>
2. … (maximaal 5 stappen)
Bewust uitgesteld:
- <note> — doen zodra <when> (alle deferrals uit state.json; leeg → "niets")
De code staat in de worktree op branch `<branch>` (`<WT>`).
Hoe verder: mergen (`rtk git switch <base> && rtk git merge <branch>`) / eerst zelf spelen in `<WT>` / parkeren met reden — zeg het maar.
Elke "Zelf draaien"-regel is vooraf door jou uitgevoerd en werkend bevonden — geen ongeteste instructies; je draaide ze in <WT>. De merge-keuze is expliciet aan de gebruiker; deze skill merget nooit zelf.
9a. Autonome eindreview + commit-gate
Bereikt een autonome run de laatste stap (status=done uit record-step.sh --no-commit), of rond je een onderbroken run af, dan is er nog niets gecommit. Toon eerst de eindreview — het opgetelde beeld (het eindbeeld uit plan.md) — en commit pas na ok:
── Autonome run klaar: stap <a>→<b>/<M> zonder tussenstop ────────
Gebouwd (nog niets gecommit):
<id> <titel> +<x>/-<y> <bestanden>
… (één regel per autonome stap)
Totaal: <n> stappen · +<X>/-<Y> · <k> bestanden
Gate: <X/X> groen (na elke stap herdraaid)
Reviewer: <n>/<n> stappen schoon
Doubt (na <id>): <verdict — "niets aanpassen" of wat er speelde>
Deferrals: <alle deferrals uit state.json; leeg → "niets">
Open punt(en): <reviewer-punten die open bleven, of "geen">
Zelf zien: cd <WT> && rtk git diff <base> · <gate-commando>
── ok = commit alles (1 commit) & klaar · message aanpassen? zeg 't · stop = niets committen ──
ok → finalize-autonomous.sh <slug> "<message>" maakt er één commit van al 't opgestapelde werk. De gebruiker mag de message bijsturen; per-stap splitsen kan niet (de --no-commit-accumulatie liet geen commit-grenzen na). Lees de uitvoer: status=done → draai het gewone eindrapport (sectie 9); status=in_progress (deel-finalize na een eerdere break-out) → meld wat gecommit is en dat de resterende stappen nog open staan.
stop → niets committen; het opgestapelde werk blijft in de worktree. Hervatten kan altijd met /fwd:steps-run <slug> (zie Hervatten van een onderbroken autonome run, sectie 0).
Brak de run halverwege uit (vastgelopen stap / gate rood / reviewer-FAIL / doubt-voorstel), dan verschijnt in plaats van deze eindreview het gewone "vastgelopen"-rapport (sectie 8) of de tussenbalans (sectie 7), en staat de beurt bij de gebruiker — het opgestapelde werk blijft ongecommit tot je later afrondt.
Stijl
- Nederlands, technische termen Engels; schrijf afkortingen uit bij eerste gebruik.
- Het stap-rapport is gevraagde uitleg en dus geen ballast — maar daarbuiten geldt ponytail's uitvoerregel: code eerst, geen essays, geen feature-tours.
- Rapporteer uitkomsten trouw: falende gates met hun uitvoer, een niet-gedraaide reviewer als "niet gedraaid" — nooit aandikken.