v1.3.0
Release-tooling and CI hardening. Adds the /sd:release command (10th), a single-command repo invariant validator with a Windows + Ubuntu CI matrix, an uninstaller, and a batch of command/agent refinements.
Added
/sd:releasecommand (10th command) - generates release notes from completed specs: collects every spec indonestatus (feature / bug / refactor / perf; RCA excluded), groups them into Keep-a-Changelog sections (FEAT -> Added, BUG -> Fixed, REF/PERF -> Changed) under an inferred SemVer heading (any feature -> minor bump, else patch; major never auto-inferred), then transitions eachdone -> archived. One hard gate previews the notes and the archive plan before any write;--dry-runstops before writing. Pure file ops, no subagent (mirrors/sd:spec). Gives thedone(merged, unshipped) vsarchived(shipped) states a concrete meaning.scripts/validate.ps1+scripts/validate.sh- one command that runs every documented engine invariant: pure-ASCII scan of*.ps1,bash -non*.sh, hook-pair parity, agentmodel:alias-only check, install-target file counts (real install to a temp base), and a non-empty[Unreleased]CHANGELOG gate. Exit 1 on any failure..github/workflows/ci.yml- runsvalidateon push/PR across a Windows + Ubuntu matrix, plus an install -> uninstall round-trip per theCLAUDE.mdsandbox recipe.install/uninstall.ps1+install/uninstall.sh- removes the five<base>/<area>/sd/directories with dry-run preview, confirmation prompt (-Force/--forceto skip), and per-project cleanup reminders (.claude/settings.jsonhook wiring,.claude/.hookstate/).
Changed
scripts/validate.{ps1,sh}Check 6 now treats an empty[Unreleased]section as passing when the section immediately below it is a dated[x.y.z] - <date>release heading (the freshly cut version), so a clean post-release CHANGELOG no longer fails CI. A non-release-state empty[Unreleased]still fails, preserving the "every PR adds a changelog line" invariant./sd:perfGate 6 now structurally refuses a no-measurable-gain "keep" instead of merely warning about it in prose. The gate branches on the noise check: a measurable improvement still offerskeep/revert, but a within-noise result defaults torevertand allowskeeponly as an explicit logged constitution exception (decisionkept (exception)+ a reason recorded to05-retro.md). With no reason supplied, the change is reverted.docs/architecture.mdgains two reference sections: a "Command -> agent routing" tree showing the subagent fan-out per command (and the three file-ops commands that invoke none), and an "Artifact ownership" table mapping each.specs/<ID>/file to its producing phase/agent and downstream readers. Consolidates routing/ownership that previously lived only in scattered command files./sd:setupQ1 and thesd-spec-architectticket protocol now state explicitly that automatic ticket-context fetch is JIRA-only: GitHub Issues and Linear are still recorded as the project tracker (for prompt-hook ID recognition), but their ticket content is not auto-fetched - paste it into the prompt instead. The ticket snapshot protocol is documented as JIRA-specific. Closes the silent degradation where non-JIRA projects got no ticket fetch and no explanation.
Fixed
/sd:spec statusnow spells out the illegal-transition refusal instead of the vague "REFUSED with explanation": it prints the current state, the requested state, the valid next state(s) from the state machine, and the shortest legal path to the requested state when reachable (e.g.draft -> doneis rejected with the hintdraft -> approved -> in-progress -> done). No file is mutated on refusal./sd:bugPhase 3 no longer assumes a confirmed root cause always arrives. The investigation loop previously said "Continue until one is CONFIRMED" with no exit, so a bug whose every hypothesis is rejected/inconclusive had no defined stopping point. Added Gate 3a (hypothesis tree exhausted): the loop now terminates on a CONFIRMED hypothesis OR an exhausted tree, and the exhausted case STOPs and asks the user to re-enumerate (with new evidence), add observability, or abort as "root cause not found" - never guessing a fix from an unconfirmed tree.install/install.shmarked executable (mode100755, matchinguninstall.sh); it was100644, so the documented./install/install.shinvocation failed with "Permission denied" on a fresh Linux checkout. Surfaced by the new CI round-trip.install/README.md: total file count corrected (21 -> 32),skills/sd/added to the layout tree, install table, and manual uninstall commands (skills were missed since 1.1.0), and the-Prefix/--prefixoption documented.