test(#1977): consolidate 22 misc + repo-invariant regression tests

Final epic-#1969 batch. Fold 22 issue-named files: the 4 genuine repo-wide invariant
scans (551-eslint-bin-lib-coverage, bug-3054 stale /gsd-next, bug-3810 no-gsd-sdk-runtime-refs,
feat-3593 cli-negative-universal) into a NEW shared repo-invariants.test.cjs; the other 18 as
singletons into their nearest module suite (model-resolver, codex-config, runtime-converters,
security, state-transition, worktree-safety, roadmap-parser, etc.). Verbatim block-scoped
describe wrappers; 334 subtests conserved 1:1.

Host-env pre-check (B2+B6): the 6 CLI folds into GSD_TEST_MODE-setting hosts (model-resolver/
codex-config/runtime-converters) are benign — each origin independently sets GSD_TEST_MODE=1
itself (idempotent), unlike the B6 real-install case.

Regenerates regression-name allowlist (222->213), ratchets file-count allowlist (state 17->16),
makes 7 relocated allow-test-rule exemptions issue-ref-compliant (ADR-456; prunes stale ids).
Repoints 2 tests/ refs in docs/TESTING-SUITES.md. lint:ci green.

Part of epic #1969. Closes #1977.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-07-03 03:33:07 -04:00
parent 4c77b46e3d
commit 697cbb1f05
41 changed files with 5972 additions and 5767 deletions

View File

@@ -838,3 +838,246 @@ describe('scanEntropyAnomalies', () => {
assert.equal(result.findings.length, 1, 'only 1 high-entropy paragraph should be flagged');
});
});
// ────────────────────────────────────────────────────────────────────────
// Folded from tests/fix-1627-asvs-level-scaling.test.cjs — consolidation epic #1969 (B8 #1977)
// ────────────────────────────────────────────────────────────────────────
{
const { describe: __foldDescribe } = require('node:test');
__foldDescribe("folded:fix-1627-asvs-level-scaling (consolidation epic #1969 B8 #1977)", () => {
// allow-test-rule: source-text-is-the-product #1627
// Agent .md / reference .md files — their text IS what the runtime loads.
// Testing text content tests the deployed contract.
// Per CONTRIBUTING.md exception matrix.
/**
* Fix #1627 — ASVS level scaling
*
* Asserts that `workflow.security_asvs_level` now scales both planner
* threat-disposition rigor and auditor verification depth rather than
* being display-only.
*/
'use strict';
const { describe, test } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const ROOT = path.join(__dirname, '..');
const AGENTS_DIR = path.join(ROOT, 'agents');
const REFS_DIR = path.join(ROOT, 'gsd-core', 'references');
const MANIFEST_PATH = path.join(ROOT, 'docs', 'INVENTORY-MANIFEST.json');
describe('SECURE: ASVS level scaling (#1627)', () => {
// ── 1. New reference file ────────────────────────────────────────────────
describe('security-asvs-levels.md reference', () => {
const refPath = path.join(REFS_DIR, 'security-asvs-levels.md');
test('file exists', () => {
assert.ok(fs.existsSync(refPath), 'gsd-core/references/security-asvs-levels.md must exist');
});
test('defines all three levels', () => {
const content = fs.readFileSync(refPath, 'utf-8');
assert.ok(content.includes('L1'), 'must define L1');
assert.ok(content.includes('L2'), 'must define L2');
assert.ok(content.includes('L3'), 'must define L3');
});
test('L1 describes opportunistic scope and planner disposition', () => {
const content = fs.readFileSync(refPath, 'utf-8');
assert.ok(
content.toLowerCase().includes('opportunistic'),
'L1 must be described as opportunistic'
);
assert.ok(
content.includes('mitigate') && content.includes('accept'),
'must describe mitigate/accept dispositions'
);
});
test('L2 requires explicit rationale for accepted threats', () => {
const content = fs.readFileSync(refPath, 'utf-8');
// L2 must require documented rationale for accepted risks
assert.ok(
content.includes('rationale') || content.includes('documented'),
'L2 must require documented rationale for accepted threats'
);
});
test('L3 describes deep/comprehensive verification', () => {
const content = fs.readFileSync(refPath, 'utf-8');
const lower = content.toLowerCase();
assert.ok(
lower.includes('deep') || lower.includes('comprehensive') || lower.includes('exhaustive'),
'L3 must describe deep/comprehensive verification'
);
});
test('mentions that higher levels are supersets of lower', () => {
const content = fs.readFileSync(refPath, 'utf-8');
const lower = content.toLowerCase();
assert.ok(
lower.includes('superset') || lower.includes('higher level') || lower.includes('includes all'),
'must note that higher levels are supersets of lower'
);
});
test('describes distinct auditor verification depth for each level', () => {
const content = fs.readFileSync(refPath, 'utf-8');
// All three audit depth keywords should appear
assert.ok(content.includes('grep') || content.includes('PRESENT'), 'L1 audit depth must mention grep/presence check');
assert.ok(content.includes('boundary') || content.includes('addresses'), 'L2 audit depth must mention boundary/addresses');
assert.ok(content.includes('end-to-end') || content.includes('bypass'), 'L3 audit depth must mention end-to-end or bypass check');
});
});
// ── 2. gsd-planner.md — no hardcoded L1 in disposition ──────────────────
describe('gsd-planner.md security disposition', () => {
const plannerPath = path.join(AGENTS_DIR, 'gsd-planner.md');
test('planner security instruction does not hardcode "ASVS L1"', () => {
const content = fs.readFileSync(plannerPath, 'utf-8');
// The old bug: "mitigate if ASVS L1 requires it" — must be gone
assert.ok(
!content.includes('ASVS L1 requires it'),
'planner must not hardcode "ASVS L1 requires it"; it must reference the configured level'
);
});
test('planner references the configured OWASP ASVS level', () => {
const content = fs.readFileSync(plannerPath, 'utf-8');
assert.ok(
content.includes('OWASP ASVS level') || content.includes('configured OWASP'),
'planner must reference the configured OWASP ASVS level'
);
});
test('planner @-references security-asvs-levels.md', () => {
const content = fs.readFileSync(plannerPath, 'utf-8');
assert.ok(
content.includes('security-asvs-levels.md'),
'planner must @-reference security-asvs-levels.md'
);
});
test('planner is under the 49152-char cap', () => {
const content = fs.readFileSync(plannerPath, 'utf-8').replace(/\r\n/g, '\n').replace(/\r/g, '\n');
assert.ok(
content.length < 49152,
`gsd-planner.md must be < 49152 chars (LF-normalized); got ${content.length}`
);
});
});
// ── 3. gsd-security-auditor.md — scaled verification depth ──────────────
describe('gsd-security-auditor.md verification depth', () => {
const auditorPath = path.join(AGENTS_DIR, 'gsd-security-auditor.md');
test('auditor scales verification depth by asvs_level', () => {
const content = fs.readFileSync(auditorPath, 'utf-8');
assert.ok(
content.includes('asvs_level') || content.includes('ASVS level'),
'auditor must reference asvs_level to scale verification'
);
});
test('auditor describes L1/L2/L3 depth differences', () => {
const content = fs.readFileSync(auditorPath, 'utf-8');
// All three levels must appear in context of depth scaling
assert.ok(content.includes('L1'), 'auditor must mention L1 depth');
assert.ok(content.includes('L2'), 'auditor must mention L2 depth');
assert.ok(content.includes('L3'), 'auditor must mention L3 depth');
});
test('auditor @-references security-asvs-levels.md', () => {
const content = fs.readFileSync(auditorPath, 'utf-8');
assert.ok(
content.includes('security-asvs-levels.md'),
'auditor must @-reference security-asvs-levels.md'
);
});
test('auditor still echoes ASVS Level in structured output', () => {
const content = fs.readFileSync(auditorPath, 'utf-8');
assert.ok(
content.includes('ASVS Level:') && content.includes('{1/2/3}'),
'auditor must still emit ASVS Level in SECURED/OPEN_THREATS output'
);
});
});
// ── 4. secure-phase.md — ASVS-aware short-circuit ──────────────────────
describe('secure-phase.md short-circuit conditioned on asvs_level', () => {
const wfPath = path.join(ROOT, 'gsd-core', 'workflows', 'secure-phase.md');
test('short-circuit to Step 6 is gated on asvs_level == 1', () => {
const content = fs.readFileSync(wfPath, 'utf-8');
// The condition must reference asvs_level so that L2/L3 don't skip the auditor
assert.ok(
content.includes('asvs_level == 1'),
'secure-phase.md must gate the skip-to-Step-6 short-circuit on asvs_level == 1'
);
});
test('auditor runs at L2/L3 even when threats_open is 0 (asvs_level >= 2 branch present)', () => {
const content = fs.readFileSync(wfPath, 'utf-8');
// The >= 2 branch must explicitly say the auditor is spawned for L2/L3 deep verification
assert.ok(
content.includes('asvs_level >= 2'),
'secure-phase.md must include asvs_level >= 2 branch that does NOT skip the auditor'
);
// The >= 2 branch must make clear the auditor is spawned (not skipped)
assert.ok(
content.includes('L2/L3 deep verification') || content.includes('L2 boundary') || content.includes('L3 end-to-end'),
'secure-phase.md asvs_level >= 2 branch must reference L2/L3 deep verification'
);
});
});
// ── 5. security-asvs-levels.md — L1 medium-severity gap closed ──────────
describe('security-asvs-levels.md L1 medium-severity is specified', () => {
const refPath = path.join(REFS_DIR, 'security-asvs-levels.md');
test('L1 explicitly handles medium-severity threats (no gap)', () => {
const content = fs.readFileSync(refPath, 'utf-8');
// L1 section must say something about medium-severity
assert.ok(
content.includes('medium-severity') || content.includes('medium severity'),
'L1 must explicitly specify disposition for medium-severity threats (no ambiguity gap)'
);
});
test('L1 medium-severity disposition is conditional (trust-boundary-aware)', () => {
const content = fs.readFileSync(refPath, 'utf-8');
// L1 must distinguish between medium on primary trust boundary vs not
assert.ok(
content.includes('trust boundary') || content.includes('primary trust'),
'L1 medium-severity rule must reference trust boundary to disambiguate disposition'
);
});
});
// ── 6. Inventory manifest ─────────────────────────────────────────────────
describe('inventory manifest', () => {
test('security-asvs-levels.md is registered in INVENTORY-MANIFEST.json', () => {
const manifest = JSON.parse(fs.readFileSync(MANIFEST_PATH, 'utf-8'));
const refs = (manifest.families || {}).references || [];
assert.ok(
refs.includes('security-asvs-levels.md'),
'security-asvs-levels.md must appear in families.references of INVENTORY-MANIFEST.json'
);
});
});
});
});
}