# df12-build user guide `df12-build` drives a df12-house GIST roadmap forward with a parallel [Open Dynamic Workflows (ODW)](https://github.com/xz1220/open-dynamic-workflows) workflow. It plans, reviews, implements, gates, integrates, audits, and files remediation work through isolated worker branches. Use it only for projects that already have a roadmap, design documentation, `AGENTS.md`, repository gates, and the df12 skill/toolchain installed. ## Workflow at a glance Three sequence diagrams sketch the moving parts an operator works around: how the shipped workflow artefact is built, how a fresh launch recovers surviving branches, and how a single task moves from plan to integration. Each diagram is followed by a text description that conveys the same sequence. Figure 1 shows how the single-file workflow artefact is produced and kept honest. ```mermaid sequenceDiagram participant Makefile participant scripts/build-workflow.mjs participant workflows/df12-build-odw.js Makefile->>scripts/build-workflow.mjs: run workflow-build scripts/build-workflow.mjs->>workflows/df12-build-odw.js: regenerate artefact Makefile->>scripts/build-workflow.mjs: run workflow-freshness ``` *Figure 1 — the build pipeline.* `make workflow-build` runs `scripts/build-workflow.mjs`, which regenerates the committed single-file artefact `workflows/df12-build-odw.js` from the module tree. `make workflow-freshness` then re-runs the build and fails if the committed artefact differs, so a stale artefact can never land. Figure 2 shows fresh-run recovery of surviving task branches. ```mermaid sequenceDiagram participant RecoveryDiscovery participant RecoveryDecision participant Main RecoveryDiscovery->>RecoveryDecision: candidate + evidence RecoveryDecision-->>Main: resume or report Main->>RecoveryDecision: continue-mode dispatch ``` *Figure 2 — fresh-run recovery.* Recovery discovery hands each surviving branch's candidate record and host-collected git evidence to the recovery decision. The decision returns either an eligible branch to resume or a report-only result to the main loop; in continue mode, the main loop asks the decision which stage to dispatch next from the committed ExecPlan state. Figure 3 shows how a single task moves from plan to integration. ```mermaid sequenceDiagram participant runTask participant runPlanDesignLoop participant runImplementationStage participant runDualReviewAndIntegration runTask->>runPlanDesignLoop: approve ExecPlan runPlanDesignLoop->>runImplementationStage: validated plan runImplementationStage->>runDualReviewAndIntegration: gates-green implementation runDualReviewAndIntegration-->>runTask: integrate or halt ``` *Figure 3 — the per-task pipeline.* `runTask` drives the plan and design-review loop until the ExecPlan is approved, hands the validated plan to the implementation stage, and that stage passes gates-green work to dual review and integration. The review-and-integration stage either integrates the branch through the merge lock or halts it for the operator. ## Launch model Current ODW launches use a `.workshop` sidecar outside the target project's Git worktree. Do not launch a long-running workshop from `.claude/`, `/tmp`, the project source tree, or a workflow-owned `...worktrees/roadmap-*` worktree. Those locations can be cleaned, switched, or removed while the workshop is still recoverable. The sidecar is durable run-control state. The target repository remains the source of truth for product changes, and `origin/` remains the recovery point for fresh restarts. ```bash PROJECT=/data/leynos/Projects/example-project RUN_ID="$(date -u +%Y%m%dT%H%M%SZ)-$$" SIDECAR="${PROJECT}.workshop/df12-build-${RUN_ID}" mkdir -p "$SIDECAR" ``` ## Sidecar artefacts Keep these files together in the sidecar: - `df12-build-odw.js`: the copied workflow script that the live run executes. - `odw.config.json`: the ODW runtime, adapter, model, workspace, and permission configuration for the run. - `args.json`: the project-specific workflow arguments. - `operator-notes.md`: the run id, launch command, local sidecar patches, validation notes, health checks, failures, and operator decisions. Set `concurrency` to `16` in `odw.config.json` for normal Codex and Claude Code workshops. That leaves room for an eight-task worker pool, four planning-stage agents, four build-stage agents, and review, triage, audit, or assessment slack. Keep `maxAgents` high (such as the ODW default of `1000`) because it is the per-run dispatch guard rather than the live process-pool size. Set the adapter `timeout` with the CodeRabbit flow in mind. With the default host-run CodeRabbit review (`coderabbitHostReview`, see the configuration list), agents never wait on CodeRabbit — the host absorbs rate-limit backoff in its own wall-clock — so the adapter timeout only needs to cover honest stage work; 4500–5400 seconds (75–90 minutes) is generous, and a longer silent stream is a hung connection, not progress. Only when `coderabbitHostReview=false` do implementation agents wait through 45–90 minute CodeRabbit backoffs with `vsleep` themselves, and then the timeout must be at least `21600` seconds to avoid killing a healthy task mid-backoff. Make sure every adapter named by `args.json` exists in `odw.config.json` or in ODW's built-in adapter set. The checked-in ODW workflow now defaults planning and review judgement to the `claude` adapter, so a Codex-only sidecar config must either add a `claude` adapter or explicitly route those stages back to Codex. Minimal sidecar `odw.config.json` shape for the Claude/Codex split: ```json { "defaultAdapter": "codex-medium", "concurrency": 16, "maxAgents": 1000, "workspaceMode": "inplace", "timeout": 5400, "schemaRetries": 2, "runsRoot": "/abs/path/to/example-project.workshop/df12-build-RUN/runs", "workflowsRoot": "~/.odw/workflows", "claudeJobsScope": "project", "adapters": { "claude": { "label": "Claude Code", "command": [ "claude", "--print", "--permission-mode", "acceptEdits", "--no-session-persistence" ], "stdin": "{prompt}", "flags": { "model": ["--model"] } }, "codex-medium": { "label": "Codex GPT 5.5 medium", "timeout": 3600, "command": [ "codex", "--ask-for-approval", "never", "exec", "--skip-git-repo-check", "--sandbox", "danger-full-access", "-c", "model_reasoning_effort=\"medium\"", "--cd", "{workspace}", "-" ], "stdin": "{prompt}", "flags": { "model": ["--model"] } }, "codex-high": { "label": "Codex GPT 5.5 high", "command": [ "codex", "--ask-for-approval", "never", "exec", "--skip-git-repo-check", "--sandbox", "danger-full-access", "-c", "model_reasoning_effort=\"high\"", "--cd", "{workspace}", "-" ], "stdin": "{prompt}", "flags": { "model": ["--model"] } } } } ``` ### Inspectable logs in the sidecar Point both log sinks at the sidecar so a run's agent transcripts and CodeRabbit findings are durably inspectable next to the run, without touching workflow behaviour — both are out-of-band sinks outside the project Git worktree, so they never enter a diff, trip `workflow-freshness`, or affect a gate: - **Agent logs** — set `runsRoot` (in `odw.config.json`) to an absolute path inside the run's sidecar, e.g. `"$SIDECAR/runs"`. ODW writes each run's durable artefacts there: `events.jsonl` (an ordered stream with `agent_started`/`agent_finished` per `agent()` call, tagged by adapter, label, and phase), `result.json` (the final return, including every `reviewRounds`, `assessments`, host-gate result, and CodeRabbit summary), and `error.json`. This is entirely ODW's domain — no workflow involvement. Regenerate the value per run, or use a shared `~/.odw/runs` for a single pool; the sidecar keeps each run's logs beside its config and notes. - **CodeRabbit findings** — set `coderabbitFindingsFile` (in `args.json`) to a sidecar JSONL path, e.g. `"$SIDECAR/coderabbit-findings.jsonl"`. Every parsed finding (timestamp, task label, severity, file, comment, codegen instructions, suggestion count) is appended best-effort: a bad path or full disk degrades logging with a warning and never fails a task. Patch the sidecar copy only to recover or tune a live workshop. Record the patch in `operator-notes.md`, validate it there, then promote the proven change back to the `df12-build` repository through a normal branch. ## Starting a run Copy the checked-in ODW workflow into the sidecar, then launch it from the sidecar while using the target project as `--source`. ```bash cp /path/to/df12-build/workflows/df12-build-odw.js \ "$SIDECAR/df12-build-odw.js" odw run "$SIDECAR/df12-build-odw.js" \ --source "$PROJECT" \ --config "$SIDECAR/odw.config.json" \ --args @"$SIDECAR/args.json" ``` Use an absolute or fully expanded sidecar path for the workflow script. When `--source` is present, ODW anchors relative workflow paths under the source project, not under the shell's current working directory. Start normal workshop runs in the background. Supervise them with `odw status`, `odw logs`, `odw result`, and the ODW dashboard. Keep `operator-notes.md` current enough that another operator can continue after context compaction. When adopting a newer checked-in workflow into an existing sidecar, audit `args.json` before relaunching. Older sidecars may still carry Codex-only `planAdapter`, `reviewAdapter`, or `assessmentAdapter` overrides, and those overrides deliberately win over the workflow defaults. ## Monitoring runs `odw status`, `odw logs`, and the dashboard remain the primary supervision surface. Operator scripts in `scripts/` add workshop-oriented views over ODW run directories, Git branch movement, and sibling worktree filesystem activity. `scripts/odw-list-runs` tabulates runs from the ODW runs root, showing the source project, status, last update, run id, and workflow name. It defaults to running runs; filters widen or narrow the view: ```bash scripts/odw-list-runs # running runs only scripts/odw-list-runs --all --limit 20 # every status, newest first scripts/odw-list-runs -s failed -s stopped # explicit statuses scripts/odw-list-runs --source my-project # substring match on source ``` `scripts/odw-watch` tails events for every *running* run whose metadata records a given source directory, printing recent history and then following new events, discovering newly started runs as it polls: ```bash scripts/odw-watch "$PROJECT" -n 20 # last 20 events, then follow scripts/odw-watch "$PROJECT" --poll 2.0 # slower discovery/tail cadence ``` Both ODW scripts tolerate live writes (a torn `status.json` or event line is re-read on the next pass) and warn on stderr when run state is genuinely malformed. Both read `--runs-dir` (defaulting to `~/.odw/runs`), so point them at a sidecar-local `runsRoot` when a workshop overrides it. `scripts/git-commit-feed` prints a live commit feed for local branches in a Git repository. It prints an initial backlog, then follows branch-tip changes: ```bash scripts/git-commit-feed "$PROJECT" # latest 10 commits, then follow scripts/git-commit-feed "$PROJECT" --remotes # include remote-tracking refs scripts/git-commit-feed "$PROJECT" -n 0 # follow-only ``` `scripts/blinkentrees` opens a Textual dashboard over sibling Git worktrees, using Linux inotify to show file activity per worktree. Run it from the parent directory that contains the worktrees, or pass that directory explicitly: ```bash scripts/blinkentrees --pattern 'roadmap-*' . scripts/blinkentrees --any-matching-dir /path/to/worktrees ``` A task's post-merge audit and a settled step's remediation triage each create their own throwaway inspection worktree, which appears in `blinkentrees` alongside the `roadmap-*` build worktrees. These inspection worktrees are built with the same verified sequence the build worktrees use: fetch `origin/`, create with `git donkey ` (the configured base is passed explicitly, because git donkey's no-argument default is always `main`), then `git reset --hard origin/` inside the new worktree and re-verify its base sha. So audit and triage always inspect the current `origin/` and can never silently root on a stale local base. If an audit or triage agent reports a "based on a stale commit" style failure, that sequence is where to look. ## Roadmap format `df12-build` expects the target roadmap to follow the df12-house GIST shape: Goals -> Ideas -> Steps -> Tasks. New projects should use this as the baseline format before launching a workshop. Older project roadmaps may need grooming first, because the ODW workflow now uses a deterministic selector rather than a model-based selector. The roadmap path defaults to `docs/roadmap.md`. Selection reads the canonical roadmap from `origin/:`, not from a worker branch or a local working-tree edit. Keep the integration branch current before launching or relaunching a run. At minimum, a runnable roadmap task must be a Markdown checkbox line with a dotted numeric id: ```markdown - [ ] 1.2.3. Add parser diagnostics. - Success: Parser failures include a stable diagnostic code and source span. ``` The selector recognizes checked and unchecked task lines in this form: ```markdown - [ ] 1.2.3. Task title. - [x] 1.2.4. Completed task title. ``` Use dependency lines directly under the task body when a task must wait for other roadmap ids: ```markdown - [ ] 1.2.5. Wire diagnostics into the CLI. - Requires 1.2.3 and 1.2.4. - Success: CLI output includes parser diagnostic codes in error reports. ``` Step ranges are also accepted in `Requires` lines: ```markdown - [ ] 1.6.1. Stabilize the integration surface. - Requires steps 1.2 - 1.5. - Success: The integration API is documented and covered by tests. ``` The deterministic selector treats a task as unblocked when all of these are true: - The task checkbox is unchecked. - Every id named by its `Requires` lines is complete. - The task has not already been processed, left manual-merge-ready, marked as a dry run, or spawned in the current workflow run. A task is complete when its own checkbox is checked and every nested addendum subtask below it is also checked. The selector also treats a prefix id as complete when every task under that prefix is complete. For example, if every task under `1.2.*` is complete, then `1.2` can satisfy a later `Requires 1.2` dependency. Completed tasks may carry nested unchecked addendum subtasks. These are used for small follow-up corrections that do not need a full plan and review cycle: ```markdown - [x] 1.2.8. Implement the parser state machine. - Success: The parser accepts valid fixtures and rejects invalid fixtures. - [ ] 1.2.8.1. Addendum (from review:high). Cover empty-input recovery. Lightweight addendum pass. ``` When an addendum subtask is open under a completed parent, the workflow selects an addendum pass for the parent task and scopes the implementation to the open nested ids. Selection is deliberately simple and reproducible: - Build all normal and addendum candidates from the canonical roadmap. - Exclude blocked or already-taken work. - Apply `taskId` if one was supplied. - Sort remaining candidates by roadmap line number. - Select the first candidate. The workflow parses only the mechanical parts needed for scheduling: checkbox lines, dotted ids, `Requires` lines, step ranges, and nested addendum subtasks. The broader GIST discipline is still required for useful planning and triage: each phase should carry an `Idea:`, each step should state the hypothesis it answers, and each task should include a clear `Success:` criterion. Treat this section as the baseline contract for future roadmap tooling. A roadmap editor or linter should preserve these parseable forms, verify that `Requires` references resolve, and flag malformed ids or dependency lines before a long-running workshop starts. ## Workflow arguments Set project-specific behaviour in `args.json`. The workflow also has matching top-of-file defaults, but the sidecar `args.json` is the normal retuning point for ODW launches. Common arguments: - `base`: integration branch. Defaults to `main`. - `roadmap`: roadmap path. Defaults to `docs/roadmap.md`. - `designDocs`: design document and ADR locations cited in planner prompts. - `researchNote`: optional external-library research pointer, such as a vendored source path. - `projectRoot`: target-project checkout to `chdir` into before the workflow creates worktrees. Use this when launching a copied workflow from a sidecar. - `searchBackend`: canonical code-search backend for prompt guidance. Supported values are `grepai` and `memtrace`. Defaults to `grepai`, or to `memtrace` when `memtraceRepoId` is set. - `grepaiWorkspace`: GrepAI workspace name. Defaults to `Projects`. - `grepaiProject`: canonical main-branch GrepAI project name. Set this when the ODW source path or worker worktree path would make `$(get-project)` resolve to the wrong project. - `memtraceRepoId`: canonical Memtrace repository id. Set this, or set `searchBackend` to `memtrace`, when GrepAI is unavailable on the host. - `coderabbitReviewCommand`: CodeRabbit command used in implementation prompts. Defaults to `coderabbit review --agent`. - `maxParallel`: task worker-pool width. Defaults to `8` unless `taskId` is set. - `maxPlanningParallel`: concurrent planning-stage agents. Defaults to `4`. - `maxBuildParallel`: concurrent build-stage agents. Defaults to `4`. - `maxTasks`: maximum roadmap tasks for one run. - `maxDesignRounds`: planning and design-review exchange cap. Defaults to `4`. - `maxReviewRounds`: implementation review/fix exchange cap. Defaults to `3`. - `commitGates`: ordered list of deterministic gate commands every task, addendum, fix, and remediation agent must run before declaring work green. Defaults to `["make all"]`. The run result echoes the effective list so operators can audit reported gate greenness against it; agents are told never to assume `make all` aggregates the gates a project names in `AGENTS.md`. - `hostCommitGates`: when `true` (the default), the workflow host re-runs the `commitGates` commands itself against each branch's committed HEAD before review and integration, so a `gatesGreen` claim is verified rather than trusted. Set `false` to restore the trust-the-agent flow. - `commitGateTimeoutSeconds`: per-command timeout for host-run gates. Defaults to `3600`; a gate that exceeds it is killed and reported as a failure with the timeout named in the evidence. - `stageAttempts`: total attempts per stage agent when the previous attempt died on an infrastructure fault (an ODW adapter timeout or crash, or schema-retry exhaustion). Defaults to `2`. Product failures are never retried, and the host never re-dispatches a faulted integration stage: a crash between the squash push and the agent's return can leave a hidden success already landed on `origin/`, which the host cannot detect, so repeating the stage risks a double merge. (The integration agent still redoes its own squash idempotently on a non-fast-forward push rejection within a single turn — see the recovery model.) - `perWorkItemBuild`: when `true` (the default), the workflow host reads the approved ExecPlan's `## Progress` checklist and dispatches one builder turn per unticked work item, verifying committed progress after every turn. Plans without a Progress checklist fall back to the single-turn build automatically; set `false` to force the single-turn build for every task. - `maxWorkItemRounds`: builder turns per task before the work-item loop fails closed. Defaults to `16`. - `coderabbitHostReview`: when `true` (the default), the workflow host runs `coderabbit review --agent` against each task's committed work instead of asking agents to babysit CodeRabbit. Rate-limit backoff is absorbed as host wall-clock (zero agent tokens), and blocking findings feed the fix rounds. Set `false` to restore the legacy agent-run flow. - `hostGatesBetweenWorkItems`: when `true` (the default), and when both `hostCommitGates` and `perWorkItemBuild` are on, the host re-runs the commit gates after each committed work item — before the between-item CodeRabbit review — so a committed work item whose gates are actually red is caught at the item boundary instead of only at the dual-review stage. A red gate drives a bounded fix loop; if it cannot be made green the work item fails. Set `false` to verify gates only at the dual-review boundary (cheaper: one gate run per review round rather than one per work item). - `csCheck`: when `true` (the default), the host runs a CodeScene code-health check on the committed changed files as a deterministic gate AFTER the commit gates and BEFORE CodeRabbit (both free checks precede the quota-limited CodeRabbit and the token-spending reviewer agents). A regression drives a bounded fix round; the build agent clears it by refactoring or, only where refactoring would be deleterious, suppresses the specific smell with a justified `@codescene(disable:"...")` comment. The check skips gracefully when its binary is absent, like `make verify-modules` without Dafny. Set `false` to disable it. - `csCheckCommand`: the command the CodeScene check runs in the worktree. Defaults to `cs-check-changed` (an operator-provided wrapper); override it with the exact invocation, e.g. `cs check --changed --base main`. - `coderabbitBetweenWorkItems`: when `true` (the default), and when both `coderabbitHostReview` and `perWorkItemBuild` are on, the host runs a CodeRabbit review after each committed work item — a deterministic gate between build turns, after the host gates — rather than only once after the whole implementation stage. Blocking findings drive a bounded fix loop; if they cannot be cleared the work item fails, and if CodeRabbit stays rate-limited or errors after its retries the task halts for assessment instead of continuing unreviewed. Set `false` to review only once at the end of the implementation stage. - `coderabbitAttempts`: total host review attempts when CodeRabbit rate limits. Defaults to `3`. - `coderabbitBackoffMinutes`: `[low, high]` range for the deterministic backoff wait between rate-limited attempts. Defaults to `[45, 90]`. - `coderabbitFindingsFile`: optional absolute path to an append-only JSONL file recording every CodeRabbit finding (timestamp, task, severity, file, comment). Point it at a sidecar file to accumulate findings across runs and tune deterministic lint rules from the recurring classes. - `writeProbeEffort`: reasoning effort for the once-per-run write-preflight probe (write an exact token to an exact path — no reasoning). Defaults to `minimal`. The probe keeps the plan/build ADAPTER but never inherits `planModel`/`buildModel`. - `writeProbeModelByAdapter`: optional `{ "": "" }` map to run the probe on a cheaper model per adapter (adapter name lowercased). Defaults to Claude Haiku (`claude-haiku-4-5`) and GPT-5.6 Luna (`gpt-5.6-luna`) for the default planning and build adapters respectively. - `assessmentModel`: model for the report-only partial-branch assessment. Defaults to a medium model (`claude-sonnet-5`) rather than inheriting the Opus-class review model, because a deterministic fast-classifier already handles the clear cases (empty branch, evidence-collection failure) with zero tokens and only genuinely ambiguous branches reach the model. - `assessmentEscalationModel`: the stronger model used for a strong adopt-complete candidate (a branch that committed an ExecPlan). Defaults to the review model. - `triageModel`: model for remediation triage. Defaults to a medium model (`gpt-5.6-sol`); a deterministic pre-pass collapses exact-duplicate proposals before the agent runs. - `triageEffort`: reasoning effort for remediation triage. Defaults to `medium`. - `triageEscalationModel`: the stronger model used when the deduped proposals span more than one audit/review source (potential cross-phase or conflicting routing). Defaults to the same `gpt-5.6-sol` model. - `taskId`: run exactly one roadmap task. - `dryRun`: when `true`, a fresh task stops before worktree creation — and so before planning, review, implementation, integration, or document writes — making it a read-only validation path that mutates no git state. (Recovery and continue-mode resume keep their own dry-run handling over pre-existing worktrees.) - `autoMerge`: when `false`, leave reviewed task branches for manual integration. - `documentAudit`: when `false`, return audit findings without writing audit files. - `assessPartialBranches`: when `false`, skip the report-only assessment of failed or halted task branches. Defaults to enabled. - `resumePartialBranches`: when `true`, discover surviving `roadmap-*` branches on launch and assess them before normal roadmap selection. Defaults to `false`; the default workflow behaviour is unchanged unless an operator opts in. - `resumeMode`: the maximum recovery action for discovered branches. `assess` (the default) reports only. `review` may additionally route clean, committed, task-scoped `adopt-complete` branches with validation evidence into the ordinary review and integration path. `continue` dispatches each surviving branch deterministically from its committed ExecPlan status, with no judgement agent. Any other value fails fast at launch. - `resumeTaskId`: limit recovery discovery to one roadmap id. This is separate from `taskId`, which selects normal roadmap work. - `resumeMaxCandidates`: bound on recovery candidates per run. Defaults to `4`; excess candidates are reported as skipped with reason `candidate-cap`. - `worktreeWritePreflight`: when `false`, skip the once-per-run probe that proves the planning and build adapters can write into sibling task worktrees. Defaults to enabled; a failed probe fails the task at stage `worktree-write` as an environment fault. - `buildAdapter` and `buildModel`: adapter and model for worktree creation, implementation, integration, and remediation agents. - `planAdapter` and `planModel`: adapter and model for planning agents. - `reviewAdapter` and `reviewModel`: adapter and model for design review, code review, expert review, and addendum fallback review agents. - `auditAdapter`, `auditModel`, and `auditEffort`: adapter, model, and effort for post-merge audits. Defaults to Claude Code, `claude-sonnet-5`, and `medium`. - `triageAdapter` and `triageModel`: adapter and model for remediation triage (routing review and audit proposals onto roadmap lanes). Defaults are `codex` and `gpt-5.6-sol`. - `assessmentAdapter` and `assessmentModel`: adapter and model for partial branch assessment. `assessmentAdapter` defaults to the review adapter, while `assessmentModel` independently defaults to `claude-sonnet-5`. Current defaults deliberately split execution and judgement. Build, implementation, and integration use GPT-5.6 Terra through the medium-effort Codex adapter; triage uses GPT-5.6 Sol at medium effort. Planning and review judgement default to Claude Code with `claude-opus-4-8`. That means the plan stage, design review, code review, expert review, and addendum fallback review use the `reviewAdapter` or `planAdapter` Claude routing unless `args.json` overrides them. Post-merge audit uses Claude Sonnet 5 at medium effort. Set `assessmentAdapter` explicitly when partial-branch assessment should stay on Codex instead of inheriting the review adapter. Example `args.json`: ```json { "base": "main", "roadmap": "docs/roadmap.md", "projectRoot": "/home/example/Projects/example-project", "designDocs": "docs/architecture.md, docs/adr-001-adopt-odw-sidecar-launches.md, docs/users-guide.md, docs/developers-guide.md", "searchBackend": "grepai", "grepaiWorkspace": "Projects", "grepaiProject": "example-project", "maxParallel": 8, "maxPlanningParallel": 4, "maxBuildParallel": 4, "maxTasks": 12, "coderabbitFindingsFile": "/home/example/Projects/example-project.workshop/df12-build-run/coderabbit-findings.jsonl", "buildAdapter": "codex-medium", "buildModel": "gpt-5.6-terra", "planAdapter": "claude", "planModel": "claude-opus-4-8", "assessmentAdapter": "codex-high", "assessmentModel": "gpt-5.5", "triageAdapter": "codex", "triageModel": "gpt-5.6-sol", "triageEffort": "medium", "reviewAdapter": "claude", "reviewModel": "claude-opus-4-8", "auditAdapter": "claude", "auditModel": "claude-sonnet-5", "auditEffort": "medium" } ``` ## Host-run CodeRabbit review By default the workflow host — not the task agents — runs `coderabbit review --agent --type committed` against each task branch: once per dual-review round (alongside the code and expert reviewers) and once per addendum implementation. Because only committed changes are reviewed, the ExecPlan durability contract doubles as the review contract. The host parses the CLI's structured findings; `critical` and `major` severities join the reviewers' blocking items and drive the ordinary fix rounds, while lower severities are captured without gating integration. Rate limits are absorbed by the host: a rate-limited review waits a deterministic 45–90 minutes (`coderabbitBackoffMinutes`) and retries, up to `coderabbitAttempts` total attempts, costing wall-clock but zero agent tokens. A rate limit that outlives every attempt — or a CLI fault — defers the review with a documented `openIssues` entry on the task result instead of blocking integration; the dual reviewers remain decisive. A CodeRabbit authentication failure halts the task as `fatal-auth`. The run result's `coderabbit` object reports the effective configuration and bounded counters (reviews run, findings by severity, rate-limited runs, deferred reviews). When `coderabbitFindingsFile` is set, every finding is also appended as JSONL for cross-run linter tuning. ## Per-work-item builds By default the build is host-driven, one work item at a time. The planner records the plan's work items as `- [ ] WI-: ` checklist lines in the ExecPlan's `## Progress` section, and after design approval the host loops: read the committed checklist, dispatch a builder turn scoped to exactly the first unticked item, then verify that the turn left the worktree fully committed and moved the committed checklist forward. A turn that returns `ok` without committing a tick is bounced once with the defect named in the next prompt; two consecutive no-progress turns fail the task. The loop is bounded by `maxWorkItemRounds`, and the committed checklist — not the agent's say-so — decides when the build is done. Small turns change the failure economics: each builder turn does one work item's worth of code, tests, docs, gates, and one atomic commit, so the ODW build adapter can sit on a tight timeout (roughly 3600 seconds) and a hung stream costs at most one work item plus a warm `stageAttempts` retry from the committed ExecPlan — not a whole task. Legacy plans whose Progress section is prose ticks rather than work items still work: the loop dispatches "the first unticked item" by its text, and a plan with no checklist at all falls back to the single-turn build. The run result's `workItemBuild` object reports the effective configuration. Work-item turns appear in the events as `implement: wi` labels. ## Host-run commit gates By default the workflow host also re-runs the deterministic `commitGates` commands itself — a `gatesGreen` claim from an agent is verified, never trusted. The gates run at the start of every dual-review round (before any reviewer agent spends tokens; a red branch goes straight to a fix round carrying the host's log evidence) and once per addendum implementation (addenda have no fix rounds, so an unreproducible green claim fails the addendum outright). Gate runs are serialized across the whole worker pool so sequential execution benefits from the target project's build caching, and each command's full output is streamed to a log in a secure per-run directory (`/tmp/df12-gates-XXXXXX/gate---N.out`, created with mode `0700` and opened exclusively without following symlinks) with a bounded tail quoted in the failure evidence. A command that exceeds `commitGateTimeoutSeconds` is killed and reported as a failure. The run result's `hostGates` object reports the configuration and bounded counters (gate runs, failures); per-round pass/fail detail appears in each failed task's `reviewRounds[].hostGates`. ## Recovery model Do not try to resume a failed workflow from transient cache state. Treat `origin/` as the source of truth, inspect the result, clean up or repair the target project as needed, and relaunch from the sidecar. The workflow re-selects unblocked roadmap work from the current roadmap state. When a normal task or addendum fails or halts after its worktree exists, the ODW workflow runs a read-only assessment of the surviving task branch unless `assessPartialBranches=false`. The per-task result may include an `assessment` object and the top-level result includes an `assessments` summary array. The classification is one of: - `adopt-complete`: the branch appears to satisfy the task and can continue through the ordinary review and integration path after gates are verified. - `adopt-partial`: the branch contains a coherent useful slice, but the roadmap task must remain unchecked. - `continue-manual`: the branch needs operator judgement before any merge. - `discard`: the branch is stale, unsafe, incoherent, or too incomplete to keep. Assessment is report-only. It never marks roadmap checkboxes, pushes, merges, or cherry-picks. Use it to decide whether to preserve, manually finish, park, or discard the branch before relaunching from `origin/`. After an `adopt-partial` or `continue-manual` verdict — and also after an infrastructure fault such as schema-retry exhaustion — the workflow commits any dirty `docs/execplans/*.md` artefacts onto the task branch so they survive worktree cleanup. This is artefact salvage. It never merges, pushes, or ticks a roadmap checkbox; it commits only under a deterministic machine identity (`df12-build`). Paths outside the `docs/execplans/` tree, symlinks, and paths that escape the worktree are all rejected before the commit. Salvage does not run for `adopt-complete` (which proceeds through the ordinary path) or `discard` (thrown away); it also skips when host evidence collection failed and is therefore untrustworthy (the deterministic `continue-manual` from a collection-error), or when no worktree path is present in the assessment evidence. The per-task result carries a `result.salvage` field (`{ classification, committed, skipped, sha, detail }`) for every branch where salvage ran or was skipped; the top-level run result includes a `salvages` summary array and the summary string appends `| salvaged artefacts on N branch(es)` when N > 0. Salvage runs only when partial-branch assessment is enabled (`assessPartialBranches=true`), the same switch that governs assessment; it does not run when that setting is disabled. Auth failures, provider outages such as `429`, `500`, or `529`, worktree-creation failures, dry runs, successful tasks, and manual-merge-ready branches are not assessed. Provider outages also suppress the final remediation flush, so transient adapter failures do not create roadmap work. Infrastructure faults are classified separately from product failures. When a stage agent's process dies — an ODW adapter timeout or crash, or schema-retry exhaustion — the failure carries no evidence about the task branch, so the workflow retries the stage agent in place up to `stageAttempts` total attempts. A persistent fault terminates the task with status `infra-fault` rather than `failed`: no assessment agent is spawned, remediation triage writes are skipped (as with provider faults), and the halt detail directs the operator to relaunch with `resumePartialBranches=true` and `resumeMode="continue"`. Integration is the exception: a fault there is never retried, because a hidden-success first attempt may already have pushed — inspect `origin/` and the roadmap before relaunching. The run result's `faultMetrics` object counts retries and terminal faults per class (`infraRetries`, `infraFaults`, `providerFaults`, `authFaults`). That host-level caution is distinct from the integration agent's own retry loop, which is idempotent by construction. Because sibling tasks merge through a single merge lock, `origin/` can advance between a task's rebase and its squash push. The agent lands each squash on a throwaway branch created with `git switch --discard-changes -C integrate- origin/`: the `-C` force-resets `integrate-` onto the freshly fetched base whether or not the branch already exists, and `--discard-changes` restores the index and working tree to that base, throwing away any half-finished squash a prior attempt left staged. (The earlier `git switch -c` form instead failed with `a branch named 'integrate-' already exists` the moment a first attempt had created the branch.) So when the push is rejected non-fast-forward, the agent re-fetches, re-rebases the task branch onto the new `origin/`, re-runs that reset, and retries the push — with no manual cleanup, no collision with the branch the previous attempt left behind, and no stale squash carried forward. It retries until the push lands. The host simply does not extend that idempotence across a process crash, where a hidden success may already have merged. Separately from that in-agent retry loop, the host validates the integration agent's report before counting a task done. All five fields — `ok`, `rebased`, `squashMerged`, `pushed`, and `roadmapMarkedDone` — must be truthy. A branch that was squash-merged and pushed but never rebased onto `origin/` (so `rebased` is false or absent) halts the task at `stage: integrate`. The `detail` field reports the integration agent's `conflicts` text or its `summary`, whichever is set first; only when both are absent does it fall back to the generic `'integration incomplete (need ok+rebased+squashMerged+pushed+roadmapMarkedDone)'`. Inspect the halted task result's `detail` field, rebase the branch manually if it is salvageable, and relaunch; otherwise discard the branch and relaunch from `origin/`. Addendum implementations have one extra recovery state. If an addendum agent reports all work items complete, green gates, and no open issues, but fails to set the strict `ok=true` schema field, the workflow returns `manual-merge-ready` instead of treating the branch as ordinary failed work. That preserves throughput without auto-merging ambiguous output: an operator must rerun gates, confirm review evidence, reconcile the roadmap checkbox, and then integrate or discard the branch. ### Fresh-run recovery A fresh launch can also discover branches that survived an earlier failed run. Set `resumePartialBranches=true` and choose the maximum action with `resumeMode` before launching: - **Assess-only** (`resumeMode="assess"`, the default): the workflow maps surviving `roadmap-*` branches back to roadmap ids, assesses each candidate with the same ADR 002 contract used for in-run failures, and reports the outcome in a top-level `recovery` object. Nothing is merged, pushed, ticked, or deleted, and `processed` is unchanged. Use this mode first: it guarantees the target project is not written to, though recovered branch content still flows to the assessment adapter (see the security guide's data-flow and prompt-injection notes). - **Review-mode resume** (`resumeMode="review"`): in addition to assessment, a candidate classified `adopt-complete` that is clean, committed, task-scoped, and carries validation evidence re-enters the ordinary dual review and merge-lock integration path without re-running implementation. Everything else is still report-only, and an `adopt-complete` verdict with incomplete evidence is downgraded to `continue-manual` with an explicit skip reason (`dirty-worktree`, `no-committed-work`, `not-task-scoped`, `missing-validation-evidence`, `evidence-collection-error`, or `addendum-branch`). Blocking evidence gaps (`missingEvidence`) still trigger that downgrade, but advisory residual risk (`residualRisk`) never does: it is non-blocking and is instead carried forward into the resumed dual review and integration prompts as an explicit, clearly delimited advisory section for the reviewer or integrator to weigh. Review-mode resume mutates the target project exactly as ordinary integration does, so grant it the same permissions and trust. - **Continue-mode resume** (`resumeMode="continue"`): no judgement agent at all. The workflow collects host git evidence and reads the committed ExecPlan `Status:` line, then dispatches deterministically: `DRAFT` (or a missing plan) re-enters planning, `APPROVED` or `IN PROGRESS` re-enters implementation, `COMPLETE` re-enters the dual review, and `BLOCKED` is reported. The downstream gates and reviewers are the judgement. Dirty worktrees, addendum branches, evidence-collection failures, and plans the host cannot read are reported instead of resumed (reasons such as `dirty-worktree`, `plan-blocked`, and `plan-unreadable`). Continue-mode resume mutates the target project exactly as ordinary work does. The `recovery` result object indexes the pass for operators: `candidates`, `assessed`, `resumed`, per-candidate `results` (classification and action), and `skipped` entries with machine-readable reasons (including `unmapped-branch`, `already-complete`, `missing-worktree`, and `candidate-cap` from discovery). Ids with surviving branches are held out of normal selection for the rest of the run, so the pool cannot collide with an existing branch; hoover the branch or resume it before expecting normal selection to rebuild that task. Survivor branches that are still unresolved when the run ends are listed in `recovery.unresolved` (id, branch, last classification, action, and reason), and the run reports `halted: needs-operator-recovery …` instead of a clean stop, so a blocked roadmap frontier is never mistaken for finished work. A fatal auth preflight blocks recovery entirely (`recovery.blocked = "auth-preflight-failed"`), and dry runs never resume. Use the `df12-build-supervisor` skill for the detailed operator playbook: failure-mode diagnosis, orphan worktree cleanup, remediation triage, stash hygiene, and deciding when a roadmap frontier is actually dry. Read `docs/security-and-permissions.md` before granting a workshop write, network, or GitHub access. It names the permissions and external services a run can use, and explains why roadmap, design, audit, and review text must be treated as prompt-injection input rather than trusted control logic.