@skitterbyte/skitterspec 17.0.0 → 18.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 +52 -0
- package/assets/claude-md-section.md +10 -0
- package/assets/core/env.config.json.example +3 -0
- package/assets/core/env.config.md +36 -11
- package/assets/core/gating.config.json.example +4 -0
- package/assets/core/gating.config.md +81 -0
- package/assets/rules/spec-planning.md +31 -10
- package/assets/skills/spec/SKILL.md +31 -8
- package/assets/skills/spec-bug/SKILL.md +21 -18
- package/assets/skills/spec-cancel/SKILL.md +16 -2
- package/assets/skills/spec-complete/SKILL.md +47 -15
- package/assets/skills/spec-hotfix/SKILL.md +30 -11
- package/assets/skills/spec-init/SKILL.md +15 -2
- package/assets/skills/spec-next/SKILL.md +2 -2
- package/assets/skills/spec-review/SKILL.md +19 -6
- package/assets/skills/spec-start/SKILL.md +133 -53
- package/assets/skills/spec-to-main/SKILL.md +14 -14
- package/package.json +1 -1
- package/src/cli.js +209 -3
- package/src/env/classify.js +91 -0
- package/src/env/config.js +15 -0
- package/src/env/provision.js +145 -11
- package/src/env/resolve.js +1 -0
- package/src/gating.js +155 -0
- package/src/init.js +28 -1
- package/src/prompts.js +10 -1
|
@@ -63,9 +63,12 @@ that header — must exist **before** `spec-env up`:
|
|
|
63
63
|
-b hotfix/<slug> <tag>` command (the branch forks from **the tag**, not
|
|
64
64
|
`main`), the worktree path, the opener, and any `in the worktree, run:`
|
|
65
65
|
bootstrap steps.
|
|
66
|
-
- Run the printed `git worktree add
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
- Run the printed `git worktree add`, then **move the stub across yourself.**
|
|
67
|
+
This is where a hotfix differs from `/spec-bug`, which no longer needs the move:
|
|
68
|
+
that skill's worktree forks from `main`, so committing the stub puts it there,
|
|
69
|
+
while **this worktree is checked out at the tag** — a commit on `main` is not in
|
|
70
|
+
it and never will be. The move is not redundant here; keep it.
|
|
71
|
+
**Create the destination bucket first:**
|
|
69
72
|
|
|
70
73
|
```
|
|
71
74
|
mkdir -p <worktreePath>/specs/in-progress
|
|
@@ -74,14 +77,13 @@ that header — must exist **before** `spec-env up`:
|
|
|
74
77
|
|
|
75
78
|
The `mkdir -p` is not belt-and-braces. Git does not store empty directories, so
|
|
76
79
|
`specs/in-progress/` is **absent** from the worktree whenever nothing was in
|
|
77
|
-
progress at that point in history — and here that point is an
|
|
78
|
-
tag**, where it is absent more often than not. `mv` into a
|
|
79
|
-
renames your spec folder **to** `specs/in-progress`,
|
|
80
|
-
end up one level too high, `00-overview.md` sits
|
|
81
|
-
every later step still appears to work until
|
|
82
|
-
Confirm the result before carrying on — you
|
|
83
|
-
`<worktreePath>/specs/in-progress/hotfix-<name>/00-overview.md`.
|
|
84
|
-
- **Bootstrap the worktree.** A fresh worktree has no installed dependencies and
|
|
80
|
+
progress at that point in history — and here that point is an
|
|
81
|
+
**old release tag**, where it is absent more often than not. `mv` into a
|
|
82
|
+
missing destination renames your spec folder **to** `specs/in-progress`,
|
|
83
|
+
silently: the spec's files end up one level too high, `00-overview.md` sits
|
|
84
|
+
where the bucket should be, and every later step still appears to work until
|
|
85
|
+
something cannot find the spec. Confirm the result before carrying on — you
|
|
86
|
+
want `<worktreePath>/specs/in-progress/hotfix-<name>/00-overview.md`. - **Bootstrap the worktree.** A fresh worktree has no installed dependencies and
|
|
85
87
|
none of the repo's gitignored files (`.env`, local overrides). Run the printed
|
|
86
88
|
`in the worktree, run:` steps (file seeding, then `setup`) in order, before
|
|
87
89
|
anything else.
|
|
@@ -123,6 +125,8 @@ is usually a single-pass fix, so the `## Fix` block can live directly in
|
|
|
123
125
|
> **Base version:** <tag prod is running, e.g. v33.16.4>
|
|
124
126
|
> **Raised:** <YYYY-MM-DD (today)>
|
|
125
127
|
> **Area:** <files/modules>
|
|
128
|
+
> **Gating:** <pre-filled "none: hotfix — restoring released behaviour"; only
|
|
129
|
+
> when release gating is configured, and overridable — see below>
|
|
126
130
|
|
|
127
131
|
## Symptom
|
|
128
132
|
|
|
@@ -189,6 +193,21 @@ narrative and decisions).
|
|
|
189
193
|
|
|
190
194
|
|
|
191
195
|
|
|
196
|
+
### Release gating (only when configured)
|
|
197
|
+
|
|
198
|
+
**Only when `specs/.core/gating.config.json` exists.** A hotfix is the one spec
|
|
199
|
+
type that does **not** ask the question cold: it writes
|
|
200
|
+
`none: hotfix — restoring released behaviour` and asks only for confirmation.
|
|
201
|
+
|
|
202
|
+
The default differs on purpose. A hotfix restores behaviour a release already
|
|
203
|
+
had, under time pressure, and the fix is captured by a deploy tag rather than
|
|
204
|
+
riding the next release — so a flag has nothing to gate and nothing to roll back
|
|
205
|
+
to. Making someone answer a design question mid-incident buys nothing.
|
|
206
|
+
|
|
207
|
+
It is a **default, not a rule**: say what you are writing and let the user
|
|
208
|
+
override it. If they name a flag, record that instead. Skip entirely when the
|
|
209
|
+
config is absent.
|
|
210
|
+
|
|
192
211
|
## 6. Drive to GREEN
|
|
193
212
|
|
|
194
213
|
- Implement the **minimal, root-cause** fix on the branch. Match surrounding code;
|
|
@@ -37,6 +37,19 @@ checkout you are already in; one spec at a time, no hand-off). It is a question
|
|
|
37
37
|
about how the operator works, not about what the repo contains, so ask rather
|
|
38
38
|
than infer it from whether dev servers or Docker are configured.
|
|
39
39
|
|
|
40
|
+
## 0b. Release gating (optional, and separate)
|
|
41
|
+
|
|
42
|
+
Ask whether specs should record a **release-gating** decision — does this change
|
|
43
|
+
ship behind a feature flag, or land live? Adopting it copies
|
|
44
|
+
`specs/.core/gating.config.json.example` → `gating.config.json` and sets
|
|
45
|
+
`guidance` to wherever this project documents its flags.
|
|
46
|
+
|
|
47
|
+
It is **orthogonal to isolation**: a project can adopt either, both, or neither.
|
|
48
|
+
Skitterspec never learns how the flags work — it asks the question, cites that
|
|
49
|
+
path, and records the answer on each spec. Leave it off and nothing appears:
|
|
50
|
+
no question, no header, no check. Off is a perfectly good answer for a project
|
|
51
|
+
that does not use flags.
|
|
52
|
+
|
|
40
53
|
## 1. Folders
|
|
41
54
|
|
|
42
55
|
Create any that are missing; drop a `.gitkeep` into ones that would otherwise be
|
|
@@ -80,8 +93,8 @@ Ensure it exists. If missing, create it documenting:
|
|
|
80
93
|
- the **Author** / **Developer** header fields;
|
|
81
94
|
- the **State log** audit table (folder/status transitions), kept separate from
|
|
82
95
|
the **Changelog** (decisions);
|
|
83
|
-
- the project's concrete typecheck/test commands, and the rule that
|
|
84
|
-
phase ends with creating + running tests**.
|
|
96
|
+
- the project's concrete typecheck/test commands, and the rule that
|
|
97
|
+
**every phase ends with creating + running tests**.
|
|
85
98
|
|
|
86
99
|
Read a sibling spec skill (e.g. `spec`, `spec-next`) for the canonical shapes
|
|
87
100
|
rather than inventing them. If the rule already exists, leave it unless stale.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spec-next
|
|
3
|
-
description: Build the next unfinished phase of the spec
|
|
3
|
+
description: Build the next unfinished phase of the spec in flight for this session — pre-flight, implement with tests, record progress and refresh the tracker. Refuses when no spec is in flight rather than guessing one, and never builds a spec it is not standing in. Use when the user says "/spec-next", "build the next phase", "continue the spec", or "carry on with this spec".
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /spec-next — build the next phase of the spec in flight
|
|
@@ -26,7 +26,7 @@ Resolve **in this order**, and stop at the first that answers:
|
|
|
26
26
|
branch the checkout is on names the spec.
|
|
27
27
|
|
|
28
28
|
**If none answers, refuse and stop:**
|
|
29
|
-
`no spec in flight — run /spec-start <name> to
|
|
29
|
+
`no spec in flight — run /spec-start <name> to start one`.
|
|
30
30
|
|
|
31
31
|
**Never fall back to the spec "in context".** A spec discussed in conversation
|
|
32
32
|
is not a spec in flight, and this skill writes real code: building the wrong
|
|
@@ -44,6 +44,19 @@ trust the spec's own wording — verify:
|
|
|
44
44
|
- **Backward compatibility.** Re-confirm the planned API/schema changes are still
|
|
45
45
|
additive/safe given the current code (see the project's compatibility rules).
|
|
46
46
|
|
|
47
|
+
### Release gating (only when configured)
|
|
48
|
+
|
|
49
|
+
**Only when `specs/.core/gating.config.json` exists.** Run
|
|
50
|
+
`skitterspec gating check <spec>`. A spec it names has no recorded gating
|
|
51
|
+
decision — or a bare `none` that records nothing — and that is
|
|
52
|
+
**drift like any other**: the question was never asked, or its answer was lost. Grill for it in
|
|
53
|
+
step 3 and write the header in step 4, exactly as you would a stale file path.
|
|
54
|
+
|
|
55
|
+
**This check is advisory.** It reports; it never refuses, and nothing below is
|
|
56
|
+
conditional on it. A spec written before the project adopted gating has no header
|
|
57
|
+
and is not broken — turning this into a gate would accuse the very specs the
|
|
58
|
+
feature was designed not to disturb.
|
|
59
|
+
|
|
47
60
|
## 3. Grill only where a decision is needed
|
|
48
61
|
|
|
49
62
|
Where the drift forces a choice (the old approach no longer fits, a referenced
|
|
@@ -54,12 +67,12 @@ resolve it by reading the code, do that instead of asking.
|
|
|
54
67
|
|
|
55
68
|
## 4. Update the spec
|
|
56
69
|
|
|
57
|
-
- Rewrite stale **Decisions** / **Solution overview** and refresh the
|
|
58
|
-
map** in `00-overview.md`, and stale **tasks** in the phase files,
|
|
59
|
-
match the current code and the resolved questions. Add/remove tasks
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
completed `[x]` history**.
|
|
70
|
+
- Rewrite stale **Decisions** / **Solution overview** and refresh the
|
|
71
|
+
**Impact map** in `00-overview.md`, and stale **tasks** in the phase files,
|
|
72
|
+
so they match the current code and the resolved questions. Add/remove tasks
|
|
73
|
+
within a phase file; add a new phase by creating a `0N-<slug>.md` file
|
|
74
|
+
**and** a matching overview index row, or drop a dead phase by removing both.
|
|
75
|
+
Keep the index and files in sync; **preserve completed `[x]` history**.
|
|
63
76
|
- **A phase's status is the `⬜`/`🔄`/`✅` on its H1** — `# Phase 2 — <goal> 🔄`.
|
|
64
77
|
It is mirrored in that file's `> **Status:**` line and in the matching
|
|
65
78
|
`00-overview.md` phase-index row, but the **heading is the authoritative one**:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spec-start
|
|
3
|
-
description: Put a spec in flight
|
|
3
|
+
description: Put a spec in flight — provision its branch, move it to in-progress, refresh the tracker, then build phase 1. Commits the spec itself when that is all that is uncommitted, and refuses to touch anyone else's unfinished work. Use when the user says "/spec-start", "start this spec", or "begin implementing <spec>".
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /spec-start — put a spec in flight
|
|
@@ -12,30 +12,49 @@ finishing it is `/spec-complete`.
|
|
|
12
12
|
|
|
13
13
|
## 1. The gate — refuse unless the workbench is free
|
|
14
14
|
|
|
15
|
-
**Check this first, before resolving anything or touching a file.**
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
**Check this first, before resolving anything or touching a file.** What the
|
|
16
|
+
gate demands depends on the mode, because the two modes hold work in different
|
|
17
|
+
places — read `mode` from `specs/.core/env.config.json` (default `worktree`).
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
**`worktree` mode — the tree must be clean, and that is all.** The spec is built
|
|
20
|
+
in its own worktree, so another spec being in flight is not a conflict; it is the
|
|
21
|
+
parallelism the mode exists for. The only requirement is that this checkout has
|
|
22
|
+
no uncommitted work — *except* the spec you are starting, which `spec-env up`
|
|
23
|
+
commits for you (see below). Nothing is switched here and nothing is parked.
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
**`checkout` mode — the workbench must be free**: on the base branch (`main`, or
|
|
26
|
+
the configured `baseBranch`) and clean, since the branch is built right here and
|
|
27
|
+
this mode holds one spec at a time. If it isn't, relay what is in flight and
|
|
28
|
+
stop — name the spec holding the checkout and the two ways out, then end your
|
|
29
|
+
turn:
|
|
24
30
|
|
|
25
31
|
- **`/spec-complete`** — it's finished; land it and free the workbench.
|
|
26
32
|
- **`/spec-cancel`** — it isn't wanted; record why and free the workbench.
|
|
27
|
-
- **`/spec-live main`** *(worktree mode)* — park it: the branch goes back to its
|
|
28
|
-
worktree and stays exactly as it is, ready to resume later.
|
|
29
33
|
|
|
30
|
-
**Never get past the gate yourself.** Do not stash, do not commit
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
an afternoon.
|
|
34
|
+
**Never get past the gate yourself.** Do not stash, do not commit
|
|
35
|
+
**another spec's** work, do not switch branches for them. An uncommitted tree
|
|
36
|
+
and a half-built phase are each a decision someone must make deliberately — and
|
|
37
|
+
the cost of guessing is another spec's work moved without its author asking. A
|
|
38
|
+
refusal costs one command; the alternative can cost an afternoon.
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
**The one exception is the spec you are starting.** `spec-env up` classifies the
|
|
41
|
+
uncommitted tree against the target spec and answers one of three ways — relay
|
|
42
|
+
what it says rather than deciding for yourself:
|
|
43
|
+
|
|
44
|
+
| What it found | What it does |
|
|
45
|
+
|---------------|--------------|
|
|
46
|
+
| clean | provisions, as always |
|
|
47
|
+
| every path belongs to this spec | plans `git add` + `git commit` **first**, then the fork |
|
|
48
|
+
| any path does not | refuses, naming the paths that disqualified it |
|
|
49
|
+
|
|
50
|
+
That is membership in an exactly-known set — the spec's own folder plus the
|
|
51
|
+
project's `spec.companionPaths` — and **not** a judgement about whether the
|
|
52
|
+
changes look important. The gate still never decides that. When it plans the
|
|
53
|
+
commit, the paths are printed above the commands, so run them as printed; when it
|
|
54
|
+
refuses, relay the reason and stop.
|
|
55
|
+
|
|
56
|
+
It also refuses a **clean** tree whose spec is not in the commit the worktree
|
|
57
|
+
would fork from — otherwise you get a branch missing the very spec it is for.
|
|
39
58
|
|
|
40
59
|
## 2. Identify the spec
|
|
41
60
|
|
|
@@ -48,51 +67,88 @@ not try to judge whether the changes look important.
|
|
|
48
67
|
spec is a `<name>/` folder whose entry point is `00-overview.md`, with one
|
|
49
68
|
file per phase beside it (`01-<slug>.md`, `02-…`). Legacy specs may be a bare
|
|
50
69
|
`<name>.md`, or a `00-overview.md` with inline phases — handle those too.
|
|
51
|
-
- A spec already in `specs/in-progress/` was started before.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
## 3. Put its branch in this checkout
|
|
70
|
+
- A spec already in `specs/in-progress/` was started before. Its worktree
|
|
71
|
+
probably still exists, so this is a re-attach: say so rather than reporting a
|
|
72
|
+
fresh start, and skip the housekeeping that is already done.
|
|
56
73
|
|
|
57
|
-
|
|
74
|
+
## 3. Build its branch
|
|
58
75
|
|
|
59
76
|
### `worktree` mode
|
|
60
77
|
|
|
61
78
|
1. **Provision.** Run `skitterspec spec-env up <name>` — a planner, so run the
|
|
62
|
-
`to provision, run:` commands it prints and confirm they succeeded
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
the
|
|
79
|
+
`to provision, run:` commands it prints and confirm they succeeded, **except**
|
|
80
|
+
the `open.command` line, which belongs to the hand-off in 3 below.
|
|
81
|
+
|
|
82
|
+
2. **Enter the worktree — this session, no new window.** The spec is built in its
|
|
83
|
+
worktree; that is what the mode is for, and it is why `main` stays free and
|
|
84
|
+
several specs run at once. So put *this* session there rather than opening
|
|
85
|
+
another one: call **`EnterWorktree`** with the worktree path.
|
|
86
|
+
|
|
87
|
+
**Do it immediately after `git worktree add`, before bootstrap and before the step 4 housekeeping.**
|
|
88
|
+
Once the session is the worktree, `setup` runs in place and the housekeeping
|
|
89
|
+
is plain `git` — the `cd` and the `git -C <worktreePath>` prefix both
|
|
90
|
+
disappear. **Never `cd` into the worktree first:** `EnterWorktree` refuses a
|
|
91
|
+
path that is already the working directory
|
|
92
|
+
(`is the current working directory`), so a bootstrap `cd` does not merely
|
|
93
|
+
make the call redundant, it makes it fail.
|
|
94
|
+
|
|
95
|
+
Then run the planner's **`then, in the worktree, run:`** steps in order (file
|
|
96
|
+
seeding, then `setup`) — a fresh worktree has no dependencies and none of the
|
|
97
|
+
repo's gitignored files, so hooks, typechecks and tests fail until they are
|
|
98
|
+
there. Do the step 4 housekeeping, then say to run **`/spec-next`**, here.
|
|
99
|
+
|
|
100
|
+
**Do not move the branch into this checkout**, and do not ask the operator to.
|
|
101
|
+
Entering the worktree is the opposite of moving the branch out of it — the
|
|
102
|
+
branch never leaves. `/spec-live` is for testing a finished-enough spec on the
|
|
103
|
+
already-running dev server; it is not the way work gets started, and reaching
|
|
104
|
+
for it here is what used to split a start across two invocations.
|
|
105
|
+
|
|
106
|
+
3. **When you cannot enter, hand off as before.** Two cases, and
|
|
107
|
+
**decide from cwd before calling**, not by calling and catching — an error
|
|
108
|
+
surfaced mid-skill reads as a bug, and both conditions are knowable in
|
|
109
|
+
advance:
|
|
110
|
+
|
|
111
|
+
- **This session's cwd is already inside a worktree.** `EnterWorktree` only
|
|
112
|
+
allows a worktree→worktree switch when the target lives under
|
|
113
|
+
`.claude/worktrees/`, and a project's worktree root usually does not
|
|
114
|
+
(`../{repo}-wt` is the shipped shape). Do not "fix" this by relocating the
|
|
115
|
+
root: starting a spec from the base branch is the documented path anyway.
|
|
116
|
+
- **`EnterWorktree` is unavailable** — a harness without it. There is no CLI
|
|
117
|
+
counterpart to fall back on, so the skill degrades rather than fails.
|
|
118
|
+
|
|
119
|
+
On either, do exactly what this skill did before: bootstrap with
|
|
120
|
+
`cd "<worktreePath>"`, housekeep with `git -C <worktreePath>`, run
|
|
121
|
+
`open.command` if one is configured, print the worktree path, and say to run
|
|
122
|
+
**`/spec-next`** from a session in it.
|
|
123
|
+
**Trust the worktree first** on this path: `spec-env up` wrote the printed
|
|
124
|
+
`trusted:` root into `.claude/settings.local.json`, but that file will not
|
|
125
|
+
hot-reload in this session — run `/add-dir <trusted root>` before editing into
|
|
126
|
+
the worktree, or the first write prompts. (Entering the worktree makes both
|
|
127
|
+
moot: the writes are then in-cwd.)
|
|
128
|
+
|
|
129
|
+
`EnterWorktree` is gated on being told to work in a worktree by the user or by
|
|
130
|
+
project instructions. A lifecycle skill directing it **is** project
|
|
131
|
+
instruction, so the call is in contract here.
|
|
132
|
+
|
|
133
|
+
**`/spec-next` is unchanged by this.** Its rule 2 — "the worktree you are
|
|
134
|
+
standing in" — is what answers once the session has actually moved; nothing about
|
|
135
|
+
its resolution is loosened, and it must not be. The refusal exists so the wrong
|
|
136
|
+
branch is never built.
|
|
84
137
|
|
|
85
138
|
### `checkout` mode
|
|
86
139
|
|
|
87
140
|
Run `skitterspec spec-env up <name>` and the single `git switch` it prints.
|
|
88
|
-
There is no worktree, no bootstrap
|
|
141
|
+
There is no worktree, no bootstrap and no hand-off — the checkout is already the
|
|
89
142
|
workbench. Its planner enforces the same gate from the engine side, so relay any
|
|
90
143
|
refusal and stop.
|
|
91
144
|
|
|
92
145
|
## 4. Move the spec into development
|
|
93
146
|
|
|
94
|
-
|
|
95
|
-
spec
|
|
147
|
+
**Do this before you report anything**, so no path can end with a provisioned
|
|
148
|
+
worktree and a spec still reading `Ready` in `specs/backlog/`. Having entered the
|
|
149
|
+
worktree (step 3.2) this is plain `git` — you are standing in it. On the hand-off
|
|
150
|
+
path (step 3.3) run it against the worktree with `git -C <worktreePath>` instead;
|
|
151
|
+
in `checkout` mode the branch is already here.
|
|
96
152
|
|
|
97
153
|
- `git mv "specs/backlog/<name>" "specs/in-progress/<name>"` if it isn't there
|
|
98
154
|
already (`mkdir -p specs/in-progress` first). Use `git mv` to keep history.
|
|
@@ -107,6 +163,17 @@ spec):
|
|
|
107
163
|
A spec ideally arrives `Ready` from `/spec`; a `Draft` works too — sanity-check
|
|
108
164
|
it is well-formed first.
|
|
109
165
|
|
|
166
|
+
## 4b. Note a missing gating decision (only if configured)
|
|
167
|
+
|
|
168
|
+
**Only when `specs/.core/gating.config.json` exists.** Run
|
|
169
|
+
`skitterspec gating check <name>` and, if it names this spec, mention it **once**
|
|
170
|
+
before phase 1 starts — the cheapest moment to decide is before any code exists.
|
|
171
|
+
|
|
172
|
+
**This check is advisory.** It reports; it never refuses, and nothing below is
|
|
173
|
+
conditional on it. A spec written before the project adopted gating has no header
|
|
174
|
+
and is not broken — turning this into a gate would accuse the very specs the
|
|
175
|
+
feature was designed not to disturb.
|
|
176
|
+
|
|
110
177
|
## 5. Bring the spec's dev servers up — confirm before heavy steps
|
|
111
178
|
|
|
112
179
|
**Only when the project configures host dev servers** (`env.config.json` → a
|
|
@@ -121,10 +188,23 @@ invoke it yourself.
|
|
|
121
188
|
|
|
122
189
|
## 6. Build phase 1
|
|
123
190
|
|
|
124
|
-
|
|
125
|
-
started, refreshes the mirror again, builds it with tests and
|
|
126
|
-
stop and ask the operator to run it
|
|
127
|
-
start the spec.
|
|
191
|
+
**`checkout` mode — carry straight on into `/spec-next`** in this session: it
|
|
192
|
+
marks phase 1 started, refreshes the mirror again, builds it with tests and
|
|
193
|
+
reports. Do not stop and ask the operator to run it: the branch is here and they
|
|
194
|
+
asked to start the spec.
|
|
195
|
+
|
|
196
|
+
**`worktree` mode — the spec is built in its worktree**, and step 3.2 put this
|
|
197
|
+
session there, so end by saying the worktree path is now the session's and to run
|
|
198
|
+
**`/spec-next`** here. On the hand-off path (step 3.3) the session did not move:
|
|
199
|
+
say so plainly, print the path, and tell them to run `/spec-next` from a session
|
|
200
|
+
in it.
|
|
201
|
+
|
|
202
|
+
`/spec-next` resolves the spec it is *standing in* — the live spec of the
|
|
203
|
+
checkout, the worktree its cwd is inside, or the branch in `checkout` mode — and
|
|
204
|
+
a name argument narrows a re-run rather than selecting a spec elsewhere. That
|
|
205
|
+
refusal is deliberate: building the wrong spec's phase writes commits on a branch
|
|
206
|
+
nobody asked for. **Do not work around it**, and do not offer to build the phase
|
|
207
|
+
from here.
|
|
128
208
|
|
|
129
209
|
## Opt-outs
|
|
130
210
|
|
|
@@ -8,9 +8,9 @@ disable-model-invocation: true
|
|
|
8
8
|
|
|
9
9
|
The **intermediate** landing. `/spec-complete` also lands the branch, but then
|
|
10
10
|
verifies every phase, flips the status to Complete, `git mv`s the spec to
|
|
11
|
-
`complete/`, and tears the environment down.
|
|
12
|
-
land**: the worktree stays, the spec stays
|
|
13
|
-
as you add commits.
|
|
11
|
+
`complete/`, and tears the environment down.
|
|
12
|
+
**`/spec-to-main` stops after the land**: the worktree stays, the spec stays
|
|
13
|
+
`In Progress`, and you can land again as you add commits.
|
|
14
14
|
|
|
15
15
|
Use it when a later phase can only be done *after* the current work is on `main` —
|
|
16
16
|
e.g. it needs to run in CI, a deploy pipeline, or a shared test environment that
|
|
@@ -19,9 +19,9 @@ the remaining phases with `/spec-next` and eventually `/spec-complete`.
|
|
|
19
19
|
|
|
20
20
|
It reuses the **same engine** as `/spec-complete`'s landing (`spec-env integrate`
|
|
21
21
|
— rebase + fast-forward), so it produces identical linear history. Because a
|
|
22
|
-
fast-forward leaves `base == branch`, the operation is
|
|
23
|
-
repeatable**: new commits put the branch ahead of base again,
|
|
24
|
-
`/spec-to-main` as many times as you like.
|
|
22
|
+
fast-forward leaves `base == branch`, the operation is
|
|
23
|
+
**idempotent and repeatable**: new commits put the branch ahead of base again,
|
|
24
|
+
and you can run `/spec-to-main` as many times as you like.
|
|
25
25
|
|
|
26
26
|
## 0. Preconditions — when this applies
|
|
27
27
|
|
|
@@ -58,10 +58,10 @@ primary checkout is dirty, or if a *different* spec holds it (release that one w
|
|
|
58
58
|
|
|
59
59
|
## 3. Tests must be green before landing
|
|
60
60
|
|
|
61
|
-
Don't push red to `main`. Run the project's typecheck and test commands
|
|
62
|
-
worktree**; the suite must be **green**. For a **Bug** spec, confirm
|
|
63
|
-
originally-failing test now passes. If anything is red, stop and report —
|
|
64
|
-
broken code onto `main` defeats the purpose.
|
|
61
|
+
Don't push red to `main`. Run the project's typecheck and test commands
|
|
62
|
+
**in the worktree**; the suite must be **green**. For a **Bug** spec, confirm
|
|
63
|
+
the originally-failing test now passes. If anything is red, stop and report —
|
|
64
|
+
landing broken code onto `main` defeats the purpose.
|
|
65
65
|
|
|
66
66
|
(Note this is the *worktree* suite. The whole point of this skill is often to run
|
|
67
67
|
a *further* check that only exists on `main` / in CI — that one runs **after** the
|
|
@@ -69,8 +69,8 @@ land, in step 5.)
|
|
|
69
69
|
|
|
70
70
|
## 4. Land — rebase + fast-forward
|
|
71
71
|
|
|
72
|
-
Run `skitterspec spec-env integrate <name>` and run the printed commands
|
|
73
|
-
order**:
|
|
72
|
+
Run `skitterspec spec-env integrate <name>` and run the printed commands
|
|
73
|
+
**in order**:
|
|
74
74
|
|
|
75
75
|
- `git -C <worktree> rebase <base>` — replay the branch onto base.
|
|
76
76
|
- `git -C <mainRepoPath> merge --ff-only <branch>` — fast-forward base.
|
|
@@ -91,8 +91,8 @@ and continue — the branch has no commits base doesn't already have.
|
|
|
91
91
|
`- <YYYY-MM-DD> — Landed intermediate work onto <base> to <run CI / deploy to
|
|
92
92
|
test env / …>; spec stays In Progress.`
|
|
93
93
|
- Do **NOT**: add a State-log row (status doesn't change), flip any phase/status
|
|
94
|
-
to Complete, `git mv` the spec, or tear down the worktree/stack.
|
|
95
|
-
stays `In Progress` and the worktree stays put.**
|
|
94
|
+
to Complete, `git mv` the spec, or tear down the worktree/stack.
|
|
95
|
+
**The spec stays `In Progress` and the worktree stays put.**
|
|
96
96
|
- Report: the base branch, the fast-forward result, and the green base test. It
|
|
97
97
|
**never pushes** — mention the user can `git push` the base branch themselves to
|
|
98
98
|
trigger CI / the shared env.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skitterbyte/skitterspec",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "18.0.0",
|
|
4
4
|
"description": "Spec-driven development for Claude Code — 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",
|