Skip to content

fix(stryker-js-typescript-checker): own error positions, check counts - #264

Merged
ryanleecode merged 17 commits into
mainfrom
stryker/tsgo-checker
Oct 10, 2026
Merged

ryanleecode merged 17 commits into
mainfrom
stryker/tsgo-checker

Conversation

@systemfsoftware-maker

@systemfsoftware-maker systemfsoftware-maker commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

A CompileError reason now points at the line where the error is in that mutant's own code; before, any mutant other than the last in a batched check could report a line computed from a different mutant's text. Each check span also reports how much compiler work the check cost, which the parity lane in the next layer reads to compare this branch's checker with main's.

This is layer 1 of 4 of the TypeScript 7 native checker stack (base main). Layers 2 to 4 add the parity lane, the type-query port and the edit-location shortcut. Plan: docs/plans/2026-10-09-2106-perf-typescript-checker-tsgo-native-plan.md.

What changes

  • Docs (U1). The README states the TypeScript floor the checker already enforces (>=7.0.0), and a changeset corrects the 8.1.0 release note that said importers are re-checked "only when the mutant changes what that file exports" (they are re-checked whenever the mutated file has no compile errors of its own).
  • Own positions (U2, R14, KTD3, AE10). A CompileError reason now names the line and column in that mutant's own text. Diagnostics are rendered inside checkOne while that mutant's snapshot is current; before, Checker.cell rendered them after the whole call, against the last mutant's text, so an earlier mutant in the same call could report a wrong line (the AE10 fixture reported line 16 instead of 20).
  • Counts (U3, R3, KTD6). Each typescript-checker.compiler.check span reports the compiler work it did: snapshot updates, parenthesized re-splices, TCE emit builds and emit time. No new span names.

Checker verdict statuses do not change. Only the (line,col) inside a reason can change, and only for a mutant that was not the last one in its call.

Tests and the mutants they target

Main's mutation report: run 37960922409, artifact mutation-report-416.

  • src/__tests__/check-mutants.workflow.property.test.ts, new property ∀diagnostics_FailedReason_≡RenderedLinesJoinedByNewline, kills dogfood mutant 47892392410b616f (check-mutants.workflow.ts, join separator). Checked against the mutant: PropertyRefuted within 100 runs; passes on the real code. The existing OwnRenderedDiagnostics property survives that mutant because it never draws two diagnostics.
  • tests/check-mutants.integration.test.ts, scenario "An earlier mutant of one call reports the line its own text put it on", with fixture tests/__fixtures__/per-mutant-position/. It fails on the pre-U2 code (brokenLine 16, expected 20) and passes after. ts-compiler.handle.ts and Checker.cell.ts are outside the dogfood mutate globs (stryker.config.ts:12-19 mutates src/**/*.workflow.ts and src/**/*.schema.ts), so they have no mutant ids.
  • U3 has no package test (Test Admission refused it as wiring). Layer 2's parity lane refuses a branch side that checks mutants but reports zero snapshot updates, so a tally that never gets set fails there.

Local verification (targeted, per supervisor ruling S1)

  • pnpm --filter @systemfsoftware/stryker-js-typescript-checker typecheck: exit 0.
  • pnpm --filter @systemfsoftware/stryker-js-typescript-checker test: 31 files / 193 tests passed. Full suite after U3: two program-digest.integration.test.ts cases timed out under host load average ~140, then passed on a rerun of that file (193/193).
  • No local corpus, e2e or mutation run. CI runs those.

