agentleFS
phuthuycodingphuthuycoding/kanban-flow/skills/implement/SKILL.md

implement

Skill2 starsChanged 5 days agoMITView on GitHub

Implement an approved kanban feature or bug: run the subagent-driven task loop — per task a test-writer, a developer and an independent code-reviewer, a bounded fix loop and a ledger — then verify the build. Use in implementation — after `kf approve` started the item, an explicit start from backlog, or a FAIL/REJECT repair loop.

  • Reads credentials

191 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use setup-ts-deep-modules, ask-matt and 10 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • liufeng1976Skill

    setup-ts-deep-modules

    Wire dependency-cruiser into a TypeScript repo so each package is a deep module — implementation hidden in subfolders, reachable only through its entry-point files. User-invoked.

    Also in 43 projects that use this

  • GoogleSkill

    ask-matt

    Ask which skill or flow fits your situation. A router over the skills in this repo.

    Also in 91 projects that use this

  • RoentekSkill

    loop-me

    Grill me about specs for the workflows I want to build, within this workspace.

    Also in 50 projects that use this

  • AWSSkill

    to-questionnaire

    Turn a decision you can't fully answer into a questionnaire for someone else to fill in.

    Also in 88 projects that use this

  • ryotaroh180105Skill

    claude-handoff

    Hand the current conversation off to a fresh background agent that picks up the work immediately.

    Also in 42 projects that use this

  • GoogleSkill

    to-spec

    Turn the current conversation into a spec and publish it to the project issue tracker — no interview, just synthesis of what you've already discussed.

    Also in 168 projects that use this

  • +3 more from google

The file

We split this skill into the rules it gives an agent

