@skitterbyte/skitterspec-linear 10.7.0 → 11.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/commands/spec-live.md +2 -2
- package/assets/core/SETUP.md +1 -1
- package/assets/core/env.config.json.example +4 -1
- package/assets/core/env.config.md +26 -6
- package/assets/core/linear.config.json.example +2 -1
- package/assets/core/linear.config.md +46 -4
- package/assets/rules/spec-planning.md +30 -10
- package/assets/skills/spec/SKILL.md +15 -10
- package/assets/skills/spec-bug/SKILL.md +43 -9
- 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 +42 -8
- package/assets/skills/spec-init/SKILL.md +16 -6
- package/assets/skills/spec-linear-setup/SKILL.md +1 -1
- package/assets/skills/spec-next/SKILL.md +141 -0
- package/assets/skills/spec-push/SKILL.md +2 -2
- package/assets/skills/spec-review/SKILL.md +5 -5
- package/assets/skills/spec-start/SKILL.md +146 -0
- package/assets/skills/spec-status/SKILL.md +2 -2
- package/assets/skills/spec-sync/SKILL.md +9 -1
- package/assets/skills/spec-to-main/SKILL.md +7 -5
- package/package.json +1 -1
- package/src/cli.js +234 -20
- 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/src/vendor/linear/cli-sync.js +55 -4
- package/src/vendor/linear/config.js +70 -3
- package/src/vendor/linear/released.js +65 -5
- package/assets/skills/spec-go/SKILL.md +0 -233
|
@@ -110,6 +110,18 @@ directly (the old `/spec-env-down` skill is gone — teardown is folded in here)
|
|
|
110
110
|
1. If `.spec-env/connected` names this spec, run `skitterspec spec-env connect
|
|
111
111
|
main` first to free the canonical ports.
|
|
112
112
|
2. `skitterspec spec-env dev down <name>` — stop its host dev servers.
|
|
113
|
+
**Standing in the worktree? Leave it before you tear it down.** If this
|
|
114
|
+
session's cwd is inside the spec's own worktree, `cd` to the primary checkout
|
|
115
|
+
**first**, then run the teardown commands.
|
|
116
|
+
|
|
117
|
+
Not because git refuses — it does not. `git worktree remove` **succeeds** on the
|
|
118
|
+
tree you are standing in, and that is the problem: the directory vanishes under
|
|
119
|
+
the shell, `pwd` keeps reporting the path that no longer exists, and every
|
|
120
|
+
command after it dies with `fatal: Unable to read current working directory`.
|
|
121
|
+
The teardown looks fine and everything following it breaks — the report, the
|
|
122
|
+
prune, any check you meant to run. Relocating first costs nothing and is the
|
|
123
|
+
only ordering that survives.
|
|
124
|
+
|
|
113
125
|
3. `skitterspec spec-env down <name>` — then execute the printed commands to
|
|
114
126
|
remove the worktree/stack and free the slot. It respects the teardown guards
|
|
115
127
|
(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
|
|
@@ -105,8 +105,11 @@ Confirm the move, the commit, the final test result, and list anything deferred.
|
|
|
105
105
|
|
|
106
106
|
## 6. Land the branch (opt-in, only if isolated)
|
|
107
107
|
|
|
108
|
-
**Only when `specs/.core/env.config.json` exists and the spec
|
|
109
|
-
(
|
|
108
|
+
**Only when `specs/.core/env.config.json` exists and the spec was provisioned**
|
|
109
|
+
(a worktree in `worktree` mode, or its branch in the checkout in `checkout`
|
|
110
|
+
mode — `spec-env integrate` and `down` pick the right plan from `mode`, so the
|
|
111
|
+
commands you run differ but these steps do not)
|
|
112
|
+
(it was provisioned by `/spec-start` or `/spec-hotfix`). Otherwise skip this entirely
|
|
110
113
|
— a non-isolated spec has nothing to land, and `/spec-complete` behaves exactly as
|
|
111
114
|
before. When it applies, offer to land the finished branch so the work reaches its
|
|
112
115
|
destination in one flow. **How it lands depends on the spec type:**
|
|
@@ -157,7 +160,7 @@ is finished — e.g. to run a later phase in CI or a shared test env? Use
|
|
|
157
160
|
work is actually landable and **aborts loudly** rather than finalize a spec
|
|
158
161
|
having landed nothing. Two cases, both leaving the live session intact:
|
|
159
162
|
- *stranded commits* — commits sit on the worktree's **detached HEAD** (e.g. a
|
|
160
|
-
pre-fix `/spec-
|
|
163
|
+
pre-fix `/spec-next` committed there instead of on the branch). It prints the
|
|
161
164
|
count, the sha, and a `git -C <worktree> branch <tmp> <sha>` recovery hint —
|
|
162
165
|
recover those commits onto the branch, then re-run.
|
|
163
166
|
- *no worktree* — the spec is live but its worktree is gone. Re-isolate it with
|
|
@@ -200,6 +203,18 @@ worktree and branch are being kept, and go straight to sub-step 4. Mention
|
|
|
200
203
|
canonical ports go back to the primary checkout.
|
|
201
204
|
2. **Stop its host dev servers:** `skitterspec spec-env dev down <name>` (a
|
|
202
205
|
no-op when none are running / configured).
|
|
206
|
+
**Standing in the worktree? Leave it before you tear it down.** If this
|
|
207
|
+
session's cwd is inside the spec's own worktree, `cd` to the primary checkout
|
|
208
|
+
**first**, then run the teardown commands.
|
|
209
|
+
|
|
210
|
+
Not because git refuses — it does not. `git worktree remove` **succeeds** on the
|
|
211
|
+
tree you are standing in, and that is the problem: the directory vanishes under
|
|
212
|
+
the shell, `pwd` keeps reporting the path that no longer exists, and every
|
|
213
|
+
command after it dies with `fatal: Unable to read current working directory`.
|
|
214
|
+
The teardown looks fine and everything following it breaks — the report, the
|
|
215
|
+
prune, any check you meant to run. Relocating first costs nothing and is the
|
|
216
|
+
only ordering that survives.
|
|
217
|
+
|
|
203
218
|
3. **Remove worktree + stack + slot:** run `skitterspec spec-env down <name>`
|
|
204
219
|
and execute the commands it prints, in order. After a landing — merged into
|
|
205
220
|
base for a **feature/bug**, captured by the deploy tag for a **hotfix** —
|
|
@@ -210,7 +225,7 @@ worktree and branch are being kept, and go straight to sub-step 4. Mention
|
|
|
210
225
|
rather than reaching for `--force`.
|
|
211
226
|
|
|
212
227
|
**If the plan prints a `remote branch — confirm with the user first:`
|
|
213
|
-
section, ask before running it.** `/spec-
|
|
228
|
+
section, ask before running it.** `/spec-start` pushed this branch when it
|
|
214
229
|
provisioned, so the remote copy outlives teardown unless someone deletes it.
|
|
215
230
|
The planner only ever offers this for a branch that has **landed**, so say so
|
|
216
231
|
plainly when you ask — the commits are on the base branch (or captured by the
|
|
@@ -230,6 +245,12 @@ worktree and branch are being kept, and go straight to sub-step 4. Mention
|
|
|
230
245
|
finish completing anyway — never block the spec on it. Skip when Docker isn't
|
|
231
246
|
in use (the command self-reports "no orphaned volumes").
|
|
232
247
|
|
|
248
|
+
**Report from where you now are.** After a teardown you relocated for, the
|
|
249
|
+
worktree path in the report is a directory that no longer exists and the landed
|
|
250
|
+
work is on the base branch in the primary checkout — say both, so nobody goes
|
|
251
|
+
looking for a tree that is gone. A session that was a worktree tab has finished
|
|
252
|
+
its job at that point; its shell is the operator's own to close.
|
|
253
|
+
|
|
233
254
|
**Say what you reclaimed.** With no confirmation step the user never saw this
|
|
234
255
|
coming, so the final report must name the worktree path removed and the branch
|
|
235
256
|
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
|
|
@@ -97,7 +97,7 @@ it happens differs (`/spec` writes the spec in Phase B, `/spec-bug` in its step
|
|
|
97
97
|
|
|
98
98
|
- **Stamp `linear_identifier` and `linear_url`** in `00-overview.md` frontmatter
|
|
99
99
|
from the adopted issue. That is the whole link: every later skill
|
|
100
|
-
(`/spec-push`, `/spec-status`, `/spec-
|
|
100
|
+
(`/spec-push`, `/spec-status`, `/spec-start`) keys off it being present.
|
|
101
101
|
- **Do not run the project picker** and never send `project`. The issue was filed
|
|
102
102
|
somewhere deliberately — where it lives is Linear's business, and adoption is
|
|
103
103
|
not a mint.
|
|
@@ -173,7 +173,7 @@ that header — must exist **before** `spec-env up`:
|
|
|
173
173
|
`<worktreePath>/specs/in-progress/hotfix-<name>/00-overview.md`.
|
|
174
174
|
- **Bootstrap the worktree.** A fresh worktree has no installed dependencies and
|
|
175
175
|
none of the repo's gitignored files (`.env`, local overrides). Run the printed
|
|
176
|
-
`in the worktree, run:` steps (file seeding, then setup) in order, before
|
|
176
|
+
`in the worktree, run:` steps (file seeding, then `setup`) in order, before
|
|
177
177
|
anything else.
|
|
178
178
|
- **Trust the worktree for this session.** The engine wrote the printed
|
|
179
179
|
`trusted:` root into `.claude/settings.local.json`, but it won't hot-reload now
|
|
@@ -206,7 +206,7 @@ is usually a single-pass fix, so the `## Fix` block can live directly in
|
|
|
206
206
|
# Hotfix: <short title>
|
|
207
207
|
|
|
208
208
|
> **Type:** Hotfix
|
|
209
|
-
> **Name:** hotfix-<kebab-name> (the spec folder name — the handle you paste into `/spec-
|
|
209
|
+
> **Name:** hotfix-<kebab-name> (the spec folder name — the handle you paste into `/spec-start`)
|
|
210
210
|
> **Status:** In Progress — fixing (red test added)
|
|
211
211
|
> **Author:** <git user.name — who reported/captured it>
|
|
212
212
|
> **Developer:** <git user.name — you, since you're fixing it now>
|
|
@@ -243,8 +243,10 @@ Service, CLI command, Config key, Skill/rule, Business rule — or whatever fits
|
|
|
243
243
|
this project (skitterspec itself is a CLI with no HTTP surface). Keep `Detail`
|
|
244
244
|
terse — names/signatures, not sentences. List **only** surfaces that actually
|
|
245
245
|
change; the heading is always present, but if nothing external changes write the
|
|
246
|
-
single line below instead of an empty table
|
|
247
|
-
|
|
246
|
+
single line below instead of an empty table.>
|
|
247
|
+
|
|
248
|
+
<A hotfix should be minimal — often no external surface changes; that's
|
|
249
|
+
fine, use the one-liner.>
|
|
248
250
|
|
|
249
251
|
| Surface | Change | Detail |
|
|
250
252
|
|---------|--------|--------|
|
|
@@ -306,7 +308,7 @@ does — you never create the issue by hand:
|
|
|
306
308
|
`spec-sync record`. That path is fully supported — it is what anyone without
|
|
307
309
|
an API key uses.
|
|
308
310
|
5. **Echo the branch name** from `branch.pattern` so the user knows what
|
|
309
|
-
`/spec-
|
|
311
|
+
`/spec-start` will fork.
|
|
310
312
|
|
|
311
313
|
**If Linear can't be reached**, say so in one line and leave the spec written and
|
|
312
314
|
local — it is still a perfectly good spec, and `/spec-push` links it later. Do
|
|
@@ -323,6 +325,38 @@ and **never auto-push git** — Linear's own automation reacts to real branch/PR
|
|
|
323
325
|
events later. Report the Linear issue URL as part of the skill's finish-up
|
|
324
326
|
message.
|
|
325
327
|
|
|
328
|
+
### Picking the Linear Project
|
|
329
|
+
|
|
330
|
+
Run this **only when minting a spec issue** — creating it for the first time. On
|
|
331
|
+
an update the issue already has a project (or deliberately has none), and that
|
|
332
|
+
placement is **Linear's to own**: never send `project` on an update, and never
|
|
333
|
+
record the choice in the spec file or the snapshot. A PM re-homing a spec issue
|
|
334
|
+
must not show up as drift or be overwritten on the next push.
|
|
335
|
+
|
|
336
|
+
1. **List the candidates.** Ask the engine:
|
|
337
|
+
`skitterspec spec-sync projects --json`. On the API path it returns the team's
|
|
338
|
+
projects; on the MCP path it says so, and you call the discovered project-list
|
|
339
|
+
tool instead. Drop archived / completed projects — they can't take new work.
|
|
340
|
+
2. **Offer them.** Show the names (most recently updated first is fine), plus an
|
|
341
|
+
explicit **None (team only)** option. Pre-select `linear.projectId` from
|
|
342
|
+
`linear.config.json` when it's set and still in the list; otherwise pre-select
|
|
343
|
+
**None**.
|
|
344
|
+
3. **Narrow on request.** If the user types a fragment rather than choosing, filter
|
|
345
|
+
the list case-insensitively by name and re-offer. Don't re-fetch.
|
|
346
|
+
4. **Never offer to create a project.** Projects are the PM's surface — if none
|
|
347
|
+
fits, that's **None (team only)**, and someone makes the project in Linear.
|
|
348
|
+
5. **Pass it once**, to whichever thing mints the issue: `--project <chosen id>`
|
|
349
|
+
on `spec-sync apply`, or `project: <chosen id>` on the MCP issue-create call.
|
|
350
|
+
Chose None → omit it entirely (do not pass an empty string).
|
|
351
|
+
|
|
352
|
+
**Degrade, never block.** If the list can't be fetched — Linear not connected, no
|
|
353
|
+
project-list tool, no API key, or `spec-sync projects` reporting it couldn't ask —
|
|
354
|
+
say so in one line — *"project picker unavailable"* — and carry on with
|
|
355
|
+
`linear.projectId` if it's set, else no project at all. A missing picker must never fail the skill that called it.
|
|
356
|
+
|
|
357
|
+
If `linear.projectId` is set but that Project is archived or missing, relay
|
|
358
|
+
Linear's error and stop rather than silently minting an unparented issue.
|
|
359
|
+
|
|
326
360
|
## 6. Drive to GREEN
|
|
327
361
|
|
|
328
362
|
- Implement the **minimal, root-cause** fix on the branch. Match surrounding code;
|
|
@@ -334,7 +368,7 @@ message.
|
|
|
334
368
|
|
|
335
369
|
**Then refresh the mirror (only if a provider is installed).** The Fix tasks are
|
|
336
370
|
ticked, so the repo is now the truth about this fix — and this skill can take a
|
|
337
|
-
bug all the way to green without `/spec-
|
|
371
|
+
bug all the way to green without `/spec-next` ever running. Without a provider this
|
|
338
372
|
is a no-op.
|
|
339
373
|
|
|
340
374
|
**Only when `specs/.core/linear.config.json` exists** and the spec carries a
|
|
@@ -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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spec-linear-setup
|
|
3
|
-
description: Configure Linear sync for this repo by interview rather than by hand
|
|
3
|
+
description: Configure Linear sync for this repo by interview rather than by hand — discovers the workspace, asks how the work is organised, then validates the answers and writes specs/.core/linear.config.json. Safe to re-run; an existing config is reviewed, never overwritten without consent. Use when the user says "/spec-linear-setup", "set up Linear sync", "connect this repo to Linear", "configure linear.config.json", or "check my Linear setup".
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /spec-linear-setup — configure Linear sync by interview
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-next
|
|
3
|
+
description: Build the next unfinished phase of the spec currently in flight on this checkout — pre-flight, implement with tests, record progress and refresh the tracker. Refuses when no spec is in flight rather than guessing one. Use when the user says "/spec-next", "build the next phase", "continue the spec", or "carry on with this spec".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /spec-next — build the next phase of the spec in flight
|
|
7
|
+
|
|
8
|
+
It assumes the workbench is already set up: a spec is **in flight** on this
|
|
9
|
+
checkout, and this skill implements its next unfinished phase. Putting a spec in
|
|
10
|
+
flight — provisioning, moving it to `in-progress`, getting its branch here — is
|
|
11
|
+
`/spec-start`'s job. Re-run this per phase until the spec is done, then
|
|
12
|
+
`/spec-complete`.
|
|
13
|
+
|
|
14
|
+
## 1. Identify the spec in flight
|
|
15
|
+
|
|
16
|
+
Resolve **in this order**, and stop at the first that answers:
|
|
17
|
+
|
|
18
|
+
1. **The live spec of this checkout** — run
|
|
19
|
+
`skitterspec spec-env live status` and read its `live:` line. `live: yes`
|
|
20
|
+
names the spec whose branch is checked out here; that is the one to build.
|
|
21
|
+
2. **The worktree you are standing in** — if this session's cwd is inside a
|
|
22
|
+
spec's worktree, that spec is in flight *for this session*. This is the
|
|
23
|
+
manual-parallel path: several specs may be provisioned, and a terminal tab
|
|
24
|
+
opened in one is its own workbench.
|
|
25
|
+
3. **The current branch, in `checkout` mode** — no worktrees exist, so the
|
|
26
|
+
branch the checkout is on names the spec.
|
|
27
|
+
|
|
28
|
+
**If none answers, refuse and stop:**
|
|
29
|
+
`no spec in flight — run /spec-start <name> to put one on this checkout`.
|
|
30
|
+
|
|
31
|
+
**Never fall back to the spec "in context".** A spec discussed in conversation
|
|
32
|
+
is not a spec in flight, and this skill writes real code: building the wrong
|
|
33
|
+
spec's phase produces commits on a branch nobody asked for. The refusal is
|
|
34
|
+
cheap; the mistake is not.
|
|
35
|
+
|
|
36
|
+
A **name argument** is accepted, but it must *match* the spec in flight — it
|
|
37
|
+
narrows a re-run, it does not select a different spec. A mismatch refuses,
|
|
38
|
+
naming both.
|
|
39
|
+
|
|
40
|
+
## 2. Pre-flight — commit prior work
|
|
41
|
+
|
|
42
|
+
Before writing any code for this phase, get the workspace clean:
|
|
43
|
+
|
|
44
|
+
- **Confirm the last-worked phase is committed.** Run `git status` and
|
|
45
|
+
`git log --oneline -5`. The most recently *implemented* phase (not necessarily
|
|
46
|
+
the numerically previous one) should already be committed. If prior-phase work
|
|
47
|
+
is still uncommitted, **stop and suggest committing it first** (e.g. via
|
|
48
|
+
`/commit`) so each phase lands as its own reviewable commit — don't build the
|
|
49
|
+
next phase on top of an uncommitted one. (Skip if this is the first phase —
|
|
50
|
+
there's nothing prior to commit.)
|
|
51
|
+
|
|
52
|
+
## 3. Implement the phase
|
|
53
|
+
|
|
54
|
+
Identify the **first unfinished phase** from the `00-overview.md` phase index,
|
|
55
|
+
then open its phase file (`0N-<slug>.md`) — that file holds the tasks. Mark it
|
|
56
|
+
started: set the phase-file heading to `🔄` and its `> **Status:**` to
|
|
57
|
+
`In progress`, and flip the matching row in the overview phase index to `🔄`.
|
|
58
|
+
|
|
59
|
+
**Then sync with the tracker (only if a provider is installed).** The phase has
|
|
60
|
+
just changed state, so refresh the mirror before the build starts — that is what
|
|
61
|
+
makes the phase show as in progress *while* it is being built rather than only
|
|
62
|
+
once it is over. Without a provider this is a no-op and nothing below changes.
|
|
63
|
+
|
|
64
|
+
**Only when `specs/.core/linear.config.json` exists** and the spec carries a
|
|
65
|
+
`linear_identifier`. Otherwise skip this step — no config means zero change.
|
|
66
|
+
|
|
67
|
+
- **No pull.** Linear is a generated mirror in one-way sync, so there is nothing
|
|
68
|
+
to bring down before building — the repo is already the source of truth. (A
|
|
69
|
+
workflow-state a teammate moved in Linear is advisory only; `/spec-status`
|
|
70
|
+
surfaces it. It is overwritten on the next push.)
|
|
71
|
+
- **Refresh the mirror now, without asking.** Run `/spec-push`. The spec has just
|
|
72
|
+
moved to `in-progress` and its phase to `🔄` — both real state changes, and the
|
|
73
|
+
tracker is a generated mirror of them. This holds under **both**
|
|
74
|
+
`mapping.phases` modes, for different reasons:
|
|
75
|
+
- `"subissue"` (the default) — the phase sub-issues already exist, and this
|
|
76
|
+
push is what moves the current one into its in-progress state. Skip it and
|
|
77
|
+
every sub-issue sits in Backlog until the spec completes.
|
|
78
|
+
- `"deferred"` — the sub-issues do not exist yet, and this push is what mints
|
|
79
|
+
them. Skip it and a started spec stays mirrored as a phase-less issue.
|
|
80
|
+
- **Never mint the spec issue.** An unlinked spec is skipped, not created —
|
|
81
|
+
`/spec-push` is how someone opts in.
|
|
82
|
+
- **Never fatal.** If the push fails — offline, no key, a Linear error — say so
|
|
83
|
+
and **carry on with the build**. The repo is correct regardless; the mirror is
|
|
84
|
+
disposable and the next push repairs it.
|
|
85
|
+
- **Expect a dirty `specs/.core/` afterwards.** The push writes a base snapshot
|
|
86
|
+
and stamps any new ids, and `/spec-next` does not commit. The next `/commit`
|
|
87
|
+
sweeps it up with the phase's own work.
|
|
88
|
+
- Linear's GitHub branch/PR automation may drive status transitions off the
|
|
89
|
+
branch/PR you pushed in step 2; that's expected and the repo still wins on the
|
|
90
|
+
next `/spec-push`.
|
|
91
|
+
|
|
92
|
+
Then build it, following the project rules in `.claude/rules/*.md` and `CLAUDE.md`:
|
|
93
|
+
|
|
94
|
+
- Work task by task through the phase file. Make focused edits that match
|
|
95
|
+
surrounding code.
|
|
96
|
+
- Honour the project's conventions (see `.claude/rules/spec-planning.md` and the
|
|
97
|
+
rules it links).
|
|
98
|
+
- **Tests are part of the phase, not after it.** Create/extend tests for the
|
|
99
|
+
work, then run the project's typecheck and test commands. Do not declare the
|
|
100
|
+
phase done until green.
|
|
101
|
+
- Never hardcode dates in tests; never run destructive commands against a real
|
|
102
|
+
database — use the project's test database only.
|
|
103
|
+
|
|
104
|
+
## 4. Record progress
|
|
105
|
+
|
|
106
|
+
- In the **phase file**: tick completed tasks (`- [x]`), flip its heading to `✅`,
|
|
107
|
+
and set its `> **Status:**` to `Done`.
|
|
108
|
+
- In **`00-overview.md`**: flip the matching phase-index row to `✅`.
|
|
109
|
+
- If anything changed from the plan (a decision, a deviation, a discovered
|
|
110
|
+
constraint), add a dated **Changelog** entry in `00-overview.md`.
|
|
111
|
+
- If new work surfaced, add it as tasks to the appropriate phase file (or add a
|
|
112
|
+
new phase file + index row) rather than doing it silently.
|
|
113
|
+
|
|
114
|
+
**Then refresh the mirror (only if a provider is installed).** The phase is done
|
|
115
|
+
in the repo now; leaving the tracker to catch up at `/spec-complete` is what makes
|
|
116
|
+
a mirror lag a whole spec behind. Without a provider this is a no-op.
|
|
117
|
+
|
|
118
|
+
**Only when `specs/.core/linear.config.json` exists** and the spec carries a
|
|
119
|
+
`linear_identifier`. Either missing → **skip**, in one line
|
|
120
|
+
(`not linked to Linear — /spec-push to mirror it`), and carry on.
|
|
121
|
+
|
|
122
|
+
**Refresh the mirror now, without asking.** Run `/spec-push`. The repo has just
|
|
123
|
+
become the truth about this phase's progress, and progress is what the mirror
|
|
124
|
+
exists to show. Deferring it to `/spec-complete` is what makes every phase
|
|
125
|
+
sub-issue jump from Backlog straight to Done, with nothing visible in between.
|
|
126
|
+
|
|
127
|
+
- **Never mint.** An unlinked spec is skipped, not created.
|
|
128
|
+
- **Never fatal.** If the push fails — offline, no key, a Linear error — say so
|
|
129
|
+
and **finish the operation anyway**. The phase is done in the repo regardless;
|
|
130
|
+
the mirror is disposable and the next push repairs it.
|
|
131
|
+
- **Expect a dirty `specs/.core/` afterwards.** The push writes a base snapshot
|
|
132
|
+
and stamps any new ids, and these skills do not commit. The next `/commit`
|
|
133
|
+
sweeps it up with the phase's own work.
|
|
134
|
+
- **Say what happened** in the skill's report: mirror updated, skipped as
|
|
135
|
+
unlinked, or failed with the reason.
|
|
136
|
+
|
|
137
|
+
## 5. Report
|
|
138
|
+
|
|
139
|
+
Summarise what was implemented, the test result (quote failures if any), and
|
|
140
|
+
which phase is next. Do **not** `git commit` unless the user asks — finish,
|
|
141
|
+
verify, and wait.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spec-push
|
|
3
|
-
description: Push a spec up to its linked Linear issue (repo → Linear, one-way). The repo is the source of truth
|
|
3
|
+
description: Push a spec up to its linked Linear issue (repo → Linear, one-way). The repo is the source of truth and Linear a generated mirror, so content is never read back or merged. A spec is an issue and each phase a sub-issue. Opt-in — needs specs/.core/linear.config.json. Use when the user says "/spec-push", "push to Linear", "update the Linear issue from this spec".
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /spec-push — send a spec up to Linear (one-way)
|
|
@@ -90,7 +90,7 @@ issue-state NAME via `config.states` at apply time.
|
|
|
90
90
|
|
|
91
91
|
A **`phasesDeferred`** field means `mapping.phases` is `"deferred"` and this spec
|
|
92
92
|
has not started, so its phases are deliberately absent from the plan — the issue
|
|
93
|
-
pushes alone and the sub-issues are minted by the push that follows `/spec-
|
|
93
|
+
pushes alone and the sub-issues are minted by the push that follows `/spec-start`.
|
|
94
94
|
Relay the count; it is not a sign the phase files failed to parse. Nothing else
|
|
95
95
|
about applying the plan changes.
|
|
96
96
|
|
|
@@ -8,7 +8,7 @@ description: Re-validate an existing spec against the current codebase — detec
|
|
|
8
8
|
Specs rot: the code moves on while a spec sits in the backlog or pauses
|
|
9
9
|
mid-build. This skill re-validates a spec against the **current** code and
|
|
10
10
|
rewrites the stale parts so it's safe to act on. It plans only — it does not
|
|
11
|
-
implement anything (that's `/spec-
|
|
11
|
+
implement anything (that's `/spec-next`).
|
|
12
12
|
|
|
13
13
|
## 1. Identify the target spec
|
|
14
14
|
|
|
@@ -48,9 +48,9 @@ trust the spec's own wording — verify:
|
|
|
48
48
|
|
|
49
49
|
Where the drift forces a choice (the old approach no longer fits, a referenced
|
|
50
50
|
thing is gone, scope is now ambiguous), grill the user like `/spec` Phase A —
|
|
51
|
-
**
|
|
52
|
-
the drift. Don't re-litigate decisions that still hold. If you can
|
|
53
|
-
reading the code, do that instead of asking.
|
|
51
|
+
**batching independent questions, each with a recommended answer** — but scoped
|
|
52
|
+
tightly to the drift. Don't re-litigate decisions that still hold. If you can
|
|
53
|
+
resolve it by reading the code, do that instead of asking.
|
|
54
54
|
|
|
55
55
|
## 4. Update the spec
|
|
56
56
|
|
|
@@ -119,5 +119,5 @@ In `/spec-complete` and `/spec-cancel` this step is deliberately pinned
|
|
|
119
119
|
## 5. Report
|
|
120
120
|
|
|
121
121
|
Summarise the drift found, what you changed, any questions still open, and
|
|
122
|
-
whether the spec is now safe to `/spec-
|
|
122
|
+
whether the spec is now safe to `/spec-start` (or should drop back to `Draft` until
|
|
123
123
|
the open questions are resolved). Do **not** `git commit` unless the user asks.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
---
|
|
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>".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /spec-start — put a spec in flight
|
|
7
|
+
|
|
8
|
+
One checkout, one spec in flight. This skill is how a spec gets there:
|
|
9
|
+
provision, move it to `in-progress`, refresh the tracker, then hand straight on
|
|
10
|
+
to `/spec-next` for phase 1. Continuing a spec afterwards is `/spec-next`;
|
|
11
|
+
finishing it is `/spec-complete`.
|
|
12
|
+
|
|
13
|
+
## 1. The gate — refuse unless the workbench is free
|
|
14
|
+
|
|
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:
|
|
18
|
+
|
|
19
|
+
- **on the base branch** (`main`, or the configured `baseBranch`), and
|
|
20
|
+
- **clean** — no uncommitted changes.
|
|
21
|
+
|
|
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:
|
|
24
|
+
|
|
25
|
+
- **`/spec-complete`** — it's finished; land it and free the workbench.
|
|
26
|
+
- **`/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
|
+
|
|
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.
|
|
36
|
+
|
|
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.
|
|
39
|
+
|
|
40
|
+
## 2. Identify the spec
|
|
41
|
+
|
|
42
|
+
- Use the name/path argument when given.
|
|
43
|
+
- Otherwise use the spec **in context** (the one just created or discussed).
|
|
44
|
+
Unlike `/spec-next`, that fallback is safe here: this skill starts nothing
|
|
45
|
+
without the gate above passing, and a wrong guess is caught by the operator
|
|
46
|
+
before any code is written.
|
|
47
|
+
- Locate it under `specs/` — `specs/backlog/` first, then the other buckets. A
|
|
48
|
+
spec is a `<name>/` folder whose entry point is `00-overview.md`, with one
|
|
49
|
+
file per phase beside it (`01-<slug>.md`, `02-…`). Legacy specs may be a bare
|
|
50
|
+
`<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.
|
|
54
|
+
|
|
55
|
+
## 3. Put its branch in this checkout
|
|
56
|
+
|
|
57
|
+
**Read `mode` from `specs/.core/env.config.json`** (default `worktree`).
|
|
58
|
+
|
|
59
|
+
### `worktree` mode
|
|
60
|
+
|
|
61
|
+
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.
|
|
84
|
+
|
|
85
|
+
### `checkout` mode
|
|
86
|
+
|
|
87
|
+
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
|
|
89
|
+
workbench. Its planner enforces the same gate from the engine side, so relay any
|
|
90
|
+
refusal and stop.
|
|
91
|
+
|
|
92
|
+
## 4. Move the spec into development
|
|
93
|
+
|
|
94
|
+
On the branch, in this checkout (or via `git -C <worktreePath>` for a parked
|
|
95
|
+
spec):
|
|
96
|
+
|
|
97
|
+
- `git mv "specs/backlog/<name>" "specs/in-progress/<name>"` if it isn't there
|
|
98
|
+
already (`mkdir -p specs/in-progress` first). Use `git mv` to keep history.
|
|
99
|
+
- Set the **Status** header: `> **Status:** In Progress — Phase 1 (started <YYYY-MM-DD>)`.
|
|
100
|
+
- Set **Developer** if it is still `—` (`git config user.name`).
|
|
101
|
+
- 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.
|
|
106
|
+
|
|
107
|
+
A spec ideally arrives `Ready` from `/spec`; a `Draft` works too — sanity-check
|
|
108
|
+
it is well-formed first.
|
|
109
|
+
|
|
110
|
+
## 5. Bring the spec's dev servers up — confirm before heavy steps
|
|
111
|
+
|
|
112
|
+
**Only when the project configures host dev servers** (`env.config.json` → a
|
|
113
|
+
non-empty `dev` array). Show what will start — the commands, the ports, any
|
|
114
|
+
Docker stack — and get a yes; on **`--plan`**, print it and stop. On
|
|
115
|
+
confirmation run `skitterspec spec-env dev up <name>`. With none configured this
|
|
116
|
+
is a clean no-op.
|
|
117
|
+
|
|
118
|
+
To reach the spec at your normal `localhost` URL afterwards, the **user** types
|
|
119
|
+
**`/spec-connect <name>`** (`/spec-connect main` hands the ports back). Never
|
|
120
|
+
invoke it yourself.
|
|
121
|
+
|
|
122
|
+
## 6. Build phase 1
|
|
123
|
+
|
|
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.
|
|
128
|
+
|
|
129
|
+
## Opt-outs
|
|
130
|
+
|
|
131
|
+
- **`--plan`** — print the provisioning and dev-server plan, change nothing.
|
|
132
|
+
- **`--no-worktree`** — skip provisioning and build on the current branch. Warn
|
|
133
|
+
that the work lands wherever you are (usually the base branch); reserve it for
|
|
134
|
+
a trivial change or an explicit request.
|
|
135
|
+
|
|
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.
|
|
138
|
+
|
|
139
|
+
## Why there is no tracker seam here
|
|
140
|
+
|
|
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.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spec-status
|
|
3
|
-
description: Show a spec's one-way sync status against Linear — a read-only drift report
|
|
3
|
+
description: Show a spec's one-way sync status against Linear — a read-only drift report naming what would push, and whether the tracker's workflow-state has drifted from the spec's. Changes nothing. Opt-in — needs specs/.core/linear.config.json. Use when the user says "/spec-status", "is this spec in sync with Linear", "what would push", or "show spec sync status".
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -77,4 +77,4 @@ given spec got is stated. Under **`inline`** the phases live in the spec issue's
|
|
|
77
77
|
description rather than as sub-issues, so "0 to create" is the expected shape
|
|
78
78
|
rather than a sign the phase files failed to parse; under **`deferred`** the
|
|
79
79
|
`N phase(s) deferred` line above it says how many are still waiting on
|
|
80
|
-
`/spec-
|
|
80
|
+
`/spec-next`. Relay both lines as printed.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spec-sync
|
|
3
|
-
description: Run the repo-wide spec-sync operations against Linear — what
|
|
3
|
+
description: Run the repo-wide spec-sync operations against Linear — what is linked, the workspace states and projects, read-back verification, manual stamping, and bulk apply. Run it bare for the repo-wide overview. Defers to /spec-push and /spec-status for per-spec work. Opt-in — needs specs/.core/linear.config.json. Use when the user says "/spec-sync", "run spec-sync", "what's linked to Linear", "which states does the workspace have", or "mirror the whole backlog".
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -156,6 +156,14 @@ Relay the **unreferenced count** even when it is zero. A chore commit
|
|
|
156
156
|
legitimately carries no ticket and a *missed* trailer looks identical, so
|
|
157
157
|
omitting the number reads as "everything is accounted for" when it may not be.
|
|
158
158
|
|
|
159
|
+
**Bookkeeping commits are excluded.** A spec's `chore(spec): complete <name>`
|
|
160
|
+
commit carries the same ref as the code it describes but lands *after* the tag
|
|
161
|
+
that shipped it, so counting it would put the ticket in two consecutive releases.
|
|
162
|
+
A commit whose changed paths are **all** under `release.ignorePaths` (default
|
|
163
|
+
`specs/`) contributes nothing; one that touches an ignored path *and* a source
|
|
164
|
+
file still counts. Relay the **ignored count** whenever it is non-zero — that is
|
|
165
|
+
the report saying which commits it set aside.
|
|
166
|
+
|
|
159
167
|
## 8. `retarget` — after a Linear team is renamed
|
|
160
168
|
|
|
161
169
|
```
|