Files
Claude-Code-Monitor/docs/superpowers/specs/2026-08-04-ship-feature-skill-design.md
T
nntrivi2001 b08504858c docs(lanes): design E1 — ship-feature pipeline template + skill port
Scopes the first of E's four independent pieces: --qc boot flag +
QC_BOOT_ENV, the pipeline template, and the ported skill text. Agents,
sync-base, and F's integrations are named but deliberately out of scope,
per the roadmap's own subsystem split.
2026-08-04 17:37:33 +07:00

8.7 KiB
Raw Blame History

E1 — Ship-feature pipeline template + skill port

Status: approved 2026-08-04. Roadmap it belongs to: docs/superpowers/plans/2026-08-03-shipyard-parity-lanes.md (subsystem E).

Problem

Shipyard's ship-feature/SKILL.md (~/MyDrive/Projects/ResearchAndDevelopment/AgentWorkflow/claude/skills/ship-feature/SKILL.md, 208 lines, 16 stages) is the driving skill that runs a lane end-to-end: intake → TDD implement → gates → e2e → review → QC → senior gate → publish PR → watch → post-merge verify → done. CCAM has no equivalent yet. E (per the roadmap) is four independent pieces — this spec covers only the first: the pipeline template + the skill text itself. Agents (qc-local, senior-gate-reviewer, ticketer, dev-qc, pr-reviewer) and ccam lanes sync-base are separate, later tasks; F's integrations (tracker, dev-QC, CI-wait) are later still.

Scope

In scope:

  1. A backend gap the skill text requires to be truthful: ccam lanes up --qc, backed by a new QC_BOOT_ENV profile declaration.
  2. server/data/pipelines/ship-feature.json — the node/stage definitions the dashboard renders against.
  3. .claude/skills/ship-feature-lane/SKILL.md — the ported skill, every Shipyard bin/… call rewritten to its CCAM equivalent.

Out of scope (later tasks, referenced by name in the ported skill but not built here):

  • ccam lanes sync-base (the migration-collision + merge-driver command Stage 2/8/12 call).
  • ccam lanes mcp sync (F) — Stage 0's MCP preflight becomes a manual check + a message to the human, not an auto-sync call.
  • ccam lanes integration <name> / .ccam/profile/integrations.env (F) — tracker/dev_qc/ci_wait are hardcoded off in this port; Stage 9 (ticket) and the dev-QC half of Stage 13 unconditionally skip; Stage 10's CI watch unconditionally uses the gh pr checks fallback the original skill already documents for "helper not configured" (no conditional branch needed — there is nothing to branch on yet).
  • ccam ci (F, ci-job.sh port) — same reasoning; Stage 10/13's CI-triage logic that depends on it is dropped to the fallback path.
  • The five agents — the skill references them by subagent_type at Stages 6/7/9/13/12(pr-reviewer callout), but none exist yet. This spec's own verification stops where an agent invocation would occur.

Decisions

