Skip to content

Start mutation-checking the scripts/ folder - #1944

Merged
stefan-burke merged 26 commits into
mainfrom
claude/mutation-check-scripts
Jul 27, 2026
Merged

Start mutation-checking the scripts/ folder#1944
stefan-burke merged 26 commits into
mainfrom
claude/mutation-check-scripts

Conversation

@stefan-burke

@stefan-burke stefan-burke commented Jul 26, 2026

Copy link
Copy Markdown
Member

Mutation testing has only ever been pointed at src/. This branch points it at scripts/ for the first time, and closes the gaps it found in sixteen of those files.

What a gap means here: a mutation run makes one small change to the code — swaps a + for a -, empties a piece of text, deletes a line — and runs that file's tests. If they still pass, nothing was really checking that piece of code. Every gap closed below was a change that used to slip through unnoticed.

The survey

65 files under scripts/ have a test beside them. I ran all of them:

  • 26 already caught every change.
  • 39 did not, ~700 misses in total.

Fixed in this branch

File Misses What was missing
compact-test-reporter.ts 152 Almost the whole file: reading TAP failure reports, working out where a failure happened, the progress bar, the run summary, and guessing how many tests a run will report
mutation/summary.ts 63 The wording and layout of both reports it writes — the one in your terminal and the one GitHub shows
pr-queue (four files) 63 Reading the arguments, working out which repo to report on, every gh call, and both ways of printing the report
process.ts 7 That a child shares all three streams, that removing a folder takes its contents, and that a force-stopped child is waited for
cleanup.ts 3 The message on the error that carries several failures at once
bench/…/javascript-ast.ts 2 (see below)
lock-file.ts 2 That the lock really keeps two jobs apart, and that it creates its own file
check-copy.ts / check-copy/run.ts 1 Which folder the site's English copy is read from
check-copy/rules.ts 1 That markup between "click" and "here" still reads as one phrase
biome-command.ts 1 That the Biome version we install matches the one biome.json is written for
test-subjects.ts 1 That the shared start-up helpers are both ignored, not just one
specs/parallel.ts 1 A single case gets no worker, and a machine reporting no cores still gets one
project-root.ts 1 That the project root really is the folder holding deno.json
stream-lines.ts 1 A character split across two chunks is joined back together

All sixteen now score 100%.

Two files had to be restructured, not just tested

pr-queue.ts and check-copy.ts were untestable by construction: they did their work as the file loaded and ended the process with an exit code, so no test could ever call them.

  • pr-queue.ts is now one line. Reading the arguments, talking to gh, and printing the report each live in their own file under scripts/pr-queue/, and hand back an answer instead of ending the process. The command to run is a parameter, so the whole report can be exercised without a network.
  • check-copy.ts now names the folder holding the site's English copy in a place a test can reach.

Along the way the gh runner and the git runner turned out to be doing the same job, so they now share one captureOutput helper, and their two identical result types became one.

Code that came out

Some things gained no test because nothing could ever reach them: a repeat-visit guard on a tree that has no repeats, a colon check on text that always has colons, a "no total yet" branch that a running count always fills in, a duplicate way of spotting --reporter, and an optional read that contradicted the fail-loudly rule beside it.

Eleven changes genuinely cannot be caught by any test — the parser filename that only labels error messages, a fallback for a pattern that always matches — and those are written down in equivalent-mutants.txt with the reason.

Test files that had grown past the 400-line mark were split: the copy checks now sit beside the file each one tests, and the mutation summary's tests are three files, one per report.

Still to do

24 files still have misses. The big ones are mutation/isolation.ts (49), stripe-mock.ts (48), stripe-mock/install.ts (39), specs/run.ts (38) and mutation.ts (30). Like pr-queue was, most are command-line entry points whose work happens in child processes, so they need the same treatment: pull the decisions out where a test can see them.

TODO.md also records the follow-up to split compact-test-reporter.ts, which is over the 400-line target but was already so before this branch.

