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.

Start here

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.

Start here

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:

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).

Milestone Builder

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.

graph TB Start([Start]) --> Setup["Setup Workspace"] Setup --> Env["Bootstrap Env
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

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.

# Run it
tracker build_product

# Copy and customize
tracker init build_product
# edit build_product.dip, then:
tracker build_product.dip
Competitive Fan-Out

ask_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.

graph TB Ask{{"What would you like done?"}} --> Explore["Explore Codebase"] Explore --> Spec["Write Spec"] Spec --> Approve{{"Approve Spec?"}} Approve -->|approve| WT["Create Git Worktrees"] subgraph compete ["Competitive Implementation"] WT --> P["Parallel Fan-Out"] P --> C["Claude"] P --> O["OpenAI"] P --> G["Gemini"] C --> J["Fan-In Join"] O --> J G --> J end J --> Crit["Cross-Critique"] Crit --> Pick["Pick Best"] Pick --> Apply["Apply & Commit"] Apply --> Clean["Clean Worktrees"] Clean --> Done([Done])

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_execute
Parallel Streams

build_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.

graph TB Analyze["Analyze Spec
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.

Interview-Driven

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.

graph TB Ask{{"What to review?"}} --> Explore["Explore
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_review

Run 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_product

Auto-approve

Deterministic — no LLM call, always picks the default or first option. Best for CI and pipeline-flow tests.

tracker --auto-approve build_product

Webhook 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_product

Workflow 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 failed

For 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).