@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,220 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-sync
|
|
3
|
+
description: Run the repo-wide spec-sync operations against Jira — what is linked, the project's statuses, read-back verification, manual stamping, and bulk apply. Run it bare for the repo-wide overview. Defers to /spec-push and /spec-status for per-spec work. Opt-in — needs specs/.core/jira.config.json. Use when the user says "/spec-sync", "run spec-sync", "what's linked to Jira", "which statuses does the project have", or "mirror the whole backlog".
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# /spec-sync — the repo-wide Jira sync operations
|
|
8
|
+
|
|
9
|
+
> Stay silent while this runs — speak only to ask something you cannot answer
|
|
10
|
+
> yourself, or to report a failure at the moment it happens. Read
|
|
11
|
+
> `.claude/rules/spec-reports.md` before reporting; it defines the block this
|
|
12
|
+
> skill ends with.
|
|
13
|
+
|
|
14
|
+
`/spec-push` and `/spec-status` cover **one spec**. This skill covers everything
|
|
15
|
+
**repo-wide**, and is the answer to a bare "run spec-sync" — which is not itself
|
|
16
|
+
a command.
|
|
17
|
+
|
|
18
|
+
**Opt-in**: only runs when `specs/.core/jira.config.json` exists. If absent,
|
|
19
|
+
tell the user how to enable Jira sync and stop.
|
|
20
|
+
|
|
21
|
+
## The invocation — always state it
|
|
22
|
+
|
|
23
|
+
`spec-sync` is a subcommand of a binary that is a **local devDependency**, so it
|
|
24
|
+
is never on `PATH`. Typing `spec-sync` gives `command not found`, which reads as
|
|
25
|
+
a broken install rather than a wrong invocation. Always run it — and always show
|
|
26
|
+
the user you ran it — in full:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
pnpm exec skitterspec-jira spec-sync <subcommand> [args]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
In a project that installs the Jira superset the binary is
|
|
33
|
+
`skitterspec-jira` (it also answers to `skitterspec`). Never print a bare
|
|
34
|
+
`spec-sync …` as if the user could type it.
|
|
35
|
+
|
|
36
|
+
## 1. Route the ask
|
|
37
|
+
|
|
38
|
+
| The user asks | Run |
|
|
39
|
+
|---------------|-----|
|
|
40
|
+
| bare `/spec-sync`, "what's linked?", "how much is mirrored?" | `linked` |
|
|
41
|
+
| "what statuses does the project have?" | `states` |
|
|
42
|
+
| "what specs are there?", "what's in the backlog?" | `list` — or hand to `/spec-list` |
|
|
43
|
+
| "did the mirror survive the push?" | `verify <spec> --stored <file>` |
|
|
44
|
+
| "link this spec to PROJ-1 by hand" | `stamp <spec> --issue PROJ-1` |
|
|
45
|
+
| "mirror the whole backlog / every complete spec" | `apply --all <bucket>` — **confirm first** |
|
|
46
|
+
| "what ticket am I on?", writing a commit | `ref` |
|
|
47
|
+
| "what shipped in this release?", "which tickets does CI mark deployed?" | `released` — `--json` for a script; recording deploys is the project's own |
|
|
48
|
+
| "is any of this wired up?", "why isn't sync working?" | `doctor` — scaffold, isolation, tracker and credentials in one |
|
|
49
|
+
| "set my Jira credentials", "am I authenticated?" | `credentials <status\|set\|unset>` |
|
|
50
|
+
| push one spec, or "what would push?" | **defer** — see below |
|
|
51
|
+
|
|
52
|
+
The Linear provider's `retarget`, `reattach`, `stage`, `whoami`, `users`,
|
|
53
|
+
`assign` and `sanitise` are **not yet shipped for the Jira provider** — say so
|
|
54
|
+
when one is asked for, rather than improvising an equivalent.
|
|
55
|
+
|
|
56
|
+
**With no argument, run `linked`.** It is the repo-wide overview, it is
|
|
57
|
+
read-only, and it is what a bare "run spec-sync" means.
|
|
58
|
+
|
|
59
|
+
**When the ask is genuinely ambiguous between a read and a write — ask.**
|
|
60
|
+
"Sync the backlog" could mean `linked` (show me) or `apply --all backlog`
|
|
61
|
+
(write dozens of issues). Never resolve that guess in favour of the write.
|
|
62
|
+
|
|
63
|
+
## 2. Defer, don't duplicate
|
|
64
|
+
|
|
65
|
+
Two front doors to one write path is worse than none:
|
|
66
|
+
|
|
67
|
+
- **Push one spec** → `/spec-push`. It owns the transport choice, the
|
|
68
|
+
status-name gate, the plan, the apply, the stamping and the snapshot.
|
|
69
|
+
- **Per-spec status** ("is this spec in sync?", "what would push?") →
|
|
70
|
+
`/spec-status`.
|
|
71
|
+
|
|
72
|
+
Say which skill you're handing to and stop; don't reimplement either.
|
|
73
|
+
|
|
74
|
+
## 3. The read-only subcommands
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
pnpm exec skitterspec-jira spec-sync linked [--json]
|
|
78
|
+
pnpm exec skitterspec-jira spec-sync states [--via api|mcp] [--json]
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
- **`linked`** is offline: which specs carry a `jira_identifier`, their bucket,
|
|
82
|
+
and an `N/M linked` total. Relay it, and when specs in `in-progress` have no
|
|
83
|
+
issue, say so — those are the ones a push would mint.
|
|
84
|
+
- **`states`** reaches the project. It also reports the **transport** (`api`
|
|
85
|
+
when credentials resolve, else `mcp`), which is the honest way to answer "how
|
|
86
|
+
is this talking to Jira?". Its non-JSON output ends with the **bucket map** —
|
|
87
|
+
every lifecycle bucket against the project's real statuses, a verdict per
|
|
88
|
+
row — which is the answer to relay when the user asks whether the mapping is
|
|
89
|
+
right.
|
|
90
|
+
- **`list`** is the read side of the mirror: every spec issue Jira holds,
|
|
91
|
+
joined to the local spec folder that owns it. Unlike `linked`, it asks JIRA
|
|
92
|
+
what exists rather than the repo — which is the only way to see a spec started
|
|
93
|
+
on a branch this checkout has not got. Scope is the live statuses by default
|
|
94
|
+
(`--all`, or `--state <name>`). **`/spec-list` is the front door** — hand over
|
|
95
|
+
to it for anything beyond a bare listing; it carries the MCP path and the
|
|
96
|
+
offline degradation.
|
|
97
|
+
|
|
98
|
+
## 4. `verify` — check what the tracker actually stored
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
pnpm exec skitterspec-jira spec-sync verify <spec> --stored <file>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`--stored` is **what Jira currently holds**, read back over MCP:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{ "issue": "…", "subIssues": { "01-engine": "…" } }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**It is not a `jira-base/*.base.json` snapshot.** That file holds content
|
|
111
|
+
*hashes* keyed by identifier; comparing one against a description reports
|
|
112
|
+
enormous losses on a perfectly intact mirror. The engine refuses a snapshot
|
|
113
|
+
outright — if you see that refusal, you passed the wrong file, not found a bug.
|
|
114
|
+
|
|
115
|
+
Warns, never fails. The repo is the source of truth; a mangled mirror is fixed
|
|
116
|
+
by pushing again. Jira stores descriptions as ADF and the adapter converts
|
|
117
|
+
markdown at the boundary, so the comparison is words, not bytes.
|
|
118
|
+
|
|
119
|
+
## 5. `stamp` — the manual escape hatch
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
pnpm exec skitterspec-jira spec-sync stamp <spec> --issue PROJ-1 [--url URL] [--sub <ref>=PROJ-2 …]
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Writes the keys into the spec's frontmatter without touching Jira. For adopting
|
|
126
|
+
an issue created by hand, or repairing a stamp — not the normal path, which is
|
|
127
|
+
`/spec-push`. A wrong key here makes the next push see an **unlinked** spec and
|
|
128
|
+
mint a duplicate, so read the values back to the user before writing.
|
|
129
|
+
|
|
130
|
+
## 6. `apply --all <bucket>` — bulk, and the one with real blast radius
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
pnpm exec skitterspec-jira spec-sync apply --all <bucket> [--via api|mcp] [--json]
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Confirm before running, and state creates and updates separately.** They are
|
|
137
|
+
not the same risk:
|
|
138
|
+
|
|
139
|
+
- an **update** refreshes a mirror that already exists;
|
|
140
|
+
- a **create** mints new issues and subtasks in someone's shared tracker.
|
|
141
|
+
|
|
142
|
+
A repo adopting Jira reports "N to create" for every unlinked spec, so an
|
|
143
|
+
unconsidered `--all` can mint dozens of subtasks. Get the counts first — run
|
|
144
|
+
`linked` to see what is unlinked, or `spec-sync plan <spec>` per spec for exact
|
|
145
|
+
numbers — then show the user something like:
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
apply --all backlog would:
|
|
149
|
+
create 12 issue(s) + 34 subtask(s) ← new objects in Jira
|
|
150
|
+
update 3 issue(s) + 5 subtask(s) ← refresh existing mirrors
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Only run it on an explicit yes. It is resumable: every key is stamped the moment
|
|
154
|
+
its object exists, so an interrupted run continues rather than duplicating.
|
|
155
|
+
|
|
156
|
+
`--all` refuses over MCP by design — bulk goes through the API path.
|
|
157
|
+
|
|
158
|
+
## 7. `ref` and `released` — tickets in commits
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
pnpm exec skitterspec-jira spec-sync ref [--json]
|
|
162
|
+
pnpm exec skitterspec-jira spec-sync released [<range>] [--json]
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
`ref` prints the ticket for the branch you are on, so a commit can carry
|
|
166
|
+
`Refs: <PROJ-N>` — see `.claude/rules/commit-trailers.md`.
|
|
167
|
+
**Off a spec branch, or on a spec that is not linked, it prints nothing and exits non-zero.**
|
|
168
|
+
That is the correct answer, not an error to work around: do not invent a ref,
|
|
169
|
+
and never write `Refs: none`.
|
|
170
|
+
|
|
171
|
+
`released` reports the tickets in a commit range — by default since the most
|
|
172
|
+
recent tag, and it always prints the range it chose so a wrong default is
|
|
173
|
+
visible. It is **read-only**: it does not move anything in Jira. Each ticket
|
|
174
|
+
row names the `spec` and `url` behind it (`null` when no spec linked the ref),
|
|
175
|
+
so `--json` is what a project's CI pipes into its own tooling to record a
|
|
176
|
+
release or a deploy. Recording those is the project's job, not skitterspec's.
|
|
177
|
+
|
|
178
|
+
Relay the **unreferenced count** even when it is zero. A chore commit
|
|
179
|
+
legitimately carries no ticket and a *missed* trailer looks identical, so
|
|
180
|
+
omitting the number reads as "everything is accounted for" when it may not be.
|
|
181
|
+
|
|
182
|
+
**Bookkeeping commits are excluded.** A spec's `chore(spec): complete <name>`
|
|
183
|
+
commit carries the same ref as the code it describes but lands *after* the tag
|
|
184
|
+
that shipped it, so counting it would put the ticket in two consecutive releases.
|
|
185
|
+
A commit whose changed paths are **all** under `release.ignorePaths` (default
|
|
186
|
+
`specs/`) contributes nothing; one that touches an ignored path *and* a source
|
|
187
|
+
file still counts. Relay the **ignored count** whenever it is non-zero — that is
|
|
188
|
+
the report saying which commits it set aside.
|
|
189
|
+
|
|
190
|
+
## 8. Report
|
|
191
|
+
|
|
192
|
+
Relay the engine's output **above the block**, and name the subcommand you ran
|
|
193
|
+
**in full**, so the user can re-run it themselves.
|
|
194
|
+
|
|
195
|
+
End with the block defined in `.claude/rules/spec-reports.md`. That file carries
|
|
196
|
+
the shape; this section carries only what is specific here.
|
|
197
|
+
|
|
198
|
+
**Verdicts**
|
|
199
|
+
|
|
200
|
+
- `✅` — the subcommand did what it says.
|
|
201
|
+
- `⚠️` — it ran, with something worth knowing — a partial result, a warning it
|
|
202
|
+
printed, a degradation it fell back to.
|
|
203
|
+
- `❌` — it wrote some objects and failed on another. Say what exists now.
|
|
204
|
+
- `⏸` — it refused: no config, an unvalidated status list, a bad argument.
|
|
205
|
+
Nothing was written.
|
|
206
|
+
|
|
207
|
+
**A branch-local bucket is the normal case, never the caveat.** `linked`
|
|
208
|
+
reads the checkout it runs in, and an in-flight spec's move to
|
|
209
|
+
`in-progress` lives on its own unlanded branch — so from the primary
|
|
210
|
+
checkout the spec still reads `backlog` while the tracker (pushed from
|
|
211
|
+
the worktree) is ahead. That is worktree mode working as designed:
|
|
212
|
+
report it `✅` with the fact in `Notes`. Spending `⚠️` on the normal
|
|
213
|
+
case is how the verdict stops meaning anything — the same argument
|
|
214
|
+
`spec-reports.md` makes for `Untouched`.
|
|
215
|
+
|
|
216
|
+
**Fields:** `Tracker` · `Notes` · `Follow-ups` · `Next`
|
|
217
|
+
|
|
218
|
+
`Tracker` says what changed in Jira **and that the repo is unchanged** — it is
|
|
219
|
+
the source of truth either way, and a report that omits the second half reads as
|
|
220
|
+
though a sync had edited the repo.
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-to-main
|
|
3
|
+
description: Land an in-progress spec's branch onto main WITHOUT finishing it — rebase + fast-forward so the work reaches main (to run it in CI / a shared test env), while the worktree stays and the spec stays In Progress. Repeatable — land again as you commit more. Targets a spec by name (arg) or the spec in context. Use when the user says "/spec-to-main", "land this on main but keep going", "I need this on main to run tests before finishing", or "merge to main without completing the spec".
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# /spec-to-main — land the branch on main, keep the spec open
|
|
8
|
+
|
|
9
|
+
> Stay silent while this runs — speak only to ask something you cannot answer
|
|
10
|
+
> yourself, or to report a failure at the moment it happens. Read
|
|
11
|
+
> `.claude/rules/spec-reports.md` before reporting; it defines the block this
|
|
12
|
+
> skill ends with.
|
|
13
|
+
|
|
14
|
+
The **intermediate** landing. `/spec-complete` also lands the branch, but then
|
|
15
|
+
verifies every phase, flips the status to Complete, `git mv`s the spec to
|
|
16
|
+
`complete/`, and tears the environment down.
|
|
17
|
+
**`/spec-to-main` stops after the land**: the worktree stays, the spec stays
|
|
18
|
+
`In Progress`, and you can land again as you add commits.
|
|
19
|
+
|
|
20
|
+
Use it when a later phase can only be done *after* the current work is on `main` —
|
|
21
|
+
e.g. it needs to run in CI, a deploy pipeline, or a shared test environment that
|
|
22
|
+
builds from `main`. Land what you have, run that step, then come back and finish
|
|
23
|
+
the remaining phases with `/spec-next` and eventually `/spec-complete`.
|
|
24
|
+
|
|
25
|
+
It reuses the **same engine** as `/spec-complete`'s landing (`spec-env integrate`
|
|
26
|
+
— rebase + fast-forward), so it produces identical linear history. Because a
|
|
27
|
+
fast-forward leaves `base == branch`, the operation is
|
|
28
|
+
**idempotent and repeatable**: new commits put the branch ahead of base again,
|
|
29
|
+
and you can run `/spec-to-main` as many times as you like.
|
|
30
|
+
|
|
31
|
+
## 0. Preconditions — when this applies
|
|
32
|
+
|
|
33
|
+
- **Isolation must be on** (`specs/.core/env.config.json` exists **and** the spec
|
|
34
|
+
was provisioned by `/spec-start` — a worktree, or its branch in the checkout under
|
|
35
|
+
`mode: checkout`). If isolation is absent, there is nothing to land — the spec
|
|
36
|
+
is authored directly on `main` already. Say so and stop. `spec-env integrate`
|
|
37
|
+
reads `mode` and emits the matching plan; in checkout mode it rebases in place,
|
|
38
|
+
switches to base and fast-forwards, all in the one repo.
|
|
39
|
+
- **Feature / Bug specs only.** A **Hotfix** (`Type: Hotfix`) is built on a
|
|
40
|
+
release *tag* and cannot fast-forward onto `main` — refuse it and point the user
|
|
41
|
+
at `/spec-complete` (it lands a hotfix via tag + cherry-pick). Check the header
|
|
42
|
+
`> **Type:**` before proceeding.
|
|
43
|
+
|
|
44
|
+
## 1. Identify the target spec
|
|
45
|
+
|
|
46
|
+
- Use the name/path argument if given, else the spec **in context**. If unclear,
|
|
47
|
+
ask which spec.
|
|
48
|
+
- Locate its folder under `specs/in-progress/`. Entry point is `00-overview.md`;
|
|
49
|
+
confirm `> **Status:**` is `In Progress` and `> **Type:**` is `Feature` or
|
|
50
|
+
`Bug`.
|
|
51
|
+
|
|
52
|
+
## 2. Require a clean worktree
|
|
53
|
+
|
|
54
|
+
The land rebases the branch — it refuses a dirty tree. If the worktree has
|
|
55
|
+
uncommitted changes, offer `/commit` and **stop**; don't auto-commit.
|
|
56
|
+
|
|
57
|
+
**If the spec is live** (you took the running instance with `/spec-live`):
|
|
58
|
+
`integrate` is live-aware — it ends the live session first (releases the branch
|
|
59
|
+
back to base, re-isolates it into its worktree, clears the receipt), then prints
|
|
60
|
+
the landing plan. Commit any live fixes to the branch first; it refuses if the
|
|
61
|
+
primary checkout is dirty, or if a *different* spec holds it (release that one with
|
|
62
|
+
`/spec-live main`, which the user types).
|
|
63
|
+
|
|
64
|
+
## 3. Tests must be green before landing
|
|
65
|
+
|
|
66
|
+
Don't push red to `main`. Run the project's typecheck and test commands
|
|
67
|
+
**in the worktree**; the suite must be **green**. For a **Bug** spec, confirm
|
|
68
|
+
the originally-failing test now passes. If anything is red, stop and report —
|
|
69
|
+
landing broken code onto `main` defeats the purpose.
|
|
70
|
+
|
|
71
|
+
(Note this is the *worktree* suite. The whole point of this skill is often to run
|
|
72
|
+
a *further* check that only exists on `main` / in CI — that one runs **after** the
|
|
73
|
+
land, in step 5.)
|
|
74
|
+
|
|
75
|
+
## 4. Land — rebase + fast-forward
|
|
76
|
+
|
|
77
|
+
Run `skitterspec spec-env integrate <name>` and run the printed commands
|
|
78
|
+
**in order**:
|
|
79
|
+
|
|
80
|
+
- `git -C <worktree> rebase <base>` — replay the branch onto base.
|
|
81
|
+
- `git -C <mainRepoPath> merge --ff-only <branch>` — fast-forward base.
|
|
82
|
+
|
|
83
|
+
On a **rebase conflict** (non-zero exit), run `git -C <worktree> rebase --abort`,
|
|
84
|
+
relay the conflict, and **stop** — leave the resolution to the user; change
|
|
85
|
+
nothing else.
|
|
86
|
+
|
|
87
|
+
On a **no-op** ("already landed on `<base>` — nothing to integrate"), just say so
|
|
88
|
+
and continue — the branch has no commits base doesn't already have.
|
|
89
|
+
|
|
90
|
+
**Then run the after-land commands.** Where the plan ends with a
|
|
91
|
+
`then, in the primary checkout (<path>), run:` section — the project's
|
|
92
|
+
`afterLand`, such as a data migration — run those commands in that directory,
|
|
93
|
+
in order, after the fast-forward and **before** the re-test below, which may
|
|
94
|
+
need them. Run only the lines under that heading; a
|
|
95
|
+
`skipped (nothing in the land matched):` block lists conditional entries this
|
|
96
|
+
land did not need, and is information, never commands. Run them on the no-op too: the engine prints them there because a
|
|
97
|
+
land made elsewhere leaves them pending here.
|
|
98
|
+
**Stop at the first non-zero exit**, and carry on with §5: a failure makes the run `⚠️`, naming the command
|
|
99
|
+
that failed and the ones that did not run, and it **never undoes the land**.
|
|
100
|
+
No section, nothing to run, and nothing to say about it.
|
|
101
|
+
|
|
102
|
+
## 5. Re-test on base, then report
|
|
103
|
+
|
|
104
|
+
- Run the project's test command **from the primary checkout** — base must be
|
|
105
|
+
**green** after the fast-forward.
|
|
106
|
+
- Add a **Changelog** entry to `00-overview.md` recording the intermediate land
|
|
107
|
+
and *why*, e.g.
|
|
108
|
+
`- <YYYY-MM-DD> — Landed intermediate work onto <base> to <run CI / deploy to
|
|
109
|
+
test env / …>; spec stays In Progress.`
|
|
110
|
+
- Do **NOT**: add a State-log row (status doesn't change), flip any phase/status
|
|
111
|
+
to Complete, `git mv` the spec, or tear down the worktree/stack.
|
|
112
|
+
**The spec stays `In Progress` and the worktree stays put.**
|
|
113
|
+
- It **never pushes** — say the user can `git push` the base branch themselves to
|
|
114
|
+
trigger CI / the shared env.
|
|
115
|
+
- `Next` points the way forward: `/spec-next` to continue the remaining phases
|
|
116
|
+
(you'll keep committing on the same branch and can `/spec-to-main` again), and
|
|
117
|
+
`/spec-complete` when every phase is genuinely done — it will land the final
|
|
118
|
+
commits, finalise, and tear down.
|
|
119
|
+
|
|
120
|
+
End with the block defined in `.claude/rules/spec-reports.md`. That file carries
|
|
121
|
+
the shape; this section carries only what is specific here.
|
|
122
|
+
|
|
123
|
+
**Verdicts**
|
|
124
|
+
|
|
125
|
+
- `✅` — the branch is on the base and the base is green.
|
|
126
|
+
- `⚠️` — landed, with something worth knowing — an after-land command that
|
|
127
|
+
failed, for one.
|
|
128
|
+
- `❌` — the rebase conflicted, or the base went red after the fast-forward.
|
|
129
|
+
Quote it; the repo is mid-something and that is what the reader needs.
|
|
130
|
+
- `⏸` — a dirty worktree, red tests, or no spec to land. Nothing moved.
|
|
131
|
+
|
|
132
|
+
**Fields:** `Branch` · `Tests` · `Notes` · `Landed` · `Follow-ups` · `Next`
|
|
133
|
+
|
|
134
|
+
`Notes` carries the after-land commands §4 ran, and where, and any it
|
|
135
|
+
skipped because the land matched no `when` — or the one that failed and the ones that did not run. Nothing about it when none are
|
|
136
|
+
configured.
|
|
137
|
+
|
|
138
|
+
**No `Spec` field, deliberately.** This skill changes no status and moves no
|
|
139
|
+
folder, and a `Spec` line here would read as though it had. The spec stays
|
|
140
|
+
`In Progress` and the worktree stays standing — if that needs saying, the
|
|
141
|
+
verdict clause says it.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
// The Jira superset's entry point: the base CLI plus this provider's commands.
|
|
5
|
+
//
|
|
6
|
+
// In the PUBLISHED distribution, bin/src/assets are composed at build time and
|
|
7
|
+
// never committed — so a missing src/ means someone is running from a raw
|
|
8
|
+
// checkout of the dist package, which has nothing to run. Inline rather than
|
|
9
|
+
// shared: a helper would have to live in src/, which is exactly what may be
|
|
10
|
+
// missing. In the workspace source package src/ always exists, so this is
|
|
11
|
+
// inert there.
|
|
12
|
+
const { existsSync } = require('node:fs')
|
|
13
|
+
const { join } = require('node:path')
|
|
14
|
+
if (!existsSync(join(__dirname, '..', 'src'))) {
|
|
15
|
+
console.error(
|
|
16
|
+
'skitterspec-jira: no build output — this package\'s bin/src/assets are composed, not committed.\n' +
|
|
17
|
+
' run "npm run build" in the skitterspec repo, then try again.',
|
|
18
|
+
)
|
|
19
|
+
process.exit(1)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const { run, HELP } = require('../src/cli.js')
|
|
23
|
+
|
|
24
|
+
// The provider's isolation defaults, registered beneath the project's own
|
|
25
|
+
// env.config.json so `spec-env stage` claims this provider's snapshot sidecar
|
|
26
|
+
// without a hand edit (see common src/env/config.js, setProviderEnvDefaults).
|
|
27
|
+
require('../src/env/config.js').setProviderEnvDefaults(
|
|
28
|
+
require('../src/vendor/jira/config.js').ENV_CONFIG_DEFAULTS,
|
|
29
|
+
)
|
|
30
|
+
const {
|
|
31
|
+
PROVIDER_COMMANDS,
|
|
32
|
+
providerHelpSection,
|
|
33
|
+
} = require('../src/vendor/jira/commands.js')
|
|
34
|
+
|
|
35
|
+
async function main(argv) {
|
|
36
|
+
const [cmd, ...rest] = argv
|
|
37
|
+
|
|
38
|
+
// A source package HAS a runnable bin and src, but its assets/ is
|
|
39
|
+
// PRE-composition (seam markers still literal). Installing from it would
|
|
40
|
+
// write those markers into the user's skills — refuse before any install
|
|
41
|
+
// command runs.
|
|
42
|
+
if (cmd === 'init' || cmd === 'update') {
|
|
43
|
+
require('../src/init.js').assertComposedAssets()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Base help + what this distribution adds. Matched on the COMMAND SLOT only,
|
|
47
|
+
// never the whole argv: `spec-sync --help` must reach that command's own
|
|
48
|
+
// help, not be swallowed by the top-level one.
|
|
49
|
+
if (!cmd || cmd === '--help' || cmd === '-h') {
|
|
50
|
+
process.stdout.write(`${HELP}\n${providerHelpSection()}`)
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const provider = PROVIDER_COMMANDS[cmd]
|
|
55
|
+
if (provider) {
|
|
56
|
+
// Propagate the exit code: a refused stamp or a failed state check must
|
|
57
|
+
// not look successful to a caller checking $?.
|
|
58
|
+
process.exitCode = await provider.run(rest)
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
await run(argv)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
main(process.argv.slice(2)).catch((err) => {
|
|
66
|
+
console.error(`skitterspec-jira: ${err.message}`)
|
|
67
|
+
process.exit(1)
|
|
68
|
+
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,42 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skitterbyte/skitterspec-jira",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Spec-driven development for Claude Code, with one-way Jira Cloud sync — a superset of @skitterbyte/skitterspec: the base filesystem workflow plus /spec-status · /spec-push and the spec-sync CLI. The repo is canonical; Jira is a generated mirror. Install this OR the base OR the Linear superset — exactly one.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"claude",
|
|
7
|
+
"claude-code",
|
|
8
|
+
"spec-driven-development",
|
|
9
|
+
"sdd",
|
|
10
|
+
"skills",
|
|
11
|
+
"scaffold",
|
|
12
|
+
"jira"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"author": "Reuben Greaves",
|
|
16
|
+
"type": "commonjs",
|
|
17
|
+
"bin": {
|
|
18
|
+
"skitterspec-jira": "bin/skitterspec-jira.js",
|
|
19
|
+
"skitterspec": "bin/skitterspec-jira.js"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"bin",
|
|
23
|
+
"src",
|
|
24
|
+
"assets",
|
|
25
|
+
"MIGRATION.md"
|
|
26
|
+
],
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=22.13"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"prompts": "^2.4.2"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"prepare": "node ../../scripts/build-dist.js skitterspec-jira",
|
|
35
|
+
"prepack": "node ../../scripts/build-dist.js skitterspec-jira"
|
|
36
|
+
},
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/SkitterByte/skitterspec.git",
|
|
40
|
+
"directory": "packages/skitterspec-jira"
|
|
41
|
+
}
|
|
42
|
+
}
|