Choice Rationale
--qc boot flag New QC_BOOT_ENV profile declaration (space-separated KEY=value pairs, same shape as Shipyard's), injected into the boot hook's environment only when up is called with qc: true The skill calls lane-up.sh "$N" --qc in Stage 3 to get a deterministic (mocked/stubbed) stack for QC. Without a real flag this line in the ported skill would be false documentation — violates this repo's docs rule (executable, aligned with actual scripts). A profile that never declares QC_BOOT_ENV gets no extra env (dead code doesn't run), same pattern every other A2 declaration in DEFAULTS already follows.
state.sh "$N" init (open a clean feature slot before Stage 0's Q&A) Dropped — replaced by a plain ccam feature activate <slug> at Stage 1 Task B's activateFeature already archives the outgoing active feature automatically on switch; Shipyard needed a separate init step because it had no DB-backed archive. Porting init as a distinct call would be redundant with what activate already does.
Integration toggles (tracker/dev_qc/ci_wait) Hardcoded off, not a runtime check F doesn't exist yet. The alternative (a stub ccam lanes integration that always returns off) adds surface area for no behavioral difference today; the skill's own text already documents the "toggle off" behavior for each stage, so hardcoding is truthful, not a shortcut. When F ships, this becomes a follow-up edit to swap hardcoded skips for real checks — an explicit, later, reviewable diff.
Hook names for lane-ci-gate.sh / lane-e2e.sh ccam lanes hook ci-gate / ccam lanes hook e2e Both names are already in server/lib/lane-profile.js's HOOKS allowlist, added during A1 specifically "because... the driving skill needs that surface stable" — this spec is that driving skill. No backend change needed for these two.
.harness-lane marker / lane-assign.sh Dropped entirely CCAM already resolves a lane from cwd (path-boundary prefix match, documented in this repo's CLAUDE.md) — the marker file and the assign step exist in Shipyard only because it has no such resolution.
@@HARNESS_ROOT@@ / @@DEV_QC_MCP@@ / @@TRACKER_MCP@@ placeholders Dropped Install-time templating that doesn't exist in CCAM; every reference becomes the literal CCAM command or, for the two MCP placeholders, is deleted along with the (out-of-scope) integrations that used them.

Command mapping

Shipyard CCAM Status
state.sh "$N" set stage=X status=Y ccam stage X --status Y exists
state.sh "$N" activate feat/<slug> ccam feature activate <slug> exists (Task B)
state.sh "$N" init (dropped — see Decisions) n/a
lane-ci-gate.sh "$N" ccam lanes hook ci-gate exists (hook allowlisted)
lane-up.sh "$N" --qc ccam lanes up --qc new in this task
lane-e2e.sh "$N" [-- specs] ccam lanes hook e2e [-- specs] exists (hook allowlisted)
lane-sync-dev.sh … ccam lanes sync-base … later task (referenced, not built)
lane-mcp-sync.sh "$N" ccam lanes mcp sync F (referenced as manual fallback)
lane-env.sh "$N" --check X (hardcoded off) F (deferred)
ci-job.sh status|failures|rerun|cancel ccam ci … F (deferred; skill uses its own gh-only fallback)

Design

--qc boot flag

  • QC_BOOT_ENV added to server/lib/lane-profile.js's DEFAULTS (empty string default — off).
  • POST /:id/up accepts {build, qc} in its body (currently only reads build); qc: true is threaded through to whatever assembles the boot hook's environment (read the actual upLane/hook-invocation code path in server/lib/lane-runtime.js before implementing — this spec names the profile declaration and the route contract, not the exact internal plumbing function).
  • ccam lanes up [--no-build] [--qc] in bin/ccam.js--qc sets {qc: true} in the POST body alongside the existing --no-build{build: false} handling.
  • QC_BOOT_ENV format: space-separated KEY=value pairs, parsed the same way this file already parses PORTS/LANE_DIRS (space-separated lists) — not a new parsing convention.

Pipeline template

server/data/pipelines/ship-feature.json — one node per skill stage (0 through 15, using the skill's own stage names: intake, plan, implementing, gates, e2e-feature, e2e-feature-passed, review, qc-plan, qc, gate, publishing, pr-open, reported, watching-pr, merged, done), same node-definition shape default.json already uses (label, detect rules matching the stage= values ccam stage sets). default.json untouched. A lane opts into this template via its pipeline field, same mechanism every other custom template already uses.

Skill

.claude/skills/ship-feature-lane/SKILL.md — the full port. Frontmatter, hard rules, and all 16 stages carried over with the Command mapping table's substitutions applied line-by-line. Every hard-won rule (turn-liveness, no-retry-cap/phase-clock, one-driver-per-MCP, never-push-base, the fix-loop's two fast-path exceptions, cross-lane etiquette) is kept verbatim in spirit, with lane-lock.sh etiquette re-pointed at D's ccam lock CLI and named locks.

Invariants

  1. CCAM still does not orchestrate. The skill runs in the session and calls ccam commands one at a time; nothing in this task adds chaining, gate evaluation, or retry logic to the dashboard itself.
  2. Every command the skill text names must actually exist and behave as documented — the docs-markdown rule (executable examples, aligned with actual scripts) applies to a skill file exactly as it applies to docs/*.md.
  3. A profile that never declares QC_BOOT_ENV sees no behavior change--qc degrades to a plain boot when the declaration is absent, same as every other optional A2 declaration.

Verify

A real dry run on a scratch repo with a profile, walking Stage 0 through Stage 2 (intake → plan → ccam lanes hook ci-gate) — the furthest the pipeline can go without the not-yet-built agents. Confirms every ccam command named in stages 02 exists and behaves as documented. ccam lanes up --qc gets its own unit/integration test verifying QC_BOOT_ENV reaches the boot hook's environment when declared, and is a no-op when absent. Full Stage 0→14 verification is the agents-port task's responsibility, once qc-local/senior-gate-reviewer exist.