# ddflow (oci · docker.io/delian/ddflow-mcp)

Work-queue kernel for AI coding agents: dependencies, worktree isolation, quality gates, recovery

- Trust score: 9/100 (low)
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-10-04

## Components

- oci · `docker.io/delian/ddflow-mcp`: 9/100 (this document), [markdown](https://verifymcp.io/servers/delian-ddflow-mcp/docker-io-delian-ddflow-mcp.md), [page](https://verifymcp.io/servers/delian-ddflow-mcp/docker-io-delian-ddflow-mcp)
- oci · `ghcr.io/delian/ddflow-mcp`: 40/100, [markdown](https://verifymcp.io/servers/delian-ddflow-mcp/ghcr-io-delian-ddflow-mcp.md), [page](https://verifymcp.io/servers/delian-ddflow-mcp/ghcr-io-delian-ddflow-mcp)
- pypi · `ddflow-mcp`: 49/100, [markdown](https://verifymcp.io/servers/delian-ddflow-mcp/ddflow-mcp.md), [page](https://verifymcp.io/servers/delian-ddflow-mcp/ddflow-mcp)

## Channel facts

- Registry: `oci`
- Package: `docker.io/delian/ddflow-mcp`
- Version: `0.2.0`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-10-04.

- **Supply Chain Security**: 0/100
  - No malware scan is available for this kind of package: the supply-chain vendors we use do not cover it. This is a permanent gap in our coverage, not a finding about the package.
  - Known CVEs could not be checked: this image's dependency list comes from an SBOM its publisher attached, which nothing verifies, so we will not report it as a clean result.
  - Install-script risk not yet assessed.
  - Dependency health could not be checked: this image's dependency list comes from an SBOM its publisher attached. It names packages and versions but not whether each is deprecated, still maintained or linked to its source, so there is nothing we can fairly grade.
- **Provenance & Transparency**: 45/100
  - Source repository is publicly reachable at the declared URL.
  - Provenance check failed: no build-provenance attestation is published.
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 0 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 0/100
  - Schema quality not yet verified: we do not have a sandbox capture of the MCP schema this version of the package serves yet.
- **Stability & Change Management**: 0/100
  - Stability not yet verified: we do not have a sandbox capture of the MCP schema this version of the package serves yet.
- **Tool Coverage**: 0/100
  - Tool coverage not yet verified: we do not have a sandbox capture of the tool definitions this version of the package serves yet.
- **Tool Safety**: 0/100
  - Tool safety not yet verified: we do not have a sandbox capture of the tool definitions this version of the package serves yet.
- **Capabilities**: 0/100
  - Protocol version not yet verified: we do not have a sandbox capture of the MCP handshake this version of the package performs yet.

**Unverified: 6 categories.** Categories scored 0 because we could not verify them: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.

## Install

### How do I install the ddflow MCP server?

ddflow runs locally as a container image, launched with docker run --rm -i -e DDFLOW_REPO -e DDFLOW_AGENT docker.io/delian/ddflow-mcp:0.2.0. Ready-made configuration for Claude, Cursor, VS Code, Codex and 3 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add delian-ddflow-mcp -- docker run --rm -i -e DDFLOW_REPO -e DDFLOW_AGENT docker.io/delian/ddflow-mcp:0.2.0
```

This image reads DDFLOW_REPO and DDFLOW_AGENT. Set them in your client's env block for this server; docker run -e passes each one through to the container.

### Cursor

```json
{
  "mcpServers": {
    "delian-ddflow-mcp": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "-e",
        "DDFLOW_REPO",
        "-e",
        "DDFLOW_AGENT",
        "docker.io/delian/ddflow-mcp:0.2.0"
      ]
    }
  }
}
```

This image reads DDFLOW_REPO and DDFLOW_AGENT. Set them in your client's env block for this server; docker run -e passes each one through to the container.

### VS Code

```json
{
  "servers": {
    "delian-ddflow-mcp": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "-e",
        "DDFLOW_REPO",
        "-e",
        "DDFLOW_AGENT",
        "docker.io/delian/ddflow-mcp:0.2.0"
      ]
    }
  }
}
```

This image reads DDFLOW_REPO and DDFLOW_AGENT. Set them in your client's env block for this server; docker run -e passes each one through to the container.

### Codex

```bash
codex mcp add delian-ddflow-mcp -- docker run --rm -i -e DDFLOW_REPO -e DDFLOW_AGENT docker.io/delian/ddflow-mcp:0.2.0
```

This image reads DDFLOW_REPO and DDFLOW_AGENT. Set them in your client's env block for this server; docker run -e passes each one through to the container.

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "delian-ddflow-mcp": {
      "type": "local",
      "command": [
        "docker",
        "run",
        "--rm",
        "-i",
        "-e",
        "DDFLOW_REPO",
        "-e",
        "DDFLOW_AGENT",
        "docker.io/delian/ddflow-mcp:0.2.0"
      ],
      "enabled": true
    }
  }
}
```

This image reads DDFLOW_REPO and DDFLOW_AGENT. Set them in your client's env block for this server; docker run -e passes each one through to the container.

### Hermes

```yaml
mcp_servers:
  delian-ddflow-mcp:
    command: "docker"
    args: ["run", "--rm", "-i", "-e", "DDFLOW_REPO", "-e", "DDFLOW_AGENT", "docker.io/delian/ddflow-mcp:0.2.0"]
```

This image reads DDFLOW_REPO and DDFLOW_AGENT. Set them in your client's env block for this server; docker run -e passes each one through to the container.

### Netclaw

```json
{
  "McpServers": {
    "delian-ddflow-mcp": {
      "Transport": "stdio",
      "Command": "docker",
      "Arguments": [
        "run",
        "--rm",
        "-i",
        "-e",
        "DDFLOW_REPO",
        "-e",
        "DDFLOW_AGENT",
        "docker.io/delian/ddflow-mcp:0.2.0"
      ]
    }
  }
}
```

This image reads DDFLOW_REPO and DDFLOW_AGENT. Set them in your client's env block for this server; docker run -e passes each one through to the container.

### Other

```json
{
  "mcpServers": {
    "delian-ddflow-mcp": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "-e",
        "DDFLOW_REPO",
        "-e",
        "DDFLOW_AGENT",
        "docker.io/delian/ddflow-mcp:0.2.0"
      ]
    }
  }
}
```

This image reads DDFLOW_REPO and DDFLOW_AGENT. Set them in your client's env block for this server; docker run -e passes each one through to the container.

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-10-04 (score 9, −30)

- [security regression] Stability: 0.03 → unverified
- [security regression] Tool safety: pass → unverified
- [functional regression] Tool coverage: 100 → unverified
- [functional regression] Schema quality: 100 → unverified
- [functional regression] Capabilities: fail → unverified
- [functional improvement] Schema quality: 190 → 157
- [functional] Package version: 0.1.11 → 0.1.13
- [functional] Package version: 0.1.11 → 0.1.12

### 2026-10-03 (score 39, 0)

- [functional improvement] Stability: unverified → 0.03
- [functional] Package version: 0.1.10 → 0.1.11

### 2026-10-02 (score 39)

First indexed and scored.

## MCP tools (106)

### `ddflow_abandon` (~158 tokens)

Stop work on an item without completing it, with a reason. Use when a task turns out to be unnecessary or impossible. DIFFERENT from blocking: a blocked item is waiting and will resume; an abandoned one will not, and so it stops holding its phase open — which an unfinished task otherwise does forever, since nothing can ever finish it.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `force` (boolean): Abandon although a sub-task is still open. Those sub-tasks are NOT abandoned with it: decide about each, or they sit under a parent nobody will finish.
- `id` (string, required): Item id.
- `reason` (string, required): Why it is being dropped.

### `ddflow_bisect` (~121 tokens)

Which earlier test file makes `victim` fail only in full-suite order? Delta-debugs the files before it, running `cmd` many times. Exit 2: nothing to report.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `candidates` (string): Comma-separated files in run order.
- `cmd` (string, required): Test command; {tests} = the list.
- `timeout` (integer): Seconds per run (600).
- `victim` (string, required): Failing test id.

### `ddflow_block` (~110 tokens)

Mark an item blocked on something outside the queue — a decision, an upstream outage, an operator question. Better than leaving it claimed: a blocked item states its reason. A DONE or ABANDONED item needs reopen.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `id` (string, required): Item id.
- `reason` (string, required): What it is waiting on.
- `reopen` (boolean): Allow blocking a DONE or ABANDONED item.

