@skitterbyte/skitterspec 16.10.0 → 18.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 CHANGED
@@ -1,5 +1,93 @@
1
1
  # Migration guide
2
2
 
3
+ ## `@skitterbyte/skitterspec` v17 → v18 (a spec is built in its own worktree)
4
+
5
+ ### Breaking change
6
+
7
+ **`/spec-start` no longer moves the branch into your checkout.** In `worktree`
8
+ mode it provisions the spec's worktree, does the housekeeping there, opens a
9
+ session in it, and stops. The spec is built where it was provisioned — which is
10
+ what worktrees are for, and why `main` stays free.
11
+
12
+ This **supersedes the "one checkout holds one spec in flight" rule** described
13
+ under v16 → v17 below. That rule was a consequence of moving the branch into the
14
+ primary checkout; with the move gone, so is the restriction:
15
+
16
+ | v17 | v18 |
17
+ |-----|-----|
18
+ | `/spec-start` refused while another spec held your checkout | In `worktree` mode it only requires a **clean tree**. Several specs in flight is what the mode is for. |
19
+ | Starting a spec took two invocations, with a `/spec-live <name>` you typed in between | **One invocation.** No hand-off command, no re-run. |
20
+ | `/spec-live main` was one of the ways out of the gate | The ways out are `/spec-complete` and `/spec-cancel`. Parking to free a workbench is a one-workbench answer, and only `checkout` mode holds one spec now. |
21
+
22
+ **`/spec-live` is for testing only** — reusing your running dev server to reach a
23
+ spec at the canonical URL. It was never meant to be how work gets started, and no
24
+ lifecycle skill calls it.
25
+
26
+ `checkout` mode is unchanged: the branch is built in the primary checkout, the
27
+ gate still requires the workbench free, and `/spec-start` carries straight on
28
+ into phase 1 in the same session.
29
+
30
+ ### What to do
31
+
32
+ 1. **Upgrade** — `npx @skitterbyte/skitterspec update`.
33
+ 2. **Expect a session, not a swap.** After `/spec-start` in `worktree` mode, run
34
+ `/spec-next` from the session it opens in the worktree. `/spec-next` builds
35
+ the spec it is *standing in* and refuses to build one from elsewhere.
36
+ 3. **Nothing to configure.** `spec.companionPaths` in `env.config.json` is new
37
+ and optional — it names paths that belong to a spec alongside its own folder
38
+ (a tracker's per-spec snapshot), so `/spec-start` can commit them together.
39
+ Empty by default; `/spec-linear-setup` sets it for you.
40
+
41
+ ## `@skitterbyte/skitterspec-linear` v11 → v12 (a spec is built in its own worktree)
42
+
43
+ The same change as `@skitterbyte/skitterspec` v17 → v18 above — this
44
+ distribution composes the same lifecycle skills. Read that entry; nothing here
45
+ is Linear-specific.
46
+
47
+ ## `@skitterbyte/skitterspec` v16 → v17 (`/spec-go` splits in two)
48
+
49
+ ### Breaking change
50
+
51
+ **`/spec-go` is removed.** It did two jobs — set an environment up, and build a
52
+ phase — and the seam between them is where the worktree hand-off hurt: you ran
53
+ the same command twice, once to provision and once, from another session, to
54
+ build. They are now two commands with one job each:
55
+
56
+ | Removed | Use instead |
57
+ |---------|-------------|
58
+ | `/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. |
59
+ | `/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. |
60
+ | `/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. |
61
+
62
+ **One checkout holds one spec in flight.** `/spec-start` refuses while another
63
+ spec holds your checkout, naming it and the three ways to free the workbench
64
+ (`/spec-complete`, `/spec-cancel`, or `/spec-live main` to park it). It will not
65
+ stash, commit or switch on your behalf — moving unfinished work is a decision,
66
+ not a side effect.
67
+
68
+ **`/spec-next` refuses when nothing is in flight** rather than guessing a spec
69
+ from the conversation. It writes real code; a wrong guess produces commits on a
70
+ branch nobody asked for.
71
+
72
+ ### What to do
73
+
74
+ 1. **Upgrade** — `npx @skitterbyte/skitterspec update` removes the retired
75
+ `/spec-go` skill and installs the two replacements. A `/spec-go` you edited
76
+ yourself is kept with a warning rather than deleted; remove it by hand.
77
+ 2. **Retrain the muscle memory** — `/spec-start <name>` to begin, `/spec-next` to
78
+ carry on, unchanged `/spec-complete` to finish.
79
+ 3. **Providers**: the `spec-go-start` seam is now **`spec-next-start`**. A
80
+ provider distribution must rename its fragment file to match, or the build
81
+ fails on an orphaned seam.
82
+
83
+ ## `@skitterbyte/skitterspec-linear` v10 → v11 (`/spec-go` splits in two)
84
+
85
+ The same change as `@skitterbyte/skitterspec` v16 → v17 above — this
86
+ distribution composes the same lifecycle skills, so `/spec-go` is removed here
87
+ too and replaced by `/spec-start` + `/spec-next`. Read that entry; nothing here
88
+ is Linear-specific. (Backfilled: the base entry was written when the change
89
+ landed and this one was missed.)
90
+
3
91
  ## `@skitterbyte/skitterspec-linear` v9 → v10 (`push` validates your issue states)
4
92
 
5
93
  **`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-go → /spec-connect → /commit → /spec-complete
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-go`, `/spec-complete`,
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-go`
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,25 @@
1
1
  ## Spec workflow
2
2
 
3
- Spec-driven development runs through the lifecycle **skills** below — use them so
4
- structure and lifecycle stay consistent (see `.claude/rules/spec-planning.md`).
5
- The everyday loop is **`spec → go → commit → complete`**, with `/spec-connect`
6
- in the middle when you want to test the spec in a browser.
3
+ Spec-driven development runs through the lifecycle **skills** — use them so
4
+ structure and lifecycle stay consistent. The everyday loop is
5
+ **`spec → startnext → commit → complete`**, with `/spec-connect` when you want to test
6
+ the spec in a browser.
7
7
 
8
- | Skill | Action | Status | Folder |
9
- |-------|--------|--------|--------|
10
- | `/spec` | (Feature) Grill to a shared understanding, then write a groomed spec | `Ready` (or `Draft`) | `specs/backlog/` |
11
- | `/spec-bug` | (Bug) Reproduce with a failing test, capture spec, drive red→green | `In Progress` | `specs/in-progress/` |
12
- | `/spec-review` | Re-validate a spec against the codebase; refresh stale parts | `—` | (unchanged) |
13
- | `/spec-go` | Provision the env, bring dev servers up, implement the next phase | `In Progress` | `specs/in-progress/` |
14
- | `/spec-complete` | Verify all phases done + tests green; land + tear down | `Complete` | `specs/complete/` |
15
- | `/spec-cancel` | Record progress, stamp a reason; tear down | `Cancelled` | `specs/cancelled/` |
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) | — | — |
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.
19
12
 
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.
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.
24
16
 
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.
17
+ **Release gating** *(only when `specs/.core/gating.config.json` exists)* each
18
+ spec records whether it ships behind a feature flag, as
19
+ `> **Gating:** <flag name>` or `> **Gating:** none: <one-line reason>`. `/spec`,
20
+ `/spec-bug` and `/spec-hotfix` ask; `/spec-review`, `/spec-start` and
21
+ `/spec-complete` report a spec that has no answer, and never block over it.
22
+ `skitterspec gating check` lists them and always exits 0. The point is that the
23
+ question is **on the record**: a missing line is an oversight, a reason is a
24
+ decision. Skitterspec never reads your flag system it asks and cites the doc
25
+ you point it at. Without that config, none of this appears.
@@ -1,4 +1,5 @@
1
1
  {
2
+ "mode": "worktree",
2
3
  "worktree": {
3
4
  "root": "../{repo}-wt",
4
5
  "folderPattern": "{slug}"
@@ -14,7 +15,9 @@
14
15
  },
15
16
  "seedFiles": {
16
17
  "mode": "symlink",
17
- "files": [".env"]
18
+ "files": [
19
+ ".env"
20
+ ]
18
21
  },
19
22
  "setup": [],
20
23
  "dev": [],
@@ -30,6 +33,9 @@
30
33
  "pattern": "{type}/{slug}",
31
34
  "identifierField": ""
32
35
  },
