Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/implementation/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "implementation",
"version": "0.19.0",
"version": "0.19.1",
"description": "Disciplined implementation stage: execute approved plans inline (`/implementation:implement`) or via orchestrated worker subagents (`/implementation:implement-dispatch`) with incremental validation, TDD-by-default cadence, green-checkpoint commits, scope-fence drift detection, and divergence detection that routes back to planning. Build/test/lint, testing, and outcome verification live in the companion `toolchain`, `testing`, and `verification` plugins, invoked when installed.",
"author": {
"name": "Melodic Software",
Expand Down
14 changes: 14 additions & 0 deletions plugins/implementation/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@
All notable changes to the `implementation` plugin are documented here. Format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning.

## [0.19.1] - 2026-09-27

### Fixed

- **`implement-dispatch` defines the wave, and one git writer per worktree binds under both
commit authorities.** A wave is a batch of one phase's worker rows, each an independent brief
with its own disjoint fence, and `--wave-cap` bounds the rows in flight at once; waves never
span phases. 0.18.0 added commit authority `orchestrator` with its single-committer
Concurrency rule (#4511), but that rule bound only under `orchestrator`. Under the default
`worker` authority, rows that share a worktree now run one at a time whatever the cap, since a
worktree has one index and one HEAD; concurrent rows in a shared worktree need `orchestrator`.
The wave-cap eval now runs its rows under `orchestrator`, and a new eval covers two `worker`
rows sharing a worktree (#4262).

## [0.19.0] - 2026-09-27

### Changed
Expand Down
17 changes: 11 additions & 6 deletions plugins/implementation/skills/implement-dispatch/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Structural variant of `/implementation:implement` for orchestrated execution: th

**Orchestration mode detection**. Infer autonomous vs interactive from the session shape: a goal/loop harness driving turns with no human in the cycle, a plan that declares itself autonomous-ready, or an explicit orchestration instruction means **autonomous**; a human reviewing each turn means **interactive**.

**Autonomous:** the main window is orchestrator only. Dispatch workers per phase; orchestrated cadence is the **default** even when the plan's routing is all-main-window (synthesize per-phase worker rows from the plan). Cap concurrent dispatch waves at 3–5 workers by default; when the caller passes `--wave-cap <N>` (see Arguments), for example `/work-items:work` threading its `work_dispatch_concurrency_cap`, cap at that `N` instead of the internal 3–5. The parameter is the single enforcement point for a caller-configured concurrency ceiling; omitting it keeps the internal default, so existing callers are unaffected.
**Autonomous:** the main window is orchestrator only. Dispatch workers per phase; orchestrated cadence is the **default** even when the plan's routing is all-main-window (synthesize per-phase worker rows from the plan). A **wave** is a batch of one phase's worker rows dispatched together: each row is an independent brief with its own disjoint fence, waves never span phases (see Arguments), and a phase with more rows than the cap runs them as sequential waves. Cap each wave at 3–5 concurrent worker rows by default; when the caller passes `--wave-cap <N>` (see Arguments), for example `/work-items:work` threading its `work_dispatch_concurrency_cap`, cap at that `N` instead of the internal 3–5. The parameter is the single enforcement point for a caller-configured concurrency ceiling; omitting it keeps the internal default, so existing callers are unaffected. Whatever the cap, one git writer per worktree binds under both commit authorities (see Commit authority), so under the default `worker` authority rows that share a worktree run one at a time.

**Interactive:** read the plan's execution-shape/routing table. Worker rows present (any surface other than main-window) → this skill's dispatch cadence for those phases. Routing table absent or all main-window → `/implementation:implement` classic inline cadence instead.

Expand All @@ -28,7 +28,7 @@ Structural variant of `/implementation:implement` for orchestrated execution: th

The **phase selector** (e.g. `phase-2`) scopes the dispatch cadence to that plan phase only. Otherwise walk the remaining plan phases strictly in order. Never dispatch a later worker-routed phase past an incomplete earlier phase: dispatch each worker-routed phase as it becomes current; in interactive mode, at the first inline-routed phase hand back by invoking `/implementation:implement` via the Skill tool (classic cadence) and re-enter here when a later worker-routed phase becomes current. Under autonomous mode every remaining phase dispatches in order, synthesizing worker rows per the Autonomous rule above when the routing table lacks them.

`--wave-cap <N>`. An optional positive-integer ceiling on **concurrent dispatch waves**. When passed, it replaces the internal 3–5 default (see the Autonomous rule); when omitted, the internal default stands. This is how a chaining caller threads a configured concurrency cap in. `/work-items:work` passes its resolved `${user_config.work_dispatch_concurrency_cap}` here, and passes nothing when that key is unset so the internal default applies. Waves are discrete: floor a fractional argument to `⌊N⌋` (e.g. `2.5` → `2`) and treat `< 1` as `1`, so a stray non-integer never produces a fractional or zero cap.
`--wave-cap <N>`. An optional positive-integer ceiling on **worker rows in flight at once within one phase**, the size of a wave. When passed, it replaces the internal 3–5 default (see the Autonomous rule); when omitted, the internal default stands. This is how a chaining caller threads a configured concurrency cap in. `/work-items:work` passes its resolved `${user_config.work_dispatch_concurrency_cap}` here, and passes nothing when that key is unset so the internal default applies. Rows are discrete: floor a fractional argument to `⌊N⌋` (e.g. `2.5` → `2`) and treat `< 1` as `1`, so a stray non-integer never produces a fractional or zero cap.

## Prerequisites (before any dispatch)

Expand Down Expand Up @@ -66,8 +66,11 @@ Because the orchestrator stays on the default branch, **every source-touching op
`CLAUDE_CODE_SUBAGENT_MODEL` when set to a model alias or id, then the main conversation's model,
per <https://code.claude.com/docs/en/sub-agents#choose-a-model>, verified 2026-09-11. Recheck when
a release note touches subagent model selection.)
Dispatch a wave and keep working while it runs: verify returns from the same phase as they
arrive, compose the next brief, and run the build/test gate on accepted returns. Intervene when
Dispatch a wave, up to the cap's worker rows from the current phase, and keep working while it
runs: verify returns from the same phase as they arrive, compose the next brief, and run the
build/test gate on accepted returns. Under commit authority `worker` each row stages and
commits, so a wave in a shared worktree is one row; more than one concurrent row in a shared
worktree needs commit authority `orchestrator` and its Concurrency rule. Intervene when
a worker goes off track or is missing context. Do not block on the slowest worker before
starting orchestrator-side work that does not depend on it.
3. **Verify the return against direct evidence before accepting edits**. Worker returns are synthesis, not ground truth; promote their claims to direct evidence (diff read, grep, file Read) before building on them. Under commit authority `orchestrator` the return is an uncommitted tree; read it as Commit authority describes
Expand All @@ -78,13 +81,15 @@ Because the orchestrator stays on the default branch, **every source-touching op

Every brief states **commit authority**: `worker` (the default, and what an absent field means, so existing callers are unchanged) or `orchestrator`. Declare `orchestrator` when the plan's worker fence forbids staging, committing, or pushing, when the orchestrator owns a commit-subject gate, or when the plan has a push-once rule. Write the field into the brief; the worker never infers it from a fence. A worker handed a fence that forbids those writes with no declared mode STOPs and reports the conflict, and a fence that forbids only a narrow action (a force-push, opening the PR) leaves the mode at `worker`. A no-commit plan therefore needs no fenced generic subagent: the implementer honors the mode and keeps its tier binding.

**One git writer per worktree, under either authority.** A worktree has one index and one HEAD, and git writes the index under an exclusive lock, so two workers staging or committing in one worktree at once either fail on the lock or commit each other's paths. Under `worker`, where every worker stages and commits, run at most one worker per worktree at a time: rows that share the item's worktree dispatch one per wave, whatever `--wave-cap` allows. Concurrent rows in one shared worktree need `orchestrator`, where the orchestrator is the only git writer (see Concurrency below). This skill provisions no per-row worktrees; a phase whose rows must run concurrently under `worker` is a plan question, not a dispatch-time split. (A linked worktree is linked to its repository "sharing everything except per-worktree files such as HEAD, index", per <https://git-scm.com/docs/git-worktree>, verified 2026-09-27. Recheck when a git release note changes per-worktree state.)

Under `orchestrator`:

- **Worktree.** The brief carries an assigned worktree path. Worker-side provisioning cannot combine with this mode, because a provisioning worker must commit and push before returning; a brief asking for both makes the worker STOP. The orchestrator creates the worktree itself (a non-entering `git worktree add`, or the project's own tool) and hands over the path.
- **Brief.** Omit the commit-and-push-early clause, and shrink the exec-bit clause to `chmod +x <path>` plus listing the file in the return. The worker never runs `git add`, `git commit`, `git push`, `git stash`, or any other index or ref write; it returns `git -C <path> status --porcelain --untracked-files=all` output in place of a commit sha.
- **Verification.** Return verification (step 3) reads the uncommitted tree with `git -C <path> status --porcelain --untracked-files=all`, `git -C <path> diff HEAD`, and `git -C <path> ls-files --others --exclude-standard`; a plain `git diff` misses untracked files. The build/test gate (step 4) runs on that tree. The phase-verifier gets the worktree path plus the base ref and is told the changes are uncommitted, so it reads untracked files with `status --porcelain --untracked-files=all` or `ls-files --others --exclude-standard` as well as `git diff <base>`, or gets the diff itself: `diff HEAD` output plus the content of every file `ls-files --others --exclude-standard` lists (plain `status --porcelain` collapses a new directory to one entry).
- **Commit.** The orchestrator commits in the assigned worktree via `git -C <path>`, never in its own checkout, at the phase boundary: source and plan marks in one commit (see Phase boundaries), under the project's commit convention and gate, staging each listed shebang file in the order the Gotchas bullet "New shebang files need `chmod`" gives. It pushes per the plan's push rule, and as under `worker` when the plan states none. Commit as soon as the phase is accepted: until then the work exists only on local disk. When the commit gate is one only the user can pass, follow `/implementation:implement` Step 4 item 4: complete the plan marks and handoff first, then hand the commit to the user.
- **Concurrency.** Run one worker per worktree at a time. When several must share a worktree, give them disjoint fences, let none stage, attribute returned paths by fence, and run the build/test gate only after the wave settles.
- **Concurrency.** The orchestrator is the only git writer, so this is the one mode where several rows may share a worktree. Prefer one worker per worktree at a time. When several must share one, up to the wave cap, give them disjoint fences, let none stage, attribute returned paths by fence, and run the build/test gate only after the wave settles.

## Divergence in non-interactive runs

Expand Down Expand Up @@ -146,7 +151,7 @@ Which way the boundary goes decides its ritual (see Phase boundaries): a clear g
- **No issue-number back-references in code comments.** Brief every worker that a comment citing an issue number (`# Issue #NNN ...`, `(issue #NNN obs #N)`) trips the `comment-hygiene` check; `TODO(#issue)` is the sanctioned exception
- **New shebang files need `chmod`, then `git add`, then `git update-index --chmod=+x`. In that order.** Brief every `worker`-authority worker (for `orchestrator`, see Commit authority): `chmod +x <path>`, then `git add <path>` (a not-yet-tracked file fails `git update-index --chmod=+x` outright. It can't override the index mode of a path that isn't staged yet), then `git update-index --chmod=+x <path>` to force the index mode explicitly, since a plain `git add` alone can't be trusted to carry an executable bit across every platform and filesystem (skip symlinks, staged `120000`, they fail the same command), a shebang file staged non-executable trips the `exec-bit` check
- **Push early, before the CI-poll tail. But never the PR.** Brief every `worker`-authority worker to commit and push as early as practical rather than deferring until its fix-and-verify loop is done, so a mid-session death never orphans unpushed work. This is a source-only checkpoint commit. The phase-boundary plan-mark commit (Step 4) still runs separately, orchestrator-side, once the phase's acceptance criteria are verified. PR creation stays out of every worker brief. It happens in the orchestrator's post-verification flow (`/implementation:implement` Step 5) after every return is verified and the build/test gate passes. Commit authority `orchestrator` forgoes the early push: uncommitted work lives only on local disk until the orchestrator commits.
- **Shared-worktree workers under `orchestrator` need disjoint fences.** See Commit authority
- **One git writer per worktree, under both commit authorities.** Under `worker`, rows that share a worktree run one at a time even when `--wave-cap` allows more; concurrent rows in a shared worktree need `orchestrator`, with disjoint fences. See Commit authority
- **Scope-fence drift applies to agent returns.** Every worker return is a decision boundary. Classify proposed follow-ups per `/implementation:implement` "Step 3.5: Scope-fence drift detector (run at every decision boundary)" before announcing them
- **The capability-tier binding lives in agent frontmatter. Don't undercut it.** Workers dispatch as `implementation:implementer` and phase verifiers as `implementation:phase-verifier`; a generic subagent type inherits the orchestrator's model, which under a fast orchestrator root silently runs implementers at orchestrator strength. A per-invocation `model` routes only upward (frontier-alias for security-surface work, or the session's own higher tier). `CLAUDE_CODE_SUBAGENT_MODEL` ranks below both the per-invocation parameter and the frontmatter, so it cannot undercut the binding; it decides only where neither is set, which is the generic-subagent case this bullet already rules out
- **An omitted `--wave-cap` keeps the internal 3–5. Never coerce an absent value into a number.** Only cap at `N` when the caller passed a real positive integer; a missing, empty, or unresolved-placeholder argument means "use the internal default," not `0` and not a hard `1`
Loading
Loading