Files
AgentHub/docs/superpowers/specs/2026-08-25-agenthub-ci-status-design.md
T
nntrivi2001 17d56d0e01 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).
2026-09-07 12:09:15 +07:00

130 lines
5.6 KiB
Markdown

# `agenthub ci status` — unblock Stage 13's CI-wait half
**Status:** approved 2026-08-25.
## Problem
`ship-feature-lane`'s Stage 13 (post-merge verification) is hardcoded
skipped. Two integrations gate it: dev-CI-wait (watch CI on `development`
after a PR merges, before QCing the deployed site) and dev-QC (QC the
deployed site). Neither exists yet.
This spec covers only the CI-wait half. `agenthub lanes integration ci_wait`
already exists (`server/lib/lane-profile.js:isIntegrationEnabled`,
`bin/agenthub.js:cmdLanesIntegration`) and reports whether a profile *wants* the
integration on — but nothing acts on it. `agenthub ci` doesn't exist
(`skills/ship-feature-lane/SKILL.md:167` notes this explicitly at Stage 10,
where the skill falls back to raw `gh pr checks`/`gh run view`).
Dev-QC (QCing the deployed site) is a separate, later task — out of scope
here. Stage 13's dev-QC half stays noted as unavailable until that lands.
## Approach
**A read-only status snapshot, not a wait loop.** Per the project's
orchestration doctrine (`docs/LANES.md` § "Orchestration: what AgentHub does NOT
do" — no chaining, no queue, no retry logic), `agenthub ci status` reports a
fact once; it does not poll, block, or retry. The driving skill owns the
poll loop and the fix/escalate decision, the same shape Stage 12 already
uses for watching a PR (`sleep 300` backgrounded, re-invoked per iteration).
This also means `agenthub ci status` needs no flake classification. Stage 10
already does that triage (infra/flake signature vs. real failure) reading
`gh` output directly — Stage 13 reuses the same triage, now reading this
command's structured JSON instead of raw `gh`.
**Server-backed, following the `sync-base` pattern**, not a CLI-local `gh`
spawn. Every existing `agenthub` command is a thin HTTP client — no command in
`bin/agenthub.js` spawns a child process directly (`worktree.js`'s `git()`
helper is the only child-process boundary AgentHub has today, always
server-side). A new `server/lib/gh.js` mirrors that helper:
```js
async function gh(cwd, args) { /* execFile("gh", args, { cwd }) */ }
```
New route: `GET /api/lanes/:id/ci/status?ref=<branch-or-sha>`
- Resolves the lane's `cwd` (same lookup every other lane route uses).
- Runs `gh run list --branch <ref> --json databaseId,conclusion,status,url --limit 1`
to find the latest run for that ref, then `gh run view <id> --json jobs`
for per-job conclusions. (A `sha` ref: `gh run list` accepts a commit SHA
via `--commit`, not `--branch` — the route tries `--branch` first and
falls back to `--commit` if the ref doesn't look like a branch name a
lane would use, i.e. it's a 7-40 char hex string.)
- No run found for the ref at all → `state: "pending"` (CI hasn't started
yet, not an error).
- `gh` missing or not authenticated → `{ error: { message } }`, HTTP 500.
New CLI: `agenthub lanes ci status <branch-or-sha> [<lane-id>]`
- GETs the route above, prints the JSON, sets `process.exitCode`.
- Resolves the lane the same way every other `agenthub lanes <verb>` command
does (`resolveLaneArg`), so it works with an implicit lane-from-cwd or an
explicit id, matching `agenthub lanes integration`.
## Response shape
```json
{
"state": "success",
"ref": "a1b2c3d",
"checks": [
{ "name": "server-tests", "conclusion": "failure", "url": "https://github.com/.../runs/123" }
]
}
```
`state` is derived, never taken from a single field: any job still
`in_progress`/`queued` → `pending`; else any `failure`/`cancelled`/
`timed_out` → `failure`; else (`success`/`skipped` only) → `success`.
## Exit codes
CLI mirrors the response into a process exit code, same convention as
`sync-base`'s distinct exit codes per outcome:
- `0` — `state: "success"`
- `1` — `state: "failure"`, OR any execution error (`gh` missing, lane not
found, route error) — printed as `✖ ci status → <message>` on stderr
- `3` — `state: "pending"` (covers both "checks running" and "no run found
yet for this ref")
## Skill changes
`skills/ship-feature-lane/SKILL.md` Stage 13: replace the hardcoded-skip
note with a poll loop mirroring Stage 12's:
- Get the merge SHA: `gh pr view <pr_url> --json mergeCommit -q .mergeCommit.oid`.
- Loop (`sleep 300`, `run_in_background: true`, bump heartbeat each
iteration): `agenthub lanes ci status <sha>`.
- `pending` → keep waiting.
- `failure` → triage like Stage 10 (`gh run view` for job logs on the
same run id returned in `checks[].url`), fix + re-enter from Stage 2,
or escalate.
- `success` → dev-QC half is still unavailable (separate task) — note
that explicitly and proceed to Stage 14, same as today but now honest
that CI-wait specifically passed.
- Update `docs/LANES.md`: the "Stages currently hardcoded skipped" list
(Stage 13 becomes "CI-wait works; dev-QC still off"), the
`agenthub lanes integration` section's claim that `ci_wait`'s consumer isn't
built, and add `agenthub ci status` to the command reference.
## Non-goals
- No flake auto-classification or auto-rerun inside `agenthub ci status` —
stays a dumb fact-reporter; the skill keeps owning that judgment, per
AgentHub's no-retry-logic rule.
- No change to Stage 10 (PR CI watch) — it keeps using raw `gh` directly.
Reusing this command there is a plausible future cleanup, not required
now.
- No dev-QC implementation — separate task, tracked independently.
## Testing
- `server/tests` — new test for the `/api/lanes/:id/ci/status` route,
mocking `execFile`/`gh` output for: pending (no run yet), pending
(in-progress run), success, failure, and `gh`-not-found — pattern after
the existing `sync-base` route tests.
- `npm run test:server` before considering this done.