@skitterbyte/skitterspec-jira 0.0.0-stage → 2.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 +1266 -0
- package/README.md +44 -2
- package/assets/claude-md-section.md +85 -0
- package/assets/commands/allow-main.md +33 -0
- package/assets/commands/spec-connect.md +13 -0
- package/assets/commands/spec-live.md +14 -0
- package/assets/commands/spec-remote-review.md +37 -0
- package/assets/commands/spec-skip.md +24 -0
- package/assets/core/SETUP.md +192 -0
- package/assets/core/env.config.json.example +56 -0
- package/assets/core/env.config.md +606 -0
- package/assets/core/gating.config.json.example +4 -0
- package/assets/core/gating.config.md +81 -0
- package/assets/core/jira.config.json.example +18 -0
- package/assets/core/jira.config.md +88 -0
- package/assets/hooks/main-guard.cjs +162 -0
- package/assets/hooks/review-gate.cjs +146 -0
- package/assets/review/page.html +3384 -0
- package/assets/rules/commit-trailers.md +96 -0
- package/assets/rules/negative-checks.md +69 -0
- package/assets/rules/offered-unblocks.md +100 -0
- package/assets/rules/spec-planning.md +702 -0
- package/assets/rules/spec-reports.md +572 -0
- package/assets/skills/no-spec/SKILL.md +249 -0
- package/assets/skills/spec/SKILL.md +714 -0
- package/assets/skills/spec-bug/SKILL.md +585 -0
- package/assets/skills/spec-cancel/SKILL.md +261 -0
- package/assets/skills/spec-complete/SKILL.md +451 -0
- package/assets/skills/spec-diff/SKILL.md +870 -0
- package/assets/skills/spec-hotfix/SKILL.md +607 -0
- package/assets/skills/spec-init/SKILL.md +178 -0
- package/assets/skills/spec-jira-setup/SKILL.md +221 -0
- package/assets/skills/spec-list/SKILL.md +173 -0
- package/assets/skills/spec-next/SKILL.md +678 -0
- package/assets/skills/spec-push/SKILL.md +306 -0
- package/assets/skills/spec-review/SKILL.md +256 -0
- package/assets/skills/spec-reviewed/SKILL.md +284 -0
- package/assets/skills/spec-start/SKILL.md +496 -0
- package/assets/skills/spec-status/SKILL.md +114 -0
- package/assets/skills/spec-sync/SKILL.md +220 -0
- package/assets/skills/spec-to-main/SKILL.md +141 -0
- package/bin/skitterspec-jira.js +68 -0
- package/package.json +40 -4
- package/src/cli.js +5967 -0
- package/src/deprecate.js +138 -0
- package/src/env/bootstrap.js +188 -0
- package/src/env/building.js +143 -0
- package/src/env/classify.js +176 -0
- package/src/env/commitcmd.js +108 -0
- package/src/env/config.js +850 -0
- package/src/env/dev.js +63 -0
- package/src/env/glob.js +34 -0
- package/src/env/hooks.js +226 -0
- package/src/env/hotfix.js +413 -0
- package/src/env/hotfixland.js +302 -0
- package/src/env/integrate.js +167 -0
- package/src/env/live.js +479 -0
- package/src/env/mainguard.js +299 -0
- package/src/env/provision.js +466 -0
- package/src/env/proxy.js +225 -0
- package/src/env/prune.js +119 -0
- package/src/env/registry.js +159 -0
- package/src/env/render.js +17 -0
- package/src/env/resolve.js +716 -0
- package/src/env/review.js +2622 -0
- package/src/env/reviewers/coderabbit.js +228 -0
- package/src/env/reviewers.js +517 -0
- package/src/env/serve.js +1044 -0
- package/src/env/supervise.js +157 -0
- package/src/env/teardown.js +248 -0
- package/src/env/trust.js +87 -0
- package/src/gating.js +155 -0
- package/src/init.js +1150 -0
- package/src/lines-diff.js +114 -0
- package/src/prompts.js +129 -0
- package/src/vendor/jira/adf.js +414 -0
- package/src/vendor/jira/api.js +295 -0
- package/src/vendor/jira/cli-sync.js +1252 -0
- package/src/vendor/jira/commands.js +44 -0
- package/src/vendor/jira/config.js +286 -0
- package/src/vendor/jira/credentials.js +108 -0
- package/src/vendor/jira/dialect.js +45 -0
- package/src/vendor/jira/mcp.js +129 -0
- package/src/vendor/provider-kit/index.js +41 -0
- package/src/vendor/provider-kit/src/adapter.js +23 -0
- package/src/vendor/provider-kit/src/apply.js +207 -0
- package/src/vendor/provider-kit/src/args.js +68 -0
- package/src/vendor/provider-kit/src/assignment.js +277 -0
- package/src/vendor/provider-kit/src/config.js +251 -0
- package/src/vendor/provider-kit/src/credentials.js +404 -0
- package/src/vendor/provider-kit/src/doctor.js +35 -0
- package/src/vendor/provider-kit/src/http.js +63 -0
- package/src/vendor/provider-kit/src/identity.js +93 -0
- package/src/vendor/provider-kit/src/list-assignee.js +71 -0
- package/src/vendor/provider-kit/src/list-rows.js +35 -0
- package/src/vendor/provider-kit/src/md-compare.js +39 -0
- package/src/vendor/provider-kit/src/md-tables.js +94 -0
- package/src/vendor/provider-kit/src/prompt.js +50 -0
- package/src/vendor/provider-kit/src/released.js +219 -0
- package/src/vendor/provider-kit/src/specs.js +248 -0
- package/src/vendor/provider-kit/src/transport.js +22 -0
- package/src/vendor/sync-core/index.js +92 -0
- package/src/vendor/sync-core/src/base.js +81 -0
- package/src/vendor/sync-core/src/compare.js +338 -0
- package/src/vendor/sync-core/src/dialect.js +51 -0
- package/src/vendor/sync-core/src/fields.js +36 -0
- package/src/vendor/sync-core/src/legacy.js +100 -0
- package/src/vendor/sync-core/src/normalize.js +971 -0
- package/src/vendor/sync-core/src/push.js +85 -0
- package/src/vendor/sync-core/src/retarget.js +278 -0
- package/src/vendor/sync-core/src/task-block.js +308 -0
- package/src/vendor/sync-core/src/verify.js +67 -0
- package/src/vendor/sync-core/src/write.js +191 -0
|
@@ -0,0 +1,714 @@
|
|
|
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
|
+
> 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
|
+
|
|
13
|
+
Produce ONE concise spec in `specs/backlog/`. Do not start coding — this skill
|
|
14
|
+
plans only. Implementation happens later via `/spec-start`.
|
|
15
|
+
|
|
16
|
+
Lifecycle (the governing skills) — status in parentheses:
|
|
17
|
+
`/spec` (writes **Ready** when fully groomed, else Draft; backlog) → `/spec-start`
|
|
18
|
+
(In Progress, in-progress; implement phase 1) → `/spec-complete` (Complete) /
|
|
19
|
+
`/spec-cancel` (Cancelled). See `.claude/rules/spec-planning.md`. (There is no
|
|
20
|
+
separate grooming command — `/spec` grills to a Ready spec directly.)
|
|
21
|
+
|
|
22
|
+
## Phase 0 — start from a Jira issue (only when asked)
|
|
23
|
+
|
|
24
|
+
**Only when `specs/.core/jira.config.json` exists** *and* the invocation names an
|
|
25
|
+
issue. Otherwise skip this phase entirely and grill from the user's own words.
|
|
26
|
+
|
|
27
|
+
Two ways in:
|
|
28
|
+
|
|
29
|
+
- **`<ISSUE-REF>`** (`PROJ-123`, an issue URL, or a bare key anywhere in the
|
|
30
|
+
arguments) — adopt that issue.
|
|
31
|
+
- **`--from-issue [query]`** — browse the intake inbox: issues carrying
|
|
32
|
+
`intake.label` (what the web app files under). With a `query`, filter that list
|
|
33
|
+
case-insensitively by title. Show the shortlist and let the user pick one.
|
|
34
|
+
|
|
35
|
+
Then:
|
|
36
|
+
|
|
37
|
+
1. **Exclude what's already adopted.** Run `skitterspec spec-sync linked --json`
|
|
38
|
+
and drop any issue whose identifier is already stamped on a spec. If the user
|
|
39
|
+
named such an issue directly, **stop** and point them at that spec — one issue
|
|
40
|
+
never becomes two specs.
|
|
41
|
+
2. **Read the issue** with the discovered issue-read tool (`getJiraIssue`):
|
|
42
|
+
title, description, labels, reporter, URL. If Jira isn't connected, say so
|
|
43
|
+
and offer to carry on without it — a spec written from the user's own
|
|
44
|
+
description is still a spec.
|
|
45
|
+
3. **Route the issue to the right skill.** Match the issue's labels
|
|
46
|
+
(case-insensitively) against two lists, **checking `hotfixLabels` first**:
|
|
47
|
+
|
|
48
|
+
- **`intake.hotfixLabels`** → this is broken in **production**, so it needs a
|
|
49
|
+
fix against the released version, not `main`. Say so, name the matching
|
|
50
|
+
label, and tell the user to run **`/spec-hotfix <ISSUE-REF>`** — then stop.
|
|
51
|
+
- **`intake.bugLabels`** → a bug report, not a feature request. Say so, name
|
|
52
|
+
the label, and tell the user to run **`/spec-bug <ISSUE-REF>`** — then stop,
|
|
53
|
+
without authoring a Feature spec.
|
|
54
|
+
|
|
55
|
+
**Hotfix wins when an issue carries both**, and deliberately: production is the
|
|
56
|
+
more specific destination, and the two mistakes are not equally costly. Routing
|
|
57
|
+
a prod issue to `/spec-bug` produces a fix that lands on `main` and never
|
|
58
|
+
reaches the running version — discovered only when someone asks why it hasn't
|
|
59
|
+
shipped. The reverse is a hotfix branch for something that could have waited,
|
|
60
|
+
which is merely wasteful.
|
|
61
|
+
|
|
62
|
+
With a list unset, nothing routes through it; with both unset every issue is
|
|
63
|
+
treated as a feature request, exactly as before.
|
|
64
|
+
|
|
65
|
+
**Which checks run depends on where you are**, because a skip is about not
|
|
66
|
+
bouncing someone to the skill they are already in — not about ignoring an
|
|
67
|
+
escalation:
|
|
68
|
+
|
|
69
|
+
- **In `/spec`** — both checks run.
|
|
70
|
+
- **In `/spec-bug`** — the bug check is skipped (it would route you to
|
|
71
|
+
yourself), but the **hotfix check still runs**. A bug report labelled for
|
|
72
|
+
production is not "already handled" by being in the bug path: `/spec-bug`
|
|
73
|
+
fixes on `main`, and prod would stay broken. Say so and hand off.
|
|
74
|
+
- **In `/spec-hotfix`** — both are skipped. It is already the most specific
|
|
75
|
+
destination; there is nowhere left to route.
|
|
76
|
+
|
|
77
|
+
Then adopt the issue and reproduce it as usual: the issue body is your repro
|
|
78
|
+
material, and the failing test comes before the spec exactly as normal.
|
|
79
|
+
4. **Seed, don't skip, the grill.** The issue's title becomes the working spec
|
|
80
|
+
title and its description the starting material for **Problem** — or
|
|
81
|
+
**Symptom** in a bug or hotfix spec, which is where a report belongs. Quote the
|
|
82
|
+
reporter's words rather than paraphrasing them away. Note the reporter and the
|
|
83
|
+
issue URL for context. Everything after this runs exactly as normal: an issue
|
|
84
|
+
is a *request*, not a groomed spec, so grill it as hard as anything else.
|
|
85
|
+
|
|
86
|
+
**In `/spec-hotfix`, also mine the issue for a version.** Any release-shaped
|
|
87
|
+
string in the report is a *suggestion* for the base tag, offered when the skill
|
|
88
|
+
asks which version prod is running — never used as a default. The reporter's
|
|
89
|
+
version is the one they saw the bug on, which is often not what is deployed.
|
|
90
|
+
|
|
91
|
+
### Adopting the issue
|
|
92
|
+
|
|
93
|
+
The issue **becomes** the spec's issue — it is not copied and no second issue is
|
|
94
|
+
minted. This is identical in `/spec`, `/spec-bug` and `/spec-hotfix`; only *when*
|
|
95
|
+
it happens differs (`/spec` writes the spec in Phase B, `/spec-bug` in its step 4,
|
|
96
|
+
`/spec-hotfix` in its step 5). Once the spec file exists:
|
|
97
|
+
|
|
98
|
+
- **Stamp `jira_identifier` and `jira_url`** in `00-overview.md` frontmatter
|
|
99
|
+
from the adopted issue. That is the whole link: every later skill
|
|
100
|
+
(`/spec-push`, `/spec-status`, `/spec-start`) keys off it being present.
|
|
101
|
+
- **Adoption is not a mint.** The issue was filed somewhere deliberately — it
|
|
102
|
+
stays where it is, whatever `jira.projectKey` says, and nothing re-homes it.
|
|
103
|
+
- **Do not write a base sidecar.** Leaving `sync.baseDir` empty for this spec is
|
|
104
|
+
what makes the **linking push** send the spec over the reporter's original
|
|
105
|
+
description (an **update** to the existing issue, plus a subtask per phase).
|
|
106
|
+
Recording a snapshot here would declare the mirror already in sync and strand
|
|
107
|
+
the issue showing the raw report forever.
|
|
108
|
+
- **Preserve the original, before anything replaces it.** Run this the moment
|
|
109
|
+
the spec file exists and **before the linking push**:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
skitterspec spec-sync preserve <spec>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
It posts the issue's current description onto the issue as a comment — the one
|
|
116
|
+
surface one-way sync never touches, so no push can clobber it. On the API path
|
|
117
|
+
it reads the description itself; without credentials it prints the body and
|
|
118
|
+
the marker, and you post it with the discovered Jira comment tool after
|
|
119
|
+
checking the comments for that marker.
|
|
120
|
+
|
|
121
|
+
**The ordering is the whole correctness condition.** Run before the push, this
|
|
122
|
+
keeps what the reporter filed. Run after it, it would keep the generated spec
|
|
123
|
+
and report success — which is why it is a step of its own here rather than a
|
|
124
|
+
line in the push sequence. The engine warns when it can tell it is late, but it
|
|
125
|
+
cannot always tell.
|
|
126
|
+
|
|
127
|
+
**It never fails the adoption.** A project that set
|
|
128
|
+
`intake.preserveOriginal: false`, an unreachable Jira, an issue with no
|
|
129
|
+
description, a comment Jira refused — every one of them exits 0 and says so.
|
|
130
|
+
Relay what it printed and carry on.
|
|
131
|
+
- **Say what will happen** in the finish-up message. The linking step runs right
|
|
132
|
+
after the spec is written, so the issue's description is replaced by the spec
|
|
133
|
+
**then** — not on some later manual push. Say both halves: the description
|
|
134
|
+
becomes the spec, **and** the original is preserved as a comment on the same
|
|
135
|
+
issue, so the reporter can still read what they wrote.
|
|
136
|
+
|
|
137
|
+
**Do not send anyone to the issue's history for it.** This used to say the
|
|
138
|
+
tracker keeps the original there, and that is true and useless: history is a
|
|
139
|
+
diff viewer nobody opens, it is not quotable, and it degrades to "it is in
|
|
140
|
+
there somewhere". The comment is the answer, and the other half is the spec's
|
|
141
|
+
own **Problem** (or **Symptom**) section quoting the reporter.
|
|
142
|
+
|
|
143
|
+
## Phase A — reach a clear shared understanding (grill first)
|
|
144
|
+
|
|
145
|
+
Interview the user until requirement AND proposed solution are unambiguous. Do
|
|
146
|
+
not write the spec until this is resolved.
|
|
147
|
+
|
|
148
|
+
- Break the problem into **distinctive areas** and work them in logical order,
|
|
149
|
+
resolving dependencies between decisions one at a time.
|
|
150
|
+
- **Batch independent questions; sequence dependent ones.** When several
|
|
151
|
+
questions do not affect each other's answers, put them to the user together
|
|
152
|
+
(up to four at once — use the harness's multi-question ask tool where it has
|
|
153
|
+
one) rather than spending a round trip on each. When an answer would change
|
|
154
|
+
what you ask next, ask that one alone and wait for it. Give your
|
|
155
|
+
**recommended answer** either way.
|
|
156
|
+
- If a question can be answered by **reading the codebase, read it** instead of
|
|
157
|
+
asking. Verify endpoints/models/files actually exist before relying on them.
|
|
158
|
+
- Cover, at minimum, the areas that apply:
|
|
159
|
+
1. **Problem & why** — what's broken/missing, who feels it, why now.
|
|
160
|
+
2. **Scope & non-goals** — explicit out-of-scope items.
|
|
161
|
+
3. **Affected areas** — concrete files/modules/packages this touches.
|
|
162
|
+
4. **Proposed solution shape** — the chosen approach and the alternatives
|
|
163
|
+
rejected, with the reason (this becomes "Decisions").
|
|
164
|
+
5. **Data / API impact** — schema/model changes, new endpoints, and
|
|
165
|
+
**backward compatibility** (additive = safe; breaking = needs explicit
|
|
166
|
+
permission and coordination).
|
|
167
|
+
6. **Security & multi-tenancy** — authz, tenant scoping, untrusted input.
|
|
168
|
+
7. **Edge cases & failure modes.**
|
|
169
|
+
8. **Testing approach** — what proves each phase correct.
|
|
170
|
+
9. **Isolation stack** *(only when `specs/.core/env.config.json` exists)* — does
|
|
171
|
+
this spec touch the DB / stateful services (so its worktree needs a Docker
|
|
172
|
+
stack), or is a plain worktree enough? Default `worktree`; escalate to
|
|
173
|
+
`worktree + docker` only when it must. This sets the `> **Stack:**` header
|
|
174
|
+
that `/spec-start` acts on (it can be escalated later). Skip when isolation
|
|
175
|
+
isn't enabled — leave the default `worktree`.
|
|
176
|
+
10. **Release gating** *(only when `specs/.core/gating.config.json` exists)* —
|
|
177
|
+
should this ship behind a feature flag, or land live?
|
|
178
|
+
**Offer, don't impose**: the user decides and you raise it, so a spec
|
|
179
|
+
never reaches
|
|
180
|
+
`/spec-complete` with the question unasked. Cite the project's own
|
|
181
|
+
`guidance` path from that config when it names one — skitterspec knows
|
|
182
|
+
nothing about how this project does flags, and must not guess. Record the
|
|
183
|
+
answer **either way**: a flag name, or `none: <one-line reason>`. "No" is a
|
|
184
|
+
decision and belongs in the header; silence is not. Skip entirely when the
|
|
185
|
+
config is absent — that project does not use flags.
|
|
186
|
+
11. **Open questions** — anything still undecided.
|
|
187
|
+
|
|
188
|
+
Stop grilling when there are no unresolved branches that would change the spec.
|
|
189
|
+
Briefly play back the agreed understanding before writing.
|
|
190
|
+
|
|
191
|
+
## Phase B — write the spec
|
|
192
|
+
|
|
193
|
+
This skill is for **features**. For bugs, use `/spec-bug` (test-first, red→green).
|
|
194
|
+
|
|
195
|
+
### Write it in its own worktree
|
|
196
|
+
|
|
197
|
+
**Only when the project has per-spec isolation** (`specs/.core/env.config.json`
|
|
198
|
+
present). Without it there is no worktree to make and this section does not
|
|
199
|
+
apply — write the folder where you are standing, exactly as before.
|
|
200
|
+
|
|
201
|
+
**Provision before you write, not after.** Grilling put nothing on disk and the
|
|
202
|
+
spec's name is settled by the time Phase A ends, so this is the one moment where
|
|
203
|
+
a worktree costs nothing to obtain and everything is still ahead of it:
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
skitterspec spec-env up <name> --docs
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Run the commands it prints under `to provision, run:`, and the
|
|
210
|
+
`skitterspec spec-env bootstrap <name> --docs` under `then, run:` where there is
|
|
211
|
+
one (it seeds the gitignored files, nothing more). Then move this session into
|
|
212
|
+
the worktree with a plain `cd` — the Bash working directory persists between
|
|
213
|
+
calls, so from here on the spec is written on its own branch. Confirm the move landed rather than
|
|
214
|
+
reading silence as success (`.claude/rules/negative-checks.md` rule 1):
|
|
215
|
+
`skitterspec spec-env resolve` with no argument must name this spec. If it does
|
|
216
|
+
not, say so and write the spec where you are standing instead; a spec in the
|
|
217
|
+
wrong tree is worse than a spec with no worktree.
|
|
218
|
+
|
|
219
|
+
**`--docs` is what makes this cheap.** It skips the `setup` commands and the
|
|
220
|
+
Docker stack — everything whose only purpose is making a tree *runnable* — so
|
|
221
|
+
provisioning a worktree to write markdown in is a `git worktree add` and nothing
|
|
222
|
+
else. `/spec-start` re-runs `up` over the same worktree without the flag, and the
|
|
223
|
+
setup runs then, at the first moment the tree is used for code.
|
|
224
|
+
|
|
225
|
+
**Why the base branch is no longer where this happens.** `main` is where work
|
|
226
|
+
**lands**, not where it happens. Authoring on it meant the spec sat uncommitted
|
|
227
|
+
there for as long as Phase C2's page went unanswered — which is unbounded by
|
|
228
|
+
design, because a reader walking away from a diff is the normal case — and a
|
|
229
|
+
release could not be cut through it. The verdict lands the spec instead, so
|
|
230
|
+
`main` gains it as one commit and is never dirty on the way.
|
|
231
|
+
|
|
232
|
+
**A spec written in ANOTHER spec's worktree is still the mistake it always was**,
|
|
233
|
+
and this section does not soften that. It physically lives on that branch: not on
|
|
234
|
+
`main` until that spec lands, invisible to anyone listing `specs/backlog/`
|
|
235
|
+
meanwhile, and cancelled along with its host. Committing it there also mis-stamps
|
|
236
|
+
the ticket trailer, which is resolved from the branch (see
|
|
237
|
+
`.claude/rules/commit-trailers.md`, installed with a ticketing provider). The
|
|
238
|
+
difference is whose worktree: **its own** is now the normal path, and someone
|
|
239
|
+
else's is the accident.
|
|
240
|
+
|
|
241
|
+
So if Phase A ran inside another spec's worktree — most likely because a design
|
|
242
|
+
question came up part-way through implementing it — the provision above is the
|
|
243
|
+
fix rather than something to warn about: it moves the session out of that tree
|
|
244
|
+
and into this spec's own. Where isolation is off and there is no worktree to
|
|
245
|
+
move to, **warn, don't refuse**, and say the trailer for that commit wants
|
|
246
|
+
`spec-sync ref <new-spec-name>` rather than the bare form.
|
|
247
|
+
|
|
248
|
+
- **Every spec is a folder** — never a bare file, even for a one-line change:
|
|
249
|
+
`specs/backlog/feat-<kebab-name>/`. Create it with `mkdir -p`.
|
|
250
|
+
- The entry point is **always `00-overview.md`** — the index/dashboard for the
|
|
251
|
+
spec. It holds the header block, Problem, Decisions, Solution overview, the
|
|
252
|
+
**phase index** (a table linking to each phase file), Open questions, State
|
|
253
|
+
log, and Changelog. It does **not** hold the per-phase task lists.
|
|
254
|
+
- **Each phase is its own file** — `01-<phase-slug>.md`, `02-<phase-slug>.md`, …
|
|
255
|
+
numbered in execution order; the slug is a short kebab description of the phase
|
|
256
|
+
goal (e.g. `01-data-model.md`, `02-api-endpoints.md`). The phase file holds
|
|
257
|
+
that phase's goal, its task checkboxes (tests included), and any phase-specific
|
|
258
|
+
notes. **Even a single-phase spec gets `01-….md`** — never lump phase tasks
|
|
259
|
+
into `00-overview.md`. This keeps each phase easy to dive into on its own.
|
|
260
|
+
- Choose a short kebab-case name and **prefix it `feat-`** (the bug counterpart
|
|
261
|
+
uses `bug-`).
|
|
262
|
+
|
|
263
|
+
Use this template (keep it **as concise as possible** — no filler, no restating
|
|
264
|
+
the codebase, link rather than duplicate):
|
|
265
|
+
|
|
266
|
+
```markdown
|
|
267
|
+
# <Feature title>
|
|
268
|
+
|
|
269
|
+
> **Type:** Feature
|
|
270
|
+
> **Name:** feat-<kebab-name> (the spec folder name — the handle you paste into `/spec-start`)
|
|
271
|
+
> **Status:** Ready — not started
|
|
272
|
+
> **Author:** <git user.name — `git config user.name`>
|
|
273
|
+
> **Developer:** —
|
|
274
|
+
> **Raised:** <YYYY-MM-DD (today)>
|
|
275
|
+
> **Area:** <comma-separated files/modules this touches>
|
|
276
|
+
> **Stack:** <worktree — or "worktree + docker" if it touches the DB/stateful
|
|
277
|
+
> services; only acted on when isolation is enabled — see Phase A item 9>
|
|
278
|
+
> **Gating:** <flag name — or "none: <one-line reason>". Only when release gating
|
|
279
|
+
> is configured; omit the line entirely otherwise. An empty value or a bare
|
|
280
|
+
> "none" is not a valid outcome — see Phase A item 10>
|
|
281
|
+
|
|
282
|
+
## Problem
|
|
283
|
+
|
|
284
|
+
<2–6 sentences: what's wrong/missing and why it matters. No fluff.>
|
|
285
|
+
|
|
286
|
+
## Decisions
|
|
287
|
+
|
|
288
|
+
<Numbered, confirmed decisions from Phase A. Each: the choice + one-line why,
|
|
289
|
+
and the rejected alternative when it sharpens the choice. This is the heart of
|
|
290
|
+
the spec — be specific.>
|
|
291
|
+
|
|
292
|
+
## Solution overview
|
|
293
|
+
|
|
294
|
+
<Short prose or bullets describing the chosen shape end-to-end. Optional small
|
|
295
|
+
schema/grammar/output snippets where they remove ambiguity.>
|
|
296
|
+
|
|
297
|
+
## Impact
|
|
298
|
+
|
|
299
|
+
<The concrete surfaces this spec touches — the scannable blast radius, so a
|
|
300
|
+
reader can eyeball where the spec got something wrong without reading prose.
|
|
301
|
+
`Change` is `add` · `update` · `remove`. `Surface` is guided-but-open: use
|
|
302
|
+
values like Endpoint, Route/UI, Schema/model, DB table/migration, Domain object,
|
|
303
|
+
Service, CLI command, Config key, Skill/rule, Business rule — or whatever fits
|
|
304
|
+
this project (skitterspec itself is a CLI with no HTTP surface). Keep `Detail`
|
|
305
|
+
terse — names/signatures, not sentences. List **only** surfaces that actually
|
|
306
|
+
change; the heading is always present, but if nothing external changes write the
|
|
307
|
+
single line below instead of an empty table.>
|
|
308
|
+
|
|
309
|
+
| Surface | Change | Detail |
|
|
310
|
+
|---------|--------|--------|
|
|
311
|
+
| <e.g. Endpoint> | add | <e.g. POST /orders> |
|
|
312
|
+
| <e.g. DB> | update | <e.g. orders (+status col)> |
|
|
313
|
+
|
|
314
|
+
<_No external surface changes — internal refactor only._ — use this line in
|
|
315
|
+
place of the table when the spec touches no external surface.>
|
|
316
|
+
|
|
317
|
+
## Phases
|
|
318
|
+
|
|
319
|
+
Each phase lives in its own file in this folder. Status: ⬜ not started ·
|
|
320
|
+
🔄 in progress · ✅ done.
|
|
321
|
+
|
|
322
|
+
| # | Phase | Status | File |
|
|
323
|
+
|---|-------|--------|------|
|
|
324
|
+
| 1 | <goal> | ⬜ | [01-<phase-slug>.md](01-<phase-slug>.md) |
|
|
325
|
+
| 2 | <goal> | ⬜ | [02-<phase-slug>.md](02-<phase-slug>.md) |
|
|
326
|
+
|
|
327
|
+
## Open questions
|
|
328
|
+
|
|
329
|
+
- [ ] <anything deferred — or "None">
|
|
330
|
+
|
|
331
|
+
## State log
|
|
332
|
+
|
|
333
|
+
| Date | Status | Folder | By |
|
|
334
|
+
|------|--------|--------|----|
|
|
335
|
+
| <YYYY-MM-DD> | Ready | backlog | <author> |
|
|
336
|
+
|
|
337
|
+
## Changelog
|
|
338
|
+
|
|
339
|
+
- <YYYY-MM-DD> — Spec created.
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Then create **one file per phase** (`01-<phase-slug>.md`, `02-…`, in execution
|
|
343
|
+
order). Each phase file uses this template:
|
|
344
|
+
|
|
345
|
+
```markdown
|
|
346
|
+
# Phase 1 — <goal> ⬜
|
|
347
|
+
|
|
348
|
+
> Spec: [00-overview.md](00-overview.md) · **Status:** Not started
|
|
349
|
+
|
|
350
|
+
**Goal:** <one line — what this phase delivers and how it's proven>.
|
|
351
|
+
|
|
352
|
+
## Tasks
|
|
353
|
+
|
|
354
|
+
- [ ] <clear, verb-first task>
|
|
355
|
+
- [ ] <clear, verb-first task>
|
|
356
|
+
- [ ] Add/extend tests covering this phase; run the project's typecheck and
|
|
357
|
+
test commands (see `.claude/rules/spec-planning.md`) — green before the
|
|
358
|
+
phase is done.
|
|
359
|
+
|
|
360
|
+
## Notes
|
|
361
|
+
|
|
362
|
+
<Phase-specific decisions, gotchas, or context. Delete if empty.>
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
Keep the `00-overview.md` phase index and the phase files in sync: the index row
|
|
366
|
+
is the one-line summary + status; the phase file is the detail.
|
|
367
|
+
|
|
368
|
+
The **State log** is the audit trail of folder/status transitions — every
|
|
369
|
+
lifecycle skill (`/spec-start`, `/spec-complete`, `/spec-cancel`) appends one row
|
|
370
|
+
when it moves the spec. The **Changelog** is for decisions and course-corrections
|
|
371
|
+
only — keep the two separate.
|
|
372
|
+
|
|
373
|
+
Rules for the spec body:
|
|
374
|
+
|
|
375
|
+
- **Every phase is independently shippable and ends with tests.** A phase is
|
|
376
|
+
not "done" until its tests are written and the suite is green. Bake a test
|
|
377
|
+
task into each phase — never a separate "testing phase" at the end only.
|
|
378
|
+
- **Tasks are checkboxes** (`- [ ]`), clear, verb-first, and granular enough to
|
|
379
|
+
finish in one session. They live in the **phase files**, not the overview. Use
|
|
380
|
+
`⬜`/`🔄`/`✅` on each phase-file heading and mirror it in the `00-overview.md`
|
|
381
|
+
phase index.
|
|
382
|
+
- **Honour project conventions** when writing tasks — reference the relevant
|
|
383
|
+
`.claude/rules/*.md` rather than re-explaining them.
|
|
384
|
+
-
|
|
385
|
+
**The `## Impact` table is derived from Phase A items 3 (Affected areas) & 5 (Data/API impact)**
|
|
386
|
+
— a structured place to record what those already surface, not new grilling.
|
|
387
|
+
It is the scannable substitute for spelling impact out in prose: name the
|
|
388
|
+
surfaces (endpoints, schemas, DB tables, domain objects, routes, business
|
|
389
|
+
rules) instead of describing them, keep `Detail` terse, and let it — not
|
|
390
|
+
paragraphs — carry the blast radius. It complements the `Area:` header
|
|
391
|
+
(files) by naming behavioural surfaces.
|
|
392
|
+
- **Changelog** is mandatory and lives in the spec. Every later decision or
|
|
393
|
+
course-correction gets a dated one-line entry. Convert relative dates to
|
|
394
|
+
absolute.
|
|
395
|
+
- Keep it tight. If a section adds no information, delete it.
|
|
396
|
+
|
|
397
|
+
## Phase C — finish up
|
|
398
|
+
|
|
399
|
+
Decide the status: **`Ready`** in `backlog` when grilling in Phase A resolved the
|
|
400
|
+
open questions, `Draft` when you deliberately left some unresolved. Either way
|
|
401
|
+
the next step is `/spec-start`. The Report section below is where all of that
|
|
402
|
+
reaches the user — do not narrate it here as well.
|
|
403
|
+
|
|
404
|
+
## Phase C2 — render the spec, then wait for the verdict
|
|
405
|
+
|
|
406
|
+
**Only when the project has per-spec isolation** (`specs/.core/env.config.json`
|
|
407
|
+
present). Without it there is no page and this phase does not exist — skip it in
|
|
408
|
+
silence rather than explaining an absence.
|
|
409
|
+
|
|
410
|
+
A spec is the one artefact whose whole purpose is to be
|
|
411
|
+
**read before work begins**, and until now it was the only one with no reading
|
|
412
|
+
surface: `/spec`
|
|
413
|
+
finished, the spec sat uncommitted, and `/spec-start` had to point that out and
|
|
414
|
+
commit it as a side effect of provisioning. So this phase ends where every other
|
|
415
|
+
phase of the lifecycle ends — on a page, in a verdict.
|
|
416
|
+
|
|
417
|
+
```
|
|
418
|
+
skitterspec spec-env review <spec> --docs --buttons authoring
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
`--docs` reads the spec's own documents from the tree you are standing in, which
|
|
422
|
+
after Phase B is **this spec's own worktree**. It renders
|
|
423
|
+
**this spec's documents and nobody else's**: the `owned` half of
|
|
424
|
+
`spec-env stage` is what supplies the file set, and it stays load-bearing even
|
|
425
|
+
now that the tree holds one spec — a project's `spec.companionPaths` and a
|
|
426
|
+
hand-edited `specs/.core/` both land in the same tree, and only the spec's own
|
|
427
|
+
documents belong under this verdict.
|
|
428
|
+
|
|
429
|
+
**This is free.** The engine reads git and splices text into a template; the
|
|
430
|
+
diff never passes through you.
|
|
431
|
+
|
|
432
|
+
**Never pass `--run-reviewers` here.** A spec is prose, and the reviewers
|
|
433
|
+
`review.reviewers` names read code — spending a rate-limited review on a
|
|
434
|
+
paragraph buys nothing. The engine refuses it on a `--docs` render whatever this
|
|
435
|
+
skill asks for, so this is a note about intent rather than a guard you are
|
|
436
|
+
holding: do not add the flag on the assumption that it was an oversight.
|
|
437
|
+
|
|
438
|
+
**Render nothing when nothing was written.** A `⏸` run — grilling that never
|
|
439
|
+
reached a shared understanding — has no spec to show, and must not ask for a
|
|
440
|
+
verdict on one.
|
|
441
|
+
|
|
442
|
+
**Arm nothing.** There is no `spec-env review arm` in this path, and that is a
|
|
443
|
+
decision rather than an omission: the gate asserts that *a phase which ended*
|
|
444
|
+
owes an answer, and a backlog spec owes no phase. A `/spec` run must leave
|
|
445
|
+
`spec-env review gate --check` exiting 0.
|
|
446
|
+
|
|
447
|
+
**And walking away from this page now costs nobody anything**, which is a
|
|
448
|
+
stronger reason than the one that used to sit here. It read *"the spec is simply
|
|
449
|
+
still uncommitted, which `/spec-start` already handles"* — true, and a
|
|
450
|
+
concession: an uncommitted spec meant a dirty base branch, which is everyone's
|
|
451
|
+
problem, so "arm nothing" was tolerating a mess rather than describing a clean
|
|
452
|
+
state. Since Phase B the unanswered spec sits on its own branch in its own
|
|
453
|
+
worktree, where it is in nothing's way: no release is blocked, no other spec has
|
|
454
|
+
to replay over it, and it is still exactly where it was tomorrow morning.
|
|
455
|
+
|
|
456
|
+
### The two endings this page offers
|
|
457
|
+
|
|
458
|
+
`--buttons authoring` offers `Commit & Start` and `Commit` in place of the
|
|
459
|
+
committing pair, because "commit and build the next phase" is meaningless for a
|
|
460
|
+
spec with no phase in flight.
|
|
461
|
+
|
|
462
|
+
- **`commit-start`** — hand off to `review.commitWith` (`/commit` by default),
|
|
463
|
+
passing the pathspec the render reported on `docs.paths`; **land it** (below);
|
|
464
|
+
then **keep the worktree** and run **`/spec-start <name>`**, and **stop there**.
|
|
465
|
+
It never completes or tears anything down, exactly as `commit-continue` stops
|
|
466
|
+
after `/spec-next`. This is the `commit && /spec-start` that was typed by hand.
|
|
467
|
+
- **`commit`** — the same commit and the same land, then
|
|
468
|
+
**tear the worktree down** and finish. The spec stays `Ready` in `backlog` —
|
|
469
|
+
on the base branch, where anyone can see it — ready for a `/spec-start`
|
|
470
|
+
whenever it is wanted.
|
|
471
|
+
|
|
472
|
+
**Both committing verdicts land, and that is what keeps the backlog findable.**
|
|
473
|
+
`ls specs/backlog/` is how specs are found, and a folder bucket is only the truth
|
|
474
|
+
on the branch you are standing on — so a spec left on its own branch would be
|
|
475
|
+
invisible to everyone, including the next `/spec` run. The commit goes on the
|
|
476
|
+
branch and then the branch goes onto the base:
|
|
477
|
+
|
|
478
|
+
```
|
|
479
|
+
skitterspec spec-env integrate <name>
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
It plans a rebase onto the base branch in the worktree, then a
|
|
483
|
+
`merge --ff-only` in the primary checkout — run the commands it prints. It
|
|
484
|
+
refuses on a dirty tree, which is correct here: the commit ran first, so anything
|
|
485
|
+
still uncommitted at this point is not this spec's and the land must not proceed.
|
|
486
|
+
|
|
487
|
+
**Do not run its after-land section.** Where the plan ends with
|
|
488
|
+
`then, in the primary checkout (<path>), run:`, those are the project's
|
|
489
|
+
`afterLand` commands — a data migration, an install — and they exist for code
|
|
490
|
+
that landed. This land is documents only, so it changes nothing they would
|
|
491
|
+
catch up on; `/spec-complete`, `/spec-to-main` and `/no-spec` run them.
|
|
492
|
+
|
|
493
|
+
**If the rebase conflicts, stop and say so.** It is unlikely on a
|
|
494
|
+
documents-only branch and not impossible — two specs authored at once can both
|
|
495
|
+
touch `specs/.core/`. Run `git rebase --abort`, leave the commit sitting on the
|
|
496
|
+
branch, and report `❌` with the conflict: there is a standing worktree to clear,
|
|
497
|
+
which is what separates `❌` from `⏸`. Never resolve someone else's conflict to
|
|
498
|
+
get the land through.
|
|
499
|
+
|
|
500
|
+
**The worktree lifetime follows the verdict, and the asymmetry is deliberate.**
|
|
501
|
+
`commit-start` keeps it because you are carrying straight on, and `/spec-start`
|
|
502
|
+
re-runs `up` and `bootstrap` over it without `--docs`, which is where the setup commands
|
|
503
|
+
Phase B skipped finally run. Plain `commit` tears it down with
|
|
504
|
+
`skitterspec spec-env down <name>`, because a spec parked in the backlog should
|
|
505
|
+
hold no worktree and no `node_modules`; `/spec-start` provisions from scratch
|
|
506
|
+
whenever it is wanted. Always-keep would leave five backlog specs holding five
|
|
507
|
+
checkouts, and always-teardown would have `commit-start` re-provision seconds
|
|
508
|
+
after destroying the tree it needed.
|
|
509
|
+
- **`changes`** — work the notes into the spec, record a resolution for each one
|
|
510
|
+
so the next render shows it struck through with what changed, then
|
|
511
|
+
**re-render, and wait again**. The reader is still holding a decision, so
|
|
512
|
+
ending the turn and
|
|
513
|
+
making them type `/spec-diff` would reopen the loop this exists to close.
|
|
514
|
+
- **`discuss`** — report and talk. Claim nothing, change nothing.
|
|
515
|
+
|
|
516
|
+
**Take the pathspec from the render, not from the tree.** A checkout is shared,
|
|
517
|
+
so the set of this spec's uncommitted documents can differ between the render and
|
|
518
|
+
the verdict — and the reader's conclusion is about what the page showed them.
|
|
519
|
+
|
|
520
|
+
### Then wait for it
|
|
521
|
+
|
|
522
|
+
**The wait is a command. Do not write one.**
|
|
523
|
+
|
|
524
|
+
1. **Note the moment you start waiting**, as an ISO timestamp. That instant is
|
|
525
|
+
the whole scope of what you may claim.
|
|
526
|
+
2. **Run the engine's wait, and end your turn** — under the harness's
|
|
527
|
+
persistent watch primitive where one exists, else in the background
|
|
528
|
+
(`.claude/rules/spec-reports.md` carries the preference):
|
|
529
|
+
|
|
530
|
+
```
|
|
531
|
+
skitterspec spec-env review wait <spec> --since <the timestamp>
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
It takes no timeout unless you pass one, and you must not pass one: a reader
|
|
535
|
+
who walks away from a spec is the normal case, and a bounded watch once lost a
|
|
536
|
+
verdict to a lunch break.
|
|
537
|
+
3. **On waking, let the engine pick:**
|
|
538
|
+
|
|
539
|
+
**A watch that dies is re-armed on the same window**, silently and bounded by
|
|
540
|
+
the age of that window — `.claude/rules/spec-reports.md` carries the contract,
|
|
541
|
+
including when to stop and what the banner says instead. Do not restate it
|
|
542
|
+
here.
|
|
543
|
+
|
|
544
|
+
```
|
|
545
|
+
skitterspec spec-env review <spec> --docs --claim-since <the timestamp> --json
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
It claims the one pass that arrived inside the window, acts on nothing when
|
|
549
|
+
none did, and refuses to choose when two did.
|
|
550
|
+
4. **Route on the verdict** as above.
|
|
551
|
+
|
|
552
|
+
**Where the page is `file://`** — the engine could not serve — there is no server
|
|
553
|
+
to POST to, so the pass is copied and pasted and the reader's next message is
|
|
554
|
+
what carries it. **Do not start a watch that cannot fire**: a wait on the pending
|
|
555
|
+
store would spin forever while the report underneath it claimed to be holding,
|
|
556
|
+
which is the exact failure `.claude/rules/spec-reports.md` records. The wait is
|
|
557
|
+
the turn ending, and the banner says so.
|
|
558
|
+
|
|
559
|
+
Relay the engine's **stack** — the `local:`, `network:` and `remote:` lines, all
|
|
560
|
+
three, in that order — never the bare `page:` path. `.claude/rules/spec-reports.md`
|
|
561
|
+
carries the shape and why every tier is named rather than one being chosen.
|
|
562
|
+
|
|
563
|
+
## Phase D — record the isolation stack (only if configured)
|
|
564
|
+
|
|
565
|
+
**Only when `specs/.core/env.config.json` exists** (per-spec isolation is
|
|
566
|
+
enabled), make sure the `> **Stack:**` header reflects the Phase A item 9
|
|
567
|
+
decision — `worktree` (default) or `worktree + docker` when it touches the DB /
|
|
568
|
+
stateful services. Nothing to provision now: `/spec-start` gives every in-progress
|
|
569
|
+
spec its own worktree automatically, and brings up Docker only when the Stack
|
|
570
|
+
says so. Mention the operator can escalate the Stack later (edit the header, or
|
|
571
|
+
run `skitterspec spec-env up <name>` to add Docker to an existing worktree). If
|
|
572
|
+
`env.config.json` is absent, isolation is off — leave the default `worktree` and
|
|
573
|
+
finish as above.
|
|
574
|
+
|
|
575
|
+
## Phase D2 — record the gating decision (only if configured)
|
|
576
|
+
|
|
577
|
+
**Only when `specs/.core/gating.config.json` exists.** Make sure the
|
|
578
|
+
`> **Gating:**` header carries the Phase A item 10 answer — a flag name, or
|
|
579
|
+
`none: <reason>` using the config's `default` wording if it sets one. Nothing is
|
|
580
|
+
provisioned or enforced by this: the header exists so the decision is
|
|
581
|
+
**on the record and reviewable**, and `skitterspec gating check` reports a spec that has
|
|
582
|
+
none. It never blocks. If the config is absent, do not write the line at all.
|
|
583
|
+
|
|
584
|
+
## Phase E — link to a ticketing provider (only if one is installed)
|
|
585
|
+
|
|
586
|
+
**Only when a ticketing provider is installed and configured** (it ships the
|
|
587
|
+
`/spec-push` · `/spec-status` skills and a provider config under
|
|
588
|
+
`specs/.core/`). If none is present, skip this phase entirely — the spec stays
|
|
589
|
+
local-only and `/spec` behaves exactly as above. When a provider is present, link
|
|
590
|
+
the spec to the tracker after writing it, so status and discussion live there
|
|
591
|
+
while the repo stays the source of truth — follow the provider's link steps
|
|
592
|
+
below (nothing to do here without one).
|
|
593
|
+
|
|
594
|
+
**Only when `specs/.core/jira.config.json` exists** (Jira sync is opted in).
|
|
595
|
+
If it's absent, skip this entirely — the spec stays local-only and the skill
|
|
596
|
+
behaves exactly as above. When present, link the spec you just wrote so status
|
|
597
|
+
and discussion live in Jira while the repo stays the source of truth. A spec is
|
|
598
|
+
a Jira **issue**; each phase is a **subtask**, carrying that phase's tasks in
|
|
599
|
+
its description as a read-only checklist.
|
|
600
|
+
|
|
601
|
+
**Linking is just the first push**, so it runs the same engine path `/spec-push`
|
|
602
|
+
does — you never create the issue by hand:
|
|
603
|
+
|
|
604
|
+
1. **Pick the transport.** `skitterspec spec-sync states --json`. With Jira
|
|
605
|
+
credentials set it answers `api` and prints the project's status names;
|
|
606
|
+
without them it answers `mcp` and you do the MCP work `/spec-push` describes.
|
|
607
|
+
Write the status names to a file for step 2.
|
|
608
|
+
2. **Get the plan.**
|
|
609
|
+
`skitterspec spec-sync plan <spec> --workspace-states <file> --json > plan.json`
|
|
610
|
+
— the spec is unlinked, so this plan is all-creates: the issue and one
|
|
611
|
+
subtask per phase.
|
|
612
|
+
3. **Apply it.**
|
|
613
|
+
`skitterspec spec-sync apply <spec> --plan plan.json`. There is no project
|
|
614
|
+
to pick: the issue lands in the configured `jira.projectKey` by construction.
|
|
615
|
+
That creates the issue and its subtasks and checks what Jira stored. It then
|
|
616
|
+
**stamps the keys into the spec** — `jira_identifier`/`jira_url` on the
|
|
617
|
+
overview, `jira_issue_id` on each phase — and **records the base snapshot**,
|
|
618
|
+
so `/spec-status` reports in-sync immediately. There is no hand-editing of
|
|
619
|
+
frontmatter and no separate `stamp` or `record` call.
|
|
620
|
+
|
|
621
|
+
If it prints `transport = mcp`, it wrote nothing: apply the plan over MCP as
|
|
622
|
+
`/spec-push` steps 4a–5 describe, ending with `spec-sync stamp` and
|
|
623
|
+
`spec-sync record`. That path is fully supported — it is what anyone without
|
|
624
|
+
credentials uses.
|
|
625
|
+
4. **Echo the branch name** from `branch.pattern` so the user knows what
|
|
626
|
+
`/spec-start` will fork.
|
|
627
|
+
|
|
628
|
+
**If Jira can't be reached**, say so in one line and leave the spec written and
|
|
629
|
+
local — it is still a perfectly good spec, and `/spec-push` links it later. Do
|
|
630
|
+
nothing destructive.
|
|
631
|
+
|
|
632
|
+
**A spec that adopted an existing issue** (see the intake step) is already
|
|
633
|
+
stamped, so its plan is an **update**, not a create: applying it replaces the
|
|
634
|
+
reporter's description with the spec. That is the one-way rule working as
|
|
635
|
+
intended — the repo is canonical, and the original was preserved as a comment
|
|
636
|
+
on the issue by the intake step. Nothing re-homes an adopted issue: where it
|
|
637
|
+
lives stays Jira's.
|
|
638
|
+
|
|
639
|
+
Leave committing to the existing convention (the user commits the spec as usual)
|
|
640
|
+
and **never auto-push git** — Jira's own automation reacts to real branch/PR
|
|
641
|
+
events later. Report the Jira issue URL as part of the skill's finish-up
|
|
642
|
+
message.
|
|
643
|
+
|
|
644
|
+
Jira has no project picker: a minted issue lands in the configured
|
|
645
|
+
`jira.projectKey` by construction, decided once in `specs/.core/jira.config.json`.
|
|
646
|
+
There is nothing to ask.
|
|
647
|
+
|
|
648
|
+
## Report
|
|
649
|
+
|
|
650
|
+
End with the block defined in `.claude/rules/spec-reports.md`. That file carries
|
|
651
|
+
the shape; this section carries only what is specific here.
|
|
652
|
+
|
|
653
|
+
**Verdicts**
|
|
654
|
+
|
|
655
|
+
- `✅` — a `Ready` spec is written to `specs/backlog/<name>/`.
|
|
656
|
+
- `⚠️` — written as `Draft`; open questions were deliberately left. Name them.
|
|
657
|
+
- `❌` — the spec was committed and the land failed part-way: the rebase
|
|
658
|
+
conflicted, or the fast-forward was refused. There is a standing worktree and a
|
|
659
|
+
branch to deal with, so say where both are.
|
|
660
|
+
- `⏸` — grilling did not reach a shared understanding, so nothing was written.
|
|
661
|
+
That is the skill working: a spec written over an unresolved requirement is
|
|
662
|
+
the outcome Phase A exists to prevent.
|
|
663
|
+
|
|
664
|
+
**Fields:** `Tracker` · `Spec` · `Built` · `Landed` · `Worktree` · `Follow-ups` ·
|
|
665
|
+
`Next`
|
|
666
|
+
|
|
667
|
+
`Built` is the spec's path and phase count; `Spec` is its status and bucket;
|
|
668
|
+
`Tracker` appears only when a provider is installed and linked it.
|
|
669
|
+
|
|
670
|
+
`Landed` and `Worktree` belong to the **verdict** half of the run and appear
|
|
671
|
+
only once one has been acted on — a run that is still waiting on the page has
|
|
672
|
+
neither. `Landed` says the base branch fast-forwarded and to what; `Worktree`
|
|
673
|
+
says kept (on `commit-start`) or removed (on `commit`), with the path. Neither
|
|
674
|
+
appears where isolation is off: nothing was provisioned and nothing was landed.
|
|
675
|
+
|
|
676
|
+
**`Next` depends on whether Phase C2 rendered a page.** Where it did, the run is
|
|
677
|
+
waiting on a verdict, so the block **omits the `Review` row** and ends on the
|
|
678
|
+
banner defined in `.claude/rules/spec-reports.md` — counts, the tier stack, and
|
|
679
|
+
this page's two exits:
|
|
680
|
+
|
|
681
|
+
---
|
|
682
|
+
|
|
683
|
+
## ⏸ Review ready — <N> files, +<a> −<d>
|
|
684
|
+
|
|
685
|
+
- **local** — <the `local:` URL>
|
|
686
|
+
- **network** — <the `network:` URL, or off with the command that turns it on>
|
|
687
|
+
- **remote** — <the `remote:` URL, or off with the command that turns it on>
|
|
688
|
+
|
|
689
|
+
I'm holding here until you send a verdict — the wait covers local and network.
|
|
690
|
+
|
|
691
|
+
`Commit & Start` puts it in flight · `Commit` keeps it for later
|
|
692
|
+
|
|
693
|
+
---
|
|
694
|
+
|
|
695
|
+
There `Next` names the page rather than a command, because the button is what
|
|
696
|
+
carries the work on.
|
|
697
|
+
|
|
698
|
+
**Neither exit leaves the spec anywhere awkward**, and the banner does not
|
|
699
|
+
explain that — the whole point of Phase B is that there is nothing to warn
|
|
700
|
+
about. Both buttons commit and land, so either way the spec reaches the base
|
|
701
|
+
branch as one commit; the only difference is whether the worktree stays.
|
|
702
|
+
|
|
703
|
+
Where no page was rendered — isolation is not configured, or nothing was
|
|
704
|
+
written — `Next` is `/spec-start <name>`, with the name spelled the way it must
|
|
705
|
+
be typed.
|
|
706
|
+
|
|
707
|
+
**A spec written without a page is still uncommitted**, so that `Next` relies on
|
|
708
|
+
`/spec-start` committing the spec when it is all that is uncommitted. Say
|
|
709
|
+
`/commit, then /spec-start <name>` when anything else is uncommitted too, or the
|
|
710
|
+
row sends the reader to a refusal.
|
|
711
|
+
|
|
712
|
+
**`Follow-ups` is almost always `none` here.** This skill's whole job is to
|
|
713
|
+
capture work, so anything it surfaced belongs in the spec it just wrote rather
|
|
714
|
+
than in a follow-up line beneath it.
|