Issue Description
Convert the eval text-moderation runner scripts/evals/Modules/retext-runner.mjs to strictly typed TypeScript as retext-runner.mts, and enforce the types in local validation and PR CI.
Node 24, the version pinned in CI, the devcontainer, and Copilot setup, runs .mts files directly through built-in type stripping, so no build step or generated output is needed. .mts is used instead of .ts because the root package.json has no "type": "module". A .ts file would print a MODULE_TYPELESS_PACKAGE_JSON warning to stderr on every run.
Scope:
- Rename the runner to
.mts with strict, erasable-only types. Its stdin/stdout/exit-code contract and output must stay byte-identical.
- Add exact-pinned
typescript and @types/node dev dependencies, a root tsconfig.json, and an npm run lint:ts (tsc --noEmit) check, and add lint:ts to validate:local.
- Run
lint:ts on every PR through a new reusable typescript-check.yml workflow that is part of the PR validation gate.
- Point
Test-EvalSpecText.ps1 at the new file.
- Teach
Test-CopyrightHeaders.ps1 to scan .mts with // comments. Today .mts is skipped.
- Update the contributor docs that name the runner path or list validation commands.
Additional Context
- While prototyping, the type check found a dead fallback in the current runner:
message.position does not exist on vfile-message v4 messages. The conversion removes it without changing behavior.
- Other
.mjs files, a root "type": "module", and .cts support are out of scope.
- Known follow-up, not part of this issue: the root
spell-check glob does not scan .mjs, .mts, or .cjs sources.
Issue Description
Convert the eval text-moderation runner
scripts/evals/Modules/retext-runner.mjsto strictly typed TypeScript asretext-runner.mts, and enforce the types in local validation and PR CI.Node 24, the version pinned in CI, the devcontainer, and Copilot setup, runs
.mtsfiles directly through built-in type stripping, so no build step or generated output is needed..mtsis used instead of.tsbecause the rootpackage.jsonhas no"type": "module". A.tsfile would print aMODULE_TYPELESS_PACKAGE_JSONwarning to stderr on every run.Scope:
.mtswith strict, erasable-only types. Its stdin/stdout/exit-code contract and output must stay byte-identical.typescriptand@types/nodedev dependencies, a roottsconfig.json, and annpm run lint:ts(tsc --noEmit) check, and addlint:tstovalidate:local.lint:tson every PR through a new reusabletypescript-check.ymlworkflow that is part of the PR validation gate.Test-EvalSpecText.ps1at the new file.Test-CopyrightHeaders.ps1to scan.mtswith//comments. Today.mtsis skipped.Additional Context
message.positiondoes not exist on vfile-message v4 messages. The conversion removes it without changing behavior..mjsfiles, a root"type": "module", and.ctssupport are out of scope.spell-checkglob does not scan.mjs,.mts, or.cjssources.