Built-in Workflows
Six pipelines embedded in the binary. Start with explain and quickfix; run any by name; customize with tracker init.
All six embedded workflows are coding-flavored — they shipped with
the binary because they were the original use case. The pipeline framework itself is
general: any sequence of LLM calls plus parallel branches plus human gates fits the
same .dip shape. RAG, eval, content moderation, agent triage are all doable;
we just haven’t shipped opinionated templates for them yet. Pull requests welcome.
Where to start
Climb one rung at a time. explain only reads: ask a
question about your repo. quickfix makes one small
change on its own branch and waits for you to approve it. Then
ask_and_execute builds a feature three ways and
keeps the best, and build_product builds a whole
product from a SPEC.md, milestone by milestone. The two starters run on your
Claude subscription when claude is installed and signed in, so they need no API key.
explain
Ask one question about the repo you're in. Read-only: nothing is changed.
tracker explain --param question="what does this repo do?"Start → Answer → WriteAnswer → Done. Answer runs on your Claude
subscription when the claude CLI is installed and signed in
(backend: auto; no API key needed), otherwise on a configured API key, with
tool_access: read_only: it can read, search and list files, never write, and
secret-looking files are refused. The answer is saved to
.tracker/runs/<id>/explain.md and the run ends by pointing at
quickfix. Without --param, it asks the question first. Backstops:
1 hour, $1.
quickfix
Make one small change on its own branch, review the diff, then commit or throw it away.
tracker quickfix --param change="fix the typo in the README"The change is made in a separate git worktree on tracker/quickfix/<run-id>,
so Tracker never changes your checkout, branch or uncommitted work. The agent is told to
stay in the worktree; it is not sandboxed, so the review gate warns if anything outside the
worktree changed while it worked. After the project's
tests run (a Makefile test target, go.mod, a
package.json test script, pytest or Cargo, if any), the review gate shows
the diff and the result:
- approve commits to that branch (unsigned, your hooks kept) and prints how to look at it, merge it or open a PR. Nothing is merged or pushed.
- revise asks what to change and tries again, up to three times; typing anything else at the gate counts as revision feedback.
- reject removes the worktree and branch.
Untracked secrets, private keys and compiled binaries are never staged (the same rules as
build_product). The branch, base commit and worktree are recorded in
.tracker/runs/<id>/quickfix.json. Needs a git repo with at least one
commit. Unattended: --auto-approve and a timed-out webhook gate reject, so
nothing is committed; --autopilot can approve, which only ever creates a local,
unpushed branch. Backstops: $3 and 8 hours (wall time counts time spent
at the review gates).
build_product
Read a SPEC.md, decompose into milestones, implement each with verification loops, cross-review the complete result with three models, verify spec compliance.
build-setup.sh hook"] Env -->|env-ready| Lint["Lint Spec
sonnet"] Env -->|env-failed| Abort Lint -->|ready| ReadSpec["Read & Analyze Spec
sonnet, reasoning: medium"] Lint -->|needs work| Forge["Forge Spec
opus, budget-capped"] Forge --> Fidelity{{"Fidelity
check"}} Fidelity -->|ok| Lint Fidelity -->|budget out| Done([Done]) ReadSpec -->|success| Decompose["Decompose into
Milestones
opus, reasoning: high"] ReadSpec -->|fail| Abort["AbortRun
run ends fail"] Decompose -->|success| Approve{{"Human:
Approve Plan"}} Decompose -->|fail| Abort Approve -->|approve| Pick["Pick Next
Milestone"] Approve -->|adjust| Decompose Approve -->|reject| Done subgraph loop ["Build Loop · per milestone"] Pick -->|milestone N| Impl["Implement
opus, 50 turns"] Impl --> Test["Test Milestone
tests + verify cmd"] Impl -.->|turns exhausted| Op{{"Human:
Operator Decision"}} Op -->|continue| Impl Op -->|commit + advance| Mark Test -->|pass / not-yet-verifiable| Verify["Verify Completion
sonnet"] Verify -->|pass| Mark["Mark Done"] Mark --> Pick Test -->|fail| Fix["Fix Issues
opus, 50 turns"] Fix --> Test Test -->|escalate| EM{{"EscalateMilestone"}} EM -->|mark done| Mark EM -->|retry| Impl end Pick -->|all done| Review subgraph xreview ["Cross-Review · 3 models"] Review["Parallel Fan-Out"] --> Claude["Claude Review
sonnet"] Review --> Codex["Codex Review
gpt-5.6-sol, 40 turns"] Review --> Gemini["Gemini Review
gemini-2.5-flash"] Claude --> Join["Fan-In Join"] Codex --> Join Gemini --> Join Join --> Synth["Synthesize Reviews
opus"] end Synth -->|pass| FinalBuild["Final Build
& Test"] Synth -->|fail| ApplyFix["Apply Review
Fixes"] --> FinalBuild FinalBuild --> FinalSpec["Final Spec
Compliance
opus"] FinalSpec -->|pass| Cleanup --> FinalCommit -->|success| Done FinalCommit -->|fail| Abort FinalBuild -->|fail| EV{{"EscalateVerification"}} FinalSpec -->|fail| EV EV -->|accept| Cleanup EV -->|retry| Decompose EV -->|abandon| Abort Synth -->|re-review budget out| ER{{"EscalateReview"}} ER -->|accept| Cleanup ER -->|retry| Decompose ER -->|abandon| Abort EM -->|accept| Cleanup EM -->|abandon| Abort Op -->|abandon| Abort Abort --> Done
Why it’s shaped this way
- Split escalation gates.
EscalateMilestonehandles mid-build stuck-ness (mark done / retry / accept / abandon, defaults to mark-done).EscalateVerificationhandles a red or unverified build — redFinalBuild, failedFinalSpecCheck, a reviewer failing (abandon / retry / accept, defaults to abandon so an unattended run never ships unverified).EscalateReviewhandles only a green build the reviewers still object to after the re-review budget runs out (accept / retry / abandon, defaults to accept as an audited override). Pre-build agent failures (ReadSpec/Decompose) go straight toAbortRun. One gate would conflate three different decisions. - Abandon always ends the run
fail. Every gate’sabandonroutes to theAbortRunterminal (a tool that exits 1), never straight toDone— a gate edge to the exit ends the runsuccess, so an abandoned build would report as shipped. - Environment bootstrap before any agent runs. Right after
Setup,EnsureEnvruns the first found ofbuild-setup.sh/.build/setup.sh/scripts/build-setup.sh— a hook the seed repo or operator ships to pin toolchains and dependencies (a.venv,npm ci,go mod download). No hook is fine; a hook that fails stops the run atAbortRunwith the hook’s log replayed (.tracker/env-bootstrap.log/.status), because milestones built against a partial environment — or an agent improvising its own dependencies over a failed pin — waste the whole run. A hook that must reach a private registry needsTRACKER_PASS_ENV=1on thetrackerinvocation: tool subprocesses (the hook included) run with*_TOKEN/*_API_KEY/*_SECRET/*_PASSWORDvariables,DOCKER_AUTH_CONFIGand any variable whose value is a URL carrying credentials (an authenticatedPIP_INDEX_URLorNPM_CONFIG_REGISTRY) stripped. - Contract tests, reconciled against what actually ran. Each milestone names its
**Contract tests**— the exact tests that prove its done-when (GoTestX/TestX/sub, Rustmodule::test_name, pytestpath::test_name, a JS title) ornone — reason.PickNextMilestonewrites them to.ai/milestones/contract-tests; everyverify.shrun rewrites.ai/build/executed-tests.txtwith every test that executed;TestMilestonereconciles the two after a green run, and a declared test that never executed is an ordinary red (CONTRACT-TEST-MISSING→FixMilestone) — a milestone that authored no test of its own can no longer go green on the prior suite. - Deny-by-default test gate.
TestMilestoneis green only when a real oracle ran: a test suite that executed a positive number of tests (counted fromgo test -v, the jest/vitest/mocha/TAP reporters, cargo’s summary lines, or a pytest run that collected something) or a project Makefileci/check/lint/testtarget. A tree with no runnable oracle (a milestone-1 scaffold, a suite that ran zero tests) is neither green nor red: it routes toVerifyMilestoneastests-not-yet-verifiableand the verifier decides whether the milestone legitimately needs no executable verification. Python suites are discovered without apyproject.tomland run through a.venv/venv/ PATHpytest/uv runchain. Language-native lint (vet, golangci-lint, tsc, eslint, ruff, mypy, clippy) always runs but is advisory — findings are printed with anADVISORY:line and never fail a milestone; only a project-declared Makefile target blocks. - Per-milestone circuit breaker. A
fix_attemptsfile on disk caps retries per milestone to 3 and persists across pipeline restarts. Reset only byMarkMilestoneDone. The engine’s global restart counter would otherwise let a stuck milestone 1 burn through milestone 10’s budget. - Three-model cross-review. Claude, Codex, and Gemini review independently. Reviews are synthesized to surface consensus vs. disputed findings — cheaper than asking a single model to argue with itself.
- Defensive shell scripts. Tool nodes never
evalLLM output. Milestone headers are matched flexibly. Empty-file guards fail loudly so an empty patch file doesn’t silently no-op the build.
Operator stamps
Two empty marker files under .ai/build/ let the operator (never an agent) opt a repo out of a fail-closed check. Both survive Setup’s per-plan state reset, ResetReviewBudget and Cleanup, so they persist across tracker -r resumes and EscalateReview → retry re-plans; delete the file to re-arm the check.
.ai/build/allow-dirty— dirty-tree preflight opt-out.Setuprefuses to start when the repository (the whole tree, not just the workdir) has uncommitted changes or untracked files, because the checkpoint commit after every milestone stages every tracked change and untracked file (only detected compiled binaries and secret-looking files such as.env/ private keys are left out), so stray WIP would be swept into the build’s history and reviewed as milestone output. Safe when the tree is deliberately dirty. Create it before the run:mkdir -p .ai/build && touch .ai/build/allow-dirty..ai/build/no-tests-ok— ship-gate opt-out for a product with no test stack. Without it,FinalBuild(verify.sh --final) fails when no build system is detected anywhere in the tree (nogo.work/go.mod/package.json/pyproject.toml/Cargo.tomland no Makefileci/check/lint/testtarget) and routes toEscalateVerification(unattended defaultabandon: the run endsfailatAbortRun) — a product with no test runner cannot ship green. With it, the ship gate passes with aNOTEthat nothing was tested. Without it, milestone-modeTestMilestonereports such a tree astests-not-yet-verifiable(VerifyMilestoneconfirms the milestone’s done-when needs no tests); with it, the milestone gate passes with the sameNOTE. The operator must create it before the run:PickNextMilestonesnapshots the hatch files at the start of every milestone, and a stamp that appears mid-milestone is reported byTestMilestone/FinalBuildas agent-created and treated as a finding. Agents are instructed never to create either stamp.
# Run it
tracker build_product
# Copy and customize
tracker init build_product
# edit build_product.dip, then:
tracker build_product.dipask_and_execute
Ask the user what to build, explore and spec it, fan out to three implementations in isolated git worktrees, cross-critique, pick the winner, apply it, clean up the rest.
Each model implements the same spec in its own git worktree — full filesystem isolation, no interference. Each implementation is reviewed by all three models; a judge selects the winner from aggregate scores; the winning branch is merged and the others are deleted.
tracker ask_and_executebuild_product_with_superspec
For large structured specs with parallel work streams and dependency graphs. Independent streams run concurrently; mechanical quality gates between phases; cross-review at the end; full traceability audit.
Structure"] --> Plan["Build Execution
Plan"] Plan --> Approve{{"Approve?"}} Approve -->|approve| P1["Phase 1:
Parallel Streams"] P1 --> G1["Quality
Gate 1"] G1 -->|pass| P2["Phase 2:
Dependent Streams"] G1 -->|fail| Fix1["Fix Phase 1"] Fix1 --> G1 P2 --> G2["Quality
Gate 2"] G2 -->|pass| Review["Cross-Review
(3 models)"] Review --> Final["Final Gates
& Traceability"] Final --> Done([Done])
Quality gates are mechanical, not LLM-judged — build, test, lint, coverage, complexity. The final gate verifies every spec requirement maps to implementation and test coverage. Designed for specs big enough that a single milestone-builder run would lose the plot.
Which one? Start with build_product — it is the default
for a normal SPEC.md and builds one milestone at a time in a single working
tree. Reach for build_product_with_superspec only when the spec is large enough
to name independent work streams and a dependency graph the engine can
parallelize; on a small or single-track spec the extra machinery is overhead. Both run the
same fail-closed SpecLint spec-coherence preflight first. Superspec-only:
parallel streams in isolated git worktrees, per-phase mechanical quality gates, three
specialized cross-reviewers (architect / QA / product), and a
docs/traceability.yaml scaffold with a final traceability-audit goal gate.
deep_review
Structured codebase review powered by interview mode. Three rounds of targeted questions (scope, findings, priorities) drive parallel analysis and produce an actionable remediation plan.
Codebase"] Explore --> GenScope["Generate Scope
Questions"] GenScope --> Scope{{"Interview:
Scope"}} subgraph analysis ["Parallel Analysis"] Scope --> P["Fan-Out"] P --> Correct["Correctness
opus"] P --> Sec["Security
opus"] P --> Design["Design
opus"] Correct --> J["Fan-In"] Sec --> J Design --> J end J --> Synth["Synthesize
Findings"] Synth --> Findings{{"Interview:
Findings"}} Findings --> GenPri["Generate Priority
Questions"] GenPri --> Priority{{"Interview:
Priorities"}} Priority --> Plan["Write Remediation
Plan"] Plan --> Review{{"Approve Plan?"}} Review -->|approve| Final["Finalize"] --> Done([Done]) Review -->|revise| Plan
Three interview gates narrow down the work: scope (primary concern, target area, deployment context), findings (each finding presented as intentional / known bug / needs investigation — your context kills false positives), priorities (timeline, fix approach, dependencies). The output is a remediation plan, not a wall of nitpicks.
# Review any codebase
tracker deep_review
# Fully autonomous (LLM answers the interviews)
tracker --autopilot mid deep_reviewRun them unattended
Every workflow is designed for hands-on AND fully unattended operation. Pick the gate-handling strategy that matches your deployment.
Autopilot personas
An LLM judge answers every gate. Four personas: lax (forward progress), mid (balanced, default), hard (high bar), mentor (approve with feedback).
tracker --autopilot mid build_productAuto-approve
Deterministic — no LLM call, always picks the default or first option. Best for CI and pipeline-flow tests.
tracker --auto-approve build_productWebhook gates
POST every gate to your URL; pipeline blocks on the callback. Slack bots, email approval, mobile push, factory workers. Per-gate tokens, configurable timeout.
tracker --webhook-url https://... build_productWorkflow customization
After tracker init <name>, the local .dip file takes precedence on subsequent runs.
Tweak per-node models, backends, or prompts without forking the whole pipeline.
Workflow params
Top-level vars become ${params.*} graph attrs referenceable in prompts, commands, and conditions. Override at runtime with --param key=value; unknown keys hard-fail at startup.
Declared inputs
An inputs block declares a typed run signature (text/number/bool/enum/file/secret, with required/default/prompt/validation). Read as the closed, untrusted ${inputs.*} namespace. A host introspects it (DescribeInputs) and validates values (ValidateInputs) before the run; a missing required input fails closed at start. file/secret values are staged to a 0600 file the workflow’s shell reads by path — a secret’s value never enters a prompt, the wire, the trace, or the checkpoint. Requires dippin ≥ v0.51.
Budget ceilings
Put max_total_tokens / max_cost_cents / max_wall_time in a workflow’s defaults: block; CLI flags override per-run. Halts emit EventBudgetExceeded.
Human-gate timeouts
Set timeout and timeout_action per human gate so unattended runs keep moving if no one responds. Works with freeform, choice, and interview modes.
Stall & per-node guards
A stall_timeout in defaults: is enforced by the budget guard to halt runs that stop making progress. Per-node max_cost_usd and no_progress_turns cap individual nodes, emitting EventNodeCostLimitExceeded / EventNodeNoProgressDetected.
Manager loops in .dip
Declare stack.manager_loop supervisors directly via ir.NodeManagerLoop. Six flat attrs — no DOT escape hatch. Snippet below.
Commit-only fs-jail
Bound a node’s file writes with writable_paths (native Landlock fs-jail) plus params: commit_only: true to keep it from authoring source. With writable_paths_mode: prefer (#648) it is enforced wherever Landlock is available and runs unjailed with a recorded warning on macOS / Linux < 6.2 instead of refusing. No shipped built-in uses it today: build_product’s FinalCommit became a deterministic tool node in #656, and its failure routes to AbortRun.
manager_loop Supervise
label: "Watch build attempts"
subgraph_ref: "subgraphs/build.dip"
poll_interval: 30s
max_cycles: 10
stop_condition: "stack.child.status = success"
steer_condition: "stack.child.cycles > 3"
steer_context: "hint=try-alternate-plan,priority=high"Backend selection is per-pipeline or per-node:
tracker --backend claude-code build_product flips globally; per-node
backend: claude-code attrs win over the global flag. backend: auto
(used by explain and quickfix) picks Claude Code when
claude is installed, else an API key; an explicit --backend wins
over it. All six built-in workflows work with every backend, except that
explain's read-only node refuses ACP.
Pipeline testing
Every gate’s routing is tested with dippin simulation tests — scenario
overrides inject conditions, assertions verify the routing path. No LLM calls.
build_product’s 52 scenarios cover 95 of its 96 edges (the review
fan-out’s failure edge can’t be simulated), and make dippin-test
runs every suite in pre-commit and CI.
{
"name": "milestone escalation default — mark done continues build",
"scenario": {
"EnsureEnv.tool_marker": "env-ready",
"TestMilestone.tool_stdout": "__ROUTE_ESCALATE__",
"TestMilestone.outcome": "fail"
},
"expect": {
"immediately_after": {"EscalateMilestone": "MarkMilestoneDone", "MarkMilestoneDone": "PickNextMilestone"}
}
}dippin test examples/build_product.dip
# 52 tests: 52 passed, 0 failedFor the generated code a build workflow produces, tracker verify-tests [dir] [--race]
v0.54.0 is a milestone-gate fidelity check: it flags Go test bodies that are
duplicated (byte-for-byte or literal-only differences) so a copied “distinct” test can't hand out
false coverage credit, and with --race runs go test -race ./... to catch a suite
that passes only by timing luck. Exits 1 on a finding — drop it into a
VerifyMilestone tool node. The race pass is opt-in and Go-only (skipped, not failed, when
there is no go.mod/go.work).