@skitterbyte/skitterspec 22.0.0 → 22.1.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 +14 -0
- package/assets/claude-md-section.md +13 -0
- package/assets/commands/allow-main.md +33 -0
- package/assets/commands/spec-skip.md +24 -0
- package/assets/core/env.config.json.example +2 -1
- package/assets/core/env.config.md +83 -2
- package/assets/hooks/main-guard.cjs +145 -0
- package/assets/hooks/review-gate.cjs +8 -3
- package/assets/review/page.html +132 -2
- package/assets/rules/offered-unblocks.md +100 -0
- package/assets/rules/spec-planning.md +160 -11
- package/assets/rules/spec-reports.md +50 -9
- package/assets/skills/no-spec/SKILL.md +219 -0
- package/assets/skills/spec/SKILL.md +135 -36
- package/assets/skills/spec-bug/SKILL.md +5 -0
- package/assets/skills/spec-cancel/SKILL.md +29 -0
- package/assets/skills/spec-complete/SKILL.md +25 -0
- package/assets/skills/spec-diff/SKILL.md +33 -1
- package/assets/skills/spec-init/SKILL.md +4 -2
- package/assets/skills/spec-next/SKILL.md +47 -2
- package/assets/skills/spec-reviewed/SKILL.md +3 -3
- package/assets/skills/spec-start/SKILL.md +14 -0
- package/package.json +1 -1
- package/src/cli.js +702 -59
- package/src/env/config.js +121 -4
- package/src/env/hooks.js +102 -33
- package/src/env/live.js +30 -1
- package/src/env/mainguard.js +240 -0
- package/src/env/provision.js +106 -10
- package/src/env/registry.js +70 -6
- package/src/env/resolve.js +92 -3
- package/src/env/review.js +324 -20
- package/src/env/reviewers/coderabbit.js +228 -0
- package/src/env/reviewers.js +517 -0
- package/src/env/serve.js +189 -44
- package/src/env/teardown.js +12 -1
- package/src/init.js +125 -15
|
@@ -73,25 +73,56 @@ Briefly play back the agreed understanding before writing.
|
|
|
73
73
|
|
|
74
74
|
This skill is for **features**. For bugs, use `/spec-bug` (test-first, red→green).
|
|
75
75
|
|
|
76
|
-
### Write it
|
|
77
|
-
|
|
78
|
-
**
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
76
|
+
### Write it in its own worktree
|
|
77
|
+
|
|
78
|
+
**Only when the project has per-spec isolation** (`specs/.core/env.config.json`
|
|
79
|
+
present). Without it there is no worktree to make and this section does not
|
|
80
|
+
apply — write the folder where you are standing, exactly as before.
|
|
81
|
+
|
|
82
|
+
**Provision before you write, not after.** Grilling put nothing on disk and the
|
|
83
|
+
spec's name is settled by the time Phase A ends, so this is the one moment where
|
|
84
|
+
a worktree costs nothing to obtain and everything is still ahead of it:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
skitterspec spec-env up <name> --docs
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Run the commands it prints, then move this session into the worktree with a
|
|
91
|
+
plain `cd` — the Bash working directory persists between calls, so from here on
|
|
92
|
+
the spec is written on its own branch. Confirm the move landed rather than
|
|
93
|
+
reading silence as success (`.claude/rules/negative-checks.md` rule 1):
|
|
94
|
+
`skitterspec spec-env resolve` with no argument must name this spec. If it does
|
|
95
|
+
not, say so and write the spec where you are standing instead; a spec in the
|
|
96
|
+
wrong tree is worse than a spec with no worktree.
|
|
97
|
+
|
|
98
|
+
**`--docs` is what makes this cheap.** It skips the `setup` commands and the
|
|
99
|
+
Docker stack — everything whose only purpose is making a tree *runnable* — so
|
|
100
|
+
provisioning a worktree to write markdown in is a `git worktree add` and nothing
|
|
101
|
+
else. `/spec-start` re-runs `up` over the same worktree without the flag, and the
|
|
102
|
+
setup runs then, at the first moment the tree is used for code.
|
|
103
|
+
|
|
104
|
+
**Why the base branch is no longer where this happens.** `main` is where work
|
|
105
|
+
**lands**, not where it happens. Authoring on it meant the spec sat uncommitted
|
|
106
|
+
there for as long as Phase C2's page went unanswered — which is unbounded by
|
|
107
|
+
design, because a reader walking away from a diff is the normal case — and a
|
|
108
|
+
release could not be cut through it. The verdict lands the spec instead, so
|
|
109
|
+
`main` gains it as one commit and is never dirty on the way.
|
|
110
|
+
|
|
111
|
+
**A spec written in ANOTHER spec's worktree is still the mistake it always was**,
|
|
112
|
+
and this section does not soften that. It physically lives on that branch: not on
|
|
113
|
+
`main` until that spec lands, invisible to anyone listing `specs/backlog/`
|
|
114
|
+
meanwhile, and cancelled along with its host. Committing it there also mis-stamps
|
|
115
|
+
the ticket trailer, which is resolved from the branch (see
|
|
116
|
+
`.claude/rules/commit-trailers.md`, installed with a ticketing provider). The
|
|
117
|
+
difference is whose worktree: **its own** is now the normal path, and someone
|
|
118
|
+
else's is the accident.
|
|
119
|
+
|
|
120
|
+
So if Phase A ran inside another spec's worktree — most likely because a design
|
|
121
|
+
question came up part-way through implementing it — the provision above is the
|
|
122
|
+
fix rather than something to warn about: it moves the session out of that tree
|
|
123
|
+
and into this spec's own. Where isolation is off and there is no worktree to
|
|
124
|
+
move to, **warn, don't refuse**, and say the trailer for that commit wants
|
|
125
|
+
`spec-sync ref <new-spec-name>` rather than the bare form.
|
|
95
126
|
|
|
96
127
|
- **Every spec is a folder** — never a bare file, even for a one-line change:
|
|
97
128
|
`specs/backlog/feat-<kebab-name>/`. Create it with `mkdir -p`.
|
|
@@ -266,26 +297,40 @@ phase of the lifecycle ends — on a page, in a verdict.
|
|
|
266
297
|
skitterspec spec-env review <spec> --docs --buttons authoring
|
|
267
298
|
```
|
|
268
299
|
|
|
269
|
-
`--docs` reads the spec's own documents from the tree you are standing in,
|
|
270
|
-
|
|
271
|
-
**this spec's documents and nobody else's**:
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
verdict.
|
|
300
|
+
`--docs` reads the spec's own documents from the tree you are standing in, which
|
|
301
|
+
after Phase B is **this spec's own worktree**. It renders
|
|
302
|
+
**this spec's documents and nobody else's**: the `owned` half of
|
|
303
|
+
`spec-env stage` is what supplies the file set, and it stays load-bearing even
|
|
304
|
+
now that the tree holds one spec — a project's `spec.companionPaths` and a
|
|
305
|
+
hand-edited `specs/.core/` both land in the same tree, and only the spec's own
|
|
306
|
+
documents belong under this verdict.
|
|
276
307
|
|
|
277
308
|
**This is free.** The engine reads git and splices text into a template; the
|
|
278
309
|
diff never passes through you.
|
|
279
310
|
|
|
311
|
+
**Never pass `--run-reviewers` here.** A spec is prose, and the reviewers
|
|
312
|
+
`review.reviewers` names read code — spending a rate-limited review on a
|
|
313
|
+
paragraph buys nothing. The engine refuses it on a `--docs` render whatever this
|
|
314
|
+
skill asks for, so this is a note about intent rather than a guard you are
|
|
315
|
+
holding: do not add the flag on the assumption that it was an oversight.
|
|
316
|
+
|
|
280
317
|
**Render nothing when nothing was written.** A `⏸` run — grilling that never
|
|
281
318
|
reached a shared understanding — has no spec to show, and must not ask for a
|
|
282
319
|
verdict on one.
|
|
283
320
|
|
|
284
321
|
**Arm nothing.** There is no `spec-env review arm` in this path, and that is a
|
|
285
322
|
decision rather than an omission: the gate asserts that *a phase which ended*
|
|
286
|
-
owes an answer, and a backlog spec owes no phase.
|
|
287
|
-
|
|
288
|
-
|
|
323
|
+
owes an answer, and a backlog spec owes no phase. A `/spec` run must leave
|
|
324
|
+
`spec-env review gate --check` exiting 0.
|
|
325
|
+
|
|
326
|
+
**And walking away from this page now costs nobody anything**, which is a
|
|
327
|
+
stronger reason than the one that used to sit here. It read *"the spec is simply
|
|
328
|
+
still uncommitted, which `/spec-start` already handles"* — true, and a
|
|
329
|
+
concession: an uncommitted spec meant a dirty base branch, which is everyone's
|
|
330
|
+
problem, so "arm nothing" was tolerating a mess rather than describing a clean
|
|
331
|
+
state. Since Phase B the unanswered spec sits on its own branch in its own
|
|
332
|
+
worktree, where it is in nothing's way: no release is blocked, no other spec has
|
|
333
|
+
to replay over it, and it is still exactly where it was tomorrow morning.
|
|
289
334
|
|
|
290
335
|
### The two endings this page offers
|
|
291
336
|
|
|
@@ -294,12 +339,46 @@ committing pair, because "commit and build the next phase" is meaningless for a
|
|
|
294
339
|
spec with no phase in flight.
|
|
295
340
|
|
|
296
341
|
- **`commit-start`** — hand off to `review.commitWith` (`/commit` by default),
|
|
297
|
-
passing the pathspec the render reported on `docs.paths
|
|
298
|
-
**`/spec-start <name
|
|
299
|
-
anything down, exactly as `commit-continue` stops
|
|
300
|
-
the `commit && /spec-start` that was typed by hand.
|
|
301
|
-
- **`commit`** — the same commit
|
|
302
|
-
|
|
342
|
+
passing the pathspec the render reported on `docs.paths`; **land it** (below);
|
|
343
|
+
then **keep the worktree** and run **`/spec-start <name>`**, and **stop there**.
|
|
344
|
+
It never completes or tears anything down, exactly as `commit-continue` stops
|
|
345
|
+
after `/spec-next`. This is the `commit && /spec-start` that was typed by hand.
|
|
346
|
+
- **`commit`** — the same commit and the same land, then
|
|
347
|
+
**tear the worktree down** and finish. The spec stays `Ready` in `backlog` —
|
|
348
|
+
on the base branch, where anyone can see it — ready for a `/spec-start`
|
|
349
|
+
whenever it is wanted.
|
|
350
|
+
|
|
351
|
+
**Both committing verdicts land, and that is what keeps the backlog findable.**
|
|
352
|
+
`ls specs/backlog/` is how specs are found, and a folder bucket is only the truth
|
|
353
|
+
on the branch you are standing on — so a spec left on its own branch would be
|
|
354
|
+
invisible to everyone, including the next `/spec` run. The commit goes on the
|
|
355
|
+
branch and then the branch goes onto the base:
|
|
356
|
+
|
|
357
|
+
```
|
|
358
|
+
skitterspec spec-env integrate <name>
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
It plans a rebase onto the base branch in the worktree, then a
|
|
362
|
+
`merge --ff-only` in the primary checkout — run the commands it prints. It
|
|
363
|
+
refuses on a dirty tree, which is correct here: the commit ran first, so anything
|
|
364
|
+
still uncommitted at this point is not this spec's and the land must not proceed.
|
|
365
|
+
|
|
366
|
+
**If the rebase conflicts, stop and say so.** It is unlikely on a
|
|
367
|
+
documents-only branch and not impossible — two specs authored at once can both
|
|
368
|
+
touch `specs/.core/`. Run `git rebase --abort`, leave the commit sitting on the
|
|
369
|
+
branch, and report `❌` with the conflict: there is a standing worktree to clear,
|
|
370
|
+
which is what separates `❌` from `⏸`. Never resolve someone else's conflict to
|
|
371
|
+
get the land through.
|
|
372
|
+
|
|
373
|
+
**The worktree lifetime follows the verdict, and the asymmetry is deliberate.**
|
|
374
|
+
`commit-start` keeps it because you are carrying straight on, and `/spec-start`
|
|
375
|
+
re-runs `up` over it without `--docs` — which is where the setup commands
|
|
376
|
+
Phase B skipped finally run. Plain `commit` tears it down with
|
|
377
|
+
`skitterspec spec-env down <name>`, because a spec parked in the backlog should
|
|
378
|
+
hold no worktree and no `node_modules`; `/spec-start` provisions from scratch
|
|
379
|
+
whenever it is wanted. Always-keep would leave five backlog specs holding five
|
|
380
|
+
checkouts, and always-teardown would have `commit-start` re-provision seconds
|
|
381
|
+
after destroying the tree it needed.
|
|
303
382
|
- **`changes`** — work the notes into the spec, record a resolution for each one
|
|
304
383
|
so the next render shows it struck through with what changed, then
|
|
305
384
|
**re-render, and wait again**. The reader is still holding a decision, so
|
|
@@ -328,6 +407,11 @@ the verdict — and the reader's conclusion is about what the page showed them.
|
|
|
328
407
|
verdict to a lunch break.
|
|
329
408
|
3. **On waking, let the engine pick:**
|
|
330
409
|
|
|
410
|
+
**A watch that dies is re-armed on the same window**, silently and bounded by
|
|
411
|
+
the age of that window — `.claude/rules/spec-reports.md` carries the contract,
|
|
412
|
+
including when to stop and what the banner says instead. Do not restate it
|
|
413
|
+
here.
|
|
414
|
+
|
|
331
415
|
```
|
|
332
416
|
skitterspec spec-env review <spec> --docs --claim-since <the timestamp> --json
|
|
333
417
|
```
|
|
@@ -391,15 +475,25 @@ the shape; this section carries only what is specific here.
|
|
|
391
475
|
|
|
392
476
|
- `✅` — a `Ready` spec is written to `specs/backlog/<name>/`.
|
|
393
477
|
- `⚠️` — written as `Draft`; open questions were deliberately left. Name them.
|
|
478
|
+
- `❌` — the spec was committed and the land failed part-way: the rebase
|
|
479
|
+
conflicted, or the fast-forward was refused. There is a standing worktree and a
|
|
480
|
+
branch to deal with, so say where both are.
|
|
394
481
|
- `⏸` — grilling did not reach a shared understanding, so nothing was written.
|
|
395
482
|
That is the skill working: a spec written over an unresolved requirement is
|
|
396
483
|
the outcome Phase A exists to prevent.
|
|
397
484
|
|
|
398
|
-
**Fields:** `Tracker` · `Spec` · `Built` · `Follow-ups` ·
|
|
485
|
+
**Fields:** `Tracker` · `Spec` · `Built` · `Landed` · `Worktree` · `Follow-ups` ·
|
|
486
|
+
`Next`
|
|
399
487
|
|
|
400
488
|
`Built` is the spec's path and phase count; `Spec` is its status and bucket;
|
|
401
489
|
`Tracker` appears only when a provider is installed and linked it.
|
|
402
490
|
|
|
491
|
+
`Landed` and `Worktree` belong to the **verdict** half of the run and appear
|
|
492
|
+
only once one has been acted on — a run that is still waiting on the page has
|
|
493
|
+
neither. `Landed` says the base branch fast-forwarded and to what; `Worktree`
|
|
494
|
+
says kept (on `commit-start`) or removed (on `commit`), with the path. Neither
|
|
495
|
+
appears where isolation is off: nothing was provisioned and nothing was landed.
|
|
496
|
+
|
|
403
497
|
**`Next` depends on whether Phase C2 rendered a page.** Where it did, the run is
|
|
404
498
|
waiting on a verdict, so the block **omits the `Review` row** and ends on the
|
|
405
499
|
banner defined in `.claude/rules/spec-reports.md` — counts, the tier stack, and
|
|
@@ -422,6 +516,11 @@ I'm holding here until you send a verdict — the wait covers local and network.
|
|
|
422
516
|
There `Next` names the page rather than a command, because the button is what
|
|
423
517
|
carries the work on.
|
|
424
518
|
|
|
519
|
+
**Neither exit leaves the spec anywhere awkward**, and the banner does not
|
|
520
|
+
explain that — the whole point of Phase B is that there is nothing to warn
|
|
521
|
+
about. Both buttons commit and land, so either way the spec reaches the base
|
|
522
|
+
branch as one commit; the only difference is whether the worktree stays.
|
|
523
|
+
|
|
425
524
|
Where no page was rendered — isolation is not configured, or nothing was
|
|
426
525
|
written — `Next` is `/spec-start <name>`, with the name spelled the way it must
|
|
427
526
|
be typed.
|
|
@@ -239,6 +239,11 @@ wait a timeout — the reasoning is in `/spec-next` §5 and is not repeated here
|
|
|
239
239
|
The banner it describes is what this skill emits in place of a `Review` row,
|
|
240
240
|
and the routing on the verdict is `/spec-diff` §2 and §4, as it is everywhere.
|
|
241
241
|
|
|
242
|
+
**A watch that dies is re-armed on the same window**, silently and bounded by
|
|
243
|
+
the age of that window — `.claude/rules/spec-reports.md` carries the contract,
|
|
244
|
+
including when to stop and what the banner says instead. Do not restate it
|
|
245
|
+
here.
|
|
246
|
+
|
|
242
247
|
**Why this skill arms as well as waits.** Waiting is what any offer does;
|
|
243
248
|
**arming** asserts an obligation that outlives the turn, and belongs only to
|
|
244
249
|
work that is finished. A bug fix is a completed unit — red→green, suite
|
|
@@ -114,6 +114,35 @@ of the work, so an unreclaimed one is worth a line rather than a silence.
|
|
|
114
114
|
reclaim the cancelled spec's environment. On confirmation, run the `spec-env` CLI
|
|
115
115
|
directly (the old `/spec-env-down` skill is gone — teardown is folded in here):
|
|
116
116
|
|
|
117
|
+
0. **Name a pass still waiting for THIS spec — before anything is removed.**
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
skitterspec spec-env review waiting --json
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Filter to the spec being cancelled and say nothing about any other: a run
|
|
124
|
+
reports itself and nothing else (`.claude/rules/spec-reports.md`). For each
|
|
125
|
+
one, give the code, the verdict and the age, then the two exits — claim it
|
|
126
|
+
now with `/spec-reviewed <code>` **while the worktree still stands**, or
|
|
127
|
+
disown it with `skitterspec spec-env review <spec> --drop <code>`.
|
|
128
|
+
|
|
129
|
+
**Why here and not anywhere else.** Nothing is about to become unreachable —
|
|
130
|
+
a pass can be disowned long after its spec is gone. What is about to pass is
|
|
131
|
+
the last moment the verdict can still be **honoured**: before teardown a
|
|
132
|
+
`commit` pass can be claimed and acted on, after it there is no branch left
|
|
133
|
+
to commit to and disowning is all that remains. On a cancelled spec that is
|
|
134
|
+
sharper still — the worktree may hold the only copy of the work, so a pass
|
|
135
|
+
approving it is the one thing that might argue for keeping it.
|
|
136
|
+
|
|
137
|
+
**It reports, and it never blocks.** No refusal, no confirmation of its own,
|
|
138
|
+
no non-zero exit — this step already asks before it reclaims anything, and a
|
|
139
|
+
waiting pass is information rather than a second gate.
|
|
140
|
+
And **it never claims** — reporting a pass is not taking one, and
|
|
141
|
+
`/spec-diff` §0 is untouched by this step.
|
|
142
|
+
|
|
143
|
+
Put what you found in the report's `Notes` row.
|
|
144
|
+
Silent when nothing is waiting, which is the usual case.
|
|
145
|
+
|
|
117
146
|
1. If `.spec-env/connected` names this spec, run `skitterspec spec-env connect
|
|
118
147
|
main` first to free the canonical ports.
|
|
119
148
|
2. `skitterspec spec-env dev down <name>` — stop its host dev servers.
|
|
@@ -231,6 +231,31 @@ nothing left to protect.
|
|
|
231
231
|
worktree and branch are being kept, and go straight to sub-step 4. Mention
|
|
232
232
|
`skitterspec spec-env up <name>` re-attaches it later either way.
|
|
233
233
|
|
|
234
|
+
0. **Name a pass still waiting for THIS spec — before anything is removed.**
|
|
235
|
+
|
|
236
|
+
```
|
|
237
|
+
skitterspec spec-env review waiting --json
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Filter to the spec being completed and say nothing about any other: a run
|
|
241
|
+
reports itself and nothing else (`.claude/rules/spec-reports.md`). For each
|
|
242
|
+
one, give the code, the verdict and the age, then the two exits — claim it
|
|
243
|
+
now with `/spec-reviewed <code>` **while the worktree still stands**, or
|
|
244
|
+
disown it with `skitterspec spec-env review <spec> --drop <code>`.
|
|
245
|
+
|
|
246
|
+
**Why here and not anywhere else.** Nothing is about to become unreachable —
|
|
247
|
+
a pass can be disowned long after its spec is gone. What is about to pass is
|
|
248
|
+
the last moment the verdict can still be **honoured**: before teardown a
|
|
249
|
+
`commit` pass can be claimed and acted on, after it there is no branch left
|
|
250
|
+
to commit to and disowning is all that remains.
|
|
251
|
+
|
|
252
|
+
**It reports, and it never blocks.** No refusal, no confirmation of its own,
|
|
253
|
+
no non-zero exit. And **it never claims** — reporting a pass is not taking
|
|
254
|
+
one, and `/spec-diff` §0 is untouched by this step.
|
|
255
|
+
|
|
256
|
+
Put what you found in the report's `Notes` row.
|
|
257
|
+
Silent when nothing is waiting, which is the usual case.
|
|
258
|
+
|
|
234
259
|
1. **Disconnect the proxy if this spec is connected.** If `.spec-env/connected`
|
|
235
260
|
names this spec, run `skitterspec spec-env connect main` first so the
|
|
236
261
|
canonical ports go back to the primary checkout.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spec-diff
|
|
3
|
-
description: See what a spec's worktree changed — render its diff as a page you can mark up, take that review pass back, and act on it. Answers at any point, including half-way through a phase. Use when the user says "/spec-diff", "show me the diff", "what did this phase change", "review this spec's work",
|
|
3
|
+
description: See what a spec's worktree changed — render its diff as a page you can mark up, take that review pass back, and act on it. Answers at any point, including half-way through a phase, and takes --reviewers to run the project's configured code reviewers. Use when the user says "/spec-diff", "show me the diff", "what did this phase change", "review this spec's work", "run the reviewers", or hands back what the review page produced — a six-digit claim code, a bare verdict word, or the pasted JSON.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /spec-diff — see the phase before you commit it
|
|
@@ -161,6 +161,13 @@ back, and these steps replace §3–§5 below.
|
|
|
161
161
|
applies: it concluded nothing. Go to **§2b**. The engine refuses a pass
|
|
162
162
|
carrying both, so there is never a choice to make between them.
|
|
163
163
|
|
|
164
|
+
**It is on the `claimed:` line** — `· action: live-on` at the end of it, and
|
|
165
|
+
`claimed.action` under `--json`. Read it there rather than inferring one
|
|
166
|
+
from a pass that merged nothing: a claim reporting no verdict and no counts
|
|
167
|
+
used to be the only trace a press left, which made every action look like a
|
|
168
|
+
reader who had concluded nothing. If the line carries no action, there was
|
|
169
|
+
none.
|
|
170
|
+
|
|
164
171
|
3. **Say what you read, then ask what's up.** Report the accepted count, then
|
|
165
172
|
each open comment as `file:line — note`, then the files you would touch.
|
|
166
173
|
**Wait — unless the verdict already said otherwise.** Pasting on its own is
|
|
@@ -395,6 +402,14 @@ way out. **Never park another spec's live session** to make room — that is
|
|
|
395
402
|
someone else's work, and freeing it is their decision. Re-render and wait, so
|
|
396
403
|
the reader can choose something else.
|
|
397
404
|
|
|
405
|
+
**A refusal may declare the way out of itself.** Ask with
|
|
406
|
+
`skitterspec spec-env live take <spec> --json` and read its `offer` field:
|
|
407
|
+
where one is present, relay the refusal and **then** offer it, exactly as
|
|
408
|
+
`.claude/rules/offered-unblocks.md` describes. Do not re-decide from the reason
|
|
409
|
+
text, and do not infer an offer that is not there — the boundary that keeps
|
|
410
|
+
another spec's workbench out of this lives in that field rather than in prose
|
|
411
|
+
here.
|
|
412
|
+
|
|
398
413
|
**`allow` writes a committed file, and that is worth a sentence.** It edits
|
|
399
414
|
`specs/.core/env.config.json` in the **primary checkout**, so it changes
|
|
400
415
|
behaviour for everyone who pulls and leaves that tree dirty — unlike the live
|
|
@@ -437,9 +452,26 @@ help someone give one.
|
|
|
437
452
|
```
|
|
438
453
|
skitterspec spec-env review <spec> # uncommitted work (the default)
|
|
439
454
|
skitterspec spec-env review <spec> --branch # everything since the base branch
|
|
455
|
+
skitterspec spec-env review <spec> --run-reviewers # …and run review.reviewers
|
|
440
456
|
skitterspec spec-env review serve # every spec, on localhost
|
|
441
457
|
```
|
|
442
458
|
|
|
459
|
+
**`--run-reviewers` is opt-in here, and a BARE `/spec-diff` MUST NOT PASS IT.**
|
|
460
|
+
`/spec-next` runs the project's configured reviewers once per phase, where the
|
|
461
|
+
cost is paid against work that is finished. This skill answers at any point,
|
|
462
|
+
including several times in one phase — and each run spends a review against
|
|
463
|
+
whatever hourly limit the reviewer has, which on the tiers this was built for is
|
|
464
|
+
measured in single figures.
|
|
465
|
+
|
|
466
|
+
So pass it when the operator asked for it: `/spec-diff --reviewers`, or they said
|
|
467
|
+
in words that they want the second opinion. Otherwise render without it. The
|
|
468
|
+
cached findings from the phase-end run still show on the page whenever the diff
|
|
469
|
+
has not moved, so the usual mid-phase read loses nothing by not asking.
|
|
470
|
+
|
|
471
|
+
Where it does run, say what it cost — a reviewer takes 30s–3min — and nothing
|
|
472
|
+
else. The page's own strip reports each reviewer's outcome, and a reviewer that
|
|
473
|
+
could not run is that strip's business rather than yours.
|
|
474
|
+
|
|
443
475
|
**There is no switch left to handle.** The engine serves and prints a **stack** —
|
|
444
476
|
one line per tier, `local`, `network`, `remote`, each either a URL or the one
|
|
445
477
|
command that turns it on. All of it is free and none of it publishes anything.
|
|
@@ -27,8 +27,10 @@ clobber customised content. Finish with a summary of created vs already-present.
|
|
|
27
27
|
> **Leave alone**. Non-interactively it only adds what's missing; `--resync` /
|
|
28
28
|
> `--reset` (reset needs `--yes`) drive the stronger actions.
|
|
29
29
|
|
|
30
|
-
The system is **
|
|
31
|
-
`spec-hotfix` (a bug fixed on a released tag),
|
|
30
|
+
The system is **thirteen skills**: `spec` (feature), `spec-bug` (bug),
|
|
31
|
+
`spec-hotfix` (a bug fixed on a released tag),
|
|
32
|
+
`no-spec` (work that genuinely has none — off the base branch all the same),
|
|
33
|
+
`spec-review`, `spec-start`,
|
|
32
34
|
`spec-next`, `spec-diff` (read a spec's diff as a page),
|
|
33
35
|
`spec-reviewed` (pick up a review you approved on that page), `spec-to-main`,
|
|
34
36
|
`spec-complete`, `spec-cancel`, and this `spec-init`. The lifecycle is `backlog → in-progress → complete / cancelled`,
|
|
@@ -148,6 +148,12 @@ Before writing any code for this phase, get the workspace clean:
|
|
|
148
148
|
anything is owed (`.claude/rules/negative-checks.md`). Do not mention it: a
|
|
149
149
|
line about a gate nobody armed is an accusation against a healthy repo.
|
|
150
150
|
|
|
151
|
+
**It may also declare the way out.** An `armed` answer can carry an `offer`,
|
|
152
|
+
and where it does, relay the refusal and **then** offer it — once — exactly as
|
|
153
|
+
`.claude/rules/offered-unblocks.md` describes, spending it with
|
|
154
|
+
`skitterspec spec-env review gate <spec> --offered` as you raise it. Where
|
|
155
|
+
there is no `offer`, the three exits in the `Next` row are the whole answer.
|
|
156
|
+
|
|
151
157
|
**This refusal counts nothing.** It is not a tally of ticked boxes — those
|
|
152
158
|
still gate nothing and still are not counted. It asserts one thing: a phase
|
|
153
159
|
that ended has an answer. And the exit is always **one command**, one of them
|
|
@@ -280,13 +286,34 @@ the moment the page is about, so render it now — **after** the tests pass and
|
|
|
280
286
|
**before** the commit:
|
|
281
287
|
|
|
282
288
|
```
|
|
283
|
-
skitterspec spec-env review <spec>
|
|
289
|
+
skitterspec spec-env review <spec> --run-reviewers
|
|
284
290
|
```
|
|
285
291
|
|
|
286
292
|
**This is free.** It is the engine reading git and splicing text into a template;
|
|
287
293
|
the diff never passes through you, so a 266KB patch costs nothing. Report the
|
|
288
294
|
path it prints and move on.
|
|
289
295
|
|
|
296
|
+
**`--run-reviewers` is free to *you* as well, and costs wall-clock.** Where the
|
|
297
|
+
project configured any (`review.reviewers` — empty in most projects, and then
|
|
298
|
+
this flag does nothing at all), the engine runs each one against the diff before
|
|
299
|
+
rendering, so the page is already populated when it is opened. Their findings
|
|
300
|
+
come back as JSON and land on the page as **checks**; the patch still never
|
|
301
|
+
passes through you. What it spends is 30s–3min once, after the tests are green —
|
|
302
|
+
which is the cheap half of a step that is about to wait on a person for far
|
|
303
|
+
longer. A re-render of unchanged work reuses the cached findings rather than
|
|
304
|
+
spending another review.
|
|
305
|
+
|
|
306
|
+
**Findings never gate.** A check is not a comment, so a page carrying twenty of
|
|
307
|
+
them still offers `Commit`; a reader who replies to one creates a comment, and
|
|
308
|
+
that does gate, because then a person has asked for something. Nothing here
|
|
309
|
+
counts them, and nothing here acts on them — you render and wait exactly as you
|
|
310
|
+
would have.
|
|
311
|
+
|
|
312
|
+
**A reviewer that could not run is reported by the page**, not by you. Do not
|
|
313
|
+
re-state its outcome, do not investigate it, and never treat it as a failure of
|
|
314
|
+
the phase: the strip on the page says `clean` or `did not run — <why>` for each
|
|
315
|
+
one, which is where a reader deciding whether to commit will look.
|
|
316
|
+
|
|
290
317
|
**This render takes the committing button set**, which is the default — so
|
|
291
318
|
`--buttons` is not passed. That is a statement about the work, not about the
|
|
292
319
|
gate: the phase is finished, so `Commit` and `Commit & Continue` are the right
|
|
@@ -315,7 +342,7 @@ so one subject lives in one place:
|
|
|
315
342
|
|
|
316
343
|
---
|
|
317
344
|
|
|
318
|
-
## ⏸ Review ready — <N> files, +<a> −<d>
|
|
345
|
+
## ⏸ Review ready — <N> files, +<a> −<d><, <n> flagged by <reviewer> — only where one found something>
|
|
319
346
|
|
|
320
347
|
- **local** — <the `local:` URL>
|
|
321
348
|
- **network** — <the `network:` URL, or off with the command that turns it on>
|
|
@@ -327,6 +354,19 @@ I'm holding here until you send a verdict — the wait covers local and network.
|
|
|
327
354
|
|
|
328
355
|
`/spec-reviewed` picks it up · `spec-env review skip "<reason>"` moves on
|
|
329
356
|
|
|
357
|
+
**The findings count goes in the COUNTS, and nowhere else.** Where `--json`
|
|
358
|
+
reported a reviewer in the `findings` state, its count joins the heading — the
|
|
359
|
+
slot that already says `7 files, +212 −18` — and that is the whole of it. No
|
|
360
|
+
extra line, no extra row, and nothing at all when every reviewer was `clean`,
|
|
361
|
+
`cached` or could not run: the page's own strip is where the per-reviewer
|
|
362
|
+
outcomes belong, and repeating them here would be the second place naming one
|
|
363
|
+
subject that `.claude/rules/spec-reports.md` exists to prevent.
|
|
364
|
+
|
|
365
|
+
**This is not a third amendment to that contract.** The counts slot is already
|
|
366
|
+
there and already carries numbers about the same diff; nothing about the
|
|
367
|
+
banner's shape, its lines or its exits changes. A reader who has configured no
|
|
368
|
+
reviewer sees the heading they have always seen.
|
|
369
|
+
|
|
330
370
|
**The stack is the engine's — copy it, do not compose it.** `spec-env review`
|
|
331
371
|
printed one line per tier, in that order, and `--json` carries the same thing as
|
|
332
372
|
`tiers`. Relay all three whatever they say, including the ones that are off with
|
|
@@ -408,6 +448,11 @@ reading — and that is the gap the whole gate exists to close.
|
|
|
408
448
|
a diff is the normal case rather than the edge one. Do not give it a duration
|
|
409
449
|
of your own.
|
|
410
450
|
|
|
451
|
+
**A watch that dies is re-armed on the same window**, silently and bounded by
|
|
452
|
+
the age of that window — `.claude/rules/spec-reports.md` carries the contract,
|
|
453
|
+
including when to stop and what the banner says instead. Do not restate it
|
|
454
|
+
here.
|
|
455
|
+
|
|
411
456
|
Then **end your turn**. Do not poll it and do not hold the turn open: the
|
|
412
457
|
point is that the reader has the terminal back while they read.
|
|
413
458
|
3. **On waking, let the engine pick**:
|
|
@@ -82,9 +82,9 @@ A **six-digit code** is a pass the operator read off their own page. It says
|
|
|
82
82
|
invocation does, above, and claim the code *there*. Then go to step 4 — a named
|
|
83
83
|
pass has nothing to disambiguate.
|
|
84
84
|
|
|
85
|
-
A **verdict word** — `commit`, `commit-continue`, `commit-start`,
|
|
86
|
-
`changes`, `discuss` — is the conclusion itself,
|
|
87
|
-
it. It is
|
|
85
|
+
A **verdict word** — `commit`, `commit-continue`, `commit-start`,
|
|
86
|
+
`commit-land`, `continue`, `changes`, `discuss` — is the conclusion itself,
|
|
87
|
+
arriving without a pass behind it. It is
|
|
88
88
|
what a **`file://` page** hands over: that page has no server to POST to and no
|
|
89
89
|
store to write to, so it copies a command instead of sending anything, and this
|
|
90
90
|
is the command. Resolve the spec as a bare invocation does, then send the word
|
|
@@ -73,6 +73,20 @@ as printed; when it refuses, relay the reason and stop.
|
|
|
73
73
|
It also refuses a **clean** tree whose spec is not in the commit the worktree
|
|
74
74
|
would fork from — otherwise you get a branch missing the very spec it is for.
|
|
75
75
|
|
|
76
|
+
**A spec that `/spec` already landed is the HEALTHY case of that check.**
|
|
77
|
+
It is not the refusal. `/spec` authors in its own `--docs` worktree and its committing
|
|
78
|
+
verdict fast-forwards the base branch, so by the time `/spec-start` runs the
|
|
79
|
+
spec is already in the commit the worktree forks from and the tree is clean —
|
|
80
|
+
which is exactly what that check is looking for. Do not read "clean tree,
|
|
81
|
+
nothing to commit" as a sign something was skipped: it means the landing worked.
|
|
82
|
+
|
|
83
|
+
**And the worktree may already exist**, because `Commit & Start` keeps it. That
|
|
84
|
+
is a re-attach, not a clash: `spec-env up` plans the attach form rather than a
|
|
85
|
+
second `-b` fork, and its `then, in the worktree, run:` step is where the
|
|
86
|
+
`setup` commands `--docs` deliberately skipped finally run. So run the plan as
|
|
87
|
+
printed — the install belongs to this moment, the first at which the tree is
|
|
88
|
+
used for code — and report a re-attach rather than a fresh provision.
|
|
89
|
+
|
|
76
90
|
## 2. Identify the spec
|
|
77
91
|
|
|
78
92
|
- Use the name/path argument when given.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skitterbyte/skitterspec",
|
|
3
|
-
"version": "22.
|
|
3
|
+
"version": "22.1.0",
|
|
4
4
|
"description": "Spec-driven development for Claude Code \u2014 a tracker-free filesystem workflow: lifecycle skills and per-spec isolation. For Linear sync, install @skitterbyte/skitterspec-linear instead.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|