@mlmcps/ml-specs 1.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/.claude-plugin/marketplace.json +15 -0
- package/LICENSE +21 -0
- package/README.md +106 -0
- package/ml-specs/.claude-plugin/plugin.json +11 -0
- package/ml-specs/.mcp.json +17 -0
- package/ml-specs/CHANGELOG.md +860 -0
- package/ml-specs/LICENSE +21 -0
- package/ml-specs/README.md +347 -0
- package/ml-specs/agents/coder.md +76 -0
- package/ml-specs/agents/developer.md +78 -0
- package/ml-specs/agents/pr-author.md +36 -0
- package/ml-specs/agents/reviewer.md +65 -0
- package/ml-specs/agents/scanner.md +66 -0
- package/ml-specs/agents/spec-author.md +91 -0
- package/ml-specs/agents/spec-reviewer.md +59 -0
- package/ml-specs/commands/code.md +29 -0
- package/ml-specs/commands/fix.md +67 -0
- package/ml-specs/commands/nfr.md +114 -0
- package/ml-specs/commands/pr.md +32 -0
- package/ml-specs/commands/repo-adopt.md +86 -0
- package/ml-specs/commands/repo-doctor.md +57 -0
- package/ml-specs/commands/repo-estate.md +79 -0
- package/ml-specs/commands/repo-impact.md +77 -0
- package/ml-specs/commands/repo-init.md +155 -0
- package/ml-specs/commands/repo-refresh.md +58 -0
- package/ml-specs/commands/repo-rollout.md +84 -0
- package/ml-specs/commands/repo-status.md +59 -0
- package/ml-specs/commands/spec-advance.md +81 -0
- package/ml-specs/commands/spec-build.md +66 -0
- package/ml-specs/commands/spec-fanout.md +64 -0
- package/ml-specs/commands/spec-review.md +24 -0
- package/ml-specs/commands/spec-verify.md +55 -0
- package/ml-specs/commands/spec.md +73 -0
- package/ml-specs/hooks/hooks.json +23 -0
- package/ml-specs/hooks/knowledge-drift.sh +43 -0
- package/ml-specs/hooks/secret-scan.sh +56 -0
- package/ml-specs/mcp/README.md +173 -0
- package/ml-specs/mcp/ml-specs-server.mjs +708 -0
- package/ml-specs/mcp/ml-specs-server.test.mjs +225 -0
- package/ml-specs/package.json +44 -0
- package/ml-specs/scripts/branch-policy.mjs +71 -0
- package/ml-specs/scripts/fix-specs.mjs +289 -0
- package/ml-specs/scripts/lib/cli.mjs +43 -0
- package/ml-specs/scripts/lib/estate.mjs +108 -0
- package/ml-specs/scripts/lib/http.mjs +73 -0
- package/ml-specs/scripts/lib/knowledge.mjs +91 -0
- package/ml-specs/scripts/lib/knowledge.test.mjs +70 -0
- package/ml-specs/scripts/lib/nfr.mjs +119 -0
- package/ml-specs/scripts/lib/nfr.test.mjs +89 -0
- package/ml-specs/scripts/lib/policy.mjs +114 -0
- package/ml-specs/scripts/lib/policy.test.mjs +139 -0
- package/ml-specs/scripts/lib/scm.mjs +189 -0
- package/ml-specs/scripts/lib/scm.test.mjs +155 -0
- package/ml-specs/scripts/lib/specs.mjs +192 -0
- package/ml-specs/scripts/lib/specs.test.mjs +69 -0
- package/ml-specs/scripts/lib/trace.mjs +90 -0
- package/ml-specs/scripts/lib/trace.test.mjs +110 -0
- package/ml-specs/scripts/lib/tracker.mjs +257 -0
- package/ml-specs/scripts/lib/tracker.test.mjs +177 -0
- package/ml-specs/scripts/nfr-compile.mjs +120 -0
- package/ml-specs/scripts/scripts.test.mjs +182 -0
- package/ml-specs/scripts/spec-brief.mjs +127 -0
- package/ml-specs/scripts/spec-dashboard.mjs +331 -0
- package/ml-specs/scripts/spec-fanout.mjs +120 -0
- package/ml-specs/scripts/spec-gate.mjs +329 -0
- package/ml-specs/scripts/spec-trace.mjs +91 -0
- package/ml-specs/scripts/survey-estate.mjs +230 -0
- package/ml-specs/scripts/tracker-sync.mjs +91 -0
- package/ml-specs/skills/knowledge-retrieval/SKILL.md +75 -0
- package/ml-specs/templates/CLAUDE.fragment.md +87 -0
- package/ml-specs/templates/ci/azure-pipelines-spec-gate.yml +64 -0
- package/ml-specs/templates/ci/knowledge-check.mjs +176 -0
- package/ml-specs/templates/ci/knowledge-layer.yml +35 -0
- package/ml-specs/templates/ci/spec-gate.yml +69 -0
- package/ml-specs/templates/docs/ARCHITECTURE.template.md +110 -0
- package/ml-specs/templates/docs/ESTATE.template.md +55 -0
- package/ml-specs/templates/docs/PATTERNS.template.md +80 -0
- package/ml-specs/templates/gitattributes +18 -0
- package/ml-specs/templates/hooks/settings.hooks.example.json +32 -0
- package/ml-specs/templates/mcp/.mcp.json +34 -0
- package/ml-specs/templates/settings.json +18 -0
- package/ml-specs/templates/specs/AGENTS.md +57 -0
- package/ml-specs/templates/specs/README.md +104 -0
- package/ml-specs/templates/specs/TEMPLATE.md +114 -0
- package/ml-specs/templates/standards/.mlskills.json +24 -0
- package/package.json +36 -0
|
@@ -0,0 +1,860 @@
|
|
|
1
|
+
# Changelog — ml-specs
|
|
2
|
+
|
|
3
|
+
All notable changes to this plugin. Bump `version` in `.claude-plugin/plugin.json`, `package.json`,
|
|
4
|
+
**and** the `ml-specs` entry in `../.claude-plugin/marketplace.json` together on each release —
|
|
5
|
+
`release.yml` checks all three against the tag and refuses to publish if any disagrees.
|
|
6
|
+
|
|
7
|
+
Entries before 1.0.0 refer to this plugin under its former name, `sdd-toolkit`.
|
|
8
|
+
|
|
9
|
+
## [1.0.0]
|
|
10
|
+
|
|
11
|
+
**Breaking.** The plugin is renamed and eight commands change name with it. Existing installs will
|
|
12
|
+
not upgrade in place — see *Migrating* at the end of this entry.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- **`sdd-toolkit` is now `ml-specs`, in the `ml-tools` marketplace.** "SDD" named a methodology,
|
|
17
|
+
not a product, and it meant nothing to anyone who had not already met the acronym. The plugin now
|
|
18
|
+
sits under the same house prefix as its sibling: `ml-skills` says what good looks like here,
|
|
19
|
+
`ml-specs` is the loop that proves you met it. Marketplace owner, npm package
|
|
20
|
+
(`@mlmcps/ml-specs`), mirror repo and release tag prefix (`ml-specs-v*`) move with it.
|
|
21
|
+
|
|
22
|
+
- **The eight knowledge-layer commands are now `/repo-*`.** `/sdd-init`, `/sdd-refresh`,
|
|
23
|
+
`/sdd-doctor`, `/sdd-adopt`, `/sdd-estate`, `/sdd-impact`, `/sdd-rollout` and `/sdd-status`
|
|
24
|
+
become `/repo-init`, `/repo-refresh`, and so on. None of them was ever about specs — they learn,
|
|
25
|
+
refresh and audit the repo's knowledge layer, and the `sdd-` prefix said only which plugin they
|
|
26
|
+
came from, which the client already namespaces. The surface now splits along what it does:
|
|
27
|
+
**`/spec-*` is the loop, `/repo-*` is the knowledge layer.** The loop commands are unchanged.
|
|
28
|
+
|
|
29
|
+
- **Agents lose their `sdd-` prefix**: `sdd-developer` → `developer`, `sdd-reviewer` → `reviewer`,
|
|
30
|
+
`sdd-scanner` → `scanner`, `sdd-spec-author` → `spec-author`, `sdd-spec-reviewer` →
|
|
31
|
+
`spec-reviewer`. `coder` and `pr-author` already had no prefix; the two conventions were an
|
|
32
|
+
accident of history.
|
|
33
|
+
|
|
34
|
+
- **MCP server renamed** to `ml-specs`, its file to `mcp/ml-specs-server.mjs`, and its resource
|
|
35
|
+
scheme from `sdd://` to `mlspec://`. Tools now arrive as `mcp__ml-specs__*`.
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- **The architecture standards are wired into the loop at four points**, replacing prose that told
|
|
40
|
+
each agent to work the routing out for itself. Where a command previously said *"call
|
|
41
|
+
`skill_list`, then `skill_get` for the ones that apply — `openapi-contract` if §4.1 describes
|
|
42
|
+
HTTP, `entity-relationships` if §4.2 changes a schema"*, it now calls one tool that knows that
|
|
43
|
+
mapping:
|
|
44
|
+
|
|
45
|
+
| Phase | Tool | What it replaced |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| `/spec` | `spec_standards` | hand-picking standards per §4.x |
|
|
48
|
+
| `/spec`, `/spec-review` | `spec_precheck` | nothing — there was no pre-code check |
|
|
49
|
+
| `/spec-verify`, `/spec-advance` | `verify_evidence` | interpreting `check_repo` by hand |
|
|
50
|
+
| `/nfr` | `gate_manifest` | drafting a rule and hoping it fires |
|
|
51
|
+
|
|
52
|
+
`spec_precheck` is the one with no predecessor. It runs the real checkers over the fenced blocks
|
|
53
|
+
in a **draft spec** and reports findings at the spec's own line numbers, so a versioning, money-
|
|
54
|
+
type or idempotency mistake is caught while it still costs one edit. Sections with no fenced
|
|
55
|
+
contract are reported as **not checked** rather than folded into a clean result.
|
|
56
|
+
|
|
57
|
+
- **`verify_evidence` gives the `Verified` gate four verdicts, not two.** `/spec-advance` already
|
|
58
|
+
said in prose that "`Verified` against a gate nothing could fail is a weaker claim than it
|
|
59
|
+
looks"; that judgement is now a field. `inconclusive` — clean, but no standard in scope was
|
|
60
|
+
ratified, so nothing *could* have failed — is reported as the absence of evidence rather than
|
|
61
|
+
rounded up to a pass. Only `pass` clears the gate on its own.
|
|
62
|
+
|
|
63
|
+
- **Five deterministic scripts are exposed as MCP tools** — `spec_gate`, `spec_trace`,
|
|
64
|
+
`spec_brief`, `nfr_check`, `estate_survey`. `scripts/` holds the half of the toolkit that must
|
|
65
|
+
not be a model call, and until now only Claude Code could reach it, which left the most
|
|
66
|
+
load-bearing check in the toolkit — *does this spec have the evidence for `Verified`?* —
|
|
67
|
+
unavailable to CI, to Cursor, and to any other agent. They are invoked as subprocesses rather
|
|
68
|
+
than imported, so they run the same execution path a human gets, and the write-capable flags
|
|
69
|
+
are never passed.
|
|
70
|
+
|
|
71
|
+
- **The developer agent can reach a third-party skill catalog** via `skill_search` / `skill_fetch`
|
|
72
|
+
for the things the eleven standards do not cover — a payment provider, a niche integration.
|
|
73
|
+
Those results are reference material with no authority: where one contradicts a standard, the
|
|
74
|
+
standard wins.
|
|
75
|
+
|
|
76
|
+
### Fixed
|
|
77
|
+
|
|
78
|
+
- **`/spec-fanout` gave a false all-clear when the estate index was missing.** A repo with no
|
|
79
|
+
`docs/ESTATE.md` reported no affected consumers, which is indistinguishable from "there are
|
|
80
|
+
none" and is the more dangerous of the two answers.
|
|
81
|
+
- **`/spec-brief` refused a Draft spec but not one with no acceptance criteria**, so the emptier
|
|
82
|
+
failure got through the check written to catch it.
|
|
83
|
+
- **The release now fails when `MIRROR_TOKEN` is missing**, instead of shipping npm and reporting
|
|
84
|
+
green while the public mirror — the channel Claude Code actually installs from — sat on an old
|
|
85
|
+
version. 0.20.0, 0.20.1 and 0.21.0 all reported success against a mirror stuck at 0.19.0.
|
|
86
|
+
|
|
87
|
+
### Migrating
|
|
88
|
+
|
|
89
|
+
Existing installs point at a marketplace and plugin that no longer exist under those names:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
/plugin uninstall sdd-toolkit
|
|
93
|
+
/plugin marketplace remove ace-tools
|
|
94
|
+
/plugin marketplace add MLMCPS/ml-claude-plugins
|
|
95
|
+
/plugin install ml-specs
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Repo-level `.claude/settings.json` files that enable the plugin need the same edit. Two strings are
|
|
99
|
+
deliberately **not** renamed, because both are live contracts with things outside this repo: the
|
|
100
|
+
`sdd-spec-gate` required-status-check context (renaming it breaks branch protection on every repo
|
|
101
|
+
already configured) and the `<!-- sdd:constraints -->` markers already written into consumers'
|
|
102
|
+
`CLAUDE.md` (renaming them orphans every block already generated). Both need a migration, not a
|
|
103
|
+
find-and-replace.
|
|
104
|
+
|
|
105
|
+
## [0.21.0]
|
|
106
|
+
|
|
107
|
+
### Added
|
|
108
|
+
- **The MCP server now serves the plugin's commands as prompts**, so a client outside Claude Code
|
|
109
|
+
gets the workflow and not just the lookups. Until now `@mlmcps/sdd-mcp` exposed four read-only
|
|
110
|
+
tools and nothing else: someone wiring it into Cursor or a custom agent could ask *what specs
|
|
111
|
+
exist* but had no `/spec`, `/spec-build` or `/code` to act on the answer. The commands were
|
|
112
|
+
already the shape of an MCP prompt — frontmatter over a body with an `$ARGUMENTS` placeholder —
|
|
113
|
+
so they are served as one. All 18 arrive, described from their own frontmatter.
|
|
114
|
+
|
|
115
|
+
Clients namespace MCP prompts, so `spec` shows up as `/mcp__sdd-toolkit__spec`, not `/spec`.
|
|
116
|
+
That is the client's doing and cannot be opted out of.
|
|
117
|
+
|
|
118
|
+
- **Agents a command delegates to are inlined into the prompt.** Several commands hand real work
|
|
119
|
+
to a subagent, and MCP has no way to register one — so those steps would have silently done
|
|
120
|
+
nothing, which is the worst failure available here: the command appears to run and quietly skips
|
|
121
|
+
its adversarial pass. Any agent a command names in bold now has its instructions appended to the
|
|
122
|
+
prompt under a heading that says why. The client follows them inline, losing the isolated
|
|
123
|
+
context, tool restrictions and parallelism the plugin gets. `/spec-fanout` degrades most, being
|
|
124
|
+
parallel by design.
|
|
125
|
+
|
|
126
|
+
Matching the bolded name in the command's prose, rather than adding a machine-readable field,
|
|
127
|
+
is deliberate: it is the same string a reader of the command sees, so the two halves cannot
|
|
128
|
+
drift apart without the prose being wrong too.
|
|
129
|
+
|
|
130
|
+
- **Protocol tests for the MCP server** (`mcp/sdd-server.test.mjs`), which had none. They drive it
|
|
131
|
+
the way a client does — spawn the process, write newline-delimited JSON-RPC to stdin, read the
|
|
132
|
+
replies — so they also catch the one failure a unit test cannot: the server not starting at all.
|
|
133
|
+
|
|
134
|
+
### Changed
|
|
135
|
+
- `commands/` and `agents/` are now part of the `@mlmcps/sdd-mcp` package, since the prompts are
|
|
136
|
+
read from them at runtime. Both directories are already on the public mirror, so this discloses
|
|
137
|
+
nothing new. Skills, hooks, and the plugin's real subagent execution remain Claude Code only.
|
|
138
|
+
|
|
139
|
+
## [0.20.1]
|
|
140
|
+
|
|
141
|
+
### Fixed
|
|
142
|
+
- **`/nfr` and `/spec-fanout` were missing from the plugin's own description**, so the two commands
|
|
143
|
+
0.20.0 added shipped invisible: the description is the command list a user sees in the marketplace
|
|
144
|
+
and in `/plugin`, and neither new command appeared in it. They worked perfectly for anyone who
|
|
145
|
+
already knew they existed, which is not how anyone finds a command.
|
|
146
|
+
|
|
147
|
+
The cause is worth recording because it will recur otherwise. Two manifests carry that list —
|
|
148
|
+
`plugin.json` and the `marketplace.json` entry — and nothing kept either in step with `commands/`.
|
|
149
|
+
Preparing 0.20.0 one was updated and the other was not, and every existing check passed: the
|
|
150
|
+
release gate verifies versions, and this is not a version. `validate-plugin.mjs` now fails when a
|
|
151
|
+
command is missing from either description, and warns when a description names one that no longer
|
|
152
|
+
exists, so the next release cannot repeat it.
|
|
153
|
+
|
|
154
|
+
Git-source installs were unaffected — they resolve from the default branch, which had the fix
|
|
155
|
+
within the hour. This release is for the npm packages and the public mirror, where 0.20.0 is
|
|
156
|
+
immutable.
|
|
157
|
+
|
|
158
|
+
## [0.20.0]
|
|
159
|
+
|
|
160
|
+
### Added
|
|
161
|
+
- **The chain from ticket to test case is now checkable — `scripts/spec-trace.mjs`.**
|
|
162
|
+
`spec-gate.mjs` already checked that a spec's claimed evidence exists on disk. Nothing checked
|
|
163
|
+
that the branch, the pull-request title and the test-case ids all carry the *same* spec id — which
|
|
164
|
+
is the chain an auditor actually asks about, and the way it silently stops being true is a
|
|
165
|
+
hand-typed branch name. Every downstream id is now produced by a function with a matching parser,
|
|
166
|
+
so a link that lost the key is a parse failure rather than a divergence nobody notices. Exits
|
|
167
|
+
non-zero, so it gates a pull request.
|
|
168
|
+
|
|
169
|
+
It reports **broken** and **unverifiable** separately, and that distinction is deliberate. A
|
|
170
|
+
`Ticket` typed into a spec's header table cannot be checked from inside the repo; counting it as
|
|
171
|
+
passing would make the whole report a lie, so it is named as unchecked instead.
|
|
172
|
+
|
|
173
|
+
- **`/nfr` — non-functional requirements stop vanishing.** NFRs are the requirements most likely to
|
|
174
|
+
be agreed and then lost, because they do not decompose into user stories: a story breakdown
|
|
175
|
+
flattens "the API shall be performant" into prose that nothing checks, and nobody notices until
|
|
176
|
+
the load test that was never written would have caught it. This compiles each NFR into the two
|
|
177
|
+
things that actually enforce it — a standing constraint in `docs/CONSTRAINTS.md`, and a blocking
|
|
178
|
+
pipeline gate — and **refuses** one with no machine-checkable threshold, because an NFR nothing
|
|
179
|
+
can fail is not a requirement. It also fails when an NFR id has been written into an acceptance
|
|
180
|
+
criterion, which is the exact moment enforcement turns back into a sentence.
|
|
181
|
+
|
|
182
|
+
The constraints it writes are carried into the next spec automatically, so a rule agreed in
|
|
183
|
+
August is in front of whoever writes a spec in November without anyone remembering it exists.
|
|
184
|
+
|
|
185
|
+
- **`/spec-fanout` — a change spanning four services is one change, provably.** Today that is four
|
|
186
|
+
pull requests a reviewer correlates by hand and hopes they got right. Every branch in a fan-out
|
|
187
|
+
now carries the same derived name, and `docs/ESTATE.md` supplies the consumers — including the
|
|
188
|
+
service one hop out that nobody remembered. Plans first, then `--dry-run` prints the exact
|
|
189
|
+
requests, then opens them. Partial failure is reported rather than thrown: a permissions error on
|
|
190
|
+
the fourth repository must not hide that three succeeded.
|
|
191
|
+
|
|
192
|
+
- **`scripts/branch-policy.mjs` — the gate can be checked for still being a gate.** A pipeline that
|
|
193
|
+
runs and reports changes nothing; the load-bearing artifact is the branch policy. The quiet
|
|
194
|
+
failure mode is someone demoting it to advisory to unblock a release on a Friday — nothing breaks,
|
|
195
|
+
no test fails, and merges simply stop being gated until an audit finds the holes months later.
|
|
196
|
+
`install` has no flag that can produce an advisory gate, and `audit` treats advisory, disabled,
|
|
197
|
+
`manualQueueOnly` and GitHub's `enforce_admins: false` as blockers rather than warnings.
|
|
198
|
+
|
|
199
|
+
- **`scripts/tracker-sync.mjs` — governed sync with Azure DevOps or Jira.** A spec and a work item
|
|
200
|
+
can both hold a title, a status and a list of criteria; two stores for one truth diverge silently.
|
|
201
|
+
Exactly one system may now write each field — the spec owns the contract, the tracker owns status,
|
|
202
|
+
assignee and sprint — and an attempt to write the other's field is refused rather than winning.
|
|
203
|
+
|
|
204
|
+
- **`scripts/spec-brief.mjs` — the handoff to whoever implements a spec.** An approved spec is a
|
|
205
|
+
contract, but a scattered one: the criteria are in one section, the constraints in force in
|
|
206
|
+
another file, the gates that will fail the build in a third. The parts most often skipped are the
|
|
207
|
+
ones that cause the rework. This assembles them, and refuses a Draft spec — the contract is still
|
|
208
|
+
being negotiated. It is deliberately **not a prompt**: the same document for a person or an agent,
|
|
209
|
+
because anything an agent needs that a new engineer would not is a sign the spec is
|
|
210
|
+
underspecified, and that fix belongs in the spec.
|
|
211
|
+
|
|
212
|
+
- **`templates/ci/spec-gate.yml` and `templates/ci/azure-pipelines-spec-gate.yml`** — the merge gate
|
|
213
|
+
for both hosts. Both carry the same adoption note as `knowledge-layer.yml`: run it non-blocking
|
|
214
|
+
for a fortnight first, because a gate that fails on day one gets disabled on day two. The Azure
|
|
215
|
+
one audits its own branch policy on every run, which is the only check that survives someone
|
|
216
|
+
changing that setting.
|
|
217
|
+
|
|
218
|
+
- **The first tests in this package — 99 of them**, on Node's built-in runner, no dependencies.
|
|
219
|
+
They run offline: the tracker and source-control clients take an injectable transport, so the
|
|
220
|
+
documents they build are asserted without credentials. `npm test` runs them.
|
|
221
|
+
|
|
222
|
+
### Changed
|
|
223
|
+
- **`scripts/lib/specs.mjs` gains `criteria[]`, `repos`, `nfrs`, `approvedBy` and `author`.**
|
|
224
|
+
Additive only — `mcp/sdd-server.mjs` and `spec-dashboard.mjs` both read this shape and are
|
|
225
|
+
unaffected. Acceptance criteria now parse as structured rows, so a script can pair each with its
|
|
226
|
+
test case rather than counting checkboxes.
|
|
227
|
+
|
|
228
|
+
### Fixed
|
|
229
|
+
- **Test files would have shipped in the `@mlmcps/sdd-mcp` tarball.** `files[]` includes
|
|
230
|
+
`scripts/lib/` wholesale, so the new `*.test.mjs` files were being packaged. Excluded via a
|
|
231
|
+
negation pattern; `npm pack --dry-run` now contains none.
|
|
232
|
+
|
|
233
|
+
### Notes
|
|
234
|
+
- The Azure DevOps, Jira and GitHub clients are **contract-tested, not integration-tested**. They
|
|
235
|
+
build what ADO 7.1, Jira Cloud v3 and GitHub 2022-11-28 document, verified offline against a
|
|
236
|
+
recording transport. **None has run against a live organisation.** Every write path has
|
|
237
|
+
`--dry-run`, which prints the exact requests and needs no credentials — which is also the thing
|
|
238
|
+
to hand whoever has to approve an access token.
|
|
239
|
+
- The read/write split is enforced at runtime, not by convention: the read-only tracker and SCM
|
|
240
|
+
clients are frozen objects carrying only read methods, so a write path from the planning side is
|
|
241
|
+
absent and cannot be re-attached.
|
|
242
|
+
|
|
243
|
+
## [0.19.0]
|
|
244
|
+
|
|
245
|
+
### Changed
|
|
246
|
+
- **Both packages are now public on npmjs.org, under MIT.** `npm install @mlmcps/sdd-mcp` and
|
|
247
|
+
`npm install @mlmcps/sdd-toolkit` now work for anyone, with no `.npmrc` scope line and no token.
|
|
248
|
+
Until now they were published to GitHub Packages, which requires authentication *even for public
|
|
249
|
+
packages* and inherited this repository's private access control — so "install the toolkit" meant
|
|
250
|
+
"first get a GitHub PAT with `read:packages`, then map the `@mlmcps` scope in your `.npmrc`". That
|
|
251
|
+
was the friction this change removes.
|
|
252
|
+
|
|
253
|
+
The source repository stays private. What is public is the two published tarballs and nothing
|
|
254
|
+
else — which makes each manifest's `files[]` a disclosure boundary rather than a tidiness rule.
|
|
255
|
+
`@mlmcps/sdd-toolkit` carries the marketplace manifest and the plugin directory;
|
|
256
|
+
`@mlmcps/sdd-mcp` carries the MCP server, `scripts/lib/`, and the CI knowledge-check. Neither
|
|
257
|
+
ships `scripts/`, `examples/`, `CONTRIBUTING.md`, `PUBLISHING.md`, `.github/`, or git history, and
|
|
258
|
+
`validate-plugin.mjs` fails the build if the plugin package's `files[]` widens.
|
|
259
|
+
|
|
260
|
+
**Existing installs keep working but stop receiving updates.** Anything pinned to the GitHub
|
|
261
|
+
Packages registry resolves to 0.18.0 forever — versions from 0.19.0 on exist only on npmjs. Drop
|
|
262
|
+
the `@mlmcps:registry=` line from your `.npmrc` to pick them up.
|
|
263
|
+
- **License changed from `UNLICENSED` to `MIT`** in both manifests, with a `LICENSE` file at the
|
|
264
|
+
repo root. A public package under `UNLICENSED` tells people they may not use what you just handed
|
|
265
|
+
them; MIT is the grant that makes a public publish coherent. This applies from 0.19.0 onward —
|
|
266
|
+
it does not retroactively relicense 0.16.0–0.18.0.
|
|
267
|
+
- **`release.yml` publishes to npmjs with an `NPM_TOKEN` secret** instead of the built-in
|
|
268
|
+
`GITHUB_TOKEN`, and fails fast when that secret is missing — before the manifest and CHANGELOG
|
|
269
|
+
gates, so a release can never get half-published. `packages: write` is no longer requested.
|
|
270
|
+
|
|
271
|
+
## [0.18.0]
|
|
272
|
+
|
|
273
|
+
This release is about what the toolkit *costs to run*. Nothing changes about the workflow; the same
|
|
274
|
+
commands do the same work while reading less, reasoning less about what a script can settle, and
|
|
275
|
+
running the expensive parts concurrently.
|
|
276
|
+
|
|
277
|
+
### Added
|
|
278
|
+
- **`sdd-scanner` agent — the learn phase no longer fills the calling session's context.** The
|
|
279
|
+
commands that study a codebase (`/sdd-init`, `/sdd-refresh`, `/sdd-estate`) used to read source
|
|
280
|
+
files inline, so every file sampled to write a doc stayed in the window for the rest of the run —
|
|
281
|
+
while the model was writing docs, not reading code. Those commands now spawn scanners instead, in
|
|
282
|
+
a single message so they run concurrently, and each returns a **capped findings block of
|
|
283
|
+
`file:line` citations and never file contents**. `/sdd-init` fans out three briefs (stack,
|
|
284
|
+
structure, patterns); `/sdd-estate` fans out one per peer repo, so N peers cost roughly one peer's
|
|
285
|
+
wall-clock instead of N.
|
|
286
|
+
- **`scripts/spec-gate.mjs` — the mechanical half of a `/spec-advance` gate, checked exactly.**
|
|
287
|
+
Lifecycle ordering, leftover `<placeholder>` text, whether every acceptance criterion is ticked,
|
|
288
|
+
whether **every test file named in the §6 table exists on disk**, and whether the recorded branch
|
|
289
|
+
is merged. That work was being done by a model re-reading the spec and globbing — slow, paid for
|
|
290
|
+
on every run, and the half most likely to be done sloppily, since a named-but-missing test is the
|
|
291
|
+
most common way a status ends up claiming evidence that is not there. It deliberately refuses to
|
|
292
|
+
judge what a script cannot witness (human approval, whether a §8 question is blocking, whether the
|
|
293
|
+
suite ran green) and marks those `MANUAL`, because a `PASS` there would be believed. Pure Node, no
|
|
294
|
+
dependencies, no network calls; exits non-zero on any `FAIL` so it also works as a CI gate.
|
|
295
|
+
|
|
296
|
+
### Changed
|
|
297
|
+
- **`/sdd-refresh` re-learns only what moved.** It now derives the changed surface from
|
|
298
|
+
`git diff --name-only <last-doc-commit>..HEAD` and scopes the scanners to those paths, re-detecting
|
|
299
|
+
the stack only when the manifest itself changed — and stops early, saying so, when nothing has
|
|
300
|
+
changed at all. Re-learning an entire repo to update a few drifted sections was the single most
|
|
301
|
+
wasteful path in the toolkit. It still falls back to a full re-learn when most of the source moved
|
|
302
|
+
or the last-doc commit is unreachable, and says which it did.
|
|
303
|
+
- **`CLAUDE.fragment.md` trimmed from 118 lines to 80** (~1,690 → ~1,220 tokens). This file is
|
|
304
|
+
merged into every adopted repo's `CLAUDE.md`, so it is paid for on every session in every repo —
|
|
305
|
+
the one place in the toolkit where prose has a recurring cost. What went: the
|
|
306
|
+
`PLAN/FILES/IMPLEMENTATION/REVIEW/TESTS` block and the nine-rule working agreement, both of which
|
|
307
|
+
the `coder` agent already carries in full and only needs when it actually runs. What stayed,
|
|
308
|
+
verbatim: the no-AI-attribution policy and the knowledge-layer retrieval order, which is the part
|
|
309
|
+
that pays for itself by keeping later reads small.
|
|
310
|
+
- **Model routing on the mechanical commands.** `/spec-advance`, `/sdd-impact`, `/sdd-estate` and
|
|
311
|
+
`/sdd-rollout` now run on Sonnet — checking a fixed gate table, classifying a diff against a fixed
|
|
312
|
+
taxonomy, filling a template, and summarizing a script's output are not Opus-shaped work.
|
|
313
|
+
`/spec-review`, `/spec-verify` and both reviewer agents deliberately stay on the inherited model:
|
|
314
|
+
adversarial review is exactly what the larger model is for, and cheapening it would trade the
|
|
315
|
+
toolkit's main guarantee for a small saving.
|
|
316
|
+
- **Agent and command descriptions trimmed to what routing actually needs** (~1,390 → ~1,260 tokens
|
|
317
|
+
including the new agent). Descriptions are loaded on every session whether or not the command
|
|
318
|
+
runs, so an enumeration of supported languages or an output format in a `description` is paid for
|
|
319
|
+
continuously and used never.
|
|
320
|
+
|
|
321
|
+
## [0.17.0]
|
|
322
|
+
|
|
323
|
+
### Added
|
|
324
|
+
- **`@mlmcps/sdd-toolkit` — install the plugin without read access to the marketplace repo.** Until
|
|
325
|
+
now the only marketplace source was `github`, and Claude Code installs that with a `git clone`, so
|
|
326
|
+
anyone who could install could also take a full copy of the repo — history, tooling, everything.
|
|
327
|
+
Read access on GitHub *is* download access; there is no install-only permission, so the fix had to
|
|
328
|
+
be a different artifact rather than a different setting. This package carries the marketplace
|
|
329
|
+
manifest and the plugin directory and nothing else, letting a team be granted the package alone.
|
|
330
|
+
Point `.claude/settings.json` at `{ "source": "npm", "package": "@mlmcps/sdd-toolkit" }` instead of
|
|
331
|
+
the github source. The trade-off is when updates arrive: the git source updates on merge to the
|
|
332
|
+
default branch, this one only when a tag is published.
|
|
333
|
+
|
|
334
|
+
### Changed
|
|
335
|
+
- **One tag now publishes both packages** — `@mlmcps/sdd-mcp` (the MCP server, for non-Claude
|
|
336
|
+
clients) and `@mlmcps/sdd-toolkit` (the plugin) — with the marketplace package published second,
|
|
337
|
+
so a failure there still leaves the MCP server shipped rather than advertising a plugin version
|
|
338
|
+
that never existed.
|
|
339
|
+
- `validate-plugin.mjs` gained the fifth version location and a guard that **fails the build if the
|
|
340
|
+
plugin package's `files[]` widens beyond the plugin**. That package exists specifically to
|
|
341
|
+
withhold repo tooling, and a well-meaning `"scripts/"` added later would hand it over with no
|
|
342
|
+
visible symptom — the kind of regression only an explicit check catches.
|
|
343
|
+
|
|
344
|
+
## [0.16.0]
|
|
345
|
+
|
|
346
|
+
### Changed
|
|
347
|
+
- **Moved to the `MLMCPS` organisation** — the marketplace source is now
|
|
348
|
+
`MLMCPS/ace-claude-plugins`. Existing installs keep working because GitHub redirects the old path,
|
|
349
|
+
but update the `repo` value in your `.claude/settings.json` rather than relying on that redirect
|
|
350
|
+
outliving the move. The point of the move is how access is granted: an org team with read
|
|
351
|
+
permission lets teammates install the toolkit without being able to change it, which per-person
|
|
352
|
+
collaborator invites on a personal account do not scale to.
|
|
353
|
+
- **Breaking, npm consumers only: the package is now `@mlmcps/sdd-mcp`.** GitHub Packages requires
|
|
354
|
+
the npm scope to match the owning account, so moving the repo forced the rename — it was not a
|
|
355
|
+
preference. `@venkatmotivity/sdd-mcp` stays published at 0.13.0–0.15.0 and keeps working, but will
|
|
356
|
+
never receive another version: published package versions cannot be renamed or transferred. Anyone
|
|
357
|
+
pinning the old name in `.mcp.json` must change it to keep getting updates, and **0.16.0 is the
|
|
358
|
+
first version to exist under the new scope** — pinning `@mlmcps/sdd-mcp` at anything earlier
|
|
359
|
+
resolves to nothing. Claude Code users are unaffected either way: the MCP server ships inside the
|
|
360
|
+
plugin and was never installed from npm.
|
|
361
|
+
|
|
362
|
+
## [0.15.0]
|
|
363
|
+
|
|
364
|
+
### Added
|
|
365
|
+
- **`templates/settings.json`** — committed project settings that stop AI attribution reaching
|
|
366
|
+
commits and PRs, by setting `attribution.commit` and `attribution.pr` to empty. 0.14.1 stated that
|
|
367
|
+
rule in `CLAUDE.fragment.md`, but prose is something a model has to read and remember; this is
|
|
368
|
+
enforced by Claude Code itself, so the guarantee no longer depends on an instruction being
|
|
369
|
+
followed. The two work together — `CLAUDE.md` explains why, the setting makes it true.
|
|
370
|
+
|
|
371
|
+
### Changed
|
|
372
|
+
- **`/sdd-init` and `/sdd-adopt` now install that setting** (step 10 and step 9 respectively)
|
|
373
|
+
rather than merely offering it, because it is policy rather than something project-specific like
|
|
374
|
+
hook commands or CI invocations. Both merge only the `attribution` key into
|
|
375
|
+
`.claude/settings.json`, leaving every other key untouched, and both keep an existing
|
|
376
|
+
`attribution` value and report it rather than overwriting a deliberate choice. Because the file is
|
|
377
|
+
committed, it applies to everyone who clones the repo with no per-machine setup — the alternative
|
|
378
|
+
was a per-developer git hook, which secures exactly one laptop and silently misses every teammate,
|
|
379
|
+
every cloud session, and CI.
|
|
380
|
+
|
|
381
|
+
## [0.14.1]
|
|
382
|
+
|
|
383
|
+
### Added
|
|
384
|
+
- **`TEAM-SETUP.md`** at the marketplace root — the per-repo auto-enable rollout, what to verify
|
|
385
|
+
afterwards, and the private-repo access prerequisite that causes most failed setups. A
|
|
386
|
+
marketplace installs over a plain `git clone`, so a teammate without repo access hits a confusing
|
|
387
|
+
failure rather than a permission error; that prerequisite now has a documented home instead of
|
|
388
|
+
living in the head of whoever set it up first. `README.md` links to it, and the validator checks
|
|
389
|
+
its relative links along with the other docs.
|
|
390
|
+
|
|
391
|
+
### Changed
|
|
392
|
+
- **No AI attribution in commits or PRs.** The `pr-author` agent, `/pr`, `/fix`, `/spec-build`, and
|
|
393
|
+
the `CLAUDE.fragment.md` template now all state that commit messages, trailers, PR titles, and PR
|
|
394
|
+
bodies name the humans who own the change and nothing else — no assistant `Co-Authored-By:` line,
|
|
395
|
+
no "Generated with" line, no model or vendor name, no badge or emoji. The fragment and
|
|
396
|
+
`/spec-build` also spell out why a stray trailer is not a local problem: a squash merge
|
|
397
|
+
aggregates trailers from **every** commit on the branch, so one line added early resurfaces on
|
|
398
|
+
the merge commit long after, attributed to a tool rather than to the people who own the work.
|
|
399
|
+
- **Releases no longer cut a GitHub Release** (`release.yml`). Every Release carries
|
|
400
|
+
auto-generated "Source code (zip/tar.gz)" archives that GitHub builds from the tag, with no
|
|
401
|
+
setting to suppress them — so the tag plus the published package is now the release, and
|
|
402
|
+
`CHANGELOG.md` is where per-version notes live. The CHANGELOG gate survives the change (a
|
|
403
|
+
version with no section still fails before anything publishes), and the workflow's `contents`
|
|
404
|
+
permission drops from `write` to `read`, since creating the Release was the only step that
|
|
405
|
+
needed it.
|
|
406
|
+
|
|
407
|
+
## [0.14.0]
|
|
408
|
+
|
|
409
|
+
### Added
|
|
410
|
+
- **Release automation** (`.github/workflows/release.yml`), fired by pushing a
|
|
411
|
+
`sdd-toolkit-vX.Y.Z` tag. It re-checks the tag against **all three manifests before publishing
|
|
412
|
+
anything** — an npm version can be deprecated but never replaced, so a wrong tag has to fail
|
|
413
|
+
before it ships, not after — then validates, publishes to GitHub Packages, and cuts a GitHub
|
|
414
|
+
Release. It authenticates with the built-in `GITHUB_TOKEN`, so there is no secret to configure
|
|
415
|
+
and the package stays behind the same access control as the private repo.
|
|
416
|
+
- `scripts/changelog-section.mjs` — extracts one version's CHANGELOG section for the release body,
|
|
417
|
+
and **exits non-zero when that section is missing or empty**, so a release cannot ship with
|
|
418
|
+
unreadable notes.
|
|
419
|
+
- `CONTRIBUTING.md` and `/release` now state plainly that the two halves ship differently: the
|
|
420
|
+
**plugin** releases by merging to the default branch (a marketplace installs from a branch, so no
|
|
421
|
+
tag is involved), while the **npm package** releases on a tag. Conflating the two is the obvious
|
|
422
|
+
way to think you've shipped and haven't.
|
|
423
|
+
|
|
424
|
+
## [0.13.0]
|
|
425
|
+
|
|
426
|
+
### Added
|
|
427
|
+
- **The MCP server is publishable as a standalone npm package** (`sdd-toolkit/package.json`,
|
|
428
|
+
`@venkatmotivity/sdd-mcp`), so a team can use it without cloning the marketplace repo. The
|
|
429
|
+
package ships only `mcp/`, `scripts/lib/`, and the single CI module the server imports — ~18KB,
|
|
430
|
+
**zero dependencies**, no agents, commands, or templates. `publishConfig` targets GitHub
|
|
431
|
+
Packages, which keeps distribution behind the same access control as the private repo rather
|
|
432
|
+
than requiring a new registry account. Teammates then point `.mcp.json` at
|
|
433
|
+
`npx -y @venkatmotivity/sdd-mcp`, which is safe to commit because it names a package instead of
|
|
434
|
+
a path on someone's laptop. Verified end to end: packed, installed into a clean project, and
|
|
435
|
+
driven over stdio through the published `sdd-mcp` binary.
|
|
436
|
+
- `mcp/README.md` documents the three sharing options with their real costs, including the point
|
|
437
|
+
that **you cannot ship JavaScript and prevent it being read** — `node_modules` is source and a
|
|
438
|
+
compiled executable is unpackable — and that **remote hosting cannot work for this server**,
|
|
439
|
+
since every tool answers questions about the repo the caller is sitting in.
|
|
440
|
+
- `--version` / `-v` on the server, printing the version **and the resolved file path** — version
|
|
441
|
+
skew across a team is the predictable failure of distributing this (one stale npx cache, one
|
|
442
|
+
freshly-updated plugin, two different answers), and "which copy am I running?" should be one line
|
|
443
|
+
rather than archaeology. `mcp/README.md` documents how updates actually reach people per
|
|
444
|
+
distribution path, including that plugin users get the server updated *with the plugin* and need
|
|
445
|
+
no npm package at all.
|
|
446
|
+
- Validator: the version now has four homes (plugin manifest, marketplace entry, npm package,
|
|
447
|
+
and the version the server reports over the wire) and all four must agree — the last two drift
|
|
448
|
+
invisibly, which this release caught in itself. It also fails the build if the package ever
|
|
449
|
+
declares a dependency or its `bin` target is missing or non-executable.
|
|
450
|
+
|
|
451
|
+
## [0.12.1]
|
|
452
|
+
|
|
453
|
+
### Fixed
|
|
454
|
+
- **`fix-specs.mjs` would have written statuses their authors never claimed.** Found by running the
|
|
455
|
+
dry run against a real 190-spec repo — which is what dry runs are for. Two compounding mistakes:
|
|
456
|
+
- The lifecycle word was matched by position in the **enum**, not position in the **text**, so a
|
|
457
|
+
Status reading "Phase 1 ✓ + Phase 2a ✓ … branch master verified" resolved to whichever stage
|
|
458
|
+
came first in `[Draft, Approved, Implemented, Verified, Archived]` rather than what the author
|
|
459
|
+
led with. Now matched by where the word actually appears.
|
|
460
|
+
- Even matched correctly, promoting a stage word found *mid-sentence* turns narration into a
|
|
461
|
+
claim. Normalization now requires the word to **lead** the cell ("Implemented (2026-07-07) — …"
|
|
462
|
+
is a declaration; "…branch master verified" is discussion). Anything else is left untouched and
|
|
463
|
+
reported, alongside the existing no-lifecycle-word case, with the reason given per file.
|
|
464
|
+
`resolveStatus()` moved into `scripts/lib/specs.mjs` so the dashboard and MCP server apply the
|
|
465
|
+
same rule, and exposes `leading` / `ambiguous` / `candidates` for callers that want to flag rather
|
|
466
|
+
than resolve.
|
|
467
|
+
- **`survey-estate.mjs` reported a parent directory as "not a git repo".** It only expanded a
|
|
468
|
+
directory into the repos beneath it when given exactly one argument — so any extra argument made
|
|
469
|
+
it treat every path as a repo. Each target is now expanded independently. It also detects the
|
|
470
|
+
cause of the extra arguments: zsh does not treat `#` as a comment interactively, so a pasted
|
|
471
|
+
trailing `# comment` arrives as arguments, and the script now says that instead of listing six
|
|
472
|
+
English words as failed repos.
|
|
473
|
+
|
|
474
|
+
## [0.12.0]
|
|
475
|
+
|
|
476
|
+
### Added
|
|
477
|
+
- **`scripts/spec-dashboard.mjs`** — a self-contained HTML dashboard of every spec, generated
|
|
478
|
+
locally. No CDN, no fonts, no network calls, so it works offline and the spec data never leaves
|
|
479
|
+
the machine — which is the point for a repo that can't be shared. Lifecycle bars,
|
|
480
|
+
acceptance-criteria completion, a severity-ordered needs-attention list, duplicate ids, and a
|
|
481
|
+
searchable table.
|
|
482
|
+
- **In-flight view for parallel work.** Running several specs at once (the three-developers
|
|
483
|
+
pattern) means several worktrees on several branches, and telling them apart was guesswork.
|
|
484
|
+
The dashboard joins each live `git worktree` back to the spec it's building — branch, commits
|
|
485
|
+
ahead, dirty or clean, path — so four concurrent builds are four labelled rows.
|
|
486
|
+
- One chart, deliberately: the lifecycle bars are single-hue with the stage named on the axis and
|
|
487
|
+
the count direct-labeled, because colouring five stages five ways would be decoration. Status
|
|
488
|
+
colours stay reserved for the attention list and always ship with an icon and a word, so meaning
|
|
489
|
+
is never carried by colour alone. Light and dark are both explicitly stepped.
|
|
490
|
+
- `scripts/lib/specs.mjs` — spec parsing extracted so the dashboard and the MCP server share one
|
|
491
|
+
implementation of "what a spec says" instead of two that drift. It also resolves a Status cell
|
|
492
|
+
holding prose down to its lifecycle word, and reads header cells to the last pipe rather than the
|
|
493
|
+
first, so prose containing `|` is no longer silently truncated.
|
|
494
|
+
- MCP `spec_list` now returns a **summary** (counts by status, AC totals, duplicate ids,
|
|
495
|
+
needs-attention count) alongside the rows, plus a `summaryOnly` argument — so a client can answer
|
|
496
|
+
"what's the state?" on a repo with hundreds of specs without rendering every row.
|
|
497
|
+
|
|
498
|
+
## [0.11.0]
|
|
499
|
+
|
|
500
|
+
### Added
|
|
501
|
+
- **The MCP server now ships bundled with the plugin** (`sdd-toolkit/.mcp.json`), declared with a
|
|
502
|
+
`${CLAUDE_PLUGIN_ROOT}`-relative path so it resolves wherever the plugin was installed — any
|
|
503
|
+
machine, any checkout. Previously each person had to hand-edit an absolute path into their repo's
|
|
504
|
+
`.mcp.json`, which is fine for the author's laptop and broken for everyone else; that template
|
|
505
|
+
remains as a fallback. The validator now **rejects absolute paths** in the bundled config, since
|
|
506
|
+
that is precisely the bug that makes a git-distributed plugin work only for whoever wrote it.
|
|
507
|
+
|
|
508
|
+
### Fixed
|
|
509
|
+
- **The documented repo did not exist.** Manifests and READMEs pointed at an org that does not host
|
|
510
|
+
this repo, in 7 places — so `/plugin marketplace add <documented path>` 404'd and git-based
|
|
511
|
+
distribution could not have worked at all. Corrected to the real remote, and `PUBLISHING.md` now
|
|
512
|
+
carries a rename recipe that ends in a validator run rather than a hand-written `sed` that had
|
|
513
|
+
itself drifted.
|
|
514
|
+
|
|
515
|
+
## [0.10.0]
|
|
516
|
+
|
|
517
|
+
### Added
|
|
518
|
+
- **`/fix <bug>`** — bugs had no home. `/spec` is built for features (it asks what the contract
|
|
519
|
+
*should* be), but a defect already has a contract and the code is just violating it, so a
|
|
520
|
+
feature-shaped spec is wasted ceremony. Bugs were therefore falling through to `/code`, which
|
|
521
|
+
applies no discipline at all. `/fix` is the middle path, and its discipline is a single rule:
|
|
522
|
+
**reproduce it with a test that fails, and show the failure, before changing anything.** A fix
|
|
523
|
+
without a test that failed first is a guess, and nothing stops the bug returning. Then: root cause
|
|
524
|
+
stated in one sentence with `file:line` (and an explicit admission when the symptom is suppressed
|
|
525
|
+
rather than understood), the smallest change that turns it green, real verification output, and a
|
|
526
|
+
search for the same defect in sibling code paths. Escalates to `/spec` when the fix would change a
|
|
527
|
+
contract — at that point it isn't a bugfix, it's a change of intent.
|
|
528
|
+
|
|
529
|
+
### Fixed
|
|
530
|
+
- **`/sdd-status` was unusable on a mature repo.** It rendered one table row per spec, which is fine
|
|
531
|
+
at 12 specs and unreadable at 184 — and expensive, since it read every file into context to do it.
|
|
532
|
+
It now summarizes above ~25 specs (counts by status, overall AC completion) and tables **only the
|
|
533
|
+
specs needing a decision**, saying how many rows it withheld and how to see them
|
|
534
|
+
(`/sdd-status all`, or a status to filter). It also prefers the MCP `spec_list` tool when
|
|
535
|
+
available, which parses the specs locally instead of loading them all. New checks in the
|
|
536
|
+
needs-attention list: a Status holding free-text prose rather than a lifecycle word, and duplicate
|
|
537
|
+
spec numbers — both pointing at `scripts/fix-specs.mjs` rather than proposing to fix them one at
|
|
538
|
+
a time.
|
|
539
|
+
|
|
540
|
+
## [0.9.0]
|
|
541
|
+
|
|
542
|
+
### Added
|
|
543
|
+
- **`/sdd-rollout`** — onboarding an estate, which is the bottleneck everything else waits on:
|
|
544
|
+
`/sdd-impact` and the MCP `estate_lookup` both correctly refuse to answer until the peer repos
|
|
545
|
+
have knowledge layers, so a toolkit installed in one service out of seventeen is mostly inert.
|
|
546
|
+
The command exists to **aim the expensive part** rather than spray it. `/sdd-init` is the costliest
|
|
547
|
+
operation here, and running it unattended across an estate buys both a large bill and a pile of
|
|
548
|
+
knowledge layers nobody reviewed — the exact failure this toolkit exists to prevent. So:
|
|
549
|
+
- Survey first, mechanically and free (below), then order repos by **cross-service surface** rather
|
|
550
|
+
than alphabetically — onboarding a hub unlocks `/sdd-impact` for its peers, a leaf unlocks nothing.
|
|
551
|
+
- **The first repo is an explicit calibration run**: onboard exactly one, stop, have a human read
|
|
552
|
+
the generated docs. Something is almost always systematically off, and fixing it before repo two
|
|
553
|
+
is the difference between 17 good knowledge layers and 17 copies of one mistake.
|
|
554
|
+
- Routes each repo to `/sdd-init` or `/sdd-adopt` from the survey, never `/sdd-init` over existing
|
|
555
|
+
docs. Leaves everything uncommitted. Ends with `/sdd-estate`, which is the actual payoff.
|
|
556
|
+
- Resumable with no ledger: the survey re-derives each repo's state from disk, so onboarded repos
|
|
557
|
+
show as `refresh` and fall out of the queue.
|
|
558
|
+
- **`scripts/survey-estate.mjs`** — the cheap half, split out so it needs no model: per repo, the
|
|
559
|
+
stack from its manifest, knowledge-layer state, spec count, 90-day commit activity, uncommitted
|
|
560
|
+
changes, and cross-service edge signals (event listeners, HTTP clients, contract files), ending in
|
|
561
|
+
an init / adopt / refresh / review recommendation. Detects other tools' agent instructions
|
|
562
|
+
(`AGENTS.md`, `.cursorrules`, Copilot) and routes those repos to `/sdd-adopt`, since `/sdd-init`
|
|
563
|
+
would clobber them. Bounded file walk so a survey stays cheap on a monorepo, and it says when the
|
|
564
|
+
cap truncated its counts rather than reporting a floor as a total. Read-only, no dependencies,
|
|
565
|
+
no network calls.
|
|
566
|
+
|
|
567
|
+
## [0.8.0]
|
|
568
|
+
|
|
569
|
+
### Added
|
|
570
|
+
- **`scripts/fix-specs.mjs`** — repairs the two spec-hygiene problems that accumulate in a repo
|
|
571
|
+
that adopted `specs/` before the newer commands existed. 0.6.0 stopped `/spec` from *creating*
|
|
572
|
+
duplicate numbers but did nothing about ones already on disk, and the evidence-gated `Status`
|
|
573
|
+
from 0.4.0 assumes a one-word value that older specs don't have.
|
|
574
|
+
- **Duplicate numbers** — keeps the earliest-added file on the number and renumbers the rest to
|
|
575
|
+
the next free id across **all** branches, `git mv` so history follows, rewriting exact filename
|
|
576
|
+
references in `specs/`, `docs/`, and the root READMEs. Only exact filenames are rewritten;
|
|
577
|
+
prose like "see spec 0043" is reported, not guessed at. Sub-spec suffixes (`0165b`, `0171c`)
|
|
578
|
+
are distinct ids, not collisions.
|
|
579
|
+
- **Prose in `Status`** — moves the lifecycle word into `Status` and preserves the original text
|
|
580
|
+
**verbatim** as a `> **Status note:**` under the header table. That text is usually real
|
|
581
|
+
information sitting in the wrong field, so it is relocated, never deleted. A status with no
|
|
582
|
+
recognisable lifecycle word is left alone and reported for a human.
|
|
583
|
+
- Dry run by default, `--apply` to write, `--force` to override the guard that refuses to apply
|
|
584
|
+
over a dirty `specs/`/`docs/` (so the script's diff stays reviewable on its own). Idempotent.
|
|
585
|
+
Pure Node, no dependencies, **no network calls** — it runs entirely on the user's machine, which
|
|
586
|
+
matters when the repo it repairs can't be shared.
|
|
587
|
+
- `/sdd-doctor` now points at the script when it finds either problem, rather than proposing to fix
|
|
588
|
+
them one file at a time.
|
|
589
|
+
|
|
590
|
+
## [0.7.0]
|
|
591
|
+
|
|
592
|
+
### Added
|
|
593
|
+
- **MCP server** (`mcp/sdd-server.mjs`) — the deterministic half of the toolkit, exposed to any MCP
|
|
594
|
+
client (Cursor, a custom agent, CI), read-only and dependency-free.
|
|
595
|
+
- `estate_lookup` — who produces/consumes a contract, from `docs/ESTATE.md`, with each row marked
|
|
596
|
+
confirmed or unverified. Returns `present: false` with an explicit note when there's no index:
|
|
597
|
+
"no index" is not "no consumers", and a false all-clear on a cross-service change is worse than
|
|
598
|
+
no answer because it gets believed.
|
|
599
|
+
- `knowledge_check` — the CI gate's checks as structured data. **Imports** the implementation from
|
|
600
|
+
`templates/ci/knowledge-check.mjs` rather than copying it, so the two can't drift; that file is
|
|
601
|
+
now a module with a CLI guard, and importing it is silent (a stray `console.log` would corrupt
|
|
602
|
+
the JSON-RPC stream).
|
|
603
|
+
- `spec_list`, `spec_next_number` — specs as structured data, with the across-all-branches
|
|
604
|
+
numbering from 0.6.0, reporting explicitly when it couldn't fetch instead of assuming.
|
|
605
|
+
- Templates served as `sdd://templates/…` resources, with path traversal rejected.
|
|
606
|
+
No dependencies: stdio MCP is newline-delimited JSON-RPC 2.0, implemented directly, by the same
|
|
607
|
+
convention that keeps `validate-plugin.mjs` dependency-free. `templates/mcp/.mcp.json` wires it
|
|
608
|
+
into a repo; `/sdd-init` offers it rather than installing it, since it needs an absolute path.
|
|
609
|
+
**The agents, skills, and hooks deliberately do NOT port** — MCP can't spawn a subagent with its
|
|
610
|
+
own tool allowlist and model, and can't register a hook. Those stay in the plugin; the two compose.
|
|
611
|
+
- Validator: the server's advertised `serverInfo.version` must match `plugin.json` (nothing else
|
|
612
|
+
keeps them in step, and the drift is visible only to clients), and its relative imports must
|
|
613
|
+
resolve. `templates/mcp/.mcp.json` must parse and declare `mcpServers`.
|
|
614
|
+
|
|
615
|
+
### Fixed
|
|
616
|
+
- **`estate_lookup` parsed every event table with the wrong columns.** Section detection tested
|
|
617
|
+
`includes('synchronous')` before `includes('asynchronous')` — and "asynchronous" contains
|
|
618
|
+
"synchronous", so async rows were classified `sync` and their fields shifted by one, reporting an
|
|
619
|
+
event name as the calling service. Caught by fixture testing before release.
|
|
620
|
+
- `spec_next_number` reported `remoteChecked: false` identically for "no remote configured" and
|
|
621
|
+
"fetch failed" — the second is a real collision risk and now says so.
|
|
622
|
+
|
|
623
|
+
## [0.6.0]
|
|
624
|
+
|
|
625
|
+
### Added
|
|
626
|
+
- **Knowledge-layer CI gate** (`templates/ci/knowledge-check.mjs` + `knowledge-layer.yml`, seeded by
|
|
627
|
+
`/sdd-init`). 0.5.0's `SessionStart` hook made drift *visible*; this makes it *enforced*, because
|
|
628
|
+
advisory is exactly what got the docs to zero maintenance in the first place. It's the mechanical
|
|
629
|
+
half of `/sdd-doctor` — the checks needing no judgment, so CI can run them on every PR: every
|
|
630
|
+
`file:line` in the knowledge layer still resolves and the file is still that long, relative doc
|
|
631
|
+
links resolve, every shard is reachable from the router, docs are within budget. Plus an advisory
|
|
632
|
+
when a PR changes source and touches no doc. Pure Node, no dependencies. `--warn-only` exists for
|
|
633
|
+
adoption on a repo with existing drift: a gate that fails on day one gets disabled on day two.
|
|
634
|
+
`/sdd-doctor` now runs the script when present instead of eyeballing references.
|
|
635
|
+
- **`/sdd-impact [spec-file]`** — who breaks if this ships? Detects changes to *observable*
|
|
636
|
+
contracts (event payloads, API request/response shapes, shared tables, exported types), resolves
|
|
637
|
+
consumers from `docs/ESTATE.md`, classifies each as additive / compatible-with-sequence /
|
|
638
|
+
breaking, and produces a deploy order that's safe at every intermediate step. Nothing else in the
|
|
639
|
+
loop looks outside this repo — tests, `/code-review`, and `/spec-verify` all pass cleanly on a
|
|
640
|
+
change that breaks a consumer. If the estate index is missing or mostly `_TBD_`, it **refuses to
|
|
641
|
+
answer** rather than reporting "no consumers affected": that false all-clear is worse than no
|
|
642
|
+
answer, because it gets believed. Wired into `/spec-verify` for contract-touching changes.
|
|
643
|
+
- **`/sdd-adopt`** — `/sdd-init` assumes a blank slate, which is wrong for most repos that already
|
|
644
|
+
have a hand-written `CLAUDE.md`, `docs/`, or an RFC/ADR practice, and clobbering documentation a
|
|
645
|
+
team wrote is the fastest way to make them distrust the tool. This classifies every existing
|
|
646
|
+
section as keep-verbatim / merge / missing, keeps their structure and file names, maps the spec
|
|
647
|
+
loop onto their existing process instead of replacing it, and reports where their docs and the
|
|
648
|
+
code disagree **without changing anything** — a stale claim a human wrote is theirs to retire.
|
|
649
|
+
`/sdd-init` now detects an existing knowledge layer and redirects here.
|
|
650
|
+
|
|
651
|
+
### Fixed
|
|
652
|
+
- **Spec numbers collided across branches.** `/spec` picked the next number from the working tree,
|
|
653
|
+
so two people speccing in parallel both got `0007-` and found out at merge — as a conflict in a
|
|
654
|
+
*filename*, which git resolves badly. It now takes the max across every branch
|
|
655
|
+
(`git log --all --diff-filter=A -- 'specs/[0-9]*'`) unioned with `specs/` and `specs/archive/`,
|
|
656
|
+
fetching first where there's a remote, and says so explicitly when it can't fetch rather than
|
|
657
|
+
numbering off a stale view. Documented in `specs/README.md`, including how to resolve a collision
|
|
658
|
+
that does land.
|
|
659
|
+
|
|
660
|
+
## [0.5.0]
|
|
661
|
+
|
|
662
|
+
### Added
|
|
663
|
+
- **Hooks that ship with the plugin and activate on install** (`hooks/hooks.json`). Usage data
|
|
664
|
+
showed `/sdd-refresh`, `/sdd-doctor`, and `/sdd-status` at effectively zero — the knowledge layer
|
|
665
|
+
was generated once by `/sdd-init` and then never re-checked, which quietly undoes the toolkit's
|
|
666
|
+
main claim. A command nobody remembers to type loses to automation:
|
|
667
|
+
- `knowledge-drift.sh` (`SessionStart`) — one line when `CLAUDE.md`/`docs/` are more than
|
|
668
|
+
`SDD_DRIFT_THRESHOLD` (default 30) *source* commits behind the code; doc-only commits don't
|
|
669
|
+
count, so refreshing the docs doesn't itself look like drift. Silent otherwise, and exits 0 on
|
|
670
|
+
anything unexpected — a session-start hook must never be why a session starts badly.
|
|
671
|
+
- `secret-scan.sh` (`PreToolUse` on Bash) — the old copy-paste example, hardened into a real
|
|
672
|
+
script: added lines only (removing a leaked key isn't blocked), an allowlist at
|
|
673
|
+
`.claude/secret-allowlist.txt`, and JWTs added to the pattern set. The only hook allowed to
|
|
674
|
+
block, because a committed key is unbounded damage and a false positive costs one line.
|
|
675
|
+
Project-specific automation (format/lint/test) still can't ship — the plugin can't know your
|
|
676
|
+
commands — so `templates/hooks/settings.hooks.example.json` now holds only those, and points at
|
|
677
|
+
what the plugin already runs for you.
|
|
678
|
+
- **`skills/knowledge-retrieval`** — the deep retrieval procedure (sharded-doc navigation, the 1-hop
|
|
679
|
+
dependency closure, designing across a service boundary: both sides of the contract, deploy order,
|
|
680
|
+
compatibility) moved out of the always-loaded `CLAUDE.md` fragment into a skill that loads only
|
|
681
|
+
when a task actually hits one of those. The always-needed ladder stayed in `CLAUDE.md` on purpose —
|
|
682
|
+
a rule you must know *before* you know you need it can't live on-demand.
|
|
683
|
+
- **`/release`** in `.claude/commands/` (the marketplace repo, not the plugin — it publishes plugins,
|
|
684
|
+
so it must not ship to the repos that install them). Reads the real diff since the last release,
|
|
685
|
+
proposes the semver level, writes the CHANGELOG entry in house style, bumps the version in both
|
|
686
|
+
manifests that CI requires to match, and validates. Stops before committing.
|
|
687
|
+
|
|
688
|
+
### Changed
|
|
689
|
+
- **`/spec-build` now actually spawns `sdd-developer`.** It ran at 26% of skill usage while the
|
|
690
|
+
agent ran at ~1% — the command was reimplementing the agent's job inline, so the agent's
|
|
691
|
+
guarantees (test per criterion, functional/E2E for user-facing ones, real results only) silently
|
|
692
|
+
didn't apply, and the parallel three-worktree pattern in `specs/AGENTS.md` couldn't happen at all.
|
|
693
|
+
Blocking questions are resolved in the command *before* handing off, since a subagent has no
|
|
694
|
+
channel to the human.
|
|
695
|
+
- **The validator now catches dead wiring** — the check that would have made 0.4.0's two orphaned
|
|
696
|
+
agents impossible. A *mention* no longer counts as an invocation: it matches the idiom
|
|
697
|
+
`Use the **agent-name** agent`, because describing an agent in backticks is exactly how
|
|
698
|
+
`sdd-reviewer` and `pr-author` looked wired while nothing ran them. An agent with no command must
|
|
699
|
+
declare why with an `<!-- invoked-by: … -->` comment (`sdd-spec-author` does — `/spec` must ask the
|
|
700
|
+
human its contract questions, which a subagent can't). Also added: `${CLAUDE_PLUGIN_ROOT}/…` paths
|
|
701
|
+
resolve, `hooks.json` scripts exist **and are executable** (a non-executable hook fails silently),
|
|
702
|
+
`skills/<name>/SKILL.md` frontmatter matches its directory, and relative README links resolve.
|
|
703
|
+
|
|
704
|
+
## [0.4.0]
|
|
705
|
+
|
|
706
|
+
### Added
|
|
707
|
+
- **`/spec-verify <spec-file>` — the VERIFY phase finally has an entry point.** The `sdd-reviewer`
|
|
708
|
+
agent had shipped since 0.1.0 with *nothing* invoking it: `/spec-build` sent users to the built-in
|
|
709
|
+
`/code-review` instead, which reviews the diff for bugs and never opens the spec. The gate the
|
|
710
|
+
toolkit advertised — "test per criterion + adversarial review" — was reachable only if the model
|
|
711
|
+
happened to route to the agent on its own. `/spec-verify` delegates to it, relays the
|
|
712
|
+
per-criterion verdict and the real final-acceptance output unsoftened, and splits must-fixes into
|
|
713
|
+
*code is wrong* (fix and re-run) vs *spec is wrong* (a contract change → back through
|
|
714
|
+
AskUserQuestion, never a quiet widening of the spec to match what was built). Both reviews are now
|
|
715
|
+
prescribed, with a table saying which question each one answers.
|
|
716
|
+
- **`/pr <spec-file>`** — same orphan problem: `pr-author` existed with no command. Defaults to the
|
|
717
|
+
spec matching the current branch, flags a not-yet-`Verified` spec up front, produces text only,
|
|
718
|
+
and opens the PR only on an explicit ask (via `--body-file`, never a retyped body).
|
|
719
|
+
- **`/spec-advance <spec-file> [status]` — spec status becomes evidence-backed.** Status was written
|
|
720
|
+
ad hoc by whichever agent felt done, so `Verified` meant "an agent said so". It is now written
|
|
721
|
+
*only* here, and each transition must show its evidence: `Approved` needs the human's approval in
|
|
722
|
+
conversation and no blocking question parked in §8; `Implemented` needs every test named in the §6
|
|
723
|
+
table to **exist on disk** (a named-but-missing test being the usual lie); `Verified` needs a clean
|
|
724
|
+
`/spec-verify` *and* a green §6.1 suite, never an assertion; `Archived` needs the branch merged,
|
|
725
|
+
then `git mv`s the spec to `specs/archive/` keeping its number. Missing evidence means the
|
|
726
|
+
transition is **refused**, which is a successful run. Backwards moves are allowed but must add a
|
|
727
|
+
Revisions row. The command also records the spec's **Branch**, so `/sdd-status` reads it instead of
|
|
728
|
+
guessing from `git branch --all`.
|
|
729
|
+
- **`/sdd-estate`** — `docs/ESTATE.md` had a template but no generator, so the estate index (the
|
|
730
|
+
thing that makes this a multi-service toolkit rather than a per-repo one) was hand-maintained.
|
|
731
|
+
The command scans the peer repos read-only, indexes the real edges — HTTP/RPC clients, event
|
|
732
|
+
producers/consumers, shared tables/packages — with `file:line` on **both** sides, marks unconfirmed
|
|
733
|
+
peer-side rows `(inferred)`, merges rather than overwrites, and reports the edges it could not
|
|
734
|
+
resolve as the headline output (an unresolved edge is where a cross-service change breaks).
|
|
735
|
+
|
|
736
|
+
### Changed
|
|
737
|
+
- `templates/docs/ESTATE.md` → **`ESTATE.template.md`** (matching `PATTERNS.template.md` /
|
|
738
|
+
`ARCHITECTURE.template.md`) and genericized. It shipped pre-filled with one estate's real services
|
|
739
|
+
and queues, which `/sdd-init` would then copy verbatim into unrelated repos. Now placeholders,
|
|
740
|
+
plus an evidence column and an optional shared-data table.
|
|
741
|
+
- Spec template: `Branch` row and the `Archived` status; a note that Status is written by
|
|
742
|
+
`/spec-advance`, not by hand.
|
|
743
|
+
- `specs/README.md` gained a **Lifecycle** table (status → meaning → gate), and the loop's VERIFY
|
|
744
|
+
step now names `/spec-verify` and `/pr`. `specs/AGENTS.md` maps each agent to the command that
|
|
745
|
+
runs it — the mapping whose absence hid the two orphans.
|
|
746
|
+
- `/spec-build` now hands off through `/spec-advance Implemented` → `/spec-verify` → `/code-review`
|
|
747
|
+
→ `/spec-advance Verified` → `/pr` instead of ending at "recommend `/code-review`". `/spec` and
|
|
748
|
+
`/spec-review` no longer touch Status (an author doesn't approve their own spec).
|
|
749
|
+
- `/sdd-status` reads the spec's `Branch` row (marking fallback guesses with `?`), collapses
|
|
750
|
+
`specs/archive/` to a count, and flags merged-but-unarchived specs. `/sdd-doctor` now flags
|
|
751
|
+
`Verified` specs whose named tests don't exist and blocking questions parked in §8.
|
|
752
|
+
- `/sdd-init` and `/sdd-refresh` delegate `docs/ESTATE.md` to `/sdd-estate` rather than copying or
|
|
753
|
+
hand-editing it.
|
|
754
|
+
|
|
755
|
+
## [0.3.0]
|
|
756
|
+
|
|
757
|
+
### Added
|
|
758
|
+
- **One-pass spec review.** Human review of a spec was looping: read → find holes → answer →
|
|
759
|
+
re-read. Three causes, all fixed:
|
|
760
|
+
- `/spec` and `sdd-spec-author` gave **opposite instructions** on the same trigger — the command
|
|
761
|
+
said ask the user before writing; the agent said park the questions in the document. The agent
|
|
762
|
+
won whenever the model routed to it, so blocking contract decisions reached the human as
|
|
763
|
+
homework. Both now resolve blocking ambiguity *before* the spec is written, with one definition
|
|
764
|
+
of blocking (the answer changes an API shape, data model, error code, scope boundary, or
|
|
765
|
+
compatibility — i.e. you'd rewrite a section knowing it). `/spec` asks the batch directly via
|
|
766
|
+
AskUserQuestion, each question carrying concrete options and a recommendation; `sdd-spec-author`
|
|
767
|
+
is a subagent with no user channel, so it stops and returns the questions to its caller instead.
|
|
768
|
+
Section 8 is now non-blocking follow-ups **only**, and the template says so.
|
|
769
|
+
- **`/spec` never routed through `/spec-review`** — it sent the user straight from draft to
|
|
770
|
+
approve to `/spec-build`, making the human the first reviewer. `/spec` now runs the adversarial
|
|
771
|
+
pass over its own draft and fixes what it finds before the human sees anything.
|
|
772
|
+
- **Revisions had no bounded surface** — a sent-back spec cost a full re-read. `TEMPLATE.md` now
|
|
773
|
+
carries a `Revisions` table (what changed, why, which sections) so round two is a diff read.
|
|
774
|
+
- `sdd-spec-reviewer` agent — the adversarial spec pass as a reusable unit with **fresh context**
|
|
775
|
+
(a spec's author cannot see its own holes). `/spec-review` is now a thin delegator to it, and
|
|
776
|
+
`/spec` spawns it automatically. Also flags blocking questions parked in section 8 as blockers.
|
|
777
|
+
- **Per-component model tiering (quality-first).** Everything that affects code quality stays on
|
|
778
|
+
the inherited (Opus) model: the code-writing agents (`coder`, `sdd-developer`, `/spec-build`),
|
|
779
|
+
the spec author (`sdd-spec-author`, `/spec`), and both quality gates (`sdd-reviewer`,
|
|
780
|
+
`/spec-review`). Only work with **no** bearing on code correctness runs cheaper via frontmatter:
|
|
781
|
+
`pr-author` (PR prose) → **sonnet**; `/sdd-doctor`, `/sdd-status` (mechanical read-only
|
|
782
|
+
dashboards) → **haiku**. `spec-build`/`sdd-developer` run only the targeted tests during
|
|
783
|
+
implementation and the full functional/E2E suite **once** at the final-acceptance step (cheaper,
|
|
784
|
+
no quality loss — the full gate still runs). The validator checks `model` frontmatter values.
|
|
785
|
+
- **Functional/E2E tests + final-acceptance gate.** The spec template now has a functional/E2E
|
|
786
|
+
test type and a `## 6.1 Final acceptance` section, and a `Verified` status. Every user-facing /
|
|
787
|
+
contract-level acceptance criterion needs a functional/E2E test (not just a unit test), and a
|
|
788
|
+
spec is only `Verified` once the project's *full* suite (incl. functional/E2E) passes end to
|
|
789
|
+
end. Threaded through `/spec-build`, the `sdd-developer` and `sdd-reviewer` agents,
|
|
790
|
+
`specs/README.md`, the CLAUDE.md fragment, and `docs/PATTERNS.md`.
|
|
791
|
+
- `/spec-review <spec-file>` — adversarial review of a spec **before** any code: checks contracts,
|
|
792
|
+
acceptance criteria, and cross-module ripple are complete and testable.
|
|
793
|
+
- `/sdd-doctor` — read-only health check of the knowledge layer (broken `file:line` refs, stale
|
|
794
|
+
commands, over-budget docs, `(inferred)` markers, spec hygiene); recommends `/sdd-refresh`.
|
|
795
|
+
- `/sdd-status` — dashboard of every spec: lifecycle status, acceptance-criteria progress, and the
|
|
796
|
+
matching git branch.
|
|
797
|
+
- `pr-author` agent — turns a completed spec + its diff into a PR title and body with the
|
|
798
|
+
acceptance criteria as a review checklist (read-only; does not open the PR).
|
|
799
|
+
- **CI:** `.github/workflows/validate.yml` + `scripts/validate-plugin.mjs` (no-dependency) validate
|
|
800
|
+
manifests, agent/command frontmatter, agent-name/filename match, and **version sync** between
|
|
801
|
+
`plugin.json` and the `ace-tools` marketplace entry.
|
|
802
|
+
- `CONTRIBUTING.md` — agent/command authoring conventions and the release checklist.
|
|
803
|
+
- `examples/promo-service/` — a worked example of what `/sdd-init` produces (filled-in `CLAUDE.md`,
|
|
804
|
+
`docs/PATTERNS.md`, and a completed spec).
|
|
805
|
+
|
|
806
|
+
### Changed
|
|
807
|
+
- Set the real git org across the manifests and READMEs (was a placeholder).
|
|
808
|
+
<!-- Corrected in 0.11.0: this pointed at an org that did not host the repo. -->
|
|
809
|
+
|
|
810
|
+
- Hardened the optional PreToolUse hook example into a working staged-diff secret scan (AWS keys,
|
|
811
|
+
private keys, Slack/GitHub tokens, generic `key=…` assignments) that blocks the commit.
|
|
812
|
+
|
|
813
|
+
## [0.2.1]
|
|
814
|
+
|
|
815
|
+
### Changed
|
|
816
|
+
- **Leaner agents / DRY:** collapsed the duplicated stack-detection prose (was repeated across all
|
|
817
|
+
4 agents + 3 commands) into one short "detect from the manifest, mirror the code, read the docs"
|
|
818
|
+
procedure. `coder.md` dropped ~45 lines; per-stack/DB specifics now live only in the generated
|
|
819
|
+
`docs/PATTERNS.md` (where project detail belongs), not in always-loaded agent prompts.
|
|
820
|
+
- Added a confidence convention to `PATTERNS.template.md` — mark `(inferred)` patterns so the agent
|
|
821
|
+
re-checks them against code; never invent a convention to fill a section.
|
|
822
|
+
- Clarified `/code` vs `/spec` boundary and noted `/code-review`/`/security-review` are built-in.
|
|
823
|
+
|
|
824
|
+
### Fixed
|
|
825
|
+
- Duplicate step number in `/sdd-init`; a Spring-specific `Feign` reference in the stack-neutral
|
|
826
|
+
knowledge layer.
|
|
827
|
+
|
|
828
|
+
## [0.2.0]
|
|
829
|
+
|
|
830
|
+
### Added
|
|
831
|
+
- `/code <task>` — one-shot coding command via the `coder` agent.
|
|
832
|
+
- `/sdd-refresh` — re-learn the project and update the knowledge files after the code drifts.
|
|
833
|
+
- `docs/PATTERNS.md` — learned "house style" memory, generated by `/sdd-init` and read by all agents.
|
|
834
|
+
- Optional `templates/hooks/settings.hooks.example.json` — opt-in post-edit/lint/test/secret hooks.
|
|
835
|
+
- Git & PR workflow section in the shared CLAUDE.md fragment.
|
|
836
|
+
|
|
837
|
+
### Changed
|
|
838
|
+
- Agents and commands are now **stack-aware for any language** (Java, React, Node/Express/NestJS,
|
|
839
|
+
Python, Go, Ruby, .NET, …) and any database (MySQL, PostgreSQL, MongoDB, …) — detect the
|
|
840
|
+
manifest/commands and mirror the project's conventions instead of assuming Spring Boot.
|
|
841
|
+
- `/sdd-init` is now **learn-first**: it studies the codebase and generates `CLAUDE.md`,
|
|
842
|
+
`docs/PATTERNS.md`, and `docs/ARCHITECTURE.md` from real `file:line` evidence.
|
|
843
|
+
- Spec template, architecture template, and knowledge layer made stack-neutral.
|
|
844
|
+
- Marketplace plugin `source` switched to the relative path `./sdd-toolkit`.
|
|
845
|
+
- **Token/memory optimization:** tiered knowledge layer (CLAUDE.md = thin index that links, not
|
|
846
|
+
inlines; PATTERNS/ARCHITECTURE loaded on demand, ~200-line budgets each), `file:line` references
|
|
847
|
+
over pasted code, read file ranges not whole files, and `/sdd-refresh` now prunes/trims to budget.
|
|
848
|
+
- **Large-app mode:** sharded knowledge layer — `docs/ARCHITECTURE.md` becomes a router linking to
|
|
849
|
+
per-module `docs/architecture/<module>.md` (and `docs/patterns/<module>.md`) shards loaded on
|
|
850
|
+
demand, so each task's context is the router + only the relevant shard. `/sdd-init` generates and
|
|
851
|
+
`/sdd-refresh` updates shards per-module.
|
|
852
|
+
- **Interlinked modules (edges, not just nodes):** each shard carries a `Depends on / Used by`
|
|
853
|
+
header, the router holds a module **contract index** (shared events/APIs/types/tables →
|
|
854
|
+
producers/consumers), and the agent loads the bounded **1-hop dependency closure** (target shard +
|
|
855
|
+
neighbors' contract sections). Optional always-loaded `docs/architecture/_core.md` for heavily
|
|
856
|
+
shared contracts; tightly-coupled specs are sequenced, not parallelized.
|
|
857
|
+
|
|
858
|
+
## [0.1.0]
|
|
859
|
+
- Initial release: `coder` + `sdd-spec-author`/`sdd-developer`/`sdd-reviewer` agents,
|
|
860
|
+
`/spec`, `/spec-build`, `/sdd-init`, and the spec/docs templates (publisher-service focused).
|