How an agent consumes this

  • Span typescript-checker.compiler.check (OTLP, OTEL_ENABLED=true), numeric attributes (OTLP JSON: counts arrive as intValue strings; typescript.tce.ms is usually fractional and arrives as doubleValue):
    • typescript.counts.schema_version: 1. Gate on this before reading the others. Main's checker emits the span without any of these attributes.
    • typescript.snapshot_updates.count: updateSnapshot calls in this check call (a parenthesized re-splice counts its own update).
    • typescript.resplices.count: mutants re-spliced as (replacement) because the bare splice changed the parse.
    • typescript.tce_builds.count: tsc emit builds this call ran for TCE (at most one per file that has passing mutants).
    • typescript.tce.ms: wall time of those builds, summed.
    • typescript.importer_shortcut.count: always 0 in this layer; layer 4's edit-location shortcut sets it.
    • The existing typescript.diagnostics.count, typescript.compile_errors.count and typescript.tce.* attributes are unchanged.
  • Verdict reason: unchanged format <file>(<line>,<col>): <severity> TS<code>: <text>, one line per diagnostic, joined by \n. (line,col) is 1-based and refers to the text the compiler checked for the mutant the verdict belongs to. When that mutant needed the parenthesized fallback splice, a column on the replacement's line counts the added (.
  • No new reason codes or artifacts in this layer. The lane artifacts and reason codes come in layer 2.

Review and overlap

Changesets

  • typescript-checker-ts7-only-docs.md (patch): README floor and 8.1.0 note correction.
  • typescript-checker-own-positions.md (patch): U2.
  • typescript-checker-check-counts.md (patch): U3.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Gap table against origin/main, measured updateSnapshot cost on the TS 7.0.2
unstable/async API, the edit-location soundness rule for the importer
re-check shortcut, the CI verdict-parity design, the api-extractor TS5
ruling, and six open questions for the supervisor.
…unit

Twelve stacked units: per-produce diagnostic rendering, snapshot/emit
counters, the edit-location Soundness Rule shortcut, file-bounded rounds,
one emit build per call, a sharded checker-parity CI lane against the
merge-base checker, and the B10 type-query port for Stream I.
Report-only ce-doc-review findings with proposed dispositions appended.
Applies every document-review disposition the supervisor ruled in
.omp-brief/rulings-plan.md (F1-F11, F13-F18; F13 and F17 narrowed; F12
rejected) and records OQ-P1..OQ-P10 as ruled. Replaces the nine-layer
sequencing with four linear layers: docs+U1-U3, lane U8-U10, type query
U11-U12, shortcut U4-U7.
… correct the 8.1.0 importer note

U1 of docs/plans/2026-10-09-2106-perf-typescript-checker-tsgo-native-plan.md (R11). README prerequisites match minimumTypeScriptVersion; the changeset corrects the released importer re-check claim without rewriting CHANGELOG.md.
…against its own text

U2 of the TS7 checker plan (R14, KTD3). checkOne renders its mutant's diagnostics while that mutant's snapshot is current; MutantCheck carries rendered lines and Checker.cell no longer renders after the call. AE10 (per-mutant-position fixture) fails on the old code (line 16 instead of 20). The join property targets dogfood mutant 47892392410b616f.
…ces and emit builds per check

U3 of the TS7 checker plan (R3, KTD6). A per-call tally on the compiler runtime counts snapshot updates, parenthesized re-splices and TCE emit builds and sums emit time; check annotates them on typescript-checker.compiler.check with typescript.counts.schema_version 1. No new span names. No package test (Test Admission refused); the parity lane's zero-updates refusal catches a tally that is never set.
…1 added

The per-mutant-position fixture's padding variable is now _b (oxlint no-unused-vars); lines and the shift mutant's body span are unchanged. The reason-format law is deleted: the OwnRenderedDiagnostics law already pins every mutant's reason over the full CheckMutantsInput schema, and the duplicate declared a module-scope schema in a test file (schema-declaration-location).
@systemfsoftware-maker
systemfsoftware-maker marked this pull request as ready for review October 10, 2026 17:15

@ryanleecode ryanleecode 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.

Root verified: all checks green on e22a2fa except the bench enterprise-fixture leg (setup-timed-out, an inherited lane defect Stream G owns); 0 threads, up to date with main, no suppressions.

@ryanleecode
ryanleecode merged commit 56426ca into main Oct 10, 2026
18 of 19 checks passed
@ryanleecode
ryanleecode deleted the stryker/tsgo-checker branch October 10, 2026 20:22
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