7 rules. 0 are common, 4 are distinctive, and 3 are very specific to this project.

  • 0

    Common

    Most of the 171 edited versions we read keep these.

  • 4

    Distinctive

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Same-wave test-writers: When two tasks of one wave do not overlap, their test-writers may run at the same time.

    line 86
  2. Distinctive:

    Never wait idle on a seat while one of these steps is pending: end the turn only when no item applies and a seat or background command is …

    line 90
  3. Very specific:

    When verify reports, ledger TASK-NNN: verify done exit=<n> — the exit code kf verify itself returned and logged, never one read from …

    line 116
  4. Very specific:

    After each round append TASK-NNN: fix round <R>/5 (<X> addressed, <Y> open — <one-liners>.

    line 144
  5. Very specific:

    When .kf/config.json sets harness.verify.stage, kf verify <f> --stage replaces the hand-run build gate: run it in the worktree once all …

    line 166
  6. Distinctive:

    Do not modify the approved requirement, plan or test-case contract.

    line 176
  7. Distinctive:

    All tasks complete, build and suite green, rulings reported.

    line 193

“Common” is measured: kept by at least 6 in 10 of the 171 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Kanban Phase 3 — Implement (Autonomous)

Plugin root: ${CLAUDE_PLUGIN_ROOT} — the reference files of this skill write paths with this placeholder; resolve it to this path.

Argument: <feature_name>.

Execute the approved implementation plan for a feature, or the approved bug report's fix scope and regression strategy for a bug. If implementation requires a scope change, explain it and obtain the user's decision before revising the contract.

You are the controller, not the implementer. The plan is executed by fresh subagents with isolated context, each reviewed by another fresh subagent before its work cascades into the next task. Your context stays for coordination: the ledger, the briefs, the rulings. Fixing a finding yourself pollutes that context and skips review.


1. Move to implementation

Read kf status --change {feature_name}. kf approve already moved a freshly approved item here. Move only when coming from backlog with a valid approval and the user's explicit start decision, or when a FAIL/REJECT report requires a loop. If already in implementation, skip the move and resume existing tasks. If approval changed, stop and return to planning on the user's direction.

kf stage {feature_name} implementation

Worktree: when the project opted in with worktree.enabled: true, entering implementation provisions a git worktree + a .<tld> domain for the item — kf status --change {feature_name} prints Worktree: (path), Domain: (http://<feature>.<baseDomain>) and the direct 127.0.0.1:<port> fallback. All code work happens inside that worktree on its branch (<prefix>/<feature>, printed as Worktree: … (branch …)) — never on the user's main checkout. Commit your changes there; the merge back is the human's call, not yours. .works/ artifacts and kf commands keep working from inside the worktree (project root resolves through the git common dir). If domain DNS is not set up on the machine yet, the direct 127.0.0.1:<port> URL always works; kf worktree setup (sudo, once) fixes the domain. When worktree.domains is false in .kf/config.json, use http://127.0.0.1:<port> (the JSON outputs still carry domain; do not use it then): no domain is set up and kf status prints only the direct URL. A project worktree-create.sh hook may already have installed deps and seeded .env — check before re-installing.

Owner rule: a driving or blocked line for this item in .kf/travel/progress.md carries an owner token. Only one travel session runs per day; a session that is not travel never runs a task loop for an owner=travel line. A blocked item the human opens in this session is rewritten to owner=human and is yours to fix until they say it is done; travel then sets it back to owner=travel.

Create tasks.md if missing: - [ ] 1. ... checkboxes mapping tasks to the approved test cases for a feature, or reproduction/acceptance/regression scope in the bug report for a bug. Preserve completed tasks on resume. Record the starting HEAD and pre-existing working-tree changes in a ## Baseline section at the top of tasks.md so review can distinguish this work item's changes. When a worktree exists, the baseline HEAD is the worktree branch's branch point, recorded from inside the worktree.

2. Read the verify configuration

Read .kf/config.json. harness.verify.task lists the commands kf verify <f> --task runs after each task commit (3.2); harness.verify.stage lists the commands kf verify <f> --stage runs at the build gate (section 4). With no commands configured, kf verify still checks the task's Files allowlist on --task; exit 0 then means only that nothing was run, so call it unconditionally.

3. The subagent-driven task loop

Read the approved plan once: kf tasks {feature_name} --json gives the task graph, one row per task with id, description, dependencies, files, refs (FR/UC refs, never TC refs), expectedOutput, wave, overlaps and state; the plan's ## Global Constraints and ## Review Focus bind every task. For a bug, the "plan" is the approved bug report: one task per fix scope item plus one regression task. Read the requirement the plan argues from; conflicts inside the plan resolve against the requirement.

Seats, in this order. Each task gets Agent(kf:test-writer), which writes the failing tests from the task's test cases; then Agent(kf:developer), which makes them pass and commits the task — except in an inline wave, where the controller fills the developer seat (Inline waves below); then Agent(kf:code-reviewer), which reviews the task's diff. Whoever writes a file owns it: the developer never edits the test-writer's tests, and neither of them edits the automation-writer's specs. The agent bodies live in ${CLAUDE_PLUGIN_ROOT}/agents/<name>.md; when a seat's agent is not registered, a general-purpose subagent stands in with that body pasted first, recorded on its own line Note TASK-NNN: <seat> stand-in general-purpose @ <ts> written right after the seat's dispatched line, so the dispatched line keeps the grammar.

Ledger first. The item folder holds this item's loop artifacts under <item>/loop/: progress.md (the ledger, first line # Task loop ledger — <feature> — plan: <abs plan path>), task-NNN-brief.md, task-NNN-tests-report.md, task-NNN-report.md, task-NNN-e2e-report.md, task-NNN-verify.log, review-<first7>..<last7>.diff. Every ledger line after the header ends with @ <ISO-8601 timestamp with offset>, once; the lines kf loop-stats reads follow the grammar in references/task-loop.md § The ledger, and the lines quoted below omit the suffix. Conversation memory does not survive compaction; the ledger and git log do.

Resume from the ledger. After compaction or in a new session, rebuild the live cap N first (Resume the live cap below), before anything is re-dispatched or re-run. Then rebuild the state of every open task, and of every incomplete task with a test-writer line, from its ledger lines and git log, and resume each at its first unmet step, checked in this order. First re-dispatch every seat of any kind that has a dispatched line with no done — test-writers, code-reviewers, cascade re-reviews and automation-writers, plus every developer (except an inline task, which step 4 resumes): a developer already dispatched with no done is always resumed whatever N is, since N gates only new developer dispatches — and re-run every verify started that has no verify done, except a pending re-run, which Resume the live cap (b) holds, all before any new developer is dispatched; the dispatch conditions and the completion check (3.5) still apply, and the ledger stays the only source of in-flight state. After that phase the controller dispatches new developers up to N. A cap reached note with no later complete line of its task holds every new dispatch of the item (Repairing after the loop). A task with a complete line is never re-dispatched, unless a later Note TASK-NNN: reopened line reopens it (3.4); the no-subagent implemented line (3.5) counts as a complete line.

  1. No test-writer dispatched and no no test-writer line → dispatch the test-writer once the test-writer rule (Test-writers ahead) allows it.
  2. test-writer dispatched without its test-writer done → re-dispatch the test-writer.
  3. No developer dispatched → except an inline task (step 4), dispatch the developer under the dispatch conditions and the cap; held back, ledger the matching developer waits line and wait for what it names. An inline task not yet started is started by the controller under the same conditions, the cap aside: it writes developer dispatched and its Note TASK-NNN: developer seat inline (Inline waves rule 1), or, when a chain Ruling: names a chain subagent for it, hands the task to that subagent and writes developer dispatched at the hand-over.
  4. developer dispatched without its developer done → when task-NNN-report.md lists a commit under Commits created that git log dates after that line, ledger developer done status=DONE and add it to the task's commit list; otherwise re-dispatch the developer, whatever N is. An open inline task (its Note TASK-NNN: developer seat inline line, or the plan's Execution: wave <w> inline) is resumed by the controller itself and never spawns a developer: the controller inspects the worktree diff, finishes, commits and ledgers developer done — unless a chain Ruling: names a chain subagent for it, in which case the controller resumes that subagent and ledgers developer done when it reports. The same holds in steps 3, 9 and 10: fix rounds of an inline task run inline, or in the chain subagent its Ruling: names.
  5. An automation-writer done answering a dispatch with no round=, and no developer dispatched after both that line and the task's first developer done → resume the developer to commit the specs unchanged as the task's second commit (3.2, UI tasks), under the cap, else the cap wait line.
  6. No verify started after the task's last commit → build the review package, start kf verify and dispatch the code-reviewer (3.2).
  7. verify started without its verify done → re-run kf verify, with --at-head when a verify waits note comes after the task's last verify done; a verify waits note with no later verify started, once the task it names has committed → start the --at-head verify; an orphan re-run (Resume the live cap (b)) stays held.
  8. No code-reviewer dispatched after the task's last commit, or one without its code-reviewer done → dispatch the code-reviewer.
  9. A latest review code-reviewer done status=findings, or a latest verify done exit=1 the task keeps (3.2) — with no Note TASK-NNN: verify rerun or Note TASK-NNN: verify waits line after that verify and not an owed step-down under Resume the live cap rule (c), since a pending re-run or a wait for a neighbour's commit is never a fix round — or a latest reopened note with no round seat after it, whose findings are in its report — with no developer dispatched, no developer waits, no legacy fix queued and no round seat (test-writer or automation-writer dispatched … round=<R>) after it → below the five-round cap, the next fix round (round R+1, R counting every round of the task), its developer dispatched when a seat is free under the cap, else ledgered developer waits — <N> developers in flight; at the cap, the breaker (3.4: park with rulings), or, for a task with a reopened note and no later complete line, the cap reached stop (Repairing after the loop); a round seat done with no later developer dispatched and no later developer waits → hash the changed tests, ledger test hashes, and resume the developer to commit them unchanged, under the cap, else the cap wait line. A task never reopened whose open findings and kept failures all have a parked line goes on to step 12.
  10. A cap wait line, or a legacy fix queued line, with no later developer dispatched → dispatch that developer once a seat is free under the cap.
  11. A cascade re-review owed line is answered by a code-reviewer dispatched … cascade=<sha7> line followed by that seat's code-reviewer done; without both → dispatch that re-review.
  12. Otherwise → the completion check (3.5). Completion is earned from the ledger, never inferred from the absence of open seats, and after a reopened note only lines after it count: developer done, verify done exit=0 after the task's last commit (or the routed case of 3.2, or a failure it parked at the cap), and a clean review — code-reviewer done status=clean, or every open finding parked at the cap — with no cascade line unanswered. A task with a reopened note and no later complete line never completes by parking; a cap reached note stops it (Repairing after the loop).

Resume the live cap. Before anything is re-dispatched or re-run, rebuild N from the ledger, in this order: (a) N is the cap the latest Ruling: developer cap line sets (its <new>, or the <N> of a start ruling), or min(2, harness.developers.max) when there is none — then ledger the start ruling; either way N is capped at the current max from kf tasks <f> --json field developers.max, and a lowered max is ledgered Ruling: developer cap <old> → <new> — ceiling lowered to <max> — cost if wrong: <…>. (b) A Note TASK-NNN: verify rerun line with no later TASK-NNN: verify done is a pending re-run, an orphan one (its verify started with no done) included: run it, held until fewer than N developer seats are in flight (step 3 of Contention below), never as a fix round. (c) A task's latest verify done exit=1 of a verify that is not a re-run, whose output in <item>/loop/task-NNN-verify.log is contention-shaped, with no later Note TASK-NNN: verify rerun line, is an owed step-down: it owes steps 1–4 of Contention. When that log has no block for a failed verify, re-run that verify once as a plain verify and classify its output; it is not a re-run, so a contention-shaped failure of it owes steps 1–4 like any other. A re-run's failure is never an owed step-down. (d) Decide, in wave order, the step-up of every complete wave that has neither a wave <w> clean cap ruling nor a Note wave <w>: no step-up line, as in The live cap. Seats in flight above a lowered N finish; they are never cancelled, and no new developer starts until fewer than N are in flight.

Pre-Task-1 conflict scan. Before the first dispatch, scan the plan for tasks that contradict each other or the Global Constraints, and for anything the plan mandates that the review rubric treats as a defect. Write the table to the ledger with a Ruling: per row — the requirement is binding, the plan is its argument. A clean scan is a table with no rows, not a sentence.

Rulings, not stalls. Decide conflicts, ambiguities, plan defects and caps yourself, requirement-binding, and ledger each as Ruling: <decision> — <why> — <cost if wrong>. Five things stop you, and only these: an irreversible or destructive operation; a security-sensitive action; a side effect outside this worktree (merge, push to a shared branch, publish, a database write); a reopened task at its round cap; a plan too broken to act on. Never check in between tasks.

Order and parallelism. Tasks are taken in plan order, and a worktree runs at most the live cap N developer seats at once (The live cap below) — a task's developer (a chain subagent included; the controller's inline seat does not count, or at N = 1 an inline task and an earlier task's fix round would hold each other), a fix-round developer and a resume-commit developer (the one resumed to commit specs or fixed tests) each count one. A task's developer is dispatched only under the three dispatch conditions: every dependency's developer has reported DONE, so its task commit exists; the task's test-writer is done and its test hashes are ledgered; and its Files overlap no open task. An open task is a task with a test-writer dispatched or a developer dispatched line and no complete line after it — so a task whose test-writer is in flight counts as open, and so does one whose tests are written and whose developer waits for a seat — and its Files take part in the overlap check for developers and for test-writers; the overlap check reads the overlaps list of kf tasks <f> --json, which names each other task whose Files are not disjoint and the first overlapping entry pair (null when a side has no Files), and a task with unknown Files overlaps everything. Overlapping tasks open in wave order: a seat that would open its task — its test-writer, its developer when it has a no test-writer line, or a reopened task's first round seat — never starts while an earlier task that overlaps it is not complete, earlier meaning a lower wave of kf tasks <f> --graph, then plan order within a wave. A dependency always sits in a lower wave, so this order never makes a task wait on one that waits for it. So a developer never waits on a later task, and two overlapping tasks never wait on each other. Gating on open tasks, not on running developers, keeps a later fix round of one task out of files another developer is changing.

The live cap. N is set from the run, never fixed. Its ceiling is harness.developers.max (an integer 1–16, default 6), read from kf tasks <f> --json field developers.max; the start value and the step rules are not configurable. source: "invalid-config" means .kf/config.json failed for another key: the ceiling is unknown, so it reads 1 and developers.error says why — ledger a Ruling: that quotes it and report it to the human. Before the first developer dispatch the loop sets N = min(2, harness.developers.max) and ledgers Ruling: developer cap <N> — start — cost if wrong: <…>. A wave is a wave of kf tasks <f> --graph; it is complete when every task in it has a complete line, and clean when none of its tasks had a contention-shaped verify failure (Contention below; a verify failure belongs to the wave of the task whose verify failed, and a Note TASK-NNN: verify rerun line marks one). Step up: +1 per clean parallel wave (a parallel wave has more than one task), decided in wave order, never in the order waves finish: the decision is due at the complete line that leaves wave w and every earlier wave complete. An inline wave never changes N, nor does any other one-task wave, nor a wave that is not clean, even when its re-runs passed. Every step-up decision is written when it is due, the ones that change nothing included: a clean parallel wave raises N by 1 and ledgers Ruling: developer cap <old> → <new> — wave <w> clean — cost if wrong: <…>, unless N + 1 would exceed the ceiling, no wave is left incomplete at that due complete line (nothing remains for a higher N to run), or N + 1 would exceed the width of the widest incomplete wave — the most tasks in any wave not complete at that line, read from the ledger up to it, not when the decision is written; any other outcome writes Note wave <w>: no step-up — <not clean | inline | ceiling | last wave | widest incomplete wave>, naming the first that applies in that order (inline for every one-task wave) — a note, not a cap ruling. Fix-round and resume-commit seats count against N whatever the wave width.

Contention: step down, re-run once. Only the controller's ledgered verify runs count — a TASK-NNN: verify started … verify done exit=1 pair; kf verify --stage and developers' own runs never change N. kf verify appends each run to <item>/loop/task-NNN-verify.log, one block headed ## kf verify <finish time> exit=<n>, and the controller classifies contention — live and on resume — from the block of the run being classified, the first one timed after its verify started line, never from the whole file: an earlier run's block says nothing about this one. A failure is contention-shaped when that block contains one of these strings: EADDRINUSE, index.lock, database is locked, SQLITE_BUSY, Lock wait timeout exceeded, ETIMEDOUT, ECONNREFUSED, Test timed out, Hook timed out — an assertion failure beside one included. Its <signature> is the first string of that list, in list order, that the output contains. A re-run is a verify whose verify started follows a Note TASK-NNN: verify rerun line of that task with no verify done of that task between them. On a contention-shaped failure of a verify that is not a re-run, the controller, in order: (1) halves N to max(1, ⌊N/2⌋) and ledgers Ruling: developer cap <old> → <new> — <signature> in TASK-NNN verify — cost if wrong: <…>, unless N already dropped since that verify started — a step-down ruling Ruling: developer cap … in TASK-MMM verify of any signature, of any task, written after this task's verify started line marks the same contention event, and a ceiling lowered ruling never does — or unless this task already has a Ruling: developer cap … — <signature> in TASK-NNN verify line with the same signature and no verify done exit=0 of this task after it, in which case N stays; so N halves at most once per contention event, and at N = 1 it stays 1 with no ruling; (2) ledgers Note TASK-NNN: verify rerun — contention <signature>; (3) dispatches no developer, and holds the re-run, until fewer than N developer seats are in flight; (4) runs one re-run of that verify (verify started / verify done). A pass completes the check with no fix round. A re-run's failure never triggers steps 1–4 nor Resume the live cap (c): N is unchanged and the failure goes straight to the fix loop (3.4), or to the other-task routing of A verify failure in another task's Files (3.2), which applies only after the re-run. Each failing verify of one event gets its own one re-run. A task steps N down at most once per signature until one of its verifies passes: a later failure of that task with that signature skips only step 1 and still gets its rerun note and one re-run, with N unchanged — on resume too, since rule (c) owes steps 1–4 with step 1's exceptions.

Inline waves. A wave the plan records as Execution: wave <w> inline (one task: nothing to run beside it) spawns no developer — the controller fills the developer seat itself, because a subagent per sequential step only adds handover cost. Five rules keep the other seats intact:

  1. Ledger. In an inline wave the controller still writes developer dispatched model=inline and developer done, with Note TASK-NNN: developer seat inline right after the dispatched line, so kf loop-stats reads it unchanged.
  2. Tests first. In an inline wave the test-writers still run ahead, four tasks deep as in Test-writers ahead, in parallel, from the TCs and the plan's signatures; the controller makes them pass and never edits their tests.
  3. Review stays an independent agent. Agent(kf:code-reviewer) reviews every inline task; the controller never reviews its own task.
  4. Pipelined review. After committing task N, the controller starts kf verify and the code-reviewer in the background and starts task N+1. It does not commit N+1 until N's review is back, and fixes N's HIGH and MEDIUM findings first, committing those fixes through the path-limited script with only N's files. N+1's developer dispatched is written when its work starts; when N+1's Files overlap N's, N+1 starts only after N's review is clean and N's complete line is written, the same release point as the dispatch conditions.
  5. Signature drift. On signature drift from the plan in task N, ledger a Ruling: and re-dispatch the dependent tasks' test-writers; the controller never edits their tests.

A chain — consecutive tasks in inline waves — of more than 5 inline tasks uses one developer subagent resumed for the whole chain instead of the controller, so the controller's context stays for coordination; a shorter chain with large diffs does the same on a Ruling: that says why. For the chain subagent the controller writes each chain task's developer dispatched when it hands that task over and its developer done when the subagent reports — never ahead of the hand-over, so kf loop-stats sees sequential intervals (no inline Note); a Ruling: names the chain and the subagent's identity, and a resume after compaction resumes that same subagent.

Waiting developers. A developer held back only by an overlap is ledgered TASK-NNN: developer waits — Files overlap <mine> / <theirs> (TASK-MMM), naming the overlapping entry pair and the open task that holds it, and waits for TASK-MMM: complete. A developer seat held back only by the cap, a fix round's included, is ledgered TASK-NNN: developer waits — <N> developers in flight; its N is the cap in force when it is written, for information only. The wait is released against the live N: re-checked at the next developer done and whenever a step-up raises N, it ends once fewer than N developer seats are in flight.

Concurrent checks and commits. While any other seat is in flight, a developer's own typecheck, lint, build and test runs are advisory: it runs focused tests, no full suite, and reports failures in files it neither wrote nor was handed as not mine: <file>; the task's authoritative checks are kf verify --commits (3.2). At dispatch, fill [IN_FLIGHT] with every seat dispatched in the same turn as well as the seats already running. Each developer commits only its own paths, by name, through the commit script (references/developer-brief.md). Each task's review package and kf verify use that task's own commit list, never a range, so none grades another task's commits. Batch several tiny same-shape tasks (the same one-line change across files) into one brief and one review; keep one-dispatch-per-task for anything that needs its own judgement or its own tests.

Test-writers ahead. Test-writers may run for the next 4 tasks, earliest first (lower wave, then plan order), that have no test-writer done line, no no test-writer line, are not complete and are not held by an overlap, so tests are ready before a developer seat frees up. A test-writer never writes a file inside another open task's Files: one whose task overlaps an open task, or an earlier incomplete task (Order and parallelism), waits for that task's complete line. Its runs are advisory while any developer is in flight (the build setup continues on tsc exit 2), and the developer's own first run confirms the failures (3.1).

Same-wave test-writers. When two tasks of one wave do not overlap, their test-writers may run at the same time; their developers follow the dispatch conditions above. Ledger wave <w>: parallel test-writers TASK-A, TASK-B — disjoint Files, or wave <w>: sequential TASK-A, TASK-B — Files overlap <entry> / <entry> (wave <w>: sequential TASK-A, TASK-B — Files unknown when a side has no Files).

Controller work while a seat runs. Every time you get a turn — a seat reports, a background command exits, or you have just dispatched something — run this work list in order: (1) start the next held re-run, one at a time and earliest task first, once fewer than N developer seats are in flight and no other re-run is running; no developer, a fix round's included, starts until the last held re-run has finished; then dispatch every ready seat: developers under the cap and the dispatch conditions — a freed seat goes first to waiting fix-round and resume-commit developers, then to new task developers in plan order — test-writers for the next 4 tasks, code-reviewers and re-reviews for committed tasks, and the cascade re-reviews due; (2) start kf verify --commits and build the review package (TASK-NNN: review package <sha7>,…) for every newly committed task, and the --at-head verify of every task whose verify waits note names it; (3) write the brief of the next task that has none (TASK-NNN: brief written) and hash its test files; (4) run the scouts a later task needs; (5) write the ledger lines and reports that are owed — each step ledgered as it lands. kf verify, a full suite and a build run with the runtime's background option, never in the foreground, while any item above still applies.

Never wait idle on a seat while one of these steps is pending: end the turn only when no item applies and a seat or background command is running.

Scout before a shared change — reuse first. The plan stage saved its scout reports under <item>/reviews/scout-<target>.md; a task whose target is covered there carries that report's Highest risk and Uncovered paths lines into the brief and dispatches nothing. Dispatch Agent(kf:scout) only for a shared surface (a route, an event, a schema, a public export, a CLI contract) the plan stage did not scout, or one that changed on the base after approval; save the new report beside the others. A bug's task dispatches none. A scout report that changes nothing about the brief was either unnecessary or unread.

3.1 Write the brief and dispatch the test-writer

  1. Record BASE — git rev-parse HEAD in the worktree — and, from every seat report, the task's own commits: the task's commit list is those commits in history order. The review package, kf verify and the fix diffs take the commit list, because other open tasks' commits may interleave with this task's.
  2. Write the brief to <item>/loop/task-NNN-brief.md: the task row verbatim (description, expected output, FR/UC refs, Files allowlist; when the plan's Files is - (unknown), [FILES] is . and its developer commits with --allow . — name each file you changed, never . or a directory), the UC and TC excerpts it serves, the Global Constraints, the interfaces earlier tasks produced, your resolution of any ambiguity, and the scout lines. Exact values live only in the brief; no subagent reads the whole plan. The refs of kf tasks are FR/UC refs only, never TC refs: select the ## TC-### blocks of phase-2-test-case.md whose requirement or use case reference matches the task's FR/UC refs, and sort them by Test type — Unit / Integration for the test-writer, UI / E2E for the automation-writer (3.2).
  3. Pick the seats. A task whose TCs include Unit or Integration gets the test-writer; so does a bug's regression task, where the test-writer writes the regression test from the bug report's reproduction. A task with no Unit or Integration TC (docs, config, glue) skips it: ledger TASK-NNN: no test-writer — <why>, and the developer's report then carries the No TDD: <why> line with real-run output. For a task with both Unit and UI TCs, the Unit TCs go to the test-writer and the UI TCs to the automation-writer; neither edits the other's files.
  4. Dispatch Agent(kf:test-writer) with references/test-writer-brief.md verbatim, naming the model per references/task-loop.md § Model selection; the controller fills [IN_FLIGHT] at dispatch with the other seats in flight, or none. It writes <item>/loop/task-NNN-tests-report.md, never commits and returns the short contract.
  5. Check that each test fails for the right reason — the report's failing output shows the TC's expected value not met, or the export, route or command the task adds missing. When the test-writer's run was advisory (another seat in flight), the "fails for the right reason" judgement uses the developer's step-3 run, and the ledger says so: the developer stops with NEEDS_CONTEXT if a handed test passes before implementation or fails for a reason other than the missing behaviour in its step-3 run, and the controller rules then, before the developer builds. When the developer's step-3 run is advisory too (other developers in flight) and a handed test fails inside another task's Files, the developer has stopped with NEEDS_CONTEXT: the controller re-runs the handed tests once those developers report, before resuming it to build, or ledgers a Ruling: that names the weaker evidence. Then:
    • A test that passes before implementation proves nothing about this task: record a Ruling: before the developer is dispatched — the behaviour already exists (the task shrinks to what is missing) or the test is wrong (back to the test-writer). Never dispatch the developer on it silently.
    • A test-writer NEEDS_CONTEXT for a TC with no concrete expected value is a plan defect: rule on the value the requirement fixes and re-dispatch the test-writer with that Ruling:, or stop — a plan too broken to act on — when the requirement fixes none. It never goes to the developer, who would invent the value.
    • Any other NEEDS_CONTEXT or BLOCKED is handled as in 3.2.

3.2 Dispatch the developer and handle its report

Dispatch Agent(kf:developer) with references/developer-brief.md verbatim, naming the model per references/task-loop.md § Model selection; the controller fills [IN_FLIGHT] at dispatch with the other seats in flight, or none, and [COMMIT_SCRIPT] with the absolute path of scripts/commit-task.mjs. Append the test-writer's test files and their failing output to the brief file first, and run git hash-object <test files> and ledger the result as TASK-NNN: test hashes <file>=<sha> …. The developer never edits those test files, makes them pass and commits the task — tests and code — on the item branch. When it reports, hash the same files again, read from the worktree files at the developer's committed HEAD, and compare them with the latest TASK-NNN: test hashes line — every test-writer change ledgers a new one (3.2 dispute, 3.4 test findings): a mismatch is handled like a TEST_DISPUTE — back to the test-writer — never accepted silently. Record the developer's agent identity — rounds 1–3 of the fix loop resume it.

The developer writes its full report to <item>/loop/task-NNN-report.md and returns only status, commits, a one-line test summary and concerns. It never dispatches subagents and never spawns a reviewer.

UI tasks under Level: full. A task whose TCs include UI or E2E gets Agent(kf:automation-writer) with references/automation-writer-brief.md verbatim, naming the model: after the developer's commit, against the screen it built — or before the developer when the plan fixes a data-testid contract, the specs then expected to fail until the screen lands; in that case pass their paths to the developer as [SPEC_FILES], which it never edits and keeps out of its task commit. It writes <item>/loop/task-NNN-e2e-report.md and never commits. Once the developer's task commit exists, resume the developer once to commit the automation-writer's spec files unchanged as a second commit of the task, before the code-reviewer, under the cap, else the cap wait line, so the task's commit list covers both commits. A spec the report says fails because the product is wrong is a code finding for the fix loop (3.4). The Playwright MCP is for selector discovery only, one agent at a time; the evidence is the headless npx playwright test run.

  • DONE → for a UI task under Level: full, the automation-writer step above first (a DONE with no commit is sent back — DONE requires a commit); then, at the task's last commit:
    1. Build the package from the task's commit list: bash ${CLAUDE_PLUGIN_ROOT}/skills/review/scripts/review-package --commits <sha>[,<sha>…] <item>/loop/review-<first7>..<last7>.diff, ledgered TASK-NNN: review package <sha7>,….
    2. Then, at the same time, start kf verify <f> --task TASK-### --commits <sha>[,<sha>…] in the worktree, ledgered TASK-NNN: verify started, and dispatch the task's code-reviewer (3.3), ledgered TASK-NNN: code-reviewer dispatched …. With one task in flight, the single-task form kf verify <f> --task TASK-### --base <BASE> still works; the loop uses --commits.
    3. When verify reports, ledger TASK-NNN: verify done exit=<n> — the exit code kf verify itself returned and logged, never one read from another command, with nothing after it; kf loop-stats checks it against the log — and act on its exit code:
      • exit 0 → verify passed; the task completes once its review does (3.5).
      • exit 2 (a changed file is outside the task's Files; the output lists them) → stop: this is a plan change — every in-flight seat reports and is ledgered before kf stage <f> planning, and the review result is kept; then edit the plan's Files, have the human re-approve with kf approve <f> (moves the item back to implementation), then re-run kf verify. Never a fix round, and never widen Files or commit the change yourself to get past it.
      • exit 1 (a harness.verify.task command failed) → when the output is contention-shaped and the verify is not a re-run, the step-down and its one re-run come first (Contention, in 3), and only a failed re-run goes on; otherwise the verify output joins the code-reviewer's findings as one developer fix round (3.4), started when that review reports, then re-run kf verify; when the failing tests lie in another open task's Files, the evidence rule below decides which task's round it is.
      • exit 3 (bad input: unknown task, a commit that is not a commit, a merge, not an ancestor or out of history order, an empty list, missing worktree; nothing ran) → your call is wrong: fix the call and re-run it, never a fix round. Exit 3 with kf verify could not run: … (an unexpected kf error) → report it to the human, not a fix round.
  • DONE_WITH_CONCERNS → read the concerns; correctness or scope concerns are addressed before review, observations are noted and reviewed.
  • NEEDS_CONTEXT → supply it, re-dispatch the same agent. When the missing piece is outside knowledge (a library's behaviour, an API version, a standard, how other tools do it), dispatch Agent(kf:researcher) first with ${CLAUDE_PLUGIN_ROOT}/skills/flow/references/researcher-brief.md, report path <item>/reviews/research-<slug>.md, and pass its conclusion and the report path as the context when you re-dispatch the same developer. The same holds for a BLOCKED caused by missing outside knowledge. It does not apply to a plan defect, a test dispute or an architectural choice. Ledger Ruling: research <report path> supplied to TASK-NNN developer — <why> — <cost if wrong>. This dispatch is not a fix round and uses no fix brief; the seat grammar of references/task-loop.md is unchanged.
  • BLOCKED → a context problem gets more context; a reasoning problem gets a more capable model; a too-large task gets split; a wrong plan gets a ledgered Ruling: and a re-dispatch carrying it. Never force an unchanged retry, never ignore an escalation. A BLOCKED that quotes commit made names a commit that exists: add its sha to the task's commit list and continue as for DONE, never a re-commit.
  • TEST_DISPUTE: <file:line> <why> → read the reason first. When it says the TC contradicts an FR or another TC (not the code), stop and report it to the human as a plan or requirement problem — never rule on it. Otherwise dispatch Agent(kf:test-writer) with the line verbatim: it fixes the test against the TC, or keeps it and quotes the TC. Fixed → re-run git hash-object on the changed test files and ledger a new TASK-NNN: test hashes line before resuming the developer with the fixed test. Kept → record a Ruling: that the TC is binding, quoting it, and resume the developer with it. Stop, too, on a second dispute on the same test after a Ruling — it is not another round: report it to the human. Ledger every step as TASK-NNN: test dispute <file:line> — <fixed | kept, Ruling | stopped>.

A task's commit that cannot build alone. Parallel tasks interleave commits on one branch, so H's newest commit may not build when it needs a file another open task X has not committed yet. That exit 1 is no fix round: ledger Note TASK-H: verify waits — <file> (TASK-X) and, once X's commit lands, re-run with kf verify <f> --task H --commits <sha>[,<sha>…] --at-head, a new verify started / verify done pair. X held by H's own overlap cannot land first: that is a plan defect, so stop and report it. It keeps the allowlist check on H's commits and runs the commands in a detached worktree at HEAD. A failure there is an ordinary exit 1. Another command's pass never stands in for kf verify.

A verify failure in another task's Files. When H's verify exits 1 on tests inside the Files of another open task X (X's commits are in the checked-out tree), the cause decides, by evidence: first wait for X's running verify, if any; if X's latest verify on a tree without H's fix commit passed those same tests, H broke them and the failure stays with H; otherwise it goes to X as a fix round of X, with a Ruling: line naming the tests and the evidence. H stays unverified until X's next verify passes. If X's developer reports BLOCKED because the cause lies in H's Files, the controller returns it to H as a fix round. If X parks the routed failure at its five-round cap, H counts as verified and completes with the parked failure named in its complete line. No deadlock: X's verify never waits for H's completion.

3.3 Review the task

Dispatch Agent(kf:code-reviewer) with references/task-reviewer-brief.md verbatim, beside the task's kf verify (3.2): the brief file, the developer's report file, the review package, the Global Constraints copied verbatim, and the model (sonnet; opus for a high-risk diff). It grades the review package only; the working tree may hold other tasks' uncommitted edits, which are context only. It returns a spec-compliance verdict (✅ / ❌ / ⚠️ cannot verify from diff) and a quality verdict with findings in the shared schema. Resolve every ⚠️ item yourself from the plan or the code before completing the task; a confirmed gap is a failed spec review. A ⚠️ that only a real run can answer is ledgered TASK-NNN: unverified — <claim>, and kf:test runs it. Never accept a report missing either verdict; self-review never replaces this gate. Never pre-judge a finding in the brief ("do not flag X" is the tell).

3.4 The fix loop

Triggered by spec ❌, any HIGH or MEDIUM finding, or a ⚠️ you confirmed. Minor (LOW) findings never enter the loop: ledger them as TASK-NNN: minor (deferred): <one-liner> — the whole-branch review at the review stage reads them from the pack's ## Deferred block. A plan-mandated finding is yours to rule on, ledgered before you act.

A round is one fix dispatch plus one scoped re-review. Five rounds maximum per task, one counter whichever seat fixes.

  • Code findings go to the developer. Rounds 1–3 resume the original developer with the open findings verbatim; it fixes, re-runs the covering tests, appends a fix report to its report file and returns the short contract.
  • Rounds 4–5 dispatch a fresh developer one tier up, with the brief path, the report path, the open findings and the framing "a prior developer attempted this N times; you own it now".
  • Findings about a test go to the test-writer (a spec's to the automation-writer): resume it with those findings verbatim; it fixes the test against the TC, re-runs it and appends a fix report to its report file — task-NNN-tests-report.md for the test-writer, task-NNN-e2e-report.md for the automation-writer. Then re-run git hash-object on the changed test files and ledger a new TASK-NNN: test hashes line before resuming the developer to commit the fixed test unchanged, under the cap, else the cap wait line. The round counts the same as a code round.
  • The re-review is scoped: review-package --commits <fix sha>[,<fix sha>…] over the round's fix commits, FIX_BASE being the head the previous review saw, dispatched with references/re-review-brief.md. Each finding comes back ADDRESSED or NOT ADDRESSED; new breakage in the fix diff joins the open list; out-of-scope observations become deferred minors.
  • After each round append TASK-NNN: fix round <R>/5 (<X> addressed, <Y> open — <one-liners>; commits <a7>,<b7>,…), listing the round's fix commits.

The cascade re-review. A fix commit of task H that lands after the developer of task X was dispatched owes X a scoped re-review of X's own commits after X's review only when X depends on H, directly or transitively, by the dependencies of kf tasks <f> --json; a task that does not depend on H owes nothing, since disjoint Files and per-task commit lists keep its reviewed diff valid. H's fix diff goes in the re-review brief's [CASCADE_FIX_DIFF]. Ledger TASK-X: cascade re-review owed — after <sha7> of TASK-H; dispatch it as TASK-X: code-reviewer dispatched model=<m> round=<R> cascade=<sha7>, R being the fix round of TASK-H that made <sha7>, and its done line answers it. Each cascade re-review owed line is answered by its own re-review, matched by its sha7. X is never marked complete while a dependency is incomplete or a cascade line of X is unanswered.

Coupling the plan did not declare is not a cascade: the stage gate's full build and full suite (section 4) are the backstop that catches it.

The breaker. When round 5 still leaves findings open, stop dispatching and adjudicate each: a contestable one is parked — TASK-NNN: parked — <finding> — Ruling: <why>; a load-bearing one gets a ruling on the smallest unblocking change. Silent discards are forbidden. Never complete a task — and so never let a task that depends on it complete — with a HIGH finding neither fixed nor parked with a ruling. A task never reopened takes the breaker for its open findings and kept verify failures; a task with a reopened note and no later complete line takes the cap reached stop instead.

Repairing after the loop. When a testing or review FAIL or REJECT, or red CI, loops the item back (section 1), each failure is repaired on the task that owns it: the task whose Files hold the failing file. A failure outside every task's Files is a plan change (3.2, exit 2), never routed to another task. Ledger Note TASK-NNN: reopened — <testing|review|ci> <first 8 chars of the execution id> first, then the usual round lines, continuing the task's round count, then a new TASK-NNN: complete … line. Five rounds is the whole life of a task: a repair that finds it at the cap never runs rounds 6–10 and is never parked to completion: ledger Note TASK-NNN: cap reached — <failure>, let the seats in flight finish, dispatch nothing new for the item and report the failure to the human. Only the human ends the stop: by kf cancel, or by kf stage <f> planning, where the re-approved contract gives the work a new task with its own five rounds, or no longer requires what failed. The session that resumes after that approval ledgers TASK-NNN: complete (commits <a7>,<b7>,…, superseded by TASK-MMM), or … superseded by contract) when no task replaces it. Either line ends the stop. A task waiting on TASK-NNN's verify (3.2) re-verifies once TASK-MMM commits, or at once under superseded by contract, and a task depending on TASK-NNN waits for TASK-MMM's complete line, the re-approved plan listing TASK-MMM among its dependencies. The task's tasks.md box stays ticked. A reopened note cancels the task's earlier complete line: wherever the loop asks whether a task is complete, only a complete line after its latest reopened note counts. No other line shape is written for a repair.

3.5 Complete the task

A task is complete when its developer is done, its latest verify is exit=0 (or its failures were routed to another task X and X's next verify passed, or X parked them at its five-round cap, or it parked them itself at its five-round cap), its latest review is clean or every open finding is parked at the five-round cap, none of its own cascade lines is unanswered, and every dependency is complete. A task stopped at cap reached never reaches this check (Repairing after the loop). There is no plan-order barrier: independent tasks complete in any order. Every other task completes by this check; then tick the task in tasks.md and append TASK-NNN: complete (commits <a7>,<b7>,…, review clean) or … (<K> parked), listing the task's commit list, naming any verify failure X parked. "Review clean" certifies the diff matched the brief and the code is sound; it certifies nothing visual. A task whose deliverable is something a person looks at gets a real run before its ledger line (start the app at the item's domain or port, exercise the screen) — the plan should have flagged it.

No subagent tool in your runtime? Implement task by task in the same order (brief, tests, implement, commit, ledger), but do not fill the independent seats yourself — a session does not grade its own work, and it never fills the test-writer and the developer seats in one session and claims them independent: tests and code written by one session are one seat. Write TASK-NNN: implemented, test-writer seat: none, review seat: none in the ledger — it counts as the task's complete line, on resume too — and leave the review to the review stage, which then treats every task as unreviewed and reviews the whole branch at the tier the diff demands. A complete (review clean) line without an independent reviewer is a lie the ledger must not carry.

4. Tick tasks as they land; gate on build

{build_command}

When .kf/config.json sets harness.verify.stage, kf verify <f> --stage replaces the hand-run build gate: run it in the worktree once all tasks are complete, instead of {build_command}. Exit 0 is the PASS and exit 1 the FAIL below; exit 3 means your call is wrong — fix it and re-run.

  • PASS → continue.
  • FAIL → the failing task's developer fixes, re-run.
  • Failed again → STOP, show error, ask.

When all tasks are complete, run the FULL build and the FULL suite (not just the touched module), in the worktree. Collect every ledger Ruling: line into your final message under "Rulings I made", each with what it costs if wrong — that list is the only place the decisions you took on the human's behalf reach them.

Then run kf loop-stats <f> --record (it prints the item's report and writes (replacing any earlier) its row in .works/loop-metrics.md) and kf loop-stats --all (it prints the history and its largest: line), and print the item's report and the largest: line in your final message beside "Rulings I made". A session with no subagent tool has no seat lines and skips --record. An orphan a resume re-dispatched is expected and recorded. When --record refuses for unparsed lines, other orphans or late stamps, fix the ledger lines it lists and run it again; never hand-edit .works/loop-metrics.md. The numbers report where the loop's time went; they change no rule of the loop.

Do not modify the approved requirement, plan or test-case contract. Project-specific permissions for database operations and other external actions still apply.


References

  • references/test-writer-brief.md — the test-writer dispatch, verbatim.
  • ${CLAUDE_PLUGIN_ROOT}/skills/flow/references/researcher-brief.md — the researcher dispatch, verbatim.
  • references/developer-brief.md — the developer dispatch, verbatim.
  • references/automation-writer-brief.md — the automation-writer dispatch, verbatim.
  • references/task-reviewer-brief.md — the task review dispatch, verbatim.
  • references/re-review-brief.md — the scoped re-review after a fix round.
  • references/task-loop.md — model selection, the ledger, fix-loop mechanics, the rationalizations to refuse.
  • ${CLAUDE_PLUGIN_ROOT}/skills/review/scripts/review-package — the review package script (shared with the review stage).

Done

All tasks complete, build and suite green, rulings reported. Hand off:

Load the kf:test skill and move the feature to testing.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.