claude added 6 commits July 26, 2026 18:34
The parser hands back a tree, so no node is ever reached twice and the
WeakSet could never skip anything. Record the parser's filename argument
as a known-equivalent mutant: it only labels diagnostics.
Lock the Biome package version to the one biome.json is written against,
name the copy catalog folder once and check it really holds the site's
English copy, and assert the message on the combined-failure error. Split
the copy-check tests so each one sits beside the file it tests.
@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The changes extract the PR queue CLI into focused modules, centralize process and copy-check contracts, expand compact reporter and mutation-summary coverage, simplify AST traversal, add equivalent-mutant records, and test several script utility edge cases.

Changes

PR queue reporting

Layer / File(s) Summary
PR queue modules and entrypoint
scripts/pr-queue.ts, scripts/pr-queue/*
The CLI delegates to runPrQueue, which parses arguments, invokes gh, fetches and re-polls GraphQL PR data, sanitizes output, and renders terminal or JSON reports.
PR queue behavior tests
test/scripts/pr-queue/*
Tests cover parsing, repository resolution, timeout and failure handling, GraphQL construction, mergeability retries, pagination warnings, ordering, and output sanitization.

Compact TAP reporting

Layer / File(s) Summary
Reporter parsing and progress behavior
scripts/compact-test-reporter.ts
Reporter argument detection, diagnostic location parsing, estimated totals, and progress rendering are updated.
Reporter parsing and output tests
test/scripts/compact-test-reporter/*
Tests cover diagnostics, locations, TAP parsing, test-count estimation, progress output, TAP detection, compact summaries, and integration behavior.

Validation and process utilities

Layer / File(s) Summary
Shared validation and process contracts
scripts/check-copy.ts, scripts/check-copy/run.ts, scripts/process.ts, scripts/precommit/git.ts
The catalog path and captured command-output shape are centralized, and precommit Git execution uses the shared capture helper.
Copy-check and process validation
test/scripts/check-copy/*, test/scripts/process.test.ts, test/scripts/precommit*.test.ts, test/scripts/lock-file.test.ts, test/scripts/cleanup.test.ts, test/scripts/specs/evidence-git.test.ts
Tests cover catalog behavior, process cleanup, locking, aggregate errors, and updated command-output contracts.

Mutation and script consistency

Layer / File(s) Summary
Mutation summary fixtures and output validation
test/scripts/mutation/summary/*
Tests cover mutation scores, timing aggregation, terminal and Markdown output, survivors, suppressed equivalents, append behavior, and step-summary handling.
AST traversal and mutation records
scripts/bench/bundle-composition/javascript-ast.ts, scripts/mutation/equivalent-mutants.txt
AST traversal no longer tracks revisited objects, and equivalent mutations are recorded across several script modules.
Script utility edge-case coverage
test/scripts/biome-command.test.ts, test/scripts/project-root.test.ts, test/scripts/specs/parallel.test.ts, test/scripts/stream-lines.test.ts, test/scripts/test-subjects.test.ts
Additional tests validate Biome version resolution, project-root discovery, worker allocation, multibyte decoding, and environment-overlay filtering.
Reporter decomposition follow-up
TODO.md
Documents a planned responsibility-aligned split of the compact test reporter.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant runPrQueue
  participant GhIntegration
  participant GitHub
  User->>runPrQueue: provide CLI arguments
  runPrQueue->>GhIntegration: resolve repository and fetch queue
  GhIntegration->>GitHub: execute GraphQL request
  GitHub-->>GhIntegration: return pull request data
  GhIntegration-->>runPrQueue: return queue and pagination state
  runPrQueue-->>User: print report
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: expanding mutation checking to the scripts folder.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/mutation-check-scripts
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/mutation-check-scripts

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b4aa4e40b3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/compact-test-reporter.ts Outdated
Comment thread scripts/check-copy/run.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cd3c0d62ad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread test/scripts/mutation/summary.test.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/scripts/check-copy/run.test.ts`:
- Around line 83-88: Strengthen the real copy catalog test in “the real copy
catalog” by asserting a known complete {file, key, value} entry from the
expected English catalog, rather than relying only on catalog.length and the
presence of common.json. Keep the existing broad checks, and use an established
stable catalog entry that verifies its file, key, and translated value together.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: da08ac26-0a2c-4bdd-a514-1ff85d845520

📥 Commits

Reviewing files that changed from the base of the PR and between 93a9c8b and cd3c0d6.

📒 Files selected for processing (15)
  • scripts/bench/bundle-composition/javascript-ast.ts
  • scripts/check-copy.ts
  • scripts/check-copy/run.ts
  • scripts/compact-test-reporter.ts
  • scripts/mutation/equivalent-mutants.txt
  • test/scripts/biome-command.test.ts
  • test/scripts/check-copy/rules.test.ts
  • test/scripts/check-copy/run.test.ts
  • test/scripts/cleanup.test.ts
  • test/scripts/compact-test-reporter/diagnostics.test.ts
  • test/scripts/compact-test-reporter/estimate.test.ts
  • test/scripts/compact-test-reporter/progress.test.ts
  • test/scripts/compact-test-reporter/reporter.test.ts
  • test/scripts/compact-test-reporter/summary.test.ts
  • test/scripts/mutation/summary.test.ts

Comment thread test/scripts/check-copy/run.test.ts
…y tests

Adds the missing checks for the shared start-up files, worker counts, the
project root, stream decoding, and the file lock's exclusivity. The mutation
summary's tests now sit in three files, one per report.
@stefan-burke stefan-burke changed the title WIP: mutation-check the scripts/ folder Start mutation-checking the scripts/ folder Jul 26, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 83c1291b07

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/compact-test-reporter.ts
Comment thread test/scripts/lock-file.test.ts Outdated
A plain 20ms wait could pass on a busy runner before the second holder had
even asked for the lock. It now waits for the attempt itself, then gives it
time to get in, so the check only passes because the lock kept it out.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/scripts/lock-file.test.ts`:
- Line 108: Replace the fixed setTimeout sleep in the lock contention test with
deterministic synchronization tied to the second holder’s actual
lock-acquisition attempt. Add or use a test seam/hook to signal that attempt,
assert the second holder remains blocked, and only then resolve releaseFirst;
avoid real-time sleeps.

In `@test/scripts/mutation/summary/markdown.test.ts`:
- Around line 119-122: Reuse the shared ANSI normalizer by importing plain from
./fixtures.ts in test/scripts/mutation/summary/markdown.test.ts and replacing
the inline regex callback with logs.map(plain); make the same callback
replacement in test/scripts/mutation/summary/terminal.test.ts, ensuring the
terminal test also imports plain as needed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f31fb747-d282-40e8-a44a-52f937b85ef0

📥 Commits

Reviewing files that changed from the base of the PR and between cd3c0d6 and f7d0733.

📒 Files selected for processing (13)
  • TODO.md
  • scripts/mutation/equivalent-mutants.txt
  • test/scripts/check-copy/run.test.ts
  • test/scripts/lock-file.test.ts
  • test/scripts/mutation/summary.test.ts
  • test/scripts/mutation/summary/fixtures.ts
  • test/scripts/mutation/summary/markdown.test.ts
  • test/scripts/mutation/summary/score.test.ts
  • test/scripts/mutation/summary/terminal.test.ts
  • test/scripts/project-root.test.ts
  • test/scripts/specs/parallel.test.ts
  • test/scripts/stream-lines.test.ts
  • test/scripts/test-subjects.test.ts
💤 Files with no reviewable changes (1)
  • test/scripts/mutation/summary.test.ts

Comment thread test/scripts/lock-file.test.ts Outdated
Comment thread test/scripts/mutation/summary/markdown.test.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f7d0733f01

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread test/scripts/lock-file.test.ts Outdated
Comment thread test/scripts/mutation/summary/fixtures.ts Outdated
claude added 2 commits July 26, 2026 21:42
…odules

The entry script now only wires things up: reading the arguments and every
gh call live in scripts/pr-queue/, hand back a message and exit code rather
than ending the process, and take the command to run as a parameter. Adds the
shared captureOutput helper so the gh runner and the git runner decode output
one way, and collapses their two identical result types into one.

Also fixes the file-lock test: it now waits for the second holder to really
ask for the lock before checking it is still blocked (the earlier edit never
landed).
They now check that a child shares all three streams, that removing a folder
takes its contents with it, and that a force-stopped child is waited for
before the cleanup runs.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: feb5ddaa2e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/pr-queue/gh.ts Outdated
Comment thread scripts/pr-queue/args.ts Outdated
Comment thread scripts/pr-queue/gh.ts Outdated
The entry script is now one line. Following Codex's notes: the gh helpers are
module-private again and tested through the two calls the report actually
makes, the argument reader is named for what it does rather than for the
functional pattern, and the comment restating the runner type is gone.
claude added 3 commits July 26, 2026 22:07
The stand-in gh now steps through its answers instead of indexing past the
end, so it has no unreachable fallback, and the re-poll waits with the shared
delay helper rather than its own copy.
@stefan-burke
stefan-burke added this pull request to the merge queue Jul 26, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Jul 26, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/pr-queue/gh.ts`:
- Around line 173-179: Update the repository access in the fetchQueue flatMap
logic to remove optional chaining from data.repository, preserving the existing
!fresh guard for missing pull-request aliases and allowing malformed payloads
without repository to fail loudly.

In `@test/scripts/precommit.test.ts`:
- Around line 19-36: Centralize the duplicated CapturedOutput fixture
construction in a shared helper under `#test-utils`, preserving support for
successful and failed outputs. In test/scripts/precommit.test.ts lines 19-36 and
test/scripts/precommit/mutation-step.test.ts lines 13-36, replace the local
ok/fail implementations with the shared factory while retaining domain-specific
wrappers such as sha. In test/scripts/specs/evidence-git.test.ts lines 7-19,
replace the local result object construction with the same shared factory.

In `@test/scripts/process.test.ts`:
- Around line 107-130: Update the force-stop test around stopProcess and
fakeChild so it synchronizes on the SIGKILL request instead of using a fixed 20
ms delay. Resolve a promise from the SIGKILL branch, await that promise before
invoking endKilled, and preserve the expected child-ended then cleanup ordering.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 57faeebd-4e70-4ecd-8df0-cabbad3e71f9

📥 Commits

Reviewing files that changed from the base of the PR and between f7d0733 and 00ea69a.

📒 Files selected for processing (21)
  • TODO.md
  • scripts/mutation/equivalent-mutants.txt
  • scripts/pr-queue.ts
  • scripts/pr-queue/args.ts
  • scripts/pr-queue/gh.ts
  • scripts/pr-queue/run.ts
  • scripts/precommit/git.ts
  • scripts/process.ts
  • test/scripts/cleanup.test.ts
  • test/scripts/lock-file.test.ts
  • test/scripts/mutation/summary/fixtures.ts
  • test/scripts/mutation/summary/markdown.test.ts
  • test/scripts/mutation/summary/terminal.test.ts
  • test/scripts/pr-queue/args.test.ts
  • test/scripts/pr-queue/fixtures.ts
  • test/scripts/pr-queue/gh.test.ts
  • test/scripts/pr-queue/run.test.ts
  • test/scripts/precommit.test.ts
  • test/scripts/precommit/mutation-step.test.ts
  • test/scripts/process.test.ts
  • test/scripts/specs/evidence-git.test.ts
💤 Files with no reviewable changes (1)
  • test/scripts/mutation/summary/fixtures.ts

Comment thread scripts/pr-queue/gh.ts
Comment thread test/scripts/precommit.test.ts Outdated
Comment thread test/scripts/process.test.ts
Reads the re-poll reply straight rather than optionally, so a malformed one
fails loudly like the rest of the fetch. Shares one command-output fixture
between the three test files that were each building their own. Waits for the
force-stop to be asked for instead of guessing at twenty milliseconds.
A module-level alias is what the code-quality rule forbids, and it hid the
helper behind a second name for no gain.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants