@skitterbyte/skitterspec 17.0.0 → 19.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.
Files changed (40) hide show
  1. package/MIGRATION.md +260 -10
  2. package/README.md +53 -4
  3. package/assets/claude-md-section.md +48 -2
  4. package/assets/commands/spec-connect.md +2 -2
  5. package/assets/commands/spec-live.md +2 -2
  6. package/assets/core/env.config.json.example +9 -3
  7. package/assets/core/env.config.md +102 -30
  8. package/assets/core/gating.config.json.example +4 -0
  9. package/assets/core/gating.config.md +81 -0
  10. package/assets/review/page.html +1501 -0
  11. package/assets/rules/spec-planning.md +224 -15
  12. package/assets/rules/spec-reports.md +269 -0
  13. package/assets/skills/spec/SKILL.md +63 -12
  14. package/assets/skills/spec-bug/SKILL.md +134 -26
  15. package/assets/skills/spec-cancel/SKILL.md +85 -6
  16. package/assets/skills/spec-complete/SKILL.md +109 -20
  17. package/assets/skills/spec-diff/SKILL.md +564 -0
  18. package/assets/skills/spec-hotfix/SKILL.md +143 -21
  19. package/assets/skills/spec-init/SKILL.md +49 -9
  20. package/assets/skills/spec-next/SKILL.md +289 -7
  21. package/assets/skills/spec-review/SKILL.md +45 -9
  22. package/assets/skills/spec-reviewed/SKILL.md +241 -0
  23. package/assets/skills/spec-start/SKILL.md +323 -66
  24. package/assets/skills/spec-to-main/SKILL.md +42 -20
  25. package/package.json +11 -7
  26. package/src/cli.js +1710 -80
  27. package/src/env/building.js +143 -0
  28. package/src/env/classify.js +91 -0
  29. package/src/env/config.js +57 -9
  30. package/src/env/provision.js +192 -19
  31. package/src/env/proxy.js +34 -1
  32. package/src/env/render.js +3 -12
  33. package/src/env/resolve.js +296 -9
  34. package/src/env/review.js +1329 -0
  35. package/src/env/serve.js +549 -0
  36. package/src/env/teardown.js +13 -6
  37. package/src/gating.js +155 -0
  38. package/src/init.js +124 -2
  39. package/src/prompts.js +10 -1
  40. package/LICENSE +0 -21
@@ -1,41 +1,77 @@
1
1
  ---
2
2
  name: spec-start
3
- description: Put a spec in flight on this checkout — provision its branch, move it to in-progress, refresh the tracker, then build phase 1. Refuses unless the checkout is on the base branch with nothing already in flight, so it never parks or swaps someone's unfinished work. Use when the user says "/spec-start", "start this spec", or "begin implementing <spec>".
3
+ description: Put a spec in flight — provision its branch, move it to in-progress, refresh the tracker, then build phase 1. Commits the spec itself when that is all that is uncommitted, and refuses to touch anyone else's unfinished work. Use when the user says "/spec-start", "start this spec", or "begin implementing <spec>".
4
4
  ---
5
5
 
6
6
  # /spec-start — put a spec in flight
7
7
 
8
+ > Stay silent while this runs — speak only to ask something you cannot answer
9
+ > yourself, or to report a failure at the moment it happens. Read
10
+ > `.claude/rules/spec-reports.md` before reporting; it defines the block this
11
+ > skill ends with.
12
+
8
13
  One checkout, one spec in flight. This skill is how a spec gets there:
9
14
  provision, move it to `in-progress`, refresh the tracker, then hand straight on
10
15
  to `/spec-next` for phase 1. Continuing a spec afterwards is `/spec-next`;
11
16
  finishing it is `/spec-complete`.
12
17
 
13
- ## 1. The gate — refuse unless the workbench is free
18
+ ## 1. The gate — what each mode demands of the tree
14
19
 
15
- **Check this first, before resolving anything or touching a file.** In
16
- `worktree` mode run `skitterspec spec-env live status`; in `checkout` mode read
17
- the current branch. The workbench must be:
20
+ **Check this first, before resolving anything or touching a file.** What the
21
+ gate demands depends on the mode, because the two modes hold work in different
22
+ places read `mode` from `specs/.core/env.config.json` (default `worktree`).
18
23
 