36
+ "spec": {
37
+ "companionPaths": []
38
+ },
33
39
  "baseBranch": "",
34
40
  "guards": {
35
41
  "refuseTeardownIfDirty": true,
@@ -2,17 +2,17 @@
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-go`, teardown into
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-go` gives
11
- **every** in-progress spec its own git worktree automatically. Docker is a **per-
12
- spec escalation** — a spec brings up a stack only when its `> **Stack:**` header
13
- is `worktree + docker` (set at `/spec` when it touches the DB / stateful
14
- services). A `worktree`-only spec takes no registry slot, no port block, and no
15
- `.env`.
10
+ **Once this file is present, isolation is the default policy:** `/spec-start` gives
11
+ **every** in-progress spec its own git worktree automatically. Docker is a
12
+ **per- spec escalation** — a spec brings up a stack only when its
13
+ `> **Stack:**` header is `worktree + docker` (set at `/spec` when it touches
14
+ the DB / stateful services). A `worktree`-only spec takes no registry slot, no
15
+ port block, and no `.env`.
16
16
 
17
17
  **Adopt it** with `skitterspec init --isolation` (or copy
18
18
  `env.config.json.example` → `env.config.json` here) and edit the values. While
@@ -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,18 @@ 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 run after `spec-env up`. The
112
- // template is expanded with {worktreePath}, {slug}, {branch}, {projectName},
113
- // {portOffset}. Empty = nothing is opened (the path is just printed).
127
+ // Optional, editor/terminal-agnostic opener the FALLBACK for reaching a
128
+ // worktree. `/spec-start` normally moves the session you typed into into the
129
+ // worktree, and then there is nothing to open: it runs this only when it
130
+ // could not switch in place (the session is already inside another worktree,
131
+ // or the harness cannot move it). Run after provisioning and bootstrap, so
132
+ // the session opens onto a tree that is ready to work in. The template is
133
+ // expanded with {worktreePath}, {slug}, {branch}, {projectName},
134
+ // {portOffset}.
135
+ // Empty = nothing is opened (the path is just printed), which is how you turn
136
+ // the auto-open off, and the right value unless you actually want a second
137
+ // window on the fallback path. A non-interactive run skips it either way — an
138
+ // opened window nobody is sitting at helps no one.
114
139
  // Examples: "code {worktreePath}", "tmux new-window -c {worktreePath}",
115
140
  // or a "warp://..." deeplink for Warp users.
116
141
  "open": {
@@ -133,6 +158,26 @@ no live `env.config.json` was found.
133
158
  "identifierField": ""
134
159
  },
135
160
 
161
+ // Paths that belong to a spec ALONGSIDE its own `specs/<bucket>/<name>/`
162
+ // folder. `/spec-start` uses this to tell "the spec you just wrote, not yet
163
+ // committed" apart from someone else's uncommitted work: if every dirty path
164
+ // belongs to the spec being started it is committed for you, and if a single
165
+ // path does not, the start is refused as before.
166
+ //
167
+ // Provider-neutral by design — the base engine must not know that any
168
+ // particular tracker exists — so you declare the shape here. `{slug}` and
169
+ // `{identifier}` expand exactly as in `branch.pattern` above, `{identifier}`
170
+ // via `branch.identifierField`.
171
+ //
172
+ // A pattern using {identifier} matches NOTHING when no identifier resolves
173
+ // (no `identifierField` set, or a spec never pushed to a tracker). That is
174
+ // deliberate: the file it names then belongs to some other spec, and the safe
175
+ // failure is a refusal you clear with /commit, not a stranger's file swept
176
+ // into your commit. Default: none — a spec owns only its own folder.
177
+ "spec": {
178
+ "companionPaths": []
179
+ },
180
+
136
181
  // Integration base branch — the branch specs fork from and land back onto
137
182
  // (used by the teardown "merged?" guard and, later, the integrate step).
138
183
  // Empty = auto-detect: origin/HEAD → main → master. Set it when your default
@@ -148,7 +193,7 @@ no live `env.config.json` was found.
148
193
  "refuseTeardownIfUnpushed": true
149
194
  },
