Shape
The two commands
The tests run as a command with atarget. When the command exits
non-zero, the step returns a revision request aimed at implement, with the
captured output as the finding:
examples/command-kickback.ts (excerpt)
size, between the
test and two reviews, and each review carries a when:
examples/command-kickback.ts (excerpt)
passed('size') runs one review when the command exited 0, failed('size')
the other when it didn’t. Both read the named dependency’s outcome through
ctx.needs; a name the node doesn’t need is a configuration error, not a
quiet false. The deciding node is optional: true, so its red result blocks
nothing and the branches decide. Without that, a red result would block
every step that needs it and the failed branch could never run; the dag
refuses that shape and says why. The step whose condition isn’t met is
skipped and recorded as skipped. Leave when off any branch that must run,
because a skip doesn’t fail the run. failed means the command ran and
failed; a dependency that never got to decide meets neither condition.
maxKickbacks limits how many times the writer runs again. A number is one
count for the whole graph; a map gives each target its own. When a count is
spent, the run fails with the last output as its reason instead of looping.
What the run did
The writer here is a function that getsadd wrong once, so the red test
has something to carry. Run it with npx tsx command-kickback.ts:
Output
implement ran twice: the first attempt subtracted, the test exited 1, and
its output went to implement, which ran again with it in hand. The
change was small, so size exited 0 and only quick-review ran. No agent
read the test output to decide any of that. The exit code did.
Full file
Full file
examples/command-kickback.ts
Next steps
- Feature delivery: a test command as one stage of a nine-stage team, aimed at the implementer.
- Feedback loops: the limit, and the other shapes a check can take.
- Runtime:
commandJob,passed,failedanddag.