### `ddflow_board` (~53 tokens)

The whole work queue as a readable board, with the critical path.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `phase` (string): Restrict to one phase.

### `ddflow_brief` (~181 tokens)

START HERE every session. Returns a budgeted pack: work recoverable after a crash, the current item, what is ready to start now, why everything else is blocked, and the past lessons ranked as relevant to this task. Use this INSTEAD of reading the project's lesson or rule files — it is the same information retrieved for the task at hand, at a fraction of the tokens.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `check_recovery` (boolean): Also scan for crashed agents' worktrees and lead with them: unclaimed work left by a dead process is the one thing to know BEFORE picking up something new.
- `item` (string): Focus on this phase or task id (optional).
- `phase` (string): Restrict the ready set to this phase (optional).

### `ddflow_bug_file_tasks` (~76 tokens)

File a fix task for every open bug that has none (one-shot after an upgrade; `ddflow_bug_found` files one per bug by default).

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `dry_run` (boolean): List what would be filed; write nothing.

### `ddflow_bug_fixed` (~216 tokens)

Close a bug. Requires the name of the regression test that would catch it again — write the test, watch it FAIL against the unfixed code, then close.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `changelog` (string): Optional 'Fixed: text' (any category), or skip.
- `id` (string, required): Bug id.
- `lesson` (string): Id of an EXISTING lesson this bug belongs to.
- `lesson_rule` (string): The lesson in full — the transferable rule, not the incident. A future agent on a different task has to be able to apply it.
- `lesson_title` (string): Capture a lesson at the same time.
- `regression_test` (string): Test that now guards this. Several: separate them with ',' or ';', or pass regression_tests.
- `regression_tests` (array): The tests that now guard this, one per element -- the list form of regression_test. One of the two is required.

### `ddflow_bug_found` (~271 tokens)

Report a bug the moment you find it, BEFORE fixing it. Recording it first makes the fix accountable: `ddflow_bug_fixed` refuses to close one without a regression test. A hunt that records nothing looks like one that found nothing.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `check_only` (boolean): Dry run: write nothing, return the `candidates` this add would be refused for.
- `globs` (string): The fix task's files; default: the item's globs.
- `id` (string): Stable id, e.g. 'B1'. You will cite it when closing.
- `item` (string): The task it was found in or affects.
- `no_task` (boolean): File no fix task (fixed in the same commit).
- `relation` (string): Answer to a 'possible duplicate' refusal: new | extends:ID | duplicate_of:ID | related:ID (the refusal lists candidates and options). Omit at first.
- `scope` (string): project (default) or ddflow.
- `severity` (string): low|medium|high|critical.
- `summary` (string, required): What is wrong, in one line.
- `title` (string): Short headline.

### `ddflow_bug_invalid` (~174 tokens)

Close a bug as a FALSE finding -- nothing was broken, so nothing was fixed. Never counts as a fix. Requires the reason; give the probe or test that showed it false as evidence. Refused (exit 3) for an unknown id or a bug already closed; a real bug is closed with `ddflow_bug_fixed` instead. `reopen`: instead UNDO a closure (fixed or invalid) made by mistake.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `evidence` (string): The probe command or test node id that showed it false.
- `id` (string, required): Bug id.
- `reason` (string, required): Why the finding is false (with reopen: why reopen).
- `reopen` (boolean): Reopen the closed bug instead.

### `ddflow_cadence` (~96 tokens)

Which periodic whole-repo passes are due — integration tests, architecture review, mutation testing, dedupe sweep, lessons compression. Derived from completed work, so there is no state file to drift.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `note` (string): What the pass did, recorded with it.
- `ran` (string): Record that this cadence just ran.

### `ddflow_ci` (~105 tokens)

CI parity: run the pre-push checks on the branch merged with the base (run) or show what would run (status).

Input parameters:

- `action` (string): run | status (default).
- `as_agent` (string): A subagent's own name, this call only.
- `base` (string): Branch merged in first (run).
- `command` (string): Override [ci].command (run).
- `ref` (string): Commit to check (run).

### `ddflow_claim` (~261 tokens)

Lease an item and create its isolated git worktree. Refuses (exit 3) if another agent holds it or holds an item whose file globs overlap, and names what you could take instead. NEVER steals an expired lease: a crashed agent's worktree often holds finished work.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `force` (boolean): Override a refusal. Legitimate only to retry after `ddflow_recover` said a crashed agent's worktree holds nothing. Forcing past a dependency or live lease is how two agents write one file; recorded e…
- `globs` (string): Comma-separated path globs this work will write.
- `id` (string, required): Item id to claim.
- `no_worktree` (boolean): Lease the item without creating a worktree. For work that is not a code change — a research or review task.
- `note` (string): What you intend to do.
- `resources` (string): Physical resources this claim holds, e.g. 'gpu:2'; they REPLACE the item's declared ones. Refused (exit 3) when live claims already use the capacity ([schedule] resources), every holder counted.

### `ddflow_cleanup` (~115 tokens)

Classify every ddflow worktree and branch: merged (safe to remove), unmerged (carries commits nobody landed), dirty (uncommitted edits: a human looks), orphan, or stale branch. Reports by default; apply=true removes merged worktrees and branches and lands commits for items the queue considers done. A dirty tree is NEVER touched automatically: it exists nowhere else.

Input parameters:

- `apply` (boolean): Perform the safe actions.
- `as_agent` (string): A subagent's own name, this call only.

### `ddflow_companions` (~95 tokens)

Which companion MCP servers serve this project's gates, which are installed, which an agent launches. Without them, agent gates pass on assertion. Exit 2: a default one is missing or unregistered. Read-only; never installs or launches.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `no_probe` (boolean): Skip the detection probes (faster, less certain).

### `ddflow_companions_add` (~128 tokens)

WRITES the agent config: registers companion MCP servers that are ALREADY installed (exit 3 for one that is not). dry_run=true FIRST; show the operator the entry: which servers an agent launches is their decision.

Input parameters:

- `agents` (string): Comma-separated agent keys (default: claude).
- `as_agent` (string): A subagent's own name, this call only.
- `dry_run` (boolean): Report the exact entry that would be written; write nothing.
- `id` (string): Comma-separated ids; default: every installed one.

### `ddflow_companions_verify` (~88 tokens)

Launch MCP companions and require a JSON-RPC answer to `initialize`. SPAWNS processes (opt-in). Default: registered or installed ones. Exit 1: not an MCP server; 2: unsure.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `id` (string): Comma-separated ids, installed or not.

### `ddflow_complete` (~194 tokens)

Finish an item. Refuses (exit 3) when a required gate has not passed, when a phase still has open tasks, or when no reviewer came from a different model family than the author. Pass your own model as 'model'.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `changelog` (string): Optional 'Added|Changed|Deprecated|Removed|Fixed|Security: text', or skip.
- `force` (boolean): Complete over unmet conditions; each is recorded as overridden, forever. Prefer `ddflow_gate_skip` with a reason: it drops one named step.
- `id` (string, required): Item id.
- `model` (string): The AUTHOR's model.
- `regression_test` (string): For a fix task: the test that now guards its bug(s); closes them.
- `sha` (string): Commit sha this shipped as.

### `ddflow_configure` (~315 tokens)

Read or write .ddflow/config.toml (WRITES). No arguments: every knob with value, source and meaning. `set` edits one dotted key in place (preferred); `toml` APPENDS a fragment, e.g.
[gate.unit_tests]
command = "pytest -q -n auto"
(needs pytest-xdist). The committed file is generic project policy; anything of THIS machine or operator (a reviewer endpoint, a host, a key variable, worker counts) goes with local=true to the git-ignored .ddflow/local/config.toml, read last and never committed. A reviewer there is a `[[reviewer]]` block; `ddflow_reviewers_detect` write=true writes one.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `filter` (string): Only show knobs whose name contains this.
- `local` (boolean): Write `set`/`toml` to the git-ignored .ddflow/local/config.toml instead of the committed config: for this machine's endpoints, hosts, key variables and sizing.
- `set` (string): Dotted key to set, e.g. 'gate.unit_tests.command'. Preferred: it edits in place and works whether or not the section exists.
- `toml` (string): A whole TOML block to append. Fails if it would duplicate an existing table — use `set` instead then.
- `value` (string): The value for `set`.

### `ddflow_decision_add` (~405 tokens)

Record an architectural decision so the project stays consistent and the reasoning survives: HOW the software is built (a representation, boundary, library, invariant), settled by you or the operator. ALWAYS set `globs` to the code it governs, so it reaches whoever works those files; record `alternatives` too, or they get re-proposed.