150
195
 
151
- // What teardown cleans up beyond this machine. `/spec-go` pushes the spec
196
+ // What teardown cleans up beyond this machine. `/spec-start` pushes the spec
152
197
  // branch when it provisions, so without this a completed spec leaves a merged
153
198
  // branch on the remote forever. `deleteRemoteBranch`:
154
199
  // "prompt" (default) — plan `git push <remote> --delete <branch>` in its own
@@ -0,0 +1,4 @@
1
+ {
2
+ "guidance": "",
3
+ "default": "none: <reason>"
4
+ }
@@ -0,0 +1,81 @@
1
+ # `gating.config.json` — release-gating config
2
+
3
+ Opt-in config for **release gating**: whether each spec records a decision about
4
+ shipping behind a feature flag.
5
+
6
+ The problem it solves is not "we forgot to use a flag" — it is that
7
+ **nobody can tell whether the question was asked**. A spec can go from `/spec`
8
+ through
9
+ implementation to `/spec-complete` with no flag and no mention of one, and that
10
+ is indistinguishable from "we considered it and decided against". Prose guidance
11
+ in a project rule has already been shown not to close that gap; a required header
12
+ does, because its absence is visible.
13
+
14
+ **Skitterspec bakes in the offer, never the mechanism.** How your project does
15
+ flags — a resolver, an admin toggle, env precedence, a vendor SDK — is none of
16
+ its business, and it never reads your flag code. It asks the question, cites your
17
+ own documentation, and records the answer.
18
+
19
+ **Adopt it** by copying `gating.config.json.example` → `gating.config.json` here
20
+ (or `skitterspec init --gating`). While this file is absent the feature is
21
+ entirely unused: no grill question, no header, nothing to check — which is read
22
+ as "this project does not use feature flags".
23
+
24
+ ## Fields
25
+
26
+ ```jsonc
27
+ {
28
+ // Where THIS project documents how its flags work — a repo-relative path,
29
+ // cited when the question is asked so the answer is an informed one.
30
+ // Skitterspec never reads the file; it only names it. Empty = say nothing.
31
+ "guidance": ".claude/rules/feature-flags.md",
32
+
33
+ // The value written when the user declines a flag, so a project can
34
+ // standardise its wording. Must keep the `none: <reason>` shape — the reason
35
+ // half is the whole point (see below). Empty falls back to `none: <reason>`.
36
+ "default": "none: <reason>"
37
+ }
38
+ ```
39
+
40
+ ## The header it drives
41
+
42
+ With this file present, every spec `/spec`, `/spec-bug` and `/spec-hotfix` write
43
+ carries a `Gating:` field beside `Stack:` in `00-overview.md`:
44
+
45
+ ```
46
+ > **Gating:** search-ranking-v2
47
+ > **Gating:** none: additive, nothing to revert
48
+ ```
49
+
50
+ Two valid shapes, and one that is not:
51
+
52
+ | Value | Meaning |
53
+ |-------|---------|
54
+ | a flag name | ships behind that flag |
55
+ | `none: <reason>` | deliberately not flagged, and why |
56
+ | *missing, empty, or a bare `none`* | **not a decision** — nobody answered |
57
+
58
+ The reason half is load-bearing. `none: additive, nothing to revert` is a
59
+ decision a reviewer can disagree with; a bare `none` is a shrug, and a missing
60
+ line is an oversight. Distinguishing those three is the entire feature.
61
+
62
+ ## What it never does
63
+
64
+ - **It never blocks.** `skitterspec gating check` reports and exits 0;
65
+ `/spec-start` and `/spec-complete` mention a missing header and carry on.
66
+ Nothing here can stop a spec being started, completed or landed.
67
+ - **It never accuses an old spec.** Only `specs/backlog/` and
68
+ `specs/in-progress/` are read. Specs finished or abandoned before you adopted
69
+ gating are out of range by construction, not by a filter someone has to
70
+ remember.
71
+ - **It never learns your flag system.** `guidance` is a path it prints, nothing
72
+ more.
73
+
74
+ ## Checking
75
+
76
+ ```
77
+ skitterspec gating check # the spec in flight here
78
+ skitterspec gating check <spec> # one named spec
79
+ skitterspec gating check --all # every active spec
80
+ skitterspec gating check --json # for tooling
81
+ ```
@@ -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-go` | Provision the env, bring dev servers up, implement the next phase | `In Progress` | `specs/in-progress/` |
14
+ | `/spec-start` | Put a spec in flight provision its branch, then build phase 1 | `In Progress` | `specs/in-progress/` |
15
+ | `/spec-next` | Build the next phase of the spec this session is in (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/` |
@@ -21,15 +22,15 @@ and lifecycle stay consistent. Each sets a status on the spec header
21
22
  exercises judgment. `/spec-connect` and `/spec-live` are instead **slash commands**
