@benjaminthomas/spec-driven-dev 1.13.0 → 1.14.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/README.md +26 -6
- package/bin/cli.mjs +60 -12
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/skills/spec-investigate/SKILL.md +3 -1
package/README.md
CHANGED
|
@@ -75,7 +75,8 @@ and you can change any answer as you go. It asks how the project is organised (o
|
|
|
75
75
|
or several repos that change together), your tracker, branches and commit style, where specs live
|
|
76
76
|
and whether your team shares them, then looks through the code and saves the project memory
|
|
77
77
|
([details below](#project-setup-your-teams-rules)). If Claude Code or Codex is installed, the
|
|
78
|
-
installer
|
|
78
|
+
installer asks "Open Claude Code in soreto-shopify to set up your project?" (with your folder's name)
|
|
79
|
+
and opens it with "run spec-setup" already typed in.
|
|
79
80
|
|
|
80
81
|
**3. Then run each stage in order.** You can type the slash command or just say the
|
|
81
82
|
words in quotes.
|
|
@@ -272,8 +273,9 @@ a build output. Committing it would cause merge conflicts between branches. `doc
|
|
|
272
273
|
it's committed.
|
|
273
274
|
|
|
274
275
|
When `risk.enabled` is on, the skills use it:
|
|
275
|
-
- `spec-investigate`
|
|
276
|
-
dependents) and lists them as **Risk Hotspots
|
|
276
|
+
- `spec-investigate` always looks up the files in the change surface, digs into high and critical
|
|
277
|
+
ones (past fix commits, dependents), and lists them as **Risk Hotspots**, or says it checked and
|
|
278
|
+
found none;
|
|
277
279
|
- `spec-create` raises those tasks one tier and requires a test aimed at each file's past failure
|
|
278
280
|
pattern;
|
|
279
281
|
- `spec-implement`'s reviewer and `spec-review` check those tests and read the risky files line
|
|
@@ -644,6 +646,7 @@ spec-driven-dev doctor # check .spec-driven.yml again
|
|
|
644
646
|
spec-driven-dev status # list unfinished specs and each one's next step
|
|
645
647
|
spec-driven-dev context --areas=billing # print the project memory (index, or chosen areas)
|
|
646
648
|
spec-driven-dev settings # switch GitRisk, run-through and sharing from a menu
|
|
649
|
+
spec-driven-dev uninstall # remove the skills, plugin and cache (--all: settings too)
|
|
647
650
|
spec-driven-dev risk # GitRisk: score files from git history → specs/context/risk.md
|
|
648
651
|
spec-driven-dev risk-eval --tickets=tickets.md # compare agent behaviour with the risk signal on vs off
|
|
649
652
|
# (--runs=3 --arms=on --timeout=20 --model=sonnet)
|
|
@@ -717,6 +720,23 @@ Each skill becomes a tool that returns its instructions, and supporting files ar
|
|
|
717
720
|
|
|
718
721
|
---
|
|
719
722
|
|
|
723
|
+
### Uninstall
|
|
724
|
+
|
|
725
|
+
```bash
|
|
726
|
+
npx @benjaminthomas/spec-driven-dev@latest uninstall
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
It lists everything an install put on your machine (the skills in each AI tool, the Claude Code
|
|
730
|
+
plugin, the npx download cache), then removes it after one confirmation. Your other skills stay.
|
|
731
|
+
|
|
732
|
+
- **Kept by default:** your `.spec-driven.yml` settings file. Add `--all` to remove it and the
|
|
733
|
+
workspace registry (`~/.spec-driven/`) too.
|
|
734
|
+
- **Never touched:** specs, `CONTEXT.md`, `team-repos.yml` and your code. They're your team's work.
|
|
735
|
+
Delete them yourself if you want them gone.
|
|
736
|
+
- **In scripts or with `!` in Claude Code:** add `--yes`, since there's no terminal to confirm in.
|
|
737
|
+
- **Plugin installs:** `/plugin uninstall ticket-to-pr@spec-driven-dev` in Claude Code, if the
|
|
738
|
+
command can't do it for you.
|
|
739
|
+
|
|
720
740
|
## Compatibility
|
|
721
741
|
|
|
722
742
|
| Skill | Claude Code | Codex CLI | Cursor | Antigravity | Notes |
|
|
@@ -741,7 +761,7 @@ skips that step rather than failing.
|
|
|
741
761
|
| Skill | Stage | SKILL.md lines | Words | Supporting files |
|
|
742
762
|
|---|---|---:|---:|---:|
|
|
743
763
|
| `spec-setup` | 0 · configure | 210 | 2,201 | 3 |
|
|
744
|
-
| `spec-investigate` | 1 · understand |
|
|
764
|
+
| `spec-investigate` | 1 · understand | 387 | 3,367 | 1 |
|
|
745
765
|
| `spec-create` | 2 · plan | 198 | 1,782 | 6 |
|
|
746
766
|
| `spec-implement` | 3 · build | 327 | 2,753 | 3 |
|
|
747
767
|
| `spec-verify` | 4 · prove | 163 | 1,557 | 1 |
|
|
@@ -749,7 +769,7 @@ skips that step rather than failing.
|
|
|
749
769
|
| `spec-checkpoint` | 6 · commit | 140 | 1,144 | 0 |
|
|
750
770
|
| `spec-ship` | 7 · PR | 230 | 1,388 | 0 |
|
|
751
771
|
| `generative-seo` | standalone | 255 | 2,209 | 7 |
|
|
752
|
-
| **Total** | | **2,
|
|
772
|
+
| **Total** | | **2,047** | **17,695** | **22** |
|
|
753
773
|
|
|
754
774
|
- **8** skills: **1** setup + **6** workflow stages + **1** standalone
|
|
755
775
|
- **4** tools supported natively (Claude Code, Codex CLI, Cursor, Antigravity), plus an MCP fallback
|
|
@@ -802,7 +822,7 @@ plugin/evals/ `claude plugin eval` cases
|
|
|
802
822
|
1. Increase `version` in both `package.json` and `plugin/.claude-plugin/plugin.json` (the check fails if
|
|
803
823
|
they differ).
|
|
804
824
|
2. Add a `CHANGELOG.md` entry, then commit and push.
|
|
805
|
-
3. Tag the release and push the tag: `git tag v1.
|
|
825
|
+
3. Tag the release and push the tag: `git tag v1.14.0 && git push origin v1.14.0`.
|
|
806
826
|
4. Watch the **publish** run in the repo's Actions tab. When it's green, the new version is on
|
|
807
827
|
npm. Claude Code plugin users get it from the marketplace once the commit is on `main`.
|
|
808
828
|
|
package/bin/cli.mjs
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
//
|
|
5
5
|
// spec-driven-dev install the skills, then hand over to your AI tool ("run spec-setup")
|
|
6
6
|
// spec-driven-dev setup scripted setup for CI: needs --yes or answer flags (people: say "run spec-setup")
|
|
7
|
+
// spec-driven-dev uninstall remove the skills (all tools), the Claude Code plugin and the download cache; --all also removes the settings file
|
|
7
8
|
// spec-driven-dev doctor check .spec-driven.yml against the real repos (exit 1 on problems)
|
|
8
9
|
// spec-driven-dev status list specs with unfinished work and each one's "Resume here" next step
|
|
9
10
|
// spec-driven-dev context print specs/CONTEXT.md; --areas=billing,api prints only those area files
|
|
@@ -39,7 +40,7 @@ const args = process.argv.slice(2);
|
|
|
39
40
|
const flag = (n) => args.includes(`--${n}`);
|
|
40
41
|
const opt = (n) => args.find((a) => a.startsWith(`--${n}=`))?.split("=")[1];
|
|
41
42
|
const command = args.find((a) => !a.startsWith("-")) || "install";
|
|
42
|
-
const YES = flag("yes") || flag("y") || !process.stdin.isTTY || ["doctor", "status", "context", "risk", "risk-eval", "setup"].includes(command);
|
|
43
|
+
const YES = flag("yes") || flag("y") || !process.stdin.isTTY || ["doctor", "status", "context", "risk", "risk-eval", "setup"].includes(command) || (command === "uninstall" && flag("yes"));
|
|
43
44
|
const DIR = path.resolve(opt("dir") || process.cwd());
|
|
44
45
|
|
|
45
46
|
// Colour only for a person at a terminal; pipes, CI and NO_COLOR get plain text (and the tests stay plain).
|
|
@@ -167,17 +168,24 @@ async function install() {
|
|
|
167
168
|
// happen in the AI tool. Claude Code and Codex can be opened with the request already typed in.
|
|
168
169
|
const LAUNCHERS = [["claude", "Claude Code"], ["codex", "Codex"]];
|
|
169
170
|
async function handOver(tools, onlySetup) {
|
|
171
|
+
// The folder says where the AI tool opens; "project" says what gets set up (it can span several repos).
|
|
170
172
|
const name = path.basename(gitTop(DIR));
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
(
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
173
|
+
const what = "It first asks how your project is organised: one repo, a monorepo, or several repos that change together.";
|
|
174
|
+
const next = `Next: in ${name}, open your AI tool and say "run spec-setup".\n${what}
|
|
175
|
+
Then it asks about your tracker, branches and sharing, and looks through the code.
|
|
176
|
+
Start a new session if your tool doesn't recognise it yet.`;
|
|
177
|
+
step(onlySetup ? 1 : 2, "Set up your project in your AI tool", ink.magenta);
|
|
178
|
+
if (onlySetup) {
|
|
179
|
+
console.log(`Setup happens in your AI tool now, so it can read the code and you can change any answer as you go.\n${next}\nFor scripts and CI: spec-driven-dev setup --yes [--layout=… --repos=… --share=…]`);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const launcher = LAUNCHERS.find(([bin]) => tools.includes(bin) && onPath(bin));
|
|
183
|
+
if (!launcher || !process.stdin.isTTY || YES) { console.log(`Skills installed.\n${next}`); return; }
|
|
184
|
+
// The question carries the explanation, so there's no paragraph to read twice.
|
|
185
|
+
if (!(await askConfirm(`Open ${launcher[1]} in ${name} to set up your project? ${what} (A few minutes, on your ${launcher[1]} plan.)`, true))) {
|
|
186
|
+
console.log(next);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
181
189
|
const { spawnSync } = await import("node:child_process");
|
|
182
190
|
spawnSync(launcher[0], ["run spec-setup"], { cwd: DIR, stdio: "inherit" });
|
|
183
191
|
}
|
|
@@ -886,6 +894,45 @@ async function settings() {
|
|
|
886
894
|
}
|
|
887
895
|
}
|
|
888
896
|
|
|
897
|
+
// Finds everything an install put on this machine and removes it after one confirmation.
|
|
898
|
+
// Specs, CONTEXT.md and code are never touched: they're the team's work, not part of the install.
|
|
899
|
+
async function uninstall() {
|
|
900
|
+
const found = [];
|
|
901
|
+
const ours = (d) => ALL_SKILLS.map((s) => path.join(d, s)).filter((f) => fs.existsSync(path.join(f, "SKILL.md")));
|
|
902
|
+
const dirs = [...new Set(Object.values(TOOLS).flatMap((t) => [path.join(HOME, t.global), path.join(DIR, t.project)]))];
|
|
903
|
+
for (const d of dirs) { const f = ours(d); if (f.length) found.push({ what: `${f.length} skills in ${d}`, paths: f }); }
|
|
904
|
+
const plugins = readJson(path.join(HOME, ".claude/plugins/installed_plugins.json"));
|
|
905
|
+
const pluginIds = Object.keys(plugins?.plugins || plugins || {}).filter((k) => /^(ticket-to-pr|spec-driven-dev)@/.test(k));
|
|
906
|
+
for (const id of pluginIds) found.push({ what: `Claude Code plugin ${id}`, plugin: id });
|
|
907
|
+
const npx = path.join(HOME, ".npm", "_npx");
|
|
908
|
+
for (const c of subdirs(npx)) if (fs.existsSync(path.join(npx, c, "node_modules", "@benjaminthomas", "spec-driven-dev")) && process.platform !== "win32")
|
|
909
|
+
found.push({ what: `npx download cache ${path.join(npx, c)}`, paths: [path.join(npx, c)] });
|
|
910
|
+
const config = findConfig(DIR);
|
|
911
|
+
const reg = readRegistry();
|
|
912
|
+
if (flag("all")) {
|
|
913
|
+
if (config) found.push({ what: `settings file ${config}`, paths: [config], config });
|
|
914
|
+
if (fs.existsSync(path.join(HOME, ".spec-driven"))) found.push({ what: `workspace registry ${path.join(HOME, ".spec-driven")}`, paths: [path.join(HOME, ".spec-driven")] });
|
|
915
|
+
}
|
|
916
|
+
step(1, "Uninstall spec-driven-dev", ink.red);
|
|
917
|
+
if (!found.length) { console.log("✓ Nothing to remove: no skills, plugin or cache from spec-driven-dev were found."); return; }
|
|
918
|
+
console.log("Found:\n" + found.map((f) => ` • ${f.what}`).join("\n"));
|
|
919
|
+
if (!flag("all") && (config || Object.keys(reg).length)) console.log(` Kept: your settings file${config ? ` (${config})` : ""}. Add --all to remove it too.`);
|
|
920
|
+
console.log(" Never touched: specs, CONTEXT.md and your code.");
|
|
921
|
+
if (!process.stdin.isTTY && !flag("yes")) { console.log("Nothing removed. To remove the above, run: spec-driven-dev uninstall --yes"); return; }
|
|
922
|
+
if (!flag("yes") && !(await askConfirm("Remove everything listed above?", false))) { console.log("Nothing removed."); return; }
|
|
923
|
+
for (const f of found) {
|
|
924
|
+
if (f.plugin) {
|
|
925
|
+
let ok = false;
|
|
926
|
+
if (onPath("claude")) try { execFileSync("claude", ["plugin", "uninstall", f.plugin], { stdio: "ignore" }); ok = true; } catch {}
|
|
927
|
+
console.log(ok ? `✓ Removed ${f.what}` : `• Remove the plugin in Claude Code: /plugin uninstall ${f.plugin}`);
|
|
928
|
+
continue;
|
|
929
|
+
}
|
|
930
|
+
for (const p of f.paths) fs.rmSync(p, { recursive: true, force: true });
|
|
931
|
+
console.log(`✓ Removed ${f.what}`);
|
|
932
|
+
}
|
|
933
|
+
console.log("Done. Reinstall any time with: npx @benjaminthomas/spec-driven-dev@latest");
|
|
934
|
+
}
|
|
935
|
+
|
|
889
936
|
// Silent unless something is unfinished, so it's cheap to run at the start of a session.
|
|
890
937
|
function status() {
|
|
891
938
|
const file = findConfig(DIR);
|
|
@@ -916,6 +963,7 @@ try {
|
|
|
916
963
|
else if (command === "context") context();
|
|
917
964
|
else if (command === "risk") risk();
|
|
918
965
|
else if (command === "settings") await settings();
|
|
966
|
+
else if (command === "uninstall") await uninstall();
|
|
919
967
|
else if (command === "risk-eval") await riskEvalCmd();
|
|
920
968
|
else if (command === "install") {
|
|
921
969
|
if (HANDOFF) console.log("No interactive terminal (for example a \"!\" command in Claude Code), so the skills go to the AI tools it finds, for this project.\n");
|
|
@@ -923,7 +971,7 @@ try {
|
|
|
923
971
|
if (tools.length && !flag("no-setup")) await handOver(tools);
|
|
924
972
|
} else if (SETUP_IN_AGENT) handOver([], true);
|
|
925
973
|
else if (command === "setup") await setup();
|
|
926
|
-
else throw new Error(`Unknown command "${command}" — use install (default), setup, settings, doctor, status, context, risk, or risk-eval`);
|
|
974
|
+
else throw new Error(`Unknown command "${command}" — use install (default), setup, settings, uninstall, doctor, status, context, risk, or risk-eval`);
|
|
927
975
|
if (command === "setup" && !SETUP_IN_AGENT) console.log('\nNext: in your AI tool, say "investigate <ticket>" or "create a spec".');
|
|
928
976
|
} catch (e) {
|
|
929
977
|
console.error(`✗ ${e.message}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@benjaminthomas/spec-driven-dev",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"description": "Spec-driven AI development workflow (investigate → spec → implement → verify → review → ship) as Agent Skills for Claude Code, Cursor, Codex CLI and Antigravity.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ticket-to-pr",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"description": "Parallel-batch spec-driven feature workflow (spec-setup, spec-investigate, spec-create, spec-implement, spec-verify, spec-review, spec-checkpoint, spec-ship) plus a portable SEO/GEO operations skill (generative-seo) for any codebase.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Benjamin Thomas",
|
|
@@ -84,12 +84,14 @@ Use it only when `.spec-driven.yml` has `risk.enabled: on`, or has no `risk:` bl
|
|
|
84
84
|
file, compute scores, or mention risk. That keeps on/off comparisons (`spec-driven-dev risk-eval`)
|
|
85
85
|
clean.
|
|
86
86
|
|
|
87
|
-
1.
|
|
87
|
+
1. **Required, not optional:** once you know the change surface, and before writing the report, look up its files: `spec-driven-dev risk --files=a,b` (or
|
|
88
88
|
`npx -y @benjaminthomas/spec-driven-dev risk --files=…`), or find them in `risk.md`. Without the
|
|
89
89
|
CLI, approximate a file's history with `git log --since="2 years ago" --format=%s -- <file>`.
|
|
90
90
|
2. For each **high** or **critical** file in the surface, look harder: read its last ~10 commit
|
|
91
91
|
subjects and the diffs of its last 1–2 fix commits, and check its dependents. Write what keeps
|
|
92
92
|
breaking there in the report's **Risk Hotspots** section.
|
|
93
|
+
The report's **Risk Hotspots** section must exist when risk is on: list the high/critical files,
|
|
94
|
+
or write "none of the touched files are high or critical (checked)" so a reader knows it was done.
|
|
93
95
|
3. A score is a reason to look harder, never evidence. Hotspot findings still need their
|
|
94
96
|
VERIFIED / INFERRED labels.
|
|
95
97
|
4. **New files** (added in the last 90 days with fewer than 3 commits, or not committed yet) show as tier `new`: too little
|