Releases: SanderMuller/boost-skills
Release list
v2.24.0
A conventions slot for projects that mandate a label on every PR. Optional and additive — leave it out and nothing changes.
Added
-
pr.labels— a configurable mandatory-PR-label policy forpull-requests. Some organisations require every PR to carry exactly one label from a fixed vocabulary, chosen by a question the diff cannot answer: who wrote the first working version, which change class this is, which compliance category applies. There was no slot for that —praccepted onlytitle_format,template_path,gatesandrisk, and rejects unknown keys, so the policy could not even be forward-declared. The remaining option was the guideline layer, which is compiled intoCLAUDE.md/AGENTS.mdand loaded in every session, so a rule that only matters when a PR is created cost tokens on every unrelated task.Declared in
boost.php, the policy renders inside thepull-requestsskill instead, where it is read only when that skill activates:'pr' => [ 'labels' => [ 'require_exactly_one' => true, // false ⇒ at most one 'exempt_bot_authors' => true, // skip for Dependabot & friends 'rule' => 'Who wrote the first working version of the main change?', 'rule_doc' => 'docs/pr-label-policy.md', // optional prose 'options' => [ ['name' => 'Label A', 'when' => 'criterion for A'], ['name' => 'Label B', 'when' => 'criterion for B', 'on_doubt' => true], ], ], ],
The slot carries the mechanism only. Label names, the deciding question, and the policy prose are yours — no vocabulary and no semantics are fixed by the package, and
optionshas no mandated length beyond needing at least one entry.The skill applies the
nameverbatim. These vocabularies are usually aggregated outside the repo, where a translated or re-cased name does not fail loudly; it just stops counting, and the repo drops out of the aggregation unnoticed.How the label is decided: the agent answers
rulefrom first-hand knowledge when the work happened in the session, treats repository evidence (commit history, trailers, the diff) as an input rather than an answer when the branch predates it, and asks the author otherwise — batched into the existing pre-PRAskUserQuestioncall alongside the risk and description-direction questions.on_doubtmarks the option an uncertain author falls back to; the agent may not use it to skip asking. A resolved label reaches the PR viagh pr create --label.The package applies the label, it does not enforce it. Nothing here blocks an unlabelled PR — add a CI check on the PR event if you need a hard gate.
-
final-verification-reviewreports the label policy in its closeout check. A configured mandate is now visible before the PR exists rather than at creation time. An unresolved label is a note, since the pre-PR question resolves it; only a config that cannot be satisfied — an emptyoptionslist, or several options claimingon_doubt— is reported as blocking.
Notes
- Absent ⇒ no behaviour change. With no
pr.labelsdeclared, both skills render an explicit no-op and there is no label step. Existing configs are unaffected. - No
schema-versionbump. This is additive to v1;schema-versionstays1. - Orthogonal to
pr.risk. A risk tier's ownlabelis routing metadata applied by tier score;pr.labelsis an author-declared policy. Declare either, both, or neither — with both, a PR carries both labels.
Full Changelog: 2.23.1...2.24.0
v2.23.1
Fixes four ways the dangling-symbols.sh companion introduced in 2.23.0 could report a clean sweep on a merge that had a real dangling reference. If you are on 2.23.0, upgrade — a check that silently passes is worse than no check, because resolve-conflicts tells you to trust its result.
Fixed
- The sweep no longer depends on the reader's git configuration. It parsed git's human-facing output while assuming defaults, but that output is shaped by settings the script neither set nor inspected. Four of them made it print
No dangling referencesand exit0against a repository that provably had one:grep.patternType=extended— the word-boundary\bis a GNU regex extension that matches nothing under ERE, so every symbol lookup came back empty. The lookup now usesgit grep -w -F:-wis a git option rather than a regex feature, and-Ftreats the symbol as the literal identifier it is. Verified against thebasic,extended,fixedandperlpattern types.color.diff=always/color.ui=always— ANSI escapes prefixed every line, so the^-and^+matching that finds removed declarations stopped working. Closed with--no-color.diff.external, and theGIT_EXTERNAL_DIFFenvironment variable — an external driver replaced the diff output entirely. Closed with--no-ext-diff.- A
textconvdriver bound through.gitattributes— content was rewritten before diffing, so a symbol could be transformed out of the diff. Closed with--no-textconv.
- A failed sweep now fails loudly instead of reporting success.
diewas being called from inside a pipeline subshell, whereexitterminates only that subshell; the script printed its error and then fell through toNo dangling referenceswith exit0. Both diffs are now collected in the main shell, so a git failure exits2. resolve-conflictsno longer falls through to the commit phase on a fast-forward. The fast-forward outcome noted that nothing needed verifying but omitted the explicit stop its sibling outcome carries, leaving a path that reached the commit phase with an empty tree.
Full Changelog: 2.23.0...2.23.1
v2.23.0
resolve-conflicts now owns the whole merge rather than just the conflicted parts of it, and verifies the cases git reports as clean. Every git behaviour below was checked against real repositories before being written down; two claims the skill previously made turned out to be wrong.
Added
- Cross-side consistency check in
resolve-conflicts, with a shipped companion. A merge can combine both sides cleanly and still leave code that no longer agrees with itself — one side renames a declaration while the other adds a reference to the old name. Git reports no conflict, and a diff against either side looks exactly as it should, because the removal and the stale reference never appear in the same comparison. The newscripts/dangling-symbols.shcompanion sweeps both directions (they removed something you call, and you removed something they call) and reports surviving references. Retarget it at any language with--keywords;--helpdocuments the rest. - Clean-tree preflight. A dirty tree does not reliably stop a merge: git aborts only when the incoming change would overwrite the dirty file, so unrelated work-in-progress otherwise survives into the verification diffs with nothing marking it as unrelated. Untracked files stay excluded from the gate — they never reach a diff — but now carry their own documented abort path, since an incoming file landing on an untracked path stops the merge outright.
bash -nsyntax gate for shipped.shcompanions, mirroring the existingnode --checkpath for.mjsassets.
Changed
resolve-conflictsmerges with--no-commit. A conflict-free merge previously committed itself before any of the prescribed verification ran, leaving a failed check fixable only by amending or resetting. Conflicted and clean merges now behave identically: the merge stays staged until the commit phase. Fast-forwards are unaffected and need no verification.- Marker-less conflicts are handled. Modify/delete and rename/delete conflicts (
DU/UD) carry no<<<<<<<markers — git leaves the surviving side's content in place, so deciding what is left to resolve by grepping for markers skips those files entirely while they look finished. Conflicts are now enumerated by status code, with the opposite side read throughgit show :N:. - Failing tests are baselined against both parents. Red on your branch was previously enough to call a failure pre-existing and move on. But a test red on your side may have been fixed on the incoming one, in which case a red result after the merge means the resolution dropped that fix — the exact dropped-functionality bug the skill exists to prevent. All four ours/theirs combinations now have a verdict.
- Verification split by the question it answers. "Did the resolution keep both sides?" (a diff) and "do those changes still agree with each other?" (the sweep and the test suite) are separate checks, and the second runs even when git reported no conflict.
pull-requests,pr-review-feedback, andjira-reworkroute their whole base-sync merge throughresolve-conflicts, not just the conflicted case. Each previously restated the post-merge verification itself, precisely because a clean merge never reached the skill. All three now declareboost-requires: resolve-conflicts.
Fixed
merge-treeexit taxonomy inresolve-conflicts. Unrelated histories exit128withfatal: refusing to merge unrelated histories, not exit1with thenot something we can mergemessage the skill attributed to them. Exit128is now documented as its own case, covering both that and the rejected--quiet+--name-onlycombination.
Full Changelog: 2.22.0...2.23.0
v2.22.0
Two review-quality disciplines: trace behavior claims to real code before writing them, and check what was built against what was actually required.
Added
- "Trace, Don't Assume" in the verification-before-completion guideline (so it applies everywhere, via
CLAUDE.md/AGENTS.md): a claim about how the code currently behaves — a root cause, an existing mechanism, present behavior — must be traced to real code or a runtime observation before it's written into a spec, PR, commit, review, issue, or comment, and no illustrative example may be invented. Intended behavior a spec proposes as a requirement is exempt. Stops one unverified guess from seeding a whole ticket's context and tests on a false premise. - Conformance & scope check in
code-review— fetch the real requirement (the spec's goals, technical sections, and edge cases; un-superseded linked-issue criteria; or the task itself), then verdict each requirement requirement-down (Met / Partial / Unmet), and scope-check for implied requirements, unrequested extras, silent interpretations, and side effects. The diff shows what was built, never what was forgotten.
Changed
implement-specnow walks the requirements before final verification — task checkboxes track tasks done, not requirements met, so a required behaviour no task mapped to is otherwise never caught. It verifies each requirement against real code, then runs the full quality gate last so that gate covers anything the walk changed.
Full Changelog: 2.21.0...2.22.0
v2.21.0
Added
clean-specsskill (command-only,/clean-specs) — a post-merge net that removes spec files whose work is fully shipped: every task box checked and a title/branch-matched, un-reverted merge commit that is an ancestor of the base branch. Conservative by design — it leans toward keeping a spec on any ambiguity, reports and asks for confirmation before deleting, re-checks eligibility against fresh state, and ships the removal as a reviewable PR.
Changed
pull-requestsnow removes the implemented spec as a detect-and-verify step, not a from-memory delete. It finds the branch's spec from the diff against the base, removes it, and verifies no unrelated spec was swept in by a broadgit add -A— closing the path by which implemented specs reached the base branch. Unrelated specs that were swept in are restored without discarding local content.implement-speccleanup defers spec removal to that step instead of hand-deleting, and points at/clean-specsas the post-merge backstop.clarify,write-spec, andimplement-specnow delegate multi-file research sweeps to a read-only research subagent, keeping the main working context small on research-heavy flows.
Full Changelog: 2.20.0...2.21.0
v2.20.0
Added
clarifyskill — the shared questioning core: code-first exploration,
bisect-to-intent, fuzzy-term sharpening, scenario stress-tests, and an
assumptions audit. Usable standalone (/clarify) or as the base other skills
build on.promptimizeskill — turns a rough prompt into one optimized,
model-agnostic prompt and returns only the prompt. Builds onclarify.- Eye-verify harness for
frontend-quality— a shippedscripts/lib.mjs
helper library (createChecker,capturePageIssues,withFailedRoute) and a
references/eye-verify.mdcoverage-contract guide, so a project gets
browser-verification plumbing without building its own.console.mjsgained an
--axeaccessibility/contrast pass, screen-reader-attribute leak scanning, and
application-request (xhr/fetch) failure gating. - Dependency-aware spec workflow —
write-specphases now declare an
immutableIDandDepends:edges;implement-speccomputes each ready
"wave" and can implement independent phases in parallel under an explicit
opt-in, with write-disjoint and DAG-validation safeguards. Specs without the
new metadata fall back to the existing sequential behaviour.
Changed
interviewnow builds onclarify(declaresboost-requires: clarify) —
the grilling disciplines live in one place instead of being duplicated across
skills.migration-squashis now invoke-only (disable-model-invocation: true).
It no longer auto-activates on incidental mentions of migrations or
schema:dump; run it explicitly (/migration-squash) or by directly asking
for a squash. This matches its destructive nature — a squash deletes migration
files.
Internal
validate-skills.phpnow runsnode --checkover every shipped
*/scripts/*.mjscompanion asset, not only the codex-review wrapper.- Documented the
boost-requiresskill-dependency system in the README.
Full Changelog: 2.19.0...2.20.0
v2.19.0
Activates the skill dependencies declared in 2.18.0. That release shipped the
metadata.boost-requires declarations but they were inert on the engine
available at the time; boost-core 1.4.0 resolves them, so this release raises
the floor to require it.
Changed
- Requires
sandermuller/boost-core ^1.4(raised from^1.3).
boost-core 1.4.0resolvesmetadata.boost-requires: whenever a skill ships,
every skill it hands off to ships too, and a required skill that a consumer's
tags would otherwise drop is rescued in (transitively, surfaced as an INFO
diagnostic). Pinning the floor here makes the co-shipping guarantee real for
every consumer instead of best-effort.1.4.0is additive and backward
compatible, and the catalog already required^1.3, so the step is small.
Authoring guidance forboost-requireslives inboost-core's README.
No skill content changed — the declarations themselves shipped in 2.18.0.
Full Changelog: 2.18.0...2.19.0
v2.18.0
Six skills now declare their hard dependencies in frontmatter, dogfooding the
skill-dependency system boost-core is building. Once that engine lands,
selecting a skill will co-ship every skill it hands off to — a dependency the
tag filter would otherwise drop gets rescued, so a skill never delegates to
something that isn't there. This release ships the declarations only: they are
inert under the current engine (boost-core ^1.3 ignores the unknown
metadata.boost-requires key, verified against the shipped engine), so it is
safe ahead of the resolver and changes nothing for consumers until they run a
dependency-aware boost-core. Everything is additive — no skill removed or
renamed.
Added
-
Skill dependency declarations (
metadata.boost-requires). Space-delimited
bare skill names, mirroringboost-tags. Six skills declare their hard
hand-offs:interview→write-specbug-fixing→test-writingevaluate→code-review codex-reviewfinal-verification-review→evaluate codex-review pull-requestspre-release→readme release-notes upgradingjira-rework→jira-updates
Only hard hand-offs — where a skill's flow invokes another skill — are
declared. Conditional and routing references stay undeclared on purpose:
jira-create/jira-updatesonly cross-reference each other for routing,
and capability-gated mentions likebackend-quality/frontend-qualityare
scoped by tags, so declaring them would rescue tooling into projects that do
not want it.
The declarations were derived from a body-reference audit of the catalog and
validated against boost-core's ship-closure design, then dogfooded through
this repository's own review flow before shipping.
Full Changelog: 2.17.0...2.18.0
v2.17.0
Added
- A shipped eye-verify harness (
frontend-quality/scripts/, emitted asboost-core1.3
companion assets). Three framework-agnostic tools so a project stops rebuilding the plumbing:screenshot.mjs— navigate a running app, optionally crop to a--selectorwith ≥15px
padding (clamped to the page), save a PNG.console.mjs— record console errors/warnings, uncaught page errors, and failed requests;
--text-patternscans rendered text for a project-supplied leak regex (e.g. untranslated-key
markers);--fail-on-errorgates.auth-capture.mjs— the portable auth seam: open a headed browser, log in by hand, save a
PlaywrightstorageStatethe other two reuse via--storage-state. Knows nothing about any
login form, so it works for any app.
Playwright is a project prerequisite (npm i -D playwright && npx playwright install chromium);
each tool fails fast with that hint if it's absent. What stays per-app is only genuinely
app-specific glue (programmatic SSO login, data seeding, domain drivers).
- Catalog-consistency CI gate (
.github/validate-catalog.php). The format validator never
checked that the catalog's own tables agree with what ships; the new gate enforces README
Skills/Guidelines tags vs each skill'smetadata.boost-tags, skill/guideline inventory,
the guideline tag sidecar, the documented tag vocabulary,boost:convtokens vs real
conventions-schema.jsonslots, andschema-requiredvs conv usage. - On-demand design-verification reference (
frontend-quality/references/design-verification.md).
The full per-element scoring rubric — attributes incl. shadow/elevation, line-height,
letter-spacing, tap-area; the "undocumented difference is a finding, not a deviation" rule;
image-sampling to the nearest project token when there's no token spec; and a ✓/✗ scoring table.
Changed
codex-reviewreplaced the plugin path with a bounded native-CLI wrapper. The Codex
plugin's companion awaited aturn/completedevent with no timeout and hung on stale broker
sessions. The skill now shipsscripts/run-codex-review.mjs(a companion asset) that runs the
barecodexCLI under a hard timeout — it cannot hang and cannot read a stale prior run's
output. The wrapper adds an env-configurable timeout (CODEX_REVIEW_TIMEOUT_MS, floor 1000ms;
--timeout-mswins) and a no-flag target fallback that infers the review target from the repo's
default branch.codex.invocation_modeis deprecated and ignored (retained in the schema so
existing configs keep validating).- Eye-verify woven deeper.
frontend-qualitygained a "seed the off-by-default state before
capturing" step and points at the shipped harness as the primary capture path;pull-requests
documents private-repo image embedding (a committed PNG's?raw=trueblob URL renders inline
for authenticated members; a browser drag-dropuser-attachmentsURL is the no-file fallback;
data:URIs are stripped by GitHub). Thejavascriptguideline was slimmed to the always-on
principle plus a pointer, so the detailed rubric lives on-demand rather than in every project's
CLAUDE.md.
Fixed
- README tag/inventory drift, surfaced by the new gate:
pre-releasenow documents its
release-automationtag (a consumer declaring onlyphp+githubwould not have received it);
jira-updatesdrops agithubtag it never carried in frontmatter; and the shipped
signed-commitsguideline gets its missing row in the Guidelines inventory.
Internal
Repository-only; none ship to consumers (all under export-ignored paths or dev config):
- CI
composer installruns--no-scripts --no-pluginson the fork-exposedpull_requestjob. - Dependabot now watches the
composerecosystem, not just GitHub Actions. stolt/skill-validatorpinned exactly (0.0.1; the^0.0.1caret resolved to the same version).- Removed a dead
.mcp.jsonpointing at avendor/bin/testbench boost:mcpcommand this package
does not provide.
The codex, eye-verify, and design-verification work was sourced from the upstream catalog and
production adoption feedback, then dogfooded through this repository's own evaluate and
codex-review flow before shipping.
Full Changelog: 2.16.1...2.17.0
v2.16.0
A frontend-quality release: first-class frontend testing and browser eye-verification join the catalog, a new Laravel migration-squash skill and an always-on AskUserQuestion guideline ship, and codex-review is hardened against the plugin hangs that have stalled reviews. Everything here is additive — no skill or guideline was removed or renamed, no conventions slot or schema-version changed, so a consumer upgrading from 2.15.0 keeps every existing behavior and simply gains the new content (tag-gated where noted).
Added
- First-class frontend tests.
frontend-qualitynow runs the project's JS/TS test suite (Vitest / Jest / …) as a third check alongside type-checking and linting — scope to the changed area during development, full suite at completion, and cover changed logic with a test.test-writingandbug-fixinggained framework selection for JS/TS runners (auto-detected frompackage.json), so a frontend bug is reproduced with a failing JS test the same way a backend one is. (frontendtag.) - Eye-verification (browser self-verify). A UI change is best confirmed by seeing it run in a real browser — type-check and lint can't catch runtime/visual bugs (stale state, dead toggles, broken scroll / sticky behaviour, z-index show-through, async races, untranslated-key leaks). Woven through the lifecycle as advisory guidance: the
javascriptguideline gains an "Eye-verify frontend changes" section,frontend-qualitya suggested eye-verify step,pull-requestsan advisory pre-PR gate, andbug-fixing/write-specreference it for visual fixes and UI-feature success measures. Includes per-element / per-attribute design verification (don't eyeball the whole image), ~15px padding around single-element screenshot crops, ephemeral-clone host targeting (a worktree may be served elsewhere — a hard 404 means the wrong host), and PR screenshot mechanics (embed in the PR body, commit a file rather than a base64data:URI that hosts strip, include the approved design alongside; a harness that can't run this session is a tracked deferral, not a silent skip). Generic — a project supplies its own browser harness (commonlytools/verify/) or a Playwright MCP server. - New
migration-squashskill (laraveltag). Create or review a Laravel migration squash (schema:dump --pruneinto a single schema baseline) with a verification checklist that catches the defects squash PRs actually ship with: an incomplete dump (DB behind the target), a contaminated dump (a migration applied from an abandoned/local/renamed branch), and a pruned data-migration whose seeded rows vanish on a fresh DB becauseschema:dumpcaptures structure, not rows. The completeness and contamination checks compare the dump's records against the target's baseline records ∪ migration files — so legitimate history whose files earlier squashes pruned isn't false-flagged. Defaults to the standardmysql-schema.sql(the.dumprename is an optional project variant), keeps the review steps host-neutral, and defers destructive operations to thedatabase-safetyguideline. - New
ask-user-questionguideline (always-on). InAskUserQuestionthe user reads a question from the assistant, so first/second-person pronouns are ambiguous — the guideline says to name the actor explicitly ("the assistant" / "the user") or drop the pronoun, across the question text, every option label, and every option description.
Changed
codex-reviewhardened against Codex plugin hangs. The companion awaits aturn/completednotification with no timeout, so a dropped event (broker/version skew, an untrusted ephemeral clone path) could hang a review forever. The skill now clears stale brokers in a preflight before every launch, treats a poll-loop timeout as a hang and recovers via the synchronous bare-CLI path (immune to the hang) rather than reading a stale result, and calls out that ephemeral clone paths (e.g. polyscope) aren't auto-trusted — trust the dir first.- Sync the base into the branch before every push.
pull-requests(a new preflight item plus a sync step in the work-on-existing-PR flow) andjira-reworknow merge the resolved base in before pushing, so CI tests the branch against the latest target rather than a stale base — closing a conflict/break class that a green CI run can otherwise hide. The PR analysis compares against the just-fetchedorigin/<base>.pr-review-feedbackalready did this. - Sharper code-comment bar in
evaluate. Phase 3 keeps a comment only when, without it, a competent reader would draw the wrong conclusion or break the code on edit — a real-but-inferable why belongs in the tracker, not inline. Adds a density signal: more than one surviving comment in a single function is a smell that the code wants splitting or renaming. - Generic PR risk framed as residual risk. The
pull-requestsLow/Medium/High block now weighs risk after the checks that run on every change (tests, CI, QA, reviewers): a loud, reversible failure ranks below a silent or irreversible one, and a narrow, well-tested change on a shared path isn't automatically high risk. Projects withpr.risktiers still delegate scoring to their own matrix.
The frontend-testing and eye-verification work and the skill refinements were sourced from upstream and production adoption feedback, then dogfooded through this repository's own evaluate, codex-review, and release flow before shipping.
Full Changelog: 2.15.0...2.16.0