19
- - **on the base branch** (`main`, or the configured `baseBranch`), and
20
- - **clean** no uncommitted changes.
24
+ **`worktree` mode there is no tree gate.** The spec is built in its own
25
+ worktree, so neither another spec being in flight nor its uncommitted files are a
26
+ conflict; both are the parallelism the mode exists for. `git worktree add`
27
+ carries nothing and forks from a commit, and the one thing this run writes into
28
+ the checkout — the spec's own commit, which `spec-env up` plans for you — names
29
+ its paths on both the `add` and the `commit`, so it cannot reach a file that is
30
+ not this spec's. Work belonging to someone else is **reported and left alone**,
31
+ never a refusal. Nothing is switched here and nothing is parked.
21
32
 
22
- **If it isn't, relay what is in flight and stop.** Name the spec holding the
23
- checkout and the three ways out, then end your turn:
33
+ **`checkout` mode the workbench must be free**: on the base branch (`main`, or
34
+ the configured `baseBranch`) and clean, since the branch is built right here and
35
+ this mode holds one spec at a time. If it isn't, relay what is in flight and
36
+ stop — name the spec holding the checkout and the two ways out, then end your
37
+ turn:
24
38
 
25
39
  - **`/spec-complete`** — it's finished; land it and free the workbench.
26
40
  - **`/spec-cancel`** — it isn't wanted; record why and free the workbench.
27
- - **`/spec-live main`** *(worktree mode)* — park it: the branch goes back to its
28
- worktree and stays exactly as it is, ready to resume later.
29
41
 
30
- **Never get past the gate yourself.** Do not stash, do not commit on the
31
- operator's behalf, do not `/spec-live main` for them, do not switch branches. An
32
- uncommitted tree, a half-built phase and a rebase are each a decision someone
33
- must make deliberately — and the cost of guessing is another spec's work moved
34
- without its author asking. A refusal costs one command; the alternative can cost
35
- an afternoon.
42
+ **Never get past the gate yourself.** Do not stash, do not commit
43
+ **another spec's** work, do not switch branches for them. An uncommitted tree
44
+ and a half-built phase are each a decision someone must make deliberately — and
45
+ the cost of guessing is another spec's work moved without its author asking. A
46
+ refusal costs one command; the alternative can cost an afternoon.
47
+
48
+ **What `spec-env up` does with the tree**, in both modes — relay what it says
49
+ rather than deciding for yourself:
50
+
51
+ | What it found | `worktree` | `checkout` |
52
+ |---------------|-------------|-------------|
53
+ | clean | provisions | provisions |
54
+ | every path is this spec's | commits those paths **first**, then forks | same, then switches |
55
+ | some path is not | commits this spec's, provisions, **reports the rest** | refuses, naming them |
56
+
57
+ That is membership in an exactly-known set — the spec's own folder plus the
58
+ project's `spec.companionPaths` — and **not** a judgement about whether the
59
+ changes look important. It never decides that.
36
60
 
37
- A dirty tree is refused *with the same words whatever the cause*: the gate does
38
- not try to judge whether the changes look important.
61
+ **The last row is the only real difference, and it is mechanical.**
62
+ `git switch -c` carries the working tree onto the new branch, so in
63
+ `checkout` mode a colleague's files really would be moved without them asking.
64
+ `git worktree add` carries nothing, so in `worktree` mode the same files are
65
+ simply not this run's business — and refusing over them fired on the commonest
66
+ tree this workflow produces: a second spec authored while the first is still
67
+ uncommitted. When it reports them, say how many and whose in the `Untouched` row
68
+ and **keep the verdict `✅`** — nothing went wrong.
69
+
70
+ When it plans the commit, the paths are printed above the commands, so run them
71
+ as printed; when it refuses, relay the reason and stop.
72
+
73
+ It also refuses a **clean** tree whose spec is not in the commit the worktree
74
+ would fork from — otherwise you get a branch missing the very spec it is for.
39
75
 
40
76
  ## 2. Identify the spec
41
77
 
@@ -48,65 +84,201 @@ not try to judge whether the changes look important.
48
84
  spec is a `<name>/` folder whose entry point is `00-overview.md`, with one
49
85
  file per phase beside it (`01-<slug>.md`, `02-…`). Legacy specs may be a bare
50
86
  `<name>.md`, or a `00-overview.md` with inline phases — handle those too.
51
- - A spec already in `specs/in-progress/` was started before. If its branch is
52
- parked in a worktree, this skill brings it back into flight; say so rather
53
- than reporting a fresh start.
87
+ - A spec already in `specs/in-progress/` was started before. Its worktree
88
+ probably still exists, so this is a re-attach: say so rather than reporting a
89
+ fresh start, and skip the housekeeping that is already done.
90
+
91
+ ## 2b. Bring the review server up — from here, before anything else
92
+
93
+ **Only when the project has per-spec isolation** (`specs/.core/env.config.json`
94
+ present). Without it there is no review server and this step does not exist —
95
+ skip it in silence rather than explaining an absence.
54
96
 
