Walkthrough

Command reference — every pdca subcommand

← 07 Cross-cutting · Index · next: 09 Configuration reference →

The walkthrough introduces each command where the cycle first needs it. This page lists all of them in one place — first the commands that get an instance rendered, installed and checked, then every pdca subcommand: what each does, its options, what its exit code means, and where the walkthrough explains it. The usage lines are the tool's own --help output at template v0.59.0; pdca <command> --help is always the authority for the version you have installed.

Conventions

  • The command is named per project. cli_name at render time sets the console script (pdca by default; pdca-<slug> if you run several instances on one machine). Before make install, or in CI, every command also runs as PYTHONPATH=src python3 -m pdca_harness.cli <command> ….
  • Every command runs inside a rendered project. Each one loads pdca.toml from the current directory first. No pdca.toml, or an invalid one, is a one-line error and exit 2, never a traceback.
  • Bare pdca is pdca status. The dashboard is the default command.
  • Exit codes are a contract: 0 did what it says; 1 a bundle or a check did not pass, or the command refused to act; 2 bad input (config, an unknown id, an unschedulable graph). pdca flow adds 3 — see below.
  • <id> is a tracker issue id as it appears in results/issue_<id>/. Several commands take none and then act on every bundle that fits.

Getting set up

These run once per instance, or once per machine, before any pdca command. Step 01 walks through them in order with Wyrd's real answers.