Input parameters:

- `alternatives` (string): What was rejected, and why.
- `as_agent` (string): A subagent's own name, this call only.
- `by` (string): 'operator' or 'agent' or a name.
- `check_only` (boolean): Dry run: write nothing, return the `candidates` this add would be refused for.
- `consequences` (string): What it costs, including what it makes harder.
- `context` (string): The forces: why a decision was needed at all.
- `decision` (string, required): What was DECIDED (not what was discussed).
- `globs` (string): Comma-separated paths this governs.
- `id` (string): Stable id, e.g. 'D1'. Choose one: a generated id cannot be cited in advance.
- `item` (string): The task it arose from.
- `relation` (string): Answer to a 'possible duplicate' refusal: new | extends:ID | duplicate_of:ID | related:ID (the refusal lists candidates and options). Omit at first.
- `sources` (string): Where this came from, comma-separated: an ADR path, a URL, a commit sha (so an audit can check it exists).
- `status` (string): proposed | accepted (default) | superseded. 'proposed' is honest about a decision the operator has not ratified.
- `supersedes` (string): Comma-separated ids this replaces.
- `tags` (string): Comma-separated tags.
- `title` (string, required): The decision as a one-line statement.

### `ddflow_decision_applicable` (~82 tokens)

The architectural decisions that govern a specific item's declared files. CALL THIS BEFORE IMPLEMENTING: it is how a decision reaches the person writing the code, without them having to know it exists. Returns project-wide decisions too.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `id` (string, required): Item id.

### `ddflow_decision_list` (~97 tokens)

Every architectural decision in force. Superseded ones are hidden unless you ask for them — they are kept, never deleted, because how the architecture got here is what a rebuild needs.

Input parameters:

- `all` (boolean): Include superseded decisions.
- `as_agent` (string): A subagent's own name, this call only.
- `limit` (integer): Newest decisions returned (default 25; 0 = all).

### `ddflow_decision_show` (~91 tokens)

Read ONE architectural decision in full — its context, what was decided, the consequences, and what was rejected. `ddflow_decision_list` gives you the titles; this is what you read before working against one, and especially before proposing something it already considered.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `id` (string, required): Decision id.

### `ddflow_decision_supersede` (~92 tokens)

Mark a decision replaced by a newer one. Decisions are never edited or deleted; a reversal is a new decision that names the old one.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `by` (string, required): The decision that replaces it.
- `id` (string, required): The decision being replaced.
- `reason` (string): Why it changed.

### `ddflow_doctor` (~50 tokens)

Integrity and health check: log corruption, dependency cycles, unknown dependencies, orphaned worktrees, stale index.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.

### `ddflow_export` (~271 tokens)

Documents from the log (roadmap, bugs, status, worklog, sessions, decisions, rules, changelog). No doc: list. doc: capped markdown (`truncated`). Writes only with write=true AND a repo path. action: list|enable|disable|validate (enable names you and how to stop it).

Input parameters:

- `action` (string): list|enable|disable|validate.
- `all` (boolean): The selected documents.
- `as_agent` (string): A subagent's own name, this call only.
- `check` (boolean): Is it fresh.
- `diff` (boolean): Preview a write.
- `doc` (string): Kind; omit to list.
- `item` (string): Bugs item.
- `limit` (integer): At most N.
- `max_bytes` (integer): Max 60000.
- `mode` (string): enable: whole|region|append.
- `path` (string): Repo path.
- `phase` (string): One phase.
- `session` (string): One session.
- `since` (string): From YYYY-MM-DD.
- `status` (string): e.g. open.
- `tag` (string): One tag.
- `version` (string): One release.
- `write` (boolean): Write to path.

### `ddflow_external_sync` (~109 tokens)

Observe the items in SIBLING repositories that this queue depends on (`needs = ['run_nemo_run:132.D']`, repositories named in [schedule] repos), and record what changed in this log. An external dependency is met only once it has been observed done here, so run this before `ddflow_next` when work waits on another project. Reads the other repository; never writes it.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.

### `ddflow_flow_choose` (~150 tokens)

Record a workflow choice for this project, attributed to you, with a reason the next agent will read. Make it when the operator told you, or when they left it to you -- a choice left unmade is defaulted at first use and followed from then on. The operator's config file wins over a recorded choice; the result says `in_effect: false` when it does.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `knob` (string, required): The choice, e.g. port_strategy (see ddflow_flow_show).
- `reason` (string): Why this suits the project.
- `value` (string, required): One of its options.

### `ddflow_flow_show` (~109 tokens)

How THIS project works: its branching model, release lines, and every workflow choice (model, integration, pr_merge, port_strategy, ...) with its value, the options, and who decided -- the operator's config, a recorded choice, or a default nobody chose. `pending` lists relevant choices nobody has made: ask the operator, or pick what suits the project with `ddflow_flow_choose`.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.

### `ddflow_gate_record` (~292 tokens)

Record the outcome of a gate you performed (research, a review, a bug hunt). outcome is one of passed/failed/unavailable/partial/skipped. If a reviewer or tool could not run, record 'unavailable' with a reason, never 'passed'. Pass the reviewer's model for the family check.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `command` (string): The command you ran. With `exit_code` it makes an outcome evidence; a gate in `gates.evidence_required` is rejected without them.
- `evidence` (string): What you ran and what it said. Required by some gates.
- `exit_code` (string): That command's exit code.
- `gate` (string, required): Gate id.
- `id` (string, required): Item id.
- `model` (string): REVIEWER's model, e.g. 'gemini-2.5-pro'.
- `outcome` (string, required): passed | failed | unavailable | partial | skipped
- `output_file` (string): Path to its full output; a digest is recorded.
- `reason` (string): Required for failed/unavailable/partial/skipped.
- `reviewed_sha` (string): Commit reviewed (roborev review <sha>); must be the branch.
- `reviewer_model` (string): Like `model`; says it IS the reviewer.

### `ddflow_gate_run` (~87 tokens)

Execute a command gate (tests, linters) and record the result with its evidence. Agent gates cannot be run this way; they are recorded with ddflow_gate_record.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `gate` (string, required): Gate id, e.g. unit_tests.
- `id` (string, required): Item id.

### `ddflow_gate_skip` (~155 tokens)

Skip a gate ON THE RECORD, with a mandatory reason: the auditable escape hatch. `gates.require_outcome` means a silent gate BLOCKS completion, so the alternative to a skip is forcing past everything at once; a skip names the single step dropped and why, permanently in the log. A gate in `gates.required` still blocks when skipped.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `gate` (string, required): Gate id.
- `id` (string, required): Item id.
- `reason` (string, required): Why this step does not apply HERE. 'n/a' is not a reason: the next person reads this to decide whether you were right.

### `ddflow_gate_status` (~75 tokens)

Where an item stands in its quality pipeline, which gate is next, and the instruction for that gate. Gates marked '?' did not run — that is a coverage gap, never a pass.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `id` (string, required): Item id.

### `ddflow_gate_verify` (~157 tokens)

Break what a gate guards and require it to NOTICE: applies each mutation registered on the gate, runs it, requires a non-zero exit, restores the file. A gate that cannot fail reports success on every change. Exit 1: the gate did NOT catch its mutation, or none is registered. Exit 3 on a HUMAN-approval gate (nothing to mutate). A mutation whose `old` text is absent or ambiguous is a FAILURE, not a skip: the gate ran on pristine source.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `gate` (string, required): Gate id. Must be a command gate.
- `id` (string, required): Item whose worktree to mutate in.

### `ddflow_heartbeat` (~62 tokens)

Renew the lease on an item. Call periodically during long work, or the lease expires and another agent may take the item.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `id` (string, required): Item id.

### `ddflow_help` (~162 tokens)

What ddflow IS, what it can do, and what the workflow is. Call this first if you have not used it before: the other descriptions explain one tool each and the connection instructions describe THIS repository; neither answers 'how am I meant to work here'. No argument: the loop from picking work to landing it, the exit codes, and every capability grouped by purpose. `topic`: workflow, import, gates, parallel, memory, recovery, config. Read-only; the pages are templates a project may override.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `topic` (string): workflow | import | gates | parallel | memory | recovery | config. Omit for the overview, which lists them.

### `ddflow_history` (~213 tokens)

ONE timeline of everything that happened: claims, releases, gates, bugs, decisions, lessons, completions. Other views say what is true now; this says how it got that way.

