@skitterbyte/skitterspec-linear 1.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/README.md +56 -0
- package/assets/claude-md-section.md +39 -0
- package/assets/core/env.config.json.example +28 -0
- package/assets/core/env.config.md +99 -0
- package/assets/core/linear.config.json.example +39 -0
- package/assets/core/linear.config.md +121 -0
- package/assets/rules/spec-planning.md +152 -0
- package/assets/skills/spec/SKILL.md +232 -0
- package/assets/skills/spec-bug/SKILL.md +110 -0
- package/assets/skills/spec-cancel/SKILL.md +61 -0
- package/assets/skills/spec-complete/SKILL.md +87 -0
- package/assets/skills/spec-env/SKILL.md +63 -0
- package/assets/skills/spec-env-down/SKILL.md +64 -0
- package/assets/skills/spec-go/SKILL.md +134 -0
- package/assets/skills/spec-init/SKILL.md +84 -0
- package/assets/skills/spec-pull/SKILL.md +46 -0
- package/assets/skills/spec-push/SKILL.md +53 -0
- package/assets/skills/spec-ready/SKILL.md +50 -0
- package/assets/skills/spec-review/SKILL.md +69 -0
- package/assets/skills/spec-status/SKILL.md +46 -0
- package/bin/skitterspec-linear.js +26 -0
- package/package.json +38 -0
- package/src/cli.js +495 -0
- package/src/deprecate.js +138 -0
- package/src/env/config.js +165 -0
- package/src/env/integrate.js +46 -0
- package/src/env/provision.js +76 -0
- package/src/env/registry.js +95 -0
- package/src/env/render.js +26 -0
- package/src/env/resolve.js +202 -0
- package/src/env/teardown.js +109 -0
- package/src/env/trust.js +87 -0
- package/src/init.js +311 -0
- package/src/prompts.js +56 -0
- package/src/vendor/linear/cli-sync.js +256 -0
- package/src/vendor/linear/config.js +198 -0
- package/src/vendor/linear/mcp.js +112 -0
- package/src/vendor/sync-core/index.js +35 -0
- package/src/vendor/sync-core/src/apply.js +66 -0
- package/src/vendor/sync-core/src/base.js +83 -0
- package/src/vendor/sync-core/src/compare.js +99 -0
- package/src/vendor/sync-core/src/normalize.js +249 -0
- package/src/vendor/sync-core/src/pull.js +84 -0
- package/src/vendor/sync-core/src/push.js +106 -0
- package/src/vendor/sync-core/src/write.js +86 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec
|
|
3
|
+
description: Create a new spec-driven-development spec. Grills the user to a clear, shared understanding of the requirement AND the proposed solution FIRST, then writes one concise, phased, test-included, change-logged spec into specs/backlog/. Use when the user wants to plan a feature, write a spec, capture a requirement, or says "/spec" or "spec this out".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /spec — author a new spec
|
|
7
|
+
|
|
8
|
+
Produce ONE concise spec in `specs/backlog/`. Do not start coding — this skill
|
|
9
|
+
plans only. Implementation happens later via `/spec-go`.
|
|
10
|
+
|
|
11
|
+
Lifecycle (the governing skills) — status in parentheses:
|
|
12
|
+
`/spec` (Draft, backlog) → `/spec-ready` (Ready, still backlog) → `/spec-go`
|
|
13
|
+
(In Progress, in-progress; implement phase 1) → `/spec-complete` (Complete) /
|
|
14
|
+
`/spec-cancel` (Cancelled). See `.claude/rules/spec-planning.md`.
|
|
15
|
+
|
|
16
|
+
## Phase A — reach a clear shared understanding (grill first)
|
|
17
|
+
|
|
18
|
+
Interview the user until requirement AND proposed solution are unambiguous. Do
|
|
19
|
+
not write the spec until this is resolved.
|
|
20
|
+
|
|
21
|
+
- Break the problem into **distinctive areas** and work them in logical order,
|
|
22
|
+
resolving dependencies between decisions one at a time.
|
|
23
|
+
- Ask **one question at a time**. For each, give your **recommended answer**.
|
|
24
|
+
- If a question can be answered by **reading the codebase, read it** instead of
|
|
25
|
+
asking. Verify endpoints/models/files actually exist before relying on them.
|
|
26
|
+
- Cover, at minimum, the areas that apply:
|
|
27
|
+
1. **Problem & why** — what's broken/missing, who feels it, why now.
|
|
28
|
+
2. **Scope & non-goals** — explicit out-of-scope items.
|
|
29
|
+
3. **Affected areas** — concrete files/modules/packages this touches.
|
|
30
|
+
4. **Proposed solution shape** — the chosen approach and the alternatives
|
|
31
|
+
rejected, with the reason (this becomes "Decisions").
|
|
32
|
+
5. **Data / API impact** — schema/model changes, new endpoints, and
|
|
33
|
+
**backward compatibility** (additive = safe; breaking = needs explicit
|
|
34
|
+
permission and coordination).
|
|
35
|
+
6. **Security & multi-tenancy** — authz, tenant scoping, untrusted input.
|
|
36
|
+
7. **Edge cases & failure modes.**
|
|
37
|
+
8. **Testing approach** — what proves each phase correct.
|
|
38
|
+
9. **Isolation stack** *(only when `specs/.core/env.config.json` exists)* — does
|
|
39
|
+
this spec touch the DB / stateful services (so its worktree needs a Docker
|
|
40
|
+
stack), or is a plain worktree enough? Default `worktree`; escalate to
|
|
41
|
+
`worktree + docker` only when it must. This sets the `> **Stack:**` header
|
|
42
|
+
that `/spec-go` acts on (it can be escalated later). Skip when isolation
|
|
43
|
+
isn't enabled — leave the default `worktree`.
|
|
44
|
+
10. **Open questions** — anything still undecided.
|
|
45
|
+
|
|
46
|
+
Stop grilling when there are no unresolved branches that would change the spec.
|
|
47
|
+
Briefly play back the agreed understanding before writing.
|
|
48
|
+
|
|
49
|
+
## Phase B — write the spec
|
|
50
|
+
|
|
51
|
+
This skill is for **features**. For bugs, use `/spec-bug` (test-first, red→green).
|
|
52
|
+
|
|
53
|
+
- **Every spec is a folder** — never a bare file, even for a one-line change:
|
|
54
|
+
`specs/backlog/feat-<kebab-name>/`. Create it with `mkdir -p`.
|
|
55
|
+
- The entry point is **always `00-overview.md`** — the index/dashboard for the
|
|
56
|
+
spec. It holds the header block, Problem, Decisions, Solution overview, the
|
|
57
|
+
**phase index** (a table linking to each phase file), Open questions, State
|
|
58
|
+
log, and Changelog. It does **not** hold the per-phase task lists.
|
|
59
|
+
- **Each phase is its own file** — `01-<phase-slug>.md`, `02-<phase-slug>.md`, …
|
|
60
|
+
numbered in execution order; the slug is a short kebab description of the phase
|
|
61
|
+
goal (e.g. `01-data-model.md`, `02-api-endpoints.md`). The phase file holds
|
|
62
|
+
that phase's goal, its task checkboxes (tests included), and any phase-specific
|
|
63
|
+
notes. **Even a single-phase spec gets `01-….md`** — never lump phase tasks
|
|
64
|
+
into `00-overview.md`. This keeps each phase easy to dive into on its own.
|
|
65
|
+
- Choose a short kebab-case name and **prefix it `feat-`** (the bug counterpart
|
|
66
|
+
uses `bug-`).
|
|
67
|
+
|
|
68
|
+
Use this template (keep it **as concise as possible** — no filler, no restating
|
|
69
|
+
the codebase, link rather than duplicate):
|
|
70
|
+
|
|
71
|
+
```markdown
|
|
72
|
+
# <Feature title>
|
|
73
|
+
|
|
74
|
+
> **Type:** Feature
|
|
75
|
+
> **Status:** Draft — not started
|
|
76
|
+
> **Author:** <git user.name — `git config user.name`>
|
|
77
|
+
> **Developer:** —
|
|
78
|
+
> **Raised:** <YYYY-MM-DD (today)>
|
|
79
|
+
> **Area:** <comma-separated files/modules this touches>
|
|
80
|
+
> **Stack:** <worktree — or "worktree + docker" if it touches the DB/stateful
|
|
81
|
+
> services; only acted on when isolation is enabled — see Phase A item 9>
|
|
82
|
+
|
|
83
|
+
## Problem
|
|
84
|
+
|
|
85
|
+
<2–6 sentences: what's wrong/missing and why it matters. No fluff.>
|
|
86
|
+
|
|
87
|
+
## Decisions
|
|
88
|
+
|
|
89
|
+
<Numbered, confirmed decisions from Phase A. Each: the choice + one-line why,
|
|
90
|
+
and the rejected alternative when it sharpens the choice. This is the heart of
|
|
91
|
+
the spec — be specific.>
|
|
92
|
+
|
|
93
|
+
## Solution overview
|
|
94
|
+
|
|
95
|
+
<Short prose or bullets describing the chosen shape end-to-end. Optional small
|
|
96
|
+
schema/grammar/output snippets where they remove ambiguity.>
|
|
97
|
+
|
|
98
|
+
## Phases
|
|
99
|
+
|
|
100
|
+
Each phase lives in its own file in this folder. Status: ⬜ not started ·
|
|
101
|
+
🔄 in progress · ✅ done.
|
|
102
|
+
|
|
103
|
+
| # | Phase | Status | File |
|
|
104
|
+
|---|-------|--------|------|
|
|
105
|
+
| 1 | <goal> | ⬜ | [01-<phase-slug>.md](01-<phase-slug>.md) |
|
|
106
|
+
| 2 | <goal> | ⬜ | [02-<phase-slug>.md](02-<phase-slug>.md) |
|
|
107
|
+
|
|
108
|
+
## Open questions
|
|
109
|
+
|
|
110
|
+
- [ ] <anything deferred — or "None">
|
|
111
|
+
|
|
112
|
+
## State log
|
|
113
|
+
|
|
114
|
+
| Date | Status | Folder | By |
|
|
115
|
+
|------|--------|--------|----|
|
|
116
|
+
| <YYYY-MM-DD> | Draft | backlog | <author> |
|
|
117
|
+
|
|
118
|
+
## Changelog
|
|
119
|
+
|
|
120
|
+
- <YYYY-MM-DD> — Spec created.
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Then create **one file per phase** (`01-<phase-slug>.md`, `02-…`, in execution
|
|
124
|
+
order). Each phase file uses this template:
|
|
125
|
+
|
|
126
|
+
```markdown
|
|
127
|
+
# Phase 1 — <goal> ⬜
|
|
128
|
+
|
|
129
|
+
> Spec: [00-overview.md](00-overview.md) · **Status:** Not started
|
|
130
|
+
|
|
131
|
+
**Goal:** <one line — what this phase delivers and how it's proven>.
|
|
132
|
+
|
|
133
|
+
## Tasks
|
|
134
|
+
|
|
135
|
+
- [ ] <clear, verb-first task>
|
|
136
|
+
- [ ] <clear, verb-first task>
|
|
137
|
+
- [ ] Add/extend tests covering this phase; run the project's typecheck and
|
|
138
|
+
test commands (see `.claude/rules/spec-planning.md`) — green before the
|
|
139
|
+
phase is done.
|
|
140
|
+
|
|
141
|
+
## Notes
|
|
142
|
+
|
|
143
|
+
<Phase-specific decisions, gotchas, or context. Delete if empty.>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Keep the `00-overview.md` phase index and the phase files in sync: the index row
|
|
147
|
+
is the one-line summary + status; the phase file is the detail.
|
|
148
|
+
|
|
149
|
+
The **State log** is the audit trail of folder/status transitions — every
|
|
150
|
+
lifecycle skill (`/spec-ready`, `/spec-go`, `/spec-complete`, `/spec-cancel`)
|
|
151
|
+
appends one row when it moves the spec. The **Changelog** is for decisions and
|
|
152
|
+
course-corrections only — keep the two separate.
|
|
153
|
+
|
|
154
|
+
Rules for the spec body:
|
|
155
|
+
|
|
156
|
+
- **Every phase is independently shippable and ends with tests.** A phase is
|
|
157
|
+
not "done" until its tests are written and the suite is green. Bake a test
|
|
158
|
+
task into each phase — never a separate "testing phase" at the end only.
|
|
159
|
+
- **Tasks are checkboxes** (`- [ ]`), clear, verb-first, and granular enough to
|
|
160
|
+
finish in one session. They live in the **phase files**, not the overview. Use
|
|
161
|
+
`⬜`/`🔄`/`✅` on each phase-file heading and mirror it in the `00-overview.md`
|
|
162
|
+
phase index.
|
|
163
|
+
- **Honour project conventions** when writing tasks — reference the relevant
|
|
164
|
+
`.claude/rules/*.md` rather than re-explaining them.
|
|
165
|
+
- **Changelog** is mandatory and lives in the spec. Every later decision or
|
|
166
|
+
course-correction gets a dated one-line entry. Convert relative dates to
|
|
167
|
+
absolute.
|
|
168
|
+
- Keep it tight. If a section adds no information, delete it.
|
|
169
|
+
|
|
170
|
+
## Phase C — finish up
|
|
171
|
+
|
|
172
|
+
After writing, tell the user the path and that it's a `Draft` in `backlog`. Next
|
|
173
|
+
step is `/spec-ready` once it's groomed, then `/spec-go` to start building.
|
|
174
|
+
|
|
175
|
+
## Phase D — record the isolation stack (only if configured)
|
|
176
|
+
|
|
177
|
+
**Only when `specs/.core/env.config.json` exists** (per-spec isolation is
|
|
178
|
+
enabled), make sure the `> **Stack:**` header reflects the Phase A item 9
|
|
179
|
+
decision — `worktree` (default) or `worktree + docker` when it touches the DB /
|
|
180
|
+
stateful services. Nothing to provision now: `/spec-go` gives every in-progress
|
|
181
|
+
spec its own worktree automatically, and brings up Docker only when the Stack
|
|
182
|
+
says so. Mention the operator can escalate the Stack later (edit the header, or
|
|
183
|
+
run `/spec-env <name>` to add Docker to an existing worktree). If
|
|
184
|
+
`env.config.json` is absent, isolation is off — leave the default `worktree` and
|
|
185
|
+
finish as above.
|
|
186
|
+
|
|
187
|
+
## Phase E — link to a ticketing provider (only if one is installed)
|
|
188
|
+
|
|
189
|
+
**Only when a ticketing provider is installed and configured** (it ships the
|
|
190
|
+
`/spec-push` · `/spec-pull` · `/spec-status` skills and a provider config under
|
|
191
|
+
`specs/.core/`). If none is present, skip this phase entirely — the spec stays
|
|
192
|
+
local-only and `/spec` behaves exactly as above. When a provider is present, link
|
|
193
|
+
the spec to the tracker after writing it, so status and discussion live there
|
|
194
|
+
while the repo stays the co-authoring surface — follow the provider's link steps
|
|
195
|
+
below (nothing to do here without one).
|
|
196
|
+
|
|
197
|
+
**Only when `specs/.core/linear.config.json` exists** (Linear sync is opted in).
|
|
198
|
+
If it's absent, skip this phase entirely — the spec stays local-only and `/spec`
|
|
199
|
+
behaves exactly as above. When present, after writing the spec, link it to Linear
|
|
200
|
+
so status and discussion live there while the repo stays the co-authoring surface:
|
|
201
|
+
|
|
202
|
+
- **Discover the Linear MCP tools at runtime** (don't hardcode names). If Linear
|
|
203
|
+
isn't connected/authed, relay the fix and stop — leave the spec written and
|
|
204
|
+
local; the user can link it later with `/spec-push`. Do nothing destructive.
|
|
205
|
+
- **Create the Project** from the spec: name from the title, description from the
|
|
206
|
+
`00-overview.md` plan. Attach the `initiativeId` from `linear.config.json` when
|
|
207
|
+
one is set.
|
|
208
|
+
- **Create a Milestone per phase** (the `mapping.phases` target — milestones by
|
|
209
|
+
default), named from each phase file, in execution order.
|
|
210
|
+
- **Add the frontmatter block** to `00-overview.md` (above the `#` title) so the
|
|
211
|
+
spec is linkable:
|
|
212
|
+
|
|
213
|
+
```yaml
|
|
214
|
+
---
|
|
215
|
+
linear_project_id: "<uuid>"
|
|
216
|
+
linear_identifier: "<TEAM-123>"
|
|
217
|
+
linear_url: "https://linear.app/..."
|
|
218
|
+
spec_status: "backlog"
|
|
219
|
+
last_synced_at: "<ISO-8601 now>"
|
|
220
|
+
---
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
- **Write the initial base sidecar** so the spec starts clean and non-diverged —
|
|
224
|
+
run `skitterspec spec-sync normalize <spec>` to capture the local snapshot as the
|
|
225
|
+
committed base (`sync.baseDir`). `/spec-status` should report in-sync right after.
|
|
226
|
+
- **Echo the branch name** from `branch.pattern` so the user knows what `/spec-go`
|
|
227
|
+
will fork.
|
|
228
|
+
|
|
229
|
+
Leave committing to the existing convention (the user commits the spec as usual)
|
|
230
|
+
and **never auto-push git** — Linear's own automation reacts to real branch/PR
|
|
231
|
+
events later. Report the Linear project URL and the base as part of Phase C's
|
|
232
|
+
finish-up message.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-bug
|
|
3
|
+
description: Investigate a bug, capture it as a Bug-type spec, and drive it red→green. ALWAYS starts by reproducing the bug with a failing test, then writes the spec and works the test to green. Creates specs/in-progress/bug-<name>/00-overview.md. Use when the user reports a bug, says "/spec-bug", "investigate this bug", "this is broken — find and fix it", or pastes an error/stack trace.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /spec-bug — investigate a bug, prove it with a failing test, fix it
|
|
7
|
+
|
|
8
|
+
This is the **bug** counterpart to `/spec` (which is for **features**, plan-only).
|
|
9
|
+
Unlike `/spec`, this skill is hands-on and test-first: it reproduces the bug as a
|
|
10
|
+
**failing test (RED)**, captures a lean Bug spec, then works the test to **GREEN**.
|
|
11
|
+
|
|
12
|
+
Spec type convention (see `.claude/rules/spec-planning.md`):
|
|
13
|
+
- Bug specs are named `bug-<kebab-name>`; feature specs `feat-<kebab-name>`.
|
|
14
|
+
- Every spec header carries `> **Type:** Bug` (or `Feature`).
|
|
15
|
+
|
|
16
|
+
## 1. Reproduce & isolate (light investigation)
|
|
17
|
+
|
|
18
|
+
Bugs are concrete — confirm, don't over-grill. Establish:
|
|
19
|
+
|
|
20
|
+
- **Repro:** exact steps / input that triggers it. Ask only if you can't derive it.
|
|
21
|
+
- **Expected vs actual:** what *should* happen vs what does.
|
|
22
|
+
- **Scope & blast radius:** which module(s)/endpoint(s)/package; one tenant or all.
|
|
23
|
+
- **Root cause:** read the code, trace it to `file:line`. Compare a working path
|
|
24
|
+
against the broken one (the bug usually lives in the differential). Do NOT
|
|
25
|
+
patch a symptom before you understand the cause.
|
|
26
|
+
|
|
27
|
+
## 2. Write the failing test FIRST (RED) — mandatory
|
|
28
|
+
|
|
29
|
+
Encode the **correct** (expected) behaviour as a test, then run it and confirm it
|
|
30
|
+
**fails for the right reason**:
|
|
31
|
+
|
|
32
|
+
- Put it where the suite already covers that area. Reuse existing test helpers /
|
|
33
|
+
factories; follow the project's test rules (see `.claude/rules/`). Never
|
|
34
|
+
hardcode dates — compute them relative to now.
|
|
35
|
+
- Run it with the project's test command. Quote the red output. A test that
|
|
36
|
+
passes before the fix proves nothing — keep refining the assertion until it
|
|
37
|
+
genuinely captures the bug.
|
|
38
|
+
|
|
39
|
+
## 3. Write the Bug spec
|
|
40
|
+
|
|
41
|
+
Create the spec **folder** `specs/in-progress/bug-<kebab-name>/` with its entry
|
|
42
|
+
point `00-overview.md` (every spec is a folder — never a bare file). A bug is
|
|
43
|
+
usually a single-pass fix, so the `## Fix` block can live directly in
|
|
44
|
+
`00-overview.md`. **If the fix needs phasing** (large/uncertain root cause),
|
|
45
|
+
split it into phase files (`01-<slug>.md`, `02-…`) with a phase index in
|
|
46
|
+
`00-overview.md`, exactly like a feature spec. It starts in `in-progress`
|
|
47
|
+
because work is already underway. Keep it lean:
|
|
48
|
+
|
|
49
|
+
```markdown
|
|
50
|
+
# Bug: <short title>
|
|
51
|
+
|
|
52
|
+
> **Type:** Bug
|
|
53
|
+
> **Status:** In Progress — fixing (red test added)
|
|
54
|
+
> **Author:** <git user.name — who reported/captured it>
|
|
55
|
+
> **Developer:** <git user.name — you, since you're fixing it now>
|
|
56
|
+
> **Raised:** <YYYY-MM-DD (today)>
|
|
57
|
+
> **Area:** <files/modules>
|
|
58
|
+
|
|
59
|
+
## Symptom
|
|
60
|
+
|
|
61
|
+
<observed wrong behaviour + repro steps; paste the error/stack if any>
|
|
62
|
+
|
|
63
|
+
## Root cause
|
|
64
|
+
|
|
65
|
+
<the actual cause, at `file:line`. One paragraph — be specific.>
|
|
66
|
+
|
|
67
|
+
## Failing test (red)
|
|
68
|
+
|
|
69
|
+
<test name + path; what it asserts. How to run it. Paste the red failure line.>
|
|
70
|
+
|
|
71
|
+
## Fix
|
|
72
|
+
|
|
73
|
+
- [ ] <the minimal change that addresses the root cause, not the symptom>
|
|
74
|
+
- [ ] Failing test now passes (GREEN); run the project's typecheck and test
|
|
75
|
+
commands — confirm no regressions.
|
|
76
|
+
- [ ] <any follow-up hardening, or "None">
|
|
77
|
+
|
|
78
|
+
## State log
|
|
79
|
+
|
|
80
|
+
| Date | Status | Folder | By |
|
|
81
|
+
|------|--------|--------|----|
|
|
82
|
+
| <YYYY-MM-DD> | In Progress | in-progress | <developer> |
|
|
83
|
+
|
|
84
|
+
## Changelog
|
|
85
|
+
|
|
86
|
+
- <YYYY-MM-DD> — Bug reproduced; failing test added (red).
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The **State log** is the folder/status audit trail; later transitions
|
|
90
|
+
(`/spec-complete`, `/spec-cancel`) append a row. The **Changelog** is for the
|
|
91
|
+
fix narrative and decisions — keep them separate.
|
|
92
|
+
|
|
93
|
+
## 4. Drive to GREEN
|
|
94
|
+
|
|
95
|
+
- Implement the **minimal, root-cause** fix. Match surrounding code; honour all
|
|
96
|
+
project rules (see `.claude/rules/`).
|
|
97
|
+
- Re-run the failing test → it must pass. Then run the project's typecheck and
|
|
98
|
+
test commands to confirm no regressions. Quote results.
|
|
99
|
+
- Tick the Fix tasks, add a Changelog line (`- <date> — Fixed: <one line>; test green`).
|
|
100
|
+
|
|
101
|
+
If the root cause is large/uncertain and can't be fixed in one pass: keep the red
|
|
102
|
+
test, split the fix into phase files (`01-<slug>.md` …) with a phase index in
|
|
103
|
+
`00-overview.md`, and leave the spec in `in-progress` for `/spec-go` to continue.
|
|
104
|
+
Say so explicitly — don't fake green.
|
|
105
|
+
|
|
106
|
+
## 5. Report
|
|
107
|
+
|
|
108
|
+
Summarise: root cause, the failing→passing test, the fix, and the full test
|
|
109
|
+
result. The spec stays in `in-progress`; suggest `/spec-complete` to verify and
|
|
110
|
+
archive it. Do **not** `git commit` unless the user asks.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-cancel
|
|
3
|
+
description: Cancel a spec — capture the reason, record final progress, stamp the reason on the spec header, then move it into specs/cancelled/. Targets a spec by name (arg) or the spec currently in context. Use when the user says "/spec-cancel", "drop this spec", "we're not doing this spec", or "shelve <spec>".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /spec-cancel — record, stamp a reason, archive a spec
|
|
7
|
+
|
|
8
|
+
## 1. Identify the target spec
|
|
9
|
+
|
|
10
|
+
- Use the name/path argument if given, else the spec **in context**. If unclear,
|
|
11
|
+
ask which spec.
|
|
12
|
+
- Locate it under `specs/` (any bucket — `backlog/`, `in-progress/`, …). Entry point
|
|
13
|
+
is its `00-overview.md`; phases are separate files (`01-<slug>.md`, `02-…`) listed
|
|
14
|
+
in its phase index (legacy specs may be a bare `<name>.md`).
|
|
15
|
+
|
|
16
|
+
## 2. Ask for the cancellation reason — required
|
|
17
|
+
|
|
18
|
+
Ask the user **why** it's being cancelled (e.g. superseded by X, descoped, no
|
|
19
|
+
longer needed, blocked indefinitely). Do not proceed without a reason; capture
|
|
20
|
+
it verbatim/condensed for the header.
|
|
21
|
+
|
|
22
|
+
## 3. Double-check and record progress
|
|
23
|
+
|
|
24
|
+
- Read the overview and every phase file and reconcile task state with reality:
|
|
25
|
+
tick anything that was actually completed before cancelling so the record is
|
|
26
|
+
honest about what landed.
|
|
27
|
+
- Note any partial/abandoned work so it isn't mistaken for unstarted.
|
|
28
|
+
|
|
29
|
+
## 4. Stamp the spec
|
|
30
|
+
|
|
31
|
+
Update the **Status** header in the entry point so the reason is visible at the
|
|
32
|
+
top:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
> **Status:** Cancelled (<YYYY-MM-DD>) — <reason>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Append a **State log** row:
|
|
39
|
+
`| <YYYY-MM-DD> | Cancelled | cancelled | <git user.name> |`.
|
|
40
|
+
|
|
41
|
+
Add a **Changelog** entry:
|
|
42
|
+
`- <YYYY-MM-DD> — Cancelled: <reason>.`
|
|
43
|
+
|
|
44
|
+
## 5. Move to cancelled
|
|
45
|
+
|
|
46
|
+
`mkdir -p specs/cancelled` then **`git mv`** the file or folder:
|
|
47
|
+
`git mv "specs/<bucket>/<name>" "specs/cancelled/<name>"` (preserve history;
|
|
48
|
+
move the whole folder).
|
|
49
|
+
|
|
50
|
+
## 6. Report
|
|
51
|
+
|
|
52
|
+
Confirm the cancellation, the reason recorded, and the new location. Do **not**
|
|
53
|
+
`git commit` unless the user asks.
|
|
54
|
+
|
|
55
|
+
## 7. Offer teardown (opt-in, only if configured)
|
|
56
|
+
|
|
57
|
+
**Only when `specs/.core/env.config.json` exists**, offer — don't force — to
|
|
58
|
+
reclaim the cancelled spec's environment: "Want me to run `/spec-env-down
|
|
59
|
+
<name>` to remove its worktree, stack, volumes, and free its slot?" It respects
|
|
60
|
+
the teardown guards (won't destroy a dirty/unpushed worktree without `--force`).
|
|
61
|
+
If `env.config.json` is absent, skip this entirely — behave exactly as before.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-complete
|
|
3
|
+
description: Finish a spec — verify all phases are genuinely done, update progress, then move it into specs/complete/. Targets a spec by name (arg) or the spec currently in context. Use when the user says "/spec-complete", "mark this spec done", or "this spec is complete".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /spec-complete — verify, finalise, archive a spec
|
|
7
|
+
|
|
8
|
+
## 1. Identify the target spec
|
|
9
|
+
|
|
10
|
+
- Use the name/path argument if given, else the spec **in context**. If unclear,
|
|
11
|
+
ask which spec.
|
|
12
|
+
- Locate the spec folder under `specs/` (usually `specs/in-progress/`). Entry
|
|
13
|
+
point is its `00-overview.md`; phases are separate files (`01-<slug>.md`, `02-…`)
|
|
14
|
+
listed in its phase index (legacy specs may be a bare `<name>.md`).
|
|
15
|
+
|
|
16
|
+
## 2. Double-check progress — don't rubber-stamp
|
|
17
|
+
|
|
18
|
+
Before marking complete, confirm the work is actually finished:
|
|
19
|
+
|
|
20
|
+
- Read every phase file. For each **unchecked** task, check whether it is in fact
|
|
21
|
+
done in the code — tick it (`- [x]`) if so, or surface it if not.
|
|
22
|
+
- Run the project's typecheck and test commands. The suite must be **green** to
|
|
23
|
+
call a spec complete.
|
|
24
|
+
- For a **Bug** spec (`Type: Bug`), confirm the originally-failing test named in
|
|
25
|
+
the spec now passes — that test is the proof the bug is fixed.
|
|
26
|
+
- If genuinely incomplete work remains, **stop and tell the user** rather than
|
|
27
|
+
forcing completion. Offer to finish it (`/spec-go`) or to complete with the
|
|
28
|
+
remaining items explicitly listed as deferred.
|
|
29
|
+
|
|
30
|
+
## 3. Update the spec
|
|
31
|
+
|
|
32
|
+
- Tick all completed tasks in the phase files; flip every finished phase-file
|
|
33
|
+
heading **and** every row in the `00-overview.md` phase index to `✅`.
|
|
34
|
+
- Set the **Status** header in the entry point:
|
|
35
|
+
`> **Status:** Complete (<YYYY-MM-DD>)`.
|
|
36
|
+
- Append a **State log** row:
|
|
37
|
+
`| <YYYY-MM-DD> | Complete | complete | <git user.name> |`.
|
|
38
|
+
- Add a **Changelog** entry:
|
|
39
|
+
`- <YYYY-MM-DD> — Completed; all phases done, tests green.`
|
|
40
|
+
(Note any consciously-deferred items here too.)
|
|
41
|
+
|
|
42
|
+
## 4. Move to complete
|
|
43
|
+
|
|
44
|
+
`mkdir -p specs/complete` then **`git mv`** the file or folder:
|
|
45
|
+
`git mv "specs/in-progress/<name>" "specs/complete/<name>"` (preserve history;
|
|
46
|
+
move the whole folder). The `specs/complete/` folder is the record of finished
|
|
47
|
+
specs — `git log`/the per-spec State log give the completion order.
|
|
48
|
+
|
|
49
|
+
## 5. Report
|
|
50
|
+
|
|
51
|
+
Confirm the move, the final test result, and list anything deferred. Do **not**
|
|
52
|
+
`git commit` unless the user asks.
|
|
53
|
+
|
|
54
|
+
## 6. Integrate onto the base branch (opt-in, only if isolated)
|
|
55
|
+
|
|
56
|
+
**Only when `specs/.core/env.config.json` exists and the spec is on a worktree**
|
|
57
|
+
(it was provisioned by `/spec-go`). Otherwise skip this entirely — a non-isolated
|
|
58
|
+
spec has nothing to land, and `/spec-complete` behaves exactly as before. When it
|
|
59
|
+
applies, offer to land the finished branch on the base branch so the work reaches
|
|
60
|
+
`main` (or your configured `baseBranch`) in one flow:
|
|
61
|
+
|
|
62
|
+
1. **Require a clean worktree.** The completion edits (status flip, the
|
|
63
|
+
`git mv` to `complete/`) must be committed first — integrate refuses a dirty
|
|
64
|
+
tree. If it's dirty, offer `/commit` and **stop**; don't auto-commit.
|
|
65
|
+
2. **Plan + execute.** Run `skitterspec spec-env integrate <name>` and run the
|
|
66
|
+
printed commands **in order**:
|
|
67
|
+
- `git -C <worktree> rebase <base>` — replay the branch onto base.
|
|
68
|
+
- `git -C <mainRepoPath> merge --ff-only <branch>` — fast-forward base.
|
|
69
|
+
On a **rebase conflict** (non-zero exit), run
|
|
70
|
+
`git -C <worktree> rebase --abort`, relay the conflict, and **stop** — leave it
|
|
71
|
+
to the user; do not offer teardown.
|
|
72
|
+
On a **no-op** ("already landed"), just say so and continue.
|
|
73
|
+
3. **Re-test on base.** Run the project's test command from the primary checkout;
|
|
74
|
+
it must be **green** before you call the landing done.
|
|
75
|
+
4. **Report** the landing (base branch, fast-forward result). It **never pushes** —
|
|
76
|
+
mention the user can `git push` the base branch themselves.
|
|
77
|
+
|
|
78
|
+
## 7. Offer teardown (opt-in, only if configured)
|
|
79
|
+
|
|
80
|
+
**Only when `specs/.core/env.config.json` exists**, offer — don't force — to
|
|
81
|
+
reclaim the finished spec's environment: "Want me to run `/spec-env-down <name>`
|
|
82
|
+
to remove its worktree, delete its branch, stack, volumes, and free its slot?"
|
|
83
|
+
Post-integrate the branch is merged into base, so teardown needs **no `--force`**
|
|
84
|
+
and deletes the branch (`git branch -d`) as part of the plan. It still respects
|
|
85
|
+
the guards (won't destroy a dirty or unpushed-and-unmerged worktree without
|
|
86
|
+
`--force`). If `env.config.json` is absent, skip this entirely — behave exactly as
|
|
87
|
+
before.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-env
|
|
3
|
+
description: Provision an isolated environment for a spec — a git worktree on its own branch + a namespaced Docker stack (isolated containers/networks/volumes + a reserved port block), plus an optional editor/terminal opener. Runs `skitterspec spec-env up` and executes the printed git/docker/open commands. Opt-in — needs specs/.core/env.config.json. Use when the user says "/spec-env", "spin up an environment for <spec>", "give this spec its own worktree/stack", or "isolate <spec>".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /spec-env — provision an isolated environment for a spec
|
|
7
|
+
|
|
8
|
+
Give an in-progress spec its own **git worktree** (a sibling directory on its own
|
|
9
|
+
branch, no stashing) + a **namespaced Docker stack** (`COMPOSE_PROJECT_NAME`
|
|
10
|
+
isolates containers/networks/volumes; `PORT_OFFSET` reserves a port block), so N
|
|
11
|
+
specs run side by side and `main` stays clean. An optional `open.command` then
|
|
12
|
+
opens the worktree however you like.
|
|
13
|
+
|
|
14
|
+
This skill is **opt-in**: it only works when `specs/.core/env.config.json` exists
|
|
15
|
+
(copy `env.config.json.example` to adopt it). If it's absent, tell the user how
|
|
16
|
+
to enable it and stop.
|
|
17
|
+
|
|
18
|
+
## 1. Identify the target spec
|
|
19
|
+
|
|
20
|
+
- Use the spec named as an argument, else the spec **currently in context**. If
|
|
21
|
+
neither is clear, ask which spec.
|
|
22
|
+
|
|
23
|
+
## 2. Plan the environment
|
|
24
|
+
|
|
25
|
+
Run the engine — it allocates the slot (idempotent), persists the registry, and
|
|
26
|
+
**prints** the plan (worktree path, branch, project name, port block, the exact
|
|
27
|
+
commands, the `.env` contents, and the opener):
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
skitterspec spec-env up <spec>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
If it reports the feature isn't enabled, relay that and stop — do not hand-roll a
|
|
34
|
+
worktree/stack.
|
|
35
|
+
|
|
36
|
+
## 3. Execute the printed side effects
|
|
37
|
+
|
|
38
|
+
Run the printed commands **in order**, exactly as printed:
|
|
39
|
+
|
|
40
|
+
1. **`git worktree add …`** — creates the sibling worktree on its branch. It is a
|
|
41
|
+
**sibling** of this checkout, **never nested** inside it. If the worktree
|
|
42
|
+
already exists, the engine prints the *attach* form (no `-b`) — do not clobber
|
|
43
|
+
an existing worktree/branch.
|
|
44
|
+
2. **Write the `.env`** — write the printed `.env` contents into the new
|
|
45
|
+
worktree's env file (default `.env`). Do this *after* the worktree exists.
|
|
46
|
+
3. **`docker compose … up -d`** — only printed when Docker is enabled. Brings the
|
|
47
|
+
namespaced stack up in the spec's reserved port block.
|
|
48
|
+
4. **Opener** — if an `open.command` line was printed, run it (e.g. opens the
|
|
49
|
+
worktree in your editor/terminal). Skipped silently when unset.
|
|
50
|
+
5. **Trust the worktree root for this session** — the engine already wrote the
|
|
51
|
+
printed `trusted:` root into `.claude/settings.local.json` (gitignored, so it
|
|
52
|
+
persists for future sessions). That file likely won't hot-reload mid-session,
|
|
53
|
+
so also run `/add-dir <trusted root>` now to lift `Edit`/`Write` prompts for
|
|
54
|
+
the **current** session. (If the engine printed a `trusted: ! …` warning,
|
|
55
|
+
`settings.local.json` isn't valid JSON — fix it, then re-run.)
|
|
56
|
+
|
|
57
|
+
## 4. Report
|
|
58
|
+
|
|
59
|
+
Echo the summary: worktree path, branch, project name, the allocated slot + port
|
|
60
|
+
block, and whether the stack was brought up. **Idempotent** — re-running attaches
|
|
61
|
+
to the existing slot/worktree and never reallocates.
|
|
62
|
+
|
|
63
|
+
Tear down later with `/spec-env-down <spec>`.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-env-down
|
|
3
|
+
description: Tear down a spec's isolated environment — stop and remove its namespaced Docker stack (optionally backing up + dropping volumes), remove its git worktree, and free its slot. Guards refuse teardown on a dirty or unpushed worktree unless --force. Runs `skitterspec spec-env down` and executes the printed commands. Opt-in — needs specs/.core/env.config.json. Use when the user says "/spec-env-down", "tear down <spec>'s environment", "clean up the worktree/stack for <spec>", or "reclaim <spec>'s slot".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /spec-env-down — tear down a spec's isolated environment
|
|
7
|
+
|
|
8
|
+
Reverse `/spec-env`: stop + remove the spec's Docker stack, remove its git
|
|
9
|
+
worktree, and free its slot so the ports/slot are reclaimed. **Volumes are the
|
|
10
|
+
only destructive part** — dropped by default (to reclaim disk) unless
|
|
11
|
+
`--keep-volumes`, and always backed up first when `docker.backupCommand` is set.
|
|
12
|
+
|
|
13
|
+
Opt-in: only works when `specs/.core/env.config.json` exists. If absent, say so
|
|
14
|
+
and stop.
|
|
15
|
+
|
|
16
|
+
## 1. Identify the target spec
|
|
17
|
+
|
|
18
|
+
- Use the spec named as an argument, else the spec **currently in context**. If
|
|
19
|
+
neither is clear, ask which spec.
|
|
20
|
+
|
|
21
|
+
## 2. Plan the teardown
|
|
22
|
+
|
|
23
|
+
Run the engine — it checks the guards, frees the slot, and **prints** the plan:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
skitterspec spec-env down <spec> [--keep-volumes] [--force]
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- **`--keep-volumes`** — keep the stack's data (plain `down`, no backup, no drop).
|
|
30
|
+
- **`--force`** — override the guards below.
|
|
31
|
+
|
|
32
|
+
## 3. Handle a guard block
|
|
33
|
+
|
|
34
|
+
If the CLI reports **blocked** (the worktree has uncommitted changes, or unpushed
|
|
35
|
+
commits that aren't yet merged into the base branch), **relay the reason and
|
|
36
|
+
stop** — do not destroy unreviewed work. Offer the user `--force` (and suggest
|
|
37
|
+
committing/pushing first). Only re-run with `--force` when the user explicitly
|
|
38
|
+
asks. **A branch already merged into the base needs no `--force`** — the unpushed
|
|
39
|
+
guard treats "landed on base" as safe, so a completed spec (post-`/spec-complete`
|
|
40
|
+
integrate) tears down cleanly even with no remote.
|
|
41
|
+
|
|
42
|
+
## 4. Execute the printed side effects
|
|
43
|
+
|
|
44
|
+
When not blocked, run the printed commands **in order**, exactly as printed:
|
|
45
|
+
|
|
46
|
+
1. **Backup** (only when a `docker.backupCommand` is configured and volumes are
|
|
47
|
+
being dropped) — writes a dump under `.spec-env/backups/` before anything is
|
|
48
|
+
destroyed.
|
|
49
|
+
2. **`docker compose … down`** — with `--volumes` unless `--keep-volumes`.
|
|
50
|
+
3. **`git worktree remove …`** — removes the sibling worktree.
|
|
51
|
+
4. **`git branch -d <branch>`** — deletes the spec's branch (freed by the worktree
|
|
52
|
+
removal above). It's `-d` (merged-only), never `-D`: if it reports the branch
|
|
53
|
+
isn't fully merged, **relay that and stop** — don't `-D` it. That only happens
|
|
54
|
+
on a `--force` teardown of unmerged work; the user can delete it by hand if
|
|
55
|
+
they're sure.
|
|
56
|
+
|
|
57
|
+
The slot is already freed by the CLI.
|
|
58
|
+
|
|
59
|
+
## 5. Report
|
|
60
|
+
|
|
61
|
+
Confirm what happened: worktree removed, branch deleted, containers down, volumes
|
|
62
|
+
**dropped|kept**, slot freed, and the backup path (if any). If a `git branch -d`
|
|
63
|
+
was refused (unmerged), say so. If the spec wasn't provisioned / was already torn
|
|
64
|
+
down, the CLI reports a clean **no-op** — relay that; it's not an error.
|