@skitterbyte/skitterspec 20.0.0 → 22.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 +304 -4
- package/README.md +113 -6
- package/assets/claude-md-section.md +29 -18
- package/assets/commands/spec-remote-review.md +22 -0
- package/assets/core/env.config.json.example +4 -2
- package/assets/core/env.config.md +103 -25
- package/assets/review/page.html +1101 -108
- package/assets/rules/spec-planning.md +39 -7
- package/assets/rules/spec-reports.md +210 -31
- package/assets/skills/spec/SKILL.md +129 -1
- package/assets/skills/spec-bug/SKILL.md +63 -43
- package/assets/skills/spec-diff/SKILL.md +183 -39
- package/assets/skills/spec-hotfix/SKILL.md +57 -43
- package/assets/skills/spec-init/SKILL.md +18 -6
- package/assets/skills/spec-next/SKILL.md +145 -60
- package/assets/skills/spec-review/SKILL.md +87 -0
- package/assets/skills/spec-reviewed/SKILL.md +31 -5
- package/assets/skills/spec-start/SKILL.md +19 -0
- package/package.json +1 -1
- package/src/cli.js +940 -116
- package/src/env/classify.js +87 -2
- package/src/env/config.js +214 -17
- package/src/env/hooks.js +49 -9
- package/src/env/live.js +94 -0
- package/src/env/resolve.js +36 -2
- package/src/env/review.js +581 -21
- package/src/env/serve.js +298 -19
- package/src/env/supervise.js +8 -1
- package/src/init.js +88 -13
- /package/assets/hooks/{review-gate.js → review-gate.cjs} +0 -0
|
@@ -154,6 +154,24 @@ Before writing any code for this phase, get the workspace clean:
|
|
|
154
154
|
being *"I am moving on"*, which is what keeps this a push rather than a wall —
|
|
155
155
|
a gate with no exit gets switched off wholesale instead of answered.
|
|
156
156
|
|
|
157
|
+
- **Report anything left waiting, and claim none of it.** Ask the engine once:
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
skitterspec spec-env review waiting
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
A pass listed here arrived when nothing was watching — a wait that never ran,
|
|
164
|
+
a session cleared, a terminal closed overnight — and no watcher can recover
|
|
165
|
+
those, however good. Relay what it prints: the spec, the code, the verdict and
|
|
166
|
+
the age, with `/spec-reviewed <code>` to pick one up and `--drop <code>` to
|
|
167
|
+
disown it.
|
|
168
|
+
|
|
169
|
+
**It is information, not a gate.** It never refuses, nothing here is
|
|
170
|
+
conditional on it, and **you never claim one** — `/spec-diff` §0 stands
|
|
171
|
+
unchanged, and a pass sitting there when you arrived was not sent to you.
|
|
172
|
+
Silent when nothing is waiting, which is the usual case: say nothing rather
|
|
173
|
+
than reporting that there was nothing to report.
|
|
174
|
+
|
|
157
175
|
## 3. Implement the phase
|
|
158
176
|
|
|
159
177
|
Identify the **first unfinished phase** from the `00-overview.md` phase index,
|
|
@@ -269,6 +287,12 @@ skitterspec spec-env review <spec>
|
|
|
269
287
|
the diff never passes through you, so a 266KB patch costs nothing. Report the
|
|
270
288
|
path it prints and move on.
|
|
271
289
|
|
|
290
|
+
**This render takes the committing button set**, which is the default — so
|
|
291
|
+
`--buttons` is not passed. That is a statement about the work, not about the
|
|
292
|
+
gate: the phase is finished, so `Commit` and `Commit & Continue` are the right
|
|
293
|
+
verbs for it. A render part-way through a run takes `--buttons midrun` and
|
|
294
|
+
offers `Continue` instead; `/spec-diff` owns that case.
|
|
295
|
+
|
|
272
296
|
**Then arm the gate**, so the phase now owes a verdict:
|
|
273
297
|
|
|
274
298
|
```
|
|
@@ -293,41 +317,72 @@ so one subject lives in one place:
|
|
|
293
317
|
|
|
294
318
|
## ⏸ Review ready — <N> files, +<a> −<d>
|
|
295
319
|
|
|
296
|
-
**
|
|
320
|
+
- **local** — <the `local:` URL>
|
|
321
|
+
- **network** — <the `network:` URL, or off with the command that turns it on>
|
|
322
|
+
- **remote** — <the `remote:` URL, or off with the command that turns it on>
|
|
297
323
|
|
|
298
|
-
|
|
324
|
+
<the `live:` line, exactly as the engine printed it — omitted when it printed none>
|
|
299
325
|
|
|
300
|
-
|
|
301
|
-
banner carries the served URL and the wait is real. Where it could not serve —
|
|
302
|
-
a busy port, a machine with no network address — that is the case publishing
|
|
303
|
-
exists for, and then the banner carries the published URL with what is true of
|
|
304
|
-
it: *press a verdict, then type `/spec-reviewed`*, because nothing pushes from
|
|
305
|
-
the artifact store into this conversation.
|
|
326
|
+
I'm holding here until you send a verdict — the wait covers local and network.
|
|
306
327
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
328
|
+
`/spec-reviewed` picks it up · `spec-env review skip "<reason>"` moves on
|
|
329
|
+
|
|
330
|
+
**The stack is the engine's — copy it, do not compose it.** `spec-env review`
|
|
331
|
+
printed one line per tier, in that order, and `--json` carries the same thing as
|
|
332
|
+
`tiers`. Relay all three whatever they say, including the ones that are off with
|
|
333
|
+
the command that turns them on: a reader who has left the house cannot ask for a
|
|
334
|
+
remote page they were never shown.
|
|
335
|
+
|
|
336
|
+
**Do not pick one for them.** The engine used to, and the guess failed three
|
|
337
|
+
separate ways in one day. `.claude/rules/spec-reports.md` carries the shape and
|
|
338
|
+
why the *one link, never two* rule now reads
|
|
339
|
+
**one link per reachable store, each labelled** —
|
|
340
|
+
local and network are two doors into one room, so the wait
|
|
341
|
+
covers both. `remote` is a second store, so its own line carries its own caveat:
|
|
342
|
+
*a verdict here needs `/spec-reviewed`*, because nothing pushes from
|
|
343
|
+
the artifact store into this conversation. Never let the holding line promise a
|
|
344
|
+
wait over that tier.
|
|
345
|
+
|
|
346
|
+
**Publishing is still never yours to do.** `remote` reading `off` is the normal
|
|
347
|
+
state, and the fix for it is the command on that line — typed by the operator,
|
|
348
|
+
or pressed on the page, because a published page is one this tooling cannot
|
|
349
|
+
remove and permitting it is not publishing it.
|
|
350
|
+
|
|
351
|
+
**The `live:` line goes with the stack**, and it is the engine's line too —
|
|
352
|
+
copied as printed, and **absent when the engine printed none**. The page can act
|
|
353
|
+
on it: a press puts the spec live or takes it down and hands the reader back the
|
|
354
|
+
same page, which is `/spec-diff` §2b's routing and not this skill's. What
|
|
355
|
+
matters here is that an action **never clears the gate this phase armed** — the
|
|
356
|
+
reader has looked at it running and concluded nothing, so the phase still owes a
|
|
357
|
+
verdict.
|
|
313
358
|
|
|
314
359
|
---
|
|
315
360
|
|
|
316
|
-
**Where you are not waiting, it stays the `Review` row** — the counts
|
|
317
|
-
link and
|
|
361
|
+
**Where you are not waiting, it stays the `Review` row** — the counts and the
|
|
362
|
+
page link, and **no question**:
|
|
363
|
+
|
|
364
|
+
| **Review** | <N> files, +<a> −<d> · **local** <URL> · **network** <URL> · **remote** off |
|
|
318
365
|
|
|
319
|
-
|
|
366
|
+
At the end of a phase you are always waiting, so this shape belongs to the
|
|
367
|
+
renders that are not this step: a mid-phase `/spec-diff`, a page produced
|
|
368
|
+
alongside other work. A row cannot be waited on, so a question in one is
|
|
369
|
+
unanswerable however findable it is.
|
|
320
370
|
|
|
321
371
|
**Both shapes are addressed to someone, and that is the constraint.** The offer
|
|
322
372
|
was once a fenced block of engine output: two quoted lines under the test
|
|
323
373
|
counts, addressed to nobody, with the report then closing on *"commit this
|
|
324
374
|
first"* — the last instruction the reader got was to move on, so they did. A row
|
|
325
|
-
in a labelled table is findable; a
|
|
326
|
-
|
|
327
|
-
|
|
375
|
+
in a labelled table is findable; a banner says the work has stopped. What must
|
|
376
|
+
never come back is something unaddressed, unfindable, or fenced.
|
|
377
|
+
|
|
378
|
+
**The row asks nothing, and that is not a weakening of the above.** A row cannot
|
|
379
|
+
be waited on, so a question in one is unanswerable however findable it is —
|
|
380
|
+
which is the failure `spec-reports.md` records under *asking implies waiting*.
|
|
381
|
+
The row names the page; the banner is what asks, because the banner is the shape
|
|
382
|
+
the run is standing behind.
|
|
328
383
|
|
|
329
384
|
**Never bury it and never split it.** The row sits above the last two rows of
|
|
330
|
-
the block, and the page and
|
|
385
|
+
the block, and the page and its counts stay in the same row; the banner
|
|
331
386
|
replaces the row rather than joining it. Two places naming one page make the reader
|
|
332
387
|
resolve a distinction before acting on either — which is the same failure
|
|
333
388
|
whether the two places are adjacent rows or a row and a banner.
|
|
@@ -336,16 +391,25 @@ whether the two places are adjacent rows or a row and a banner.
|
|
|
336
391
|
|
|
337
392
|
The row is findable, but a row cannot make the continuation follow from the
|
|
338
393
|
reading — and that is the gap the whole gate exists to close.
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
reader pressed is what carries the work on.
|
|
394
|
+
|
|
395
|
+
**The wait is a command. Do not write one.**
|
|
342
396
|
|
|
343
397
|
1. **Note the moment you start waiting**, as an ISO timestamp. That instant is
|
|
344
398
|
the whole scope of what you may claim.
|
|
345
|
-
2. **
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
399
|
+
2. **Run the engine's wait in the background, and end your turn:**
|
|
400
|
+
|
|
401
|
+
```
|
|
402
|
+
skitterspec spec-env review wait <spec> --since <the timestamp>
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
It returns when a pass arrives inside that window, and
|
|
406
|
+
**it takes no timeout unless you pass one** —
|
|
407
|
+
the wait lasts as long as your session, because a reader who walks away from
|
|
408
|
+
a diff is the normal case rather than the edge one. Do not give it a duration
|
|
409
|
+
of your own.
|
|
410
|
+
|
|
411
|
+
Then **end your turn**. Do not poll it and do not hold the turn open: the
|
|
412
|
+
point is that the reader has the terminal back while they read.
|
|
349
413
|
3. **On waking, let the engine pick**:
|
|
350
414
|
|
|
351
415
|
```
|
|
@@ -353,11 +417,26 @@ reader pressed is what carries the work on.
|
|
|
353
417
|
```
|
|
354
418
|
|
|
355
419
|
It claims the one pass that arrived inside the window, and acts on nothing
|
|
356
|
-
at all when none did (the
|
|
357
|
-
when two did (two sittings, or two people — the operator has the
|
|
420
|
+
at all when none did (the wait can be woken by something that was not a
|
|
421
|
+
pass) or when two did (two sittings, or two people — the operator has the
|
|
422
|
+
codes).
|
|
358
423
|
4. **Route on the verdict** exactly as `/spec-diff` §2 and §4 describe. Do not
|
|
359
424
|
restate that routing here.
|
|
360
425
|
|
|
426
|
+
**WHY A COMMAND RATHER THAN A LOOP YOU COMPOSE.** This step used to say "watch
|
|
427
|
+
the pending store" and stop, so every run invented its own watcher in shell —
|
|
428
|
+
and three failed in two days, each reaching the operator as *"I pressed the
|
|
429
|
+
button and nothing happened"*. The worst wrote
|
|
430
|
+
`until [ -f "$P" ] && [ "$x" \> "$y" ]`: valid bash, a syntax error in zsh, a
|
|
431
|
+
predicate that could never be true. It spun for five minutes writing to a
|
|
432
|
+
stderr nobody reads.
|
|
433
|
+
|
|
434
|
+
**The bug is not the lesson — the silence is.** A watcher that can never fire
|
|
435
|
+
and one patiently working are indistinguishable from outside, so nothing about
|
|
436
|
+
that run looked wrong until the operator asked. `review wait` says it has
|
|
437
|
+
started, is written once, and is tested against a store that gains a pass
|
|
438
|
+
mid-flight. A predicate composed fresh each time is proven by nothing.
|
|
439
|
+
|
|
361
440
|
**WHY THIS IS SAFE, AND WHAT IT COSTS.** It was once true that a device
|
|
362
441
|
reaching your page could not reach your conversation, and that fact was the
|
|
363
442
|
whole guard: a pass sat in the holding area until a person typed
|
|
@@ -371,46 +450,52 @@ is that the page can now act, so the token has become a credential rather than
|
|
|
371
450
|
a convenience — and `--claim-since` refusing to choose between two passes is
|
|
372
451
|
what stops a race becoming a wrong commit.
|
|
373
452
|
|
|
374
|
-
**Where the harness cannot
|
|
375
|
-
|
|
376
|
-
|
|
453
|
+
**Where the harness cannot run something in the background, you still wait** —
|
|
454
|
+
the turn ending is the wait. Say the page is rendered and that you are holding
|
|
455
|
+
for the pass, then end your turn; the reader's next message is what carries it,
|
|
456
|
+
and `/spec-diff` picks it up from the paste exactly as it always has. The gate
|
|
457
|
+
holds either way: it is the engine's, not the wait's.
|
|
458
|
+
|
|
459
|
+
This once read *"change nothing"* — keep the row, keep the question, do not
|
|
460
|
+
wait — and that exemption is the hatch a whole class of unanswerable questions
|
|
461
|
+
came through. Every harness can end a turn.
|
|
377
462
|
|
|
378
463
|
**It still does not break a chained run.** `/commit && /spec-next` is typed as
|
|
379
464
|
one line; by the time this step is reached the chain has finished, so waiting
|
|
380
465
|
here stops nothing that was still going to happen.
|
|
381
466
|
|
|
382
|
-
Relay the
|
|
383
|
-
|
|
467
|
+
Relay the engine's **stack** — the `local:`, `network:` and `remote:` lines —
|
|
468
|
+
never the bare `page:` path: a path is not clickable in any terminal, and a page
|
|
469
|
+
nobody can open is a page nobody reads.
|
|
384
470
|
|
|
385
471
|
- **Never write the review unasked**, and **never publish**. Publishing leaves
|
|
386
472
|
something behind that this tooling cannot remove, so it is always something
|
|
387
473
|
someone asks for. A `file://` link is no use on a phone, and saying so **is**
|
|
388
474
|
the ask — publishing is the answer to it, and `/spec-diff` §6 owns how.
|
|
389
|
-
**
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
`file://` URL with its marker, and that is when publishing is worth naming.
|
|
475
|
+
**The `reader:` line no longer decides anything here, and that is the point.**
|
|
476
|
+
It is still printed, and it is still the only place that question is answered —
|
|
477
|
+
but the offer does not change with it, because the stack lists every tier
|
|
478
|
+
whatever it says. Three reader states used to mean three different offers, and
|
|
479
|
+
that branching is exactly what produced a `file://` page on a session detected
|
|
480
|
+
`unknown`, a LAN URL for a phone off the network, and an address that changed
|
|
481
|
+
underneath a reader when detection flipped mid-session.
|
|
482
|
+
|
|
483
|
+
So: **relay all three tier lines, every time.** Any `also:` lines sit under
|
|
484
|
+
`network` — the other addresses this machine has, offered because the
|
|
485
|
+
best-guess one can be wrong — so pass them on rather than editing them out.
|
|
486
|
+
|
|
487
|
+
**Never read an environment variable to decide anything about the offer** — not
|
|
488
|
+
`SSH_CONNECTION`, not `CLAUDE_CODE_*`, not a tty check. There is nothing left
|
|
489
|
+
here for a detection to decide, and a second implementation of one could not be
|
|
490
|
+
tested and would drift.
|
|
491
|
+
|
|
492
|
+
**Serving is the engine's to do; publishing is never.** The server is one
|
|
493
|
+
process, ended by one flag, leaving nothing behind, and `review.allowNetwork`
|
|
494
|
+
decides whether it binds wide — no detection involved. A reader the server CAN
|
|
495
|
+
reach is not a reason to publish as well: the tiers they can already open are on
|
|
496
|
+
the stack. Publishing leaves a page this tooling cannot remove, so it stays an
|
|
497
|
+
ask in every case, always — which is why `remote` shows the command rather than
|
|
498
|
+
a URL until someone types it.
|
|
414
499
|
|
|
415
500
|
- **Never fatal.** A failed render — no worktree, a git error — is one line and
|
|
416
501
|
the phase is still done. The page is a convenience; the repo is the record.
|
|
@@ -102,6 +102,67 @@ resolve it by reading the code, do that instead of asking.
|
|
|
102
102
|
|
|
103
103
|
|
|
104
104
|
|
|
105
|
+
## 4b. Hand the refresh back on a page, then wait
|
|
106
|
+
|
|
107
|
+
**Only when the project has per-spec isolation** (`specs/.core/env.config.json`
|
|
108
|
+
present) **and this review actually changed something.** Either missing → skip
|
|
109
|
+
the whole step in silence.
|
|
110
|
+
|
|
111
|
+
A refreshed spec is a rewrite of a document someone is about to work from, so it
|
|
112
|
+
gets read before it is committed — the same ending `/spec` now has:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
skitterspec spec-env review <spec> --docs --buttons refresh
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`--docs` reads the spec's own documents from the tree you are standing in, so it
|
|
119
|
+
wants no worktree and works for a spec in any bucket. These documents are
|
|
120
|
+
**tracked**, so the diff against `HEAD` is a patch rather than a set of new
|
|
121
|
+
files — which is exactly what the reader wants here: what drifted, and what you
|
|
122
|
+
rewrote.
|
|
123
|
+
|
|
124
|
+
**Render nothing when nothing changed.** `/spec-review` frequently concludes a
|
|
125
|
+
spec is still accurate, and that is a success rather than a gap. A page showing
|
|
126
|
+
an empty diff under a commit button asks for a verdict on nothing, and the
|
|
127
|
+
engine refuses it for the same reason — `nothing to review`. Take that refusal
|
|
128
|
+
as the answer and report the `⏸`/`✅` you already had.
|
|
129
|
+
|
|
130
|
+
**Arm nothing.** No `review arm` here: the gate asserts that a phase which ended
|
|
131
|
+
owes an answer, and a re-validated spec has ended no phase. Walking away leaves
|
|
132
|
+
an uncommitted spec, which is the state this skill has always finished in.
|
|
133
|
+
|
|
134
|
+
### The three endings
|
|
135
|
+
|
|
136
|
+
`--buttons refresh` offers `Commit`, `Request changes` and `Discuss`.
|
|
137
|
+
|
|
138
|
+
**No start verdict, deliberately.** The spec this skill refreshed may already be
|
|
139
|
+
in progress — that is half of what it is used for — so `Commit & Start` would
|
|
140
|
+
offer to provision a worktree for a spec that already has one.
|
|
141
|
+
|
|
142
|
+
- **`commit`** — hand off to `review.commitWith` (`/commit` by default) with the
|
|
143
|
+
pathspec the render reported on `docs.paths`, then finish. The spec keeps
|
|
144
|
+
whatever status step 4 left it in.
|
|
145
|
+
- **`changes`** — work the notes into the spec, record a resolution for each so
|
|
146
|
+
the next render strikes it through with what changed, re-render, and wait
|
|
147
|
+
again.
|
|
148
|
+
- **`discuss`** — report and talk. Claim nothing, change nothing.
|
|
149
|
+
|
|
150
|
+
### Then wait for it
|
|
151
|
+
|
|
152
|
+
**The wait is a command. Do not write one.** Note the moment you start waiting
|
|
153
|
+
as an ISO timestamp, run the engine's wait in the background, and end your turn:
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
skitterspec spec-env review wait <spec> --since <the timestamp>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Pass no timeout. On waking, let the engine pick the pass —
|
|
160
|
+
`skitterspec spec-env review <spec> --docs --claim-since <the timestamp> --json`
|
|
161
|
+
— and route on the verdict above.
|
|
162
|
+
|
|
163
|
+
**Where the page is `file://`** the pass is copied and pasted, so the wait is the
|
|
164
|
+
turn ending and the banner says so. Do not start a watch that cannot fire.
|
|
165
|
+
|
|
105
166
|
## 5. Report
|
|
106
167
|
|
|
107
168
|
Do **not** `git commit` unless the user asks.
|
|
@@ -122,6 +183,32 @@ the shape; this section carries only what is specific here.
|
|
|
122
183
|
API that moved, a task the code already does. `Spec` carries the status the
|
|
123
184
|
review leaves it in, which is the answer to "can I start this?".
|
|
124
185
|
|
|
186
|
+
**Where step 4b rendered a page the run is waiting**, so the block omits the
|
|
187
|
+
`Review` row and ends on the banner from `.claude/rules/spec-reports.md` — the
|
|
188
|
+
tier stack copied from the engine's own lines, never one link chosen for the
|
|
189
|
+
reader:
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## ⏸ Review ready — <N> files, +<a> −<d>
|
|
194
|
+
|
|
195
|
+
- **local** — <the `local:` URL>
|
|
196
|
+
- **network** — <the `network:` URL, or off with the command that turns it on>
|
|
197
|
+
- **remote** — <the `remote:` URL, or off with the command that turns it on>
|
|
198
|
+
|
|
199
|
+
I'm holding here until you send a verdict — the wait covers local and network.
|
|
200
|
+
|
|
201
|
+
`Commit` commits the refresh · `Request changes` works them now
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
`Next` then names the page rather than a command, because the button is what
|
|
206
|
+
carries the work on.
|
|
207
|
+
|
|
208
|
+
Where nothing was rendered — no isolation, or no drift to show — `Next` is
|
|
209
|
+
`/commit, then /spec-start <name>`, since this skill does not commit and
|
|
210
|
+
`/spec-start` refuses a tree holding anything that is not the spec's.
|
|
211
|
+
|
|
125
212
|
**Drift found and not fixed is a `Follow-up`, not a silence.** A spec this skill
|
|
126
213
|
declared reviewed is one nobody will re-read; something it noticed and left
|
|
127
214
|
undone has to leave the session in writing or it did not happen.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spec-reviewed
|
|
3
|
-
description: Pick up the review you approved on the page — run it bare to pick up the single waiting pass, paste the six-digit code off the page ("/spec-reviewed 608223") to name one exactly,
|
|
3
|
+
description: Pick up the review you approved on the page — run it bare to pick up the single waiting pass, paste the six-digit code off the page ("/spec-reviewed 608223") to name one exactly, or pass the verdict itself ("/spec-reviewed commit") when the page could not send and copied you a command instead. Use when the user says "/spec-reviewed", "I approved it", "I've reviewed it", "pick up my review", "I pressed approve", or otherwise says they have finished reviewing a rendered diff.
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -70,16 +70,42 @@ Several provisioned and none resolved is a refusal — relay its list and stop,
|
|
|
70
70
|
never pick from it. See `.claude/rules/spec-planning.md`; do not restate the
|
|
71
71
|
rule here.
|
|
72
72
|
|
|
73
|
-
**
|
|
74
|
-
matches `^\d{6}$`; a **
|
|
75
|
-
**
|
|
76
|
-
|
|
73
|
+
**Four argument shapes, and they cannot collide.** A **six-digit code**
|
|
74
|
+
matches `^\d{6}$`; a **verdict** is one of a closed list of six words;
|
|
75
|
+
a **tracker id** carries a letter and a hyphen;
|
|
76
|
+
a **spec name** is none of them and always carries a lifecycle prefix
|
|
77
|
+
(`feat-`, `bug-`, `hotfix-`), which no verdict does. So the parse needs no flag,
|
|
78
|
+
and nothing has to be guessed at from context.
|
|
77
79
|
|
|
78
80
|
A **six-digit code** is a pass the operator read off their own page. It says
|
|
79
81
|
**which pass**, not which spec — so resolve the spec exactly as a bare
|
|
80
82
|
invocation does, above, and claim the code *there*. Then go to step 4 — a named
|
|
81
83
|
pass has nothing to disambiguate.
|
|
82
84
|
|
|
85
|
+
A **verdict word** — `commit`, `commit-continue`, `commit-start`, `continue`,
|
|
86
|
+
`changes`, `discuss` — is the conclusion itself, arriving without a pass behind
|
|
87
|
+
it. It is
|
|
88
|
+
what a **`file://` page** hands over: that page has no server to POST to and no
|
|
89
|
+
store to write to, so it copies a command instead of sending anything, and this
|
|
90
|
+
is the command. Resolve the spec as a bare invocation does, then send the word
|
|
91
|
+
through the engine:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
skitterspec spec-env review <spec> --verdict <word>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
It joins the same merge a claimed pass goes through, so the routing in step 4
|
|
98
|
+
is unchanged: a commit over open notes is refused exactly as it would be, the
|
|
99
|
+
outcome log records it, and the gate a phase armed is cleared. Then go to step
|
|
100
|
+
4 — there is nothing to disambiguate.
|
|
101
|
+
|
|
102
|
+
**A word carries a verdict and nothing else**, and that is a property of the
|
|
103
|
+
transport, not a shortcut. Accepts and comments do not fit on a command line,
|
|
104
|
+
so the page only ever offers the words while the reader has marked nothing —
|
|
105
|
+
the moment they tick an accept or write a note it goes back to handing over the
|
|
106
|
+
blob. If someone tells you they marked things up *and* gives you a word, ask
|
|
107
|
+
for the pass: the word would land a verdict with their notes silently dropped.
|
|
108
|
+
|
|
83
109
|
A **name** targets that spec instead. A **tracker id** does too, but only
|
|
84
110
|
through a **provider seam**: the base knows nothing about tracker ids, so
|
|
85
111
|
resolve one by asking whichever provider is installed for its listing —
|
|
@@ -268,6 +268,25 @@ here beyond knowing it is no longer dead code.
|
|
|
268
268
|
A spec ideally arrives `Ready` from `/spec`; a `Draft` works too — sanity-check
|
|
269
269
|
it is well-formed first.
|
|
270
270
|
|
|
271
|
+
- **Report anything left waiting, and claim none of it.** Ask the engine once:
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
skitterspec spec-env review waiting
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
A pass listed here arrived when nothing was watching — a wait that never ran,
|
|
278
|
+
a session cleared, a terminal closed overnight — and no watcher can recover
|
|
279
|
+
those, however good. Relay what it prints: the spec, the code, the verdict and
|
|
280
|
+
the age, with `/spec-reviewed <code>` to pick one up and `--drop <code>` to
|
|
281
|
+
disown it.
|
|
282
|
+
|
|
283
|
+
**It is information, not a gate.** It never refuses, nothing here is
|
|
284
|
+
conditional on it, and **you never claim one** — `/spec-diff` §0 stands
|
|
285
|
+
unchanged, and a pass sitting there when you arrived was not sent to you.
|
|
286
|
+
Silent when nothing is waiting, which is the usual case: say nothing rather
|
|
287
|
+
than reporting that there was nothing to report.
|
|
288
|
+
|
|
289
|
+
|
|
271
290
|
## 4b. Note a missing gating decision (only if configured)
|
|
272
291
|
|
|
273
292
|
**Only when `specs/.core/gating.config.json` exists.** Run
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skitterbyte/skitterspec",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "22.0.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",
|