55
- ## 3. Put its branch in this checkout
97
+ ```
98
+ skitterspec spec-env review serve --host 0.0.0.0
99
+ ```
56
100
 
57
- **Read `mode` from `specs/.core/env.config.json`** (default `worktree`).
101
+ **Here is the point.** Right now this session is standing in the
102
+ **primary checkout**, and in a moment step 3 `cd`s into a worktree and stays
103
+ there. A
104
+ daemon started after that `cd` is started *by the worktree's copy of the code* —
105
+ and when `/spec-complete` removes that worktree, the daemon keeps answering on
106
+ its port and fails on every page it is asked for, for every spec. The engine
107
+ defends against that now, but the cheapest fix is to never create the situation:
108
+ start it while you are still somewhere that outlives the spec.
109
+
110
+ It is also what lets **several specs be reviewed at once**. Reviews all render
111
+ into the primary checkout's `.spec-env/reviews/`, so one server serves every
112
+ provisioned spec — including specs another agent is building in another
113
+ worktree. Starting it here means that one server belongs to the checkout none of
114
+ them can delete.
115
+
116
+ **Say nothing when it is already up.** The usual outcome is adoption — a server
117
+ is running and this changes nothing — and a line per `/spec-start` about a
118
+ daemon nobody asked about is the narration `.claude/rules/spec-reports.md`
119
+ forbids. Speak only if it could not start.
120
+
121
+ **Never fatal, never a gate.** A busy port, no network address, a refused
122
+ spawn — say it in one line and **carry on**; provisioning is not conditional on
123
+ it, and the page falls back to its `file://` URL exactly as it does today.
124
+
125
+ **`--host 0.0.0.0` is the deliberate half.** It binds the server to this
126
+ machine's network addresses so the page opens on a phone, and the engine mints a
127
+ token with that bind as its only guard. On a machine you would rather not expose,
128
+ drop the flag — the server is then reachable from this machine alone and the
129
+ render says so. On **`--plan`** this step does not run at all.
130
+
131
+ ## 3. Build its branch
58
132
 
59
133
  ### `worktree` mode
60
134
 
135
+ **One path. There is no branching here and none should be added back.**
136
+
61
137
  1. **Provision.** Run `skitterspec spec-env up <name>` — a planner, so run the
62
- `to provision, run:` commands it prints and confirm they succeeded. Then run
63
- its **`then, in the worktree, run:`** steps in order (file seeding, then
64
- `setup`): a fresh worktree has no dependencies and none of the repo's
65
- gitignored files, so hooks, typechecks and tests fail until they are there.
66
- 2. **Bring the branch here.** Tell the user to type **`/spec-live <name>`** — it
67
- rebases the branch, frees it from the worktree and checks it out in this
68
- checkout, which is what makes this session the workbench. It is a user-only
69
- command, so you cannot run it: print it, end your turn, and pick up at step 4
70
- when they re-run `/spec-start`.
71
- **Already here?** If the live check in step 1 showed this spec live, or the
72
- branch is already checked out, the move is done carry straight on.
73
- 3. **A spec the live overlay refuses** a hotfix, a stateful spec
74
- (`Stack: worktree + docker`), or a branch touching migrations — **parks
75
- instead.** Do the housekeeping in step 4 with `git -C <worktreePath>`, run
76
- `open.command` if configured, print the worktree path, and say to run
77
- `/spec-next` from a session there. Relay the engine's refusal reason as it
78
- printed it; those guards protect a shared dev instance and are not yours to
79
- weaken.
80
- **Trust the worktree first.** `spec-env up` wrote the printed `trusted:` root
81
- into `.claude/settings.local.json`, but that file will not hot-reload in this
82
- session run `/add-dir <trusted root>` before editing into the worktree, or
83
- the first write prompts.
138
+ `to provision, run:` commands it prints and confirm they succeeded.
139
+
140
+ 2. **Trust the worktree.** `spec-env up` wrote the printed `trusted:` root into
141
+ `.claude/settings.local.json`, but that file does not hot-reload in this
142
+ session run **`/add-dir <trusted root>`** before editing into the worktree,
143
+ or the first write prompts. This is not tab machinery: worktrees live outside
144
+ the checkout, and the trust entry is what stops the prompt.
145
+
146
+ 3. **Bootstrap it, and move into it.** The `cd` is in the command itself, and it
147
+ **moves this session** that is what it is for, not a side effect of it. The
148
+ Bash working directory persists between calls, so from here on this session is
149
+ standing in the worktree, which is what lets a bare `/spec-next` resolve the
150
+ spec on its own:
151
+
152
+ ```
153
+ cd "<worktreePath>" && <the planner's "then, in the worktree, run:" steps>
154
+ ```
155
+
156
+ Run the seeding steps before `setup`: a fresh worktree has no dependencies and
157
+ none of the repo's gitignored files, so hooks, typechecks and tests fail until
158
+ both have happened.
159
+
160
+ **Then confirm the move landed — never assume it.** Ask for a positive signal
161
+ rather than reading silence as success (`.claude/rules/negative-checks.md`
162
+ rule 1): run `skitterspec spec-env resolve` with **no argument** and read the
163
+ `spec:` line it prints.
164
+
165
+ ```
166
+ skitterspec spec-env resolve # must name this spec
167
+ ```
168
+
169
+ Three states, not two. It names this spec → carry on. It names something else,
170
+ or resolves nothing → **the `cd` did not take**. Say so plainly and fall back
171
+ to the stop-here ending in step 6, printing the path so the operator can open
172
+ a session there themselves; do not build a phase from a session whose location
173
+ you could not confirm. A failed `cd` leaves you in the primary checkout on the
174
+ base branch, where a phase's worth of code looks entirely normal at the time.
175
+
176
+ 4. **Housekeep with `git -C <worktreePath>`** — step 4 below, against the
177
+ worktree.
178
+
179
+ **Keep the `-C` prefix**, even though the session is inside the worktree now
180
+ and a bare `git` would usually do the same thing. It is immune to the one
181
+ failure this sequence can have — a `cd` that silently did not take — where a
182
+ bare `git` would instead write the spec's move into the primary checkout on
183
+ the base branch. It costs nothing and removes a whole failure mode, so do not
184
+ tidy it away.
185
+
186
+ 5. **Print the worktree path.** What happens next is step 6 — it is offered
187
+ there, not decided here.
188
+
189
+ **The session moves into the worktree, and nothing opens a window.** Those are
190
+ two different claims and both are load-bearing. The move is real, and the `cd` in
191
+ step 3 is its whole mechanism — no tool call, because an approval prompt is
192
+ unusable on a phone and leaves the session stuck. Nothing is *spawned*: no new
193
+ terminal, no tab, no editor sent anywhere, because that machinery had nothing
194
+ left to do and was removed deliberately.
195
+
196
+ **Do not move the branch into this checkout**, and do not ask the operator to.
197
+ `/spec-live` is for testing a finished-enough spec on the already-running dev
198
+ server; it is not how work gets started.
199
+
200
+ **`/spec-next`'s refusal is unchanged by this.** Its rule 2 — "the worktree you
201
+ are standing in" — is what answers afterwards, and step 3 is what puts the session
202
+ there; nothing about rules 1 to 3 is loosened, and it must stay that way, because
203
+ the refusal exists so the wrong branch is never built. What changed is where the
204
+ session stands, not how weakly the rules read: a bare `/spec-next` typed from
205
+ somewhere that is neither a worktree nor a live checkout still refuses exactly as
206
+ it did. `--worktree <path>` survives untouched beside it — it answers before those
207
+ rules and cannot be reached by guessing.
208
+
209
+ **And the `cd` is a convenience, not the only thing holding this together.**
210
+ `/spec-next`'s **rule 4** asks the engine for the sole provisioned spec, so a
211
+ bare `/spec-next` resolves this spec from anywhere in the repo — after a
212
+ `/clear`, from a new tab, tomorrow morning. That is what makes step 6's
213
+ stop-here ending an honest offer rather than a promise only this session can
214
+ keep. Do not delete rule 4 as redundant with the `cd`: the `cd` is session state,
215
+ and rule 4 is what is left once it is gone.
84
216
 
85
217
  ### `checkout` mode
86
218
 
87
219
  Run `skitterspec spec-env up <name>` and the single `git switch` it prints.
88
- There is no worktree, no bootstrap, no live step — the checkout is already the
220
+ There is no worktree, no bootstrap and no hand-off — the checkout is already the
89
221
  workbench. Its planner enforces the same gate from the engine side, so relay any
90
222
  refusal and stop.
91
223
 
92
224
  ## 4. Move the spec into development
93
225
 
