The prohibition-enforcement real-runner tests linted src/clock.cts (a .cts) as their clean target. Under eslint.config.mjs's type-aware block for src/**/*.cts (recommendedTypeChecked + parserOptions.project: tsconfig.build.json), each eslint spawn loaded the WHOLE tsconfig.build.json program (~2s, CPU-heavy). The real-runner tests spawn eslint repeatedly; under --test-concurrency those full-program type-checks oversubscribed the bench CPU and blew the 60s subprocess bound -> fail-closed (intermittent, load-dependent — passed 24241/24241 in an earlier run, failed here). Root fix (not a retry/timeout bandaid; measured projectService = no faster since a single-file .cts lint still loads type info): add tests/_ff_lint_clean.cjs, a KNOWN-CLEAN lint-scoped .cjs companion to _ff_lint_violation.cjs, with a flat-config block enabling local/no-source-grep so the clean pass stays non-vacuous. Repoint the 6 src/clock.cts real-runner usages (5 targets + the FF-02 toothless violationFixture) at it. Each spawn is now ~0.8s non-type-aware (no whole-program load) — starvation removed. All 6 tests' semantics verified in-process (SF-01 greens; toothless/fail-closed stay unverified); full-repo `eslint .` green. Refs #2126, #1259 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -399,4 +399,17 @@ export default tseslint.config(
|
||||
languageOptions: { sourceType: 'commonjs', globals: { ...globals.node } },
|
||||
rules: { 'local/no-source-grep': 'error' },
|
||||
},
|
||||
// ── #2126 lint-rule CLEAN fixture ───────────────────────────────────────────
|
||||
// `tests/_ff_lint_clean.cjs` is the KNOWN-CLEAN companion to the violation fixture: the
|
||||
// prohibition-enforcement real-runner tests lint it as their non-vacuous "clean target" instead of
|
||||
// a type-aware `src/**/*.cts` file, so each eslint spawn is ~0.8s (non-type-aware) not ~2s
|
||||
// (whole-tsconfig-program load) — removing the CPU starvation that blew the 60s bound under
|
||||
// --test-concurrency. Rule enabled (as error) so the pass is non-vacuous; the file is clean so it
|
||||
// greens. PLAIN `.cjs`, kept OFF the `*.test.cjs` runner glob. (#2126)
|
||||
{
|
||||
files: ['tests/_ff_lint_clean.cjs'],
|
||||
plugins: { local: localPlugin },
|
||||
languageOptions: { sourceType: 'commonjs', globals: { ...globals.node } },
|
||||
rules: { 'local/no-source-grep': 'error' },
|
||||
},
|
||||
);
|
||||
|
||||
19
tests/_ff_lint_clean.cjs
Normal file
19
tests/_ff_lint_clean.cjs
Normal file
@@ -0,0 +1,19 @@
|
||||
// PERMANENT LOAD-BEARING FIXTURE for #1259 / #2126 — DO NOT delete or rename to `*.test.cjs`.
|
||||
//
|
||||
// A KNOWN-CLEAN, lint-scoped `.cjs` companion to `_ff_lint_violation.cjs`. It has NO
|
||||
// `local/no-source-grep` violation, so the prohibition-enforcement real-runner tests can use it as
|
||||
// the "clean target" for a NON-VACUOUS pass — the rule RUNS on it (enabled via the flat-config
|
||||
// block below) and finds nothing.
|
||||
//
|
||||
// Why a `.cjs` and not `src/clock.cts`: linting a `src/**/*.cts` file is type-aware
|
||||
// (`recommendedTypeChecked` + `parserOptions.project`), which loads the whole `tsconfig.build.json`
|
||||
// program on every eslint spawn (~2s, CPU-heavy). The real-runner tests spawn eslint repeatedly and,
|
||||
// under `--test-concurrency`, those full-program type-checks oversubscribe the bench CPU and blow the
|
||||
// 60s subprocess bound (#2126). A plain `.cjs` is linted non-type-aware (~0.8s) — same coverage of
|
||||
// the AST-only `no-source-grep` rule, no starvation.
|
||||
//
|
||||
// PLAIN `.cjs` (NOT `*.test.cjs`) on purpose — same reason as the violation fixture: keep it OFF the
|
||||
// `node --test` runner glob so it is only ever linted, never executed.
|
||||
'use strict';
|
||||
|
||||
module.exports = {};
|
||||
@@ -716,13 +716,13 @@ describe('prohibition-enforcement REAL runner end-to-end (#1259)', () => {
|
||||
const enforce = require(ENFORCEMENT_LIB);
|
||||
// Migrated to the SHIPPING prover (#1279): the default real prover lints the committed
|
||||
// `_ff_lint_violation.cjs` violationFixture (the rule fires -> fail-first proven) while the
|
||||
// clean runCheck lints src/clock.cts (no violation -> non-vacuous pass). Both via real eslint.
|
||||
// clean runCheck lints tests/_ff_lint_clean.cjs (no violation -> non-vacuous pass). Both via real eslint.
|
||||
const result = enforce.runProhibitionEnforcement(
|
||||
TEST_TIER,
|
||||
{
|
||||
kind: 'lint-rule',
|
||||
rule: 'local/no-source-grep',
|
||||
target: 'src/clock.cts',
|
||||
target: 'tests/_ff_lint_clean.cjs',
|
||||
failFirst: true,
|
||||
violationFixture: path.join('tests', '_ff_lint_violation.cjs'),
|
||||
},
|
||||
@@ -759,13 +759,13 @@ describe('prohibition-enforcement REAL runner end-to-end (#1259)', () => {
|
||||
const enforce = require(ENFORCEMENT_LIB);
|
||||
// No injected runCheck/proveFailFirst: the default prover lints the committed
|
||||
// `_ff_lint_violation.cjs` (the rule fires -> fail-first proven) AND the default runner lints
|
||||
// the clean `src/clock.cts` (no violation -> non-vacuous pass). BOTH directions via real eslint.
|
||||
// the clean `tests/_ff_lint_clean.cjs` (no violation -> non-vacuous pass). BOTH directions via real eslint.
|
||||
const result = enforce.runProhibitionEnforcement(
|
||||
TEST_TIER,
|
||||
{
|
||||
kind: 'lint-rule',
|
||||
rule: 'local/no-source-grep',
|
||||
target: 'src/clock.cts',
|
||||
target: 'tests/_ff_lint_clean.cjs',
|
||||
violationFixture: path.join('tests', '_ff_lint_violation.cjs'),
|
||||
},
|
||||
{ cwd: process.cwd() },
|
||||
@@ -780,7 +780,7 @@ describe('prohibition-enforcement REAL runner end-to-end (#1259)', () => {
|
||||
|
||||
test('FULL producer (real): lint-rule hard-gates on a TOOTHLESS violationFixture (rule does not flag it) (FF-02 wrong-direction)', () => {
|
||||
const enforce = require(ENFORCEMENT_LIB);
|
||||
// The "violation fixture" is a CLEAN in-tree file (src/clock.cts) the rule does NOT flag, so the
|
||||
// The "violation fixture" is a CLEAN in-tree file (tests/_ff_lint_clean.cjs) the rule does NOT flag, so the
|
||||
// default prover cannot prove fail-first -> the producer must hard-gate (never green), even though
|
||||
// the clean target itself would pass the runner. A toothless guard is not a guard.
|
||||
const result = enforce.runProhibitionEnforcement(
|
||||
@@ -788,8 +788,8 @@ describe('prohibition-enforcement REAL runner end-to-end (#1259)', () => {
|
||||
{
|
||||
kind: 'lint-rule',
|
||||
rule: 'local/no-source-grep',
|
||||
target: 'src/clock.cts',
|
||||
violationFixture: 'src/clock.cts',
|
||||
target: 'tests/_ff_lint_clean.cjs',
|
||||
violationFixture: 'tests/_ff_lint_clean.cjs',
|
||||
},
|
||||
{ cwd: process.cwd() },
|
||||
);
|
||||
@@ -807,8 +807,8 @@ describe('prohibition-enforcement REAL runner end-to-end (#1259)', () => {
|
||||
{
|
||||
kind: 'lint-rule',
|
||||
rule: 'local/no-source-grep',
|
||||
target: 'src/clock.cts',
|
||||
violationFixture: 'src/clock.cts',
|
||||
target: 'tests/_ff_lint_clean.cjs',
|
||||
violationFixture: 'tests/_ff_lint_clean.cjs',
|
||||
},
|
||||
{ cwd: process.cwd(), mode },
|
||||
);
|
||||
@@ -1009,11 +1009,11 @@ describe('prohibition-enforcement defaultProveFailFirst REAL prover (#1279)', ()
|
||||
|
||||
test('lint-rule: a CLEAN violationFixture (rule does not flag) is NOT proven (FF-02 toothless direction)', () => {
|
||||
const enforce = require(ENFORCEMENT_LIB);
|
||||
// src/clock.cts is a clean in-tree source with no no-source-grep violation. If a "violation
|
||||
// tests/_ff_lint_clean.cjs is a clean in-tree source with no no-source-grep violation. If a "violation
|
||||
// fixture" does not actually trigger the rule, the rule is toothless on it → not a guard → not
|
||||
// proven → must hard-gate.
|
||||
const proof = enforce.defaultProveFailFirst(
|
||||
{ kind: 'lint-rule', rule: 'local/no-source-grep', target: 'src/clock.cts', violationFixture: 'src/clock.cts' },
|
||||
{ kind: 'lint-rule', rule: 'local/no-source-grep', target: 'tests/_ff_lint_clean.cjs', violationFixture: 'tests/_ff_lint_clean.cjs' },
|
||||
process.cwd(),
|
||||
);
|
||||
assert.equal(proof.provenFailFirst, false,
|
||||
@@ -1023,7 +1023,7 @@ describe('prohibition-enforcement defaultProveFailFirst REAL prover (#1279)', ()
|
||||
test('lint-rule: no violationFixture -> not proven (FF-05 fail-closed)', () => {
|
||||
const enforce = require(ENFORCEMENT_LIB);
|
||||
const proof = enforce.defaultProveFailFirst(
|
||||
{ kind: 'lint-rule', rule: 'local/no-source-grep', target: 'src/clock.cts' }, // no violationFixture
|
||||
{ kind: 'lint-rule', rule: 'local/no-source-grep', target: 'tests/_ff_lint_clean.cjs' }, // no violationFixture
|
||||
process.cwd(),
|
||||
);
|
||||
assert.equal(proof.provenFailFirst, false, 'no violationFixture -> cannot prove -> hard-gate');
|
||||
|
||||
Reference in New Issue
Block a user