@skitterbyte/skitterspec-jira 0.0.0-stage → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +1266 -0
- package/README.md +44 -2
- package/assets/claude-md-section.md +85 -0
- package/assets/commands/allow-main.md +33 -0
- package/assets/commands/spec-connect.md +13 -0
- package/assets/commands/spec-live.md +14 -0
- package/assets/commands/spec-remote-review.md +37 -0
- package/assets/commands/spec-skip.md +24 -0
- package/assets/core/SETUP.md +192 -0
- package/assets/core/env.config.json.example +56 -0
- package/assets/core/env.config.md +606 -0
- package/assets/core/gating.config.json.example +4 -0
- package/assets/core/gating.config.md +81 -0
- package/assets/core/jira.config.json.example +18 -0
- package/assets/core/jira.config.md +88 -0
- package/assets/hooks/main-guard.cjs +162 -0
- package/assets/hooks/review-gate.cjs +146 -0
- package/assets/review/page.html +3384 -0
- package/assets/rules/commit-trailers.md +96 -0
- package/assets/rules/negative-checks.md +69 -0
- package/assets/rules/offered-unblocks.md +100 -0
- package/assets/rules/spec-planning.md +702 -0
- package/assets/rules/spec-reports.md +572 -0
- package/assets/skills/no-spec/SKILL.md +249 -0
- package/assets/skills/spec/SKILL.md +714 -0
- package/assets/skills/spec-bug/SKILL.md +585 -0
- package/assets/skills/spec-cancel/SKILL.md +261 -0
- package/assets/skills/spec-complete/SKILL.md +451 -0
- package/assets/skills/spec-diff/SKILL.md +870 -0
- package/assets/skills/spec-hotfix/SKILL.md +607 -0
- package/assets/skills/spec-init/SKILL.md +178 -0
- package/assets/skills/spec-jira-setup/SKILL.md +221 -0
- package/assets/skills/spec-list/SKILL.md +173 -0
- package/assets/skills/spec-next/SKILL.md +678 -0
- package/assets/skills/spec-push/SKILL.md +306 -0
- package/assets/skills/spec-review/SKILL.md +256 -0
- package/assets/skills/spec-reviewed/SKILL.md +284 -0
- package/assets/skills/spec-start/SKILL.md +496 -0
- package/assets/skills/spec-status/SKILL.md +114 -0
- package/assets/skills/spec-sync/SKILL.md +220 -0
- package/assets/skills/spec-to-main/SKILL.md +141 -0
- package/bin/skitterspec-jira.js +68 -0
- package/package.json +40 -4
- package/src/cli.js +5967 -0
- package/src/deprecate.js +138 -0
- package/src/env/bootstrap.js +188 -0
- package/src/env/building.js +143 -0
- package/src/env/classify.js +176 -0
- package/src/env/commitcmd.js +108 -0
- package/src/env/config.js +850 -0
- package/src/env/dev.js +63 -0
- package/src/env/glob.js +34 -0
- package/src/env/hooks.js +226 -0
- package/src/env/hotfix.js +413 -0
- package/src/env/hotfixland.js +302 -0
- package/src/env/integrate.js +167 -0
- package/src/env/live.js +479 -0
- package/src/env/mainguard.js +299 -0
- package/src/env/provision.js +466 -0
- package/src/env/proxy.js +225 -0
- package/src/env/prune.js +119 -0
- package/src/env/registry.js +159 -0
- package/src/env/render.js +17 -0
- package/src/env/resolve.js +716 -0
- package/src/env/review.js +2622 -0
- package/src/env/reviewers/coderabbit.js +228 -0
- package/src/env/reviewers.js +517 -0
- package/src/env/serve.js +1044 -0
- package/src/env/supervise.js +157 -0
- package/src/env/teardown.js +248 -0
- package/src/env/trust.js +87 -0
- package/src/gating.js +155 -0
- package/src/init.js +1150 -0
- package/src/lines-diff.js +114 -0
- package/src/prompts.js +129 -0
- package/src/vendor/jira/adf.js +414 -0
- package/src/vendor/jira/api.js +295 -0
- package/src/vendor/jira/cli-sync.js +1252 -0
- package/src/vendor/jira/commands.js +44 -0
- package/src/vendor/jira/config.js +286 -0
- package/src/vendor/jira/credentials.js +108 -0
- package/src/vendor/jira/dialect.js +45 -0
- package/src/vendor/jira/mcp.js +129 -0
- package/src/vendor/provider-kit/index.js +41 -0
- package/src/vendor/provider-kit/src/adapter.js +23 -0
- package/src/vendor/provider-kit/src/apply.js +207 -0
- package/src/vendor/provider-kit/src/args.js +68 -0
- package/src/vendor/provider-kit/src/assignment.js +277 -0
- package/src/vendor/provider-kit/src/config.js +251 -0
- package/src/vendor/provider-kit/src/credentials.js +404 -0
- package/src/vendor/provider-kit/src/doctor.js +35 -0
- package/src/vendor/provider-kit/src/http.js +63 -0
- package/src/vendor/provider-kit/src/identity.js +93 -0
- package/src/vendor/provider-kit/src/list-assignee.js +71 -0
- package/src/vendor/provider-kit/src/list-rows.js +35 -0
- package/src/vendor/provider-kit/src/md-compare.js +39 -0
- package/src/vendor/provider-kit/src/md-tables.js +94 -0
- package/src/vendor/provider-kit/src/prompt.js +50 -0
- package/src/vendor/provider-kit/src/released.js +219 -0
- package/src/vendor/provider-kit/src/specs.js +248 -0
- package/src/vendor/provider-kit/src/transport.js +22 -0
- package/src/vendor/sync-core/index.js +92 -0
- package/src/vendor/sync-core/src/base.js +81 -0
- package/src/vendor/sync-core/src/compare.js +338 -0
- package/src/vendor/sync-core/src/dialect.js +51 -0
- package/src/vendor/sync-core/src/fields.js +36 -0
- package/src/vendor/sync-core/src/legacy.js +100 -0
- package/src/vendor/sync-core/src/normalize.js +971 -0
- package/src/vendor/sync-core/src/push.js +85 -0
- package/src/vendor/sync-core/src/retarget.js +278 -0
- package/src/vendor/sync-core/src/task-block.js +308 -0
- package/src/vendor/sync-core/src/verify.js +67 -0
- package/src/vendor/sync-core/src/write.js +191 -0
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-complete
|
|
3
|
+
description: Finish a spec — verify all phases are genuinely done, update progress, then move it into specs/complete/. Targets a spec by name (arg) or the spec currently in context. Use when the user says "/spec-complete", "mark this spec done", or "this spec is complete".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /spec-complete — verify, finalise, archive a spec
|
|
7
|
+
|
|
8
|
+
> Stay silent while this runs — speak only to ask something you cannot answer
|
|
9
|
+
> yourself, or to report a failure at the moment it happens. Read
|
|
10
|
+
> `.claude/rules/spec-reports.md` before reporting; it defines the block this
|
|
11
|
+
> skill ends with.
|
|
12
|
+
|
|
13
|
+
## 1. Identify the target spec
|
|
14
|
+
|
|
15
|
+
- Use the name/path argument if given, else the spec **in context**. If unclear,
|
|
16
|
+
ask which spec.
|
|
17
|
+
- Locate the spec folder under `specs/` (usually `specs/in-progress/`). Entry
|
|
18
|
+
point is its `00-overview.md`; phases are separate files (`01-<slug>.md`, `02-…`)
|
|
19
|
+
listed in its phase index (legacy specs may be a bare `<name>.md`).
|
|
20
|
+
- **A hotfix already in `specs/complete/` whose worktree still stands** is a
|
|
21
|
+
hotfix waiting on its deploy. That run is the teardown only: go straight to
|
|
22
|
+
step 7's hotfix paragraph, and do not re-verify, re-move or re-land it.
|
|
23
|
+
|
|
24
|
+
## 2. Double-check progress — don't rubber-stamp
|
|
25
|
+
|
|
26
|
+
Before marking complete, confirm the work is actually finished:
|
|
27
|
+
|
|
28
|
+
- Read every phase file. For each **unchecked** task, check whether it is in fact
|
|
29
|
+
done in the code — tick it (`- [x]`) if so, or surface it if not.
|
|
30
|
+
- Run the project's typecheck and test commands. The suite must be **green** to
|
|
31
|
+
call a spec complete.
|
|
32
|
+
- For a **Bug** or **Hotfix** spec (`Type: Bug` / `Type: Hotfix`), confirm the
|
|
33
|
+
originally-failing test named in the spec now passes — that test is the proof
|
|
34
|
+
the fix works.
|
|
35
|
+
- If genuinely incomplete work remains, **stop and tell the user** rather than
|
|
36
|
+
forcing completion. Offer to finish it (`/spec-next`) or to complete with the
|
|
37
|
+
remaining items explicitly listed as deferred.
|
|
38
|
+
- **Check for pre-existing uncommitted changes — before you touch anything.**
|
|
39
|
+
Run `git status`. Anything already uncommitted is the *user's* work (a
|
|
40
|
+
half-finished phase, a stray fix) and must not be swept into the completion
|
|
41
|
+
commit: offer `/commit` and **stop**. Everything this skill writes in steps 3–4
|
|
42
|
+
is its own, and step 4 commits that.
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
### Release gating (only when configured)
|
|
46
|
+
|
|
47
|
+
**Only when `specs/.core/gating.config.json` exists.** Run
|
|
48
|
+
`skitterspec gating check <spec>` and report what it says. This is the last point
|
|
49
|
+
at which the question can still be answered cheaply, which is exactly why it is
|
|
50
|
+
asked here — a spec that reaches `Complete` with no decision recorded is the gap
|
|
51
|
+
the feature exists to close.
|
|
52
|
+
|
|
53
|
+
**Never refuse to complete over it.** Say plainly that no decision was recorded,
|
|
54
|
+
offer to record one now, and finish either way. The work is done; withholding the
|
|
55
|
+
status flip would punish the wrong thing.
|
|
56
|
+
|
|
57
|
+
**This check is advisory.** It reports; it never refuses, and nothing below is
|
|
58
|
+
conditional on it. A spec written before the project adopted gating has no header
|
|
59
|
+
and is not broken — turning this into a gate would accuse the very specs the
|
|
60
|
+
feature was designed not to disturb.
|
|
61
|
+
|
|
62
|
+
## 3. Update the spec
|
|
63
|
+
|
|
64
|
+
- Tick all completed tasks in the phase files; flip every finished phase-file
|
|
65
|
+
heading **and** every row in the `00-overview.md` phase index to `✅`.
|
|
66
|
+
- Set the **Status** header in the entry point:
|
|
67
|
+
`> **Status:** Complete (<YYYY-MM-DD>)`.
|
|
68
|
+
- Append a **State log** row:
|
|
69
|
+
`| <YYYY-MM-DD> | Complete | complete | <git user.name> |`.
|
|
70
|
+
- Add a **Changelog** entry:
|
|
71
|
+
`- <YYYY-MM-DD> — Completed; all phases done, tests green.`
|
|
72
|
+
(Note any consciously-deferred items here too.)
|
|
73
|
+
|
|
74
|
+
## 4. Move to complete — and commit it
|
|
75
|
+
|
|
76
|
+
`mkdir -p specs/complete` then **`git mv`** the file or folder:
|
|
77
|
+
`git mv "specs/in-progress/<name>" "specs/complete/<name>"` (preserve history;
|
|
78
|
+
move the whole folder). The `specs/complete/` folder is the record of finished
|
|
79
|
+
specs — `git log`/the per-spec State log give the completion order.
|
|
80
|
+
|
|
81
|
+
**Only when `specs/.core/jira.config.json` exists** and the spec's overview
|
|
82
|
+
carries a `jira_identifier`. Either missing → **skip**, in one line
|
|
83
|
+
(`not linked to Jira — /spec-push to mirror it`), and carry on. Nothing else in
|
|
84
|
+
this step changes.
|
|
85
|
+
|
|
86
|
+
**Refresh the mirror now, without asking.** Run `/spec-push`. The repo has just
|
|
87
|
+
become the truth about this spec's state, and the tracker is a generated mirror
|
|
88
|
+
of it — leaving them to diverge until someone remembers to push by hand is the
|
|
89
|
+
gap this exists to close. It costs one engine call and no model tokens when
|
|
90
|
+
Jira credentials are set (see `apply.transport` in `jira.config.md`).
|
|
91
|
+
|
|
92
|
+
- **Never mint.** An unlinked spec is skipped, not created. An issue born `Done`
|
|
93
|
+
is tracker noise, and a spec kept deliberately local should stay that way —
|
|
94
|
+
`/spec-push` is how someone opts in.
|
|
95
|
+
- **Never fatal.** If the push fails — offline, no credentials, a Jira error —
|
|
96
|
+
say so and **finish the operation anyway**. The spec is
|
|
97
|
+
complete/cancelled/reviewed in the repo regardless; the mirror is disposable
|
|
98
|
+
and the next push repairs it. Do not roll anything back, and do not stop to
|
|
99
|
+
ask.
|
|
100
|
+
- **Say what happened** in the skill's report: mirror updated, skipped as
|
|
101
|
+
unlinked, or failed with the reason.
|
|
102
|
+
- **There is no assignment to release here.** Assignment sync is not yet
|
|
103
|
+
supported by the Jira provider; the `> **Developer:**` header stays put as the
|
|
104
|
+
repo's own record of who actioned the work.
|
|
105
|
+
|
|
106
|
+
### Why it sits here
|
|
107
|
+
|
|
108
|
+
In `/spec-complete` and `/spec-cancel` this step is deliberately pinned
|
|
109
|
+
**after the `git mv` and before the commit**, and both halves matter:
|
|
110
|
+
|
|
111
|
+
- **After the move**, because the projection reads a spec's workflow status from
|
|
112
|
+
its folder bucket. Push while the folder is still in `in-progress/` and the
|
|
113
|
+
issue is set to the status the spec is *leaving*.
|
|
114
|
+
- **Before the commit**, because the push stamps keys into the spec and writes a
|
|
115
|
+
snapshot under `specs/.core/`. Push after the commit instead and both are left
|
|
116
|
+
uncommitted, which makes `spec-env integrate` refuse to land the branch.
|
|
117
|
+
|
|
118
|
+
The snapshot is reached **by name**, not by breadth. It is a declared
|
|
119
|
+
`spec.companionPaths` entry (`specs/.core/jira-base/{identifier}.base.json`),
|
|
120
|
+
so `spec-env stage` returns it among this spec's owned paths and the commit below
|
|
121
|
+
names it. This is why the commit no longer stages `specs/` wholesale: the one
|
|
122
|
+
file outside the spec's folder that had to be swept up is addressable, so the
|
|
123
|
+
breadth bought nothing and cost another session's work.
|
|
124
|
+
|
|
125
|
+
Then **commit the completion edits** — steps 3–4 are this skill's own output, so
|
|
126
|
+
it finishes its own work rather than handing you a dirty tree. Ask the engine
|
|
127
|
+
which paths are this spec's, then stage and commit **exactly those**:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
skitterspec spec-env stage <name> # lists them; --json to consume
|
|
131
|
+
git add -- <the owned paths>
|
|
132
|
+
git commit -m "chore(spec): complete <name>" -- <the owned paths>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Never `git add specs/`.** That stages a *directory*, so a spec another
|
|
136
|
+
session is part-way through writing lands in this commit under this spec's
|
|
137
|
+
ticket. The `--` on the **commit** is the other half: a checkout has one
|
|
138
|
+
`.git/index`, shared by every session standing in it, so a bare `git commit`
|
|
139
|
+
takes whatever else is staged there however carefully you staged your own.
|
|
140
|
+
`.claude/rules/spec-planning.md` carries the full account.
|
|
141
|
+
|
|
142
|
+
So this commits exactly the status flip and the move, and nothing of yours — or
|
|
143
|
+
of anyone else's — rides along.
|
|
144
|
+
**This is what lets step 6 land:** `integrate` refuses a dirty worktree, so
|
|
145
|
+
without committing here the skill would block on the very edits it just made.
|
|
146
|
+
Do not `git push`.
|
|
147
|
+
|
|
148
|
+
## 5. Report
|
|
149
|
+
|
|
150
|
+
**The block is emitted when the run ends, not where this section sits.** The
|
|
151
|
+
sections below run after it, so their outcome belongs in the block — write it
|
|
152
|
+
once, at the end, with what actually happened.
|
|
153
|
+
|
|
154
|
+
End with the block defined in `.claude/rules/spec-reports.md`. That file carries
|
|
155
|
+
the shape; this section carries only what is specific here.
|
|
156
|
+
|
|
157
|
+
**Verdicts**
|
|
158
|
+
|
|
159
|
+
- `✅` — every phase done, tests green, landed, torn down.
|
|
160
|
+
- `⚠️` — finished, with something worth knowing: teardown declined, a tracker
|
|
161
|
+
refresh that failed, a hotfix tag still waiting to be pushed, an after-land
|
|
162
|
+
command that failed.
|
|
163
|
+
- `❌` — it acted and stopped part-way — a conflicted rebase, a failed
|
|
164
|
+
cherry-pick, a red base after landing. Say what state the repo is in and quote
|
|
165
|
+
the failure; there is a mess to clear and the reader needs to know where.
|
|
166
|
+
- `⏸` — phases are unfinished, tests are red, or the tree is dirty. Nothing
|
|
167
|
+
moved.
|
|
168
|
+
|
|
169
|
+
**Fields:** `Tracker` · `Spec` · `Tests` · `Notes` · `Landed` · `Worktree` ·
|
|
170
|
+
`Follow-ups` · `Next`
|
|
171
|
+
|
|
172
|
+
`Notes` carries the after-land commands step 6 ran, and where, and any it
|
|
173
|
+
skipped because the land matched no `when` — or, on a failure, the command that failed and the ones that did not run. A project with
|
|
174
|
+
no `afterLand` says nothing about it.
|
|
175
|
+
|
|
176
|
+
**Report this spec and no other.** A completion is the moment it is most
|
|
177
|
+
tempting to survey what is left — what else is in flight, what is in the
|
|
178
|
+
backlog, which worktrees are still standing — and it is the moment it helps
|
|
179
|
+
least: the reader has just finished something and cannot tell whether a line
|
|
180
|
+
about another spec followed from it. `Next` is one action for this spec, and
|
|
181
|
+
`/spec-list` is where the wider picture lives if they want it.
|
|
182
|
+
|
|
183
|
+
`Landed` says how, because the two ways differ: a fast-forward names the base
|
|
184
|
+
and the commit, a hotfix names the release tag, whether it was pushed, and the
|
|
185
|
+
`main` carry — and a release tag that has not been pushed is a `⚠️`, not a `✅`. `Worktree` says
|
|
186
|
+
what was reclaimed, including any orphaned volumes swept, or that teardown was
|
|
187
|
+
declined and the worktree still stands.
|
|
188
|
+
|
|
189
|
+
## 6. Land the branch (opt-in, only if isolated)
|
|
190
|
+
|
|
191
|
+
**Only when `specs/.core/env.config.json` exists and the spec was provisioned**
|
|
192
|
+
(a worktree in `worktree` mode, or its branch in the checkout in `checkout`
|
|
193
|
+
mode — `spec-env integrate` and `down` pick the right plan from `mode`, so the
|
|
194
|
+
commands you run differ but these steps do not)
|
|
195
|
+
(it was provisioned by `/spec-start` or `/spec-hotfix`). Otherwise skip this entirely
|
|
196
|
+
— a non-isolated spec has nothing to land, and `/spec-complete` behaves exactly as
|
|
197
|
+
before. When it applies, offer to land the finished branch so the work reaches its
|
|
198
|
+
destination in one flow. **How it lands depends on the spec type:**
|
|
199
|
+
|
|
200
|
+
### 6-hotfix. `Type: Hotfix` — release, push, carry (not fast-forward)
|
|
201
|
+
|
|
202
|
+
A hotfix is built on an old release **tag**, so it can't fast-forward onto `main`.
|
|
203
|
+
The engine runs its landing itself — `hotfix land` releases, pushes and carries,
|
|
204
|
+
in that order, and stops at the first step that fails:
|
|
205
|
+
|
|
206
|
+
1. **Require a clean worktree.** Step 4 already committed the completion edits, so
|
|
207
|
+
this should pass. If the tree is *still* dirty, that's unrelated work — offer
|
|
208
|
+
`/commit` and **stop**. The order matters beyond tidiness: a project's
|
|
209
|
+
`hotfix.releaseWith` (skittership's `release-hotfix.cjs`) refuses a dirty tree
|
|
210
|
+
and an already-tagged HEAD, so the release has to run **after** the §4 commit.
|
|
211
|
+
2. **Ask before pushing.** Pushing the tag is what starts the prod deploy, so it is
|
|
212
|
+
the operator's to say yes to — ask once, plainly, naming the tag-to-be and the
|
|
213
|
+
remote (`skitterspec spec-env hotfix land <name> --plan` says what will run).
|
|
214
|
+
3. **Land it.** On a yes:
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
skitterspec spec-env hotfix land <name> --push
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
On a no, run it **without** `--push`. Add `--also <tag>` for each extra release
|
|
221
|
+
line to patch (test/demo lines — tag-only, never through `releaseWith`).
|
|
222
|
+
It:
|
|
223
|
+
- **releases** the branch head — through `hotfix.releaseWith` when the project
|
|
224
|
+
set one (its version commit and tag; its one JSON line names the tag), else
|
|
225
|
+
the built-in tagger (`hotfix.bump`: `patch`, or `hotfix-suffix` for
|
|
226
|
+
`X.Y.Z-hotfix.N`). The release is recorded, so a re-run never cuts a second;
|
|
227
|
+
- **pushes** the branch, then the tag, to `origin` — only with `--push`. Without
|
|
228
|
+
it the run **holds** here, exit 0, printing both push commands; a re-run after
|
|
229
|
+
the operator pushes by hand finds the tag on the remote and carries on;
|
|
230
|
+
- **carries** the fix onto `main`: the branch's commits minus the version commit
|
|
231
|
+
and minus anything `main` already has, so the spec's completion commits arrive
|
|
232
|
+
and `main`'s version line does not move. In place when `main` is checked out
|
|
233
|
+
and clean, through a throwaway worktree when it is not checked out, and
|
|
234
|
+
**refused** — with the command to run later — when it is checked out and
|
|
235
|
+
dirty.
|
|
236
|
+
|
|
237
|
+
Relay its step lines. A **non-zero exit** is a refusal or a failure at a named
|
|
238
|
+
step — a refused release, a failed push, a conflicted carry (already aborted,
|
|
239
|
+
naming the commit). Relay it and **stop**; whatever was cut is recorded, so the
|
|
240
|
+
fix is to clear the cause and re-run the same command. On a **no-op** ("nothing
|
|
241
|
+
to land"), say so and continue.
|
|
242
|
+
4. **Run the after-land commands** when the run ends with a
|
|
243
|
+
`then, in the primary checkout (<path>), run:` section — exactly as step 3
|
|
244
|
+
of 6-feature/bug below says. `hotfix land` prints it only when the carry moved
|
|
245
|
+
`main`, so a held, prod-only or already-carried land has none.
|
|
246
|
+
5. **Re-test on `main`** after the carry — it must be **green**.
|
|
247
|
+
6. **Report** — `Landed` names the release tag and whether it was **pushed**, and
|
|
248
|
+
what the carry did. A tag cut but not pushed is a `⚠️`, not a `✅`.
|
|
249
|
+
**Then stop: the worktree is kept** (step 7). The branch is what the next
|
|
250
|
+
`-hotfix.N` is cut from if this deploy fails, so it waits for the deploy.
|
|
251
|
+
|
|
252
|
+
### 6-feature/bug. `Type: Feature` / `Type: Bug` — rebase + fast-forward
|
|
253
|
+
|
|
254
|
+
Land the finished branch on the base branch so the work reaches `main` (or your
|
|
255
|
+
configured `baseBranch`) in one flow. (Need the work on `main` *before* the spec
|
|
256
|
+
is finished — e.g. to run a later phase in CI or a shared test env? Use
|
|
257
|
+
**`/spec-to-main`**: same rebase + fast-forward, but it leaves the spec
|
|
258
|
+
`In Progress` and the worktree standing, and it's repeatable.)
|
|
259
|
+
|
|
260
|
+
1. **Require a clean worktree.** Step 4 already committed the completion edits, so
|
|
261
|
+
integrate's dirty-tree guard should pass. If the tree is *still* dirty, that's
|
|
262
|
+
unrelated work — offer `/commit` and **stop**; don't sweep it in.
|
|
263
|
+
**If the spec is live** (you took the running instance with `/spec-live`):
|
|
264
|
+
`integrate` is live-aware — it ends the live session first (releases the branch
|
|
265
|
+
back to base, re-isolates it into its worktree, clears the receipt), then prints
|
|
266
|
+
the normal landing plan. Commit any live fixes to the branch first; it refuses
|
|
267
|
+
if the primary checkout is dirty, or if a *different* spec holds it (release that
|
|
268
|
+
one by typing `/spec-live main`). Teardown (step 7) is unchanged.
|
|
269
|
+
**Work-loss abort.** Before it ends the live session, `integrate` checks the
|
|
270
|
+
work is actually landable and **aborts loudly** rather than finalize a spec
|
|
271
|
+
having landed nothing. Two cases, both leaving the live session intact:
|
|
272
|
+
- *stranded commits* — commits sit on the worktree's **detached HEAD** (e.g. a
|
|
273
|
+
pre-fix `/spec-next` committed there instead of on the branch). It prints the
|
|
274
|
+
count, the sha, and a `git -C <worktree> branch <tmp> <sha>` recovery hint —
|
|
275
|
+
recover those commits onto the branch, then re-run.
|
|
276
|
+
- *no worktree* — the spec is live but its worktree is gone. Re-isolate it with
|
|
277
|
+
`skitterspec spec-env up <name>`, then re-run.
|
|
278
|
+
Relay the diagnostic to the user and **stop** — do not tear anything down.
|
|
279
|
+
2. **Plan + execute.** Run `skitterspec spec-env integrate <name>` and run the
|
|
280
|
+
printed commands **in order**:
|
|
281
|
+
- `git -C <worktree> rebase <base>` — replay the branch onto base.
|
|
282
|
+
- `git -C <mainRepoPath> merge --ff-only <branch>` — fast-forward base.
|
|
283
|
+
On a **rebase conflict** (non-zero exit), run
|
|
284
|
+
`git -C <worktree> rebase --abort`, relay the conflict, and **stop** — leave it
|
|
285
|
+
to the user; do not tear anything down.
|
|
286
|
+
On a **no-op** ("already landed"), just say so and continue.
|
|
287
|
+
3. **Run the after-land commands.** Where the plan ends with a
|
|
288
|
+
`then, in the primary checkout (<path>), run:` section — the project's
|
|
289
|
+
`afterLand`, such as a data migration — run those commands in that
|
|
290
|
+
directory, in order, after the fast-forward succeeds. Run only the lines under that
|
|
291
|
+
heading; a `skipped (nothing in the land matched):` block lists conditional
|
|
292
|
+
entries this land did not need, and is information, never commands.
|
|
293
|
+
**Also on the no-op**:
|
|
294
|
+
the engine prints them there deliberately, because a land made on another
|
|
295
|
+
machine leaves them pending here. **Stop at the first non-zero exit** — a
|
|
296
|
+
later command may depend on it — and carry on with the rest of the skill:
|
|
297
|
+
a failure makes the run `⚠️`, naming the command that failed and the ones
|
|
298
|
+
that did not run, and it
|
|
299
|
+
**never undoes the land and never blocks teardown** (step 7). The land is correct; catching up is the operator's.
|
|
300
|
+
No section, nothing to run, and nothing to say about it.
|
|
301
|
+
4. **Re-test on base.** Run the project's test command from the primary checkout;
|
|
302
|
+
it must be **green** before you call the landing done.
|
|
303
|
+
5. **Report** the landing (base branch, fast-forward result). It **never pushes** —
|
|
304
|
+
mention the user can `git push` the base branch themselves.
|
|
305
|
+
|
|
306
|
+
## 7. Tear down the environment (opt-in, only if configured)
|
|
307
|
+
|
|
308
|
+
**A hotfix is torn down later, by `hotfix finish`.**
|
|
309
|
+
It is never torn down here on the run that landed it. Skip sub-steps 0–3 for a `Type: Hotfix` spec that step 6 just landed,
|
|
310
|
+
and say the worktree is kept until the deploy is confirmed. When the operator runs
|
|
311
|
+
`/spec-complete` **again** on that hotfix — it is already in `specs/complete/` and
|
|
312
|
+
already landed — this step is the whole run: `cd` to the primary checkout, then
|
|
313
|
+
|
|
314
|
+
```
|
|
315
|
+
skitterspec spec-env hotfix finish <name>
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
It tears down only when the tree is clean, a release tag is at HEAD and the branch
|
|
319
|
+
is on `origin` at HEAD, naming every check that fails; there is no `--force`.
|
|
320
|
+
Relay a refusal and stop. Report what it removed in `Worktree`.
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
**Only when `specs/.core/env.config.json` exists.** Reclaiming the environment is
|
|
324
|
+
what completing a spec *is*, so sub-steps 1–3 run **automatically — do not ask**.
|
|
325
|
+
Run the `spec-env` CLI directly (the old `/spec-env-down` skill is gone —
|
|
326
|
+
teardown is folded in here).
|
|
327
|
+
|
|
328
|
+
**The precondition is that the work actually landed.** Only tear down when step 6
|
|
329
|
+
completed: it landed (or reported "already landed") **and** the base suite came
|
|
330
|
+
back green. A failed after-land command is **not** a reason to stop here — the
|
|
331
|
+
land stands, and the command is the operator's to re-run from the primary
|
|
332
|
+
checkout, which teardown does not touch. A rebase conflict, a work-loss abort or a red suite means step 6 told
|
|
333
|
+
you to stop — tear nothing down, because the worktree is where the user picks the
|
|
334
|
+
problem up. That precondition is what makes a confirmation redundant: by the time
|
|
335
|
+
you get here the branch is an ancestor of base and the engine's guards have
|
|
336
|
+
nothing left to protect.
|
|
337
|
+
|
|
338
|
+
**Opt-out:** if the user passed **`--keep-env`**, skip sub-steps 1–3, say the
|
|
339
|
+
worktree and branch are being kept, and go straight to sub-step 4. Mention
|
|
340
|
+
`skitterspec spec-env up <name>` re-attaches it later either way.
|
|
341
|
+
|
|
342
|
+
0. **Name a pass still waiting for THIS spec — before anything is removed.**
|
|
343
|
+
|
|
344
|
+
```
|
|
345
|
+
skitterspec spec-env review waiting --json
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Filter to the spec being completed and say nothing about any other: a run
|
|
349
|
+
reports itself and nothing else (`.claude/rules/spec-reports.md`). For each
|
|
350
|
+
one, give the code, the verdict and the age, then the two exits — claim it
|
|
351
|
+
now with `/spec-reviewed <code>` **while the worktree still stands**, or
|
|
352
|
+
disown it with `skitterspec spec-env review <spec> --drop <code>`.
|
|
353
|
+
|
|
354
|
+
**Why here and not anywhere else.** Nothing is about to become unreachable —
|
|
355
|
+
a pass can be disowned long after its spec is gone. What is about to pass is
|
|
356
|
+
the last moment the verdict can still be **honoured**: before teardown a
|
|
357
|
+
`commit` pass can be claimed and acted on, after it there is no branch left
|
|
358
|
+
to commit to and disowning is all that remains.
|
|
359
|
+
|
|
360
|
+
**It reports, and it never blocks.** No refusal, no confirmation of its own,
|
|
361
|
+
no non-zero exit. And **it never claims** — reporting a pass is not taking
|
|
362
|
+
one, and `/spec-diff` §0 is untouched by this step.
|
|
363
|
+
|
|
364
|
+
Put what you found in the report's `Notes` row.
|
|
365
|
+
Silent when nothing is waiting, which is the usual case.
|
|
366
|
+
|
|
367
|
+
1. **Disconnect the proxy if this spec is connected.** If `.spec-env/connected`
|
|
368
|
+
names this spec, run `skitterspec spec-env connect main` first so the
|
|
369
|
+
canonical ports go back to the primary checkout.
|
|
370
|
+
2. **Stop its host dev servers:** `skitterspec spec-env dev down <name>` (a
|
|
371
|
+
no-op when none are running / configured).
|
|
372
|
+
**Standing in the worktree? Leave it before you tear it down.** If this session's
|
|
373
|
+
cwd is inside the spec's own worktree — the normal case in `worktree` mode, since
|
|
374
|
+
`/spec-start` moves you there — get out **first**, then run the teardown commands.
|
|
375
|
+
One instruction covers it:
|
|
376
|
+
|
|
377
|
+
```
|
|
378
|
+
cd <primary checkout>
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
That is the whole mechanism, and it does not matter how you got in: the session
|
|
382
|
+
was moved by a `cd` and it leaves by one. There is no tool to call here, and none
|
|
383
|
+
should be reached for — the move in is a plain `cd` precisely because a tool that
|
|
384
|
+
asks for approval is unusable on a phone.
|
|
385
|
+
|
|
386
|
+
**`spec-env down` stays the single thing that deletes a worktree.** The plan
|
|
387
|
+
below is the only deleter, because a second one is how the teardown guards get
|
|
388
|
+
bypassed.
|
|
389
|
+
|
|
390
|
+
Not because git refuses — it does not. `git worktree remove` **succeeds** on the
|
|
391
|
+
tree you are standing in, and that is the problem: the directory vanishes under
|
|
392
|
+
the shell, `pwd` keeps reporting the path that no longer exists, and every
|
|
393
|
+
command after it dies with `fatal: Unable to read current working directory`.
|
|
394
|
+
The teardown looks fine and everything following it breaks — the report, the
|
|
395
|
+
prune, any check you meant to run. Relocating first costs nothing and is the
|
|
396
|
+
only ordering that survives.
|
|
397
|
+
|
|
398
|
+
3. **Remove worktree + stack + slot:** run `skitterspec spec-env down <name>`
|
|
399
|
+
and execute the commands it prints, in order. After a landing — merged into
|
|
400
|
+
base for a **feature/bug** (a hotfix never reaches this sub-step; see the top
|
|
401
|
+
of step 7) —
|
|
402
|
+
teardown needs **no `--force`** and drops the branch with `git branch -D`,
|
|
403
|
+
which is safe precisely because the commits are already somewhere else. It
|
|
404
|
+
still respects the guards (won't destroy a dirty, or unpushed-and-unlanded,
|
|
405
|
+
worktree without `--force`), so if it *does* refuse, relay that and stop
|
|
406
|
+
rather than reaching for `--force`.
|
|
407
|
+
|
|
408
|
+
**The unpushed half of that guard cannot fire here, by construction.**
|
|
409
|
+
Step 6 landed the branch, so `merged` is true and `planDown` skips the check
|
|
410
|
+
entirely (`env/teardown.js`) — completing a spec never meets it, however the
|
|
411
|
+
branch was or was not published. `/spec-cancel` is where it does fire, because
|
|
412
|
+
a cancelled spec is unlanded and its worktree really is the only copy; the
|
|
413
|
+
publish-or-`--force` path therefore lives in that skill and this one needs no
|
|
414
|
+
equivalent. A refusal reaching this step is about a **dirty tree** instead,
|
|
415
|
+
which means something wrote into the worktree after the landing — read it,
|
|
416
|
+
don't force it.
|
|
417
|
+
|
|
418
|
+
**If the plan prints a `remote branch — confirm with the user first:` section, ask before running it.**
|
|
419
|
+
Nothing published this branch for you, so a remote copy exists only because
|
|
420
|
+
you pushed it by hand — and it outlives teardown unless someone deletes it. The planner only ever offers
|
|
421
|
+
this for a branch that has **landed**, so say so plainly when you ask — the
|
|
422
|
+
commits are on the base branch (or captured by the deploy tag), so deleting
|
|
423
|
+
the remote branch loses nothing. On a yes, run the printed
|
|
424
|
+
`git push <remote> --delete <branch>`; on a no, leave it and say the remote
|
|
425
|
+
branch is still there. Never fold it into the `run these:` batch — a project
|
|
426
|
+
that wants it unattended sets `teardown.deleteRemoteBranch: "always"` in
|
|
427
|
+
`env.config.json`, and then it appears in `run these:` instead of here.
|
|
428
|
+
4. **Reap orphaned test-DB volumes:** run `skitterspec spec-env prune`. It lists
|
|
429
|
+
Docker volumes in the repo namespace that belong to **no live spec** (no
|
|
430
|
+
worktree) — leftovers from declined/aborted teardowns, manual
|
|
431
|
+
`git worktree remove`, or `--keep-volumes`. Show the user the orphan list and,
|
|
432
|
+
**only on their confirmation**, execute the printed `docker volume rm`
|
|
433
|
+
commands. **This one still asks**, unlike 1–3: it reaps volumes belonging to
|
|
434
|
+
*other* specs, and this spec having landed cleanly says nothing about those.
|
|
435
|
+
Non-fatal: if prune can't run (Docker down) or the user declines, report it and
|
|
436
|
+
finish completing anyway — never block the spec on it. Skip when Docker isn't
|
|
437
|
+
in use (the command self-reports "no orphaned volumes").
|
|
438
|
+
|
|
439
|
+
**Report from where you now are.** After a teardown you relocated for, the
|
|
440
|
+
worktree path in the report is a directory that no longer exists and the landed
|
|
441
|
+
work is on the base branch in the primary checkout — say both, so nobody goes
|
|
442
|
+
looking for a tree that is gone. A session that was a worktree tab has finished
|
|
443
|
+
its job at that point; its shell is the operator's own to close.
|
|
444
|
+
|
|
445
|
+
**Say what you reclaimed.** With no confirmation step the user never saw this
|
|
446
|
+
coming, so the final report must name the worktree path removed and the branch
|
|
447
|
+
deleted (or, under `--keep-env`, that both were kept). A teardown nobody
|
|
448
|
+
authorised and nobody was told about is the one way this step can lose someone's
|
|
449
|
+
place.
|
|
450
|
+
|
|
451
|
+
If `env.config.json` is absent, skip this entirely — behave exactly as before.
|