This commit is contained in:
@@ -35,6 +35,7 @@ const JOB_RULES = [
|
||||
{ workflowFile: 'test.yml', jobKey: 'test', test: (name) => name.startsWith('test (') && name !== 'test (inert CI)' },
|
||||
{ workflowFile: 'test.yml', jobKey: 'test-full', test: (name) => name.startsWith('full test (') },
|
||||
{ workflowFile: 'test.yml', jobKey: 'coverage-gate', test: (name) => name === 'Coverage gate (merged shards)' },
|
||||
{ workflowFile: 'test.yml', jobKey: 'test-conformance', test: (name) => name.startsWith('conformance test (') },
|
||||
{ workflowFile: 'install-smoke.yml', jobKey: 'smoke', test: (name) => name.startsWith('smoke (') },
|
||||
];
|
||||
|
||||
|
||||
336
scripts/gen-platform-conformance-tier.cjs
Normal file
336
scripts/gen-platform-conformance-tier.cjs
Normal file
@@ -0,0 +1,336 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Generates scripts/lib/platform-conformance-tier.generated.cjs — the list of
|
||||
* test files under tests/**\/*.test.cjs whose CONTENT signals they exercise
|
||||
* platform-specific behavior (Windows/macOS path quirks, raw child_process
|
||||
* usage, chmod mode bits, etc.) and therefore need REAL-OS coverage rather
|
||||
* than a Linux-only conformance lane (#4591).
|
||||
*
|
||||
* Only `unit`-suite test files (no suite suffix, per `scripts/run-tests.cjs`'s
|
||||
* `suiteOf()`) are considered for the conformance tier. `install`-,
|
||||
* `security`-, `slow`-, `integration`-, and `qa`-suffixed files are excluded
|
||||
* entirely — never merely deprioritized — for three independent reasons: (1)
|
||||
* `install`/`slow` are explicitly PR-excluded suites
|
||||
* (`scripts/affected-tests-lib.cjs`'s `PR_EXCLUDED_SUITES`; "PRs must never
|
||||
* select or run these"), and this generator's output feeds a `pull_request`-
|
||||
* triggered job; (2) `integration`/`security` already run via their own
|
||||
* separate, dedicated, unsharded, shard-1-only steps in the `test`/
|
||||
* `test-full` jobs (.github/workflows/test.yml) — folding any of them into
|
||||
* this job's generic `--files-from` + `--shard` invocation is unproven and,
|
||||
* per the incident below, unsafe. (3) `qa` (loop-walk-suite files) already
|
||||
* runs via its own separate, dedicated `qa-loop-walk` job
|
||||
* (.github/workflows/test.yml) — the same rationale as (2): a purpose-built
|
||||
* home already exists, so folding it into this job's generic invocation
|
||||
* duplicates coverage without benefit. Real incident that surfaced this: a live
|
||||
* CI run's `conformance test (windows-latest, shard 2/3)` job was killed with
|
||||
* 11 tests in flight — including `tests/release-tarball-smoke.install.test.cjs`
|
||||
* — because this generator had (wrongly) placed an `install`-suite file into
|
||||
* the Linux-conformance candidate pool with no suite filtering at all.
|
||||
*
|
||||
* `classifyContent(content)` is the pure, exported classifier: it favors
|
||||
* simple, auditable substring/regex matching over AST parsing, mirroring
|
||||
* eslint-rules/lib/portability-vocab.cjs's own design stance (over-inclusion
|
||||
* is the safe direction — a false positive costs one extra test running on a
|
||||
* real OS; a false negative silently drops real-OS coverage).
|
||||
*
|
||||
* KNOWN LIMIT, disclosed deliberately: this is a STATIC content classifier,
|
||||
* not a real per-file, per-OS behavioral diff. Epic #4589's issue #4591 asked
|
||||
* for the cutover to be validated by "running the existing full matrix one
|
||||
* more time as a parity baseline, diffing pass/fail per file between the
|
||||
* real-OS runs and the Linux run" before moving any file into the Linux-only
|
||||
* bulk. That literal per-file diff was NOT performed — no historical
|
||||
* per-file, per-OS pass/fail dataset exists to diff against (GitHub Actions
|
||||
* publishes coverage/QA artifacts from CI runs, not per-file JUnit results).
|
||||
* What stands in for it: (1) the most recent push-triggered run on `next`
|
||||
* (unconditionally full-matrix) is green on every OS for every file in this
|
||||
* classification, confirmed before this classifier was built; (2) the
|
||||
* existing `test-full` job keeps running the WHOLE suite on real Windows/
|
||||
* macOS as a non-gating safety net for one release cycle (.github/workflows/
|
||||
* test.yml) — a classifier miss surfaces as a visible warning there, not a
|
||||
* silent gap, before the safety net is retired. This is the same
|
||||
* static-analysis-substitutes-for-real-OS-execution stance ADR-1703's whole
|
||||
* rule catalog already takes; it is a real, disclosed limit, not a silent
|
||||
* substitution.
|
||||
*
|
||||
* Usage:
|
||||
* node scripts/gen-platform-conformance-tier.cjs # print summary to stdout
|
||||
* node scripts/gen-platform-conformance-tier.cjs --write # write the generated file
|
||||
* node scripts/gen-platform-conformance-tier.cjs --check # exit 1 if the committed file is stale
|
||||
* node scripts/gen-platform-conformance-tier.cjs --tests-dir <path> # override the tests/ root (tests only)
|
||||
* node scripts/gen-platform-conformance-tier.cjs --out <path> # override the generated-file path (tests only)
|
||||
*
|
||||
* `--tests-dir`/`--out` (or the TESTS_DIR/OUT_PATH env vars, flag takes
|
||||
* precedence) exist solely so tests/platform-conformance-tier.test.cjs can
|
||||
* point the CLI at a small temp fixture tree instead of this repo's real,
|
||||
* 900+-file tests/ tree. Production usage (package.json's lint:generated-sync
|
||||
* / regen:derived chains) passes no flags and gets the real repo paths.
|
||||
*/
|
||||
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
const { ExitError, runMain } = require('./lib/cli-exit.cjs');
|
||||
const { suiteOf } = require('./lib/suite-detection.cjs');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '..');
|
||||
const DEFAULT_TESTS_DIR = path.join(ROOT, 'tests');
|
||||
const DEFAULT_OUT_PATH = path.join(ROOT, 'scripts', 'lib', 'platform-conformance-tier.generated.cjs');
|
||||
|
||||
const GENERATED_HEADER =
|
||||
'// GENERATED FILE — do not hand-edit. Run `node scripts/gen-platform-conformance-tier.cjs --write` to regenerate.\n';
|
||||
|
||||
/**
|
||||
* Detection categories (#4591 design doc). Each entry's `test` receives the
|
||||
* raw file content string and returns true when that category's signal is
|
||||
* present. Order matches the design doc's enumeration; `signals` in
|
||||
* `classifyContent`'s return value preserves this order.
|
||||
*/
|
||||
const CATEGORIES = [
|
||||
{
|
||||
name: 'process-platform',
|
||||
test: (content) => /process\.platform/.test(content),
|
||||
},
|
||||
{
|
||||
name: 'os-platform',
|
||||
test: (content) => /os\.platform\(\)/.test(content),
|
||||
},
|
||||
{
|
||||
name: 'win32-darwin-literal',
|
||||
test: (content) => /\bwin32\b/.test(content) || /\bdarwin\b/.test(content),
|
||||
},
|
||||
{
|
||||
name: 'chmod-mode-bit',
|
||||
test: (content) => /chmodSync|chmod\(/.test(content) || /0o[0-7]{3,4}\b/.test(content),
|
||||
},
|
||||
{
|
||||
name: 'windows-shell-token',
|
||||
test: (content) => /cmd\.exe|powershell|pwsh|ComSpec/i.test(content),
|
||||
},
|
||||
{
|
||||
name: 'windows-env-var',
|
||||
test: (content) => /\bPATHEXT\b|\bUSERPROFILE\b|\bHOMEDRIVE\b|\bHOMEPATH\b/.test(content),
|
||||
},
|
||||
{
|
||||
name: 'process-seam-subprocess',
|
||||
test: (content) => /\brunNode\(|\brunGit\(|\brunHook\(|\brunGsdTools\(|\bgitOrThrow\(/.test(content),
|
||||
},
|
||||
{
|
||||
name: 'raw-child-process',
|
||||
// Requires BOTH the child_process import/reference token AND one of the
|
||||
// three call names in the same file — this is what keeps a same-named
|
||||
// local identifier (e.g. a variable called `spawnResult`) from false-
|
||||
// positiving: `spawnResult` never forms the substring `spawnSync(`.
|
||||
test: (content) => {
|
||||
if (/require\((['"])(?:node:)?child_process\1\)/.test(content)) return true;
|
||||
if (!content.includes('child_process')) return false;
|
||||
return /\bspawnSync\(|\bexecSync\(|\bexecFileSync\(/.test(content);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'symlink-keyword',
|
||||
// A leading `\b` with no trailing one, case-insensitive: this is
|
||||
// deliberately NOT `/\bsymlink\b|\bSymlink\b/` (that literal pair would
|
||||
// never match the dominant real-world call shape `symlinkSync(` /
|
||||
// `readlinkSync(` — no word boundary exists between "symlink" and the
|
||||
// immediately-following "Sync", both \w characters). The leading `\b`
|
||||
// alone still excludes a mid-word embedding like "presymlink".
|
||||
test: (content) => /\bsymlink/i.test(content),
|
||||
},
|
||||
{
|
||||
name: 'hardcoded-path-vs-path-call',
|
||||
// Intentionally coarse (design doc: over-inclusion is the safe
|
||||
// direction): a path.* call ANYWHERE in the file plus a quoted
|
||||
// forward-slash-leading string literal ANYWHERE in the file, with no
|
||||
// attempt at proximity/scoping.
|
||||
test: (content) =>
|
||||
/path\.(join|resolve|dirname|basename|normalize|relative)\(/.test(content) &&
|
||||
/['"`]\/[\w.\-/]*['"`]/.test(content),
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* Pure classifier: given a test file's raw string content, returns which
|
||||
* platform-conformance categories matched and whether the file needs real-OS
|
||||
* coverage (true iff at least one category matched).
|
||||
*
|
||||
* @param {string} content
|
||||
* @returns {{needsRealOs: boolean, signals: string[]}}
|
||||
*/
|
||||
function classifyContent(content) {
|
||||
const text = typeof content === 'string' ? content : '';
|
||||
const signals = [];
|
||||
for (const category of CATEGORIES) {
|
||||
if (category.test(text)) signals.push(category.name);
|
||||
}
|
||||
return { needsRealOs: signals.length > 0, signals };
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively collect every `*.test.cjs` file beneath `dir`.
|
||||
* @param {string} dir
|
||||
* @returns {string[]} absolute paths
|
||||
*/
|
||||
function walkTestFiles(dir) {
|
||||
const out = [];
|
||||
let entries;
|
||||
try {
|
||||
entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
} catch {
|
||||
return out;
|
||||
}
|
||||
for (const entry of entries) {
|
||||
const full = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
out.push(...walkTestFiles(full));
|
||||
} else if (entry.isFile() && entry.name.endsWith('.test.cjs')) {
|
||||
out.push(full);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Classify every test file under `testsDir`, returning `{ total, files }`
|
||||
* where `files` is the SORTED array of `tests/<...>.test.cjs`-relative paths
|
||||
* (POSIX-normalized, per RULESET.CONTENT-PATH-NORMALIZATION) whose content
|
||||
* needs real-OS coverage.
|
||||
*
|
||||
* @param {string} testsDir
|
||||
* @returns {{ total: number, files: string[] }}
|
||||
*/
|
||||
function classifyTree(testsDir) {
|
||||
const absoluteFiles = walkTestFiles(testsDir);
|
||||
// Only unit-suite files (no suite suffix) are eligible for the conformance
|
||||
// tier — see the header doc-comment for why suite-tagged files are excluded
|
||||
// entirely rather than merely deprioritized.
|
||||
const unitFiles = absoluteFiles.filter((absPath) => suiteOf(absPath) === null);
|
||||
const flagged = [];
|
||||
for (const absPath of unitFiles) {
|
||||
const content = fs.readFileSync(absPath, 'utf8');
|
||||
const { needsRealOs } = classifyContent(content);
|
||||
if (needsRealOs) {
|
||||
const rel = path.relative(testsDir, absPath).replace(/\\/g, '/');
|
||||
flagged.push('tests/' + rel);
|
||||
}
|
||||
}
|
||||
flagged.sort();
|
||||
return { total: absoluteFiles.length, files: flagged };
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the generated `.cjs` module body — one array entry per line for a
|
||||
* readable diff, matching scripts/lib/portability-vocab.cjs's array-literal
|
||||
* style.
|
||||
*
|
||||
* @param {string[]} files - already sorted.
|
||||
* @returns {string}
|
||||
*/
|
||||
function renderGeneratedFile(files) {
|
||||
const lines = files.map((f) => ` ${JSON.stringify(f)},`).join('\n');
|
||||
return (
|
||||
GENERATED_HEADER +
|
||||
"'use strict';\n\n" +
|
||||
'module.exports = {\n' +
|
||||
' CONFORMANCE_TIER_FILES: [\n' +
|
||||
(lines.length > 0 ? lines + '\n' : '') +
|
||||
' ],\n' +
|
||||
'};\n'
|
||||
);
|
||||
}
|
||||
|
||||
/** Resolve the effective tests-dir / out-path from argv/env, flag beats env. */
|
||||
function resolveOverrides(argv) {
|
||||
let testsDir = process.env.TESTS_DIR || DEFAULT_TESTS_DIR;
|
||||
let outPath = process.env.OUT_PATH || DEFAULT_OUT_PATH;
|
||||
|
||||
for (let i = 0; i < argv.length; i++) {
|
||||
if (argv[i] === '--tests-dir') {
|
||||
const value = argv[i + 1];
|
||||
if (!value || value.startsWith('--')) {
|
||||
throw new ExitError(1, 'gen-platform-conformance-tier: --tests-dir requires a path value');
|
||||
}
|
||||
testsDir = path.resolve(value);
|
||||
i++;
|
||||
} else if (argv[i] === '--out') {
|
||||
const value = argv[i + 1];
|
||||
if (!value || value.startsWith('--')) {
|
||||
throw new ExitError(1, 'gen-platform-conformance-tier: --out requires a path value');
|
||||
}
|
||||
outPath = path.resolve(value);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return { testsDir: path.resolve(testsDir), outPath: path.resolve(outPath) };
|
||||
}
|
||||
|
||||
function main() {
|
||||
const argv = process.argv.slice(2);
|
||||
const { testsDir, outPath } = resolveOverrides(argv);
|
||||
const mode = argv.includes('--check') ? 'check' : argv.includes('--write') ? 'write' : 'print';
|
||||
|
||||
const { total, files } = classifyTree(testsDir);
|
||||
|
||||
if (mode === 'write') {
|
||||
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
||||
fs.writeFileSync(outPath, renderGeneratedFile(files));
|
||||
process.stdout.write(`Wrote ${outPath} (${files.length} conformance-tier file(s))\n`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode === 'check') {
|
||||
// Never trust a stale require cache — the committed file may have been
|
||||
// rewritten (by --write, or by hand) since this process started.
|
||||
let committed;
|
||||
try {
|
||||
const resolved = require.resolve(outPath);
|
||||
delete require.cache[resolved];
|
||||
committed = require(resolved);
|
||||
} catch (err) {
|
||||
throw new ExitError(
|
||||
1,
|
||||
`gen-platform-conformance-tier: could not load ${outPath} — run ` +
|
||||
'`node scripts/gen-platform-conformance-tier.cjs --write` first ' +
|
||||
`(${err && err.message ? err.message : err})`,
|
||||
);
|
||||
}
|
||||
const committedFiles = Array.isArray(committed.CONFORMANCE_TIER_FILES)
|
||||
? committed.CONFORMANCE_TIER_FILES
|
||||
: [];
|
||||
const committedSet = new Set(committedFiles);
|
||||
const liveSet = new Set(files);
|
||||
|
||||
const added = files.filter((f) => !committedSet.has(f));
|
||||
const removed = committedFiles.filter((f) => !liveSet.has(f));
|
||||
|
||||
if (added.length > 0 || removed.length > 0) {
|
||||
process.stderr.write(
|
||||
`${path.relative(ROOT, outPath).replace(/\\/g, '/')} is stale. Run:\n` +
|
||||
' node scripts/gen-platform-conformance-tier.cjs --write\n\n',
|
||||
);
|
||||
for (const f of added) process.stderr.write(' + ' + f + '\n');
|
||||
for (const f of removed) process.stderr.write(' - ' + f + '\n');
|
||||
throw new ExitError(1);
|
||||
}
|
||||
|
||||
process.stdout.write(
|
||||
`ok gen-platform-conformance-tier: ${files.length} conformance-tier files, list matches\n`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// No flag: print a classification summary, write nothing.
|
||||
process.stdout.write(
|
||||
`gen-platform-conformance-tier: ${total} file(s) scanned, ` +
|
||||
`${files.length} need real OS, ${total - files.length} excluded (Linux-only conformance tier eligible)\n`,
|
||||
);
|
||||
}
|
||||
|
||||
/* c8 ignore next 3 -- CLI entry guard; this repo measures coverage with c8, which does not honor istanbul pragmas */
|
||||
if (require.main === module) {
|
||||
runMain(main);
|
||||
}
|
||||
|
||||
module.exports = { classifyContent, CATEGORIES, walkTestFiles, classifyTree, renderGeneratedFile };
|
||||
553
scripts/lib/platform-conformance-tier.generated.cjs
Normal file
553
scripts/lib/platform-conformance-tier.generated.cjs
Normal file
@@ -0,0 +1,553 @@
|
||||
// GENERATED FILE — do not hand-edit. Run `node scripts/gen-platform-conformance-tier.cjs --write` to regenerate.
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
CONFORMANCE_TIER_FILES: [
|
||||
"tests/active-workstream-store.test.cjs",
|
||||
"tests/active-workstream-store.unit.test.cjs",
|
||||
"tests/adr-15-progress-converge.test.cjs",
|
||||
"tests/adr-22-plan-drift-guard.test.cjs",
|
||||
"tests/adr-612-bracket-coherence.test.cjs",
|
||||
"tests/adr-612-bracket-phase-counting.test.cjs",
|
||||
"tests/adr-612-bracket-read-tolerance.test.cjs",
|
||||
"tests/adr-index-gate.test.cjs",
|
||||
"tests/adr857-core-without-capabilities.test.cjs",
|
||||
"tests/advance-plan-ambiguous-phase.test.cjs",
|
||||
"tests/agent-frontmatter.test.cjs",
|
||||
"tests/agent-hint-routing-1689.test.cjs",
|
||||
"tests/agent-install-check.test.cjs",
|
||||
"tests/agent-install-validation.test.cjs",
|
||||
"tests/agent-skills.test.cjs",
|
||||
"tests/ai-evals.test.cjs",
|
||||
"tests/antigravity-upgrades.test.cjs",
|
||||
"tests/api-coverage-gate-e2e.test.cjs",
|
||||
"tests/api-coverage.test.cjs",
|
||||
"tests/assumption-delta-checkpoint-e2e.test.cjs",
|
||||
"tests/assumption-delta.test.cjs",
|
||||
"tests/audit-command-cutover.test.cjs",
|
||||
"tests/audit-open-remainder-count.test.cjs",
|
||||
"tests/audit-uat-acknowledged.test.cjs",
|
||||
"tests/audit-uat-summary-segmentation.test.cjs",
|
||||
"tests/audit-workstream-layouts.test.cjs",
|
||||
"tests/augment-upgrades.test.cjs",
|
||||
"tests/autonomous-converge.test.cjs",
|
||||
"tests/autonomous-interactive.test.cjs",
|
||||
"tests/benchmark-compact-content.test.cjs",
|
||||
"tests/branch-no-track-guard.test.cjs",
|
||||
"tests/broken-windows-description.test.cjs",
|
||||
"tests/broken-windows.test.cjs",
|
||||
"tests/bugs-1656-1657.test.cjs",
|
||||
"tests/canary-version-leak-lint.test.cjs",
|
||||
"tests/capability-cli.test.cjs",
|
||||
"tests/capability-command-dispatch.test.cjs",
|
||||
"tests/capability-consent.test.cjs",
|
||||
"tests/capability-ledger.test.cjs",
|
||||
"tests/capability-lifecycle.test.cjs",
|
||||
"tests/capability-loader.test.cjs",
|
||||
"tests/capability-lock-mkdir-failure-3987.test.cjs",
|
||||
"tests/capability-precedence-parity.test.cjs",
|
||||
"tests/capability-probe-fallback.test.cjs",
|
||||
"tests/capability-registry.test.cjs",
|
||||
"tests/capability-source.test.cjs",
|
||||
"tests/capability-state.test.cjs",
|
||||
"tests/capability-trust.test.cjs",
|
||||
"tests/capability-writer.test.cjs",
|
||||
"tests/changeset-cli.test.cjs",
|
||||
"tests/changeset-github-release-notes.test.cjs",
|
||||
"tests/changeset-lint.test.cjs",
|
||||
"tests/changeset-new.test.cjs",
|
||||
"tests/check-contract-drift.test.cjs",
|
||||
"tests/check-env.test.cjs",
|
||||
"tests/check-gap-analysis-plan-post-e2e.test.cjs",
|
||||
"tests/check-glossary-refs.test.cjs",
|
||||
"tests/check-tdd-review-checkpoint-e2e.test.cjs",
|
||||
"tests/check-ui-plan-gate.test.cjs",
|
||||
"tests/check-ui-safety-gate.test.cjs",
|
||||
"tests/check-update-config-dir.test.cjs",
|
||||
"tests/chunked-planning-parallel.test.cjs",
|
||||
"tests/ci-docs-guard-registry.test.cjs",
|
||||
"tests/ci-next-health.test.cjs",
|
||||
"tests/ci-pr-mergeability.test.cjs",
|
||||
"tests/ci-rebase-check.test.cjs",
|
||||
"tests/ci-test-scope.test.cjs",
|
||||
"tests/cjs-command-router-adapter.test.cjs",
|
||||
"tests/claude-md-path.test.cjs",
|
||||
"tests/claude-md.test.cjs",
|
||||
"tests/claude-orchestration-command-router.test.cjs",
|
||||
"tests/claude-orchestration.test.cjs",
|
||||
"tests/claude-skills-migration.test.cjs",
|
||||
"tests/cli-exit.test.cjs",
|
||||
"tests/cline-install.test.cjs",
|
||||
"tests/clock-seam.test.cjs",
|
||||
"tests/clock.test.cjs",
|
||||
"tests/close-phase-todos-padded-resolves.test.cjs",
|
||||
"tests/code-review-command.test.cjs",
|
||||
"tests/code-review-depth.test.cjs",
|
||||
"tests/code-review-fix-pipeline-regression.test.cjs",
|
||||
"tests/code-review-pipeline-regression.test.cjs",
|
||||
"tests/code-review-tier3-files-override-scoping.test.cjs",
|
||||
"tests/code-review.test.cjs",
|
||||
"tests/codebuddy-install.test.cjs",
|
||||
"tests/codebuddy-upgrades.test.cjs",
|
||||
"tests/codex-config-agents.test.cjs",
|
||||
"tests/codex-config-hooks.test.cjs",
|
||||
"tests/codex-config-install.test.cjs",
|
||||
"tests/codex-config.test.cjs",
|
||||
"tests/codex-declarative-reference.test.cjs",
|
||||
"tests/codex-inherit-smoke.test.cjs",
|
||||
"tests/command-contract.test.cjs",
|
||||
"tests/command-routing-hub.test.cjs",
|
||||
"tests/commands.test.cjs",
|
||||
"tests/commit-docs-bypass.test.cjs",
|
||||
"tests/commit-files-deletion.test.cjs",
|
||||
"tests/commit-files-pathspec.test.cjs",
|
||||
"tests/commonjs-marker.test.cjs",
|
||||
"tests/compact-content-4139.test.cjs",
|
||||
"tests/compact-content-partition-guard.test.cjs",
|
||||
"tests/completion-predicate-drift-guard.test.cjs",
|
||||
"tests/completion-ratio-scope-withholding.test.cjs",
|
||||
"tests/completion-ratio-single-owner.test.cjs",
|
||||
"tests/concurrency-safety.test.cjs",
|
||||
"tests/config-defaults-runtime-exclusion.test.cjs",
|
||||
"tests/config-field-docs.test.cjs",
|
||||
"tests/config-get-default.test.cjs",
|
||||
"tests/config-loader.test.cjs",
|
||||
"tests/config-schema.property.test.cjs",
|
||||
"tests/config.test.cjs",
|
||||
"tests/configuration-migrate-config.test.cjs",
|
||||
"tests/context-drift.test.cjs",
|
||||
"tests/context-predicates-query.test.cjs",
|
||||
"tests/copilot-install.test.cjs",
|
||||
"tests/copilot-upgrades.test.cjs",
|
||||
"tests/core-utils.test.cjs",
|
||||
"tests/coverage-metadata-parser.test.cjs",
|
||||
"tests/coverage-uat-routing.test.cjs",
|
||||
"tests/cursor-hook-workspace-roots.test.cjs",
|
||||
"tests/cursor-hooks.test.cjs",
|
||||
"tests/cursor-reviewer.test.cjs",
|
||||
"tests/cursor-subagent-isolation.test.cjs",
|
||||
"tests/debug-session-manager-commit.test.cjs",
|
||||
"tests/decisions.test.cjs",
|
||||
"tests/declarative-reference-antigravity.test.cjs",
|
||||
"tests/declarative-reference-augment.test.cjs",
|
||||
"tests/declarative-reference-codebuddy.test.cjs",
|
||||
"tests/declarative-reference-copilot.test.cjs",
|
||||
"tests/declarative-reference-windsurf.test.cjs",
|
||||
"tests/declarative-reference-zcode.test.cjs",
|
||||
"tests/default-flip-documentation-lint.test.cjs",
|
||||
"tests/dispatcher.test.cjs",
|
||||
"tests/docs-hooks-table-parity.test.cjs",
|
||||
"tests/docs-parity-live-registry.test.cjs",
|
||||
"tests/docs-update.test.cjs",
|
||||
"tests/drift-detection.test.cjs",
|
||||
"tests/edge-probe-spec-phase-contract.test.cjs",
|
||||
"tests/edge-probe.test.cjs",
|
||||
"tests/edit-phase-milestone-scope-guard.test.cjs",
|
||||
"tests/edit-phase.test.cjs",
|
||||
"tests/effort-surface-axis.test.cjs",
|
||||
"tests/effort-sync-installed-runtime.test.cjs",
|
||||
"tests/emitted-ack-trailer.test.cjs",
|
||||
"tests/emitted-attribution.test.cjs",
|
||||
"tests/emitted-caps-gate.test.cjs",
|
||||
"tests/emitted-provenance.test.cjs",
|
||||
"tests/emitted-sizes.test.cjs",
|
||||
"tests/ensure-runtime-build.test.cjs",
|
||||
"tests/enumeration-single-owner.test.cjs",
|
||||
"tests/eslint-glob-coverage.test.cjs",
|
||||
"tests/eslint-rules.test.cjs",
|
||||
"tests/estimate-calibrate.test.cjs",
|
||||
"tests/estimate-loop-convergence.test.cjs",
|
||||
"tests/execute-mvp-tdd-gate.test.cjs",
|
||||
"tests/execute-phase-wave.test.cjs",
|
||||
"tests/execute-phase-worktree-guard.test.cjs",
|
||||
"tests/execute-plan-update-codebase-map-diff-base.test.cjs",
|
||||
"tests/execute-wave-post-gate-pipeline-e2e.test.cjs",
|
||||
"tests/executed-plan.test.cjs",
|
||||
"tests/executor-mvp-tdd-section.test.cjs",
|
||||
"tests/exit-code-registry.test.cjs",
|
||||
"tests/explore-command.test.cjs",
|
||||
"tests/external-descriptor-confinement.test.cjs",
|
||||
"tests/failing-direction.test.cjs",
|
||||
"tests/fallow-runner.test.cjs",
|
||||
"tests/faulty-deps.test.cjs",
|
||||
"tests/feat-2296-provider-escalation.test.cjs",
|
||||
"tests/feat-2483-review-claude-mds-guard.test.cjs",
|
||||
"tests/feat-2646-deferred-items-audit-scanner.test.cjs",
|
||||
"tests/feat-3881-yaml-parser-consequences.test.cjs",
|
||||
"tests/features-index-gate.test.cjs",
|
||||
"tests/fixture-builder.test.cjs",
|
||||
"tests/frontmatter-cli.test.cjs",
|
||||
"tests/frontmatter.test.cjs",
|
||||
"tests/gap-checker.property.test.cjs",
|
||||
"tests/gate-predicate-evaluator-missing.test.cjs",
|
||||
"tests/gemini-runtime-removed.test.cjs",
|
||||
"tests/gen-context-index.test.cjs",
|
||||
"tests/gen-health-docs.test.cjs",
|
||||
"tests/gen-registry.test.cjs",
|
||||
"tests/gen-section-manifest.test.cjs",
|
||||
"tests/gen-state-md-docs.test.cjs",
|
||||
"tests/git-base-branch.test.cjs",
|
||||
"tests/git-fixture.test.cjs",
|
||||
"tests/golden-install-tree.test.cjs",
|
||||
"tests/graphify-command-cutover.test.cjs",
|
||||
"tests/graphify-graph-path.test.cjs",
|
||||
"tests/graphify-visualization.test.cjs",
|
||||
"tests/graphify.test.cjs",
|
||||
"tests/gsd-agent-isolation-guard.test.cjs",
|
||||
"tests/gsd-check-update-worker-atomic-cache.test.cjs",
|
||||
"tests/gsd-check-update-worker-platform-gate.test.cjs",
|
||||
"tests/gsd-mcp-server-bin.test.cjs",
|
||||
"tests/gsd-quick-batch-merge-integration.test.cjs",
|
||||
"tests/gsd-quick-batch-workflow.test.cjs",
|
||||
"tests/gsd-secret-read-guard.test.cjs",
|
||||
"tests/gsd-settings-advanced.test.cjs",
|
||||
"tests/gsd-statusline.test.cjs",
|
||||
"tests/gsd-tools-path-refs.test.cjs",
|
||||
"tests/gsd-validate-commit-crash-policy.test.cjs",
|
||||
"tests/gsd-write-guard.property.test.cjs",
|
||||
"tests/gsd-write-guard.test.cjs",
|
||||
"tests/gsd2-import.test.cjs",
|
||||
"tests/hardcoded-paths.test.cjs",
|
||||
"tests/health-diagnostic-rules/agent-install.test.cjs",
|
||||
"tests/health-diagnostic-rules/config-validation.test.cjs",
|
||||
"tests/health-diagnostic-rules/consistency.test.cjs",
|
||||
"tests/health-diagnostic-rules/phase-structure.test.cjs",
|
||||
"tests/health-diagnostic-rules/root-existence.test.cjs",
|
||||
"tests/health-diagnostic-rules/state-consistency.test.cjs",
|
||||
"tests/health-diagnostic-rules/worktree-health.test.cjs",
|
||||
"tests/health-diagnostic.test.cjs",
|
||||
"tests/health-validation.test.cjs",
|
||||
"tests/helpers-cleanup.test.cjs",
|
||||
"tests/helpers-process-isolation.test.cjs",
|
||||
"tests/hermes-skills-migration.test.cjs",
|
||||
"tests/hooks-commonjs-marker.test.cjs",
|
||||
"tests/hooks-crash-policy.test.cjs",
|
||||
"tests/hooks-opt-in.test.cjs",
|
||||
"tests/host-integration.test.cjs",
|
||||
"tests/host-runtime-detection.test.cjs",
|
||||
"tests/ingest-docs.test.cjs",
|
||||
"tests/init-debug.test.cjs",
|
||||
"tests/init-manager.test.cjs",
|
||||
"tests/init.test.cjs",
|
||||
"tests/injection-blocking-config.test.cjs",
|
||||
"tests/inline-plan-threshold.test.cjs",
|
||||
"tests/install-fs-adapter-seam.test.cjs",
|
||||
"tests/install-minimal-hooks.test.cjs",
|
||||
"tests/install-nested-layout.test.cjs",
|
||||
"tests/install-path-detection.test.cjs",
|
||||
"tests/install-regressions.test.cjs",
|
||||
"tests/install-runtime-artifacts.test.cjs",
|
||||
"tests/install-scope.test.cjs",
|
||||
"tests/install-write-confinement.test.cjs",
|
||||
"tests/install.test.cjs",
|
||||
"tests/installed-surface-resolver.test.cjs",
|
||||
"tests/installer-migration-antigravity-retire-confighome-artifacts.test.cjs",
|
||||
"tests/installer-migration-authoring.test.cjs",
|
||||
"tests/installer-migration-config-root-marker.test.cjs",
|
||||
"tests/installer-migration-pi-retire-hooks-dir.test.cjs",
|
||||
"tests/installer-migration-prune-stale-pristine.test.cjs",
|
||||
"tests/installer-migration-rename-gsd-core.test.cjs",
|
||||
"tests/installer-migration-report.test.cjs",
|
||||
"tests/installer-migrations-manifest-schema.test.cjs",
|
||||
"tests/installer-migrations.test.cjs",
|
||||
"tests/intel-command-cutover.test.cjs",
|
||||
"tests/intel.test.cjs",
|
||||
"tests/inventory-manifest-sync.test.cjs",
|
||||
"tests/inventory-nested-families.test.cjs",
|
||||
"tests/io.test.cjs",
|
||||
"tests/isolation-sentinel.test.cjs",
|
||||
"tests/kilo-upgrades.test.cjs",
|
||||
"tests/kimi-agent-converter.test.cjs",
|
||||
"tests/kimi-normalize-payload.property.test.cjs",
|
||||
"tests/kimi-upgrades.test.cjs",
|
||||
"tests/kimi-variant-disambiguation.test.cjs",
|
||||
"tests/learnings.test.cjs",
|
||||
"tests/legacy-cleanup-config-dir.test.cjs",
|
||||
"tests/lint-allow-test-rule-refs.test.cjs",
|
||||
"tests/lint-compiled-artifact-sync.test.cjs",
|
||||
"tests/lint-docs-command-form.test.cjs",
|
||||
"tests/lint-frontmatter-scalar-broad-grep.test.cjs",
|
||||
"tests/lint-hooks-runtime-build-seam.test.cjs",
|
||||
"tests/lint-legacy-dir-name.test.cjs",
|
||||
"tests/lint-planning-artifact-writer-drift.test.cjs",
|
||||
"tests/lint-pr-check-project-dir.test.cjs",
|
||||
"tests/lint-regression-test-names.test.cjs",
|
||||
"tests/lint-seam-enforcement.test.cjs",
|
||||
"tests/lint-skill-deps.test.cjs",
|
||||
"tests/lint-test-file-count.test.cjs",
|
||||
"tests/lint-workflow-shellcheck-fetch.test.cjs",
|
||||
"tests/list-seeds.test.cjs",
|
||||
"tests/live-config-guard.test.cjs",
|
||||
"tests/live-dom-uat.test.cjs",
|
||||
"tests/lockfile-cve-audit.test.cjs",
|
||||
"tests/locking-bugs-1909-1916-1925-1927.test.cjs",
|
||||
"tests/loop-hooks-empty-points-e2e.test.cjs",
|
||||
"tests/loop-hooks-ship-pre-e2e.test.cjs",
|
||||
"tests/loop-hooks-verify-post-e2e.test.cjs",
|
||||
"tests/loop-render-hooks.test.cjs",
|
||||
"tests/managed-hooks.test.cjs",
|
||||
"tests/manifest-version-sync.test.cjs",
|
||||
"tests/markdown-table.test.cjs",
|
||||
"tests/mcp-catalog.property.test.cjs",
|
||||
"tests/mcp-catalog.test.cjs",
|
||||
"tests/milestone-archive.test.cjs",
|
||||
"tests/milestone-lock.test.cjs",
|
||||
"tests/milestone-prefixed-convention.test.cjs",
|
||||
"tests/milestone-window-drift-guard.test.cjs",
|
||||
"tests/milestone-window-single-owner.test.cjs",
|
||||
"tests/milestone.test.cjs",
|
||||
"tests/model-omit-when-inherit-guard.test.cjs",
|
||||
"tests/model-profiles.test.cjs",
|
||||
"tests/model-resolver.test.cjs",
|
||||
"tests/mutation-matrix-ratchet.test.cjs",
|
||||
"tests/mutation-score-ratchet.test.cjs",
|
||||
"tests/mutation-workflow-base-ref.test.cjs",
|
||||
"tests/mvp-phase-integration.test.cjs",
|
||||
"tests/new-milestone-clear-phases.test.cjs",
|
||||
"tests/next-decimal-roadmap-scan.test.cjs",
|
||||
"tests/next-up-clear-order.test.cjs",
|
||||
"tests/no-bare-gsd-tools-command-position.test.cjs",
|
||||
"tests/no-bare-npm-exec.rule.test.cjs",
|
||||
"tests/no-dead-sdk-refs.test.cjs",
|
||||
"tests/no-exact-case-env-access.rule.test.cjs",
|
||||
"tests/no-hardcoded-home-gsd-tools.test.cjs",
|
||||
"tests/no-hardcoded-tmp.rule.test.cjs",
|
||||
"tests/no-path-literal-in-assert.rule.test.cjs",
|
||||
"tests/no-pending-3212-markers.test.cjs",
|
||||
"tests/no-phantom-issue-refs.test.cjs",
|
||||
"tests/no-posix-mode-bit-assert.rule.test.cjs",
|
||||
"tests/no-private-binary-resolution.rule.test.cjs",
|
||||
"tests/no-rendered-text-length-assert.rule.test.cjs",
|
||||
"tests/no-swallowed-precondition.rule.test.cjs",
|
||||
"tests/no-unbounded-dirname-walk.rule.test.cjs",
|
||||
"tests/no-unbounded-spawn-allowlist.test.cjs",
|
||||
"tests/no-unbounded-spawn.test.cjs",
|
||||
"tests/no-unguarded-nonportable-exec.rule.test.cjs",
|
||||
"tests/normalize-path-in-content.rule.test.cjs",
|
||||
"tests/normalize-test-command.test.cjs",
|
||||
"tests/npm-audit-baseline.test.cjs",
|
||||
"tests/npm-integrity-gate.test.cjs",
|
||||
"tests/onboard-command.test.cjs",
|
||||
"tests/opencode-command-dir-plural.test.cjs",
|
||||
"tests/opencode-permissions.test.cjs",
|
||||
"tests/opencode-plugin-adapter.test.cjs",
|
||||
"tests/orphan-worktree-detection.test.cjs",
|
||||
"tests/orphaned-hooks.test.cjs",
|
||||
"tests/overlay-repo-helpers.test.cjs",
|
||||
"tests/package-name-single-source.test.cjs",
|
||||
"tests/packaging-shipped-scripts-require-only-shipped.test.cjs",
|
||||
"tests/parallel-dependent-plans.test.cjs",
|
||||
"tests/path-replacement.test.cjs",
|
||||
"tests/pattern-mapper.test.cjs",
|
||||
"tests/pattern.test.cjs",
|
||||
"tests/pause-work-context-detection.test.cjs",
|
||||
"tests/perf-317-context-monitor-fs.test.cjs",
|
||||
"tests/phase-command-router.test.cjs",
|
||||
"tests/phase-completion-single-owner.test.cjs",
|
||||
"tests/phase-estimation.test.cjs",
|
||||
"tests/phase-id-drift-guard.test.cjs",
|
||||
"tests/phase-locator.test.cjs",
|
||||
"tests/phase-resolution-parity.test.cjs",
|
||||
"tests/phase-tdd-applicable.test.cjs",
|
||||
"tests/phase.test.cjs",
|
||||
"tests/phase6-capstone-conformance.test.cjs",
|
||||
"tests/phases-command-router.test.cjs",
|
||||
"tests/pi-config-dir-env-override.test.cjs",
|
||||
"tests/pi-extension-reachability.test.cjs",
|
||||
"tests/pick-flag.test.cjs",
|
||||
"tests/plan-bounce.test.cjs",
|
||||
"tests/plan-count-single-owner.test.cjs",
|
||||
"tests/plan-phase-drift-guard.test.cjs",
|
||||
"tests/plan-phase-mvp-flag.test.cjs",
|
||||
"tests/plan-phase-stall-detection.test.cjs",
|
||||
"tests/plan-pre-hook-e2e.test.cjs",
|
||||
"tests/plan-review-convergence.test.cjs",
|
||||
"tests/planning-inspect.test.cjs",
|
||||
"tests/planning-inspect.unit.test.cjs",
|
||||
"tests/planning-lock-mkdir-failure-1884.test.cjs",
|
||||
"tests/planning-prompt-drift.test.cjs",
|
||||
"tests/planning-snapshot-bypass-drift.test.cjs",
|
||||
"tests/planning-snapshot.test.cjs",
|
||||
"tests/planning-workspace.test.cjs",
|
||||
"tests/platform-conformance-tier.test.cjs",
|
||||
"tests/platform-guard.unit.test.cjs",
|
||||
"tests/playwright-ui-verify.test.cjs",
|
||||
"tests/plugin-manifest.test.cjs",
|
||||
"tests/policy-160-route0-resume.test.cjs",
|
||||
"tests/policy-shell-pinning.test.cjs",
|
||||
"tests/portability-rule-disable-ban.test.cjs",
|
||||
"tests/portability-vocab-drift.test.cjs",
|
||||
"tests/post-planning-gaps-2493.test.cjs",
|
||||
"tests/pr-branch-planning-filter.test.cjs",
|
||||
"tests/precommit-alias-drift-hook.test.cjs",
|
||||
"tests/precondition-element.test.cjs",
|
||||
"tests/prepush-enterprise-email-hook.test.cjs",
|
||||
"tests/probe-core.test.cjs",
|
||||
"tests/process-seam.test.cjs",
|
||||
"tests/profile-output.test.cjs",
|
||||
"tests/profile-pipeline.test.cjs",
|
||||
"tests/prohibition-enforcement.test.cjs",
|
||||
"tests/prohibition-probe.verify-tier.test.cjs",
|
||||
"tests/project-instruction-file-parity.test.cjs",
|
||||
"tests/project-root.test.cjs",
|
||||
"tests/prompt-budget-cli.test.cjs",
|
||||
"tests/prune-orphaned-worktrees.test.cjs",
|
||||
"tests/quick-batch-command-router.test.cjs",
|
||||
"tests/quick-batch.test.cjs",
|
||||
"tests/quick-branching.test.cjs",
|
||||
"tests/quick-research.test.cjs",
|
||||
"tests/quick-review-scope-tip-bound.test.cjs",
|
||||
"tests/qwen-upgrades.test.cjs",
|
||||
"tests/read-guard.test.cjs",
|
||||
"tests/read-injection-scanner.property.test.cjs",
|
||||
"tests/reapply-patches.test.cjs",
|
||||
"tests/reapply-verify-hunks.test.cjs",
|
||||
"tests/refactor-trigger-cli.test.cjs",
|
||||
"tests/registry-reviewer-parity.test.cjs",
|
||||
"tests/release-hotfix-empty-cherry-pick.test.cjs",
|
||||
"tests/removed-but-needed-lint.test.cjs",
|
||||
"tests/repo-invariants.test.cjs",
|
||||
"tests/repo-layout.test.cjs",
|
||||
"tests/representative-corpus.test.cjs",
|
||||
"tests/require-fs-op-fallback.rule.test.cjs",
|
||||
"tests/require-full-tmpdir-triad.rule.test.cjs",
|
||||
"tests/require-issue-link-policy.test.cjs",
|
||||
"tests/require-userprofile-with-home.rule.test.cjs",
|
||||
"tests/research-cli.test.cjs",
|
||||
"tests/research-store.test.cjs",
|
||||
"tests/resolve-execution-dynamic-routing.test.cjs",
|
||||
"tests/resolver-hoist-guard.test.cjs",
|
||||
"tests/response-language-coverage.test.cjs",
|
||||
"tests/retired-artifact-cleanup.test.cjs",
|
||||
"tests/reversibility-tagging.test.cjs",
|
||||
"tests/review-build-prompt-optional-sections.test.cjs",
|
||||
"tests/review-default-reviewers-config.test.cjs",
|
||||
"tests/review-default-reviewers-workflow.test.cjs",
|
||||
"tests/review-lane-descriptor.test.cjs",
|
||||
"tests/review-lane-invocation.test.cjs",
|
||||
"tests/review-lane-runner.test.cjs",
|
||||
"tests/review-lane-windows-spawn-resolution.test.cjs",
|
||||
"tests/review-model-config.test.cjs",
|
||||
"tests/review-parallel-lanes.test.cjs",
|
||||
"tests/review-plan-coverage-manifest.test.cjs",
|
||||
"tests/review-reviewer-instances-config.test.cjs",
|
||||
"tests/reviewer-config-federation.test.cjs",
|
||||
"tests/reviewer-docs-parity.test.cjs",
|
||||
"tests/reviewer-lane-declarations.test.cjs",
|
||||
"tests/reviewer-manifest-body.test.cjs",
|
||||
"tests/reviewer-step-dispatch.test.cjs",
|
||||
"tests/reviewer-trust-disclosure.test.cjs",
|
||||
"tests/revision-remediation-binding.test.cjs",
|
||||
"tests/roadmap-mode-field.test.cjs",
|
||||
"tests/roadmap-parser.test.cjs",
|
||||
"tests/roadmap-phase-fallback.test.cjs",
|
||||
"tests/roadmap-upgrade.test.cjs",
|
||||
"tests/roadmap.test.cjs",
|
||||
"tests/roadmapper-granularity.test.cjs",
|
||||
"tests/run-tests-harness.test.cjs",
|
||||
"tests/run-tests-temp-root.test.cjs",
|
||||
"tests/run-with-timeout.test.cjs",
|
||||
"tests/runtime-artifact-install-plan.test.cjs",
|
||||
"tests/runtime-artifact-layout-descriptor-drive.test.cjs",
|
||||
"tests/runtime-artifact-layout-install-profiles.test.cjs",
|
||||
"tests/runtime-artifact-layout-surface.test.cjs",
|
||||
"tests/runtime-artifact-layout.test.cjs",
|
||||
"tests/runtime-converters.test.cjs",
|
||||
"tests/runtime-homes-descriptor-drive.test.cjs",
|
||||
"tests/runtime-homes.property.test.cjs",
|
||||
"tests/runtime-identity.test.cjs",
|
||||
"tests/runtime-launcher-parity.test.cjs",
|
||||
"tests/runtime-name-policy.test.cjs",
|
||||
"tests/safe-resume-gate-anchoring.test.cjs",
|
||||
"tests/schema-drift.test.cjs",
|
||||
"tests/sdk-removal-query-family-dispatch.test.cjs",
|
||||
"tests/section-manifest-init-facts.test.cjs",
|
||||
"tests/section-manifest.test.cjs",
|
||||
"tests/security.test.cjs",
|
||||
"tests/settings-integrations.test.cjs",
|
||||
"tests/settings-jsonc.test.cjs",
|
||||
"tests/sh-hook-paths.test.cjs",
|
||||
"tests/shadow-report.test.cjs",
|
||||
"tests/shared-hooks-dir-resolution.test.cjs",
|
||||
"tests/shell-command-projection-dispatch.test.cjs",
|
||||
"tests/shell-command-projection-path-sep.test.cjs",
|
||||
"tests/ship-notes-wedged-pr.test.cjs",
|
||||
"tests/shipped-reference-cites.test.cjs",
|
||||
"tests/skill-frontmatter-contract.test.cjs",
|
||||
"tests/skill-manifest.test.cjs",
|
||||
"tests/slash-command-namespace.test.cjs",
|
||||
"tests/slug-derivation-drift-guard.test.cjs",
|
||||
"tests/smart-entry.unit.test.cjs",
|
||||
"tests/spec-section.test.cjs",
|
||||
"tests/stale-bake-guard.test.cjs",
|
||||
"tests/state-command-cutover.test.cjs",
|
||||
"tests/state-contract.test.cjs",
|
||||
"tests/state-document.test.cjs",
|
||||
"tests/state-field-drift.test.cjs",
|
||||
"tests/state-io.test.cjs",
|
||||
"tests/state-prune.test.cjs",
|
||||
"tests/state-rebuild-cli.test.cjs",
|
||||
"tests/state-todos-render.test.cjs",
|
||||
"tests/state-transition.test.cjs",
|
||||
"tests/state-write-path-drift-guard.test.cjs",
|
||||
"tests/state.test.cjs",
|
||||
"tests/stats-mvp-display.test.cjs",
|
||||
"tests/stats-phase-id-shape.test.cjs",
|
||||
"tests/subagent-timeout.test.cjs",
|
||||
"tests/summary-status-blocked-3345.test.cjs",
|
||||
"tests/surface-md-paths.regression.test.cjs",
|
||||
"tests/sync-skills-cross-runtime-refuse.test.cjs",
|
||||
"tests/table-schema-drift-lint.test.cjs",
|
||||
"tests/tdd-backend-wiring.test.cjs",
|
||||
"tests/tdd-mode.test.cjs",
|
||||
"tests/tdd-red-evidence.test.cjs",
|
||||
"tests/tdd-single-statement.test.cjs",
|
||||
"tests/teams-status.test.cjs",
|
||||
"tests/template.test.cjs",
|
||||
"tests/thinking-partner.test.cjs",
|
||||
"tests/todos-done-rename-guard.test.cjs",
|
||||
"tests/todos-workstream-scope.test.cjs",
|
||||
"tests/tracer-bullet.test.cjs",
|
||||
"tests/trae-imperative-reference.test.cjs",
|
||||
"tests/tsconfig-noemit.test.cjs",
|
||||
"tests/uat-predicate.test.cjs",
|
||||
"tests/uat.test.cjs",
|
||||
"tests/ui-spec-inventory-provenance.test.cjs",
|
||||
"tests/ultraplan-phase.test.cjs",
|
||||
"tests/unreachable-guard-drift.test.cjs",
|
||||
"tests/unreachable-shell-guard.test.cjs",
|
||||
"tests/unusable-input.test.cjs",
|
||||
"tests/update-context.test.cjs",
|
||||
"tests/update-custom-backup.test.cjs",
|
||||
"tests/update-workflow.test.cjs",
|
||||
"tests/user-artifact-staging.test.cjs",
|
||||
"tests/validate-context.test.cjs",
|
||||
"tests/validate-registry.test.cjs",
|
||||
"tests/verification-status.test.cjs",
|
||||
"tests/verify-archive-dirs-live-path.test.cjs",
|
||||
"tests/verify-command-grounding.test.cjs",
|
||||
"tests/verify-health.test.cjs",
|
||||
"tests/verify.test.cjs",
|
||||
"tests/vscode-browser-no-node-api.test.cjs",
|
||||
"tests/vscode-extension-reachability.test.cjs",
|
||||
"tests/windows-robustness.test.cjs",
|
||||
"tests/windsurf-conversion.test.cjs",
|
||||
"tests/windsurf-hooks-bridge.test.cjs",
|
||||
"tests/windsurf-install.test.cjs",
|
||||
"tests/workflow-compat.test.cjs",
|
||||
"tests/workflow-fragments.test.cjs",
|
||||
"tests/workflow-guard.test.cjs",
|
||||
"tests/workflow-maintainer-skip.test.cjs",
|
||||
"tests/workflow-shell-pinning.test.cjs",
|
||||
"tests/workspace.test.cjs",
|
||||
"tests/workstream-inventory.test.cjs",
|
||||
"tests/workstream-scoped-paths.test.cjs",
|
||||
"tests/workstream.test.cjs",
|
||||
"tests/worktree-base-ref.test.cjs",
|
||||
"tests/worktree-baseref-install.test.cjs",
|
||||
"tests/worktree-cleanup.test.cjs",
|
||||
"tests/worktree-safety-reap.test.cjs",
|
||||
"tests/worktree-safety.test.cjs",
|
||||
"tests/worktree.test.cjs",
|
||||
],
|
||||
};
|
||||
32
scripts/lib/suite-detection.cjs
Normal file
32
scripts/lib/suite-detection.cjs
Normal file
@@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Suite classification by filename suffix (#4591 packaging fix — extracted
|
||||
* from scripts/run-tests.cjs so a SHIPPED script, e.g.
|
||||
* scripts/gen-platform-conformance-tier.cjs, can depend on it: run-tests.cjs
|
||||
* itself does not ship (it is a repo-development-only tool), so a shipped
|
||||
* file requiring it directly is MODULE_NOT_FOUND in a published install
|
||||
* (tests/packaging-shipped-scripts-require-only-shipped.test.cjs, #2858).
|
||||
* run-tests.cjs re-exports suiteOf from here unchanged for full backward
|
||||
* compatibility — this is a pure relocation, not a behavior change.
|
||||
*
|
||||
* A file with no suite suffix (plain `foo.test.cjs`) belongs to the `unit`
|
||||
* suite and returns `null` here; a suite-tagged file (`foo.install.test.cjs`)
|
||||
* returns its marker string.
|
||||
*/
|
||||
|
||||
const { basename } = require('node:path');
|
||||
|
||||
const MARKED_SUITES = ['integration', 'install', 'security', 'slow', 'qa'];
|
||||
|
||||
function suiteOf(filename) {
|
||||
const name = basename(filename);
|
||||
if (!name.endsWith('.test.cjs')) return null;
|
||||
const base = name.slice(0, -'.test.cjs'.length);
|
||||
const lastDot = base.lastIndexOf('.');
|
||||
if (lastDot === -1) return null;
|
||||
const marker = base.slice(lastDot + 1);
|
||||
return MARKED_SUITES.includes(marker) ? marker : null;
|
||||
}
|
||||
|
||||
module.exports = { MARKED_SUITES, suiteOf };
|
||||
@@ -41,6 +41,7 @@ const { tmpdir } = require('os');
|
||||
const { pathToFileURL } = require('url');
|
||||
const { execFileSync } = require('child_process');
|
||||
const { ExitError, runMain } = require('./lib/cli-exit.cjs');
|
||||
const { suiteOf } = require('./lib/suite-detection.cjs');
|
||||
const {
|
||||
resolveLiveConfigRoots,
|
||||
resolveExtraWatchTargets,
|
||||
@@ -179,8 +180,6 @@ function ensureBuiltHooks(overrides = {}) {
|
||||
runBuild();
|
||||
}
|
||||
}
|
||||
const MARKED_SUITES = ['integration', 'install', 'security', 'slow', 'qa'];
|
||||
|
||||
// Recursively collect *.test.cjs files under dir, returning paths relative to dir.
|
||||
// Skips node_modules to avoid accidentally picking up decoy files.
|
||||
function walkTestFiles(dir, relBase) {
|
||||
@@ -794,20 +793,8 @@ function parseArgs(argv) {
|
||||
return { suite, files, filesFrom, shard };
|
||||
}
|
||||
|
||||
// Return the marked suite name embedded in a filename, or null if it's unmarked.
|
||||
// foo.security.test.cjs -> "security"
|
||||
// foo.test.cjs -> null (unit)
|
||||
// Accepts either a bare filename or a relative subdir path; classification is
|
||||
// based on the basename only so subdir paths classify identically to root files.
|
||||
function suiteOf(filename) {
|
||||
const name = basename(filename);
|
||||
if (!name.endsWith('.test.cjs')) return null;
|
||||
const base = name.slice(0, -'.test.cjs'.length);
|
||||
const lastDot = base.lastIndexOf('.');
|
||||
if (lastDot === -1) return null;
|
||||
const marker = base.slice(lastDot + 1);
|
||||
return MARKED_SUITES.includes(marker) ? marker : null;
|
||||
}
|
||||
// suiteOf (and its backing MARKED_SUITES) is imported from
|
||||
// ./lib/suite-detection.cjs — see that module's header comment for why.
|
||||
|
||||
function selectFiles(allFiles, suite) {
|
||||
if (suite === null || suite === 'all') {
|
||||
|
||||
Reference in New Issue
Block a user