* fix(#4106): drop the orphaned test:mutation:since script `"test:mutation:since": "stryker run --incremental --since origin/next"` could not run. Stryker has no `--since` flag — verified against the pinned `@stryker-mutator/core` 9.6.1, whose options schema has no `since` property and whose CLI exits `error: unknown option '--since'`. It went unnoticed because nothing invokes it. `.github/workflows/mutation.yml` uses the per-module matrix instead: `scripts/mutation-matrix.cjs` computes the changed covered modules and each shard runs its own `npx stryker run --incremental --mutate "${MUTATE_GLOB}"`. That path works, so no gate ever exercised the script. It is still worth removing rather than leaving: its name makes it the obvious thing to reach for when a reviewer asks for a mutation score on changed scope, and the Commander parse error it produces says nothing about the matrix being the real entry point — the next person has to reverse-engineer mutation.yml to find that out. Delete rather than repoint. The issue offered both, and the maintainer had not picked; delete is the option that stays scoped to the reported bug. The suggested replacement (`node scripts/mutation-matrix.cjs --base origin/next`) emits a CI matrix rather than running mutants, so shipping it under a `test:mutation:*` name would be a second, differently-shaped claim, and documenting the per-module invocation in CONTRIBUTING.md is enhancement-shaped work that belongs in its own issue. The discovery command is named in the changeset instead. Flipping this PR to the pointer script is a one-line change if that is preferred. The regression test asserts that every `stryker` script in package.json passes only flags Stryker's own options schema defines. It carries its own control — the historical `--incremental --since origin/next` string is checked to still be rejected by the same predicate — so the sweep cannot go quietly vacuous if the remaining invocations lose their flags. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017zgWzB96uz3LVKdJePYTLR * chore(#4106): backfill the changeset PR number Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017zgWzB96uz3LVKdJePYTLR * docs(#4106): mark the changeset docs-exempt `type: Removed` makes docs-lint require a `docs/` change. Nothing under `docs/` or in CONTRIBUTING.md ever referenced `test:mutation:since` — the script was orphaned and could not run — so there is no documented behaviour to update. Using the gate's own per-fragment escape hatch rather than weakening the changeset type to dodge the requirement. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017zgWzB96uz3LVKdJePYTLR --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Tom Boucher <trekkie@nomorestars.com>
Changeset Fragments
This directory holds per-PR CHANGELOG fragments. Every PR with user-facing changes drops one (or more) <random-name>.md files here describing its CHANGELOG entry. Fragments are consolidated into the top-level CHANGELOG.md at release time.
Why
Two PRs that both edit the ### Fixed block of CHANGELOG.md always conflict on merge — git can't pick a serialization order without human input. Two PRs that each add a fresh .changeset/<unique-name>.md never conflict because they don't share lines.
See #2975 for the full rationale.
Adding a fragment
node scripts/changeset/new.cjs \
--type Fixed \
--pr 1234 \
--body "fix the thing — explain the user-visible change in one sentence"
This writes .changeset/<adjective>-<noun>-<noun>.md with frontmatter and a body. Three random words → concurrent PRs don't collide.
Format
---
type: Fixed
pr: 1234
---
**`/gsd-foo` no longer drops trailing slashes** — explain the user-visible change.
Allowed type: values follow Keep a Changelog: Added, Changed, Deprecated, Removed, Fixed, Security.
Opting out
PRs that legitimately have no user-facing impact can add the no-changelog label. CI honors it. When unsure, add the fragment.
At release time
Promotion is automatic. The release workflow's finalize job runs:
node scripts/changeset/cli.cjs render --version vX.Y.Z --date YYYY-MM-DD --allow-empty
This reads every fragment, groups bullets by type:, replaces ## [Unreleased] with a new ## [vX.Y.Z] - YYYY-MM-DD block, opens a fresh ## [Unreleased] above, and deletes consumed fragments. The --allow-empty flag ensures a no-change release still gets a dated heading (with a _No notable changes._ placeholder). A subsequent verify step confirms the promotion landed correctly. Maintainers do not run this by hand.
Archived fragments
.changeset/archived/ holds fragments for already-shipped releases (≤ 1.3.1), retained for provenance. Their content was hand-curated into the dated ## [1.x.y] sections of CHANGELOG.md during the #690 backfill — they were never consumed by render. All changeset tooling enumerates .changeset/ non-recursively, so archived fragments are never picked up or rendered. Do not move them back to the top level.