22
23
  (`.claude/commands/`): each pre-executes one `skitterspec spec-env` verb and
23
24
  relays its output, so there is no judgment to apply and no model turn spent
24
- finding one. They are marked `disable-model-invocation`, meaning **only you can
25
- run them** — a skill that wants one will tell you to type it rather than invoking
26
- it.
25
+ finding one. They are marked `disable-model-invocation`, meaning
26
+ **only you can run them** — a skill that wants one will tell you to type it
27
+ rather than invoking it.
27
28
 
28
29
  `/spec-to-main`, `/spec-status` and `/spec-sync` stay **skills** — each carries
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-go` hand off to `/spec-push` as work progresses.
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,26 @@ 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 — and `/spec-start` moves
48
+ the session you typed into *into* that checkout, so the work carries on in the
49
+ same terminal. **`checkout`** builds the branch in the primary checkout instead:
50
+ one spec at a time, and nothing to move into. Neither mode costs you a second
51
+ terminal; the difference is how many specs can be in flight at once.
52
+ Pick it for how you work rather than for what the project contains — a repo with
53
+ no dev servers may still want several specs in flight. In `checkout` mode
54
+ `/spec-connect` and `/spec-live` do not apply and say so: both exist to reach
55
+ work that lives elsewhere, which is the gap that mode removes.
56
+
44
57
  **Per-spec isolation (opt-in to adopt, then the default policy).** When a project
45
58
  adopts isolation (`skitterspec init --isolation`, or `specs/.core/env.config.json`
46
- present), `/spec-go` gives **every** in-progress spec its own git worktree
59
+ present), `/spec-start` gives **every** in-progress spec its own git worktree
47
60
  automatically — several specs run side by side without stashing or clashing, and
48
61
  `main` stays free. Docker is a **per-spec escalation**: `/spec` records
49
62
  `> **Stack:** worktree` (default) or `worktree + docker` when the spec touches the
50
- DB / stateful services, and `/spec-go` brings up a namespaced stack only for the
51
- latter. `/spec-go` also starts the project's host **dev servers** (`env.config`
63
+ DB / stateful services, and `/spec-start` brings up a namespaced stack only for the
64
+ latter. `/spec-start` also starts the project's host **dev servers** (`env.config`
52
65
  → `dev`) on the spec's ports; **`/spec-connect <name>`** then exposes that spec on
53
66
  your canonical `localhost` ports so you can test it at the normal URL
54
67
  (`/spec-connect main` hands them back). All housekeeping (the backlog→in-progress
@@ -74,7 +87,8 @@ feature at the normal URL — no second stack, no proxy. The branch checked out
74
87
  the primary checkout **is** the lock: exactly one spec is live at a time, and
75
88
  `/spec-live main` hands the instance back (fixes you make while live commit
76
89
  straight onto the branch; `/spec-complete` is live-aware and lands them). Rule of
77
- thumb: **live overlay is the light default for code-only specs**; it *refuses*
90
+ thumb: **live overlay is the light default for *testing* a code-only spec** it
91
+ is not how work gets started, and no lifecycle skill invokes it; it *refuses*
78
92
  stateful ones (`Stack: worktree + docker`, or a branch touching migrations) — keep
79
93
  `/spec-connect` + a Docker stack for those, and for genuinely parallel testing.
80
94
  Beneath it, `skitterspec spec-env live <take|release|abort|status>` is the engine.
@@ -83,6 +97,13 @@ Beneath it, `skitterspec spec-env live <take|release|abort|status>` is the engin
83
97
  tracker-free: it knows nothing about any specific ticketing system. A
84
98
  ticketing provider is installed as its own distribution that plugs into named
85
99
  **seams** in the shared skills and fulfils a skill-name + CLI contract.
100
+
101
+ Part of that contract is the **binary name**: the shipped `/spec-connect` and
102
+ `/spec-live` commands invoke `skitterspec`, so a superset that replaces the base
103
+ must expose that name too, alongside whatever it calls itself — one entry point
104
+ under two names. A distribution shipping only its own name leaves those commands
105
+ failing with `command not found`, which reads as a broken install rather than a
106
+ missing alias.
86
107
  Sync is **one-way**: the repo is the source of truth and the tracker is a
87
108
  **generated mirror**. It ships `/spec-push` (repo→tracker; computes a create/update plan
88
109
  against a committed last-pushed snapshot and applies it) and `/spec-status`
@@ -92,13 +113,28 @@ the tracker is never read back or merged.
92
113
 
93
114
  **Every skill that moves a spec through the lifecycle carries a seam**, so the
94
115
  mirror keeps up without anyone remembering to push: `/spec`, `/spec-bug` and
95
- `/spec-hotfix` link the spec they create; `/spec-go` refreshes it as work starts;
116
+ `/spec-hotfix` link the spec they create; `/spec-next` refreshes it as work starts;
96
117
  `/spec-complete`, `/spec-cancel` and `/spec-review` refresh it after they change
97
118
  it. `/spec-to-main` and `/spec-live` carry none — they change no status.
98
119
  With no provider installed the seams are empty and every skill behaves as a plain
99
120
  filesystem workflow. See the provider package's own docs for its config and field
100
121
  reference.
101
122
 
123
+ **Release gating (opt-in, config-gated).** With
124
+ `specs/.core/gating.config.json` present, every spec `/spec`, `/spec-bug` and
125
+ `/spec-hotfix` write carries a `> **Gating:**` header recording one decision:
126
+ does this ship behind a feature flag, or land live? The value is a **flag name**,
127
+ or **`none: <one-line reason>`** — and the reason half is the load-bearing part,
128
+ because `none: additive, nothing to revert` is a decision a reviewer can argue
129
+ with while a bare `none` is a shrug and a missing line is an oversight.
130
+
131
+ Skitterspec bakes in **the offer, never the mechanism**: it asks, cites the
132
+ project's own doc (`guidance` in that config), and records the answer. It never
133
+ reads your flag code. `skitterspec gating check` reports specs with no decision
134
+ and **always exits 0** — it reads only `backlog/` and `in-progress/`, so specs
135
+ finished before you adopted gating are out of range by construction. With the
136
+ config absent nothing appears at all: no question, no header, no check.
137
+
102
138
  ## Project conventions (fill this in)
103
139
 
104
140
  The spec skills tell you to run "your project's typecheck and test commands" and
@@ -135,12 +171,16 @@ status.
135
171
  Every spec header carries:
136
172
 
137
173
  - `> **Name:**` — the spec's folder name (`feat-`/`bug-`/`hotfix-<kebab-name>`).
138
- It's the handle you pass to `/spec-go` and the other lifecycle skills, surfaced
174
+ It's the handle you pass to `/spec-start` and the other lifecycle skills, surfaced
139
175
  in the header so it's copy-pasteable without digging for the folder name.
140
176
  - `> **Author:**` — who created the spec (set at `/spec` / `/spec-bug`, defaults
141
177
  to `git config user.name`).
142
- - `> **Developer:**` — who implements it (`—` until `/spec-go` starts work, then
178
+ - `> **Developer:**` — who implements it (`—` until `/spec-start` starts work, then
143
179
  set to `git config user.name`; `/spec-bug` sets it immediately).
180
+ - `> **Gating:**` — the release-gating decision,
181
+ **only when `specs/.core/gating.config.json` exists**: a flag name, or
182
+ `none: <one-line reason>`. Absent entirely in a project that has not adopted
183
+ gating.
144
184
 
145
185
  Every spec also has a **State log** table — the audit trail of folder/status
146
186
  transitions. Each lifecycle skill appends exactly one row when it changes state:
@@ -175,7 +215,7 @@ When asked for a plan, implementation strategy, or feature breakdown:
175
215
 
176
216
  ```
177
217
  specs/backlog/ Ready (or Draft) specs (/spec)
178
- specs/in-progress/ under active implementation (/spec-go, /spec-bug)
218
+ specs/in-progress/ under active implementation (/spec-start, /spec-bug)
179
219
  specs/complete/ finished (/spec-complete)
180
220
  specs/cancelled/ abandoned, with a reason on the header (/spec-cancel)
181
221
  specs/.core/ project rules — ALWAYS APPLY, never moved