flow
plugin Β· agent-ops
The /flow workflow engine: a PM-agnostic, dual-mode (manual and autonomous) system that carries product work from capture to done across one stage spine, with a runnable-TypeScript engine and a pluggable tracker adapter.
What this package does
Adds slash commands
Files will be staged under .dork/marketplaces/dorkos/flow/
Adds skill files
Files will be staged under .dork/marketplaces/dorkos/flow/
Installs lifecycle hooks
Files will be staged under .dork/marketplaces/dorkos/flow/
The full permission preview, including external network hosts, is shown when you confirm install in DorkOS.
flow β the /flow engine
One unified, PM-agnostic workflow system spanning capture β done. A single identifiable installable unit: manual stages you drive from the terminal, and an autonomous loop seated on DorkOS Pulse.
This README is the manual. See for the contract (the
stage model, the PMClient promotion surface, the config schema, the FlowRun
record, and the typed engine), for the 15 goals the
system is audited against, and the published
on dorkos.ai for the user-facing reference. These three docs and the guides ship
with the package (charter G15); the manifest enumerates them as docs members.
[!IMPORTANT] Autonomous mode depends on a running DorkOS server (Pulse). Manual mode does not.
/flow,/flow:<stage>, and/flow auto(terminal draining) run without the server. The autonomous Pulse-seated loop (${CLAUDE_PLUGIN_ROOT}/skills/flow-drain/) requires the DorkOS server running to host the chokidar watcher + croner.
Stages
One canonical spine β the unit of "where work is." Spec status, tracker state, labels, and loop phase are all projected from the stage by the adapter, never authored independently.
- CAPTURE β quick, low-commitment intake of a raw thought as an
idea. Does not evaluate or classify. (capturing-work) - TRIAGE β classify freeform input into a type, or evaluate a captured item
(accept / reject / needs-research / needs-refinement) and make the
simple-vs-complex routing call. (
triaging-work) - IDEATE β shape a complex brief into a structured ideation artifact.
(
ideating-features) - SPECIFY β turn ideation into a frozen specification + draft ADRs.
(
specifying-work) - DECOMPOSE β break the spec into
03-tasks.jsontasks (mirrored to the tracker as a checklist; promote a sub-issue only atsize β₯ "xl"). (decomposing-work) - EXECUTE β implement the tasks across dependency-aware batches in an
isolated worktree. (
executing-specs) - VERIFY β run the touched surface, capture proof-of-completion evidence,
open the PR, and hand off to review. (
verifying-work) - REVIEW β the human gate. The engine parks here; there is no skill and no command. On approval + green CI it resumes into DONE.
- DONE β close the work, create follow-ups, run the project-pulse check, and
tear down the worktree. (
closing-work) - MONITOR / SIGNAL β the optional tail that keeps the loop spinning.
Match on a tracker state's category (backlog | unstarted | started | completed | canceled), never its display name β that is what keeps the
system portable across teams and trackers.
Modes
The trigger source is orthogonal to the execution mode β a 2Γ2, not a single axis:
- Manual + Step β
/flow:<stage>advances one stage and stops. Questions arrive interactively. Server-free. - Manual + Autonomous β
/flow autodrains the ready queue sequentially from the terminal, carrying each item to its review gate. Server-free. - PM-driven + Step β rare; an explicit single-stage advance triggered by a tracker transition.
- PM-driven + Autonomous β the default seat: a Pulse tick claims the top-ranked eligible item and carries it to its gate in a fresh per-item session. Requires the DorkOS server (see below).
Every stage is autonomous-capable. The human is pulled in by uncertainty (the calibration ladder), not by stage β which is why IDEATE asks freely while EXECUTE asks rarely, as an emergent property of one rule.
Command β state map
Each /flow:<stage> command is a thin trigger (β€ ~40 LOC) over the stage
skill. A PM transition into a stage and the slash command are two triggers for
the same skill. The mapping is generated from
stages:
/flow (no stage) is the orchestrator: it resolves a stage name, a work item, a
project (by name, spec slug, or umbrella id), or auto, then routes to the matching
command. Naming a project routes by its state: project-scoped single-item dispatch when it
has agent/ready children, or advancing its umbrella one stage when it has none yet
(/flow auto|continue <project> narrow the queue modes to that one project). With no
arguments at all, it offers four intents: Capture new Β· Work on a project (pick
from the active projects) Β· Continue the queue (claim the next-ranked item, carry it to
its gate, then stop) Β· Triage the backlog, with a specific item or auto (drain the
whole queue) reachable as free text. "Continue the queue" is one tick of auto.
Gates
Involvement is uncertainty-gated, not stage-gated (the calibration ladder, spec Β§5). The hard gates:
- Question / soft-escalation β any stage, dynamic; driven by the calibration ladder. Row 0 (the floor) always stops for irreversible/destructive, outward-facing, secrets/spend/prod, or material-scope-change actions, even at full confidence.
- Plan-approval gate (after DECOMPOSE) β off by default
(
gates.planApproval: false). The engine flows DECOMPOSE β EXECUTE and surfaces plan assumptions at the review gate. Flip it on for a pre-code checkpoint. - Human-review gate (after VERIFY) β always on. PR + evidence β review
state β assign the human β stop. On approval + green CI β auto-merge + close +
teardown. v1 caveat: the engine parks here and does not detect approval
β merge the approved PR yourself, then run
/flow:done <issue>to close the item and tear down the worktree. The merge-decision logic (evaluateAutoMerge, Β§6 below) is built + tested; the detection + execution that fires it unattended (poll/webhook-driven resume-on-approval) is the P2 server Extension. - Circuit breaker β stop + escalate if a unit exceeds
estimate Γ Nwall-clock or the token budget.
Auto-merge recovery ladder (spec Β§6): approval authorizes one specific state β this diff, green, cleanly mergeable. If that state can't be reproduced at merge time, the engine checks mergeable? Β· CI green? Β· functionally unchanged? and routes each failure through the calibration ladder (mechanical conflict β resolve
- announce; real tradeoff β bounce; behavior drift β re-request approval).
Adapter interface
The linear-adapter skill is the v1 PMClient: it owns every tracker
call (Linear MCP primary, Composio --account personal fallback) and fulfils the
capability verbs as a documented prose contract. Generic stage skills call it
by naming a verb (e.g. "via the linear-adapter, transition the item β¦") and
never touch a tracker string β a grep guard enforces zero mcp__linear__* /
Composio strings outside the adapter.
The verbs: getCurrentUser, getProjects, resolveProject, getProject,
getProjectWork, getEligibleWork, getInbox, getRelations, claim,
transition, comment, assignToHuman, attachEvidence, needsInput, link,
createSubIssue. The adapter normalizes
every tracker into one WorkItem shape so the dispatch policy and stage skills
never see a tracker-specific field. Full verb contract: the adapter's
; the typed interface PMClient
the P5 server build promotes it into is in .
The adapter also owns the display convention: every work item shown to a human
is rendered as DOR-157 - Title (identifier first, the identifier linked where the
surface supports it), never a bare key.
Autonomous mode & the server dependency
The autonomous loop is seated on DorkOS Pulse via a file-based schedule
(${CLAUDE_PLUGIN_ROOT}/skills/flow-drain/SKILL.md). Pulse already provides a contextless
code-loop (croner) that dispatches a fresh, isolated, resumable, runtime-agnostic
agent session per run β so there is no scheduler to build.
- One tick = one issue. Each croner fire is a fresh run-session
(
sessionId = run.id) that claims and works exactly one issue to its gate, then ends β preserving fresh-session-per-issue. - Activation requires the DorkOS server running (hosts the watcher + croner)
and the project's DorkOS agent registered (a global
~/.dork/tasks/task is watched unconditionally). No build step, no migration β dropping the file is picked up live. - Crash/stall recovery is driven by the durable
FlowRunrecord + the next-tick recovery ladder (spec Β§12): aneeds-inputitem is never reclaimed; an orphanedagent/claimeditem is adopted + resumed (re-attach the worktree at HEAD, resume the session) or restarted clean, withattemptCountguarding against runaway retries.
Autonomous mode depends on a running DorkOS server (Pulse); manual mode does not. A generic
claude -p-per-issue watcher seat (for non-DorkOS repos) is designed but not built in v1 β soautonomy.seataccepts onlypulsetoday, andwatcherrejoins the enum when the seat ships. (The "watcher" is the external poller that fires a headlessclaude -ptick per issue β not a prompt.)
Configuration
Defaults live in , validated against the
Zod-generated (authored as the
@dorkos/flow FlowConfigSchema, bridged via z.toJSONSchema). The resolved
defaults encode the key decisions: planApproval: false, subIssueThreshold: "xl",
perIssue: "fresh-session", seat: "pulse". See β
Config schema reference for the full contract.
A per-repo WORKFLOW.md override at the repo root is part of the config
contract (Decision #15), but v1 reads .agents/flow/config.json only β
applying the override is the promoted config loader's job (DOR-90 / the P5 server
build), not the v1 harness skills. A WORKFLOW.md will not take effect yet.
Templates
The system owns a template set under , loaded by skills (not projected to any harness):
- β tracker work-item bodies by
type (
ideaΒ·researchΒ·hypothesisΒ·taskΒ·project), each with## Validation criteria+## On Completion. - β the filesystem doc scaffolds
(ideation Β· specification Β·
03-tasks.jsonΒ· ADR). - β the PR template the VERIFY stage fills at the review gate.
Install
dorkos install flowOr browse the catalog inside DorkOS at /marketplace.