d1cd04e808ff3d030fd6909fb54cd8992e1dbae2
5 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
dad16b6ef9 |
fix(#4141): ignore Stryker's sandbox in eslint's global ignores (#4178)
* fix(#4141): ignore Stryker's sandbox in eslint's global ignores `stryker.config.mjs` sets `tempDirName: '.stryker-tmp'`, `.gitignore` ignores it, and Stryker's own always-ignored list carries it. eslint's global `ignores` did not, and there is no `.eslintignore`. A mutation run that dies before cleanup — chunk timeout, CI cancellation, Ctrl+C, a crash — leaves a full sandbox copy of the tree at `.stryker-tmp/sandbox-*/`, and `npm run lint` then lints the copy. The failure is not the duplicate-file failure that would suggest, which is what makes it confusing: the `local` plugin is registered only in path-scoped config blocks (`tests/**/*.cjs`, `scripts/**/*.cjs`, `hooks/**`), and a copy at `.stryker-tmp/sandbox-*/tests/*.cjs` matches none of them, so every inline `// eslint-disable-next-line local/<rule>` the original carries becomes `Definition for rule 'local/<rule>' was not found` at the copy's path. The error text names rules rather than paths, so the first read is "my change broke the local plugin" — observed as 834 errors on a branch whose own diff was clean, from a sandbox eight days stale. CI never sees this (fresh checkout), so it is purely a local-contributor tax, but a loud and misleading one. The regression test asserts the invariant the way ESLint resolves it — `isPathIgnored()` over real flat-config precedence, not a textual scan of the ignores array — mirroring the #551 block it sits beside, and carries the control that the real `tests/worktree.test.cjs` at the mirrored path is still linted, so a pattern widened enough to swallow the tree cannot pass. Scoped to the reported bug: `reports/` may deserve the same treatment, but no lint failure has been reproduced from it, so it is not claimed here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017zgWzB96uz3LVKdJePYTLR * chore(#4141): backfill the changeset PR number Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017zgWzB96uz3LVKdJePYTLR * chore(#4141): restore the file's 2-blank-line block separator Review nit: the #4141 block left three blank lines before the RETIRED block, where every other block boundary in this file uses two. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mw7WhYnrWdY8cmj8NSJj4R --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Tom Boucher <trekkie@nomorestars.com> |
||
|
|
0f3959516c |
fix(#4106): drop the orphaned test:mutation:since script (#4179)
* 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> |
||
|
|
107eb8c1d9 |
feat(#3753): run docs guards on the PR that changes the docs they read (#3787)
A PR whose diff is entirely under docs/ runs zero tests, so a guard whose INPUT
is shipped prose cannot protect the PR lane of the diffs it exists to check. Its
only firing opportunity is after merge, on the shared branch -- which is how next
went red on
|
||
|
|
ffd5370464 |
fix(#2903): use the command form that actually works in reader-facing docs (#3047)
* fix(#2903): use the command form that actually works in reader-facing docs Docs told readers to type the colon form, which no runtime registers -- 18 of 19 runtimes use slash-hyphen and the 19th uses shell-var -- so anyone copying an example got an unrecognized command. Swept 178 occurrences across 53 files, locale mirrors included so they do not re-diverge from English. The colon form is a source-authoring token, not a user-facing one: install-time converters key on it to produce the hyphen form runtimes actually register. So the sweep is scoped, and three things are deliberately left alone: - ADRs, which are a historical record; editing their prose falsifies what was written at the time. - The legacy release-notes archive, pending a maintainer decision on whether it follows the same historical carve-out. Excluding it keeps a later reversal additive rather than a revert. - Source artifacts under commands, workflows and agents, where the colon form is load-bearing. Rewriting those would break the installed-skill guarantee across every runtime -- the single largest hazard here. The plugin namespace form is a real, separate token and survives untouched. Adds a lint enforcing exactly that boundary, since the correct form genuinely differs by directory and nothing previously caught the drift. Also fixes a hardcoded colon form in the capability-matrix generator. The sweep alone would have left the generated matrix disagreeing with the template that produces it, so the fix is at the source and the output regenerated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(#2903): stop the sweep misquoting source frontmatter Adversarial review caught three lines where the sweep rewrote a citation of the literal YAML name: key from a source command file. That key genuinely is the colon form -- this change's own carve-out logic says source-authoring tokens keep it -- so the docs ended up misquoting the real files. One of the three is an acceptance-checklist assertion, which the sweep turned into a false statement. Restored the three citations to match their sources verbatim, surgically: where a line carried both a name: citation and a real reader-facing slash command, only the citation reverted and the command stayed corrected. The guard needed the same distinction, or it would have flagged the restoration and reddened the build: a gsd:<cmd> token preceded by name: is a citation of a source token and is now permitted. The exemption is deliberately narrow -- a bare gsd:<cmd> anywhere else still fails -- with a test pinning that narrowness. Also makes the detection case-insensitive. Review found /GSD:next slipped through silently; no such casing exists in the tree today, so this closes a latent gap rather than fixing a live one. Swept the whole tree for further corrupted citations: none beyond the three. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(#2903): retire the stale-next invariant and sweep next like every other command Maintainer decision on a genuine conflict between two contracts. Invariant #3054 banned the literal /gsd-next from user-facing docs because it named a retired workflow-advance command. But commands/gsd/next.md is a live command -- the state-aware smart-entry launcher -- and this issue requires docs to use the hyphen form every runtime actually registers. Both could not hold for this one command, so docs had been sidestepping the ban by keeping the colon form, which is exactly the defect this issue exists to remove. FEATURES.md already recorded the reassignment: the hyphen form "is not the retired workflow-advance command; it is reserved for the state-aware smart-entry launcher. Workflow advancement remains under /gsd-progress --next." With that reassignment the invariant's premise is obsolete and the guard now contradicts the documented command form, so it is retired with a comment recording why rather than deleted silently. next is now swept like every other command, and the earlier exemption added to the new guard is removed so nothing is special-cased. Four citations of the literal name: frontmatter key stay in colon form, because the source file really does carry name: gsd:next and a doc quoting it must reproduce it verbatim. Two of those lines were reworded to say which side is the frontmatter key and which is the slash command, since they previously conflated the two. Verified the retired scan would now genuinely fail against this tree -- the conflict was real and resolved, not dodged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore(#2903): backfill changeset pr number Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
697cbb1f05 |
test(#1977): consolidate 22 misc + repo-invariant regression tests
Final epic-#1969 batch. Fold 22 issue-named files: the 4 genuine repo-wide invariant scans (551-eslint-bin-lib-coverage, bug-3054 stale /gsd-next, bug-3810 no-gsd-sdk-runtime-refs, feat-3593 cli-negative-universal) into a NEW shared repo-invariants.test.cjs; the other 18 as singletons into their nearest module suite (model-resolver, codex-config, runtime-converters, security, state-transition, worktree-safety, roadmap-parser, etc.). Verbatim block-scoped describe wrappers; 334 subtests conserved 1:1. Host-env pre-check (B2+B6): the 6 CLI folds into GSD_TEST_MODE-setting hosts (model-resolver/ codex-config/runtime-converters) are benign — each origin independently sets GSD_TEST_MODE=1 itself (idempotent), unlike the B6 real-install case. Regenerates regression-name allowlist (222->213), ratchets file-count allowlist (state 17->16), makes 7 relocated allow-test-rule exemptions issue-ref-compliant (ADR-456; prunes stale ids). Repoints 2 tests/ refs in docs/TESTING-SUITES.md. lint:ci green. Part of epic #1969. Closes #1977. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |