@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,178 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-init
|
|
3
|
+
description: Bootstrap the spec-driven-development workflow in the current project — create the specs/ lifecycle folders and .core, wire version-control so specs are tracked, verify the spec skills are installed, and add the spec workflow to CLAUDE.md and .claude/rules. Idempotent and safe to re-run. Use when setting up a new project for specs or repairing the setup, or when the user says "/spec-init", "set up specs here", "initialise the spec process".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /spec-init — set up the spec-driven-development workflow
|
|
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
|
+
Bootstrap (or repair) everything this project needs to run the spec lifecycle.
|
|
14
|
+
**Idempotent:** detect what already exists, create only what's missing, and never
|
|
15
|
+
clobber customised content. Finish with a summary of created vs already-present.
|
|
16
|
+
|
|
17
|
+
> If `@skitterbyte/skitterspec` is installed, `npx @skitterbyte/skitterspec init` does
|
|
18
|
+
> all of the below mechanically. This skill is the manual/repair path and is
|
|
19
|
+
> useful when the package isn't available or you only need to fix part of the
|
|
20
|
+
> setup.
|
|
21
|
+
>
|
|
22
|
+
> **Re-running on an already-set-up repo is safe.** `init` detects the existing
|
|
23
|
+
> setup (via the committed `specs/.core/.skitterspec-manifest.json` of installed
|
|
24
|
+
> file hashes) and, interactively, offers three paths — **Resync** (update managed
|
|
25
|
+
> skills/rules to the latest but keep files you've edited), **Start again** (reset
|
|
26
|
+
> the managed scaffolding fresh — never your specs or config, with a confirm), or
|
|
27
|
+
> **Leave alone**. Non-interactively it only adds what's missing; `--resync` /
|
|
28
|
+
> `--reset` (reset needs `--yes`) drive the stronger actions.
|
|
29
|
+
|
|
30
|
+
The system is **thirteen skills**: `spec` (feature), `spec-bug` (bug),
|
|
31
|
+
`spec-hotfix` (a bug fixed on a released tag),
|
|
32
|
+
`no-spec` (work that genuinely has none — off the base branch all the same),
|
|
33
|
+
`spec-review`, `spec-start`,
|
|
34
|
+
`spec-next`, `spec-diff` (read a spec's diff as a page),
|
|
35
|
+
`spec-reviewed` (pick up a review you approved on that page), `spec-to-main`,
|
|
36
|
+
`spec-complete`, `spec-cancel`, and this `spec-init`. The lifecycle is `backlog → in-progress → complete / cancelled`,
|
|
37
|
+
with `.core` holding always-apply project rules.
|
|
38
|
+
|
|
39
|
+
## 0. Workspace mode (only when adopting isolation)
|
|
40
|
+
|
|
41
|
+
If this project is adopting per-spec isolation, ask which `mode` belongs in
|
|
42
|
+
`specs/.core/env.config.json` — `worktree` (default; a checkout per spec, several
|
|
43
|
+
at once, one terminal session each) or `checkout` (the branch is built in the
|
|
44
|
+
checkout you are already in; one spec at a time, no hand-off). It is a question
|
|
45
|
+
about how the operator works, not about what the repo contains, so ask rather
|
|
46
|
+
than infer it from whether dev servers or Docker are configured.
|
|
47
|
+
|
|
48
|
+
## 0b. Release gating (optional, and separate)
|
|
49
|
+
|
|
50
|
+
Ask whether specs should record a **release-gating** decision — does this change
|
|
51
|
+
ship behind a feature flag, or land live? Adopting it copies
|
|
52
|
+
`specs/.core/gating.config.json.example` → `gating.config.json` and sets
|
|
53
|
+
`guidance` to wherever this project documents its flags.
|
|
54
|
+
|
|
55
|
+
It is **orthogonal to isolation**: a project can adopt either, both, or neither.
|
|
56
|
+
Skitterspec never learns how the flags work — it asks the question, cites that
|
|
57
|
+
path, and records the answer on each spec. Leave it off and nothing appears:
|
|
58
|
+
no question, no header, no check. Off is a perfectly good answer for a project
|
|
59
|
+
that does not use flags.
|
|
60
|
+
|
|
61
|
+
## 1. Folders
|
|
62
|
+
|
|
63
|
+
Create any that are missing; drop a `.gitkeep` into ones that would otherwise be
|
|
64
|
+
empty so git keeps them:
|
|
65
|
+
|
|
66
|
+
- `specs/.core/` — project rules (always apply; never moved)
|
|
67
|
+
- `specs/backlog/` `specs/in-progress/` `specs/complete/` `specs/cancelled/`
|
|
68
|
+
|
|
69
|
+
## 2. Version control — keep specs tracked
|
|
70
|
+
|
|
71
|
+
The whole lifecycle lives in git — **everything under `specs/` is tracked**, so
|
|
72
|
+
the default is simply *no ignore rule excluding it*. Ensure `.gitignore` has no
|
|
73
|
+
`/specs/*` (or similar) entry that would hide spec folders; if one exists and the
|
|
74
|
+
project wants everything tracked, remove it. Confirm with
|
|
75
|
+
`git check-ignore -v specs/.core/<any-file>` — it should print nothing (tracked).
|
|
76
|
+
|
|
77
|
+
- **`.core` dotfile caveat:** only relevant if a `/specs/*` ignore is
|
|
78
|
+
(re)introduced — `*` matches dotfiles, so `.core` would need an explicit
|
|
79
|
+
`!/specs/.core/` negation. With no ignore rule, it's tracked automatically.
|
|
80
|
+
- If the project uses a formatter/linter ignore glob that excludes `specs/**`,
|
|
81
|
+
decide whether spec markdown should be formatted/linted and adjust accordingly.
|
|
82
|
+
- If a project later wants to **stop** versioning work-in-progress specs, that's
|
|
83
|
+
a deliberate opt-out (e.g. `/specs/*` + `!/specs/.core/`) — ask first; the
|
|
84
|
+
default is track-everything.
|
|
85
|
+
|
|
86
|
+
## 3. Verify the skills are installed
|
|
87
|
+
|
|
88
|
+
Check each of the ten skills resolves — `.claude/skills/<name>/SKILL.md`
|
|
89
|
+
(project) or `~/.claude/skills/<name>/` (global). List any missing. This skill
|
|
90
|
+
scaffolds the project; it does **not** regenerate skill bodies — missing skills
|
|
91
|
+
must be copied in (e.g. `npx @skitterbyte/skitterspec init`) from a global install
|
|
92
|
+
or a sibling project. If most/all are global, just confirm availability.
|
|
93
|
+
|
|
94
|
+
## 4. Governing rule (`.claude/rules/spec-planning.md`)
|
|
95
|
+
|
|
96
|
+
Ensure it exists. If missing, create it documenting:
|
|
97
|
+
|
|
98
|
+
- the lifecycle skills with their **status** and **folder** (table);
|
|
99
|
+
- the **type** convention — header `> **Type:** Feature|Bug` + filename prefix
|
|
100
|
+
`feat-`/`bug-` (never `[BUG]` brackets — glob hazard);
|
|
101
|
+
- the **Author** / **Developer** header fields;
|
|
102
|
+
- the **State log** audit table (folder/status transitions), kept separate from
|
|
103
|
+
the **Changelog** (decisions);
|
|
104
|
+
- the project's concrete typecheck/test commands, and the rule that
|
|
105
|
+
**every phase ends with creating + running tests**.
|
|
106
|
+
|
|
107
|
+
Read a sibling spec skill (e.g. `spec`, `spec-next`) for the canonical shapes
|
|
108
|
+
rather than inventing them. If the rule already exists, leave it unless stale.
|
|
109
|
+
|
|
110
|
+
## 4a. The review-gate hook (`.claude/hooks/review-gate.cjs`)
|
|
111
|
+
|
|
112
|
+
`skitterspec init` **and `skitterspec update`** install the hook script and
|
|
113
|
+
register it in the project's **committed** `.claude/settings.json` as a
|
|
114
|
+
`PreToolUse` hook on `Bash`. It runs one engine call per Bash tool call and
|
|
115
|
+
refuses a `git commit` in a worktree whose phase is still awaiting a verdict.
|
|
116
|
+
|
|
117
|
+
**Both commands, and that is not a detail.** Copying the script and registering
|
|
118
|
+
it are one operation, and they were once split across two code paths — so
|
|
119
|
+
`update` landed the file, reported `created:`, and wired nothing, on every
|
|
120
|
+
project that upgraded. Landing the script is not installing the hook.
|
|
121
|
+
|
|
122
|
+
**`.cjs`, and the extension is load-bearing.** The script lands inside the
|
|
123
|
+
target project, where *that* project's `package.json` decides how node parses a
|
|
124
|
+
`.js` — so CommonJS shipped as `.js` crashes in any `"type": "module"` project,
|
|
125
|
+
on every Bash tool call. `.cjs` settles it at the file. A registration left over
|
|
126
|
+
from the release that named `.js` is rewritten in place, keeping any wrapping
|
|
127
|
+
the operator added, rather than gaining a second entry beside it.
|
|
128
|
+
|
|
129
|
+
**Committed, not machine-local**, and the difference is the point: the trusted
|
|
130
|
+
worktree root is one machine's absolute path, while *a phase that ended owes an
|
|
131
|
+
answer* is the project's policy and should reach everyone who clones it. The
|
|
132
|
+
command is written with `${CLAUDE_PROJECT_DIR}`, so it holds in worktrees too.
|
|
133
|
+
|
|
134
|
+
**Say it is there, once.** A hook that blocks a commit with the operator not
|
|
135
|
+
knowing a hook exists reads as a broken git, so name it in the report when it is
|
|
136
|
+
newly registered — and say what turns it off (`review.required: false` in
|
|
137
|
+
`env.config.json`, which the hook defers to entirely).
|
|
138
|
+
|
|
139
|
+
**Never fatal, and never rewritten.** A settings file that is not parseable JSON
|
|
140
|
+
is reported and left exactly as it is — it is the operator's config, and
|
|
141
|
+
everything else in it would be lost. A settings file that already names this
|
|
142
|
+
script, however it was wrapped, is left alone rather than gaining a second copy.
|
|
143
|
+
|
|
144
|
+
## 5. CLAUDE.md
|
|
145
|
+
|
|
146
|
+
Ensure a `## Spec workflow` section exists. If absent, add one with the
|
|
147
|
+
skill table (`Skill | Action | Status | Folder`), the Feature/Bug type note,
|
|
148
|
+
and a pointer to `.claude/rules/spec-planning.md`. Also update the `specs/` entry
|
|
149
|
+
in any project-structure tree to show `.core/` + the four lifecycle folders. If
|
|
150
|
+
the section exists, refresh only stale folder/skill names — don't rewrite it.
|
|
151
|
+
|
|
152
|
+
## 6. Report
|
|
153
|
+
|
|
154
|
+
Do **not** `git commit` unless the user asks.
|
|
155
|
+
|
|
156
|
+
End with the block defined in `.claude/rules/spec-reports.md`. That file carries
|
|
157
|
+
the shape; this section carries only what is specific here.
|
|
158
|
+
|
|
159
|
+
**Verdicts**
|
|
160
|
+
|
|
161
|
+
- `✅` — every area is in place.
|
|
162
|
+
- `⚠️` — bootstrapped, with something worth knowing: a skill that could not be
|
|
163
|
+
installed, a CLAUDE.md that was left alone, a `.core` that is still ignored.
|
|
164
|
+
- `❌` — it wrote some areas and failed on another. Name which, so the re-run is
|
|
165
|
+
informed; this skill is idempotent and re-running it is the fix.
|
|
166
|
+
- `⏸` — not a git repo, or nothing it could safely write into.
|
|
167
|
+
|
|
168
|
+
**Fields:** `Built` · `Follow-ups` · `Next`
|
|
169
|
+
|
|
170
|
+
**`Built` is per area, one line each** — folders, `.gitignore` lines,
|
|
171
|
+
tooling-ignore negations, skills (present/missing), rule files, CLAUDE.md
|
|
172
|
+
section — as created / updated / already-present, plus the `git check-ignore`
|
|
173
|
+
result for `.core`. This is the one skill whose `Built` is a list rather than a
|
|
174
|
+
clause, because "what is now true of this project" is the entire answer it
|
|
175
|
+
exists to give.
|
|
176
|
+
|
|
177
|
+
**There is no spec to name**, so the verdict line drops that segment:
|
|
178
|
+
`✅ /spec-init · every area in place`.
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-jira-setup
|
|
3
|
+
description: Configure Jira sync for this repo by interview rather than by hand — asks for the site, the project and the workflow statuses, validates the answers against Jira, then writes specs/.core/jira.config.json. Safe to re-run; an existing config is reviewed, never overwritten without consent. Use when the user says "/spec-jira-setup", "set up Jira sync", "connect this repo to Jira", "configure jira.config.json", or "check my Jira setup".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /spec-jira-setup — configure Jira sync by interview
|
|
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
|
+
Writes `specs/.core/jira.config.json`, the file that switches one-way Jira
|
|
14
|
+
sync on for this repo. You **interview**; the engine
|
|
15
|
+
(`spec-sync init-config`) **validates and writes**. Keep that split: composing
|
|
16
|
+
the JSON yourself is how a malformed config gets committed, and the engine
|
|
17
|
+
already rejects everything the loader would later reject.
|
|
18
|
+
|
|
19
|
+
The gap this closes is not "I can't remember my site URL" — it's that nothing
|
|
20
|
+
ever asks which project this repo's work files into and which statuses its
|
|
21
|
+
lifecycle maps to, so the config ends up describing a shape nobody confirmed.
|
|
22
|
+
Ask about structure first; the values fall out of the answers.
|
|
23
|
+
|
|
24
|
+
## 1. Check what already exists
|
|
25
|
+
|
|
26
|
+
Read `specs/.core/jira.config.json`.
|
|
27
|
+
|
|
28
|
+
- **Absent** — this is a first-time setup. Carry on.
|
|
29
|
+
- **Present** — say so and default to **reviewing** it, not replacing it: run
|
|
30
|
+
the checks in steps 2 and 5 and report where the live config disagrees with
|
|
31
|
+
the site (a project key that no longer resolves, a status that was renamed).
|
|
32
|
+
That is the most useful thing a re-run can do. Only write when the user asks
|
|
33
|
+
for it, and then pass `--force`.
|
|
34
|
+
|
|
35
|
+
## 2. Credentials first
|
|
36
|
+
|
|
37
|
+
The interview validates its answers against Jira, so settle authentication
|
|
38
|
+
before asking anything:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
skitterspec spec-sync credentials status
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
If nothing is set, tell the user to run this **themselves**, in their own
|
|
45
|
+
terminal:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
skitterspec spec-sync credentials set
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
It prompts for **both halves** of the pair: the Atlassian account email
|
|
52
|
+
(visible) and an API token (hidden), created at
|
|
53
|
+
https://id.atlassian.com/manage-profile/security/api-tokens.
|
|
54
|
+
|
|
55
|
+
**Do not ask the user to paste an email or token into this conversation, and do not offer to store one for them.**
|
|
56
|
+
A credential pasted into a chat enters the transcript, is sent to the model,
|
|
57
|
+
and may be logged — moving where it is stored is pointless if it travels
|
|
58
|
+
through the conversation to get there. Your job is to confirm the setup is
|
|
59
|
+
ready and name the command; the values are theirs alone.
|
|
60
|
+
|
|
61
|
+
**Degrade, never block:** with no credentials and no MCP connection the answers
|
|
62
|
+
cannot be validated. Say so in one line —
|
|
63
|
+
*"Jira not reachable — can't validate the answers"* — point at the manual path
|
|
64
|
+
(`jira.config.md`, the field reference beside the example config), and
|
|
65
|
+
**stop without writing anything**. A half-written config is worse than none:
|
|
66
|
+
every other command switches on the moment the file exists.
|
|
67
|
+
|
|
68
|
+
## 3. Which site, and which project?
|
|
69
|
+
|
|
70
|
+
- **Site URL** — `https://<site>.atlassian.net`. It also keys the
|
|
71
|
+
credentials-store entry, so it must be the same site `credentials set` was
|
|
72
|
+
given.
|
|
73
|
+
- **Project key** — the identifier prefix (`PROJ` in `PROJ-123`).
|
|
74
|
+
|
|
75
|
+
**This config pins exactly one project for the whole repo**, and every spec
|
|
76
|
+
issue lands there **by construction** — there is no per-spec picker. Say that
|
|
77
|
+
plainly, because it reframes the question: it isn't "which project do you
|
|
78
|
+
like", it's *"which product's work does this repo hold"*. If the repo genuinely
|
|
79
|
+
spans two projects, sync can't express that today: say so, and offer the two
|
|
80
|
+
honest options — pick the project that owns most of the work, or split the
|
|
81
|
+
repo's specs across two checkouts. Don't invent a workaround.
|
|
82
|
+
|
|
83
|
+
## 4. Which issue types?
|
|
84
|
+
|
|
85
|
+
- **`jira.issueType`** — the type a spec mints as. Default **Task**; take the
|
|
86
|
+
default unless the project files this kind of work as something else
|
|
87
|
+
(`Story`, say).
|
|
88
|
+
- **`jira.subtaskType`** — the type a phase mints as. Default **Subtask**, and
|
|
89
|
+
it must be a subtask type in this project.
|
|
90
|
+
|
|
91
|
+
Offer the defaults and take yes for an answer — this is a confirmation, not an
|
|
92
|
+
interrogation.
|
|
93
|
+
|
|
94
|
+
## 5. Check the status names
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
skitterspec spec-sync states --json
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
It prints the project's status names, exactly as Jira spells them — and
|
|
101
|
+
reaching them is the setup's first real end-to-end check: a wrong site URL,
|
|
102
|
+
project key or credential fails here, while the user is still in the setup
|
|
103
|
+
conversation. Relay a failure with its fix rather than pressing on.
|
|
104
|
+
|
|
105
|
+
Then settle the four bucket→status names against that list:
|
|
106
|
+
|
|
107
|
+
- `backlog` → `To Do` · `in-progress` → `In Progress` · `complete` → `Done` by
|
|
108
|
+
default, and `cancelled` → `Done` too, because default Jira workflows carry
|
|
109
|
+
no Cancelled status.
|
|
110
|
+
- **Validate every non-default answer against the `states` output** before
|
|
111
|
+
writing. A status moves by **workflow transition**: a name the project lacks
|
|
112
|
+
can never be reached, and the engine refuses loudly at push time rather than
|
|
113
|
+
path-finding — catching a renamed `Done` here is the whole reason this step
|
|
114
|
+
exists.
|
|
115
|
+
- Where a configured or offered name is not in the list, show the real names
|
|
116
|
+
and ask which one means that bucket here — the mapping is the user's call,
|
|
117
|
+
never a guess.
|
|
118
|
+
|
|
119
|
+
Each answer that differs from the defaults becomes a `--state <bucket>=<name>`
|
|
120
|
+
flag in step 6.
|
|
121
|
+
|
|
122
|
+
## 6. Write it
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
skitterspec spec-sync init-config \
|
|
126
|
+
--site-url https://<site>.atlassian.net --project-key PROJ \
|
|
127
|
+
[--issue-type Task] [--subtask-type Subtask] \
|
|
128
|
+
[--state <bucket>=<name> …] [--force] [--json]
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The engine writes **only the keys that differ from the defaults**, so the file
|
|
132
|
+
shows this repo's choices and keeps inheriting everything else. `--force` is
|
|
133
|
+
required to replace an existing config — never pass it without the user having
|
|
134
|
+
asked for a rewrite in step 1.
|
|
135
|
+
|
|
136
|
+
**Relay the engine's report as printed.** It names the site, the project key,
|
|
137
|
+
the issue types and the state mapping it wrote — that report is the evidence
|
|
138
|
+
the setup is right, so don't paraphrase it into "done".
|
|
139
|
+
|
|
140
|
+
## 6b. Let `/spec-start` commit the snapshot with its spec
|
|
141
|
+
|
|
142
|
+
**Only when `specs/.core/env.config.json` exists** (per-spec isolation is on).
|
|
143
|
+
If it is absent, skip this — there is nothing to configure.
|
|
144
|
+
|
|
145
|
+
**Check before you write — a fresh install may already have this.** When this
|
|
146
|
+
superset's `init --isolation` wrote the `env.config.json`, both keys below are
|
|
147
|
+
seeded; this step is the **retrofit** for a project that adopted isolation
|
|
148
|
+
before installing the Jira provider, or ran `/spec-jira-setup` before adopting
|
|
149
|
+
it.
|
|
150
|
+
|
|
151
|
+
`/spec-start` commits an uncommitted spec for you, but only the paths it can
|
|
152
|
+
prove belong to that spec. Its own folder always does; this repo's per-spec
|
|
153
|
+
Jira snapshot (`sync.baseDir`, `specs/.core/jira-base/<ID>.base.json`) does
|
|
154
|
+
not, because the base engine is deliberately tracker-free and cannot know that
|
|
155
|
+
path exists. Declare it once, in `env.config.json`:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
"spec": {
|
|
159
|
+
"companionPaths": ["specs/.core/jira-base/{identifier}.base.json"]
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`{identifier}` resolves through `branch.identifierField`, so **set that too** if
|
|
164
|
+
it is still empty — `"jira_identifier"` is the field `/spec` stamps. Without
|
|
165
|
+
it the pattern expands to nothing and the snapshot is treated as another spec's
|
|
166
|
+
file: `/spec-start` then refuses the tree instead of committing it, which is the
|
|
167
|
+
safe failure but a needless one.
|
|
168
|
+
|
|
169
|
+
Leave both alone if the user has already set them.
|
|
170
|
+
|
|
171
|
+
## 7. Report and hand off
|
|
172
|
+
|
|
173
|
+
**Finish by checking, not by describing.** Run:
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
skitterspec spec-sync doctor
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
and relay its table. That is the difference between a summary of what setup
|
|
180
|
+
*meant* to do and a check of what is actually true — including the layers this
|
|
181
|
+
skill never touched (the scaffold, isolation). Every row that needs attention
|
|
182
|
+
names its own fix, so there is nothing to paraphrase.
|
|
183
|
+
|
|
184
|
+
It exits non-zero only when a layer is **broken** — configured but wrong. A
|
|
185
|
+
`missing` row is an opt-in nobody took, which is fine; report it, don't treat
|
|
186
|
+
it as a failure.
|
|
187
|
+
|
|
188
|
+
Then name the next step:
|
|
189
|
+
|
|
190
|
+
- `/spec` — write a spec; with Jira configured it creates the linked issue in
|
|
191
|
+
the configured project and stamps the key.
|
|
192
|
+
- `/spec-status` — read-only report of what would push, the safe way to prove
|
|
193
|
+
the link works.
|
|
194
|
+
- `/spec-push` — send a spec up.
|
|
195
|
+
|
|
196
|
+
Mention what setup did **not** configure, so the defaults aren't mistaken for
|
|
197
|
+
decisions: phase mapping (`mapping.phases` — subtask per phase by default) and
|
|
198
|
+
field ownership. Point at `jira.config.md` for those. Assignment sync is not
|
|
199
|
+
yet supported by the Jira provider, so there is no identity to settle here.
|
|
200
|
+
|
|
201
|
+
End with the block defined in `.claude/rules/spec-reports.md`. That file carries
|
|
202
|
+
the shape; this section carries only what is specific here.
|
|
203
|
+
|
|
204
|
+
**The `doctor` table goes above the block, verbatim.** It is a check rather than
|
|
205
|
+
a summary, and every row that needs attention names its own fix — paraphrasing
|
|
206
|
+
it into fields would lose exactly that.
|
|
207
|
+
|
|
208
|
+
**Verdicts**
|
|
209
|
+
|
|
210
|
+
- `✅` — every layer `doctor` checked is configured and working.
|
|
211
|
+
- `⚠️` — configured, with a `missing` row: an opt-in nobody took, which is fine.
|
|
212
|
+
Report it; do not treat it as a failure.
|
|
213
|
+
- `❌` — a `broken` row: configured but wrong. Relay the row and its fix.
|
|
214
|
+
- `⏸` — an existing config was reviewed and left alone, or Jira could not be
|
|
215
|
+
reached. Nothing was written.
|
|
216
|
+
|
|
217
|
+
**Fields:** `Built` · `Follow-ups` · `Next`
|
|
218
|
+
|
|
219
|
+
`Built` is the config written or reviewed, plus what was deliberately left
|
|
220
|
+
unset. **The credentials are never a field** — `doctor` already reports whether
|
|
221
|
+
they are set, masked, and the values are the user's alone.
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-list
|
|
3
|
+
description: List every spec Jira holds — key, title, status, and the local spec folder name to paste into /spec-start. Read-only, and it starts nothing. Falls back to the repo's own listing when Jira is unreachable. Opt-in — needs specs/.core/jira.config.json. Use when the user says "/spec-list", "what specs are there", "what is in the backlog", or "list specs from Jira".
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# /spec-list — every spec Jira holds
|
|
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
|
+
Read-only. It answers a question and writes nothing — no branch, no folder move,
|
|
15
|
+
no Jira write.
|
|
16
|
+
|
|
17
|
+
Why ask Jira rather than `ls specs/`? Because `/spec-start` moves a spec to
|
|
18
|
+
`specs/in-progress/` **on that spec's own branch**. On the base branch an
|
|
19
|
+
in-flight spec still reads `backlog`, and a teammate's unlanded spec is not on
|
|
20
|
+
disk at all. Jira knows what is actually in progress; the repo knows what each
|
|
21
|
+
issue is **called on disk**. The listing joins the two.
|
|
22
|
+
|
|
23
|
+
**Opt-in**: only runs when `specs/.core/jira.config.json` exists. If absent,
|
|
24
|
+
tell the user how to enable Jira sync (`/spec-jira-setup`) and stop.
|
|
25
|
+
|
|
26
|
+
## 1. Turn the question into flags
|
|
27
|
+
|
|
28
|
+
The user asks in plain language; the engine takes flags. Map, then run:
|
|
29
|
+
|
|
30
|
+
| They ask | Flags |
|
|
31
|
+
|----------|-------|
|
|
32
|
+
| "what specs are there", "/spec-list" | *(none — the live default)* |
|
|
33
|
+
| "what's done", "everything" | `--all` |
|
|
34
|
+
| "what's cancelled", a named status | `--state "<name>"` (repeatable) |
|
|
35
|
+
|
|
36
|
+
The default scope is **live** — whatever `config.states` maps `backlog` and
|
|
37
|
+
`in-progress` to. It is deliberately not everything: in a project with any
|
|
38
|
+
history, Done dwarfs the rows anyone wanted.
|
|
39
|
+
|
|
40
|
+
`--state` and `--all` are **alternatives**, and the engine refuses the pair
|
|
41
|
+
rather than letting one win silently.
|
|
42
|
+
|
|
43
|
+
The Linear provider's `--mine`, `--by` and `--next` filters are
|
|
44
|
+
**not yet shipped for the Jira provider** — assignee filtering and backlog
|
|
45
|
+
ordering wait on identity support. Say so when one is asked for, rather than approximating it.
|
|
46
|
+
|
|
47
|
+
## 2. Run the engine
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
skitterspec spec-sync list [--state <name> …|--all] [--json]
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- **`transport = api`** (credentials resolve) → it queried Jira and printed the
|
|
54
|
+
listing. **Relay its output verbatim** and stop. Do not re-format it and do not
|
|
55
|
+
make Jira calls of your own — the engine already joined the local spec
|
|
56
|
+
folders on.
|
|
57
|
+
- **`transport = mcp`** → the engine made no call. Go to step 3.
|
|
58
|
+
- Anything else it prints on one `spec-sync list:` line is a **degradation**, not
|
|
59
|
+
a crash — go to step 4.
|
|
60
|
+
|
|
61
|
+
## 3. The MCP path
|
|
62
|
+
|
|
63
|
+
Only when the engine said `transport = mcp`. Discover the issue **search** tool
|
|
64
|
+
at runtime the way `/spec-push` describes (`searchJiraIssuesUsingJql`). If Jira
|
|
65
|
+
isn't connected or the tool is missing, go to step 4 — do not stop with nothing.
|
|
66
|
+
|
|
67
|
+
Then build one JQL query per run:
|
|
68
|
+
|
|
69
|
+
- **Scope by status.** The live default is
|
|
70
|
+
`project = <jira.projectKey> AND status IN ("<backlog>", "<in-progress>")`
|
|
71
|
+
with the names from `config.states`; `--state` substitutes the named
|
|
72
|
+
status(es); `--all` drops the status clause entirely.
|
|
73
|
+
- **Filter out phase subtasks in the query** — add
|
|
74
|
+
`AND issuetype NOT IN subtaskIssueTypes()`. A spec is a standard issue; a
|
|
75
|
+
phase is a subtask, and a listing that includes them buries the specs.
|
|
76
|
+
- **Ask for the fields you print** — `summary` and `status`; the key rides on
|
|
77
|
+
every result, and the browse url is `<siteUrl>/browse/<key>`.
|
|
78
|
+
- **Page, and never cap silently.** Follow the tool's pagination until it runs
|
|
79
|
+
out. If you stop early, say so on its own line and say what you stopped at.
|
|
80
|
+
|
|
81
|
+
**The current phase, on in-progress rows only.** For each row whose status is
|
|
82
|
+
the in-progress one, search again with `parent = <key>` and the same fields.
|
|
83
|
+
Order the children by **key**, numerically — subtasks are minted in phase
|
|
84
|
+
order, so the key carries it. Print the live one as `2/5 — <title>`. Three
|
|
85
|
+
shapes, none of them guessed at:
|
|
86
|
+
|
|
87
|
+
- **No child in progress** — print nothing extra. A spec sits between phases all
|
|
88
|
+
the time; that is not a missing phase.
|
|
89
|
+
- **More than one** — print the lowest-numbered, then append
|
|
90
|
+
`(+N more in progress)`. Two people on one spec is real, not an error.
|
|
91
|
+
- **`mapping.phases` is `inline` for this spec's bucket** — skip the call
|
|
92
|
+
entirely. Those phases live in the spec issue's own description, so there are
|
|
93
|
+
no subtasks, and asking would report "no phase in progress" for a spec that is
|
|
94
|
+
mid-build.
|
|
95
|
+
|
|
96
|
+
Do **not** make this call for backlog, done or cancelled rows — one lookup per
|
|
97
|
+
in-progress row is the budget, and there are rarely many.
|
|
98
|
+
|
|
99
|
+
Then join locally — no second Jira call:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
skitterspec spec-sync linked --json
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
That is `[{ spec, bucket, identifier }]`. Key it by `identifier` and attach each
|
|
106
|
+
issue's local `spec` folder name. Format the rows exactly as the API path does
|
|
107
|
+
(step 5), including the `showing N of M` count.
|
|
108
|
+
|
|
109
|
+
## 4. Degrade — never leave them with nothing
|
|
110
|
+
|
|
111
|
+
Jira unreachable, no credential, no MCP tool, a Jira error: **do not stop**.
|
|
112
|
+
Print the local listing instead:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
skitterspec spec-sync linked --json
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Show `spec`, `bucket` and `identifier`, under a one-line banner naming what is
|
|
119
|
+
missing and why it may be wrong:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
Jira unreachable (<reason>) — this is the repo's own listing.
|
|
123
|
+
Buckets are this branch's; a spec someone else has started still reads "backlog" here.
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
That caveat is the point of the banner. A local bucket is not evidence of a
|
|
127
|
+
spec's real state — it is evidence of what this branch knows, which is exactly
|
|
128
|
+
what the command exists to go beyond. A query command that fails closed is one
|
|
129
|
+
people stop typing.
|
|
130
|
+
|
|
131
|
+
## 5. Report
|
|
132
|
+
|
|
133
|
+
Relay the listing. Whatever the path, three things must survive into what the
|
|
134
|
+
user reads:
|
|
135
|
+
|
|
136
|
+
- **The count, as `showing N of M`.** If they are not the same number, say what
|
|
137
|
+
was left out and how to see it.
|
|
138
|
+
- **The phase, on in-progress rows** — `2/5 — <title>`, after the status.
|
|
139
|
+
- **A row with no local match stays in**, marked `— (not linked here)`. It is not
|
|
140
|
+
noise: a teammate's unlanded spec, or one authored inside another spec's
|
|
141
|
+
worktree, is precisely what the repo could not have told them.
|
|
142
|
+
|
|
143
|
+
Finish with the hand-off, because every row carries the folder name for it —
|
|
144
|
+
as a sentence, not a fenced block: say that `/spec-start <name>` starts any of
|
|
145
|
+
them, with the name copied from a row.
|
|
146
|
+
|
|
147
|
+
**Never start it yourself.** `/spec-start` provisions a branch, moves a folder
|
|
148
|
+
and commits, and it has dirty-tree refusals this skill does not reproduce.
|
|
149
|
+
Offering the name is the whole job.
|
|
150
|
+
|
|
151
|
+
End with the block defined in `.claude/rules/spec-reports.md`. That file carries
|
|
152
|
+
the shape; this section carries only what is specific here.
|
|
153
|
+
|
|
154
|
+
**The listing goes above the block, unflattened.** It is rows of other people's
|
|
155
|
+
work; the block is the verdict on this run of the query. Do not fold the listing
|
|
156
|
+
into fields, and do not repeat it there.
|
|
157
|
+
|
|
158
|
+
**Verdicts**
|
|
159
|
+
|
|
160
|
+
- `✅` — the listing is Jira's, joined to the local folder names.
|
|
161
|
+
- `⚠️` — listed, with a caveat that changes how the rows read: a paging cap you
|
|
162
|
+
stopped at, or the local fallback listing under its banner.
|
|
163
|
+
- `⏸` — refused before acting: no config, so there is nothing to list against.
|
|
164
|
+
- `❌` — the query was wrong: `--state` and `--all` together, or a status name
|
|
165
|
+
Jira rejects.
|
|
166
|
+
|
|
167
|
+
**Fields:** `Follow-ups` · `Next`
|
|
168
|
+
|
|
169
|
+
**No `Tracker` row.** This skill names many specs and owns none, so an id row
|
|
170
|
+
would have to pick one. The counts — `showing N of M` — belong to the listing
|
|
171
|
+
above, where the engine already prints them.
|
|
172
|
+
|
|
173
|
+
`Next` is the hand-off: `/spec-start <name>`, with a name copied from a row.
|