refactor!: rebrand CCAM to AgentHub
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).
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# E2 — `ccam lanes sync-base` Implementation Plan
|
||||
# E2 — `agenthub lanes sync-base` Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** `ccam lanes sync-base` exists as a real, working command — the migration-collision preflight (`--check`), the one sanctioned merge (`origin/development` into a feature branch), and its conflict-resolution follow-up (`--continue`) — so `.claude/skills/ship-feature-lane/SKILL.md`'s Stage 2/8/12 references to it stop being "later task" placeholders.
|
||||
**Goal:** `agenthub lanes sync-base` exists as a real, working command — the migration-collision preflight (`--check`), the one sanctioned merge (`origin/development` into a feature branch), and its conflict-resolution follow-up (`--continue`) — so `.claude/skills/ship-feature-lane/SKILL.md`'s Stage 2/8/12 references to it stop being "later task" placeholders.
|
||||
|
||||
**Architecture:** One new core module (`server/lib/lane-sync.js`, pure git operations via `worktree.js`'s existing `git()` helper), two new profile declarations (`MIGRATIONS_DIR`, `GENERATED_MERGE_PATHS`), one new synchronous route (`POST /:id/sync-base`), one new CLI subcommand, and a `SKILL.md` edit that turns three "if it exists yet" conditionals into real instructions.
|
||||
|
||||
@@ -145,7 +145,7 @@ const os = require("node:os");
|
||||
const path = require("node:path");
|
||||
const { execFileSync } = require("node:child_process");
|
||||
|
||||
const ROOT = fs.mkdtempSync(path.join(os.tmpdir(), "ccam-sync-"));
|
||||
const ROOT = fs.mkdtempSync(path.join(os.tmpdir(), "agenthub-sync-"));
|
||||
|
||||
const laneSync = require("../lib/lane-sync");
|
||||
|
||||
@@ -488,7 +488,7 @@ describe("lane-sync merge: generated-file merge driver + regen fold-in", () => {
|
||||
gc(GEN_PUSHER, "push", "-q", "origin", "development");
|
||||
|
||||
// A regen hook the fold-in step will run.
|
||||
const profileDir = path.join(GEN_LANE, ".ccam", "profile");
|
||||
const profileDir = path.join(GEN_LANE, ".agenthub", "profile");
|
||||
fs.mkdirSync(path.join(profileDir, "hooks"), { recursive: true });
|
||||
fs.writeFileSync(path.join(profileDir, "profile.env"), "PORTS=api\n");
|
||||
fs.writeFileSync(
|
||||
@@ -503,7 +503,7 @@ describe("lane-sync merge: generated-file merge driver + regen fold-in", () => {
|
||||
env: { MIGRATIONS_DIR: "", GENERATED_MERGE_PATHS: "api/openapi.json" },
|
||||
generatedMergePaths: ["api/openapi.json"],
|
||||
hooks: new Set(["regen"]),
|
||||
dir: path.join(GEN_LANE, ".ccam", "profile"),
|
||||
dir: path.join(GEN_LANE, ".agenthub", "profile"),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -567,10 +567,10 @@ async function unmergedFiles(cwd) {
|
||||
* already established. */
|
||||
async function setupMergeDriver(cwd, generatedPaths) {
|
||||
if (!generatedPaths.length) return;
|
||||
await git(cwd, ["config", "merge.ccam-generated.driver", "true"]);
|
||||
await git(cwd, ["config", "merge.agenthub-generated.driver", "true"]);
|
||||
await git(cwd, [
|
||||
"config",
|
||||
"merge.ccam-generated.name",
|
||||
"merge.agenthub-generated.name",
|
||||
"keep ours; regenerated post-merge by the profile regen hook",
|
||||
]);
|
||||
|
||||
@@ -581,7 +581,7 @@ async function setupMergeDriver(cwd, generatedPaths) {
|
||||
const lines = new Set(existing.split("\n").filter(Boolean));
|
||||
let changed = false;
|
||||
for (const gp of generatedPaths) {
|
||||
const line = `${gp} merge=ccam-generated`;
|
||||
const line = `${gp} merge=agenthub-generated`;
|
||||
if (!lines.has(line)) {
|
||||
lines.add(line);
|
||||
changed = true;
|
||||
@@ -924,7 +924,7 @@ There's no HTTP-level test harness for lane routes in this repo (per the Global
|
||||
```bash
|
||||
npm run dev &
|
||||
sleep 3
|
||||
# Replace 1 with a real lane id that has a .ccam/profile and a feature branch.
|
||||
# Replace 1 with a real lane id that has a .agenthub/profile and a feature branch.
|
||||
curl -s -X POST http://localhost:4820/api/lanes/1/sync-base \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"mode":"check","branch":"feat/some-branch"}' | node -e "process.stdin.pipe(require('node:fs').createWriteStream('/dev/stdout'))"
|
||||
@@ -948,18 +948,18 @@ git commit -m "feat(lanes): add POST /:id/sync-base route (E2)"
|
||||
|
||||
---
|
||||
|
||||
### Task 4: `ccam lanes sync-base` CLI
|
||||
### Task 4: `agenthub lanes sync-base` CLI
|
||||
|
||||
**Files:**
|
||||
- Modify: `bin/ccam.js`
|
||||
- Modify: `bin/agenthub.js`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: `POST /api/lanes/:id/sync-base` (Task 3); `resolveLaneArg(args)`, `post(path, body, options)` (both already defined in `bin/ccam.js`).
|
||||
- Produces: `ccam lanes sync-base [<id>] [--check|--continue] [branch]` — `process.exitCode` set to `0`/`4`/`5` matching the route's `code`, so `SKILL.md`'s documented exit-code contract holds when scripted.
|
||||
- Consumes: `POST /api/lanes/:id/sync-base` (Task 3); `resolveLaneArg(args)`, `post(path, body, options)` (both already defined in `bin/agenthub.js`).
|
||||
- Produces: `agenthub lanes sync-base [<id>] [--check|--continue] [branch]` — `process.exitCode` set to `0`/`4`/`5` matching the route's `code`, so `SKILL.md`'s documented exit-code contract holds when scripted.
|
||||
|
||||
- [ ] **Step 1: Add the subcommand to `cmdLanesRuntime`**
|
||||
|
||||
In `bin/ccam.js`, extend the `if (sub === "hook") { ... }` block (ends at `bin/ccam.js:1902`) with a new `sync-base` branch, inside the same `cmdLanesRuntime(sub, args)` function:
|
||||
In `bin/agenthub.js`, extend the `if (sub === "hook") { ... }` block (ends at `bin/agenthub.js:1902`) with a new `sync-base` branch, inside the same `cmdLanesRuntime(sub, args)` function:
|
||||
|
||||
```js
|
||||
if (sub === "sync-base") {
|
||||
@@ -994,7 +994,7 @@ In `bin/ccam.js`, extend the `if (sub === "hook") { ... }` block (ends at `bin/c
|
||||
console.error(` conflicted: ${result.conflictedFiles.join(", ")}`);
|
||||
console.error(" resolve, then: git add <resolved files> && git commit --no-edit");
|
||||
console.error(
|
||||
` then: ccam lanes sync-base --continue ${branch ? branch + " " : ""}${laneId}`
|
||||
` then: agenthub lanes sync-base --continue ${branch ? branch + " " : ""}${laneId}`
|
||||
);
|
||||
process.exitCode = 4;
|
||||
return;
|
||||
@@ -1028,7 +1028,7 @@ In `bin/ccam.js`, extend the `if (sub === "hook") { ... }` block (ends at `bin/c
|
||||
|
||||
- [ ] **Step 2: Wire the subcommand into the dispatcher**
|
||||
|
||||
`bin/ccam.js:3088` currently reads:
|
||||
`bin/agenthub.js:3088` currently reads:
|
||||
|
||||
```js
|
||||
if (["up", "down", "runtime", "logs", "hook"].includes(rest[0])) {
|
||||
@@ -1046,7 +1046,7 @@ Change to:
|
||||
|
||||
- [ ] **Step 3: Add the help-catalog entry**
|
||||
|
||||
In the command catalog array (`bin/ccam.js:2268`, right after the `lanes hook` entry), add:
|
||||
In the command catalog array (`bin/agenthub.js:2268`, right after the `lanes hook` entry), add:
|
||||
|
||||
```js
|
||||
[
|
||||
@@ -1061,7 +1061,7 @@ In the command catalog array (`bin/ccam.js:2268`, right after the `lanes hook` e
|
||||
```bash
|
||||
npm run dev &
|
||||
sleep 3
|
||||
node bin/ccam.js lanes sync-base --check feat/some-branch 1
|
||||
node bin/agenthub.js lanes sync-base --check feat/some-branch 1
|
||||
echo "exit: $?"
|
||||
```
|
||||
|
||||
@@ -1077,8 +1077,8 @@ npm run test:server
|
||||
- [ ] **Step 6: Commit**
|
||||
|
||||
```bash
|
||||
git add bin/ccam.js
|
||||
git commit -m "feat(lanes): add ccam lanes sync-base CLI (E2)"
|
||||
git add bin/agenthub.js
|
||||
git commit -m "feat(lanes): add agenthub lanes sync-base CLI (E2)"
|
||||
```
|
||||
|
||||
---
|
||||
@@ -1097,14 +1097,14 @@ git commit -m "feat(lanes): add ccam lanes sync-base CLI (E2)"
|
||||
In `.claude/skills/ship-feature-lane/SKILL.md`, find (Stage 2, `### 2 — Pre-push CI gates + dev preflight`):
|
||||
|
||||
```
|
||||
- `ccam lanes sync-base --check feat/<slug>` — the dev preflight: fetches and checks the branch against the CURRENT `origin/development` without merging anything. **This command is a LATER task, not yet built as of this skill's authoring** — until it exists, skip this preflight check and rely on Stage 12's conflict handling to catch a divergence at merge time; note this gap explicitly in your Stage 2 evidence (`ccam stage gates --evidence "sync-base preflight unavailable, skipped"`).
|
||||
- `agenthub lanes sync-base --check feat/<slug>` — the dev preflight: fetches and checks the branch against the CURRENT `origin/development` without merging anything. **This command is a LATER task, not yet built as of this skill's authoring** — until it exists, skip this preflight check and rely on Stage 12's conflict handling to catch a divergence at merge time; note this gap explicitly in your Stage 2 evidence (`agenthub stage gates --evidence "sync-base preflight unavailable, skipped"`).
|
||||
- Once built, its contract is: exit 5 on a migration-number collision (print the exact rename, do it on the feature branch, re-run Stage 2); informational `DEV_DELTA:`/`DEV_OVERLAP:` output otherwise (you do NOT sync the branch for it — GitHub merges non-conflicting histories fine).
|
||||
```
|
||||
|
||||
Replace with:
|
||||
|
||||
```
|
||||
- `ccam lanes sync-base --check feat/<slug>` — the dev preflight: fetches and checks the branch against the CURRENT `origin/development` without merging anything. Exit 5 on a migration-number collision: rename the printed file to the suggested number on the feature branch (`git mv`, update any in-file references), then re-run Stage 2. Exit 0 with `DEV_DELTA:`/`DEV_OVERLAP:` output otherwise — informational, you do NOT sync the branch for it (GitHub merges non-conflicting histories fine); a large overlapping delta is a heads-up that post-merge behavior may differ from what you test locally.
|
||||
- `agenthub lanes sync-base --check feat/<slug>` — the dev preflight: fetches and checks the branch against the CURRENT `origin/development` without merging anything. Exit 5 on a migration-number collision: rename the printed file to the suggested number on the feature branch (`git mv`, update any in-file references), then re-run Stage 2. Exit 0 with `DEV_DELTA:`/`DEV_OVERLAP:` output otherwise — informational, you do NOT sync the branch for it (GitHub merges non-conflicting histories fine); a large overlapping delta is a heads-up that post-merge behavior may differ from what you test locally.
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Stage 8 — make the re-run unconditional**
|
||||
@@ -1112,13 +1112,13 @@ Replace with:
|
||||
Find (Stage 8, around `SKILL.md:127`):
|
||||
|
||||
```
|
||||
- Re-run the preflight if `ccam lanes sync-base` exists by the time you read this — development may have moved while you were in QC. If it doesn't exist yet, skip straight to the push (same gap noted in Stage 2).
|
||||
- Re-run the preflight if `agenthub lanes sync-base` exists by the time you read this — development may have moved while you were in QC. If it doesn't exist yet, skip straight to the push (same gap noted in Stage 2).
|
||||
```
|
||||
|
||||
Replace with:
|
||||
|
||||
```
|
||||
- Re-run the preflight: `ccam lanes sync-base --check feat/<slug>` — development may have moved while you were in QC. A migration collision here (exit 5) sends you back to Stage 2 with the rename; a clean result (exit 0) proceeds to the push.
|
||||
- Re-run the preflight: `agenthub lanes sync-base --check feat/<slug>` — development may have moved while you were in QC. A migration collision here (exit 5) sends you back to Stage 2 with the rename; a clean result (exit 0) proceeds to the push.
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Stage 12 — unconditional merge + the exit-4/`--continue` mechanics**
|
||||
@@ -1127,7 +1127,7 @@ Find (Stage 12, around `SKILL.md:155`):
|
||||
|
||||
```
|
||||
- `CONFLICTING` → the feature branch conflicts with `development`. Resolve it as real work:
|
||||
- If `ccam lanes sync-base` exists by now: `ccam lanes sync-base feat/<slug>` (merges the latest `origin/development` INTO the feature branch — the only sanctioned merge). Resolve every conflict thoughtfully — keep `development`'s behavior for code unrelated to this feature, preserve the feature's intent where they overlap; when genuinely ambiguous, STOP and escalate (`--status blocked`, note the files) rather than guess. `git add` ONLY the conflicted files, `git commit --no-edit`.
|
||||
- If `agenthub lanes sync-base` exists by now: `agenthub lanes sync-base feat/<slug>` (merges the latest `origin/development` INTO the feature branch — the only sanctioned merge). Resolve every conflict thoughtfully — keep `development`'s behavior for code unrelated to this feature, preserve the feature's intent where they overlap; when genuinely ambiguous, STOP and escalate (`--status blocked`, note the files) rather than guess. `git add` ONLY the conflicted files, `git commit --no-edit`.
|
||||
- If it doesn't exist yet: `git fetch origin && git merge origin/development` directly on the feature branch, resolve conflicts the same way, commit.
|
||||
- Re-enter the pipeline **from Stage 2 through Stage 8** (the push updates the PR), then return here and keep watching.
|
||||
```
|
||||
@@ -1136,8 +1136,8 @@ Replace with:
|
||||
|
||||
```
|
||||
- `CONFLICTING` → the feature branch conflicts with `development`. Resolve it as real work:
|
||||
- `ccam lanes sync-base feat/<slug>` (merges the latest `origin/development` INTO the feature branch — the only sanctioned merge). A migration-number collision (exit 5) means nothing was merged — rename the printed file on the feature branch, re-run Stage 2, then retry this step.
|
||||
- **Exit 4 — merge conflict, left in place on purpose.** Resolve every conflict thoughtfully on the feature branch — keep `development`'s behavior for code unrelated to this feature, preserve the feature's intent where they overlap; when genuinely ambiguous, STOP and escalate (`--status blocked`, note the files) rather than guess. Never hand-merge a generated contract/client file listed in the profile's `GENERATED_MERGE_PATHS` — the keep-ours driver + regen own them. `git add` ONLY the conflicted files, `git commit --no-edit`, then `ccam lanes sync-base --continue feat/<slug>` (folds any regenerated artifacts into a follow-up commit).
|
||||
- `agenthub lanes sync-base feat/<slug>` (merges the latest `origin/development` INTO the feature branch — the only sanctioned merge). A migration-number collision (exit 5) means nothing was merged — rename the printed file on the feature branch, re-run Stage 2, then retry this step.
|
||||
- **Exit 4 — merge conflict, left in place on purpose.** Resolve every conflict thoughtfully on the feature branch — keep `development`'s behavior for code unrelated to this feature, preserve the feature's intent where they overlap; when genuinely ambiguous, STOP and escalate (`--status blocked`, note the files) rather than guess. Never hand-merge a generated contract/client file listed in the profile's `GENERATED_MERGE_PATHS` — the keep-ours driver + regen own them. `git add` ONLY the conflicted files, `git commit --no-edit`, then `agenthub lanes sync-base --continue feat/<slug>` (folds any regenerated artifacts into a follow-up commit).
|
||||
- Re-enter the pipeline **from Stage 2 through Stage 8** (the push updates the PR), then return here and keep watching.
|
||||
```
|
||||
|
||||
@@ -1148,12 +1148,12 @@ In `docs/LANES.md`, under `## The ship-feature-lane skill (E1)` (`docs/LANES.md:
|
||||
```markdown
|
||||
### Dev preflight and merge safety: sync-base
|
||||
|
||||
`ccam lanes sync-base` is the ONE sanctioned merge in the pipeline — `origin/development` into a feature branch — used at Stages 2, 8, and 12. Three modes:
|
||||
`agenthub lanes sync-base` is the ONE sanctioned merge in the pipeline — `origin/development` into a feature branch — used at Stages 2, 8, and 12. Three modes:
|
||||
|
||||
```bash
|
||||
ccam lanes sync-base --check feat/<slug> # read-only preflight: fetch + collision check + DEV_DELTA/DEV_OVERLAP
|
||||
ccam lanes sync-base feat/<slug> # merge origin/development into the feature branch
|
||||
ccam lanes sync-base --continue feat/<slug> # finish after a manually resolved conflict
|
||||
agenthub lanes sync-base --check feat/<slug> # read-only preflight: fetch + collision check + DEV_DELTA/DEV_OVERLAP
|
||||
agenthub lanes sync-base feat/<slug> # merge origin/development into the feature branch
|
||||
agenthub lanes sync-base --continue feat/<slug> # finish after a manually resolved conflict
|
||||
```
|
||||
|
||||
Exit codes: `0` clean, `4` merge conflict (left in place — resolve, commit, then `--continue`), `5` migration-number collision (nothing merged — rename the printed file, re-run).
|
||||
@@ -1161,7 +1161,7 @@ Exit codes: `0` clean, `4` merge conflict (left in place — resolve, commit, th
|
||||
Two profile declarations control it, both empty (off) by default:
|
||||
|
||||
```bash
|
||||
# .ccam/profile/profile.env
|
||||
# .agenthub/profile/profile.env
|
||||
MIGRATIONS_DIR="db/migrations"
|
||||
GENERATED_MERGE_PATHS="api/openapi.json api/client.ts"
|
||||
```
|
||||
@@ -1194,5 +1194,5 @@ npm run test:server
|
||||
|
||||
```bash
|
||||
git add .claude/skills/ship-feature-lane/SKILL.md docs/LANES.md docs/superpowers/plans/2026-08-03-shipyard-parity-lanes.md
|
||||
git commit -m "docs(lanes): document ccam lanes sync-base (E2)"
|
||||
git commit -m "docs(lanes): document agenthub lanes sync-base (E2)"
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user