Command What it does Covered in
copier copy gh:eduralph/pdca-harness <dir> Renders the template into a new project, asking the copier.yml questions. Use a gh:/https: URL or an absolute path, never a relative one. 01
copier update From inside the rendered project: re-applies a newer template release over your render, keeping your answers and your instance files. Do it in a separate worktree, never under a live flow. 01, 04
make install Bootstraps every tool flow needs, idempotently, then creates .venv/ and installs the console script with pip install -e .. Three tiers: harness-universal tools (git, gh, a pip-capable venv), the leaf CLIs your pdca.toml configures, and your own gate toolchain hook. Re-runs when pdca.toml or the bootstrap scripts change. 01
make install-check The same checks, installing nothing: one OK|MISSING|INSTALLED|FAILED|WARN row per tool. Exit non-zero only if a REQUIRED tool is missing — the CI preflight. 01
scripts/bootstrap-tools.sh [--check] What make install and make install-check call. Ships verbatim from the template; your toolchain goes in scripts/bootstrap-tools.d/*.sh and [install].extra_bootstrap. 01
pwsh -File scripts/install.ps1 Windows: the equivalent of make install plus make setup, where GNU make is not standard. 01
make setup One-time, Claude leaves only: writes the gitignored .claude/settings.local.json granting the interactive leaves read of the sibling workspace and /tmp, so they don't prompt per file. Permissions, not trust — the first interactive pdca flow still asks once to trust the project. 01
pdca doctor [--strict] Reports every prerequisite — derived from pdca.toml plus your [[doctor.checks]] rows — and changes nothing. Run it after make install and whenever a red gate might be a missing tool. Full contract below. 01
make check The fast offline self-test: the driver's unit tests (python3 -m unittest discover -s tests), about a second. 02
make / make test check, then a full driver cycle on a throwaway bundle with stub leaves — init-issue selftest and run selftest under PDCA_LEAVES_MODE=stub. Inspect results/issue_selftest/. 02
pdca flow TOY --rehearse The same orchestration flow uses, entirely stubbed, in .rehearse/: the first command to run once the install is green. 02

The order matters: render, then make install, then pdca doctor, then the offline rehearsal — and only then point a leaf at a real model. If ship_ci_workflow was left on at render, the shipped check-gates.yml runs pdca gates --working-tree on every PR of the instance, the same gate set the driver runs.

Drive the cycle

pdca flow — the front door

usage: pdca flow [-h] [--from-csv FROM_CSV] [--from-briefs FROM_BRIEFS]
                 [--rehearse] [--no-publish] [--no-act] [--by BY]
                 [--lanes LANES] [--max-passes MAX_PASSES] [--auto-iterate]
                 [--no-inhibit]
                 [issue_ids ...]

Runs the whole cycle — Plan → Do → Check (gates → review → sign-off → publish) → Act — for one issue, a batch, or a batch planned from a tracker export. One id is a single cycle; several ids run as dependency waves, briefing any unbriefed id in one shared Plan session first; no ids plus --from-csv lets the planner pick the batch from the export. A split parent in the set hands its children to the run (07). Re-issuing the same command resumes a run that stopped.

Option What it does
--from-csv FROM_CSV Tracker export that seeds the interactive Plan of unbriefed ids.
--from-briefs FROM_BRIEFS Initialize any missing bundle from DIR/<id>.md before driving.
--rehearse Dry run: stub leaves and stub gates in an isolated bundle root (.rehearse/), publish dry-run. No model, no cargo, no network (02).
--no-publish Don't open the draft PR after an accept.
--no-act Skip the Act leaf (Act runs by default once act_cadence cycles have frozen).
--by BY Who signed off; recorded in §9.
--lanes LANES Worker-pool size for the unattended Do + Check band; overrides [driver].lanes and PDCA_LANES (07).
--max-passes MAX_PASSES Sign-off pass budget per wave before the driver stops driving a bundle; overrides [driver].max_passes and PDCA_MAX_PASSES (07).
--auto-iterate Rebuild without stopping while Check finds implementation-level work; human-judgment findings are deferred to the handover §6; overrides [driver].auto_iterate and PDCA_AUTO_ITERATE (07).
--no-inhibit Don't hold a suspend inhibitor for the run (also PDCA_NO_INHIBIT=1); for CI and containers.

Exit status, from the tool's own help: 0 every bundle finished (with one id, a stop for sign-off counts too); 1 a bundle did not finish, or the run could not start; 2 bad input (a bad pdca.toml, no ids, an unschedulable dependency graph); 3 every bundle finished, but a fold held an accepted bundle out of the run's integration line (it pushed no branch, or it conflicts with a same-wave bundle), so that work is on no line of the run.

Covered in: index, 03, 07.

pdca run — one issue, one halted state

usage: pdca run [-h] issue_id

Advances a single bundle until the driver reaches a halted state (AWAITING_SIGNOFF, COMPLETE, …): Do, gates, reviewer, assembly, STOP. It never advances an UNPLANNED bundle — there is nothing to do without a brief — and it runs no Plan, sign-off, publish or Act. This is the L2 rung of the maturity ladder; flow wraps it. Covered in: 02.

pdca init-issue — seed a bundle from a brief you already wrote

usage: pdca init-issue [-h] [--from-brief FROM_BRIEF] issue_id

Creates results/issue_<id>/ and copies the file given by --from-brief in as its brief.md, so the bundle starts PLANNED. The flag is required: to start from a ticket, use flow <id>, which plans. This bypasses the planner leaf and its advisory review, so it is for the offline toy brief, for hand-authored briefs, and for tests. Covered in: 02, 03.

pdca signoff — record the human verdict (§9)

usage: pdca signoff [-h] (--accept | --iterate-do | --iterate-plan |
                    --discontinue) [--by BY] [--delta DELTA] [--no-publish]
                    issue_id

Exactly one disposition is required.

Option What it does
--accept Accept — merged-wider, state COMPLETE, then publish (unless --no-publish).
--iterate-do Right spec, wrong build: archive the attempt into iteration-v<N>/, keep the brief, back to PLANNED.
--iterate-plan The spec was wrong: archive the whole attempt including the brief, back to UNPLANNED.
--discontinue Deliberate abandon: record §9, no transition, drop from the pending set.
--by BY Who signed off.
--delta DELTA The iteration rationale; folded into the brief's carry-forward on an iterate.
--no-publish Record the accept and stop at COMPLETE.

Refusals, all exit 1: no SUMMARY.md yet; --accept while any §6 NEEDS-HUMAN item is unchecked (the C6 guard, which lists the open items); a SUMMARY with no §9 section. The other three dispositions are not guarded. On an accept that publishes, the exit code is publish's. Covered in: 05, 05.

pdca publish — contribute an accepted bundle as a draft PR

usage: pdca publish [-h] [--dry-run] [--no-pr] [--no-issue] [--by BY] issue_id

Check's closing step: branch from the bundle's target (or the run's integration line for a dependent), apply the patch, run the host_ci rows and the contribution check against the drafted commit message and PR body, push, open a draft PR, write publish.json. A failing host-CI row or contribution check refuses the push.

Option What it does
--dry-run Print the git and gh commands without running them.
--no-pr Push the branch but don't open the draft PR.
--no-issue No tracker id yet: the T4 check drops only the tracker-trailer rule and records id_pending (travels to the gate as PDCA_PENDING_ID).
--by BY Who published; recorded in publish.json.

Covered in: 05.

pdca record — commit finished bundles to the instance repo

usage: pdca record [-h] [--dry-run] [issue_ids ...]

Commits every bundle whose cycle is over — COMPLETE, DISCONTINUED, RESOLVED — as one batch commit; with [records] mode = "pr" it pushes a records/<date> branch and opens one draft PR instead. A named id that is not terminal is excluded, loudly. Needs the [records] table in pdca.toml; once enabled, publish triggers it too. --dry-run prints the plan. Covered in: 05.

pdca revert — undo a published contribution

usage: pdca revert [-h] [--dry-run] [--by BY] issue_id

Reads the bundle's publish.json: a merged PR gets a draft revert PR that reverse-applies the bundle's own patch.diff onto the base; an open PR is withdrawn (gh pr close --delete-branch). The revert PR stays a draft for you. --by is recorded in revert.json. Covered in: 05.

Look at state

pdca status — the dashboard (also bare pdca)

usage: pdca status [-h] [issue_id]

One line per bundle, cheap-first: state, id, and markers — [N NEEDS-HUMAN] or [cheap: confirm] on a bundle awaiting sign-off, [blocked-by: …] for an unsatisfied Depends on, [oversized] from the size signal, and for a COMPLETE bundle [PR <url>] (with ↑<base> when the PR is stacked), [unpublished], or [close: no PR]. With an id, that bundle only. Exit 0. Covered in: index, 05.

pdca queue — the sign-off burn-down

usage: pdca queue [-h]

The AWAITING_SIGNOFF bundles, cheapest first — the order to work a batch's verdicts in. Exit 0.

pdca waves — preview the schedule

usage: pdca waves [-h] [issue_ids ...]

Prints the dependency-wave plan flow would run for the given ids (none: every in-flight briefed bundle) without building anything. An unschedulable graph — a cycle, an unresolved Depends on, a Merges with group under merge mode — is reported as unschedulable: with exit 1. Covered in: 03, 07.

pdca size — the a-priori size estimate

usage: pdca size [-h] [issue_ids ...]

Read-only. For each briefed bundle (or the ids given) prints the band — ok, watch, oversized — and the signals that fired, split into churn and patch size. Decides nothing and writes nothing. Covered in: 07.

Decompose

pdca split — propose, then materialize, a decomposition

usage: pdca split [-h] [--accept] [--ids IDS] [--force] issue_id

Without --accept, the splitter leaf drafts split-proposal.md — one full draft brief per child. With --accept, the deterministic half files one tracker sub-issue per child (unless --ids names existing ones, in proposal order), materializes the child bundles, rewrites the proposal's sibling labels to real ids, writes split-lineage.json everywhere, and closes the parent with close-disposition = split. Acceptance is transactional: everything is validated before any issue is filed or file written. A bundle already two splits deep is refused unless --force. Normally the planner runs both from inside the Plan session. Covered in: 07.

Gates and checks

pdca gates — run the deterministic Check gates

usage: pdca gates [-h] [--working-tree] [--promotions] [issue_id]

The same code the driver and CI call. With an id, that bundle's full gate set is run and printed, nothing recorded. --working-tree runs the repo-scoped rows only — the CI merge re-gate. --promotions lists the advisory rows that have passed in their promote_after most recent frozen cycles and so have earned promotion to gating (you flip gating = true yourself). Exit 1 when the gating overall is fail, else 0. Covered in: 01, 05.

pdca registry-check — a manifest line must point at a touched path

usage: pdca registry-check [-h] [issue_id]

A pure diff analysis for a bundle-scoped gate row: every line a patch adds to a declared registry or manifest file ([gates.registry_consistency] files, with an optional extraction pattern) must reference a path the same patch touches; anything else is cross-bundle contamination. The id may also arrive as $PDCA_BUNDLE, which is how a gate row calls it. Exit 0 with no registry files declared or no patch; 1 on a violation; 2 when no bundle can be resolved.

pdca contribcheck — the T4 contribution check

usage: pdca contribcheck [-h] [--no-issue] [issue_id]

Fails a contribution whose PR body lacks a user-impact opener or whose commit message and PR body lack the tracker id. At Check it reports deferred (the texts are drafted at publish); publish runs it for real before the push. --no-issue (or $PDCA_PENDING_ID) drops only the tracker-id rule. Exit 0 when nothing is wrong or there is no patch to contribute, 1 on a problem, 2 when no bundle resolves. Covered in: 05.

pdca revalidate — re-gate a frozen bundle against today's engine

usage: pdca revalidate [-h] [--date DATE] issue_id

Re-runs the same gate set over a COMPLETE bundle and writes an additive, dated stamp revalidation-<date>.json recording each row's old → new result. It never touches check-gates.json, check-gates.md or §9: the original decision stands, and a changed result in either direction is a signal, not a verdict.

pdca drift — which published patches no longer apply

usage: pdca drift [-h] [--no-fetch]

For every COMPLETE bundle with an open PR, git apply --checks its patch against the freshly fetched base in a throwaway worktree and reports the ones that need a rebase. Report-only: it mutates nothing and re-decides nothing. --no-fetch checks against already-fetched refs.

pdca try — run the patched build yourself

usage: pdca try [-h] issue_id

Materializes the bundle's patched tree from patch.diff and runs the project's [manual_test].cmd from it, inheriting your terminal, with no timeout — you quit the app to return. Advisory: it changes nothing in the bundle. Needs [driver].worktree on and a configured command; otherwise it prints a hint. Covered in: 05.

Act

pdca act — cross-cycle review tooling

usage: pdca act [-h] {index,log,resolve} ...

Manual, out-of-turn Act review over frozen (COMPLETE) cycles. These carry no cadence gate — [driver].act_cadence throttles only the flow's automatic Act. index and log default to the cycles frozen since the last review (the frontier in process/.act-reviewed); --all or --since widens the scope.

usage: pdca act index [-h] [--since SINCE] [--all]
usage: pdca act log [-h] [--since SINCE] [--all] --date DATE [--append]
usage: pdca act resolve [-h] [--location LOCATION] [--date DATE] signal
Subcommand What it does
index Read-only index of frozen cycles, their §6/§7/§10 extracts, recurring signals, the per-cycle sizing: line and the "⚠ Ineffective deltas" audit. Writes nothing.
log --date <ISO> Prints a scaffolded, dated act-log entry; its Process-deltas section is left TODO on purpose. With --append it is written to process/act-log.md and the review frontier advances, so the flow's next automatic Act won't re-cover these cycles. Exits 1 when no frozen cycle exists.
resolve <signal> Marks a tracked recurring signal as a delta you applied, in process/act-ledger.json; --location path:line says where. A later Act flags it as ineffective if the miss recurs after that date.

Covered in: 06.

pdca triage — ingest a published PR's review findings

usage: pdca triage [-h] [--repo REPO] [--date DATE] pr

Pulls the PR's reviews and review comments through gh api, classifies each finding as BUG, CONVENTION, NOISE or TEST-GAP, routes by class (a BUG on a merged PR files a tracker issue with a carry-forward note; the rest append candidate gate, rubric and exclusion entries to process/act-log.md), and registers every finding in the Act ledger under codex-pr:<slug>. Proposes only: it never edits pdca.toml or the rubric. pr is a URL, OWNER/REPO#N, or a bare number with --repo. Re-running ingests only new findings. Covered in: 06.

Maintenance

pdca doctor — report every prerequisite, change nothing

usage: pdca doctor [-h] [--strict]

One row per prerequisite — OK, MISSING, UNAUTH or WARN — each with a fix hint. Read-only and idempotent: it installs nothing and edits nothing. Run it after make install, and again whenever you add a gate, change a leaf's family, or a red gate might be a missing tool rather than a bad patch.

Rows derived from pdca.toml, so they follow your edits with no extra config:

  • every distinct command-leaf argv[0] on PATH, with a per-family auth probe (UNAUTH for a Codex CLI without a login; WARN when no Claude credentials are found) — the builder's family is REQUIRED, the others optional;
  • git with an identity, and gh present and authenticated (publish, merge and revert need it);
  • the bundle root writable, and free space where the harness cuts worktrees;
  • the tracker notes_cmd's tool resolvable;
  • the leaf sandbox's dependencies (bubblewrap, socat) when a bounded [leaves.sandbox] exemption will be seeded — REQUIRED, because a sandbox that cannot start does not fail, it silently does not confine.

Rows you declare, one [[doctor.checks]] table each:

Key Meaning
id The row's name. A brief's External dependencies token must equal one of these.
cmd Run with cwd = project root; exit 0 ⇒ OK. Keep it cheap and side-effect-free: the dependency guard runs it at every beat it is consulted.
hint What a human does to fix it.
group Optional section header the row prints under.
level The status when cmd fails: MISSING (default) or WARN for an optional tool.
required A failing required row makes doctor exit non-zero (default false).
per_lane One row per [driver].lanes slot, with {lane} and {lanes} filled in; nothing when lanes ≤ 1.

Exit codes: 0 when every REQUIRED row passes; 1 when a REQUIRED row failed ("REQUIRED checks failed — fix the lines above first"); with --strict, 1 on any non-OK row, WARN included — the CI setting.

The same rows are the registry a brief's External dependencies field is checked against, at Plan exit, at Do's exit and at Check, so a doctor row is not only a one-time readiness check. Covered in: 01, 03, 05.

pdca cleanup — reconcile bundles with the tracker

usage: pdca cleanup [-h] [--apply] [--repo REPO] [--by BY] [issue_ids ...]

Matches each bundle's state against its tracker issue and plans the matching action: a closed issue resolves a notes-only bundle (RESOLVED) or discontinues one awaiting sign-off; a COMPLETE or DISCONTINUED bundle whose issue is still open gets it commented and closed; a merged PR on an unaccepted bundle is reported, never auto-accepted. Dry run by default; --apply executes. --repo OWNER/REPO names the tracker when it is not the configured GitHub source; --by is the §9 attribution for discontinue records. A missing or unauthenticated gh aborts before any write. Covered in: 07.

pdca sweep — reclaim the harness's worktree footprint

usage: pdca sweep [-h] [--remove] [--dry-run]

Cleans the harness's own lane, integration and overflow worktrees — never bundle artifacts, never the primary checkout. Default: strip build state and keep the checkouts warm; --remove deletes the lane worktrees too (Do and try recreate them on demand); --dry-run reports only. Runs automatically at the publish/freeze boundary per [driver].sweep_worktrees; the manual command works even when that is "off". Exit 0. Covered in: 07.

Environment variables

Two groups. The first you may set to override pdca.toml for one run; the second the driver exports to the gate commands and leaves it spawns, so your scripts can read them.

You set Effect
PDCA_LANES Worker-pool size for one run ([driver].lanes; --lanes wins over both).
PDCA_LANE Pin a standalone pdca flow <id> process to lane slot k instead of auto-claiming one.
PDCA_MAX_PASSES The per-wave sign-off pass budget ([driver].max_passes).
PDCA_AUTO_ITERATE Turn auto-iterate on for one run ([driver].auto_iterate).
PDCA_MAX_AUTO_ITERS The auto-iterate hard cap for one run ([driver].max_auto_iters).
PDCA_LEAVES_MODE Force every leaf's mode (stub or command) regardless of pdca.toml; --rehearse sets stub.
PDCA_GATES_MODE stub empties the configured checks into the all-PASS stub rows; --rehearse sets it.
PDCA_BUNDLE_ROOT Redirect the bundle root; --rehearse points it at .rehearse/.
PDCA_NO_INHIBIT Same as flow --no-inhibit.
The driver exports To whom, meaning
PDCA_WORKTREE Gates and leaves: the per-cycle worktree Do edited — the tree a bundle-scoped gate must test.
PDCA_TARGET The reviewer and advisory leaves: the read-only grounding checkout (the same worktree, patch applied).
PDCA_BUNDLE Gates, leaves, notes_cmd and plan sources: the bundle directory.
PDCA_LANE Gates, when lanes > 1: this worker's slot, 0..N-1, for namespacing shared resources. Unset on the serial path.
PDCA_SOURCES A command plan source: the bundle's sources/ directory to write into.
PDCA_BASE The per-fix verifier: the brief's Onto branch, when set.
PDCA_VERIFY_BASE The per-fix verifier: the wave's folded integration branch, for a wave > 0 bundle.
PDCA_BRIEF_BASE The per-fix verifier: the brief's Repo + branch target base, resolved by the driver.
PDCA_PENDING_ID The T4 contribution check: set by publish --no-issue, so the gate knows which rule it is excusing.

The three base variables form a ladder the per-fix red→green row resolves in that order; Wyrd's run-verify.sh in step 01 reads them exactly so. Every pdca.toml key those commands read is in the configuration reference.

← 07 Cross-cutting · Index · next: 09 Configuration reference →