/conclave-dev [—no-interaction] [—loop] [US-NNN|BUG-NNN …]
Pick up user stories from the active sprint (or bugs from the bug backlog) and drive them through implementation. When this finishes, every item is in status: review with its own feature branch and PR ready for QA verification — or, with --loop, done with an approved PR waiting for you to merge.
/conclave-dev US-001 # single story — identical to previous behaviour
/conclave-dev US-001 US-002 US-003 # three stories in parallel, each its own branch + PR
/conclave-dev --no-interaction US-001 # headless; ends at review
/conclave-dev --loop # three waves over the active sprint: Dev → QA → Tech LeadOutside loop mode at least one US-NNN/BUG-NNN argument is required; every US-NNN must match a story file under the active sprint, every BUG-NNN a file under conclave/product/bugs/. Multiple IDs are processed in concurrent batches of ≤ 3, each with an independent branch and PR. In loop mode the argument list is optional — with no IDs the loop takes the active sprint. The single-story path is fully backward-compatible.
| Mode | How | Behavior |
|---|---|---|
| Interactive (default) | No flag | Prompts where needed. Ends at review. |
| Autonomous (v0.9.0+) | --no-interaction / --headless, or commands.dev.interactive: false | Zero prompts, documented defaults, per-item run-report section. Ends at review. |
| Three-Wave Delivery Loop (v0.15.0+) | --loop, or commands.dev.loop: true | W1 Dev + CI → W2 QA → W3 forced Tech Lead, failures return to W1, plus a run report. Implies autonomous. |
No mode merges a PR. Since 0.15.0 nothing in Conclave runs gh pr merge — landing the code is yours (ADR-006).
Multi-story behaviour
When more than one story ID is passed:
- Upfront validation — all stories are checked before any work starts. If any story fails (not found, wrong status, already in-progress on a branch), the entire invocation is refused with a per-story error table.
- Concurrent batches — stories are partitioned into groups of ≤ 3. All stories in a batch run simultaneously; the next batch starts only after the previous one completes.
- Failure isolation — a failed story is reset to
status: ready; the rest of the batch continues. A final summary table shows the outcome for every story.
| Story | Branch | PR | Outcome |
|--------|-------------------------|------------------------------|-------------------|
| US-001 | feat/US-001-login | https://github.com/…/pull/42 | ✓ done |
| US-002 | feat/US-002-profile | https://github.com/…/pull/43 | ✓ done |
| US-003 | feat/US-003-settings | — | ✗ failed: <error> |What it does
- Verifies the working tree is clean (refuses on a dirty tree).
- Locates the active sprint and the story file. Refuses if the story is past the dev gate.
- Checks the assignee — if it does not match you, asks whether to take over.
- Loads context:
config.md(profile + peer-review flag), architecture, DoD, roster (with a one-time compatibility warning if it predates theDisciplinecolumn), story, acceptance. - Creates branch
feat/US-NNN-<slug>from the integration branch. - Marks the story
in-progressin its own commit (visible to the team immediately). - Reads the story’s
disciplineand delegates to the matching subagent. The agent:- Reads story, acceptance, architecture, DoD.
- Plans a technical breakdown (scratch only — not committed).
- Detects or bootstraps the test/verification setup.
- Implements story-then-verify, scenario by scenario. Each Gherkin scenario gets at least one form of verification (a passing test for Developer/DevOps, a design decision for Designer).
- Runs the full test suite / final check once at the end.
- Lints / typechecks (where applicable).
- Commits in scoped chunks (
feat(US-NNN): ...). - Renders the PR body from
templates/pr-body.template.md.
- Pushes the branch.
- Opens the PR via
gh pr create(or prints the prepared command ifghis missing). - Tags a peer reviewer if
peer_pr_review.required: true— picks one from the roster, excluding the assignee. - Marks the story
status: review.
Discipline routing
Story discipline | Charter |
|---|---|
frontend, backend, multi, or unset (pre-0.2.0 stories) | developer.md |
design | designer.md — design artifacts and Frontend handoff notes only, never application code |
devops | devops.md — CI/CD pipelines and infrastructure-as-code, same implement → verify → PR loop as Developer |
All three charters share the same inputs, outputs shape, and PR-body template — only the domain of what gets built differs.
What it produces
- Code (or, for
design, handoff notes) + verification evidence in the repo. - A feature branch
feat/US-NNN-<slug>pushed toorigin. - A PR (or prepared
gh pr createcommand). - Story-file frontmatter updated:
assignee,status: review.
Hard rules the execution subagent follows
- Every Gherkin scenario maps to at least one form of verification.
- No architectural deviation without an ADR proposal in the PR body.
- Never modifies acceptance criteria. If they look wrong, flags it via a comment, does not silently fix.
- Touches no file under
conclave/except its own story file’s frontmatter. - Never merges its own PR.
Profile awareness
peer_pr_review.required: true→ tags a peer (typically the Tech Lead) as reviewer, PR body’s conditional checklist includes the TL-approval item.peer_pr_review.required: false→ no separate reviewer required. The Dev still self-reviews.
Guardrail change from v0.5.0
Previously the command refused to start if any story was already in-progress. The updated rule: a story is refused only if that exact US-NNN is already in-progress on an existing branch. Other stories being in-progress on their own branches is expected and allowed.
Resume on an existing branch
If feat/US-NNN-<slug> already exists locally (the story is in-progress from a prior run), the command offers three options: switch and resume, delete and recreate, or abort. On resume, the execution subagent reads what already exists in the branch before adding new code.
Autonomous mode (v0.9.0+)
/conclave-dev supports a headless mode that never calls AskUserQuestion. Activate it in one of three ways:
# 1. Ad-hoc CLI flag (highest priority; overrides config.md)
/conclave-dev --no-interaction US-042 # --headless is a synonym
# 2. Repo default — add to conclave/config.md
commands:
dev:
interactive: false
# 3. Implicit inside /conclave-sprint — Phase 2 forces autonomous mode regardless of config.md
/conclave-sprintWhat changes
- No prompts. Every
AskUserQuestionsite applies a documented default from the “sensible defaults” catalog. Cases without a safe default abort with a specific reason. - Per-run report appended to the story file as a new
## Autonomous run — <ISO>section (seeskills/conclave/templates/autonomous-run.template.md). Mode: autonomousline printed once at the start of the run. Interactive mode is silent — noMode:line means interactive.
Sensible defaults catalog
| Interactive prompt | Autonomous default |
|---|---|
Assignee mismatch (story’s assignee ≠ runner’s git config user.name) | Take over — reassign to runner; recorded as assignee_takeover: <old> → <new> |
| Existing local branch with no story commits | Delete and recreate from integration branch; recorded as branch_recreated |
| Existing local branch with prior story commits by the same runner | Switch and resume; recorded as branch_resumed: from <sha> |
Existing local branch with commits by another git config user.email | Abort — AUTONOMOUS_ABORT: story branch has commits from another dev (<their email>); manual coordination required |
Abort scenarios (subagent-side)
The Developer subagent returns AUTONOMOUS_ABORT: <reason> when:
- No test framework detected — the story would require bootstrapping one (a human decision).
- New dependency required not in any ADR — adding a dep is a scope change; the TL should have authorised it via
/conclave-adrfirst. - Ambiguous Gherkin scenario — two plausible interpretations and nothing (ADR, story text, technical notes) disambiguates.
- Story requires an architectural change — needs
/conclave-adrfirst, not/conclave-dev.
On abort, the story frontmatter is reset to status: ready. Nothing is pushed. A ## Autonomous run — section with Outcome: aborted and the abort line under Blockers is appended to the story file. Re-run interactively (/conclave-dev US-NNN without --no-interaction) to resolve the ambiguity.
Example run-report section
## Autonomous run — 2026-07-06T15:23:11Z
- **Outcome**: done
- **Branch**: `feat/US-042-jwt-middleware`
- **PR**: https://github.com/foo/bar/pull/123
- **Duration**: 4m 22s
- **Runner**: gio (git config user.email = gio@example.com)
- **Config source**: --no-interaction CLI flag
### Autonomous decisions
- assignee_takeover: alice → gio — story executed by whoever ran the batch
- test framework selection: vitest — already in package.json; architecture.md Confirmed stack lists it
### Files touched
- `src/middleware/jwt.ts` (new, 47 lines)
- `tests/middleware/jwt.test.ts` (new, 6 tests)
### Tests
- Gherkin scenarios covered: 3/3
- Suite: `pnpm test` → 342 pass, 0 fail
- Lint: 0 warningsFor blocked and aborted outcomes, the section additionally includes a ### Blockers subsection with the failure or abort line verbatim.
Asymmetry: no --force-interaction flag
There is intentionally no CLI flag to force interactive mode when config.md says autonomous. A CI job with interactive: false in its config.md fork must not be able to hang on a stray flag. To debug, edit config.md locally or use a different repo/branch. The same asymmetry applies to --loop: there is no flag to disable a configured loop for one invocation.
Autonomous Three-Wave Delivery Loop (v0.15.0+)
Autonomous mode above stops at status: review. Loop mode keeps going — it takes the active sprint (or the IDs you pass) and runs it through three ordered waves, ending with approved PRs that a human merges:
/conclave-dev --loop # every non-done story in the active sprint
/conclave-dev --loop US-042 US-043 # a subset
/conclave-dev --loop BUG-004 # bugs are allowed when passed explicitly
/conclave-dev --loop --ignore-schedule US-042 # bypass the schedule window for this run
# Repo default (see the warning below):
# commands:
# dev:
# loop: true--loop implies --no-interaction — a loop that prompts is not a loop.
The three waves
| Wave | What happens | Advances when | On failure |
|---|---|---|---|
| 0 — Conflicts | Order the scope by dependencies:; serialize stories that would collide on the same files | An execution order exists | A dependency cycle aborts the run, naming the cycle |
| 1 — Dev | Implement, push, open the PR against repo.integration_branch, poll CI | Every story is review with green checks | Retry up to budgets.max_attempts_per_story |
| 2 — QA | Headless /conclave-qa: no prompts, declines writing new CI workflows | Every story is verified | Back to Wave 1 with QA’s blockers |
| 3 — Tech Lead | /conclave-pr-review, forced even when peer_pr_review.required: false — ephemerally, config.md is never rewritten | Every story is done with an approving review | Back to Wave 1 with the review findings, then Wave 2 again |
A wave starts only once the previous one has resolved for the whole scope. Every failure returns to Wave 1: changed code invalidates the QA verdict that preceded it, so QA always re-runs after Dev rather than the Tech Lead approving something QA has not seen in its current state.
A structural AUTONOMOUS_ABORT (no test framework, unauthorised dependency, ambiguous Gherkin, architecture change needed) stops retrying that story immediately and alerts a human — a retry cannot resolve a decision that needs one.
It never merges
The terminal state is an approved, open PR. No path in Conclave runs gh pr merge since 0.15.0. The run report and the Slack message both list the PRs waiting for you, each with a copyable merge command. repo.integration_branch is only the PRs’ base branch.
For a BUG-NNN, the PR body’s Fixes #<n> line closes the mirrored GitHub issue when you merge.
Scope, scheduling, and budgets
commands.dev.schedule is a recurring local-time window (timezone, days, start_time, end_time, duration_days, active_from) and commands.dev.budgets caps attempts, CI wait, wall-clock, and a best-effort token ledger. There is no inheritance from commands.sprint.* anymore — the sprint command has no delivery schedule. See Scheduling and Configuration.
What it does not do
- It never merges. Approved PRs are the output.
- It never closes the sprint. When every non-retired story ends up
done, it prints a hint; closing stays with/conclave-review. - It never runs waves concurrently. Batch-of-3 exists only inside Wave 1, and only for stories with no dependency or file overlap between them.
- It never skips QA. The gate is Wave 2, executed headless.
Run report
Written at start with outcome: in_progress, finalized in place at the end:
| Situation | Path |
|---|---|
A sprint exists (active or draft) | conclave/sprints/SPRINT-NNN/runs/RUN-NNN-dev-loop.md |
| No sprint at all (bug-only repo) | conclave/runs/RUN-NNN-dev-loop.md |
The report is also the concurrency lock: a run whose scope shares an ID with a live run is refused, while non-overlapping scopes may run in parallel. One report covers the whole loop including re-entries — PRs awaiting merge, per-story wave counts and cycle time, agent productivity per role (dispatches, first-pass success, rework caused, tokens per story), the token ledger, conflicts, budget usage, and sprint_closed: false.
Slack, when enabled, gets a success, partial, or “needs human” message drawn from those same figures — see Scheduling.
Prerequisite
The loop needs the GitHub CLI (gh) installed and authenticated (gh auth login) with access to this repository — push, PRs, and reviews. Conclave does not install or configure gh, and refuses to start the loop without it.
commands.dev.loop: truemakes every/conclave-devinvocation in that repo a full three-wave run, including a quick single-story one. Prefer the--loopflag unless the repo exists to be driven unattended.
Architecture: ADR-006 .
After it runs
- Interactive / autonomous (no
--loop): QA verifies with/conclave-qa US-NNN, then Tech Lead with/conclave-pr-reviewwhen peer review is on. - Loop mode: QA and the Tech Lead already ran. Open
RUN-NNN-dev-loop.md, review the approved PRs, and merge them yourself:
gh pr merge <n> --squash --delete-branchFull weekend recipe (config, trigger, Slack, merge): Scheduling.