94
- On the branch, in this checkout (or via `git -C <worktreePath>` for a parked
95
- spec):
226
+ **Do this before you report anything**, so no path can end with a provisioned
227
+ worktree and a spec still reading `Ready` in `specs/backlog/`. In `worktree` mode
228
+ run it against the worktree with `git -C <worktreePath>`; in `checkout` mode the
229
+ branch is already here.
96
230
 
97
231
  - `git mv "specs/backlog/<name>" "specs/in-progress/<name>"` if it isn't there
98
232
  already (`mkdir -p specs/in-progress` first). Use `git mv` to keep history.
99
233
  - Set the **Status** header: `> **Status:** In Progress — Phase 1 (started <YYYY-MM-DD>)`.
100
234
  - Set **Developer** if it is still `—` (`git config user.name`).
235
+
236
+
237
+
101
238
  - Append a **State log** row: `| <YYYY-MM-DD> | In Progress | in-progress | <git user.name> |`.
102
- - **Commit it, and push the branch.** One commit, the spec's own — it records the
103
- in-progress state for everyone and fires the tracker's automation. Do this
104
- *before* the tracker refresh below, so the snapshot that refresh writes is
105
- swept up by the phase's own commit rather than left dirty.
239
+
240
+
241
+
242
+ - **Commit it.** One commit, the spec's own it records the in-progress state on
243
+ the branch, and sweeps up everything above so the worktree is clean when you
244
+ hand it over.
245
+
246
+ **Publishing that branch is yours to do, and nothing here does it for you.**
247
+ Whenever you want the work somewhere other than this machine:
248
+
249
+ ```
250
+ git -C <worktreePath> push -u origin <branch>
251
+ ```
252
+
253
+ Print it if it is useful; never run it. This skill once pushed here, justified as
254
+ recording the state "for everyone" and firing the tracker's automation — and
255
+ neither half survives reading. The automation needs `{identifier}` in
256
+ `branch.pattern` (see `env.config.md`) to put an issue id in the branch name, and
257
+ the shipped default carries none, so the tracker has nothing to match. Nor was it
258
+ an invariant: `/spec-bug` provisions a worktree the same way and has never
259
+ pushed, and `/spec-hotfix` forbids it outright. This was the odd one out.
260
+
261
+ **It also kept a guard from ever firing.** `refuseTeardownIfUnpushed` blocks
262
+ teardown on commits that are unpushed and unlanded — which described no branch at
263
+ all while this skill published every one of them at provisioning. It can fire now,
264
+ and the place it does is `/spec-cancel`, where the work really is about to be
265
+ destroyed: that skill relays the refusal and offers both ways out. Nothing to do
266
+ here beyond knowing it is no longer dead code.
106
267
 
107
268
  A spec ideally arrives `Ready` from `/spec`; a `Draft` works too — sanity-check
108
269
  it is well-formed first.
109
270
 
271
+ ## 4b. Note a missing gating decision (only if configured)
272
+
273
+ **Only when `specs/.core/gating.config.json` exists.** Run
274
+ `skitterspec gating check <name>` and, if it names this spec, mention it **once**
275
+ before phase 1 starts — the cheapest moment to decide is before any code exists.
276
+
277
+ **This check is advisory.** It reports; it never refuses, and nothing below is
278
+ conditional on it. A spec written before the project adopted gating has no header
279
+ and is not broken — turning this into a gate would accuse the very specs the
280
+ feature was designed not to disturb.
281
+
110
282
  ## 5. Bring the spec's dev servers up — confirm before heavy steps
111
283
 
