Clean break, no compatibility alias. Renames the product name, the CLI binary (`ccam` -> `agenthub`), the env var prefix (`CCAM_` -> `AGENTHUB_`), the Prometheus metric namespace (`ccam_*` -> `agenthub_*`), the tmux session prefix (`ccam-lane-<id>` -> `agenthub-lane-<id>`), the per-repo runtime profile directory (`.ccam/profile` -> `.agenthub/profile`), the lanes state root (`~/.claude/ccam-lanes` -> `~/.claude/agenthub-lanes`), the bundled plugins (`plugins/ccam*` -> `plugins/agenthub*`) and their slash commands (`/ccam-doctor` -> `/agenthub-doctor`, `/ccam:*` -> `/agenthub:*`). Because there is no alias, an existing install has to be updated by hand: rename its `.ccam/profile` directory and any `CCAM_*` variables, and reinstall the plugin under its new name. Two other name families are deliberately left alone here, since they are not just strings: the `Claude-Code-Monitor` repository/marketplace name, and the `agent-dashboard` npm package plus its `~/.claude/agent-dashboard` runtime directory, which holds the live database and needs a migration rather than a rename. Verified: server 1406/1406, client 459/459, `grep -i ccam` clean across tracked files, `openapi.yaml` regenerated (95 paths, unchanged count).
8.8 KiB
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. AgentHub 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 agenthub lanes sync-base are separate, later tasks; F's integrations (tracker, dev-QC, CI-wait) are later still.
Scope
In scope:
- A backend gap the skill text requires to be truthful:
agenthub lanes up --qc, backed by a newQC_BOOT_ENVprofile declaration. server/data/pipelines/ship-feature.json— the node/stage definitions the dashboard renders against..claude/skills/ship-feature-lane/SKILL.md— the ported skill, every Shipyardbin/…call rewritten to its AgentHub equivalent.
Out of scope (later tasks, referenced by name in the ported skill but not built here):
agenthub lanes sync-base(the migration-collision + merge-driver command Stage 2/8/12 call).agenthub lanes mcp sync(F) — Stage 0's MCP preflight becomes a manual check + a message to the human, not an auto-sync call.agenthub lanes integration <name>/.agenthub/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 thegh pr checksfallback the original skill already documents for "helper not configured" (no conditional branch needed — there is nothing to branch on yet).agenthub ci(F,ci-job.shport) — 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_typeat 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 agenthub 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 agenthub 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 |
agenthub lanes hook ci-gate / agenthub 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 | AgentHub 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 AgentHub; every reference becomes the literal AgentHub command or, for the two MCP placeholders, is deleted along with the (out-of-scope) integrations that used them. |
Command mapping
| Shipyard | AgentHub | Status |
|---|---|---|
state.sh "$N" set stage=X status=Y |
agenthub stage X --status Y |
exists |
state.sh "$N" activate feat/<slug> |
agenthub feature activate <slug> |
exists (Task B) |
state.sh "$N" init |
(dropped — see Decisions) | n/a |
lane-ci-gate.sh "$N" |
agenthub lanes hook ci-gate |
exists (hook allowlisted) |
lane-up.sh "$N" --qc |
agenthub lanes up --qc |
new in this task |
lane-e2e.sh "$N" [-- specs] |
agenthub lanes hook e2e [-- specs] |
exists (hook allowlisted) |
lane-sync-dev.sh … |
agenthub lanes sync-base … |
later task (referenced, not built) |
lane-mcp-sync.sh "$N" |
agenthub 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 |
agenthub ci … |
F (deferred; skill uses its own gh-only fallback) |
Design
--qc boot flag
QC_BOOT_ENVadded toserver/lib/lane-profile.js'sDEFAULTS(empty string default — off).POST /:id/upaccepts{build, qc}in its body (currently only readsbuild);qc: trueis threaded through to whatever assembles the boot hook's environment (read the actualupLane/hook-invocation code path inserver/lib/lane-runtime.jsbefore implementing — this spec names the profile declaration and the route contract, not the exact internal plumbing function).agenthub lanes up [--no-build] [--qc]inbin/agenthub.js—--qcsets{qc: true}in the POST body alongside the existing--no-build→{build: false}handling.QC_BOOT_ENVformat: space-separatedKEY=valuepairs, parsed the same way this file already parsesPORTS/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 agenthub 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 agenthub lock CLI and named locks.
Invariants
- AgentHub still does not orchestrate. The skill runs in the session and calls
agenthubcommands one at a time; nothing in this task adds chaining, gate evaluation, or retry logic to the dashboard itself. - 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. - A profile that never declares
QC_BOOT_ENVsees no behavior change —--qcdegrades 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 → agenthub lanes hook ci-gate) — the furthest the pipeline can go without the not-yet-built agents. Confirms every agenthub command named in stages 0–2 exists and behaves as documented. agenthub 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.