feat(skills,pipelines): ask the user at the two points being wrong is cheap, and stop paying for reviews the diff does not need

The `default` 8-node pipeline walked past its own intake: the node declared
`agenthub stage intake`, a stage report with no work attached, so "intake" was
a label the run passed through without ever asking a question. It now declares
`/superpowers:brainstorming` (and detects it — that rule moves off `plan`),
and both driving skills make the brainstorm mandatory, asked with
AskUserQuestion and waited on rather than answered on the user's behalf.

Three stops replace three silent slides:

- After the plan is written and adversarially challenged, it goes to the USER
  for approval. Implementation does not start without it, and work that turns
  out to need a different approach comes back for a fresh one.
- Review picks its reviewers from `git diff --name-only`: Claude Code's own
  `code-review` always, a domain reviewer only for a layer the diff actually
  touched, and — new — only once the change is big enough to have seams. Three
  agents re-reading twenty lines buys one opinion at three times the tokens, on
  every fix-loop lap. Review is also a loop now: it ends on a clean pass over
  the current diff, not on one pass having happened.
- The gate asks the user to accept before anything is claimed done (and in the
  lane pipeline, before the PR is published — publishing is outward-facing).
  A NO-GO re-enters by SIZE: a defect goes back to implement, a wrong approach
  back to plan. Nothing carries a NO-GO forward with a note about it.

Also here, from a real stall seen on a lane: `ship-feature` had no waiting rule
at all, and a session at the gate invented one with `ScheduleWakeup` — a
/loop-only primitive that paces nothing here and is refused outright when
`auto` mode cannot reach its safety classifier. The rule the lane skill already
had now exists in both.