112
284
  **Only when the project configures host dev servers** (`env.config.json` → a
@@ -121,10 +293,80 @@ invoke it yourself.
121
293
 
122
294
  ## 6. Build phase 1
123
295
 
124
- **Carry straight on into `/spec-next`** in this session: it marks phase 1
125
- started, refreshes the mirror again, builds it with tests and reports. Do not
126
- stop and ask the operator to run it the workbench is set up and they asked to
127
- start the spec.
296
+ **`checkout` mode — carry straight on into `/spec-next`** in this session: it
297
+ marks phase 1 started, refreshes the mirror again, builds it with tests and
298
+ reports. Do not stop and ask the operator to run it: the branch is here and they
299
+ asked to start the spec.
300
+
301
+ **`worktree` mode — offer it, then do what they say.** Step 3 left this session
302
+ standing in the worktree, so both endings happen right here and neither needs a
303
+ second session opened anywhere. In prose: say the worktree is ready and name its
304
+ path, then ask **"build phase 1 now?"** — recommending that they do, and naming
305
+ both endings so the decline is a real answer rather than a formality.
306
+
307
+ **Never fence that question.** A grey box is read as an artefact to skim rather
308
+ than as something someone is being asked, which is the whole reason
309
+ `.claude/rules/spec-reports.md` bans fencing a message to the reader. This step
310
+ prescribed a fenced block for a long time and an operator read straight past it,
311
+ which is the evidence, not a preference.
312
+
313
+ - **Build it here** — carry on into a bare **`/spec-next`**. Bare is right: the
314
+ session is in the worktree, so its rule 2 resolves this spec with nothing
315
+ passed and nothing guessed.
316
+ - **Stop here** — the operator is left standing in the worktree on a provisioned
317
+ branch, which is a perfectly good place to leave things. Nothing has to be
318
+ reopened or handed anywhere, and `/spec-next` typed an hour later — from this
319
+ session or a fresh one — does exactly what it would have done now.
320
+
321
+ **Ask rather than deciding for them, and mean it.** Provisioning is cheap and
322
+ reversible; a phase build is neither, and one yes should not cover both. A large
323
+ phase is often better started in a session of its own with a whole context budget
324
+ to spend, and only the operator knows which this is. On **`--plan`** this step
325
+ does not run at all — nothing was provisioned to build in.
326
+
327
+ **`--worktree <path>` is still there, and is still not a way around the refusal.**
328
+ It builds a spec the session is *not* standing in, which after step 3 is the
329
+ exception rather than the normal path. Reach for it in exactly two cases: the
330
+ confirm in step 3 reported the `cd` did not take, or you deliberately mean to
331
+ build some other spec's phase from here. A path someone typed is not a path
332
+ anything guessed, which is why it was never a loosening of the refusal and still
333
+ is not.
334
+
335
+ ## 7. Report
336
+
337
+ **When step 6 carried on into `/spec-next`, emit no block here.** That skill ends
338
+ with its own, and its `Branch` and `Spec` fields already carry everything this
339
+ one would say. Two blocks for one run is the noise the contract exists to
340
+ remove — this section is for the run that stops at step 6.
341
+
342
+ End with the block defined in `.claude/rules/spec-reports.md`. That file carries
343
+ the shape; this section carries only what is specific here.
344
+
345
+ **Verdicts**
346
+
347
+ - `✅` — the branch is provisioned, the spec is `in-progress`, the session is
348
+ standing in the worktree.
349
+ - `⚠️` — provisioned, with something worth knowing (dev servers that did not
350
+ come up, a mirror that did not refresh, a missing gating decision).
351
+ - `❌` — provisioning failed part-way and left something behind. Say what, and
352
+ where.
353
+ - `⏸` — the gate refused: in `checkout` mode a dirty tree or someone else's
354
+ unfinished work, in either mode a spec whose own files are not in the commit
355
+ the worktree would fork from. Nothing changed. Another spec's uncommitted work
356
+ is **not** on this list in `worktree` mode — it is an `Untouched` row on a
357
+ `✅`.
358
+
359
+ **Fields:** `Tracker` · `Branch` · `Spec` · `Worktree` · `Untouched` · `Follow-ups` · `Next`
360
+
361
+ `Worktree` carries the path, because the session is now standing in it and the
362
+ operator's next command depends on knowing that. `Next` is `/spec-next`.
363
+
364
+ `Untouched` appears only when `spec-env up` reported uncommitted work that was
365
+ not this spec's — say how much and whose, and **keep the verdict `✅`**. Nothing
366
+ went wrong: a worktree carries nothing, so that work was never in play.
367
+
368
+ On **`--plan`** nothing was provisioned, so the verdict is `⏸` and `Built`
369
+ carries the plan rather than a claim about the repo.
128
370
 
129
371
  ## Opt-outs
130
372
 
@@ -133,14 +375,29 @@ start the spec.
133
375
  that the work lands wherever you are (usually the base branch); reserve it for
134
376
  a trivial change or an explicit request.
135
377
 
136
- There is no `--here`: `/spec-start` **is** here. It puts the branch in the
137
- checkout you are in, which is what the old opt-out was reaching for.
378
+ There is no `--here`. It existed to ask for the branch in the checkout you are
379
+ standing in and in `checkout` mode that is already what happens, while in
380
+ `worktree` mode `--no-worktree` is the way to say it.
381
+
382
+ ## Why this skill links nothing, but does mirror what it changes
383
+
384
+ This skill creates no spec and mints no issue, so it has **nothing to link** —
385
+ the intake and picker steps belong to `/spec`, `/spec-bug` and `/spec-hotfix`.
138
386
 
139
- ## Why there is no tracker seam here
387
+ It does push, though, and that is step 4's seam. The state change it makes — the
388
+ spec moving to `in-progress` with a developer stamped on it — is mirrored by the
389
+ skill that makes it, exactly as `/spec-complete`, `/spec-cancel` and
390
+ `/spec-review` mirror theirs. It was once reasoned that the refresh `/spec-next`
391
+ runs would cover it, so a push here would send the same thing twice one commit
392
+ apart. That only ever held in `checkout` mode, where `/spec-next` follows
393
+ immediately; in `worktree` mode it can be hours away or never come, and the
394
+ issue sits in its old state with nobody assigned meanwhile.
140
395
 
141
- This skill creates no spec and mints no issue, so it has nothing to link — the
142
- intake and picker steps belong to `/spec`, `/spec-bug` and `/spec-hotfix`. The
143
- state change it *does* make (the spec moving to `in-progress`) is mirrored by
144
- the refresh `/spec-next` runs the moment it starts, which pushes the issue state
145
- and the phase states together. Adding a push here would send the same thing
146
- twice, one commit apart.
396
+ The **assignment** seam just above it is still not a push, and does not need to
397
+ be. This is the one moment in the lifecycle where "who is building this" is
398
+ actually decided the branch is being provisioned for someone, and that someone
399
+ is at the keyboard. It stamps the spec file and stops there, so it costs no
400
+ tracker call and rides out on the push below like every other field. Deferring
401
+ the stamp to `/spec-next` would be worse than untidy: in `worktree` mode the two
402
+ can be separated by hours, and a spec in flight with nobody named on it is
403
+ exactly the gap assignment exists to close.
@@ -6,11 +6,16 @@ disable-model-invocation: true
6
6
 
7
7
  # /spec-to-main — land the branch on main, keep the spec open
8
8
 
9
+ > Stay silent while this runs — speak only to ask something you cannot answer
10
+ > yourself, or to report a failure at the moment it happens. Read
11
+ > `.claude/rules/spec-reports.md` before reporting; it defines the block this
12
+ > skill ends with.
13
+
9
14
  The **intermediate** landing. `/spec-complete` also lands the branch, but then
10
15
  verifies every phase, flips the status to Complete, `git mv`s the spec to
11
- `complete/`, and tears the environment down. **`/spec-to-main` stops after the
12
- land**: the worktree stays, the spec stays `In Progress`, and you can land again
13
- as you add commits.
16
+ `complete/`, and tears the environment down.
17
+ **`/spec-to-main` stops after the land**: the worktree stays, the spec stays
18
+ `In Progress`, and you can land again as you add commits.
14
19
 
15
20
  Use it when a later phase can only be done *after* the current work is on `main` —
16
21
  e.g. it needs to run in CI, a deploy pipeline, or a shared test environment that
@@ -19,9 +24,9 @@ the remaining phases with `/spec-next` and eventually `/spec-complete`.
19
24
 
20
25
  It reuses the **same engine** as `/spec-complete`'s landing (`spec-env integrate`
21
26
  — rebase + fast-forward), so it produces identical linear history. Because a
