feat(lanes): run ONE pipeline node, from the terminal or a slash command
A pipeline was all-or-nothing: `ccam ship-full` / `ship-quick` hand the whole
thing to a skill, and a node's own `command` — added so the map would stop
hiding the driver behind its detect regexes — was display-only. Re-running just
the CI gate, or redoing the brainstorm, meant clicking copy on the node and
pasting the string into a session by hand.
`ccam lanes node [<id>] [extra…] [--print]` runs it, in the lane's own cwd. A
slash-command node spawns `claude` with it as the prompt (same shape as
`ccam ship-full`); anything else is spawned directly. No id lists every node
and its command, which is also what the two error paths print.
The node is matched by id OR alias, the same way `ccam stage` matches one:
`default` calls the step `implement` and `ship-feature` calls it `implementing`,
and one command name must not depend on which template the lane happens to be
on. That needs the template's `aliases`, which the lane payload's
`pipeline_nodes` does not carry — so the two are merged, template for the
definition, lane for the `current` marker.
Both shipped templates now fill EVERY node's `command`. The seven that were
empty are the nodes whose only work IS the declaration — a terminal `done`, a
gate another agent declares — so they get `ccam stage <id>`, which keeps all 16
(and all 8) runnable instead of leaving holes a caller has to know about.
Slash commands for the same thing, because a session should not shell out to a
nested `claude`: `/intake`, `/plan`, `/implement`, `/tests`, `/e2e`,
`/e2e-passed`, `/review`, `/qc-plan`, `/qc`, `/gate`, `/publishing`, `/pr-open`,
`/reported`, `/watching-pr`, `/merged`, `/done`, plus `/ship-full` and
`/ship-quick`. Each resolves its node through `ccam lanes node <id> --print` and
runs the result IN the current session — invoking the slash command itself when
that is what the node names, otherwise running the shell argv. Resolving at call
time rather than baking the string into the file is what stops the 18 command
files from drifting when a template changes.
Two limits are deliberate:
- The command is split on whitespace and spawned WITHOUT a shell. A template
is data — anyone can drop a file into DASHBOARD_PIPELINES_DIR — so its
`command` must never be interpreted as shell. A node needing a pipe names a
script that contains one.
- Running a node does not declare its stage. A command executing is not proof
the node passed, same boundary as the console never writing a lane's stage.
Verified: npm run test:server (1403, +3 covering alias matching, full command
coverage of both templates, and every command file being listed in the
manifest), npm run test:client (459), prettier and check-headers clean. Docs:
docs/LANES.md § Running ONE node, docs/PLUGINS.md commands table, README +
README.vi CLI blocks, CLAUDE.md marker.
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Declare the lane done
|
||||
argument-hint: [extra prompt words]
|
||||
allowed-tools: Bash(ccam lanes node:*)
|
||||
---
|
||||
|
||||
The command this lane pipeline template declares for its `done` node, resolved
|
||||
against whichever template the lane is actually on (matched by id or alias):
|
||||
|
||||
!`ccam lanes node done $ARGUMENTS --print`
|
||||
|
||||
Run that here, in THIS session - never start a nested `claude` process:
|
||||
|
||||
- Line reads `cd <dir> && "claude" "<slash command>"` -> invoke that slash
|
||||
command yourself, passing any extra words as its argument.
|
||||
- Anything else is a shell argv -> run it with Bash from `<dir>`.
|
||||
- Line is an error (`no node ...`, `declares no command`, no lane owns this
|
||||
directory) -> print it verbatim and stop. Do not guess a substitute.
|
||||
|
||||
Do NOT call `ccam stage` afterwards: a command running is not proof the node
|
||||
passed. Declare the stage when the work is actually done. (The exception is a
|
||||
node whose command already IS `ccam stage <id>` - there the declaration is the
|
||||
whole step.)
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Declare e2e passed (ship-feature only)
|
||||
argument-hint: [extra prompt words]
|
||||
allowed-tools: Bash(ccam lanes node:*)
|
||||
---
|
||||
|
||||
The command this lane pipeline template declares for its `e2e-passed` node, resolved
|
||||
against whichever template the lane is actually on (matched by id or alias):
|
||||
|
||||
!`ccam lanes node e2e-passed $ARGUMENTS --print`
|
||||
|
||||
Run that here, in THIS session - never start a nested `claude` process:
|
||||
|
||||
- Line reads `cd <dir> && "claude" "<slash command>"` -> invoke that slash
|
||||
command yourself, passing any extra words as its argument.
|
||||
- Anything else is a shell argv -> run it with Bash from `<dir>`.
|
||||
- Line is an error (`no node ...`, `declares no command`, no lane owns this
|
||||
directory) -> print it verbatim and stop. Do not guess a substitute.
|
||||
|
||||
Do NOT call `ccam stage` afterwards: a command running is not proof the node
|
||||
passed. Declare the stage when the work is actually done. (The exception is a
|
||||
node whose command already IS `ccam stage <id>` - there the declaration is the
|
||||
whole step.)
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: E2e on the feature branch (ship-feature only)
|
||||
argument-hint: [extra prompt words]
|
||||
allowed-tools: Bash(ccam lanes node:*)
|
||||
---
|
||||
|
||||
The command this lane pipeline template declares for its `e2e` node, resolved
|
||||
against whichever template the lane is actually on (matched by id or alias):
|
||||
|
||||
!`ccam lanes node e2e $ARGUMENTS --print`
|
||||
|
||||
Run that here, in THIS session - never start a nested `claude` process:
|
||||
|
||||
- Line reads `cd <dir> && "claude" "<slash command>"` -> invoke that slash
|
||||
command yourself, passing any extra words as its argument.
|
||||
- Anything else is a shell argv -> run it with Bash from `<dir>`.
|
||||
- Line is an error (`no node ...`, `declares no command`, no lane owns this
|
||||
directory) -> print it verbatim and stop. Do not guess a substitute.
|
||||
|
||||
Do NOT call `ccam stage` afterwards: a command running is not proof the node
|
||||
passed. Declare the stage when the work is actually done. (The exception is a
|
||||
node whose command already IS `ccam stage <id>` - there the declaration is the
|
||||
whole step.)
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Senior GO/NO-GO gate
|
||||
argument-hint: [extra prompt words]
|
||||
allowed-tools: Bash(ccam lanes node:*)
|
||||
---
|
||||
|
||||
The command this lane pipeline template declares for its `gate` node, resolved
|
||||
against whichever template the lane is actually on (matched by id or alias):
|
||||
|
||||
!`ccam lanes node gate $ARGUMENTS --print`
|
||||
|
||||
Run that here, in THIS session - never start a nested `claude` process:
|
||||
|
||||
- Line reads `cd <dir> && "claude" "<slash command>"` -> invoke that slash
|
||||
command yourself, passing any extra words as its argument.
|
||||
- Anything else is a shell argv -> run it with Bash from `<dir>`.
|
||||
- Line is an error (`no node ...`, `declares no command`, no lane owns this
|
||||
directory) -> print it verbatim and stop. Do not guess a substitute.
|
||||
|
||||
Do NOT call `ccam stage` afterwards: a command running is not proof the node
|
||||
passed. Declare the stage when the work is actually done. (The exception is a
|
||||
node whose command already IS `ccam stage <id>` - there the declaration is the
|
||||
whole step.)
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Implement (TDD)
|
||||
argument-hint: [extra prompt words]
|
||||
allowed-tools: Bash(ccam lanes node:*)
|
||||
---
|
||||
|
||||
The command this lane pipeline template declares for its `implement` node, resolved
|
||||
against whichever template the lane is actually on (matched by id or alias):
|
||||
|
||||
!`ccam lanes node implement $ARGUMENTS --print`
|
||||
|
||||
Run that here, in THIS session - never start a nested `claude` process:
|
||||
|
||||
- Line reads `cd <dir> && "claude" "<slash command>"` -> invoke that slash
|
||||
command yourself, passing any extra words as its argument.
|
||||
- Anything else is a shell argv -> run it with Bash from `<dir>`.
|
||||
- Line is an error (`no node ...`, `declares no command`, no lane owns this
|
||||
directory) -> print it verbatim and stop. Do not guess a substitute.
|
||||
|
||||
Do NOT call `ccam stage` afterwards: a command running is not proof the node
|
||||
passed. Declare the stage when the work is actually done. (The exception is a
|
||||
node whose command already IS `ccam stage <id>` - there the declaration is the
|
||||
whole step.)
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Intake — brainstorm the requirement
|
||||
argument-hint: [extra prompt words]
|
||||
allowed-tools: Bash(ccam lanes node:*)
|
||||
---
|
||||
|
||||
The command this lane pipeline template declares for its `intake` node, resolved
|
||||
against whichever template the lane is actually on (matched by id or alias):
|
||||
|
||||
!`ccam lanes node intake $ARGUMENTS --print`
|
||||
|
||||
Run that here, in THIS session - never start a nested `claude` process:
|
||||
|
||||
- Line reads `cd <dir> && "claude" "<slash command>"` -> invoke that slash
|
||||
command yourself, passing any extra words as its argument.
|
||||
- Anything else is a shell argv -> run it with Bash from `<dir>`.
|
||||
- Line is an error (`no node ...`, `declares no command`, no lane owns this
|
||||
directory) -> print it verbatim and stop. Do not guess a substitute.
|
||||
|
||||
Do NOT call `ccam stage` afterwards: a command running is not proof the node
|
||||
passed. Declare the stage when the work is actually done. (The exception is a
|
||||
node whose command already IS `ccam stage <id>` - there the declaration is the
|
||||
whole step.)
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Declare merged (ship-feature only)
|
||||
argument-hint: [extra prompt words]
|
||||
allowed-tools: Bash(ccam lanes node:*)
|
||||
---
|
||||
|
||||
The command this lane pipeline template declares for its `merged` node, resolved
|
||||
against whichever template the lane is actually on (matched by id or alias):
|
||||
|
||||
!`ccam lanes node merged $ARGUMENTS --print`
|
||||
|
||||
Run that here, in THIS session - never start a nested `claude` process:
|
||||
|
||||
- Line reads `cd <dir> && "claude" "<slash command>"` -> invoke that slash
|
||||
command yourself, passing any extra words as its argument.
|
||||
- Anything else is a shell argv -> run it with Bash from `<dir>`.
|
||||
- Line is an error (`no node ...`, `declares no command`, no lane owns this
|
||||
directory) -> print it verbatim and stop. Do not guess a substitute.
|
||||
|
||||
Do NOT call `ccam stage` afterwards: a command running is not proof the node
|
||||
passed. Declare the stage when the work is actually done. (The exception is a
|
||||
node whose command already IS `ccam stage <id>` - there the declaration is the
|
||||
whole step.)
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Plan — write the implementation plan
|
||||
argument-hint: [extra prompt words]
|
||||
allowed-tools: Bash(ccam lanes node:*)
|
||||
---
|
||||
|
||||
The command this lane pipeline template declares for its `plan` node, resolved
|
||||
against whichever template the lane is actually on (matched by id or alias):
|
||||
|
||||
!`ccam lanes node plan $ARGUMENTS --print`
|
||||
|
||||
Run that here, in THIS session - never start a nested `claude` process:
|
||||
|
||||
- Line reads `cd <dir> && "claude" "<slash command>"` -> invoke that slash
|
||||
command yourself, passing any extra words as its argument.
|
||||
- Anything else is a shell argv -> run it with Bash from `<dir>`.
|
||||
- Line is an error (`no node ...`, `declares no command`, no lane owns this
|
||||
directory) -> print it verbatim and stop. Do not guess a substitute.
|
||||
|
||||
Do NOT call `ccam stage` afterwards: a command running is not proof the node
|
||||
passed. Declare the stage when the work is actually done. (The exception is a
|
||||
node whose command already IS `ccam stage <id>` - there the declaration is the
|
||||
whole step.)
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Open the PR
|
||||
argument-hint: [extra prompt words]
|
||||
allowed-tools: Bash(ccam lanes node:*)
|
||||
---
|
||||
|
||||
The command this lane pipeline template declares for its `pr-open` node, resolved
|
||||
against whichever template the lane is actually on (matched by id or alias):
|
||||
|
||||
!`ccam lanes node pr-open $ARGUMENTS --print`
|
||||
|
||||
Run that here, in THIS session - never start a nested `claude` process:
|
||||
|
||||
- Line reads `cd <dir> && "claude" "<slash command>"` -> invoke that slash
|
||||
command yourself, passing any extra words as its argument.
|
||||
- Anything else is a shell argv -> run it with Bash from `<dir>`.
|
||||
- Line is an error (`no node ...`, `declares no command`, no lane owns this
|
||||
directory) -> print it verbatim and stop. Do not guess a substitute.
|
||||
|
||||
Do NOT call `ccam stage` afterwards: a command running is not proof the node
|
||||
passed. Declare the stage when the work is actually done. (The exception is a
|
||||
node whose command already IS `ccam stage <id>` - there the declaration is the
|
||||
whole step.)
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Publish the branch
|
||||
argument-hint: [extra prompt words]
|
||||
allowed-tools: Bash(ccam lanes node:*)
|
||||
---
|
||||
|
||||
The command this lane pipeline template declares for its `publishing` node, resolved
|
||||
against whichever template the lane is actually on (matched by id or alias):
|
||||
|
||||
!`ccam lanes node publishing $ARGUMENTS --print`
|
||||
|
||||
Run that here, in THIS session - never start a nested `claude` process:
|
||||
|
||||
- Line reads `cd <dir> && "claude" "<slash command>"` -> invoke that slash
|
||||
command yourself, passing any extra words as its argument.
|
||||
- Anything else is a shell argv -> run it with Bash from `<dir>`.
|
||||
- Line is an error (`no node ...`, `declares no command`, no lane owns this
|
||||
directory) -> print it verbatim and stop. Do not guess a substitute.
|
||||
|
||||
Do NOT call `ccam stage` afterwards: a command running is not proof the node
|
||||
passed. Declare the stage when the work is actually done. (The exception is a
|
||||
node whose command already IS `ccam stage <id>` - there the declaration is the
|
||||
whole step.)
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Declare the QC plan (ship-feature only)
|
||||
argument-hint: [extra prompt words]
|
||||
allowed-tools: Bash(ccam lanes node:*)
|
||||
---
|
||||
|
||||
The command this lane pipeline template declares for its `qc-plan` node, resolved
|
||||
against whichever template the lane is actually on (matched by id or alias):
|
||||
|
||||
!`ccam lanes node qc-plan $ARGUMENTS --print`
|
||||
|
||||
Run that here, in THIS session - never start a nested `claude` process:
|
||||
|
||||
- Line reads `cd <dir> && "claude" "<slash command>"` -> invoke that slash
|
||||
command yourself, passing any extra words as its argument.
|
||||
- Anything else is a shell argv -> run it with Bash from `<dir>`.
|
||||
- Line is an error (`no node ...`, `declares no command`, no lane owns this
|
||||
directory) -> print it verbatim and stop. Do not guess a substitute.
|
||||
|
||||
Do NOT call `ccam stage` afterwards: a command running is not proof the node
|
||||
passed. Declare the stage when the work is actually done. (The exception is a
|
||||
node whose command already IS `ccam stage <id>` - there the declaration is the
|
||||
whole step.)
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Browser QC + proof gallery (ship-feature only)
|
||||
argument-hint: [extra prompt words]
|
||||
allowed-tools: Bash(ccam lanes node:*)
|
||||
---
|
||||
|
||||
The command this lane pipeline template declares for its `qc` node, resolved
|
||||
against whichever template the lane is actually on (matched by id or alias):
|
||||
|
||||
!`ccam lanes node qc $ARGUMENTS --print`
|
||||
|
||||
Run that here, in THIS session - never start a nested `claude` process:
|
||||
|
||||
- Line reads `cd <dir> && "claude" "<slash command>"` -> invoke that slash
|
||||
command yourself, passing any extra words as its argument.
|
||||
- Anything else is a shell argv -> run it with Bash from `<dir>`.
|
||||
- Line is an error (`no node ...`, `declares no command`, no lane owns this
|
||||
directory) -> print it verbatim and stop. Do not guess a substitute.
|
||||
|
||||
Do NOT call `ccam stage` afterwards: a command running is not proof the node
|
||||
passed. Declare the stage when the work is actually done. (The exception is a
|
||||
node whose command already IS `ccam stage <id>` - there the declaration is the
|
||||
whole step.)
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Declare the run reported (ship-feature only)
|
||||
argument-hint: [extra prompt words]
|
||||
allowed-tools: Bash(ccam lanes node:*)
|
||||
---
|
||||
|
||||
The command this lane pipeline template declares for its `reported` node, resolved
|
||||
against whichever template the lane is actually on (matched by id or alias):
|
||||
|
||||
!`ccam lanes node reported $ARGUMENTS --print`
|
||||
|
||||
Run that here, in THIS session - never start a nested `claude` process:
|
||||
|
||||
- Line reads `cd <dir> && "claude" "<slash command>"` -> invoke that slash
|
||||
command yourself, passing any extra words as its argument.
|
||||
- Anything else is a shell argv -> run it with Bash from `<dir>`.
|
||||
- Line is an error (`no node ...`, `declares no command`, no lane owns this
|
||||
directory) -> print it verbatim and stop. Do not guess a substitute.
|
||||
|
||||
Do NOT call `ccam stage` afterwards: a command running is not proof the node
|
||||
passed. Declare the stage when the work is actually done. (The exception is a
|
||||
node whose command already IS `ccam stage <id>` - there the declaration is the
|
||||
whole step.)
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Code review
|
||||
argument-hint: [extra prompt words]
|
||||
allowed-tools: Bash(ccam lanes node:*)
|
||||
---
|
||||
|
||||
The command this lane pipeline template declares for its `review` node, resolved
|
||||
against whichever template the lane is actually on (matched by id or alias):
|
||||
|
||||
!`ccam lanes node review $ARGUMENTS --print`
|
||||
|
||||
Run that here, in THIS session - never start a nested `claude` process:
|
||||
|
||||
- Line reads `cd <dir> && "claude" "<slash command>"` -> invoke that slash
|
||||
command yourself, passing any extra words as its argument.
|
||||
- Anything else is a shell argv -> run it with Bash from `<dir>`.
|
||||
- Line is an error (`no node ...`, `declares no command`, no lane owns this
|
||||
directory) -> print it verbatim and stop. Do not guess a substitute.
|
||||
|
||||
Do NOT call `ccam stage` afterwards: a command running is not proof the node
|
||||
passed. Declare the stage when the work is actually done. (The exception is a
|
||||
node whose command already IS `ccam stage <id>` - there the declaration is the
|
||||
whole step.)
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Run the full 16-stage lane pipeline (implement → gates → e2e → review → QC → senior gate → PR, watched until merged)
|
||||
argument-hint: <requirement>
|
||||
allowed-tools: Bash(ccam lanes pipeline:*)
|
||||
---
|
||||
|
||||
Put this lane on the 16-node `ship-feature` template first, so the dashboard
|
||||
renders the right node count from the first stage rather than after the skill
|
||||
self-corrects:
|
||||
|
||||
!`ccam lanes pipeline ship-feature`
|
||||
|
||||
Then run the pipeline **in this session** by invoking `/ccam:ship-feature-lane`
|
||||
with this requirement:
|
||||
|
||||
$ARGUMENTS
|
||||
|
||||
- No requirement given → ask for one. Never guess what to build.
|
||||
- The switch above failed (no lane owns this directory) → say so and stop; the
|
||||
skill has no lane to report stages against.
|
||||
|
||||
This is the in-session twin of `ccam ship-full "<requirement>"`, which does the
|
||||
same two steps from a terminal by spawning its own `claude`.
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Run the 8-stage in-repo pipeline (plan → implement → tests → review → gate → ship). No PR, no browser QC
|
||||
argument-hint: <requirement>
|
||||
allowed-tools: Bash(ccam lanes pipeline:*)
|
||||
---
|
||||
|
||||
Put this lane on the 8-node `default` template first, so the dashboard renders
|
||||
the right node count from the first stage:
|
||||
|
||||
!`ccam lanes pipeline default`
|
||||
|
||||
Then run the pipeline **in this session** by invoking `/ccam:ship-feature` with
|
||||
this requirement:
|
||||
|
||||
$ARGUMENTS
|
||||
|
||||
- No requirement given → ask for one. Never guess what to build.
|
||||
- The switch above failed (no lane owns this directory) → say so and stop; the
|
||||
skill has no lane to report stages against.
|
||||
|
||||
This is the in-session twin of `ccam ship-quick "<requirement>"`. It stops at
|
||||
review/gate: no PR is opened and no browser QC runs — use `/ship-full` when the
|
||||
work should reach reviewers.
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Tests / pre-push CI gates
|
||||
argument-hint: [extra prompt words]
|
||||
allowed-tools: Bash(ccam lanes node:*)
|
||||
---
|
||||
|
||||
The command this lane pipeline template declares for its `tests` node, resolved
|
||||
against whichever template the lane is actually on (matched by id or alias):
|
||||
|
||||
!`ccam lanes node tests $ARGUMENTS --print`
|
||||
|
||||
Run that here, in THIS session - never start a nested `claude` process:
|
||||
|
||||
- Line reads `cd <dir> && "claude" "<slash command>"` -> invoke that slash
|
||||
command yourself, passing any extra words as its argument.
|
||||
- Anything else is a shell argv -> run it with Bash from `<dir>`.
|
||||
- Line is an error (`no node ...`, `declares no command`, no lane owns this
|
||||
directory) -> print it verbatim and stop. Do not guess a substitute.
|
||||
|
||||
Do NOT call `ccam stage` afterwards: a command running is not proof the node
|
||||
passed. Declare the stage when the work is actually done. (The exception is a
|
||||
node whose command already IS `ccam stage <id>` - there the declaration is the
|
||||
whole step.)
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Watch the PR / CI (ship-feature only)
|
||||
argument-hint: [extra prompt words]
|
||||
allowed-tools: Bash(ccam lanes node:*)
|
||||
---
|
||||
|
||||
The command this lane pipeline template declares for its `watching-pr` node, resolved
|
||||
against whichever template the lane is actually on (matched by id or alias):
|
||||
|
||||
!`ccam lanes node watching-pr $ARGUMENTS --print`
|
||||
|
||||
Run that here, in THIS session - never start a nested `claude` process:
|
||||
|
||||
- Line reads `cd <dir> && "claude" "<slash command>"` -> invoke that slash
|
||||
command yourself, passing any extra words as its argument.
|
||||
- Anything else is a shell argv -> run it with Bash from `<dir>`.
|
||||
- Line is an error (`no node ...`, `declares no command`, no lane owns this
|
||||
directory) -> print it verbatim and stop. Do not guess a substitute.
|
||||
|
||||
Do NOT call `ccam stage` afterwards: a command running is not proof the node
|
||||
passed. Declare the stage when the work is actually done. (The exception is a
|
||||
node whose command already IS `ccam stage <id>` - there the declaration is the
|
||||
whole step.)
|
||||
Reference in New Issue
Block a user