chore: rename vitest.config.mjs to .ts, so both vitest configs are TypeScript (#229)

The root config was plain JS while site/vitest.config.ts was TypeScript —
an inconsistency, not a constraint. The file was already ESM with a typed
defineConfig, so nothing inside it changed.

The landmine was removed first (#223): the path guard DISCOVERS the filename
via readdirSync().find(f => f.startsWith("vitest.config.")) instead of
spelling the extension, so this rename touches its comment, not its code.

Nine references updated; one was a live relative link in docs/testing-matrix.md
that would have broken. CLAUDE.md was regenerated from its spec, not hand-edited.

Mutation-proven three ways: green on .mjs, green on .ts, and a VALID config not
named vitest.config.* fails by the guard's own message ("no vitest.config.* at
the repo root") on exactly one assertion.

Gates: npm run check 18/18 · npm run coverage 3976 passed, 0 failed —
byte-identical to the pre-rename run.

Merged without an automated review: the Codex reviewer reported its code-review
usage limit was exhausted, so the signal was unavailable rather than pending.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
zernie
2026-09-10 06:43:46 +05:00
committed by GitHub
parent 38284bcd2e
commit e13d219ad0
10 changed files with 15 additions and 16 deletions
+1 -1
View File
@@ -85,7 +85,7 @@ Per fix:
side gains a field, the browser side needs it too.
- **Prettier + `fmt:check` before commit** — markdown code spans need surrounding
spaces; CI runs `fmt:check`.
- **Coverage gate is an allowlist** (`vitest.config.mjs` `coverage.include`) — a
- **Coverage gate is an allowlist** (`vitest.config.ts` `coverage.include`) — a
new file under it needs 100%; scan/cli files are NOT in it today.
## The two recurring bug classes — hunt for them, then PREVENT the class
+1 -1
View File
@@ -336,7 +336,7 @@ jobs:
# and upload `.vitest-reports/*` (a DOTDIR — needs upload-artifact's
# `include-hidden-files: true` or the artifact is silently empty); a
# dependent job downloads them and runs `vitest --merge-reports --coverage`,
# where the thresholds in vitest.config.mjs apply once, over the union.
# where the thresholds in vitest.config.ts apply once, over the union.
#
# THE THREE PROOFS IT STAYS HONEST, all run locally on this checkout:
# · FAITHFUL — merged 3 shards vs the unsharded run: same 19 files, 3509
+2 -2
View File
@@ -1,4 +1,4 @@
<!-- vigiles:sha256:684ae9f0b90e8b59 compiled from CLAUDE.md.spec.ts -->
<!-- vigiles:sha256:482126002a6257c6 compiled from CLAUDE.md.spec.ts -->
# CLAUDE.md
@@ -328,7 +328,7 @@ BUILD + TOOLING + GENERATED:
- `src/jest.ts` — Opt-in jest integration entry (CJS): registers vigilesMatchers + augments @jest/expect Matchers; jest is an optional peer dep
- `test/types/smoke.vitest.ts` — Type-level constraint: `vigiles/vitest` makes the matchers type-check on vitest's expect (tsc --noEmit via npm run test:types)
- `test/types/smoke.jest.ts` — Type-level constraint: `vigiles/jest` makes the matchers type-check on jest's expect
- `test/runners/matchers.vitest.mjs` — Cross-runner constraint: vigilesMatchers + helpers register and pass under vitest (proves runner-agnostic; `src/*.test.ts` excluded via vitest.config.mjs)
- `test/runners/matchers.vitest.mjs` — Cross-runner constraint: vigilesMatchers + helpers register and pass under vitest (proves runner-agnostic; `src/*.test.ts` excluded via vitest.config.ts)
- `test/runners/matchers.jest.cjs` — Cross-runner constraint: the same vigilesMatchers register and pass under jest (CommonJS dist required natively; scoped via jest.config.cjs)
- `src/core/test-utils.ts` — Shared test utilities: makeTmpDir, makeSpec, cleanupTmpDir, initGitRepo
- `src/core/types.ts` — Shared types: RulesConfig, VigilesConfig, FreshnessMode, CoverageThresholds
+1 -1
View File
@@ -545,7 +545,7 @@ BUILD + TOOLING + GENERATED:
"test/types/smoke.jest.ts":
"Type-level constraint: `vigiles/jest` makes the matchers type-check on jest's expect",
"test/runners/matchers.vitest.mjs":
"Cross-runner constraint: vigilesMatchers + helpers register and pass under vitest (proves runner-agnostic; `src/*.test.ts` excluded via vitest.config.mjs)",
"Cross-runner constraint: vigilesMatchers + helpers register and pass under vitest (proves runner-agnostic; `src/*.test.ts` excluded via vitest.config.ts)",
"test/runners/matchers.jest.cjs":
"Cross-runner constraint: the same vigilesMatchers register and pass under jest (CommonJS dist required natively; scoped via jest.config.cjs)",
"src/core/test-utils.ts":
+1 -1
View File
@@ -138,7 +138,7 @@ Deterministic Codex audit = full parity (KEEP). Real-model **trigger-rate** on C
Cold start ~20s+; a first probe may time out — retry longer.
- **A SKILL.md is NOT a skill unless registered** — bare `SKILL.md` in cwd never loads;
use `arm.pluginDir`/`skillsDir`. `CLAUDE.md` DOES auto-load as memory.
- **The 100% coverage gate is an EXPLICIT allowlist** in `vitest.config.mjs`
- **The 100% coverage gate is an EXPLICIT allowlist** in `vitest.config.ts`
(`coverage.include`). A new pillar file must be added there + real-IO seams marked
`/* v8 ignore */`.
- **`measure()` is SINGLE-arg** — `measure(spec)` where `checks`/`trials`/`model` live
+1 -1
View File
@@ -166,7 +166,7 @@ isolate the slow or privileged tiers (real-egress e2e) in their own jobs; and ru
the paid **eval** tier on demand, not on every commit — its non-determinism and
cost make it a release/regression gate, not a per-push check. The per-tier
`npm run test:unit | test:integration | test:e2e` scripts exist for exactly this
split (see [`vitest.config.mjs`](../vitest.config.mjs)).
split (see [`vitest.config.ts`](../vitest.config.ts)).
**Skips are loud, never a silent green.** `vigiles test` classifies each script
pass / skip / fail. A unit-tier `runHook` test needs no `claude` and always runs;
+6 -7
View File
@@ -334,13 +334,12 @@ describe("no root test depends on a file under site/ (#219)", () => {
* put the vitest and Jest runner suites outside the scan.
*/
async function rootSuiteGlobs(): Promise<string[]> {
// The specifier is COMPUTED, not a literal: a literal `.mjs` import is a
// tsc error here (TS7016 — no declaration file), and shipping a .d.ts for a
// config would be ceremony around a value we only want to read.
// The FILENAME is discovered, not spelled. `vitest.config.mjs` is plain JS
// while `site/vitest.config.ts` is TypeScript — an inconsistency, not a
// constraint (vitest accepts either; measured 2026-09-09). Whoever settles
// that should not have to remember this guard.
// The FILENAME is discovered, not spelled, and that is what let the config
// be renamed `.mjs` -> `.ts` (2026-09-10) without touching this guard —
// which was the point of writing it this way one day earlier.
// The specifier stays COMPUTED rather than a literal import: it is what
// makes the discovery meaningful, and it also sidesteps TS7016 for any
// future non-TS config here.
const cfgName = readdirSync(REPO).find((f) =>
f.startsWith("vitest.config."),
);
+1 -1
View File
@@ -8,7 +8,7 @@ import {
type RuleCatalog,
} from "./rule-catalog.js";
// Vitest runs from the repo root (see vitest.config.mjs).
// Vitest runs from the repo root (see vitest.config.ts).
const REPO_ROOT = process.cwd();
describe("parseEslintCatalog (pure)", () => {
+1 -1
View File
@@ -16,7 +16,7 @@ import {
} from "../../dist/harness-assert.js";
import { tool, output, blocked } from "../../dist/check.js";
// Matchers are registered by the `vigiles/vitest` entry via setupFiles
// (vitest.config.mjs) — this file asserts that wiring works end-to-end.
// (vitest.config.ts) — this file asserts that wiring works end-to-end.
const report = {
name: "demo",