vibe · git:20261015.ca7368f · 2026-10-15 · sha256 8498b23c2d1994a0
vibe git:20261015.ca7368fA
Immutable. This exact content never changes and is served at /api/v1/blob/8498b23c2d1994a0.
---
name: vibe
description: Build one feature end to end under the vibe contract — one intake round, locked acceptance tests as the only checkpoint, a fresh subagent per phase, one review, landing.
---
# Vibe: one feature, intake to landing
Invoke with: `/superpowers-gstack:vibe <what to build>`
The user answers questions once, reads the acceptance tests once, and reviews the
finished work once. Everything between is yours to decide and log. The rules live in
the project's CLAUDE.md section **Vibe contract** (marker `gstack-vibe-v2`); this skill
is the procedure. If `.gstack/workflow` is not `vibe`, say so in one line of the intake
(the contract's standing approvals then hold for this invocation only) and suggest
`/superpowers-gstack:adapt` to choose the profile for good.
Begin every Bash call that needs the lock script with:
```bash
SKILL_DIR='<the base directory the Skill tool printed when this skill loaded>'
LOCK="$SKILL_DIR/../../scripts/lock-acceptance-tests.py"
[ -f "$LOCK" ] || LOCK=$(ls ~/.claude/plugins/cache/*/superpowers-gstack/*/scripts/lock-acceptance-tests.py 2>/dev/null | sort -V | tail -1)
[ -f "$LOCK" ] || { echo "BLOCKED — lock-acceptance-tests.py not found; run /plugin update superpowers-gstack"; exit 2; }
```
## Step 0: Read before asking
Load the project's context skill (`.claude/skills/*-context` or `*-kontekst`) if there
is one, then the code the feature touches. Classify the scope: files, tracks, whether
the result is visual (UI, render, video), and the risk tier
`scripts/classify-change.py` would give it. Steps 0–2 change no code (Brainstorm and Utforsk først write nothing either). Do not enter plan
mode yourself: leaving it asks the user a second time, and the acceptance tests are the
one checkpoint.
## Step 0b: Choose how to start
Ask one `AskUserQuestion` before any intake, recommended way first, so the user picks
how much of the idea is still open. The names below are what the user sees:
- **Brainstorm** — the idea is vague. Run `superpowers:brainstorming` in its short form:
one question at a time, two or three approaches with a recommendation, no spec and no
HARD-GATE wait (the contract overrides it). Its result becomes the reference and a draft
of the acceptance criteria.
- **Hurtig** — the idea is clear. Go straight to Step 1 as written. This is the default
when the user gives no other signal.
- **Fra ferdig spec/plan** — a spec, plan or office-hours document already exists. Ask for
the path, read it, draw 5–10 acceptance criteria and the out-of-scope list from it, and
reuse the file as `SPEC.md` in Step 2 instead of writing a new one.
- **Utforsk først** — read-only. Read the code, propose two or three possible features or
moves with scope and the tier `scripts/classify-change.py` would give each, and let the
user pick one. The pick is then handled like Brainstorm's result.
Every way ends in Step 1: the reference and acceptance criteria, and what is out of scope,
are always confirmed there, and from Step 2 on nothing differs. The questions Step 1 asks
that the chosen way already answered are skipped, not asked again.
## Step 1: Intake — one round
Ask everything in one `AskUserQuestion` round: at most eight questions, four per call,
recommended option first and marked `(Recommended)`. Always ask for:
- the reference ("fasit") and the 5–10 acceptance criteria you drew from the request,
so the user can correct them;
- what is out of scope.
Ask nothing you can find in the code, the context skill or CLAUDE.md. After this round,
design, spec and plan are pre-approved.
## Step 2: SPEC.md and PLAN.md
Write `docs/superpowers/vibe/<YYYY-MM-DD>-<feature>/SPEC.md` (goal, non-goals,
acceptance criteria) and `PLAN.md` (small tasks; each has one test and one
"done when" line; no code). Commit both. Do not wait for a spec or plan review.
**A pending `## Project` in CLAUDE.md** (`<!-- gstack-project-pending -->` on the
heading, left by `/superpowers-gstack:adapt` in an empty folder) is filled in now, once,
from what the intake settled — no new question. Write `.gstack/adapt-project.md`:
`## Project` with `### Tech Stack / Testing / QA URL / Deployment` (omit what does not
apply) and `### Routing for this stack` (`/qa <url>` for a browser UI, `/cso` before
`/review` when the acceptance criteria touch auth, user data, payments or external
APIs, the Apple skills on a native track). Pick the sensitivity the way adapt does
(`very high` for real-time audio or lock-free concurrency, `high` for migrations, data
transforms or security signals, `medium` for UI work, `low` for CLI tools and
libraries). For a native platform write `.gstack/track` (`ios` | `macos` | `both`)
first and resolve `IOS_SIMULATOR` and `DEVELOPMENT_TEAM` per adapt's
`blocks/PLACEHOLDERS.md`. Then:
```bash
SKILL_DIR='<the base directory the Skill tool printed when this skill loaded>'
ADAPT="$SKILL_DIR/../../scripts/adapt-claude-md.py"
[ -f "$ADAPT" ] || ADAPT=$(ls ~/.claude/plugins/cache/*/superpowers-gstack/*/scripts/adapt-claude-md.py 2>/dev/null | sort -V | tail -1)
python3 "$ADAPT" --project-section .gstack/adapt-project.md --set 'DOMAIN_SENSITIVITY=<level>' \
[--set 'IOS_SIMULATOR=…' --set 'DEVELOPMENT_TEAM=…']
```
The script replaces the pending section once and drops the marker. Exit 2 is a refusal
with the reason on stderr: fix the input it names and run it again (an unresolved
native placeholder, a second H2 in the section file, an unclosed code fence, an
invalid pin). Only `no \`## Project\` section carries` means the section is already
the project's own: leave it and say so. Relay the report's Removed list if it has one
(lines someone wrote under the pending heading; the snapshot keeps them). Delete
`.gstack/adapt-project.md`, commit CLAUDE.md with the spec, and write one line in the log: `Filled in ## Project: <stack>, tests via
<command>, sensitivity <level>.`
## Step 3: Acceptance tests — the one checkpoint
Write the acceptance tests from the criteria, in a directory of their own (for example
`Tests/Acceptance/` or `tests/acceptance/`). For visual work the test is a truth check
against the reference — a screenshot or render measured against it — not only unit
tests. Then send ONE message: a short overview that lists the exact files (test name, what it
checks — the user approves an overview, but `lock` commits what is on disk), and this
line for the user to paste:
```
/goal All tasks in PLAN.md are done: tests green, build without warnings, STATUS.md updated. Or stop after 60 turns.
```
The user approves in one of two ways: they say ok, or they paste the `/goal` line;
whether they say ok or paste the `/goal` line, run the lock first and only then start
Step 4 (a `/goal` the user pastes is started by them; lock before you act on it):
```bash
python3 "$LOCK" lock --feature <feature> --path '<acceptance-test glob>'
```
From here on, never edit a locked test to turn red into green, by any tool. If a test
is wrong, stop and say which one and why; only the user unlocks
(`python3 "$LOCK" unlock --feature <feature>`). Send the lock commit SHA the script
printed in your next message, so the user can check what was locked.
## Step 4: One fresh subagent per phase
Run the phases of PLAN.md with `superpowers:subagent-driven-development`: each phase's
part of the plan is one subagent's brief; the main thread orchestrates and stays under
about 150k tokens of context. Two fixed rules go into every brief:
- **wire what you build into the app in the same round** the tests turn green — green
tests on code nothing calls are not done;
- **find every place the app already does the same job** and make it follow the new
rules.
At every phase boundary update `STATUS.md` (done, remaining, open Rulings). Add one line
per round to `ROUNDS.md`: what was tried, which tests still failed. Never ask "what
next" between phases.
**Stop only for:** irreversible or destructive actions, security-sensitive actions,
side effects outside the worktree, a force-push or a push to the default branch outside
the `Landing mode:` line, money, a licence, or a real blocker. Pushing the feature branch
for backup is pre-approved. Decide everything else and log it in STATUS.md as
`Ruling: <choice> — <why> — <cost if wrong>`.
## Step 5: Tests while working
A subagent runs only the tests that cover what it changed (the affected target or a
`--filter`). The full suite runs at each phase boundary and once before landing.
After a timeout: at most two reruns, then one single run with its log.
## Step 6: One review, at the end
Invoke `/superpowers-gstack:pitfall-verification` once, after the last phase, on the
whole branch; its tier is computed as always. Fix critical and important findings; do
not re-review minor ones. No plan reviews, no `/autoplan`.
## Step 7: Lessons, committed before landing
Read `ROUNDS.md`: a mistake that came back in two phases or more becomes one working
rule — at most three per feature — in the **How we work** section of the context skill,
never into CLAUDE.md. Commit the change now, on the feature branch: lessons written
after landing never reach the default branch and vanish with the worktree. Touch neither
the locked tests nor the contract in this step. If the project has no context skill,
create `.claude/skills/<project>-context/SKILL.md` with a `## How we work` section
holding the rules, and commit it with the feature; never put them in CLAUDE.md.
## Step 8: The lock must hold
```bash
python3 "$LOCK" verify --feature <feature>
```
Exit 0 is required before landing.
**Re-lock cases first.** After a rebase it warns that the lock commit left the
branch's history (a warning, not exit 1); in `pr` landing mode, a squash-merge commit on
main that changed the receipt makes `verify` exit 1 (`receipt changed by commit …`).
Both mean the lock must be redone by the user, and re-locking after a rebase or a
squash-merge receipt change is not editing a test. The squash-merge case applies only
when the exit-1 output names no file other than the receipt. A changed test file is never
a re-lock case: it goes to the next paragraph. Tell the user and ask them to re-lock.
**Any other exit 1** names each changed file (the receipt `.gstack/acceptance-lock.json`,
a new file under a locked path and a hidden assume-unchanged flag included): restore it
from the lock commit, or stop and tell the user which test is wrong. The lock defends
against mistakes and shortcuts, not against deliberate history rewriting; `verify` is a
gate, not proof. It compares the locked files with the lock commit in the working tree,
the index and HEAD, and checks the receipt and new files under the locked paths. It
cannot see a `conftest.py` or pytest configuration outside those paths that changes what
the tests do, a faked or amended commit subject on the receipt, or a rewritten history.
Only `__pycache__`, `.pytest_cache` and `.DS_Store` are exempt from the new-file
check.
## Step 9: Land
Land by the project's `Landing mode:` line — `solo` → `/superpowers-gstack:land`,
`pr` → `/ship` — with no options menu. Ask once about the push only when the project
requires it. The lock stays after landing as the record: the landed tests remain
protected, and only the user unlocks them.
## Step 10: Final report
One message: what was built, how the user verifies it, every Ruling, deferred findings.