All notable changes to specflow. Format based on Keep a Changelog; this project follows semantic versioning.
takeover— continue inherited branches, pull requests, worktrees, and handoffs from measured repository state while preserving contributor credit and concurrent work.file-pr— publish authorized PRs with a concise problem-first description, behavior-level solution, and evidence tied to the final head.pr-maintenance— assess an existing PR asCURRENT,REWORK, orSUPERSEDED; update or monitor it only under explicit authorization and current-head evidence.
guide,spec-execution, andsession-handoffnow route and preserve the state required for inherited work, authorized PR publication, and current-head PR maintenance.
review-loop— an explicit, bounded review-and-fix loop for consequential changes. It captures a shared candidate snapshot, coordinates read-only independent reviewers, keeps an evidence-backed finding ledger, and re-reviews only the delta until the final behavior diff converges or a real limitation remains visible.
spec-executionnow recommendsreview-loopafter initial review when authorization, concurrency, data integrity, or user-requested convergence merits it; ordinary changes retain the lightweightcode-reviewpath.
0.10.0 — 2026-10-25
- Contributor rules now have one canonical
AGENTS.mdwith a Claude project-rule pointer. The obsolete rootCLAUDE.mdis removed; it was repository context, never loaded as installed plugin context. - Verification follows the change, affected consumers, authorized environment and repository policy. Healthy repos no longer require a Specflow marker; tooling setup remains an explicit task.
- Accepted decisions and authorization persist between steps. Specs and tickets scale with risk; routine seam choices, long story lists and repeated approvals are no longer mandatory.
- Tests may evolve with accepted behavior changes without masking regressions. Expected TDD reds are distinct from repair failures; diagnosis and progress replace the generic three-failure counter.
- Reviews cover explicit committed, staged or working-tree candidates, including relevant new files, with fixed snapshots and affected revalidation after edits. Reviewer count and parallel work follow risk and ownership instead of fixed rules.
- Authorized implementers can correct an accepted specification defect in place and clear its marker after verification. Existing
returned/Returned:tokens and source identities remain compatible. - Handoffs retain the last usable checkpoint until superseded, preserving authorization, dirty-work limitations, evidence and the next action. Ordinary temporary reasoning no longer requires an ADR.
- Existing generated project instructions remain authoritative until explicitly migrated; the update does not rewrite them or install global skills.
- Development linking preserves foreign and dangling symlinks as well as real files/directories; links to the current checkout remain untouched. Explicit target directories support isolated use and verification.
- Documentation drift around router triggers, tracker capabilities, review scope and artifact ownership; removed a personal absolute validator path.
- ADR 0009 and ADR 0010, superseding rigid returned-source ownership and disposable handoff policy while retaining their history.
- Focused regression checks for the actual link helper and a bounded behavioral validation guide. Structural/protocol checks remain distinct from live agent/tracker evidence.
- Public Codex plugin marketplace. Anyone can install specflow from GitHub with
codex plugin marketplace add assisjp/specflow --ref mainfollowed bycodex plugin add specflow@specflow. The plugin packages the existing skills from the repository root, so there is one source of truth for Codex and Claude Code.
- Codex compatibility. Promoted skills now include portable
agents/openai.yamlmetadata, with the deliberate flow steps explicitly invoked in Codex and utility skills still eligible for implicit invocation. Codex can discover the same source through.agents/skillsor~/.agents/skills;scripts/link-skills.shlinks the latter alongside the existing Claude Code directory. AGENTS.mdas the Codex repository entry point, with the shared conventions maintained inCLAUDE.md.
- Existing Claude-specific
SKILL.mdfrontmatter remains intact. Codex-compatible metadata mirrors its invocation behavior, so both harnesses preserve their native invocation experience.
- 0.9.12 installed a reader of "done" that no backend produced — the 0.9.1 class, committed by the very fix meant to close a gap. Step 2 began requiring a blocker to be merged, and nothing said how that is observed: step 9 opened a PR "referencing the issue", a loose mention no query can follow back; locally there is no PR at all, and a ticket's status field and checkboxes are written once by
to-ticketsand updated by nobody. The live run passed only because the open PR was in plain sight. Step 2 now names the observable per backend — tracker: the blocker's issue closed and its closing PR merged; local: the blocker's behaviour passing against your base — and stops to ask when neither can be seen. Step 9 writesCloses #Nso the linkage the reader needs is created by the writer. No new state, no new owner: both hang off observables that already exist. - The write-back rule spoke for one backend only. 0.9.11 said to write a settled ambiguity back into the source and offered "a comment recording the decision" — which exists on a tracker and nowhere else. Locally the source is a file whose body
CLAUDE.mdassigns to its publisher, so the instruction was unexecutable: either violate ownership or skip the write and lose the decision to the conversation. Ownership now governs the body explicitly, andspec-executionmay append a dated implementation note — the local stand-in for an issue comment, since appending clobbers nothing the publisher wrote. A permission, not a new artifact. repo-hardeningsaid to commit its work and not what to put in the commit. In a repo that was already dirty — the case its own Phase 4 exists for — a blanket stage swallows the user's uncommitted work into the "isolated" hardening commit, silently. It now stages by path and reports a tree it found dirty.- The eval's reader guard accepted a mention in place of an instruction. Prose reading "sources sometimes carry a
Returned:line" kept the token inside step 2 and passed, though nothing was being checked — the same shape as a clearer satisfied by its own heading (0.9.7). The guard now requires a reading verb near the token, word-bounded soreadcannot hide insidealready. Step 2 is the most-edited file in the repo, which is where this mattered.
- §8 states that a committed evidence artifact belongs in the diff it evidences, so the Standards axis does not report it as scope creep.
- Step 9 had no path for a repository with no remote — the twin of the gap 0.9.14 closed one step earlier. Evidence got a home when there is no tracker; delivery did not, and still said "push to the spec's branch, open a PR" unconditionally. On a live run in a remote-less repo the model did the right thing (it did not push) and then justified it with a fact it had not measured: "the remote is still at 55272ec, behind local master" — there was no remote at all. It was the second such claim in that repo; the first was "master does not have the feature yet" after the branch had already been merged. Both sent the reader to do work that was impossible or already done. The improvisation is the symptom; the missing branch in the contract is the cause. Step 9 now says:
git remote -vdecides, deliver locally by naming the branch and commits, report only remote state just measured — and measure any repo state in the step 10 report at report time rather than recalling it, because the tree moved while you were working in it.
- Step 1 could have accepted a global
CLAUDE.mdas the repo's contract. It said to read the block from "AGENTS.md, orCLAUDE.mdif that is where the harness loads it" — and a user-levelCLAUDE.mdis precisely where the harness loads it. Those files routinely carry generic instructions ("runnpm run lint", "ensurenpm testpasses") for commands that do not exist in the repo under work, so extracting them yields a contract that cannot run: the improvisation step 1 exists to prevent, wearing the costume of a contract. Confirmed live on a bare repo whose only tooling was absent while the machine's globalCLAUDE.mdnamed all four commands; the run escaped it by judgement, not by rule, which is the gap. The block must now be tracked in the repository —git ls-filesdecides, notfind.
- Evidence had nowhere to live without a tracker. Step 6 said to save it "where the PR can reference it" — and with no remote there is no PR, so the location was undefined. On a live no-tracker run the model invented
docs/evidence/<slug>.mdand committed it: a good choice, and entirely its own. The ownership list inCLAUDE.mdnames a home for specs, tickets, the glossary, ADRs, the verification block and.scratch/, and forgot the one artifact the evidence gate exists to produce. Now stated: with no tracker,docs/evidence/<source-slug>.md, committed, durable for the same reason a spec is (ADR 0006) — whoever reads the change months later wants the proof the behaviour appeared, not just the diff claiming it. - Evidence could be captured through a lying instrument. On the same run, recapturing evidence for the error paths,
wc -con a redirected file reported zero bytes for a file with contents — a shell filter sitting between the command and its output. The model caught it, stopped trusting shell measurement and read the child process's stdout and stderr directly. Step 6 now says to do that by default and to record the capture method in the artifact: a byte count that disagrees with the file means the instrument is lying, not the app, and evidence whose capture you cannot vouch for is not evidence.
to-specpublished a spec it already knew was not implementable. Its traceability rule says an untraceable claim is cut or turned into an open question — and on a live run it did exactly that, recording honestly in Further Notes that one decision had never been made. Then it declared the spec ready and namedspec-executionas the next step. But that open question left three of ten user stories with no verifiable acceptance criterion, sospec-executionread it at step 2, refused, marked the specReturned: spec-defectand handed it straight back — a full execution round spent learning what the author knew while writing. The rule said what to do with an open question and nothing about what an open question costs. It now distinguishes the two: one that records context is publishable, one that leaves a story unbuildable and untestable means the spec is not ready, and the next step isgrillto settle it. Found by the flow itself —spec-executionnamed the upstream cause in its own report.
spec-executionnever read the blocking edgesto-ticketswrites. Every ticket carriesBlocked by: #N, andto-ticketsstates the rule beside it — work the frontier, tickets whose blockers are all done.spec-executionconsumes those tickets and had no matching rule, so on a live run it read a ticket sayingBlocked by: #3, with #3 still open and its PR unmerged, and implemented anyway. It handled the consequence sensibly — based the branch on the blocker's branch and reported the merge order — but the result is a PR whose base is another open PR: not independently reviewable, which is the single thing this skill promises, and whose base moves if that review changes anything.guidehad said to wait andto-ticketshad declared the edge; the missing half was the consumer. Step 2 now checks the edges and stops on an unfinished blocker, naming which ticket to run first. Done means merged — an open PR can still change.
spec-executionstep 2 answered a result-changing ambiguity in the conversation and never wrote it back. On a live run the frontier ticket carried an unverifiable criterion ("Confirm the accepted behaviour for a Title such as 'Straße'"); step 2 correctly stopped and asked, got an answer, and implemented — leaving the criterion on the issue exactly as it was, unable ever to go green, waiting to stop the next session with the same question. Step 4 already covers "a scenario not testable as written" by marking the source, but step 2 is reached first and had no such duty, so the two rules disagreed on the same input. Step 2 now says it: write the answer back into the source, and where the ambiguity was an unverifiable criterion, rewriting it is the fix — so mark the source and hand it to the republisher. The decision-that-evaporates is the failure ADR 0008 was written against; it had survived one skill upstream of the marker.to-specended without naming the next step, and filled the gap wrongly on a live run: it pointed a 26-story, five-endpoint spec atspec-execution, which would have spent a round refusing and proposing the cut thatto-ticketsexists to make.to-specis the only thing that can judge the size of what it just wrote, so it now states whether the spec fits one reviewable PR and routes accordingly — the completion-side counterpart to the house rule that a refusal names its exit.
- README:
/reload-pluginsafter updating. Amarketplace updaterefreshes the disk, but a session resolves its typed slash commands once at start — so an open session keeps running the version it began with while model-invoked skills pick up the new one. Measured on a live run: three typed skills ran 0.9.8 while two internally-invoked ones ran 0.9.9, in the same session, after two updates. That mix matters here specifically, because the second-failure marker's setter and clearer live in different skills and must agree./reload-pluginsrefreshes the typed commands in place — measured on the same session, which went from serving 0.9.10 to 0.9.11 without restarting.
grillcould be talked into writing the feature, skipping the entire pipeline. Rule 5 said "Grilling produces alignment, not artifacts (unlessdocsis passed)" and, in the same breath, "get an explicit go before building anything" — a clause that only makes sense if building is on the table, contradicting both the rule beside it and the skill's own description ("before any code is written"). On a live run the user answered a question with "tudo", the model read it as the go, andgrill docscommittedsrc/slug.tsandtests/slug.test.ts— no spec, no ticket, no closed scope, no evidence, no review. The one thing specflow exists to prevent, reachable through the skill that opens the flow. Rule 5 now states the prohibition outright:grillnever writes source or tests however broad the go sounds,docswidens its output toCONTEXT.mdand ADRs and no further, and the "go" it waits for is the go to the next step, never a licence to build. A contradiction removed rather than a rule added.
repo-hardeningnever committed its own work, so the verification layer it installs leaked into the next feature PR. Phase 6 ended at "report what was installed", leaving config, hooks, CI, the test scaffold and the agent-context file loose in the tree — eleven files, on a real run. The nextspec-executionthen inherits a dirty tree and breaks its own closed scope (§3) and one-diff-one-concern rule (§8) by construction, whilecode-review's Standards axis reviews the hardening config as if it were feature work. The same shape as the marker bugs: the instruction exists at one end (spec-executiondemands closed scope) and the mechanism was missing at the other (nothing put the hardening into history). Its sibling publishers already got this right —to-speccommits its spec,to-ticketscommits its tickets — and the skill that writes the most files said nothing. Phase 6 now commits the hardening as one isolated commit, with a formatter reflow of pre-existing code kept as a separate one. Found by running the real pipeline against a real repo and looking atgit statusafterwards.
- The tracker half of the second-failure gate never armed on a fresh repo. Returning the source said "add a
returnedlabel to the issue" — but nothing created the label, and on a repository that has never returned a source it does not exist.gh issue edit --add-label returnedthen fails with'returned' not found(exit 1, nothing written), so the write half errors out, no marker is set, and the next session implements a spec already known to be defective. Every live exercise of this path so far ran on a repo where the label happened to exist already, which is exactly why four attempts missed it. Now the label is created first, idempotently —gh label create returned --force— with the failure mode recorded so the step is not "optimised" away. Found by running the gate against a real fresh private repo rather than reading the skill.
- The eval detected a drifted token, never a deleted role. Delete step 2's reader half, or the whole Returning the source setter, and the marker token still litters the rest of the file:
check.mjsguard #11 passed, token agreement passed, the gate was dead and CI was green. That is the 0.9.1 class — the write half existed, the read half never met it — so 0.9.6's net covered the 0.9.4 bug while leaving its predecessor open, and looked like it covered both, which is worse than no net. Five role-presence guards close it, anchored on role rather than phrasing: step 2 must still read the marker;spec-executionmust instruct the SET on both backends (identified by what it does, so the section may be retitled or moved); each clearer must instruct the CLEAR on both backends;guidemust still route a marked source togrill;to-tickets' healing mode is anchored on its own section, so a cross-reference cannot stand in for the mode. Two silent passes surfaced while building it: the clearer guard was satisfied by a section title naming the clear, and an unboundedmark\w*matched the noun "marker" throughout step 2, so the setter guard was being satisfied by the reader — the exact confusion it exists to detect. Mutation battery: 16 mutations, 14 bite; the two that pass do so correctly (a redundant token anchor into-spec, and a renamed setter heading — no false positive by design). spec-executionstep 2 could be "optimised" back into a false negative. It read the tracker marker viagh issue view, which is per-issue and therefore correct — but nothing stopped a later hand from turning it into agh issue list --label returnedfilter, andto-ticketsalready documents why that breaks: GitHub's label index lags writes by seconds. The failure is a few-second false negative — mark, read the stale index, see nothing, implement a spec already known defective. Now explicitlygh issue view <n> --json labels, per issue, with the reason attached so it stays shut.guidewas the protocol's single point of failure for token extraction. Every other gate skill anchored the marker token twice;guideanchored it once, so rephrasing one bullet would have failed CI. It now names both backends where it describes the clear — better prose, and the redundancy the other three already had.
- The eval's success line counted 15 contract guards and 8 lifecycle steps as one total. The guards read the skills' own prose and can disagree with it — that is detection. The lifecycle steps run over fixtures the eval controls, with reader and setter derived from the same extracted token; a couple cannot fail without editing a fixture. Real value as executable documentation of the local backend's semantics, but not coverage, and one total invited reading 23 units of net where there are 15. Now reported apart.
CLAUDE.md: the tracker backend's manual release checklist, once per minor in a throwaway repo. That half stays out of CI on purpose — network,ghauth, a real issue; a reliability plugin whose CI dies on GitHub API rate limits is worse than an honest gap. Step 4 (the same cycle with a ticket, where the clear belongs toto-ticketsand notto-spec) is the one tracker transition never exercised live, and is marked unskippable. What CI does pin on that side is nomenclature, not behaviour: the label token is derived from prose shared by all four gate skills and checked against the local line token, so the two backends cannot drift apart by name.
to-ticketshad the marker's clear instruction but no mode that could execute it. Step 5 told it to republish a rewritten ticket to the same issue/file so the neighbours' blocking edges survive — but the documented process is a single path: take a whole spec and slice it. An agent following it literally to heal one marked ticket would re-slice everything and move exactly the edges that paragraph forbids moving. Same shape as the 0.9.1 bug: the instruction existed at one end, the mechanism did not exist at the other, and guard #11 could not see it because the tokens were all present.to-ticketsnow opens its process with a mode selector — a single ticket carrying areturnedmarker means healing mode: rewrite that one ticket, republish to the same source, clear the marker, skip steps 1–4, touch no neighbour.spec-execution's step 2 refused without naming its exit. Step 1 already models the convention ("stop. Suggest runningrepo-hardeningfirst"); step 2 sent the user to the second-failure rule and left them there. It now names the way out: heal and republish viato-spec(spec) orto-tickets(ticket), which is what clears the marker (ADR 0008), starting from a freshgrillif the source is not yet rewritten.guiderouted a marked source togrillunconditionally, so a user who had already rewritten the spec by hand was sent through a grill they did not need, and the actual exit was never named. Now it routes by state: defect unresolved →grill; already rewritten →to-spec/to-ticketsto republish. No transition changed owner — republishing still clears, andspec-executionstill waits.tddpointed at the wrong owner of the refactor beat. "Cleanup belongs to the review stage (seecode-review)" — butspec-execution's step 7 is what executes the in-diff cleanup. The rule was not moved intotdd:tddis model-invoked and runs standalone, where no fixed point is pinned and "the diff boundary" is undefined, so a diff-phrased rule there would be non-executable. One sentence names both cases instead — in-flow, step 7; standalone, a refactor pass over what the loop touched after each green.code-review's no-sub-agent fallback promised a capability the model does not have ("clear or set aside its working context"). Replaced with honest layers: sub-agents available at all → one per axis, sequential if need be, isolation by construction; none at all → a single combined pass labelled as such. The report shapespec-executionstep 7 consumes (## Standards/## Spec, unmerged, unranked) is unchanged — only the isolation claim degrades. Itsdescriptionno longer promises parallelism as the contract.session-handoff's "three sessions" rule was a counter with nothing to count in. ADR 0002 makes the handoff ephemeral — consumed once, then dead — so no session can observe how long an item has survived. The same bug class ADR 0008 named in the marker gate. Replaced with a stateless test any single session applies unaided: a line recording a why rather than a where things stand is a decision disguised as state — promote it to an ADR now. ADR 0002 amended (not superseded; its decision is unchanged) to record the retired test and why it could not work.repo-hardening'sdescriptionended with a trigger the model can never observe (it is user-invoked). Same information, reframed for the human who actually reads it in/pluginand the README: run it beforespec-execution, which refuses to build without the block it installs.
scripts/eval-marker-protocol.mjs— a deterministic eval of the returned-marker lifecycle, wired intonpm run evaland CI. It builds a temp repo and runs the local backend end to end for both source types: clean → set → refuse-while-uncleared → clear-on-republish → release, plus regressions for the retiredReturns:token, a marker below line 1, and set-idempotency (state, not counter). The contract is extracted from the four gate skills' prose, never typed a second time, so text drift fails the eval instead of silently opening the gate — reproducing the 0.9.4 divergence makes it fail by name. Scope is deliberate: local backend only. The tracker backend needs a network and a real issue, so it stays a manual release-checklist item — an honest gap beats a flaky gate on a reliability skill. This inverts the 0.9.x pattern of discovering protocol breaks live.argument-hintonspec-execution,to-ticketsandcode-review— the three skills that always ask for their input anyway. Inert metadata; saves a round trip.- README: First feature, start to finish — the literal command sequence for a fresh install. Adoption outside the router's trigger is a README problem, not a reason to re-widen
guide(ADR 0005). CLAUDE.md: two house rules — a refusal names its exit (the conventionspec-executionstep 1 already modelled), and a docs-sync ritual, sincecheck.mjsverifies a docs page exists but not that its content matches theSKILL.md.
check.mjsguard #7 matched skill names by raw substring. Now word-boundary-aware with hyphens treated as part of the token —\balone would let a future skill namedspecmatch insidespec-execution. Theoretical today; one line.spec-executionstep 2 gained §8's ~400-line figure as an estimate, explicitly not a gate — pre-implementation sizing is imprecise and a hard gate there would produce false refusals. §8 still measures the real diff and remains the backstop.
0.9.5 — 2026-07-24
scripts/check.mjsguard #11 is now bidirectional: besides requiring the current marker tokens in every protocol skill, it fails if the retiredReturns:token survives in any of them — catching the class (old token lingering beside new) that caused the 0.9.4 bug, not just the instance. Same shape as the other bidirectional guards (#3, #6, #8).
0.9.4 — 2026-07-24
- The local (no-tracker) second-failure gate never closed.
spec-executionwrote the marker as aReturned:line but step 2 read for aReturns:line — the old counter name's residue. So off a tracker it marked the source and then failed to recognise its own mark, and the gate silently did nothing. The 4-attempt live run missed it because it was in tracker mode, where both ends use thereturnedlabel; the marker had two backends and only one was exercised. Reader aligned toReturned:, and the local backend's full lifecycle (set → refuse → refuse-while-uncleared → clear → release) is now run and passing. - Counter-era phrasing ("come back once", "a double return", "comes back twice") replaced with the state framing ADR 0008 fixed, in
spec-executionand its docs page.
scripts/check.mjsguard #11: the second-failure marker's tokens (Returned:,returned) must be identical across every skill in the protocol — setter, reader, clearers, router. The specific check for the one cross-skill protocol that exists, exactly the divergence that had already bitten; it generalises when a second protocol appears.
0.9.3 — 2026-07-24
- The gate's exit now respects the ownership split. ADR 0008 gave the clear to
to-spec, butspec-executionruns tickets on the frontier, andto-specdoes not own tickets (ADR 0006). The clear now belongs to the republisher of the source —to-specfor a spec,to-ticketsfor a ticket — each clearing only the source type it owns.to-ticketsgains the clear-on-republish instruction it was missing; ADR 0008 generalised from "to-specclears" to "the republisher clears", covering any future publisher without amendment. guideno longer says "if a spec has come back twice" — a counter's phrasing left over from before the marker became a state. It now routes togrillwhen the source carries areturnedmarker (the gate fires on the first mark), so it stops sending work to aspec-executionthat would refuse it. Fixed in the skill and its docs page.
0.9.2 — 2026-07-24
- The second-failure gate now has an exit. 0.9.1 closed write→read but nothing ever removed the marker, so a spec healed via
grillstill carriedreturnedand step 2 refused it forever — the fix could not unblock the work. Confirmed live on a real issue (rewrite the criterion, gate still refused). Nowto-specclears the marker when it republishes the rewritten spec to the same source, and that is the only clear path —spec-executionsets,to-specclears, one owner per transition (ADR 0008). Proven end-to-end on real GitHub state: set → refuse → heal+clear → release. - The marker is named for what it is: a state (
Returned: spec-defect), not aReturns: Ncounter — it is written only when the spec is the blocker, and step 2 fires on its presence, so a count was never compared to anything (ADR 0008).
- ADR 0008 (a returned spec is the same entity;
to-specclears the marker on republish).
0.9.1 — 2026-07-24
- The second-failure gate now closes its own loop. 0.9.0 taught step 2 to read the return marker but only told the second-failure section to write it — a section reached only on the second return. So the first return (at steps 2, 4, or 5) wrote nothing, and the gate read a marker that never existed. Marking is now required at every point where a source is handed back as defective (steps 2/4/5 and the rule itself), via a single canonical Returning the source action. The write half and the read half finally meet.
guide's description was over-widened in 0.9.0 into a catch-all ("any description of a coding task", "when in doubt reach for it"), against ADR 0005's own lever ("narrow, don't broaden"). It now triggers only on an explicit which-step request and states that a plain coding task (e.g. "write a function that slugs a string") must not surface it — removing the noise and the three-way contention withtdd/code-review.
0.9.0 — 2026-07-24
- The second-failure rule is now a gate, not advice. When
spec-executionreturns a spec for a defect it marks the source durably — areturnedlabel + comment on the issue, or aReturns: Nline in the local ticket/spec — and step 2 reads that marker on open and refuses to reimplement. Previously the rule relied on the human remembering there had been a first attempt, the one thing the rule exists to save them from (same durability logic as ADR 0006).
repo-hardeningPhase 3 no longer assumes formatter and linter are two separate tools. Modern Python (ruff) and Biome (JS/TS) do both in one tool; the skill now says install one-or-two by ecosystem default rather than always reaching for a second tool. Also names ecosystem-default hook managers (husky / thepre-commitframework). Found runningrepo-hardeningon a real Python repo, which also confirmed the "type-checkers have no baseline" fix (0.8.1) generalises fromtsctomypy.guide's description widened to fire on the natural phrasings of a user who does not know which skill to use ("how do I begin", "I want to add X — where do I start", "now what"), closing the model-invoked failure mode where the router stays silent because its triggers were too narrow.
0.8.4 — 2026-07-24
to-ticketsexpand→migrate→contract now states the two things that actually keep the batches green, both found running a real wide refactor: tests are call sites (a test reading the old field must migrate before contract), and expand is only non-breaking if tests assert behaviour not object shape — prefactor full-object assertions first.
0.8.3 — 2026-07-24
Found by running the flow in tracker mode on a real GitHub repo (notes-api):
to-ticketsno longer implies GitHub has native issue-blocking.gh issuecannot set issue dependencies (a Projects/preview feature), so on GitHub theBlocked by #Ntext form is the norm, not a degraded fallback — the skill now says so, and reserves "native blocking" for CLIs that actually expose it (e.g. Linear). It also warns that GitHub's label index lags creation by a few seconds, so verify freshly-created issues with a per-issue--jsonquery, not a--labelfilter.
0.8.2 — 2026-07-24
code-review§2 no longer contradicts itself. The source-finding list said "In order:" but ranked a caller-passed path second while telling you to "prefer this". The caller-passed path (whichspec-executionalways provides) is now #1, so a commit'sCloses #45cannot send the review refetching an issue when the exact file was already handed to it — the same guessing class 0.8.0 removed.repo-hardening's "format your own output" rule now covers the class, not just the instance: it says the repo's formatter, installed or adopted, so it also applies in a repo that already had a formatter (where Phase 3 installs nothing) — the alignedAGENTS.mdblock breaks Phase 6 there too.
0.8.1 — 2026-07-24
Both found by running the full flow end-to-end on a real Node/TS repo:
repo-hardeningPhase 4: the "generate a baseline" advice was linter-shaped. A type-checker liketschas no baseline mechanism — the skill now says so and points to scope-restrict or fix-in-an-isolated-commit instead of sending the agent to look for a baseline that does not exist.repo-hardeningPhase 5: the skill now formats the files it just wrote (theAGENTS.mdblock, any configs). A freshly-installed formatter reflows an aligned block, so without this the Phase 6 check failed on the very file the skill created — the skill's output must pass the skill's own gate.
0.8.0 — 2026-07-24
code-reviewnow finds the ticket as the spec. ADR 0006 made tickets a durable per-PR spec underdocs/tickets/, butcode-reviewonly searcheddocs/specs/— so in no-tracker mode the Spec axis silently skipped every locally-ticketed PR. It now also searchesdocs/tickets/<slug>/, andspec-executionpasses the exact spec/ticket path tocode-reviewso the source is never guessed.spec-executionstep 2 acknowledges the source may be a ticket.
- ADR 0007 (evidence before review) — moves the reasoning that was in the 0.7.0 CHANGELOG entry into a proper decision record, per the "decisions go in an ADR" boundary. The 0.7.0 entry now points to it.
scripts/check.mjssteps renumbered sequentially (was… 7, 7b, 9, 8). Cosmetic, but drift is drift.
0.7.0 — 2026-07-24
- Evidence is produced before review, not after.
spec-executionreorders its steps so the evidence artifact exists beforecode-reviewruns, and the review's Spec axis checks it against the acceptance criteria. Rationale in ADR 0007. repo-hardeningPhase 6 now executes theRuncommand (unlessn/a) to confirm the app comes up — the evidence gate's contract was the one line in the block that was never tested, and it would first run mid-spec-executionat the worst time.
scripts/check.mjsguard #7b: no orphan docs pages (everydocs/<bucket>/<name>.mdmaps to a promoted skill) — the reverse direction of the existing docs check.scripts/check.mjsguard #9: everyADR NNNNcited in a skill or doc must resolve to a file indocs/adr/.
0.6.0 — 2026-07-24
- Durable local artifacts are versioned, not scratch. With no tracker,
to-specwrites the spec todocs/specs/<slug>.mdandto-ticketswrites tickets todocs/tickets/<slug>/, both committed — instead of.scratch/, which was ephemeral and git-ignored, so specs/tickets vanished on a fresh clone..scratch/is now exclusivelysession-handoff's.code-reviewlooks for the spec in one place (docs/specs/). See ADR 0006. code-reviewnow degrades gracefully across harnesses: parallel sub-agents where available, otherwise the two axes run sequentially with clean context between them — the isolation guarantee no longer depends on a Claude Code-specific feature (consistent with ADR 0003's portability stance).
spec-executionnow assigns the refactor beat an owner: a code smell inside the diff is in scope (clean it up — this is red-green-refactor's third beat); a smell outside the diff is out of scope (record it, don't fix it). Closes the gap where a smell in new code belonged to no one.scripts/check.mjsguard #8: the current plugin version must have aCHANGELOG.mdentry.- ADR 0006 (durable artifacts versioned under
docs/, not.scratch/).
0.5.0 — 2026-07-24
guide(the router) is now model-invoked, so it surfaces when a user describes a task without naming a skill — the situation it exists for — instead of being reachable only by those who already know to type it. See ADR 0005.- Every general reference to the verification-block location now reads "
AGENTS.mdorCLAUDE.md" (glossary, ownership rule, README, skills, docs), consistent with ADR 0003. Previously six files still hard-codedAGENTS.md.
scripts/check.mjsnow enforces the invocation contract (frontmatter invocation mode must match the README User-invoked / Model-invoked grouping) and router coverage (every promoted skill exceptguidemust appear inguide/SKILL.md). Thedomain-modelingregression can no longer return silently.- CI now also runs
claude plugin validate . --strictas a gate, not just an instruction. - ADR 0005 (the router is model-invoked).
- Git tags for all releases (
v0.1.0…v0.5.0), so the CHANGELOG links resolve.
0.4.1 — 2026-07-24
link-skills.shno longer destroys a real directory or file at a target path — it refuses to overwrite anything that is not its own symlink, and reports skips. Prevents data loss for users who already have a realtdd/code-reviewskill dir.domain-modelingis now model-invoked, sogrill docscan actually reach it (it was user-invoked and unreachable by another skill). See ADR 0004.
repo-hardeningwrites the verification block to the harness's auto-loaded context file (AGENTS.mdorCLAUDE.md), with a pointer when both exist, instead of hard-codingAGENTS.md. See ADR 0003.- The verification block gains a
Run:command so the evidence gate has a contract;spec-executionuses it instead of guessing a dev-server command.
- ADR 0003 (agent-context file selection) and ADR 0004 (utility skills model-invoked, ambient triggering accepted).
0.4.0 — 2026-07-24
guide— the router skill: describe a task, get the one skill to run now and why.scripts/check.mjs— zero-dependency consistency check enforcing the CLAUDE.md invariants (manifest/version sync, plugin↔disk↔README↔docs wiring, promoted vs non-promoted rules).- CI workflow (
.github/workflows/ci.yml) running the consistency check on every push and PR. npm run checkscript.
0.3.0 — 2026-07-24
- Phase 3 — scale & continuity:
to-tickets(slice a spec into dependency-ordered tracer-bullet tickets) andsession-handoff(ephemeral session handoff with git state,.scratch/+ gitignore guarantee, state-not-decisions rule).
0.2.0 — 2026-07-24
- Phase 2 — execution:
repo-hardening(deterministic verification layer +AGENTS.mdblock),spec-execution(one spec → one reviewable PR with closed scope and evidence),tdd(red → green loop reference),code-review(two-axis Standards + Spec review).
0.1.0 — 2026-07-24
- Phase 1 — spec pipeline:
grill(relentless interview with contradiction rule, priority lens, structured choices, decision-log output),domain-modeling(glossary + ADR discipline),to-spec(decision log → published spec). - Plugin and marketplace manifests, per-skill docs,
CONTEXT.mdglossary, ADR 0001 (own self-contained rewrite) and ADR 0002 (ephemeral handoff), andscripts/link-skills.sh.