Cost, measured in what each agent is actually for: the suite run leaves its
agent (nothing is judged, so nothing is delegated — an agent there buys a
second model's tokens to read output the session can read for free), and
`backend-reviewer` drops from opus to sonnet like its frontend twin; both read
a scoped diff against a fixed checklist, and the senior gate above them is
still opus.

Skill bugs found in the same sweep: doc-map told agents not to recreate the
removed translations and then, three lines later, to mirror every README change
into them; the docs mapping still carried `+VN+CN` and the punctuation left by
their removal; Procedure jumped 2 → 6; Verify required `scripts/doc-coverage.sh`,
which does not exist in this repo.
This commit is contained in:
2026-09-18 10:21:03 +07:00
parent 4227a97ab1
commit 26b0fe53c7
13 changed files with 180 additions and 80 deletions
+19 -11
View File
@@ -1,11 +1,11 @@
---
name: ship-feature-lane
description: "Autonomous end-to-end feature pipeline for ONE AgentHub lane. Invoke inside a lane's working directory with a requirement: `/ship-feature-lane <requirement>`. Frontloads ALL clarifying questions once, then runs unattended: implement (TDD) → independent unit-test agent → pre-push CI gates + dev preflight → e2e on the feature branch (agent-run) → code review (fresh-context agent) → local QC → senior GO/NO-GO gate → push branch + open PR (base `development`) → CI watch → report, then watches the PR (new comments → gated fix-loop; base conflicts → sync development into the branch) until a HUMAN merges it. The PR is only published after all local gates pass and the senior gate says GO — it's finalized when reviewers see it. Declares lane stage at every step via `agenthub stage` for the dashboard. Use when the user wants to build/ship/implement a feature in a AgentHub lane. NOTE: ticket-filing (Stage 9) and post-merge dev-site QC (Stage 13's second half) are currently OFF (F's integrations aren't built yet) — Stage 13's CI-wait half now runs via agenthub lanes ci status."
description: "Autonomous end-to-end feature pipeline for ONE AgentHub lane. Invoke inside a lane's working directory with a requirement: `/ship-feature-lane <requirement>`. Brainstorms with the user and frontloads ALL clarifying questions once (`AskUserQuestion`), stops for their approval of the plan, then runs unattended: implement (TDD) → independent unit-test agent → pre-push CI gates + dev preflight → e2e on the feature branch (agent-run) → code review (fresh-context agent) → local QC → senior GO/NO-GO gate → the user's acceptance → push branch + open PR (base `development`) → CI watch → report, then watches the PR (new comments → gated fix-loop; base conflicts → sync development into the branch) until a HUMAN merges it. The PR is only published after all local gates pass, the senior gate says GO and the user accepts — it's finalized when reviewers see it. A NO-GO loops back to the gates, or to replanning when the approach itself was wrong. Declares lane stage at every step via `agenthub stage` for the dashboard. Use when the user wants to build/ship/implement a feature in a AgentHub lane. NOTE: ticket-filing (Stage 9) and post-merge dev-site QC (Stage 13's second half) are currently OFF (F's integrations aren't built yet) — Stage 13's CI-wait half now runs via agenthub lanes ci status."
---
# Ship Feature Lane (AgentHub lane pipeline)
You are running the autonomous feature pipeline for **one AgentHub lane**. The human's only interactive touchpoints are **Stage 0 (frontloaded Q&A)** and **merging the PR on GitHub**; everything else runs to completion or to a `blocked` escalation, reporting progress through `agenthub stage` (which the dashboard renders).
You are running the autonomous feature pipeline for **one AgentHub lane**. The human's interactive touchpoints are exactly three — **Stage 0 (frontloaded Q&A)**, **Stage 0b (approving the plan)** and **Stage 7 (accepting the work before the PR is published)** — plus **merging the PR on GitHub**; everything between them runs to completion or to a `blocked` escalation, reporting progress through `agenthub stage` (which the dashboard renders). Those three are not optional politeness: they are the points where being wrong is cheapest to fix (before a plan), and where being wrong becomes public (before a PR).
## Current status
@@ -48,7 +48,7 @@ Resume from the stage shown. If state says `stage=X status=running`, you were mi
## Hard rules
- **Publish ONLY after the senior-gate-reviewer returns `VERDICT: GO`.** "Publish" = push the feature branch + open/update the PR (Stage 8). Nothing reviewer-visible exists before GO, and nothing else authorizes it.
- **Publish ONLY after the senior-gate-reviewer returns `VERDICT: GO` AND the human accepts it (Stage 7).** "Publish" = push the feature branch + open/update the PR (Stage 8). Nothing reviewer-visible exists before both, and nothing else authorizes it.
- **Testing and reviewing run in a FRESH-CONTEXT agent — never in this session.** The session that wrote the code is its worst judge: it already believes the code is correct and it remembers the reasoning the tests are supposed to challenge. Every stage whose job is to *judge* the work — Stage 0b (plan debate), Stage 1b (unit tests), Stage 3 (e2e run + triage), Stage 4 (code review), Stage 6 (browser QC), Stage 7 (senior gate) — is dispatched with the Agent tool to a subagent that starts with an EMPTY context and receives only artifacts it can verify itself: the lane's working directory, the lane spec file, the diff range, the commands to run, and the other agents' reports verbatim. The stages you keep are the ones that *do* rather than judge: intake, implementing, the mechanical gates (Stage 2), publishing (Stage 8), the CI/PR watch (Stages 10–12), and applying every fix the judges ask for. Rules: **never `subagent_type: fork`** for these (a fork inherits this session's context, which defeats the whole point); never "save a round-trip" by doing the pass yourself; never paste your own conclusions ("I already checked X", "this is safe because…") into the brief — hand facts and paths, not verdicts. You implement and you apply fixes; you do not grade your own work.
- Launch them **FOREGROUND** (they gate the pipeline, and their completion re-invokes you, which satisfies the turn-liveness rule).
- Each returns ONE parseable final line (`UNIT-TESTS:` / `E2E:` / `REVIEW:` / `LOCAL-QC:` / `VERDICT:`). Parse that line; never infer a pass from prose.
@@ -63,7 +63,7 @@ Resume from the stage shown. If state says `stage=X status=running`, you were mi
- **Run long helpers so they can't be killed mid-flight or hang your turn.** `agenthub lanes hook ci-gate`, `agenthub lanes up`, `agenthub lanes hook e2e` legitimately run 3–20+ minutes (builds, tests, Playwright, lock waits). NEVER invoke them with the default Bash timeout (2 min kills them mid-flight and strands the lane half-done): use `run_in_background: true` and poll the output file until done, or set `timeout: 600000` for the shorter gates. If a helper does die mid-run, don't panic: every hook is idempotent — re-run the step (e.g. re-run `agenthub lanes up --no-build` to revive a stack).
- **Waiting + polling NEVER use a foreground `sleep`** (the Bash tool blocks it) or `ScheduleWakeup` (that's a `/loop`-only primitive — this pipeline is not a `/loop` session, so it won't sustain your watch). To pace a poll loop or wait out a timer, **background the wait**: run `sleep <secs>` with `run_in_background: true` — you're re-invoked when it exits, and re-invoked the moment a backgrounded Agent or helper finishes, so you never busy-poll for background work. **If you ever can't sustain a wait/loop in this session, set `agenthub stage <current> --note "<honest note>"` and STOP — never narrate a watch or loop you are not actually running.**
- **e2e: actively poll — never wait on the completion re-invoke alone.** This binds whoever actually runs the hook — normally Stage 3's e2e agent, so pass this paragraph into its brief verbatim; you only follow it yourself for an ad-hoc run. A hung suite never fires the completion re-invoke, stranding the lane at `stage=e2e-feature`. When running `agenthub lanes hook e2e`: start it `run_in_background: true` AND background a `sleep 90` beside it. Each wake — finished → parse PASS/FAIL; still running → read the e2e log tail (`agenthub lanes logs <id> e2e`), bump the heartbeat, and re-background `sleep 90`, UNLESS it's erroring or has run past ~22 min, in which case kill the e2e task and treat it as FAIL → re-enter Stage 2.
- **Turn-liveness: never let the pipeline die silently.** A "stalled" lane usually died one of two ways: (a) a turn ended with NOTHING pending — no backgrounded wait, no running helper, no background agent — so nothing ever re-invoked the session; or (b) a transient API error (rate-limit, 529/overload, connection refused) killed the turn mid-stage. Rules: while the pipeline is anywhere between Stage 1 and Stage 14 (done), every turn you end MUST leave at least one re-invoker pending (a `run_in_background` helper/sleep or a background agent) — check before ending the turn. And on ANY resume after an error or a human nudge ("continue"), do not ask questions: re-derive position from lane state (Context recovery above) and continue the stage. If you truly cannot leave a re-invoker, set `--note "watch needs re-trigger: <what to do>"` so the dashboard shows it honestly.
- **Turn-liveness: never let the pipeline die silently.** A "stalled" lane usually died one of two ways: (a) a turn ended with NOTHING pending — no backgrounded wait, no running helper, no background agent — so nothing ever re-invoked the session; or (b) a transient API error (rate-limit, 529/overload, connection refused) killed the turn mid-stage. Rules: while the pipeline is anywhere between Stage 1 and Stage 14 (done), every turn you end MUST leave at least one re-invoker pending (a `run_in_background` helper/sleep or a background agent) — check before ending the turn. The ONE legitimate exception is a turn that ends on an `AskUserQuestion` at a scheduled touchpoint (Stage 0, 0b, 7): the human's answer is the re-invoker, and a pipeline waiting on a question it actually asked is not a stalled one. And on ANY resume after an error or a human nudge ("continue"), do not ask questions: re-derive position from lane state (Context recovery above) and continue the stage. If you truly cannot leave a re-invoker, set `--note "watch needs re-trigger: <what to do>"` so the dashboard shows it honestly.
- **No retry cap — the phase clock is the signal.** A failing gate/QC/CI/e2e just re-enters the loop (fix on the feature branch, re-run from Stage 2); there is NO automatic block after N attempts. The dashboard shows how long the lane has sat in its current stage, so the human can spot a stuck or endlessly-looping lane and step in. Reserve `--status blocked` for GENUINE blockers you cannot resolve (an ambiguous merge conflict, a hard/unrecoverable error).
- **Commit only on the feature branch.** Never commit on `development`/`main`. Stage only intended files (never `git add .` blindly — this repo collects stray build/QA artifacts).
- Keep the lane's state truthful: on any stop, set an accurate `agenthub stage <stage> --status <status> --note "<why>"`.
@@ -76,8 +76,9 @@ Resume from the stage shown. If state says `stage=X status=running`, you were mi
### 0 — Intake & frontloaded Q&A *(the only interactive part)*
Do NOT jump to code. Understand the requirement first.
- **Restate + quick scan.** Restate the requirement. Do a fast targeted scan of the relevant code (use the `Explore` agent for breadth; the **brainstorming** skill if the requirement is fuzzy) so your questions are grounded in what actually exists.
- **Frontloaded Q&A.** Ask the human **every** clarifying question in ONE batch: acceptance criteria, scope / non-goals, UI/UX specifics, data shapes, edge cases, which existing flows it touches. **Sibling-surface check (mandatory):** if your scan shows the app has N parallel surfaces of the pattern the requirement touches (e.g. several foldered areas, several list pages sharing a component) and the requirement names fewer than N, explicitly ask "this exists in [all N places] — apply to all, or only [the named ones]?" A missed sibling here costs a full second pipeline pass when a reviewer catches it on the PR. Then activate a clean feature slot for this run: `agenthub feature activate <slug> --title "<short title>"` — Task B's `activate` archives whatever feature was previously active on this lane automatically, so this run's dashboard state starts clean without a separate "init" step. Then mark intake: `agenthub stage intake --status running`. Announce "Questions answered — going autonomous now." After this, don't ask the human anything unless you hit a `blocked` escalation.
- **Restate + quick scan.** Restate the requirement. Do a fast targeted scan of the relevant code (use the `Explore` agent for breadth) so your questions are grounded in what actually exists.
- **The brainstorm is mandatory, not conditional.** Run the **superpowers:brainstorming** skill here on every run — not only "if the requirement is fuzzy". A one-line requirement always leaves scope, edge cases and acceptance criteria unstated, and this stage is the only place left to find that out cheaply.
- **Frontloaded Q&A — asked with `AskUserQuestion`, and you WAIT for the answers.** Put the questions to the human with the `AskUserQuestion` tool (batched, up to 4 per round, each with real options — the way plan mode asks), not as prose they may not answer. Ask **every** clarifying question in ONE batch: acceptance criteria, scope / non-goals, UI/UX specifics, data shapes, edge cases, which existing flows it touches. You may not answer them on the human's behalf and you may not go on to Stage 0b until they are answered — deciding for them here is what makes a whole autonomous pipeline build the wrong feature. Only if the human explicitly says to decide yourself do you proceed, and then you write the assumptions into the lane spec. **Sibling-surface check (mandatory):** if your scan shows the app has N parallel surfaces of the pattern the requirement touches (e.g. several foldered areas, several list pages sharing a component) and the requirement names fewer than N, explicitly ask "this exists in [all N places] — apply to all, or only [the named ones]?" A missed sibling here costs a full second pipeline pass when a reviewer catches it on the PR. Then activate a clean feature slot for this run: `agenthub feature activate <slug> --title "<short title>"` — Task B's `activate` archives whatever feature was previously active on this lane automatically, so this run's dashboard state starts clean without a separate "init" step. Then mark intake: `agenthub stage intake --status running`. After this the human is asked exactly twice more — to approve the plan (Stage 0b) and to accept the work before the PR is published (Stage 7) — plus any `blocked` escalation. Nothing else is interactive.
### 0b — Investigate & plan *(autonomous)*
- `agenthub stage plan` — now design a real plan and have it independently challenged before you implement.
@@ -85,6 +86,8 @@ Do NOT jump to code. Understand the requirement first.
- **Plan.** Produce a concrete implementation plan (the **writing-plans** skill): approach, files to change, the test strategy (which behaviors/edge cases each test will pin), migration/contract impact, and how each acceptance criterion is met.
- **Debate the plan (adversarial review) — fresh context, never `fork`.** Spawn a SEPARATE sub-agent (Agent tool — `Plan` or `general-purpose`, FOREGROUND) to critique the plan + investigation. Hand it the requirement, the Stage-0 answers and the plan as text plus the paths to read; do NOT hand it your reasoning for why the plan is right — that is exactly what it is there to test. Ask for: missed requirements, wrong assumptions, a simpler approach, unhandled edge cases, acceptance-criteria gaps. Apply the worthwhile critiques (use **receiving-code-review** judgment — verify each point, don't blindly accept or reject). Iterate once or twice until the plan holds up.
- Write the Q&A answers **and the agreed plan** to a lane spec file `docs/superpowers/specs/lane-<slug>.md` (gitignored, or add it to `.gitignore` if this is the first one) — the acceptance contract the senior gate checks against.
- **STOP — the human approves the plan before any code exists.** This is the second of the three scheduled interactive touchpoints. Show them the plan: what changes, which files, what is deliberately out of scope, the test strategy, and how each acceptance criterion is met — plus the lane spec path. Ask with `AskUserQuestion`: approve / revise / change approach. "Revise" means edit the plan and the lane spec and ask again. **Stage 1 does not start without an approval in this turn** — an adversarial agent agreeing with your plan is not the human agreeing with it. Announce "Plan approved — going autonomous now" and only then continue.
- A later stage that turns out to need a materially different approach comes BACK here for a fresh plan and a fresh approval, rather than drifting under the old one.
### 1 — Implement (TDD, to the plan)
- Choose a **single-segment slug** for the feature — lowercase, hyphens, NO slashes. Cut the feature branch from **development** (the PR base): `git fetch origin && git checkout -b feat/<slug> origin/development`.
@@ -125,15 +128,16 @@ The e2e hook doesn't run migrations itself — it tests the already-running stac
### 4 — Code review *(no open PR yet — use local diff)*
- `agenthub stage review --status running`, then launch a fresh-context reviewer agent (Agent tool, `subagent_type: Code Reviewer` — FOREGROUND, **never `fork`**; a reviewer who already watched you write the code is not a reviewer). Hand it ONLY: the lane's working directory, the lane spec path (requirement + acceptance criteria), the diff commands, and the brief below. Do NOT summarize your own implementation for it, and do NOT pre-empt findings — let it read the diff cold.
- Run the **`code-review` skill at effort `high`** on the feature diff vs `origin/development` — the deterministic gate, not an ad-hoc read. No PR is open yet, so point it at the local diff: `git diff origin/development...feat/<slug>` (and `git log origin/development..feat/<slug>` for commits). ONLY if the `code-review` skill is unavailable in its session, fall back to a manual review of that diff (correctness, security, tests, migration/contract safety, this repo's `CLAUDE.md` + `.claude/rules/` boundaries).
- Run **Claude Code's own `code-review` skill** (the official plugin's `/code-review`) **at effort `high`** on the feature diff vs `origin/development` — the deterministic gate, not an ad-hoc read, and not a reviewer summarizing the diff in its own words. No PR is open yet, so point it at the local diff: `git diff origin/development...feat/<slug>` (and `git log origin/development..feat/<slug>` for commits). ONLY if the `code-review` skill is unavailable in its session, fall back to a manual review of that diff (correctness, security, tests, migration/contract safety, this repo's `CLAUDE.md` + `.claude/rules/` boundaries).
- Final line: `REVIEW: CLEAN` or `REVIEW: FINDINGS — <n>`, with the findings listed above it as `path:line — severity — problem — suggested fix`.
- **Scale the pass to the diff.** A handful of lines in one layer gets the `code-review` pass alone — three agents re-reading a 20-line change buys one opinion at three times the tokens, and this stage re-runs on every fix-loop lap. Add the domain reviewer(s) once the change has seams: multiple files in a layer, a route/schema/migration/hook touched, or anything you would want a second reader on.
- **Domain reviewers, in parallel with the above (same message, separate Agent calls).** Check `git diff --name-only origin/development...feat/<slug>` for touched layers and launch every matching one — FOREGROUND, fresh context, **never `fork`**, addressed as `agenthub:backend-reviewer` / `agenthub:frontend-reviewer` (plugin-qualified — no lane install needed, unlike `qc-local`/`senior-gate-reviewer`):
- Any path under `server/` → `agenthub:backend-reviewer`.
- Any path under `client/` → `agenthub:frontend-reviewer`.
- Neither touched (root/`skills/`/`agents/`/`scripts/`/docs-only change) → skip both; the generic Code Reviewer above is the only gate.
- Hand each ONLY the lane's working directory and the diff range `git diff origin/development...feat/<slug>` — each scopes itself to its own domain's files even though the diff range is the same for both.
- Each ends with its own parseable line: `BACKEND-REVIEW:` / `FRONTEND-REVIEW:` — `CLEAN` or `FINDINGS — <n>`.
- Triage ALL findings — the generic review plus every domain reviewer that ran — together with **receiving-code-review** judgment (verify each, neither blind agreement nor blind rejection) and apply what's worth applying on the feature branch. Changed source → re-run **from Stage 1b**; changed only tests → **from Stage 2**. Keep the findings + your resolutions — the senior gate reads them.
- Triage ALL findings — the generic review plus every domain reviewer that ran — together with **receiving-code-review** judgment (verify each, neither blind agreement nor blind rejection) and apply what's worth applying on the feature branch. A finding you reject is answered with a reason, never with silence. Changed source → re-run **from Stage 1b**; changed only tests → **from Stage 2**. Either way the re-entry passes through THIS stage again: review ends when a pass over the current diff comes back clean (or with only findings you explicitly and defensibly rejected), not when one pass has been performed. Keep the findings + your resolutions — the senior gate reads them.
- The Stage-6 `qc-local` report covers the user-flow review for the senior gate.
- `agenthub stage review --evidence "<total findings count across all reviewers that ran> findings, resolved"`
@@ -154,9 +158,13 @@ The e2e hook doesn't run migrations itself — it tests the already-running stac
### 7 — Senior GO/NO-GO gate *(authorizes the publish)*
- Launch the **senior-gate-reviewer** agent (Agent tool, `subagent_type: senior-gate-reviewer`, or `agenthub:senior-gate-reviewer` if the lane copy isn't installed — FOREGROUND, fresh context, **never `fork`**; installed the same way as `qc-local`, see Stage 6). Give it: the lane's working directory, the requirement + Stage-0 answers (the lane spec file), the feature branch, the Stage-4 code-review findings + resolutions **as the other agents wrote them** (verbatim/by path — never your paraphrase of why each was fine), the Stage-6 `qc-local` report (the user-flow review), and the raw results of gates/e2e/QC. The agent inspects the local diff with `git diff origin/development...feat/<slug>` — no open PR is required (and none exists yet).
- Parse its final line:
- `VERDICT: GO` → proceed to Stage 8.
- `VERDICT: NO-GO — <fixes>` → `agenthub stage gate-blocked --evidence "NO-GO — <reason>"` (an alias of `gate`, so the map holds while the lane's stage name says the gate refused), then fix on the feature branch and re-run **from Stage 2**. No attempt cap — the loop re-enters; the dashboard's time-on-stage surfaces a lane stuck cycling so the human can step in. Set `--status blocked` only for a genuine blocker you can't resolve.
- `agenthub stage gate --evidence "GO"` (or `NO-GO — <reason>`)
- `VERDICT: GO` → the agent gate is satisfied; now the human's.
- `VERDICT: NO-GO — <fixes>` → `agenthub stage gate-blocked --evidence "NO-GO — <reason>"` (an alias of `gate`, so the map holds while the lane's stage name says the gate refused), then **re-enter by the SIZE of what is wrong**, not always at the same place:
- A defect, a missed case, a wrong detail → fix on the feature branch and re-run **from Stage 2** (or Stage 1b if non-test source changed).
- Wrong approach, wrong scope, or a requirement that turns out to mean something else → back to **Stage 0b**: replan, and take the new plan through its approval stop again before any further code.
- No attempt cap — the loop re-enters; the dashboard's time-on-stage surfaces a lane stuck cycling so the human can step in. Set `--status blocked` only for a genuine blocker you can't resolve. Two NO-GOs on the same root issue means the loop is not converging: stop and ask the human instead of a third lap.
- **Then ask the human to accept, before anything reviewer-visible exists.** Publishing is outward-facing and irreversible in the social sense — a PR reviewers have seen cannot be un-seen. Present: what was built, what was verified and how (gates/e2e/QC with their real outcomes), what the reviews found and what you did about it, and anything you could not run. Ask with `AskUserQuestion`: publish the PR / send back for fixes / rethink the approach. `VERDICT: GO` is the agent's opinion about evidence; it is not the human's decision to publish. Not accepted → re-enter exactly as for a NO-GO above.
- `agenthub stage gate --evidence "GO; human accepted"` (or `NO-GO — <reason>`)
### 8 — Publish: push branch + open/update PR *(GATED — only on GO)*
- `agenthub stage publishing --status running`
+120 -42
View File
@@ -1,6 +1,6 @@
---
name: ship-feature
description: Implement a feature safely end-to-end in this repository. Use when adding or changing functionality across backend, frontend, or MCP with required verification and documentation updates. Drives the Superpowers workflow skills and declares each phase with `agenthub stage` so the dashboard's pipeline map follows along.
description: Implement a feature safely end-to-end in this repository. Use when adding or changing functionality across backend, frontend, or MCP with required verification and documentation updates. Drives the Superpowers workflow skills and declares each phase with `agenthub stage` so the dashboard's pipeline map follows along. Brainstorms WITH the user at intake, stops for their approval of the plan before any code, reviews with Claude Code's own `code-review` plus only the domain reviewers the diff actually needs, and stops again at the gate for their acceptance — a NO-GO loops back to implement or plan rather than shipping.
---
# Ship Feature
@@ -37,17 +37,47 @@ never overrides a declaration — and detection cannot move a lane BACKWARD past
a declared stage, so a rework loop is invisible unless you re-declare the phase
you dropped back to.
## Waiting for an agent or a long command
A phase that dispatches a foreground agent (tests, review, gate) or runs a long
command is **already** wired to wake you: you are re-invoked the moment a
backgrounded Agent or helper finishes. So:
- Do not poll for it, and do not invent a timer. **`ScheduleWakeup` is a
`/loop`-only primitive** — this pipeline is not a `/loop` session, so it
neither paces nor sustains anything here, and in `auto` permission mode it can
simply be refused (the safety classifier is a model call, which fails when
that model is briefly unavailable). Never let a phase's progress depend on it.
- Need to pace a wait anyway (a CI run, an external queue)? Background the wait:
`sleep <secs>` with `run_in_background: true`.
- Never narrate a wait you are not actually running. If you cannot sustain one,
say so plainly and stop.
## Phases
### intake — understand before touching anything
### intake — brainstorm WITH the user, always
- `agenthub stage intake --status running`
- Restate the requirement and its success criteria.
- Explore the impacted modules: `Explore` agent for breadth, then read the key
files yourself. Identify which layers are hit (server / client / docs /
scripts) — `repo-onboarding` if the area is unfamiliar.
- Requirement fuzzy or open to more than one reading? **superpowers:brainstorming**.
- **superpowers:brainstorming is MANDATORY here, not a fallback for a fuzzy
requirement.** Run it before any plan exists. Skipping it because the ask
"seems clear" is the single most common way this pipeline builds the wrong
thing: a requirement typed in one line always leaves scope, edge cases and
acceptance criteria unstated.
- **Ask the user, and wait for the answer.** Put the open questions to them with
`AskUserQuestion` — batched in one round (up to 4 at a time), each with real
options, exactly the way plan mode asks. Questions that change what you build:
scope boundaries, which surfaces are in/out, behavior on the edge cases you
found, what "done" means. You may not answer them on the user's behalf, and
you may not move to `plan` until they are answered. Answering yourself and
proceeding IS the bug this phase exists to prevent.
- The one exception: the user explicitly said to skip the questions and decide
yourself ("cứ làm đi", "no questions", "you decide"). Then state the
assumptions you are proceeding under, in writing, and go on.
### plan — a written plan, challenged before it is code
### plan — a written plan, challenged, then APPROVED by the user
- `agenthub stage plan`
- **superpowers:writing-plans**: approach, files to change, the test strategy
(which behavior each test pins), and how each success criterion is met.
@@ -59,30 +89,44 @@ you dropped back to.
simpler approach, unhandled edge cases. Give it the requirement and the plan,
not your reasons for believing the plan. Apply what survives
**superpowers:receiving-code-review** scrutiny.
- **STOP. The plan is presented to the user and implementation does not start
until they approve it in this turn.** Show the plan (or its path plus a short
summary: what changes, which files, what is deliberately out of scope, how it
will be verified) and ask with `AskUserQuestion` — approve / revise / change
approach. "Revise" means edit the plan and ask again; the loop is the point.
Writing a plan and immediately implementing it is exactly the behavior this
phase forbids, however obvious the plan looks to you.
- Approval covers the plan as presented. Work that turns out to need a
materially different approach comes BACK here (`agenthub stage plan` again)
for a fresh approval, rather than drifting under the old one.
### implement — smallest coherent diff
- `agenthub stage implementing`
- Entered only from an **approved** plan (or from a gate NO-GO sending work
back here). No approval in this turn → you are still in `plan`.
- **superpowers:test-driven-development**: failing test → minimal code → green.
- Smallest diff that satisfies the requirement. Every changed line traces to it.
- **file-headers** applies to every source file you create or edit.
### tests — this repo's verification, not a claim
- `agenthub stage tests --status running`
- **Dispatch, don't self-grade.** Both halves below run in a **fresh-context
agent** (Agent tool, `subagent_type: general-purpose` — FOREGROUND, and
**never `fork`**: a fork inherits your context, which is the bias you are
trying to escape). Hand it only what it can verify itself — repo path, the
spec/requirement, `git diff` range, the commands — never your own conclusions.
- **Independent unit tests.** It reads the requirement and the diff cold and
writes the tests the implementation is *missing* — happy, negative and
boundary, in the repo's existing style. It may not touch non-test files nor
weaken existing tests. Final line: `UNIT-TESTS: PASS — <n> added` or
`UNIT-TESTS: FAIL — <test> :: <defect>`.
- **Suite run.** Backend changed → `npm run test:server`. Frontend →
`npm run test:client`.
A UI snapshot diff is reported for review, **never blindly regenerated**
(`cd client && npx vitest run -u` is yours to run, only after you read the
diff).
- **Dispatch the judgement, run the commands yourself.** Only work that needs an
unbiased pair of eyes is worth an agent; a deterministic command is not.
- **Independent unit tests → a fresh-context agent** (Agent tool,
`subagent_type: general-purpose` — FOREGROUND, and **never `fork`**: a fork
inherits your context, which is the bias you are trying to escape). Hand it
only what it can verify itself — repo path, the spec/requirement, `git diff`
range, the commands — never your own conclusions. It reads the requirement
and the diff cold and writes the tests the implementation is *missing* —
happy, negative and boundary, in the repo's existing style. It may not touch
non-test files nor weaken existing tests. Final line:
`UNIT-TESTS: PASS — <n> added` or `UNIT-TESTS: FAIL — <test> :: <defect>`.
- **Suite run → plain Bash, here.** Backend changed → `npm run test:server`.
Frontend → `npm run test:client`. Nothing is judged, so nothing is
delegated: an agent for this buys a second model's tokens to read output you
can read for free. A UI snapshot diff is reported for review, **never
blindly regenerated** (`cd client && npx vitest run -u` is yours to run,
only after you read the diff).
- `FAIL` → fix the **source** (root cause), not the agent's test — then re-run
this phase. Rewriting a failing independent test to pass is the one move that
makes this whole phase worthless.
@@ -90,32 +134,47 @@ you dropped back to.
`--result fail` with what failed. A step you could not run is reported as not
run, never as passed.
### review — a real review pass, not a re-read
### review — the native review, plus the domains this diff actually touched
- `agenthub stage review --status running`
- Hand the review to a **fresh-context agent** (`subagent_type: Code Reviewer`,
FOREGROUND, never `fork`) — a reviewer that watched you write the code is not
a reviewer. It runs the **code-review** skill on the working diff
(see also **superpowers:requesting-code-review** for what to hand over).
Final line: `REVIEW: CLEAN` or `REVIEW: FINDINGS — <n>`.
- **Domain reviewers, in parallel with the above (same message, separate
Agent calls).** Check `git diff --name-only` (against the base this task
started from) for touched layers and launch every matching one —
FOREGROUND, fresh context, never `fork`, addressed as `agenthub:backend-reviewer`
/ `agenthub:frontend-reviewer`:
- Any path under `server/` → `agenthub:backend-reviewer`.
- Any path under `client/` → `agenthub:frontend-reviewer`.
- Neither touched → skip both; the generic Code Reviewer
above is the only gate.
- **Read the diff first, then decide who reviews it.** `git diff --name-only`
against the base this task started from is what picks the reviewers. Spawning
a fixed set regardless of what changed wastes a pass on files nobody touched,
and worse, reads as coverage that never happened.
- **Scale the pass to the diff.** A handful of lines in one layer gets the
`code-review` pass alone — three agents re-reading a 20-line change costs
three times the tokens for one opinion. Add the domain reviewer(s) once the
change is big enough to have seams: multiple files in a layer, a route or
schema or hook touched, or anything you would want a second reader on.
- **Always: Claude Code's own `code-review` skill** (the official plugin's, run
as `/code-review` on the working diff). It is not optional and is not replaced
by an agent reviewing "in its own words" — run it in a **fresh-context agent**
(`subagent_type: Code Reviewer`, FOREGROUND, never `fork`; a reviewer that
watched you write the code is not a reviewer), whose job is to invoke that
skill and report its findings. See **superpowers:requesting-code-review** for
what to hand over. Final line: `REVIEW: CLEAN` or `REVIEW: FINDINGS — <n>`.
- **Domain reviewers, conditional on the touched layers**, launched in parallel
with the above (same message, separate Agent calls) — FOREGROUND, fresh
context, never `fork`:
- Any path under `server/` (routes, lib, hooks, db, CLI-facing code) →
`agenthub:backend-reviewer`. No backend path changed → do not launch it.
- Any path under `client/` (components, pages, i18n, styles) →
`agenthub:frontend-reviewer`. No frontend path changed → do not launch it.
- Both touched → both, in the same message so they run concurrently.
- Neither touched (docs-only, scripts-only, config-only) → neither; the
`code-review` pass above is the whole review.
- Hand each ONLY the repo path and the working diff — each scopes itself to
its own domain's files. Each ends with its own parseable line:
`BACKEND-REVIEW:` / `FRONTEND-REVIEW:` — `CLEAN` or
`FINDINGS — <n>`.
- Apply what is worth applying — the generic review plus every domain
reviewer that ran — with **superpowers:receiving-code-review** judgment:
verify each point, neither blind agreement nor blind rejection.
- Changed code in response? Re-run the `tests` phase.
`BACKEND-REVIEW:` / `FRONTEND-REVIEW:` — `CLEAN` or `FINDINGS — <n>`.
- Apply what is worth applying — `code-review` plus every domain reviewer that
ran — with **superpowers:receiving-code-review** judgment: verify each point,
neither blind agreement nor blind rejection. A point you reject is answered
with a reason, not silence.
- **Changed code in response? Re-run `tests`, then re-run THIS phase.** Review
is a loop, not a checkpoint: it ends when a pass over the current diff comes
back clean (or with only findings you have explicitly and defensibly
rejected), not when one pass has been performed.
### gate — evidence before the completion claim
### gate — evidence, then the user's acceptance
- **superpowers:verification-before-completion**. Commands actually run, output
actually read. This is the phase that stops "should work" from shipping.
- For a change of any real size, the gate is a **fresh-context agent** too
@@ -124,7 +183,26 @@ you dropped back to.
re-run and re-check them. Final line: `GATE: GO` or `GATE: NO-GO — <what is
missing>`. A one-line fix does not need it; anything you would defend in a
review does.
- `agenthub stage gate --evidence "<what was verified>"`
- **The gate is not yours to wave through. Ask the user.** Present, in a few
lines: what was built, what was verified and how (the commands and their real
outcome), what review found and what you did about it, and anything you could
not run. Then ask with `AskUserQuestion`: accept / send back for fixes /
rethink the approach. Silence is not acceptance, and neither is `GATE: GO` —
the agent gate checks the evidence, the user decides whether this is what they
wanted.
- **NO-GO, or the user does not accept → go BACK, do not proceed.** Pick the
node by the size of what is wrong, and re-declare it so the dashboard follows
the rework (a declaration on an earlier node clears the nodes ahead of it —
that is what makes a loop visible instead of leaving stale `done` evidence):
- A defect, a missed case, a wrong detail → `agenthub stage implementing`, fix
at the root cause, then forward through `tests` and `review` again.
- Wrong approach, wrong scope, a requirement that turns out to mean something
else → `agenthub stage plan`, replan, and get the plan approved again (the
`plan` phase's approval step applies in full, every time through).
- Either way the phases after it run again. Never carry a NO-GO forward into
`ship` with a note about it.
- Only once the user has accepted: `agenthub stage gate --evidence "<what was
verified, and that the user accepted it>"`
### ship — docs, then the user's call
- `agenthub stage ship`
+9 -9
View File
@@ -30,11 +30,11 @@ Update docs **in the same change-set (PR/commit) as the code**, before claiming
| Change type | Docs to update |
|---|---|
| **Env var** | `README.md` (env table), `ARCHITECTURE.md` (inline), `server/README.md`, `.env.example` |
| **Event type** | `README.md`+VN+CN (hook-event table), `ARCHITECTURE.md` (Event types line), `docs/PLUGINS.md`, + i18n, `docs/DATABASE.md` (if it enumerates types) |
| **Hook behavior / state transition** | `docs/HOOKS.md`, state-machine **mermaid** diagrams in `README.md`+VN+CN + `server/README.md` + `docs/DATABASE.md` + , `ARCHITECTURE.md` (hooks.js row) |
| **API route / response** | `docs/API.md`, `server/README.md` (routes), `ARCHITECTURE.md` (routes row), `server/openapi*.js` (code) |
| **Event type** | `README.md` (hook-event table), `ARCHITECTURE.md` (Event types line), `docs/PLUGINS.md`, `docs/DATABASE.md` (if it enumerates types), plus the `en`/`vi` strings under `client/src/i18n/locales/` if the type is rendered |
| **Hook behavior / state transition** | `docs/HOOKS.md`, the state-machine **mermaid** diagrams in `README.md`, `server/README.md` and `docs/DATABASE.md`, `ARCHITECTURE.md` (hooks.js row) |
| **API route / response** | `docs/API.md`, `server/README.md` (routes), `ARCHITECTURE.md` (routes row), `server/openapi.js` + `server/openapi-extra/*.js` (code), then regenerate `openapi.yaml` with `npm run openapi:yaml` |
| **DB schema** | `docs/DATABASE.md`, `ARCHITECTURE.md` (ERD/schema) |
| **WebSocket message** | `client/README.md` (Event Types), `server/README.md`, |
| **WebSocket message** | `client/README.md` (Event Types), `server/README.md` |
| **Feature / page / background service** | `README.md` (feature table + data-flow list), `ARCHITECTURE.md` (module table), `server/README.md` or `client/README.md` |
| **CLI command / script** | `README.md` commands, `CLAUDE.md` / `AGENTS.md`, `INSTALL.md` / `SETUP.md` |
| **New language** | `docs/I18N.md`, `client/src/i18n/locales/<xx>/*`, `client/src/i18n/index.ts` (add to `supportedLngs` AND the `resources` map) |
@@ -42,13 +42,13 @@ Update docs **in the same change-set (PR/commit) as the code**, before claiming
## Procedure
1. **Classify** the change against the table above. A change can hit multiple rows (a new feature with a new env var hits both).
2. **Write the canonical English version first** — usually `README.md` and/or `ARCHITECTURE.md`. Get the wording right there; it anchors everything else.
6. **Area READMEs / docs/**: update `server/README.md`, `client/README.md`, and the relevant `docs/*.md` per the mapping.
7. **Diagrams**: when a state transition changes, edit every mermaid `stateDiagram-v2` block that models it (they are duplicated across README, server/README and docs/DATABASE). Keep transition labels consistent.
2. **Write the canonical version first** — usually `README.md` and/or `ARCHITECTURE.md`. Get the wording right there; it anchors everything else.
3. **Area READMEs / docs/**: update `server/README.md`, `client/README.md`, and the relevant `docs/*.md` per the mapping.
4. **Diagrams**: when a state transition changes, edit every mermaid `stateDiagram-v2` block that models it (they are duplicated across README, server/README and docs/DATABASE). Keep transition labels consistent.
## Verify (do not skip)
- **Coverage**: run `scripts/doc-coverage.sh <new-term> [...]` (e.g. the new env var / event type / identifier) and confirm every doc the mapping flags shows a HIT. The matrix is advisory — not every term belongs in every file — but a flagged doc reading `0` is a miss to fix.
- **Coverage**: grep the new term (env var / event type / identifier) across the docs the mapping flags — `grep -rn "<new-term>" README.md ARCHITECTURE.md server/README.md client/README.md docs/` — and confirm each flagged doc actually shows a hit. Advisory, not mechanical: not every term belongs in every file, but a flagged doc with zero hits is a miss to fix.
- **Tables**: markdown tables stay pipe-balanced (header column count == every row).
- **Mermaid**: each edited block still parses (valid `source --> target: label`).
- **i18n**: every new English string has a `vi` entry in `client/src/i18n/locales/vi/`.
@@ -58,5 +58,5 @@ Update docs **in the same change-set (PR/commit) as the code**, before claiming
## Tips
- The fastest way to find where something already lives: `grep -n "<existing-neighbor-term>" <doc>` (e.g. grep an adjacent env var to find the env table). `references/doc-map.md` lists the stable anchors per file.
- Parallelize translations + HTML across subagents when the change is large, but write the canonical English edit yourself first so the translations have a faithful source.
- Parallelize independent doc edits across subagents when the change is large, but write the canonical `README.md`/`ARCHITECTURE.md` edit yourself first so every other file has a faithful source.
- One language/area per subagent keeps edits reviewable and tables un-corrupted.
@@ -14,10 +14,7 @@ The source of truth most other docs mirror. Key sections:
### Translations
This build ships English only. `README-VN.md`, `README-CN.md` and `README-KO.md` were removed, as were the `zh` and `ko` UI locales — do not recreate them.
Standalone full translations of `README.md`. **Every** README change must be mirrored here at the corresponding section. Conventions:
- Keep in English/code: identifiers, env-var names, event-type names, `awaiting_input_since`, `pendingInterrupt`, "watchdog", `fs.watch`, model IDs, mermaid transition labels.
- Translate prose. "Waiting" → **Đang chờ** (vi) / **等待中** (zh) / **대기 중** (ko). "watchdog" often kept; in zh sometimes 看门狗.
This build ships English only. `README-VN.md`, `README-CN.md` and `README-KO.md` were removed, as were the `zh` and `ko` UI locales — do not recreate them, and do not mirror a README change into a translation file. (The UI itself still ships `en` and `vi` locales under `client/src/i18n/locales/` — those are strings, not docs, and are covered by the frontend section below.)
### `ARCHITECTURE.md`
- **Module responsibility table** — one row per source file (`scripts/import-history.js`, `lib/transcript-cache.js`, `routes/hooks.js`, `server/index.js`, …). Update the row whose file you changed. Grep the file path.