@skitterbyte/skitterspec 21.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/MIGRATION.md +218 -0
- package/README.md +127 -6
- package/assets/claude-md-section.md +42 -18
- package/assets/commands/allow-main.md +33 -0
- package/assets/commands/spec-remote-review.md +22 -0
- package/assets/commands/spec-skip.md +24 -0
- package/assets/core/env.config.json.example +6 -3
- package/assets/core/env.config.md +183 -25
- package/assets/hooks/main-guard.cjs +145 -0
- package/assets/hooks/review-gate.cjs +8 -3
- package/assets/review/page.html +1174 -101
- package/assets/rules/offered-unblocks.md +100 -0
- package/assets/rules/spec-planning.md +195 -14
- package/assets/rules/spec-reports.md +181 -29
- package/assets/skills/no-spec/SKILL.md +219 -0
- package/assets/skills/spec/SKILL.md +248 -21
- package/assets/skills/spec-bug/SKILL.md +34 -24
- 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 +164 -37
- package/assets/skills/spec-hotfix/SKILL.md +22 -19
- package/assets/skills/spec-init/SKILL.md +4 -2
- package/assets/skills/spec-next/SKILL.md +166 -58
- 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 +33 -0
- package/package.json +1 -1
- package/src/cli.js +1612 -172
- package/src/env/classify.js +87 -2
- package/src/env/config.js +333 -19
- package/src/env/hooks.js +102 -33
- package/src/env/live.js +124 -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 +128 -5
- package/src/env/review.js +854 -29
- package/src/env/reviewers/coderabbit.js +228 -0
- package/src/env/reviewers.js +517 -0
- package/src/env/serve.js +474 -50
- package/src/env/supervise.js +8 -1
- package/src/env/teardown.js +12 -1
- package/src/init.js +185 -24
|
@@ -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`.
|
|
@@ -249,6 +280,157 @@ open questions, `Draft` when you deliberately left some unresolved. Either way
|
|
|
249
280
|
the next step is `/spec-start`. The Report section below is where all of that
|
|
250
281
|
reaches the user — do not narrate it here as well.
|
|
251
282
|
|
|
283
|
+
## Phase C2 — render the spec, then wait for the verdict
|
|
284
|
+
|
|
285
|
+
**Only when the project has per-spec isolation** (`specs/.core/env.config.json`
|
|
286
|
+
present). Without it there is no page and this phase does not exist — skip it in
|
|
287
|
+
silence rather than explaining an absence.
|
|
288
|
+
|
|
289
|
+
A spec is the one artefact whose whole purpose is to be
|
|
290
|
+
**read before work begins**, and until now it was the only one with no reading
|
|
291
|
+
surface: `/spec`
|
|
292
|
+
finished, the spec sat uncommitted, and `/spec-start` had to point that out and
|
|
293
|
+
commit it as a side effect of provisioning. So this phase ends where every other
|
|
294
|
+
phase of the lifecycle ends — on a page, in a verdict.
|
|
295
|
+
|
|
296
|
+
```
|
|
297
|
+
skitterspec spec-env review <spec> --docs --buttons authoring
|
|
298
|
+
```
|
|
299
|
+
|
|
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.
|
|
307
|
+
|
|
308
|
+
**This is free.** The engine reads git and splices text into a template; the
|
|
309
|
+
diff never passes through you.
|
|
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
|
+
|
|
317
|
+
**Render nothing when nothing was written.** A `⏸` run — grilling that never
|
|
318
|
+
reached a shared understanding — has no spec to show, and must not ask for a
|
|
319
|
+
verdict on one.
|
|
320
|
+
|
|
321
|
+
**Arm nothing.** There is no `spec-env review arm` in this path, and that is a
|
|
322
|
+
decision rather than an omission: the gate asserts that *a phase which ended*
|
|
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.
|
|
334
|
+
|
|
335
|
+
### The two endings this page offers
|
|
336
|
+
|
|
337
|
+
`--buttons authoring` offers `Commit & Start` and `Commit` in place of the
|
|
338
|
+
committing pair, because "commit and build the next phase" is meaningless for a
|
|
339
|
+
spec with no phase in flight.
|
|
340
|
+
|
|
341
|
+
- **`commit-start`** — hand off to `review.commitWith` (`/commit` by default),
|
|
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.
|
|
382
|
+
- **`changes`** — work the notes into the spec, record a resolution for each one
|
|
383
|
+
so the next render shows it struck through with what changed, then
|
|
384
|
+
**re-render, and wait again**. The reader is still holding a decision, so
|
|
385
|
+
ending the turn and
|
|
386
|
+
making them type `/spec-diff` would reopen the loop this exists to close.
|
|
387
|
+
- **`discuss`** — report and talk. Claim nothing, change nothing.
|
|
388
|
+
|
|
389
|
+
**Take the pathspec from the render, not from the tree.** A checkout is shared,
|
|
390
|
+
so the set of this spec's uncommitted documents can differ between the render and
|
|
391
|
+
the verdict — and the reader's conclusion is about what the page showed them.
|
|
392
|
+
|
|
393
|
+
### Then wait for it
|
|
394
|
+
|
|
395
|
+
**The wait is a command. Do not write one.**
|
|
396
|
+
|
|
397
|
+
1. **Note the moment you start waiting**, as an ISO timestamp. That instant is
|
|
398
|
+
the whole scope of what you may claim.
|
|
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 takes no timeout unless you pass one, and you must not pass one: a reader
|
|
406
|
+
who walks away from a spec is the normal case, and a bounded watch once lost a
|
|
407
|
+
verdict to a lunch break.
|
|
408
|
+
3. **On waking, let the engine pick:**
|
|
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
|
+
|
|
415
|
+
```
|
|
416
|
+
skitterspec spec-env review <spec> --docs --claim-since <the timestamp> --json
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
It claims the one pass that arrived inside the window, acts on nothing when
|
|
420
|
+
none did, and refuses to choose when two did.
|
|
421
|
+
4. **Route on the verdict** as above.
|
|
422
|
+
|
|
423
|
+
**Where the page is `file://`** — the engine could not serve — there is no server
|
|
424
|
+
to POST to, so the pass is copied and pasted and the reader's next message is
|
|
425
|
+
what carries it. **Do not start a watch that cannot fire**: a wait on the pending
|
|
426
|
+
store would spin forever while the report underneath it claimed to be holding,
|
|
427
|
+
which is the exact failure `.claude/rules/spec-reports.md` records. The wait is
|
|
428
|
+
the turn ending, and the banner says so.
|
|
429
|
+
|
|
430
|
+
Relay the engine's **stack** — the `local:`, `network:` and `remote:` lines, all
|
|
431
|
+
three, in that order — never the bare `page:` path. `.claude/rules/spec-reports.md`
|
|
432
|
+
carries the shape and why every tier is named rather than one being chosen.
|
|
433
|
+
|
|
252
434
|
## Phase D — record the isolation stack (only if configured)
|
|
253
435
|
|
|
254
436
|
**Only when `specs/.core/env.config.json` exists** (per-spec isolation is
|
|
@@ -293,16 +475,61 @@ the shape; this section carries only what is specific here.
|
|
|
293
475
|
|
|
294
476
|
- `✅` — a `Ready` spec is written to `specs/backlog/<name>/`.
|
|
295
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.
|
|
296
481
|
- `⏸` — grilling did not reach a shared understanding, so nothing was written.
|
|
297
482
|
That is the skill working: a spec written over an unresolved requirement is
|
|
298
483
|
the outcome Phase A exists to prevent.
|
|
299
484
|
|
|
300
|
-
**Fields:** `Tracker` · `Spec` · `Built` · `Follow-ups` ·
|
|
485
|
+
**Fields:** `Tracker` · `Spec` · `Built` · `Landed` · `Worktree` · `Follow-ups` ·
|
|
486
|
+
`Next`
|
|
301
487
|
|
|
302
488
|
`Built` is the spec's path and phase count; `Spec` is its status and bucket;
|
|
303
|
-
`Next` is `/spec-start <name>`, with the name spelled the way it must be typed.
|
|
304
489
|
`Tracker` appears only when a provider is installed and linked it.
|
|
305
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
|
+
|
|
497
|
+
**`Next` depends on whether Phase C2 rendered a page.** Where it did, the run is
|
|
498
|
+
waiting on a verdict, so the block **omits the `Review` row** and ends on the
|
|
499
|
+
banner defined in `.claude/rules/spec-reports.md` — counts, the tier stack, and
|
|
500
|
+
this page's two exits:
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
## ⏸ Review ready — <N> files, +<a> −<d>
|
|
505
|
+
|
|
506
|
+
- **local** — <the `local:` URL>
|
|
507
|
+
- **network** — <the `network:` URL, or off with the command that turns it on>
|
|
508
|
+
- **remote** — <the `remote:` URL, or off with the command that turns it on>
|
|
509
|
+
|
|
510
|
+
I'm holding here until you send a verdict — the wait covers local and network.
|
|
511
|
+
|
|
512
|
+
`Commit & Start` puts it in flight · `Commit` keeps it for later
|
|
513
|
+
|
|
514
|
+
---
|
|
515
|
+
|
|
516
|
+
There `Next` names the page rather than a command, because the button is what
|
|
517
|
+
carries the work on.
|
|
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
|
+
|
|
524
|
+
Where no page was rendered — isolation is not configured, or nothing was
|
|
525
|
+
written — `Next` is `/spec-start <name>`, with the name spelled the way it must
|
|
526
|
+
be typed.
|
|
527
|
+
|
|
528
|
+
**A spec written without a page is still uncommitted**, so that `Next` relies on
|
|
529
|
+
`/spec-start` committing the spec when it is all that is uncommitted. Say
|
|
530
|
+
`/commit, then /spec-start <name>` when anything else is uncommitted too, or the
|
|
531
|
+
row sends the reader to a refusal.
|
|
532
|
+
|
|
306
533
|
**`Follow-ups` is almost always `none` here.** This skill's whole job is to
|
|
307
534
|
capture work, so anything it surfaced belongs in the spec it just wrote rather
|
|
308
535
|
than in a follow-up line beneath it.
|
|
@@ -231,11 +231,18 @@ skitterspec spec-env review arm <spec>
|
|
|
231
231
|
```
|
|
232
232
|
|
|
233
233
|
**Then wait**, and `/spec-next` §5 owns the sequence — follow it there rather
|
|
234
|
-
than reading a second copy here: note the moment
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
234
|
+
than reading a second copy here: note the moment, run
|
|
235
|
+
`skitterspec spec-env review wait <spec> --since <that moment>` in the
|
|
236
|
+
background, end your turn, and let `--claim-since` pick the one pass that
|
|
237
|
+
arrived inside the window. **Do not compose a watcher**, and do not give the
|
|
238
|
+
wait a timeout — the reasoning is in `/spec-next` §5 and is not repeated here.
|
|
239
|
+
The banner it describes is what this skill emits in place of a `Review` row,
|
|
240
|
+
and the routing on the verdict is `/spec-diff` §2 and §4, as it is everywhere.
|
|
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.
|
|
239
246
|
|
|
240
247
|
**Why this skill arms as well as waits.** Waiting is what any offer does;
|
|
241
248
|
**arming** asserts an obligation that outlives the turn, and belongs only to
|
|
@@ -256,30 +263,33 @@ this worktree is refused until a verdict is sent or
|
|
|
256
263
|
`skitterspec spec-env review skip "<reason>"` records the decision to move on.
|
|
257
264
|
The exit is always one command, and one of them is *"I am moving on"*.
|
|
258
265
|
|
|
259
|
-
Relay the
|
|
260
|
-
|
|
266
|
+
Relay the engine's **stack** — the `local:`, `network:` and `remote:` lines, all
|
|
267
|
+
three — rather than the bare `page:` path: a path is not clickable in any
|
|
268
|
+
terminal, and a page nobody can open is a page nobody reads. Relay the `live:`
|
|
269
|
+
line with it where the engine printed one, and nothing where it did not.
|
|
270
|
+
`.claude/rules/spec-reports.md` carries the shape, including why a rigid
|
|
271
|
+
contract took that line.
|
|
261
272
|
|
|
262
273
|
- **Never write the review unasked**, and **never publish**. Publishing leaves
|
|
263
274
|
something behind that this tooling cannot remove, so it is always an ask. A
|
|
264
275
|
`file://` link is no use on a phone, and saying so **is** the ask —
|
|
265
276
|
`/spec-diff` §6 owns how.
|
|
266
|
-
**
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
drift.
|
|
277
|
+
**The `reader:` line no longer decides anything here, and that is the point.**
|
|
278
|
+
It is still printed, and it is still the only place that question is answered —
|
|
279
|
+
but the offer does not change with it, because the stack lists every tier
|
|
280
|
+
whatever it says. Three reader states used to mean three different offers, and
|
|
281
|
+
that branching is exactly what produced a `file://` page on a session detected
|
|
282
|
+
`unknown`, a LAN URL for a phone off the network, and an address that changed
|
|
283
|
+
underneath a reader when detection flipped mid-session.
|
|
284
|
+
|
|
285
|
+
So: **relay all three tier lines, every time.** Any `also:` lines sit under
|
|
286
|
+
`network` — the other addresses this machine has, offered because the
|
|
287
|
+
best-guess one can be wrong — so pass them on rather than editing them out.
|
|
288
|
+
|
|
289
|
+
**Never read an environment variable to decide anything about the offer** — not
|
|
290
|
+
`SSH_CONNECTION`, not `CLAUDE_CODE_*`, not a tty check. There is nothing left
|
|
291
|
+
here for a detection to decide, and a second implementation of one could not be
|
|
292
|
+
tested and would drift.
|
|
283
293
|
|
|
284
294
|
**Serving is the engine's to do; publishing is never.** A `remote` reader
|
|
285
295
|
authorises a local server — one process, ended by one flag, leaving nothing
|
|
@@ -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.
|