22
- fast-forward leaves `base == branch`, the operation is **idempotent and
23
- repeatable**: new commits put the branch ahead of base again, and you can run
24
- `/spec-to-main` as many times as you like.
27
+ fast-forward leaves `base == branch`, the operation is
28
+ **idempotent and repeatable**: new commits put the branch ahead of base again,
29
+ and you can run `/spec-to-main` as many times as you like.
25
30
 
26
31
  ## 0. Preconditions — when this applies
27
32
 
@@ -58,10 +63,10 @@ primary checkout is dirty, or if a *different* spec holds it (release that one w
58
63
 
59
64
  ## 3. Tests must be green before landing
60
65
 
61
- Don't push red to `main`. Run the project's typecheck and test commands **in the
62
- worktree**; the suite must be **green**. For a **Bug** spec, confirm the
63
- originally-failing test now passes. If anything is red, stop and report — landing
64
- broken code onto `main` defeats the purpose.
66
+ Don't push red to `main`. Run the project's typecheck and test commands
67
+ **in the worktree**; the suite must be **green**. For a **Bug** spec, confirm
68
+ the originally-failing test now passes. If anything is red, stop and report —
69
+ landing broken code onto `main` defeats the purpose.
65
70
 
66
71
  (Note this is the *worktree* suite. The whole point of this skill is often to run
67
72
  a *further* check that only exists on `main` / in CI — that one runs **after** the
@@ -69,8 +74,8 @@ land, in step 5.)
69
74
 
70
75
  ## 4. Land — rebase + fast-forward
71
76
 
72
- Run `skitterspec spec-env integrate <name>` and run the printed commands **in
73
- order**:
77
+ Run `skitterspec spec-env integrate <name>` and run the printed commands
78
+ **in order**:
74
79
 
75
80
  - `git -C <worktree> rebase <base>` — replay the branch onto base.
76
81
  - `git -C <mainRepoPath> merge --ff-only <branch>` — fast-forward base.
@@ -91,12 +96,29 @@ and continue — the branch has no commits base doesn't already have.
91
96
  `- <YYYY-MM-DD> — Landed intermediate work onto <base> to <run CI / deploy to
92
97
  test env / …>; spec stays In Progress.`
93
98
  - Do **NOT**: add a State-log row (status doesn't change), flip any phase/status
94
- to Complete, `git mv` the spec, or tear down the worktree/stack. **The spec
95
- stays `In Progress` and the worktree stays put.**
96
- - Report: the base branch, the fast-forward result, and the green base test. It
97
- **never pushes** — mention the user can `git push` the base branch themselves to
99
+ to Complete, `git mv` the spec, or tear down the worktree/stack.
100
+ **The spec stays `In Progress` and the worktree stays put.**
101
+ - It **never pushes** say the user can `git push` the base branch themselves to
98
102
  trigger CI / the shared env.
99
- - Point the way forward: `/spec-next` to continue the remaining phases (you'll keep
100
- committing on the same branch and can `/spec-to-main` again), and `/spec-complete`
101
- when every phase is genuinely done — it will land the final commits, finalise,
102
- and tear down.
103
+ - `Next` points the way forward: `/spec-next` to continue the remaining phases
104
+ (you'll keep committing on the same branch and can `/spec-to-main` again), and
105
+ `/spec-complete` when every phase is genuinely done — it will land the final
106
+ commits, finalise, and tear down.
107
+
108
+ End with the block defined in `.claude/rules/spec-reports.md`. That file carries
109
+ the shape; this section carries only what is specific here.
110
+
111
+ **Verdicts**
112
+
113
+ - `✅` — the branch is on the base and the base is green.
114
+ - `⚠️` — landed, with something worth knowing.
115
+ - `❌` — the rebase conflicted, or the base went red after the fast-forward.
116
+ Quote it; the repo is mid-something and that is what the reader needs.
117
+ - `⏸` — a dirty worktree, red tests, or no spec to land. Nothing moved.
118
+
119
+ **Fields:** `Branch` · `Tests` · `Landed` · `Follow-ups` · `Next`
120
+
121
+ **No `Spec` field, deliberately.** This skill changes no status and moves no
122
+ folder, and a `Spec` line here would read as though it had. The spec stays
123
+ `In Progress` and the worktree stays standing — if that needs saying, the
124
+ verdict clause says it.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@skitterbyte/skitterspec",
3
- "version": "17.0.0",
4
- "description": "Spec-driven development for Claude Code a tracker-free filesystem workflow: lifecycle skills and per-spec isolation. For Linear sync, install @skitterbyte/skitterspec-linear instead.",
3
+ "version": "19.0.0",
4
+ "description": "Spec-driven development for Claude Code \u2014 a tracker-free filesystem workflow: lifecycle skills and per-spec isolation. For Linear sync, install @skitterbyte/skitterspec-linear instead.",
5
5
  "keywords": [
6
6
  "claude",
7
7
  "claude-code",
@@ -23,14 +23,18 @@
23
23
  "MIGRATION.md"
24
24
  ],
25
25
  "engines": {
26
- "node": ">=18"
26
+ "node": ">=22.13"
27
27
  },
28
28
  "dependencies": {
29
29
  "prompts": "^2.4.2"
30
30
  },
31
+ "scripts": {
32
+ "prepare": "node ../../scripts/build-dist.js skitterspec",
33
+ "prepack": "node ../../scripts/build-dist.js skitterspec"
34
+ },
31
35
  "repository": {
32
36
  "type": "git",
33
- "url": "git+https://github.com/skitterbyte/skitterspec.git"
34
- },
35
- "scripts": {}
36
- }
37
+ "url": "git+https://github.com/SkitterByte/skitterspec.git",
38
+ "directory": "packages/skitterspec"
39
+ }
40
+ }