Filter with `item` (one task's life), `kind` (a family: 'gate', 'lease.acquired', 'decision,bug'), `since`, `by_agent`. Exit 2 means nothing matched: an answer, not a failure.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `by_agent` (string): Only this agent's events.
- `item` (string): Restrict to one item's timeline.
- `kind` (string): Comma-separated event kinds or families: 'gate', 'lease.acquired', 'decision,bug'.
- `limit` (integer): Most recent N entries (default 40).
- `since` (string): ISO timestamp lower bound.
- `tail` (integer): Last N entries, oldest first (overrides limit).

### `ddflow_hooks` (~153 tokens)

Inspect or install the enforcement git hook — the one layer of this workflow that does not depend on the agent agreeing. It refuses a commit touching paths no live lease of yours covers. `status` reports whether it is installed AND whether the policy actually blocks, since a block policy with no hook installed enforces nothing.

Input parameters:

- `action` (string): status (default), install, uninstall.
- `as_agent` (string): A subagent's own name, this call only.
- `claude` (boolean): Install/uninstall the Claude Code SessionStart hook in .claude/settings.json instead of the git hook: every session, even after compaction, starts with the ddflow brief. Other hooks there are untouch…

### `ddflow_identify` (~173 tokens)

Declare WHO you are on this connection before anything that writes. Call it first when 2+ agents or subagents work this repository at once: identity attributes every claim, gate outcome and review, and the tree-derived default merges several agents in one tree into one identity with no error (a review would pass independence against itself). Pick a short stable name (your role), distinct from the others'. Idempotent. A SUBAGENT sharing its parent's connection must NOT call this; it passes `as_agent` on each call instead (the CLI's `--agent`).

Input parameters:

- `agent` (string): A short stable name, e.g. 'reviewer-2' (letters, digits, . _ -; max 64; it names your log file). OMIT to reset to the tree-derived default.

### `ddflow_import` (~197 tokens)

For a project that ALREADY HAS HISTORY and is adopting ddflow now: reads its todo checklists, lessons corpus, ADR files and unmerged branches and proposes them as queue items. Reports by default; writes NOTHING until `apply` is true. Call it right after `ddflow_setup` on any repository that is not brand new. The proposal is a GUESS: the `import-existing-project` prompt walks through fixing it. Exit 2: nothing found.

Input parameters:

- `apply` (boolean): Write the proposal. Default false: look first.
- `as_agent` (string): A subagent's own name, this call only.
- `include_done` (boolean): Also import already-ticked items as completed. Off by default — a finished history is not a queue, and one real project yielded 3,638 of them.
- `max_tasks` (integer): Refuse to propose more tasks than this (default 200).

### `ddflow_import_verify` (~140 tokens)

Was this project's history imported, is that still true, and did anyone FINISH it? Read-only. STATUS: what carries import provenance. STILL TRUE: whether the sources moved on (what a re-run would add) or an imported item names a missing file. FINISHED: imported tasks with no globs (the conflict detector cannot protect them) and phases claiming shipped work while a task under them is open. Call after any import. Exit 1 = findings; exit 2 = nothing ever imported. `ddflow_doctor` covers the rest.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.

### `ddflow_job_add` (~118 tokens)

Register a long-running process you started some other way (torchrun, a launcher script), by pid, while it runs -- so its liveness can be checked by anyone later, including after a pid is reused.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `command` (string): What it is running, for humans.
- `item` (string, required): Item the job is for.
- `log` (string): Where its output goes.
- `pid` (integer, required): Its process id.

### `ddflow_job_end` (~136 tokens)

Record that a job ended and how. Refused while the process is still running. The exit code defaults to the one its log recorded.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `exit_code` (integer): Override the recorded exit code.
- `force` (boolean): End a job that runs on ANOTHER host, after checking it there. Without it such a job is refused: 'could not look' is not 'not running'.
- `job` (string, required): Job id.
- `note` (string): What came of it: metrics, where the output is.

### `ddflow_job_list` (~120 tokens)

Long-running jobs and their LIVE status: running, exited (with the exit code its log recorded), gone (killed: no exit recorded), elsewhere (another host), or ended. Use it to decide whether to keep waiting, collect results, or restart. A long run is a WAIT, never a reason to stop working the queue.

Input parameters:

- `all` (boolean): Include jobs already recorded as ended.
- `as_agent` (string): A subagent's own name, this call only.
- `item` (string): Only this item's jobs.

### `ddflow_job_run` (~202 tokens)

Launch a LONG-RUNNING command for an item (a training run, a data generation, a model server) detached into its own session, so it outlives you, this server and a restarted remote-control service, and record it. Runs in the item's worktree; returns the job id, pid and log path. Then WAIT with ddflow_job_list rather than polling; `ddflow_brief` shows running jobs to the next session. Declare the item's `resources` (ddflow_update) so nobody else starts a run on the same GPUs.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `command` (string, required): The shell command.
- `cwd` (string): Working directory (default: the item's worktree).
- `item` (string, required): Item the job is for.
- `log` (string): Output file (default .ddflow/local/jobs/<item>-<t>.log).

### `ddflow_lesson_add` (~431 tokens)

Record a lesson so it is never re-learned. Use after any bug, any operator correction, any surprise. Make the rule transferable — a future agent on a different task must be able to apply it.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `check_only` (boolean): Dry run: write nothing, return the `candidates` this add would be refused for.
- `globs` (string): Comma-separated globs to scan for `pattern`. Default: every tracked file.
- `how` (string): How to apply or detect it.
- `id` (string): Stable id you choose. Referenced by `supersedes`, by commit messages and by the reconstruction; a generated id cannot be cited in advance.
- `pattern` (string): A regex naming the mistake in CODE. Scans now and stores WHICH sites match, so `ddflow_lesson_verify` can name those that reappear. Prefer it to a remembered rule when mechanical: a count says 'worse…
- `relation` (string): Answer to a 'possible duplicate' refusal: new | extends:ID | duplicate_of:ID | related:ID (the refusal lists candidates and options). Omit at first.
- `rule` (string): The rule in full.
- `seen_in` (string): Comma-separated item ids where this was hit. What makes a lesson checkable later instead of merely memorable.
- `summary` (string): The lesson in ONE paragraph, for a reader who will not open the full rule. Rendered into docs/ddflow/LESSONS-SUMMARY.md.
- `supersedes` (string): Comma-separated lesson ids this replaces. The old one is retired, not deleted: the corpus stops growing without losing what was once believed.
- `tags` (string): Comma-separated tags.
- `title` (string, required): The rule as a one-line statement.
- `why` (string): Why it is true / what went wrong.

### `ddflow_lesson_search` (~78 tokens)

Search past lessons by relevance (BM25). Use before starting work, and whenever something surprises you.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `limit` (integer): Max results (default 5).
- `query` (string, required): What you are about to do, in words.

### `ddflow_lesson_verify` (~100 tokens)

Re-scan every lesson that declared a code `pattern` and report the sites where it has REAPPEARED. Exit 1 names them; exit 2 means no lesson declares a pattern, which is NOT a pass — it means this project has no mechanical ratchet on its lessons yet. Run after a change that touches code a lesson governs.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.

### `ddflow_list` (~264 tokens)

Read-only lists, newest first, 25 rows unless `limit` (0 = the most: 1000, search 200); a cut says so. `kind`: task|phase|bug|research|session|search. Bugs: open unless `all`/`state`. History: ddflow_history.

Input parameters:

- `all` (boolean): kind=bug: include fixed/invalid.
- `as_agent` (string): A subagent's own name, this call only.
- `id` (string): kind=session: one session in full.
- `kind` (string, required): task|phase|bug|research|session|search
- `limit` (integer): Rows (default 25; 0 = the most: 1000, search 200).
- `mode` (string): search: ranked|exact|regex.
- `owner` (string): Only this agent's rows.
- `phase` (string): Only under this phase id.
- `query` (string): kind=search: text to find.
- `since` (string): Changed at/after this ISO date.
- `sources` (string): search: comma-separated record kinds.
- `state` (string): Only this state.
- `tag` (string): Only this tag.

### `ddflow_loops` (~118 tokens)

Detect circular references and runtime loops: dependency cycles, an item claimed and given up over and over, a gate whose verdict keeps flipping, a gate failing again with identical output (repeated_failure), work completed and reopened repeatedly, duplicate items writing the same files, and a queue where events keep arriving but nothing advances. CALL THIS WHEN WORK FEELS REPETITIVE: stop and re-plan rather than retry the same thing. [] when nothing is wrong.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.

### `ddflow_memory_add` (~272 tokens)

Remember ONE operational fact about this machine, repository or working state ('this box has 8 H200s', 'use -n 16, never -n auto'). Shown at the top of every ddflow_brief and found by ddflow_recall, in every worktree at once. Not for rules (ddflow_lesson_add), events (ddflow_session_note) or how the software is built (ddflow_decision_add). Never a secret: the log is committed. Refused over [memory] max_chars (default 280).

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `check_only` (boolean): Dry run: write nothing, return the `candidates` this add would be refused for.
- `id` (string): Re-record an existing memory under its id -- how a fact is CORRECTED. Omit for a new one.
- `relation` (string): Answer to a 'possible duplicate' refusal: new | extends:ID | duplicate_of:ID | related:ID (the refusal lists candidates and options). Omit at first.
- `tags` (string): Comma-separated tags, e.g. 'gpu,machine'.
- `text` (string, required): The fact, in one or two sentences.

### `ddflow_memory_forget` (~99 tokens)

Stop believing a memory that is no longer true. It is kept, with the reason: 'we thought X until Y' is what stops the next agent re-learning X. Correct a fact instead with ddflow_memory_add and its id.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `id` (string, required): Memory id.
- `reason` (string, required): Why it is no longer true.

### `ddflow_memory_list` (~116 tokens)

The project's operational memories, newest first -- or ranked against `query`. What an agent must know before touching anything on this machine; read them at session start if ddflow_brief truncated the list.

Input parameters:

- `all` (boolean): Include forgotten memories, with why they were forgotten.
- `as_agent` (string): A subagent's own name, this call only.
- `limit` (integer): At most this many (default: all).
- `query` (string): Rank by relevance to this instead of by recency.

### `ddflow_merge` (~289 tokens)

Land an item's branch without ever switching a checkout's branch. With [flow].integration = 'pr' it pushes and opens (or updates) a pull request instead, releases your lease and parks the item in REVIEW — take the next item; `ddflow_pr_sync` completes it once a person merges it.

Input parameters:

- `allow_dirty` (boolean): Merge although the worktree has uncommitted changes; they are NOT included. Pass it only once you have looked at what is dirty and decided it is build output.
- `allow_empty` (boolean): Land a branch with no commits ahead of its target. Refused by default: usually the item is bound to the wrong tree (rebind with ddflow_update worktree).
- `as_agent` (string): A subagent's own name, this call only.
- `branch` (string): For an item claimed with no_worktree: the branch to land (default: the branch checked out where this connection runs). Changes outside the item's globs come back as outside_globs.
- `id` (string, required): Item id.
- `keep` (boolean): Keep the worktree after merging, for inspection.
- `message` (string): Merge commit message.
- `model` (string): The AUTHOR's model. In PR mode the item completes later, at `ddflow_pr_sync`, and the reviewer-independence check needs it then.

### `ddflow_next` (~124 tokens)

What may be started RIGHT NOW, and for everything that may not, the reason. Independent items in the ready set can be run in parallel worktrees by separate agents. Returns ready=[] when nothing is actionable — that is a result, not an error, and it never means 'pick something anyway'.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `kind` (string): 'task' (default) or 'phase'.
- `phase` (string): Restrict to one phase (the 'implement phase X' entry point).

### `ddflow_phase_add` (~349 tokens)

Add a phase to the queue. A phase is a unit of REVIEW: it gets its own research, its own whole-phase test pass and live smoke run, and it merges as one coherent feature. Group tasks into a phase when they only make sense shipped together.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `body` (string): Detail, acceptance criteria, context.
- `check_only` (boolean): Dry run: write nothing, return the `candidates` this add would be refused for.
- `globs` (string): Comma-separated path globs this phase writes: what lets two agents work different phases in parallel; the phase's dependencies are INHERITED by every task in it.
- `id` (string, required): Short stable id, e.g. 'P2' or 'auth'.
- `line` (string): Release line this lands on (a name from [flow.lines], or the current line). Omit for the current line; tasks inherit a phase's line.
- `needs` (string): Comma-separated ids this phase depends on.
- `priority` (integer): Lower is offered first (default 100).
- `readd` (boolean): File a REMOVED item's id again with this definition. An id still in the queue is always refused -- change that item with ddflow_update.
- `relation` (string): Answer to a 'possible duplicate' refusal: new | extends:ID | duplicate_of:ID | related:ID (the refusal lists candidates and options). Omit at first.
- `tags` (string): Comma-separated tags.
- `title` (string): One-line description.

### `ddflow_pins` (~199 tokens)

BEFORE compressing or rewording an instruction file (a rulebook, a driver, AGENTS.md, CLAUDE.md, a prompt template): which of its text a test pins, which suites to re-run afterwards, and the longest stretches no test holds. A sentence that reads like rationale is often a rule a test asserts. Exit 2: no Python suite to read pins from -- then treat ALL of it as pinned. Free text is a lower bound, not permission.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `document` (string, required): Path of the instruction file, relative to the repo.
- `min_needle` (integer): Shortest string literal that counts as a pin (default 12).
- `tests` (string): Comma-separated test dirs (default: tests,test).
- `top` (integer): How many free stretches to return (default 10).

### `ddflow_pr_status` (~68 tokens)

Every item's pull request as last recorded — review, checks, target, rounds of changes and when it was last looked at. Reads the log only; `ddflow_pr_sync` asks the forge.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.

### `ddflow_pr_sync` (~151 tokens)

Ask the forge (GitHub/GitLab) what reviewers did with every request in REVIEW and record it: a merged request completes its item (and retargets what is stacked on it), requested changes return the item to the queue WITH the review text, a closed one is parked for a person, an approved green one is merged when [flow].pr_merge = 'on_approval'. `ddflow_next` does this itself with [flow].sync_on_next. Exit 2: the forge could not be asked -- NOT 'nothing changed'.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `item` (string): Only this item (optional).

### `ddflow_pr_threads` (~115 tokens)

An item's review threads, read live from the forge. With `thread`, `reply` on it and/or `resolve` it, so the reviewer sees what was addressed. Exit 2 = forge not reached; 3 = refused.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `id` (string, required): The item.
- `reply` (string): Reply text.
- `resolve` (boolean): Resolve it.
- `thread` (string): Thread id, as listed.

### `ddflow_precommit` (~184 tokens)

A .pre-commit-config.yaml proposed for THIS repository: its stacks (Python, shell, Docker, JS, Go, Rust; YAML/TOML/JSON checks) mapped to pinned hooks, plus ddflow's check-commit and check-msg as local hooks, so pre-commit owns .git/hooks/ (remove ddflow's own first; the body names them). Proposes; installs nothing. `write` creates the file, REFUSED (exit 3) when one exists. The body names missing programs. Installing pre-commit is the operator's call.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `ddflow_cmd` (string): How the local hooks reach ddflow (default `ddflow` on PATH).
- `write` (boolean): Create the file; never replaces an existing one.

### `ddflow_progress` (~128 tokens)

What work has ACTUALLY been done, aggregated from the event log: attempts per item, wall-clock held, gate runs, commits produced, and who did them. Use it to answer 'how much effort has gone into this' and to see an item's full gate history including the outcomes that were not passes.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `id` (string): One item, with its per-attempt detail.
- `limit` (integer): Rows returned, most effort first (default 25; 0 = all).

### `ddflow_promote_add` (~119 tokens)

File a PROMOTION to an environment branch ([flow].environments): a task that merges the branch immediately upstream into it, runs the promotion pipeline and lands by merge or request -- always one step downstream. Exit 2 = nothing to promote; exit 3 = refused (unknown environment, one open, branch missing).

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `env` (string, required): The environment to promote TO.
- `force` (boolean): File it even with nothing to carry.

### `ddflow_promote_deployed` (~83 tokens)

Record the sha a deploy put LIVE in an environment (from the deploy hook); promote_status then shows what runs there. Exit 3 = refused.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `env` (string, required): Environment.
- `sha` (string): Deployed commit (default: branch head).

### `ddflow_promote_status` (~58 tokens)

Each environment: head, commits behind its upstream, open promotion, auto_promote, and the live (deployed) sha. Reads only.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.

### `ddflow_prompts` (~125 tokens)

Inspect the prompt templates this project uses, and where each comes from (shipped default, project override, or an explicit config path). Use `eject` to copy the shipped ones into .ddflow/prompts/ so the project can edit them as plain text — reviewer instructions and workflow commands are operator-tunable behaviour, not code.

Input parameters:

- `action` (string): list (default), show, or eject.
- `as_agent` (string): A subagent's own name, this call only.
- `name` (string): Template name, for show/eject.

### `ddflow_rebuild` (~54 tokens)

Re-derive the search index from the event log. The index is a disposable cache; this is never a data-loss operation.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.

### `ddflow_recall` (~227 tokens)

'HAVE WE BEEN HERE BEFORE?' -- one search across everything this project remembers: decisions, lessons, research verdicts, operational memories, past bugs, similar tasks and the operator's earlier prompts. CALL THIS BEFORE STARTING ANY NON-TRIVIAL WORK, so nothing is said or learned twice. Results are labelled by kind (a binding decision, a transferable lesson and an old prompt change what you do differently); a superseded decision names its replacement -- follow that.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `limit` (integer): Hits per source (default 3).
- `max_chars` (integer): Total budget for the answer. The point of a budget is that recall is called at the START of work, where a long answer costs the context the work itself needs.
- `query` (string, required): What you are about to do, in plain words.
- `sources` (string): Comma-separated subset: decisions,lessons,memories,research,bugs,items,prompts. Default: all.

### `ddflow_recover` (~139 tokens)

Find work left behind by a crashed agent: expired leases, orphaned worktrees, items stuck running. Reports what each worktree contains and never deletes anything. Run this at the start of any session that follows an interruption.

Input parameters:

- `apply` (boolean): Act on the advice: release the leases and remove the worktrees reported as holding nothing. Only a tree MEASURED as having no uncommitted and no unmerged work is touched; 'could not tell' is not 'emp…
- `as_agent` (string): A subagent's own name, this call only.
- `item` (string): Restrict to one item.

### `ddflow_release` (~96 tokens)

Give up a lease without completing the item — when you are handing off, stopping, or recovering someone else's abandoned work after inspecting it. The note is recorded in the log and is often the only lasting explanation of why a claim was broken.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `id` (string, required): Item id.
- `note` (string): Why you are releasing it.

### `ddflow_remove` (~138 tokens)

Take an item out of the queue. The log is append-only, so this RECORDS a removal rather than erasing anything — the item stays in the history and in replay, which keeps the record honest about work that was planned and then dropped. Refuses if another item depends on it.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `force` (boolean): Remove although it still has open children or dependents. Both leave the queue inconsistent in a way the scheduler reports; read the refusal before overriding.
- `id` (string, required): Item id.
- `reason` (string): Why.

### `ddflow_render` (~107 tokens)

Regenerate the human-readable markdown views (queue, lessons, the one-paragraph lessons summary, research) under docs/ddflow/.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `out` (string): Directory for the generated views (default: docs/ddflow).
- `show` (string): Print ONE view instead of writing files: lessons, lessons-summary, research, or board. This is what the ddflow:// resources are served from.

### `ddflow_replay` (~142 tokens)

Reconstruct the project's whole decision history from the log: every operator prompt in order, every architectural decision, every research verdict, every lesson, and the shape of the queue. This is what rebuilds the project if the code is lost — it reproduces the DECISIONS, not the bytes.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `out` (string): Write a recovery kit to this directory.
- `verify` (boolean): Re-resolve every recorded commit sha against this repository and report the ones that are gone: a reconstruction citing unresolvable shas is a narrative, not a record.

### `ddflow_research_add` (~366 tokens)

Record a research finding. verdict MUST be CONFIRMED, REFUTED or THEORETICAL, and CONFIRMED/REFUTED require a probe — a verdict with no probe behind it is an opinion. A REFUTED entry is as valuable as an adopted one: it stops the next session re-researching it.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `budget` (string): What you allowed yourself, e.g. '30 min, no GPU'.
- `check_only` (boolean): Dry run: write nothing, return the `candidates` this add would be refused for.
- `claim` (string): The falsifiable claim.
- `falsifier` (string): The single observation that would kill it.
- `id` (string): Stable id you choose. Referenced by `supersedes`, by commit messages and by the reconstruction; a generated id cannot be cited in advance.
- `item` (string): The task this research is for.
- `mechanism` (string): WHY it would work in this repo. The middle field of the triple — claim, mechanism, falsifier — and the one most often skipped.
- `probe` (string): The command you ran.
- `probe_output` (string): Its output, verbatim.
- `question` (string, required): What was asked.
- `relation` (string): Answer to a 'possible duplicate' refusal: new | extends:ID | duplicate_of:ID | related:ID (the refusal lists candidates and options). Omit at first.
- `sources` (string): Comma-separated URLs/DOIs you actually opened.
- `verdict` (string, required): CONFIRMED | REFUTED | THEORETICAL

### `ddflow_resolve` (~231 tokens)

Settle a CONTESTED item: two clones each added the same id with different content, or each claimed it, and a merge brought both in (`ddflow_doctor` names them, `ddflow_show` lists the rivals, `ddflow_next` withholds them). `keep` names the definition (event id or agent) and/or the lease holder to keep; the losing claim is released in the same transaction; a losing DEFINITION comes back in `lost`: re-add it under a new id with `refile_as`, or it stays only in the log. Refused (exit 3) when not contested.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `id` (string, required): The contested item.
- `keep` (string, required): Event id (or a 6+ character prefix), agent, or lease holder to keep.
- `refile_as` (string): Comma-separated new ids, one per definition NOT kept, in `show` order: each is re-added under its new id in the same transaction.

### `ddflow_review` (~345 tokens)

Run the configured cross-family reviewer over an item's diff and record the result: the critic gate, performed by ddflow. No reviewer, endpoint or verdict records UNAVAILABLE, never a pass. A gate gets [review].max_rounds (default 2) full rounds, then delta=true and ddflow_review_triage.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `base` (string): Ref to diff against (default: the base branch).
- `branch` (string): Review this branch against base, for an item claimed with no_worktree (default: the branch checked out where this connection runs). With neither, the review is recorded unavailable.
- `chunk` (array): Re-review ONLY these chunk numbers (as the recorded review numbered them, e.g. [5]) and merge into that record; needs the same diff, chunk size and reviewer.
- `commit` (string): Review this ONE landed commit (against its first parent) instead of the item's branch: the after-merge review, when the branch is gone.
- `context` (string): Extra context for the reviewer.
- `delta` (boolean): Recheck only what changed since the reviewed head.
- `full` (boolean): Force a full round (else a delta once reviewed).
- `gate` (string): Gate: critic (default) or rubber_duck.
- `id` (string, required): Item whose diff to review.
- `intent` (string): What the change is MEANT to do. The reviewer flags where the diff and the intent disagree, so without it there is nothing to disagree with. Defaults to the item's title and body.

### `ddflow_review_triage` (~208 tokens)

Record your triage of ONE finding of an item's recorded `ddflow review`: it is refuted (probe = the run that shows it false) or confirmed (probe = the fix or test that answers it). The finding number is the #N the review printed. The gate stays failed -- a review that reported findings is not re-recorded as passed; the log shows each finding's fate instead (decision D-review-triage).

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `finding` (integer, required): The finding's number: #N in the review's output -- of the RECORDED reviewer's findings, which the output's last lines name when several ran.
- `gate` (string): Omit if one gate has findings.
- `id` (string, required): The item whose review it is.
- `probe` (string, required): The evidence for the verdict. Required.
- `verdict` (string, required): refuted or confirmed.

### `ddflow_reviewers_detect` (~175 tokens)

Probe well-known local ports for an OpenAI-compatible model server (ollama, vLLM, LM Studio, llama.cpp, sglang) and report what serves, with each model's pretraining family: how to find a reviewer from a DIFFERENT family than yourself, which the critic gate requires. write=true records it in the git-ignored .ddflow/local/reviewers.toml (this machine's, never committed).

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `shared` (boolean): With write: commit them to .ddflow/config.toml instead, for every clone. Only for a reviewer the whole team reaches at the same address.
- `write` (boolean): Append the discovered reviewers to .ddflow/local/reviewers.toml.

### `ddflow_reviewers_list` (~42 tokens)

Show the configured reviewers, their families and which gates they serve.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.

### `ddflow_rule_add` (~229 tokens)

Add a project rule; duplicate-checked like every add (answer new | extends:ID | duplicate_of:ID | related:ID).

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `check` (boolean): Dry run: list duplicates only.
- `content` (string): Rule text (may be empty for check_only).
- `duplicate_of` (string): Dedup answer: same as record ID.
- `extends` (string): Dedup answer: extends record ID.
- `globs` (string): Comma-separated globs it governs.
- `id` (string, required): Rule id, e.g. r-naming.
- `new` (boolean): Dedup answer: a different record.
- `priority` (integer): Priority 0-100 (default 50).
- `related` (string): Dedup answer: related to ID.
- `scope` (string): project (default) | phase | task | global.
- `tags` (string): Comma-separated tags.
- `title` (string, required): One-line rule statement.

### `ddflow_rule_edit` (~115 tokens)

Change fields of an existing rule; omitted fields stay. Recorded in the manifest.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `content` (string): New content.
- `globs` (string): Comma-separated globs.
- `id` (string, required): Rule id to edit.
- `priority` (integer): New priority.
- `scope` (string): New scope.
- `tags` (string): Comma-separated tags.
- `title` (string): New title.

### `ddflow_rule_list` (~89 tokens)

List the project's rules, filtered by tag or scope: what governs the current work.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `json` (boolean): JSON array.
- `limit` (integer): Maximum results (default 100).
- `scope` (string): Filter by this scope.
- `tag` (string): Filter by this tag.

### `ddflow_rule_remove` (~68 tokens)

Delete a rule from the manifest; the removal is logged as an event.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `id` (string, required): Rule id to remove.
- `reason` (string): Why it is removed (recorded).

### `ddflow_rule_search` (~117 tokens)

Search rules by title or content, ranked by relevance, for an area or topic.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `exact` (boolean): Exact phrase.
- `limit` (integer): Maximum results to return (default 10).
- `query` (string, required): Search query (keywords or regex).
- `regex` (boolean): Query is a regex.
- `scope` (string): Filter results by this scope.
- `tag` (string): Filter results by this tag.

### `ddflow_rule_show` (~61 tokens)

One rule with all its metadata: title, content, tags, scope, priority, globs, timestamps.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `id` (string, required): Rule id to retrieve.

### `ddflow_session_end` (~86 tokens)

Close a session with a summary of what it achieved. The summary is what a later reader sees before deciding whether to open the whole transcript, so write it for someone who was not there.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `session` (string, required): Session id.
- `summary` (string): What this session achieved.

### `ddflow_session_note` (~114 tokens)

Record something that happened during a session which is neither an operator prompt nor a decision — a surprise, a dead end, why you changed approach. It goes into the reconstruction alongside the prompts, and a dead end recorded is a dead end nobody walks down twice.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `item` (string): Item it concerns.
- `session` (string): Session id; omit for the latest open.
- `text` (string, required): The note.

### `ddflow_session_prompt` (~107 tokens)

Record the operator's prompt verbatim. This is what makes the project reconstructible from the log alone if everything else is lost. Secrets are redacted before anything touches disk. Call it once per operator turn.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `item` (string): Item it concerns.
- `session` (string): Session id; omit for the latest open.
- `text` (string, required): The prompt, verbatim.

### `ddflow_session_start` (~67 tokens)

Open a session for provenance logging. Returns the session id.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `model` (string): Your model id.
- `tool` (string): Your harness, e.g. 'claude-code'.

### `ddflow_setup` (~231 tokens)

Install ddflow into this repository: creates .ddflow/, writes the driver and the AGENTS.md section, and registers nothing else. Run this ONCE per project, then set your test command with ddflow_configure. Safe to re-run — it updates a managed block and leaves your own prose alone.

Input parameters:

- `agents` (string): Comma-separated agents to write driver deltas for: claude,gemini,codex,copilot,vscode,kilo,cursor,kimi,opencode,glm,qwen,antigravity,devin,qodo,tabnine,aider,cline,windsurf,replit,openhands,goose,cod…
- `as_agent` (string): A subagent's own name, this call only.
- `refresh_docs` (boolean): Rewrite ONLY the driver docs, AGENTS.md/CLAUDE.md blocks and adopted agents' native rules from this ddflow's templates (no MCP, hook or command-file changes), e.g. when ddflow_doctor notes drift. Ref…

### `ddflow_show` (~106 tokens)

Everything known about one phase, task or bug (a bug id works too): state, dependencies, declared globs, the lease and who holds it, the worktree path you can cd to, and every gate's outcome with its evidence. Use it to check your own work before calling ddflow_complete.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `id` (string, required): Item id (phase, task) or bug id.

### `ddflow_similar` (~191 tokens)

'IS THIS ALREADY FILED?' -- the existing records most like a text, BEFORE you file it as a bug, task, lesson or other record. Read-only. Candidates cross kinds and include closed records (a bug that repeats a fixed one is caught); each carries id, kind, title, state, score (0-1), shared words and flags, per [dedupe] show_floor, max_candidates and kinds. A score is a prompt to LOOK, not a verdict. Nothing close: exit 2.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `kind` (string): Comma-separated subset of the configured kinds to look in: bug,task,phase,lesson,decision,research,memory. Default: all of them.
- `text` (string, required): The title or summary of the record you are about to file.

### `ddflow_split` (~195 tokens)

Split an item into sub-tasks IN PLACE when the work turns out to be two things -- the moment you discover it; mid-task discovery is normal. The original keeps its id and history and becomes an umbrella that completes when its children do; closing it and opening two new ones would lose the thread between what was planned and what happened. Children inherit the parent's globs: give each its own afterwards if they write different files, or they cannot run in parallel.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `globs` (string): Globs for the children (default: inherit).
- `id` (string, required): The item to split.
- `into` (string, required): Comma-separated 'sub-id=title' pairs. At least two.
- `needs` (string): Dependencies for the FIRST child. The others chain from it if you set theirs with ddflow_update.

### `ddflow_status` (~106 tokens)

The state of the whole project in one answer: how many tasks are done and which, what is in flight and who holds it, what is ready to start, what is blocked, how many agent-hours and commits went in, and whether anything is looping or waiting to be recovered. This is the tool for 'what is the status of this project?' and 'what has been completed?'.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.

### `ddflow_task_add` (~445 tokens)

Add a task to a phase. ALWAYS set globs to the paths this task will write: they are what lets two agents work in parallel safely, and an unset glob means the conflict detector cannot protect you.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `body` (string): Detail and acceptance criteria.
- `check_only` (boolean): Dry run: write nothing, return the `candidates` this add would be refused for.
- `globs` (string): Comma-separated path globs this task writes.
- `id` (string, required): Short stable id, e.g. 'P2.T1'.
- `line` (string): Release line this lands on (a name from [flow.lines], or the current line). Omit for the current line; tasks inherit a phase's line.
- `lines` (string): Release lines a FIX must reach, e.g. '1,2,3': written where [flow].port_strategy says, plus a port task `<id>@<line>` per other line.
- `needs` (string): Comma-separated ids this task depends on.
- `parent` (string): Owning phase id, OR another TASK's id, which makes this a SUB-TASK with its own globs and dependencies, run in parallel with its siblings. Same field as `phase` (the CLI has both names).
- `phase` (string): Owning phase id. Give this OR `parent`.
- `port_of` (string): Earlier fix this follows up: reuses the lines it reached.
- `priority` (integer): Lower is offered first (default 100).
- `readd` (boolean): File a REMOVED item's id again with this definition. An id still in the queue is always refused -- change that item with ddflow_update.
- `relation` (string): Answer to a 'possible duplicate' refusal: new | extends:ID | duplicate_of:ID | related:ID (the refusal lists candidates and options). Omit at first.
- `tags` (string): Comma-separated tags.
- `title` (string): One-line description.

### `ddflow_tests` (~150 tokens)

AFTER EACH CHANGE: the tests your change reaches (changed tests, tests importing a changed module directly or one step removed, tests named after it, a changed conftest's), each with why, and a command running them IN PARALLEL. Run it; do not reason about which matter. Never a pass: unit_tests runs the WHOLE suite. `item`: diff that item's worktree. Exit 2: no test reaches the change.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `base` (string): Compare against this ref instead of the item's base.
- `item` (string): The item whose worktree and base to use.

### `ddflow_unblock` (~148 tokens)

Release a BLOCKED item -- and every blocked item beneath it -- back into the queue, so `next` can offer them again. The inverse of ddflow_block, and how deferred work, or a whole archived section an import landed as blocked, becomes work once the OPERATOR says so: pass a phase id to release its section. Do not release held work on your own judgement. Returns nothing-to-do (exit 2) when nothing there is blocked.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `id` (string, required): Item id.
- `note` (string): Why it is work again (who decided, and when).

### `ddflow_update` (~353 tokens)

Change an item's fields. MOST IMPORTANT USE: widening `globs` when your work turns out to touch files outside what you claimed. Do that BEFORE writing them: the conflict detector and commit hook work from the declared globs, so an undeclared file is unprotected and the commit is refused.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `body` (string): New detail / acceptance criteria.
- `globs` (string): Path globs this item writes, comma-separated or a JSON array. REPLACES the list (a claimed item's lease too); the result names what it dropped.
- `id` (string, required): Item id.
- `line` (string): Move it to another release line.
- `needs` (string): Comma-separated ids it depends on. Pass an EMPTY string to clear them — that is how you break a dependency cycle the loop detector found.
- `priority` (integer): Lower is offered first (default 100).
- `resources` (string): Physical resources the work RUNS on, beside its files: 'gpu:4,vllm-fleet'. `next` withholds and `claim` refuses while live claims use up the capacity ([schedule] resources). Declare for a GPU job, mo…
- `tags` (string): Comma-separated tags.
- `title` (string): New title.
- `worktree` (string): Rebind the item and your live lease to this linked worktree (absolute, or repo-relative) and its branch: the way out of a wrong-tree binding, since re-claiming keeps the recorded tree and merge lands…

### `ddflow_verify` (~166 tokens)

Re-check a done task's claims; fails if one does not hold. No id: sweep all, worst first.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `file_bugs` (boolean): File a bug per failing completion.
- `force` (boolean): Reopen even if it holds.
- `id` (string): Task id; omit to sweep.
- `judge` (boolean): Cross-family reviewer judges it.
- `limit` (integer): How many of the worst to list (20).
- `pack` (boolean): Evidence pack for a verifier.
- `phase` (string): Sweep only this phase.
- `reason` (string): Why (reopen).
- `reopen` (boolean): Reopen a failing completion.

### `ddflow_version_cut` (~179 tokens)

Tag the next version. trunk: tags the base branch. gitflow: release/X from develop, merged to production, tagged, tag merged back; with pull requests, opens the release request (`ddflow_pr_sync` tags it once merged). Exit 2 = nothing to release.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `bump` (string): major | minor | patch.
- `changelog` (boolean): Also write CHANGELOG.md.
- `dry_run` (boolean): Report only.
- `force` (boolean): Overwrite a hand-edited file.
- `line` (string): A maintenance line: tagged where it stands; its major is kept.
- `push` (boolean): Publish the tag and branches.
- `version` (string): MAJOR.MINOR.PATCH.

### `ddflow_version_show` (~109 tokens)

The current version (highest `<tag_prefix>X.Y.Z` tag reachable from the release branch), the next one, the bump and why (Conventional Commits plus the tags of finished items), and the release notes. Reads only.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `bump` (string): Force major | minor | patch instead of the computed bump.
- `line` (string): A maintenance line (default: the current one).

### `ddflow_wait` (~280 tokens)

Sleep until an item can be claimed (or, with no item, until anything is ready) and return the moment it can. Use it instead of polling or asking the operator when a claim was refused for another agent's lease or overlapping files, or an unfinished dependency someone is working on. Exit 0: claim now (it says what freed it). Exit 2: deadline passed, or waiting cannot help (done, cycle, operator hold, a dependency nobody works on) and it says what to do. The holder is told you wait.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `globs` (string): With item: the globs you will claim with (comma-separated or a JSON array), so ready means that claim will not be refused for them.
- `item` (string): The item to wait for (default: anything ready).
- `kind` (string): 'task' (default) or 'phase'.
- `phase` (string): With no item: anything ready in this phase.
- `poll` (number): Seconds between log checks (default 2).
- `timeout` (number): Seconds to wait (default 300, at most 1800: a client may time a tool call out, so call again to keep waiting). 0 asks without waiting.

### `ddflow_workflow` (~115 tokens)

The rules THIS project runs by, in one answer: the gates every task and phase passes in order, the completion rules, parallelism caps, reviewers, and where each value came from. Call it before your first `ddflow_claim` and after any workflow change: instructions are computed once at start. Exit 1: the workflow does not hang together (e.g. a pipeline names a gate with no definition). Read-only.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.

### `ddflow_workflow_drop` (~130 tokens)

Take a gate out of both pipelines, and out of `required`, so it does not become a requirement that requires nothing. WRITES config. The gate's DEFINITION stays, so putting it back is one call. Exit 2: it was in neither pipeline. Ask the operator first: a gate in a pipeline is a check somebody added on purpose.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `dry_run` (boolean): Report the change and write nothing.
- `id` (string, required): The gate id to remove from the pipelines.

### `ddflow_workflow_gate` (~323 tokens)

Define or change one gate, optionally in a pipeline. WRITES the project config. `command` makes a COMMAND gate (ddflow runs it; its exit code is the evidence); `prompt` makes an AGENT gate (you perform and record it); one is required. `into` adds it to a pipeline (`after` places it, default last); `required` blocks completion without it. Ask the operator first; prefer dry_run.

Input parameters:

- `after` (string): Place it after this gate. Default: last.
- `applies_to` (string): 'task', 'phase' or 'both'.
- `as_agent` (string): A subagent's own name, this call only.
- `command` (string): Shell command to run. Makes it a command gate.
- `cwd` (string): 'worktree' (default) or 'repo'.
- `dry_run` (boolean): Report the change and write nothing.
- `id` (string, required): The gate id, e.g. 'lint' or 'security_scan'.
- `into` (string): Add to the 'task', 'phase' or 'both' pipeline(s).
- `prompt` (string): What an agent must do. Makes it an agent gate.
- `required` (boolean): An item cannot complete without it.
- `reviewer` (string): 'different_family' to require a reviewer from another model family, or 'same_family_ok'.
- `timeout` (integer): Seconds before the command counts as unavailable.
- `title` (string): Human-readable name.

### `ddflow_workflow_pipeline` (~161 tokens)

Set the ordered list of gates a task or a phase must pass. WRITES this project's config. Validated first: a gate id with no definition is REFUSED (it would block every item that reaches it); define it with `ddflow_workflow_gate`. Ask the operator before changing a pipeline -- it governs every future item, and removing a gate removes a check somebody added on purpose. dry_run shows what it would do.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.
- `dry_run` (boolean): Report the change and write nothing.
- `gates` (string, required): Comma-separated gate ids, in the order they run.
- `which` (string, required): 'task' or 'phase'.

### `ddflow_workflow_state` (~62 tokens)

One-call project overview: workflow, rules, decisions, active work, queue and bugs with names and priorities, blockers, and a Mermaid gate diagram. Read-only.

Input parameters:

- `as_agent` (string): A subagent's own name, this call only.

## Diagnostics

Captured diagnostic sections: Provenance, Vulnerabilities. The full working is on the page: https://verifymcp.io/servers/delian-ddflow-mcp/docker-io-delian-ddflow-mcp#diagnostics

## Score history

- 2026-10-04: 9
- 2026-10-03: 39
- 2026-10-02: 39

## Common questions

### What is the ddflow MCP server?

ddflow is an MCP server listed in the public MCP registry as io.github.delian/ddflow-mcp. Work-queue kernel for AI coding agents: dependencies, worktree isolation, quality gates, recovery. This page covers its container image (docker.io/delian/ddflow-mcp).

### Is the ddflow MCP server safe to use?

ddflow scores 9 out of 100 on VerifyMCP. The SBOM its publisher attached lists packages with 12 known advisories as of 4 October 2026. We do not grade that SBOM, as nothing verifies it. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the ddflow MCP server expose?

ddflow exposes 106 tools: ddflow_abandon, ddflow_bisect, ddflow_block, ddflow_board, ddflow_brief, and 101 more. Their descriptions and schemas cost roughly 16,898 tokens of context every time the server is loaded.

### Is the ddflow MCP server still maintained?

ddflow is still listed as active in the MCP registry. We last reached this channel on 4 October 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What licence is the ddflow MCP server under?

ddflow declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.

## Links

- Docker Hub: https://hub.docker.com/r/delian/ddflow-mcp
- Repository: https://github.com/delian/ddflow-mcp
- Changelog RSS feed: https://verifymcp.io/servers/delian-ddflow-mcp/docker-io-delian-ddflow-mcp.xml
- Changelog JSON feed: https://verifymcp.io/servers/delian-ddflow-mcp/docker-io-delian-ddflow-mcp.json
- HTML version of this page: https://verifymcp.io/servers/delian-ddflow-mcp/docker-io-delian-ddflow-mcp
