@skitterbyte/skitterspec 16.10.0 → 17.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +36 -0
- package/README.md +3 -3
- package/assets/claude-md-section.md +13 -51
- package/assets/core/env.config.json.example +4 -1
- package/assets/core/env.config.md +26 -6
- package/assets/rules/spec-planning.md +28 -9
- package/assets/skills/spec/SKILL.md +13 -8
- package/assets/skills/spec-bug/SKILL.md +9 -7
- package/assets/skills/spec-cancel/SKILL.md +12 -0
- package/assets/skills/spec-complete/SKILL.md +26 -5
- package/assets/skills/spec-hotfix/SKILL.md +8 -6
- package/assets/skills/spec-init/SKILL.md +16 -6
- package/assets/skills/spec-next/SKILL.md +98 -0
- package/assets/skills/spec-review/SKILL.md +5 -5
- package/assets/skills/spec-start/SKILL.md +146 -0
- package/assets/skills/spec-to-main/SKILL.md +7 -5
- package/package.json +1 -1
- package/src/cli.js +198 -14
- package/src/env/config.js +24 -1
- package/src/env/integrate.js +61 -1
- package/src/env/live.js +27 -3
- package/src/env/provision.js +58 -1
- package/src/env/teardown.js +41 -3
- package/src/init.js +21 -12
- package/src/prompts.js +31 -3
- package/assets/skills/spec-go/SKILL.md +0 -190
package/MIGRATION.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# Migration guide
|
|
2
2
|
|
|
3
|
+
## `@skitterbyte/skitterspec` v16 → v17 (`/spec-go` splits in two)
|
|
4
|
+
|
|
5
|
+
### Breaking change
|
|
6
|
+
|
|
7
|
+
**`/spec-go` is removed.** It did two jobs — set an environment up, and build a
|
|
8
|
+
phase — and the seam between them is where the worktree hand-off hurt: you ran
|
|
9
|
+
the same command twice, once to provision and once, from another session, to
|
|
10
|
+
build. They are now two commands with one job each:
|
|
11
|
+
|
|
12
|
+
| Removed | Use instead |
|
|
13
|
+
|---------|-------------|
|
|
14
|
+
| `/spec-go <name>` (first run — start a spec) | **`/spec-start <name>`** — puts the spec in flight on this checkout, moves it to `in-progress`, then builds phase 1. |
|
|
15
|
+
| `/spec-go` (later runs — build the next phase) | **`/spec-next`** — builds the next phase of whichever spec is in flight. Re-run it per phase. |
|
|
16
|
+
| `/spec-go --here` | **Nothing — `/spec-start` *is* here.** It puts the branch in the checkout you are in, which is what the flag was reaching for. |
|
|
17
|
+
|
|
18
|
+
**One checkout holds one spec in flight.** `/spec-start` refuses while another
|
|
19
|
+
spec holds your checkout, naming it and the three ways to free the workbench
|
|
20
|
+
(`/spec-complete`, `/spec-cancel`, or `/spec-live main` to park it). It will not
|
|
21
|
+
stash, commit or switch on your behalf — moving unfinished work is a decision,
|
|
22
|
+
not a side effect.
|
|
23
|
+
|
|
24
|
+
**`/spec-next` refuses when nothing is in flight** rather than guessing a spec
|
|
25
|
+
from the conversation. It writes real code; a wrong guess produces commits on a
|
|
26
|
+
branch nobody asked for.
|
|
27
|
+
|
|
28
|
+
### What to do
|
|
29
|
+
|
|
30
|
+
1. **Upgrade** — `npx @skitterbyte/skitterspec update` removes the retired
|
|
31
|
+
`/spec-go` skill and installs the two replacements. A `/spec-go` you edited
|
|
32
|
+
yourself is kept with a warning rather than deleted; remove it by hand.
|
|
33
|
+
2. **Retrain the muscle memory** — `/spec-start <name>` to begin, `/spec-next` to
|
|
34
|
+
carry on, unchanged `/spec-complete` to finish.
|
|
35
|
+
3. **Providers**: the `spec-go-start` seam is now **`spec-next-start`**. A
|
|
36
|
+
provider distribution must rename its fragment file to match, or the build
|
|
37
|
+
fails on an orphaned seam.
|
|
38
|
+
|
|
3
39
|
## `@skitterbyte/skitterspec-linear` v9 → v10 (`push` validates your issue states)
|
|
4
40
|
|
|
5
41
|
**`spec-sync push` now refuses to run until the configured `states` names have
|
package/README.md
CHANGED
|
@@ -4,11 +4,11 @@ Spec-driven development for [Claude Code](https://claude.com/claude-code) — a
|
|
|
4
4
|
**tracker-free** filesystem workflow. The everyday loop is five verbs:
|
|
5
5
|
|
|
6
6
|
```
|
|
7
|
-
/spec → /spec-
|
|
7
|
+
/spec → /spec-start → /spec-next → /commit → /spec-complete
|
|
8
8
|
plan build it test it live save it finish + land
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Ships the spec-lifecycle skills (`/spec`, `/spec-
|
|
11
|
+
Ships the spec-lifecycle skills (`/spec`, `/spec-start`, `/spec-next`, `/spec-complete`,
|
|
12
12
|
`/spec-cancel`, `/spec-bug`, `/spec-hotfix`, `/spec-review`, `/spec-init`) plus
|
|
13
13
|
per-spec **isolation** — a git worktree per in-progress spec, Docker on demand,
|
|
14
14
|
host dev servers on reserved ports, and `/spec-connect` to test a worktree at your
|
|
@@ -56,7 +56,7 @@ Install exactly one — the superset is a strict superset of this package.
|
|
|
56
56
|
|
|
57
57
|
When your app runs from `main` on `localhost`, a worktree's changes are
|
|
58
58
|
unreachable. Add a `dev` block to `specs/.core/env.config.json` listing your host
|
|
59
|
-
dev servers (each `{ name, command, portVar, health?, frontPort? }`); `/spec-
|
|
59
|
+
dev servers (each `{ name, command, portVar, health?, frontPort? }`); `/spec-start`
|
|
60
60
|
starts them on the spec's reserved ports, and **`/spec-connect <name>`** points
|
|
61
61
|
your canonical `localhost` ports at that spec (via a small bundled reverse proxy —
|
|
62
62
|
no external install), so you test at the exact URL you always use.
|
|
@@ -1,53 +1,15 @@
|
|
|
1
1
|
## Spec workflow
|
|
2
2
|
|
|
3
|
-
Spec-driven development runs through the lifecycle **skills**
|
|
4
|
-
structure and lifecycle stay consistent
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
| `/spec-hotfix` | (Hotfix) Fork a worktree from a release tag, red→green, land by tag | `In Progress` | `specs/in-progress/` |
|
|
17
|
-
| `/spec-to-main` | Land the branch on the base mid-spec, without finishing | (unchanged) | (unchanged) |
|
|
18
|
-
| `/spec-init` | Bootstrap/repair this workflow in a project (idempotent) | — | — |
|
|
19
|
-
|
|
20
|
-
**Skills vs commands.** The table is skills — Claude reads them and exercises
|
|
21
|
-
judgment. `/spec-connect` and `/spec-live` are **slash commands** instead: each
|
|
22
|
-
pre-executes one `spec-env` verb and relays it, so only you can run them. A skill
|
|
23
|
-
that wants one will tell you to type it.
|
|
24
|
-
|
|
25
|
-
Every spec has a **type** (`> **Type:** Feature\|Bug`) and a filename prefix
|
|
26
|
-
(`feat-<name>` / `bug-<name>`) — never `[BUG]` brackets (glob hazard). Specs use
|
|
27
|
-
markdown checkboxes (`- [ ]`) for task tracking and are the single source of
|
|
28
|
-
truth for progress. Every spec is a folder: `00-overview.md` is the dashboard
|
|
29
|
-
(problem, decisions, solution, **phase index**, logs) and **each phase is its own
|
|
30
|
-
file** (`01-<slug>.md`, `02-…`) holding that phase's tasks — never a bare file,
|
|
31
|
-
never phases lumped into the overview. **Every phase ends with creating and
|
|
32
|
-
running tests**; decisions go in the spec's Changelog, state transitions in its
|
|
33
|
-
State log.
|
|
34
|
-
|
|
35
|
-
> Tailor the per-phase test commands and project conventions referenced by the
|
|
36
|
-
> spec skills to this project's stack (see `.claude/rules/spec-planning.md`).
|
|
37
|
-
|
|
38
|
-
**Per-spec isolation (adopt once, then default):** with isolation adopted
|
|
39
|
-
(`skitterspec init --isolation`, or `specs/.core/env.config.json` present),
|
|
40
|
-
**`/spec-go`** gives every in-progress spec its own git worktree automatically —
|
|
41
|
-
parallel specs, no stashing, `main` left free — and brings up the project's host
|
|
42
|
-
**dev servers** (`env.config` → `dev`) on the spec's ports. The **`/spec-connect <name>`** command then exposes that spec on your canonical
|
|
43
|
-
`localhost` ports so you can test it at the normal URL (`/spec-connect main`
|
|
44
|
-
hands them back); for a code-only spec, **`/spec-live <name>`** reuses the dev
|
|
45
|
-
server you already have running instead. Docker is a
|
|
46
|
-
**per-spec escalation**: `/spec` sets `> **Stack:** worktree` (default) or
|
|
47
|
-
`worktree + docker` when the spec touches the DB / stateful services, and only
|
|
48
|
-
the latter gets a namespaced stack. Teardown is folded into **`/spec-complete`** ·
|
|
49
|
-
**`/spec-cancel`**; beneath the skills, `skitterspec spec-env` is the CLI engine — `up`, `down`,
|
|
50
|
-
`prune`, `dev`, `connect`, `integrate`, `hotfix`, `live`, `status` and `resolve`.
|
|
51
|
-
Most are planners the skills run; omit the spec name and it uses the worktree you
|
|
52
|
-
are standing in. Independent of lifecycle
|
|
53
|
-
status; inactive when `env.config.json` is absent.
|
|
3
|
+
Spec-driven development runs through the lifecycle **skills** — use them so
|
|
4
|
+
structure and lifecycle stay consistent. The everyday loop is
|
|
5
|
+
**`spec → start → next → commit → complete`**, with `/spec-connect` when you want to test
|
|
6
|
+
the spec in a browser.
|
|
7
|
+
|
|
8
|
+
**Skills vs commands.** The lifecycle skills are read by Claude, which exercises
|
|
9
|
+
judgment. `/spec-connect` and `/spec-live` are **slash commands** instead — each
|
|
10
|
+
pre-executes one `spec-env` verb and relays it, so only you can run them; a
|
|
11
|
+
skill that wants one will tell you to type it.
|
|
12
|
+
|
|
13
|
+
The skill table, the spec type/folder conventions and the per-spec isolation
|
|
14
|
+
model all live in **`.claude/rules/spec-planning.md`**, the canonical reference
|
|
15
|
+
every spec skill points at. Tailor its per-phase test commands to this stack.
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Opt-in config for per-spec isolation (git worktree + optional namespaced Docker
|
|
4
4
|
stack + host dev servers + a front-door proxy + an optional opener per
|
|
5
|
-
in-progress spec). Provisioning is folded into `/spec-
|
|
5
|
+
in-progress spec). Provisioning is folded into `/spec-start`, teardown into
|
|
6
6
|
`/spec-complete` · `/spec-cancel`, and traffic diversion is `/spec-connect`; the
|
|
7
7
|
`skitterspec spec-env <up|down|prune|dev|connect|integrate>` CLI is the engine
|
|
8
8
|
beneath them.
|
|
9
9
|
|
|
10
|
-
**Once this file is present, isolation is the default policy:** `/spec-
|
|
10
|
+
**Once this file is present, isolation is the default policy:** `/spec-start` gives
|
|
11
11
|
**every** in-progress spec its own git worktree automatically. Docker is a **per-
|
|
12
12
|
spec escalation** — a spec brings up a stack only when its `> **Stack:**` header
|
|
13
13
|
is `worktree + docker` (set at `/spec` when it touches the DB / stateful
|
|
@@ -28,6 +28,22 @@ no live `env.config.json` was found.
|
|
|
28
28
|
```jsonc
|
|
29
29
|
{
|
|
30
30
|
// Where sibling worktrees are created and how their dirs are named.
|
|
31
|
+
// Where a spec's branch gets built.
|
|
32
|
+
//
|
|
33
|
+
// "worktree" (default) — every spec gets its own git worktree. Several
|
|
34
|
+
// specs run side by side and `main` stays free, at the cost of
|
|
35
|
+
// one terminal session per spec (`/spec-start` sets it up for you).
|
|
36
|
+
// "checkout" — the branch is built in the primary checkout instead. One
|
|
37
|
+
// spec at a time, but no second session and no hand-off: the
|
|
38
|
+
// terminal you are already in follows the work.
|
|
39
|
+
//
|
|
40
|
+
// Pick it for how you work, not for what this repo contains — a project with
|
|
41
|
+
// no dev servers may still want several specs in flight. An unrecognised
|
|
42
|
+
// value falls back to "worktree" rather than erroring.
|
|
43
|
+
//
|
|
44
|
+
// Not to be confused with `seedFiles.mode`, which is "symlink" | "copy".
|
|
45
|
+
"mode": "worktree",
|
|
46
|
+
|
|
31
47
|
"worktree": {
|
|
32
48
|
"root": "../{repo}-wt", // dir that holds all spec worktrees; sibling of
|
|
33
49
|
// the primary checkout, never nested inside it.
|
|
@@ -108,9 +124,13 @@ no live `env.config.json` was found.
|
|
|
108
124
|
"host": "127.0.0.1" // bind host for the canonical ports
|
|
109
125
|
},
|
|
110
126
|
|
|
111
|
-
// Optional, editor/terminal-agnostic opener
|
|
112
|
-
//
|
|
113
|
-
//
|
|
127
|
+
// Optional, editor/terminal-agnostic opener. `/spec-start` RUNS it when it hands
|
|
128
|
+
// you into a new worktree — after provisioning and bootstrap, so the session
|
|
129
|
+
// opens onto a tree that is ready to work in. The template is expanded with
|
|
130
|
+
// {worktreePath}, {slug}, {branch}, {projectName}, {portOffset}.
|
|
131
|
+
// Empty = nothing is opened (the path is just printed), which is how you turn
|
|
132
|
+
// the auto-open off. A non-interactive run skips it either way — an opened
|
|
133
|
+
// window nobody is sitting at helps no one.
|
|
114
134
|
// Examples: "code {worktreePath}", "tmux new-window -c {worktreePath}",
|
|
115
135
|
// or a "warp://..." deeplink for Warp users.
|
|
116
136
|
"open": {
|
|
@@ -148,7 +168,7 @@ no live `env.config.json` was found.
|
|
|
148
168
|
"refuseTeardownIfUnpushed": true
|
|
149
169
|
},
|
|
150
170
|
|
|
151
|
-
// What teardown cleans up beyond this machine. `/spec-
|
|
171
|
+
// What teardown cleans up beyond this machine. `/spec-start` pushes the spec
|
|
152
172
|
// branch when it provisions, so without this a completed spec leaves a merged
|
|
153
173
|
// branch on the remote forever. `deleteRemoteBranch`:
|
|
154
174
|
// "prompt" (default) — plan `git push <remote> --delete <branch>` in its own
|
|
@@ -11,7 +11,8 @@ and lifecycle stay consistent. Each sets a status on the spec header
|
|
|
11
11
|
| `/spec-bug` | (Bug) Reproduce with a failing test, capture spec, drive red→green | `In Progress` | `specs/in-progress/` |
|
|
12
12
|
| `/spec-hotfix` | (Hotfix) Fork a worktree from a release tag, red→green, land by tag + cherry-pick | `In Progress` | `specs/in-progress/` |
|
|
13
13
|
| `/spec-review` | Re-validate a spec against the codebase; refresh stale parts | `—` | (unchanged) |
|
|
14
|
-
| `/spec-
|
|
14
|
+
| `/spec-start` | Put a spec in flight on this checkout, then build phase 1 | `In Progress` | `specs/in-progress/` |
|
|
15
|
+
| `/spec-next` | Build the next phase of the spec in flight (re-run per phase) | `In Progress` (unchanged) | (unchanged) |
|
|
15
16
|
| `/spec-to-main` | Land the branch on the base (rebase + ff) **without** finishing — for running the work in CI / a shared env mid-spec; repeatable | `In Progress` (unchanged) | (unchanged) |
|
|
16
17
|
| `/spec-complete` | Verify all phases done + tests green; land + tear down | `Complete` | `specs/complete/` |
|
|
17
18
|
| `/spec-cancel` | Record progress, stamp a reason on the header; tear down | `Cancelled` | `specs/cancelled/` |
|
|
@@ -29,7 +30,7 @@ it.
|
|
|
29
30
|
real judgment (green tests before a land; an MCP fetch and a team-key check; ten
|
|
30
31
|
subcommands) — but they are marked user-only too, since nobody reaches them
|
|
31
32
|
except by typing them. Everything else in the table above stays model-invocable,
|
|
32
|
-
which is what lets `/spec-
|
|
33
|
+
which is what lets `/spec-next` hand off to `/spec-push` as work progresses.
|
|
33
34
|
|
|
34
35
|
Status flow: `Ready → In Progress → Complete` (or `Cancelled` from any state).
|
|
35
36
|
`/spec` grills to a **Ready** spec directly — there is no separate grooming
|
|
@@ -41,14 +42,25 @@ mid-spec (so the work can run in CI / a shared test env) while the spec stays
|
|
|
41
42
|
`In Progress` in `specs/in-progress/`; it's the intermediate, repeatable half of
|
|
42
43
|
`/spec-complete`'s landing, without the finalise-and-tear-down.
|
|
43
44
|
|
|
45
|
+
**Two workspace modes.** `specs/.core/env.config.json` → `mode` decides where a
|
|
46
|
+
spec's branch is built. **`worktree`** (the default) gives each spec its own
|
|
47
|
+
checkout — several specs at once and `main` left free, at the cost of one
|
|
48
|
+
terminal session per spec, which `/spec-start` sets up for you. **`checkout`** builds
|
|
49
|
+
the branch in the primary checkout instead: one spec at a time, but no second
|
|
50
|
+
session and no hand-off, so the terminal you are already in follows the work.
|
|
51
|
+
Pick it for how you work rather than for what the project contains — a repo with
|
|
52
|
+
no dev servers may still want several specs in flight. In `checkout` mode
|
|
53
|
+
`/spec-connect` and `/spec-live` do not apply and say so: both exist to reach
|
|
54
|
+
work that lives elsewhere, which is the gap that mode removes.
|
|
55
|
+
|
|
44
56
|
**Per-spec isolation (opt-in to adopt, then the default policy).** When a project
|
|
45
57
|
adopts isolation (`skitterspec init --isolation`, or `specs/.core/env.config.json`
|
|
46
|
-
present), `/spec-
|
|
58
|
+
present), `/spec-start` gives **every** in-progress spec its own git worktree
|
|
47
59
|
automatically — several specs run side by side without stashing or clashing, and
|
|
48
60
|
`main` stays free. Docker is a **per-spec escalation**: `/spec` records
|
|
49
61
|
`> **Stack:** worktree` (default) or `worktree + docker` when the spec touches the
|
|
50
|
-
DB / stateful services, and `/spec-
|
|
51
|
-
latter. `/spec-
|
|
62
|
+
DB / stateful services, and `/spec-start` brings up a namespaced stack only for the
|
|
63
|
+
latter. `/spec-start` also starts the project's host **dev servers** (`env.config`
|
|
52
64
|
→ `dev`) on the spec's ports; **`/spec-connect <name>`** then exposes that spec on
|
|
53
65
|
your canonical `localhost` ports so you can test it at the normal URL
|
|
54
66
|
(`/spec-connect main` hands them back). All housekeeping (the backlog→in-progress
|
|
@@ -83,6 +95,13 @@ Beneath it, `skitterspec spec-env live <take|release|abort|status>` is the engin
|
|
|
83
95
|
tracker-free: it knows nothing about any specific ticketing system. A
|
|
84
96
|
ticketing provider is installed as its own distribution that plugs into named
|
|
85
97
|
**seams** in the shared skills and fulfils a skill-name + CLI contract.
|
|
98
|
+
|
|
99
|
+
Part of that contract is the **binary name**: the shipped `/spec-connect` and
|
|
100
|
+
`/spec-live` commands invoke `skitterspec`, so a superset that replaces the base
|
|
101
|
+
must expose that name too, alongside whatever it calls itself — one entry point
|
|
102
|
+
under two names. A distribution shipping only its own name leaves those commands
|
|
103
|
+
failing with `command not found`, which reads as a broken install rather than a
|
|
104
|
+
missing alias.
|
|
86
105
|
Sync is **one-way**: the repo is the source of truth and the tracker is a
|
|
87
106
|
**generated mirror**. It ships `/spec-push` (repo→tracker; computes a create/update plan
|
|
88
107
|
against a committed last-pushed snapshot and applies it) and `/spec-status`
|
|
@@ -92,7 +111,7 @@ the tracker is never read back or merged.
|
|
|
92
111
|
|
|
93
112
|
**Every skill that moves a spec through the lifecycle carries a seam**, so the
|
|
94
113
|
mirror keeps up without anyone remembering to push: `/spec`, `/spec-bug` and
|
|
95
|
-
`/spec-hotfix` link the spec they create; `/spec-
|
|
114
|
+
`/spec-hotfix` link the spec they create; `/spec-next` refreshes it as work starts;
|
|
96
115
|
`/spec-complete`, `/spec-cancel` and `/spec-review` refresh it after they change
|
|
97
116
|
it. `/spec-to-main` and `/spec-live` carry none — they change no status.
|
|
98
117
|
With no provider installed the seams are empty and every skill behaves as a plain
|
|
@@ -135,11 +154,11 @@ status.
|
|
|
135
154
|
Every spec header carries:
|
|
136
155
|
|
|
137
156
|
- `> **Name:**` — the spec's folder name (`feat-`/`bug-`/`hotfix-<kebab-name>`).
|
|
138
|
-
It's the handle you pass to `/spec-
|
|
157
|
+
It's the handle you pass to `/spec-start` and the other lifecycle skills, surfaced
|
|
139
158
|
in the header so it's copy-pasteable without digging for the folder name.
|
|
140
159
|
- `> **Author:**` — who created the spec (set at `/spec` / `/spec-bug`, defaults
|
|
141
160
|
to `git config user.name`).
|
|
142
|
-
- `> **Developer:**` — who implements it (`—` until `/spec-
|
|
161
|
+
- `> **Developer:**` — who implements it (`—` until `/spec-start` starts work, then
|
|
143
162
|
set to `git config user.name`; `/spec-bug` sets it immediately).
|
|
144
163
|
|
|
145
164
|
Every spec also has a **State log** table — the audit trail of folder/status
|
|
@@ -175,7 +194,7 @@ When asked for a plan, implementation strategy, or feature breakdown:
|
|
|
175
194
|
|
|
176
195
|
```
|
|
177
196
|
specs/backlog/ Ready (or Draft) specs (/spec)
|
|
178
|
-
specs/in-progress/ under active implementation (/spec-
|
|
197
|
+
specs/in-progress/ under active implementation (/spec-start, /spec-bug)
|
|
179
198
|
specs/complete/ finished (/spec-complete)
|
|
180
199
|
specs/cancelled/ abandoned, with a reason on the header (/spec-cancel)
|
|
181
200
|
specs/.core/ project rules — ALWAYS APPLY, never moved
|
|
@@ -6,10 +6,10 @@ description: Create a new spec-driven-development spec. Grills the user to a cle
|
|
|
6
6
|
# /spec — author a new spec
|
|
7
7
|
|
|
8
8
|
Produce ONE concise spec in `specs/backlog/`. Do not start coding — this skill
|
|
9
|
-
plans only. Implementation happens later via `/spec-
|
|
9
|
+
plans only. Implementation happens later via `/spec-start`.
|
|
10
10
|
|
|
11
11
|
Lifecycle (the governing skills) — status in parentheses:
|
|
12
|
-
`/spec` (writes **Ready** when fully groomed, else Draft; backlog) → `/spec-
|
|
12
|
+
`/spec` (writes **Ready** when fully groomed, else Draft; backlog) → `/spec-start`
|
|
13
13
|
(In Progress, in-progress; implement phase 1) → `/spec-complete` (Complete) /
|
|
14
14
|
`/spec-cancel` (Cancelled). See `.claude/rules/spec-planning.md`. (There is no
|
|
15
15
|
separate grooming command — `/spec` grills to a Ready spec directly.)
|
|
@@ -23,7 +23,12 @@ not write the spec until this is resolved.
|
|
|
23
23
|
|
|
24
24
|
- Break the problem into **distinctive areas** and work them in logical order,
|
|
25
25
|
resolving dependencies between decisions one at a time.
|
|
26
|
-
-
|
|
26
|
+
- **Batch independent questions; sequence dependent ones.** When several
|
|
27
|
+
questions do not affect each other's answers, put them to the user together
|
|
28
|
+
(up to four at once — use the harness's multi-question ask tool where it has
|
|
29
|
+
one) rather than spending a round trip on each. When an answer would change
|
|
30
|
+
what you ask next, ask that one alone and wait for it. Give your
|
|
31
|
+
**recommended answer** either way.
|
|
27
32
|
- If a question can be answered by **reading the codebase, read it** instead of
|
|
28
33
|
asking. Verify endpoints/models/files actually exist before relying on them.
|
|
29
34
|
- Cover, at minimum, the areas that apply:
|
|
@@ -42,7 +47,7 @@ not write the spec until this is resolved.
|
|
|
42
47
|
this spec touch the DB / stateful services (so its worktree needs a Docker
|
|
43
48
|
stack), or is a plain worktree enough? Default `worktree`; escalate to
|
|
44
49
|
`worktree + docker` only when it must. This sets the `> **Stack:**` header
|
|
45
|
-
that `/spec-
|
|
50
|
+
that `/spec-start` acts on (it can be escalated later). Skip when isolation
|
|
46
51
|
isn't enabled — leave the default `worktree`.
|
|
47
52
|
10. **Open questions** — anything still undecided.
|
|
48
53
|
|
|
@@ -95,7 +100,7 @@ the codebase, link rather than duplicate):
|
|
|
95
100
|
# <Feature title>
|
|
96
101
|
|
|
97
102
|
> **Type:** Feature
|
|
98
|
-
> **Name:** feat-<kebab-name> (the spec folder name — the handle you paste into `/spec-
|
|
103
|
+
> **Name:** feat-<kebab-name> (the spec folder name — the handle you paste into `/spec-start`)
|
|
99
104
|
> **Status:** Ready — not started
|
|
100
105
|
> **Author:** <git user.name — `git config user.name`>
|
|
101
106
|
> **Developer:** —
|
|
@@ -191,7 +196,7 @@ Keep the `00-overview.md` phase index and the phase files in sync: the index row
|
|
|
191
196
|
is the one-line summary + status; the phase file is the detail.
|
|
192
197
|
|
|
193
198
|
The **State log** is the audit trail of folder/status transitions — every
|
|
194
|
-
lifecycle skill (`/spec-
|
|
199
|
+
lifecycle skill (`/spec-start`, `/spec-complete`, `/spec-cancel`) appends one row
|
|
195
200
|
when it moves the spec. The **Changelog** is for decisions and course-corrections
|
|
196
201
|
only — keep the two separate.
|
|
197
202
|
|
|
@@ -223,14 +228,14 @@ Rules for the spec body:
|
|
|
223
228
|
After writing, tell the user the path and that it's **`Ready`** in `backlog`
|
|
224
229
|
(grilling in Phase A resolved the open questions). If you deliberately left open
|
|
225
230
|
questions unresolved, write `Draft` instead and say what still needs deciding.
|
|
226
|
-
Either way, the next step is `/spec-
|
|
231
|
+
Either way, the next step is `/spec-start` to start building.
|
|
227
232
|
|
|
228
233
|
## Phase D — record the isolation stack (only if configured)
|
|
229
234
|
|
|
230
235
|
**Only when `specs/.core/env.config.json` exists** (per-spec isolation is
|
|
231
236
|
enabled), make sure the `> **Stack:**` header reflects the Phase A item 9
|
|
232
237
|
decision — `worktree` (default) or `worktree + docker` when it touches the DB /
|
|
233
|
-
stateful services. Nothing to provision now: `/spec-
|
|
238
|
+
stateful services. Nothing to provision now: `/spec-start` gives every in-progress
|
|
234
239
|
spec its own worktree automatically, and brings up Docker only when the Stack
|
|
235
240
|
says so. Mention the operator can escalate the Stack later (edit the header, or
|
|
236
241
|
run `skitterspec spec-env up <name>` to add Docker to an existing worktree). If
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spec-bug
|
|
3
|
-
description: Investigate a bug, capture it as a Bug-type spec, and drive it red→green.
|
|
3
|
+
description: Investigate a bug, capture it as a Bug-type spec, and drive it red→green. ALWAYS starts by reproducing the bug with a failing test, then writes the spec and works the test to green — on the bug's own branch, never on main. Use when the user reports a bug, says "/spec-bug", "investigate this bug", "this is broken — find and fix it", or pastes an error/stack trace.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /spec-bug — investigate a bug, prove it with a failing test, fix it
|
|
@@ -37,7 +37,7 @@ place), skip this whole section and fix on the current branch — same as when
|
|
|
37
37
|
isolation is off. Warn that the fix will land wherever you currently are (usually
|
|
38
38
|
`main`); reserve it for a trivial one-liner or an explicit request.
|
|
39
39
|
|
|
40
|
-
A bug fix changes real source, so — exactly like `/spec-
|
|
40
|
+
A bug fix changes real source, so — exactly like `/spec-start` — it belongs on the
|
|
41
41
|
bug's **own branch**, never directly on `main`. Provision the worktree **now**,
|
|
42
42
|
before the failing test, so the test, the fix, and the spec all land together and
|
|
43
43
|
arrive as one reviewable PR.
|
|
@@ -111,7 +111,7 @@ because work is already underway. Keep it lean:
|
|
|
111
111
|
# Bug: <short title>
|
|
112
112
|
|
|
113
113
|
> **Type:** Bug
|
|
114
|
-
> **Name:** bug-<kebab-name> (the spec folder name — the handle you paste into `/spec-
|
|
114
|
+
> **Name:** bug-<kebab-name> (the spec folder name — the handle you paste into `/spec-start`)
|
|
115
115
|
> **Status:** In Progress — fixing (red test added)
|
|
116
116
|
> **Author:** <git user.name — who reported/captured it>
|
|
117
117
|
> **Developer:** <git user.name — you, since you're fixing it now>
|
|
@@ -147,8 +147,10 @@ Service, CLI command, Config key, Skill/rule, Business rule — or whatever fits
|
|
|
147
147
|
this project (skitterspec itself is a CLI with no HTTP surface). Keep `Detail`
|
|
148
148
|
terse — names/signatures, not sentences. List **only** surfaces that actually
|
|
149
149
|
change; the heading is always present, but if nothing external changes write the
|
|
150
|
-
single line below instead of an empty table
|
|
151
|
-
|
|
150
|
+
single line below instead of an empty table.>
|
|
151
|
+
|
|
152
|
+
<A bug fix often changes no external surface — that's fine, use the
|
|
153
|
+
one-liner.>
|
|
152
154
|
|
|
153
155
|
| Surface | Change | Detail |
|
|
154
156
|
|---------|--------|--------|
|
|
@@ -186,12 +188,12 @@ fix narrative and decisions — keep them separate.
|
|
|
186
188
|
|
|
187
189
|
If the root cause is large/uncertain and can't be fixed in one pass: keep the red
|
|
188
190
|
test, split the fix into phase files (`01-<slug>.md` …) with a phase index in
|
|
189
|
-
`00-overview.md`, and leave the spec in `in-progress` for `/spec-
|
|
191
|
+
`00-overview.md`, and leave the spec in `in-progress` for `/spec-next` to continue.
|
|
190
192
|
Say so explicitly — don't fake green.
|
|
191
193
|
|
|
192
194
|
**Then refresh the mirror (only if a provider is installed).** The Fix tasks are
|
|
193
195
|
ticked, so the repo is now the truth about this fix — and this skill can take a
|
|
194
|
-
bug all the way to green without `/spec-
|
|
196
|
+
bug all the way to green without `/spec-next` ever running. Without a provider this
|
|
195
197
|
is a no-op.
|
|
196
198
|
|
|
197
199
|
|
|
@@ -78,6 +78,18 @@ directly (the old `/spec-env-down` skill is gone — teardown is folded in here)
|
|
|
78
78
|
1. If `.spec-env/connected` names this spec, run `skitterspec spec-env connect
|
|
79
79
|
main` first to free the canonical ports.
|
|
80
80
|
2. `skitterspec spec-env dev down <name>` — stop its host dev servers.
|
|
81
|
+
**Standing in the worktree? Leave it before you tear it down.** If this
|
|
82
|
+
session's cwd is inside the spec's own worktree, `cd` to the primary checkout
|
|
83
|
+
**first**, then run the teardown commands.
|
|
84
|
+
|
|
85
|
+
Not because git refuses — it does not. `git worktree remove` **succeeds** on the
|
|
86
|
+
tree you are standing in, and that is the problem: the directory vanishes under
|
|
87
|
+
the shell, `pwd` keeps reporting the path that no longer exists, and every
|
|
88
|
+
command after it dies with `fatal: Unable to read current working directory`.
|
|
89
|
+
The teardown looks fine and everything following it breaks — the report, the
|
|
90
|
+
prune, any check you meant to run. Relocating first costs nothing and is the
|
|
91
|
+
only ordering that survives.
|
|
92
|
+
|
|
81
93
|
3. `skitterspec spec-env down <name>` — then execute the printed commands to
|
|
82
94
|
remove the worktree/stack and free the slot. It respects the teardown guards
|
|
83
95
|
(won't destroy a dirty/unpushed worktree without `--force`).
|
|
@@ -25,7 +25,7 @@ Before marking complete, confirm the work is actually finished:
|
|
|
25
25
|
originally-failing test named in the spec now passes — that test is the proof
|
|
26
26
|
the fix works.
|
|
27
27
|
- If genuinely incomplete work remains, **stop and tell the user** rather than
|
|
28
|
-
forcing completion. Offer to finish it (`/spec-
|
|
28
|
+
forcing completion. Offer to finish it (`/spec-next`) or to complete with the
|
|
29
29
|
remaining items explicitly listed as deferred.
|
|
30
30
|
- **Check for pre-existing uncommitted changes — before you touch anything.**
|
|
31
31
|
Run `git status`. Anything already uncommitted is the *user's* work (a
|
|
@@ -73,8 +73,11 @@ Confirm the move, the commit, the final test result, and list anything deferred.
|
|
|
73
73
|
|
|
74
74
|
## 6. Land the branch (opt-in, only if isolated)
|
|
75
75
|
|
|
76
|
-
**Only when `specs/.core/env.config.json` exists and the spec
|
|
77
|
-
(
|
|
76
|
+
**Only when `specs/.core/env.config.json` exists and the spec was provisioned**
|
|
77
|
+
(a worktree in `worktree` mode, or its branch in the checkout in `checkout`
|
|
78
|
+
mode — `spec-env integrate` and `down` pick the right plan from `mode`, so the
|
|
79
|
+
commands you run differ but these steps do not)
|
|
80
|
+
(it was provisioned by `/spec-start` or `/spec-hotfix`). Otherwise skip this entirely
|
|
78
81
|
— a non-isolated spec has nothing to land, and `/spec-complete` behaves exactly as
|
|
79
82
|
before. When it applies, offer to land the finished branch so the work reaches its
|
|
80
83
|
destination in one flow. **How it lands depends on the spec type:**
|
|
@@ -125,7 +128,7 @@ is finished — e.g. to run a later phase in CI or a shared test env? Use
|
|
|
125
128
|
work is actually landable and **aborts loudly** rather than finalize a spec
|
|
126
129
|
having landed nothing. Two cases, both leaving the live session intact:
|
|
127
130
|
- *stranded commits* — commits sit on the worktree's **detached HEAD** (e.g. a
|
|
128
|
-
pre-fix `/spec-
|
|
131
|
+
pre-fix `/spec-next` committed there instead of on the branch). It prints the
|
|
129
132
|
count, the sha, and a `git -C <worktree> branch <tmp> <sha>` recovery hint —
|
|
130
133
|
recover those commits onto the branch, then re-run.
|
|
131
134
|
- *no worktree* — the spec is live but its worktree is gone. Re-isolate it with
|
|
@@ -168,6 +171,18 @@ worktree and branch are being kept, and go straight to sub-step 4. Mention
|
|
|
168
171
|
canonical ports go back to the primary checkout.
|
|
169
172
|
2. **Stop its host dev servers:** `skitterspec spec-env dev down <name>` (a
|
|
170
173
|
no-op when none are running / configured).
|
|
174
|
+
**Standing in the worktree? Leave it before you tear it down.** If this
|
|
175
|
+
session's cwd is inside the spec's own worktree, `cd` to the primary checkout
|
|
176
|
+
**first**, then run the teardown commands.
|
|
177
|
+
|
|
178
|
+
Not because git refuses — it does not. `git worktree remove` **succeeds** on the
|
|
179
|
+
tree you are standing in, and that is the problem: the directory vanishes under
|
|
180
|
+
the shell, `pwd` keeps reporting the path that no longer exists, and every
|
|
181
|
+
command after it dies with `fatal: Unable to read current working directory`.
|
|
182
|
+
The teardown looks fine and everything following it breaks — the report, the
|
|
183
|
+
prune, any check you meant to run. Relocating first costs nothing and is the
|
|
184
|
+
only ordering that survives.
|
|
185
|
+
|
|
171
186
|
3. **Remove worktree + stack + slot:** run `skitterspec spec-env down <name>`
|
|
172
187
|
and execute the commands it prints, in order. After a landing — merged into
|
|
173
188
|
base for a **feature/bug**, captured by the deploy tag for a **hotfix** —
|
|
@@ -178,7 +193,7 @@ worktree and branch are being kept, and go straight to sub-step 4. Mention
|
|
|
178
193
|
rather than reaching for `--force`.
|
|
179
194
|
|
|
180
195
|
**If the plan prints a `remote branch — confirm with the user first:`
|
|
181
|
-
section, ask before running it.** `/spec-
|
|
196
|
+
section, ask before running it.** `/spec-start` pushed this branch when it
|
|
182
197
|
provisioned, so the remote copy outlives teardown unless someone deletes it.
|
|
183
198
|
The planner only ever offers this for a branch that has **landed**, so say so
|
|
184
199
|
plainly when you ask — the commits are on the base branch (or captured by the
|
|
@@ -198,6 +213,12 @@ worktree and branch are being kept, and go straight to sub-step 4. Mention
|
|
|
198
213
|
finish completing anyway — never block the spec on it. Skip when Docker isn't
|
|
199
214
|
in use (the command self-reports "no orphaned volumes").
|
|
200
215
|
|
|
216
|
+
**Report from where you now are.** After a teardown you relocated for, the
|
|
217
|
+
worktree path in the report is a directory that no longer exists and the landed
|
|
218
|
+
work is on the base branch in the primary checkout — say both, so nobody goes
|
|
219
|
+
looking for a tree that is gone. A session that was a worktree tab has finished
|
|
220
|
+
its job at that point; its shell is the operator's own to close.
|
|
221
|
+
|
|
201
222
|
**Say what you reclaimed.** With no confirmation step the user never saw this
|
|
202
223
|
coming, so the final report must name the worktree path removed and the branch
|
|
203
224
|
deleted (or, under `--keep-env`, that both were kept). A teardown nobody
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spec-hotfix
|
|
3
|
-
description: Fix a production bug on the exact released version — fork a worktree from a release tag, drive it red→green
|
|
3
|
+
description: Fix a production bug on the exact released version — fork a worktree from a release tag, drive it red→green, then land it by tagging a new patch for CI/CD and cherry-picking the fix onto main. ALWAYS starts from a base tag and works on the hotfix's own branch, never on main. Use when the user says "/spec-hotfix", "hotfix <tag>", "prod is broken on <version>", "patch the released version", or needs a fix shipped against a tagged release rather than main.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /spec-hotfix — fix a released version, tag it, cherry-pick back to main
|
|
@@ -83,7 +83,7 @@ that header — must exist **before** `spec-env up`:
|
|
|
83
83
|
`<worktreePath>/specs/in-progress/hotfix-<name>/00-overview.md`.
|
|
84
84
|
- **Bootstrap the worktree.** A fresh worktree has no installed dependencies and
|
|
85
85
|
none of the repo's gitignored files (`.env`, local overrides). Run the printed
|
|
86
|
-
`in the worktree, run:` steps (file seeding, then setup) in order, before
|
|
86
|
+
`in the worktree, run:` steps (file seeding, then `setup`) in order, before
|
|
87
87
|
anything else.
|
|
88
88
|
- **Trust the worktree for this session.** The engine wrote the printed
|
|
89
89
|
`trusted:` root into `.claude/settings.local.json`, but it won't hot-reload now
|
|
@@ -116,7 +116,7 @@ is usually a single-pass fix, so the `## Fix` block can live directly in
|
|
|
116
116
|
# Hotfix: <short title>
|
|
117
117
|
|
|
118
118
|
> **Type:** Hotfix
|
|
119
|
-
> **Name:** hotfix-<kebab-name> (the spec folder name — the handle you paste into `/spec-
|
|
119
|
+
> **Name:** hotfix-<kebab-name> (the spec folder name — the handle you paste into `/spec-start`)
|
|
120
120
|
> **Status:** In Progress — fixing (red test added)
|
|
121
121
|
> **Author:** <git user.name — who reported/captured it>
|
|
122
122
|
> **Developer:** <git user.name — you, since you're fixing it now>
|
|
@@ -153,8 +153,10 @@ Service, CLI command, Config key, Skill/rule, Business rule — or whatever fits
|
|
|
153
153
|
this project (skitterspec itself is a CLI with no HTTP surface). Keep `Detail`
|
|
154
154
|
terse — names/signatures, not sentences. List **only** surfaces that actually
|
|
155
155
|
change; the heading is always present, but if nothing external changes write the
|
|
156
|
-
single line below instead of an empty table
|
|
157
|
-
|
|
156
|
+
single line below instead of an empty table.>
|
|
157
|
+
|
|
158
|
+
<A hotfix should be minimal — often no external surface changes; that's
|
|
159
|
+
fine, use the one-liner.>
|
|
158
160
|
|
|
159
161
|
| Surface | Change | Detail |
|
|
160
162
|
|---------|--------|--------|
|
|
@@ -198,7 +200,7 @@ narrative and decisions).
|
|
|
198
200
|
|
|
199
201
|
**Then refresh the mirror (only if a provider is installed).** The Fix tasks are
|
|
200
202
|
ticked, so the repo is now the truth about this fix — and this skill can take a
|
|
201
|
-
bug all the way to green without `/spec-
|
|
203
|
+
bug all the way to green without `/spec-next` ever running. Without a provider this
|
|
202
204
|
is a no-op.
|
|
203
205
|
|
|
204
206
|
|
|
@@ -22,10 +22,20 @@ clobber customised content. Finish with a summary of created vs already-present.
|
|
|
22
22
|
> **Leave alone**. Non-interactively it only adds what's missing; `--resync` /
|
|
23
23
|
> `--reset` (reset needs `--yes`) drive the stronger actions.
|
|
24
24
|
|
|
25
|
-
The system is **
|
|
26
|
-
`spec-
|
|
27
|
-
`
|
|
28
|
-
|
|
25
|
+
The system is **ten skills**: `spec` (feature), `spec-bug` (bug),
|
|
26
|
+
`spec-hotfix` (a bug fixed on a released tag), `spec-review`, `spec-start`,
|
|
27
|
+
`spec-next`, `spec-to-main`, `spec-complete`, `spec-cancel`, and this
|
|
28
|
+
`spec-init`. The lifecycle is `backlog → in-progress → complete / cancelled`,
|
|
29
|
+
with `.core` holding always-apply project rules.
|
|
30
|
+
|
|
31
|
+
## 0. Workspace mode (only when adopting isolation)
|
|
32
|
+
|
|
33
|
+
If this project is adopting per-spec isolation, ask which `mode` belongs in
|
|
34
|
+
`specs/.core/env.config.json` — `worktree` (default; a checkout per spec, several
|
|
35
|
+
at once, one terminal session each) or `checkout` (the branch is built in the
|
|
36
|
+
checkout you are already in; one spec at a time, no hand-off). It is a question
|
|
37
|
+
about how the operator works, not about what the repo contains, so ask rather
|
|
38
|
+
than infer it from whether dev servers or Docker are configured.
|
|
29
39
|
|
|
30
40
|
## 1. Folders
|
|
31
41
|
|
|
@@ -54,7 +64,7 @@ project wants everything tracked, remove it. Confirm with
|
|
|
54
64
|
|
|
55
65
|
## 3. Verify the skills are installed
|
|
56
66
|
|
|
57
|
-
Check each of the
|
|
67
|
+
Check each of the ten skills resolves — `.claude/skills/<name>/SKILL.md`
|
|
58
68
|
(project) or `~/.claude/skills/<name>/` (global). List any missing. This skill
|
|
59
69
|
scaffolds the project; it does **not** regenerate skill bodies — missing skills
|
|
60
70
|
must be copied in (e.g. `npx @skitterbyte/skitterspec init`) from a global install
|
|
@@ -73,7 +83,7 @@ Ensure it exists. If missing, create it documenting:
|
|
|
73
83
|
- the project's concrete typecheck/test commands, and the rule that **every
|
|
74
84
|
phase ends with creating + running tests**.
|
|
75
85
|
|
|
76
|
-
Read a sibling spec skill (e.g. `spec`, `spec-
|
|
86
|
+
Read a sibling spec skill (e.g. `spec`, `spec-next`) for the canonical shapes
|
|
77
87
|
rather than inventing them. If the rule already exists, leave it unless stale.
|
|
78
88
|
|
|
79
89
|
## 5. CLAUDE.md
|