fix(rm-02): narrow inventory drift guarantee
ci/woodpecker/pr/ci Pipeline was successful

This commit is contained in:
2026-08-01 15:09:57 -05:00
parent c5b0d510d7
commit e910a45ab3
13 changed files with 203 additions and 38 deletions
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env node
import { readFile } from 'node:fs/promises';
import path from 'node:path';
const boundary =
"Detects accidental and incompetent inventory drift within a checkout; does NOT survive an adversary who rewrites baseline, manifest, and verifier consistently — that guarantee requires RM-60's external boundary.";
const artifacts = [
'gates/required-gates.baseline.json',
'gates/gates.manifest.json',
'docs/PRD.md',
'docs/ADMIN-GUIDE/quality-gate-registry.md',
'docs/DEVELOPER-GUIDE/quality-gate-registry.md',
'docs/remediation/GATE-CLAIMS.md',
'docs/plans/2026-08-01-rm-02-gate-registry.md',
'docs/SITEMAP.md',
];
const forbidden = [
/\bindependent\b[^\n.]{0,80}\bbaseline\b/i,
/independently baselined/i,
/independently anchored inventory/i,
/protected (?:inventory )?(?:anchor|baseline)/i,
/inventory (?:anchor|anchored)/i,
];
const failures = [];
for (const relativePath of artifacts) {
const contents = await readFile(path.join(process.cwd(), relativePath), 'utf8');
const claims =
relativePath === 'gates/gates.manifest.json'
? JSON.parse(contents)
.criteria.map((criterion) => criterion.currentText)
.join('\n')
: contents;
if (!claims.includes(boundary)) failures.push(`${relativePath}: narrowed boundary is missing`);
const overclaim = forbidden.find((pattern) => pattern.test(claims));
if (overclaim) failures.push(`${relativePath}: inventory protection is overstated`);
}
if (failures.length > 0) {
for (const failure of failures) {
process.stderr.write(`INVENTORY_CLAIM_OVERSTATED: ${failure}\n`);
}
process.exit(84);
}
process.stdout.write('inventory drift boundary is stated in both directions; owner RM-60\n');
+43 -3
View File
@@ -58,7 +58,7 @@ function shrinkManifest(manifest, removedGateId) {
}
}
test('shrinking the verifier inventory and manifest together is rejected by an independent baseline', async () => {
test('shrinking the verifier inventory and manifest together is rejected by a same-checkout baseline', async () => {
const fixture = await mkdtemp(path.join(os.tmpdir(), 'rm02-shrink-both-'));
try {
await mkdir(path.join(fixture, 'scripts'), { recursive: true });
@@ -94,13 +94,13 @@ test('shrinking the verifier inventory and manifest together is rejected by an i
{ cwd: fixture, encoding: 'utf8' },
);
assert.notEqual(result.status, 0, 'shrinking source anchor and manifest together must go red');
assert.match(output(result), /independent required-gate baseline.*hook-pre-push/i);
assert.match(output(result), /same-checkout required-gate baseline.*hook-pre-push/i);
} finally {
await rm(fixture, { recursive: true, force: true });
}
});
test('shrinking the independent baseline and manifest together is rejected by verifier inventory', async () => {
test('shrinking the same-checkout baseline and manifest together is rejected by verifier inventory', async () => {
const fixture = await mkdtemp(path.join(os.tmpdir(), 'rm02-shrink-baseline-manifest-'));
try {
await mkdir(path.join(fixture, 'scripts'), { recursive: true });
@@ -154,6 +154,46 @@ test('every gate carries an evidence-side subject distinct from its definition',
}
});
test('inventory claim control rejects qualified independence wording', async () => {
const fixture = await mkdtemp(path.join(os.tmpdir(), 'rm02-inventory-overclaim-'));
const artifacts = [
'gates/required-gates.baseline.json',
'gates/gates.manifest.json',
'docs/PRD.md',
'docs/ADMIN-GUIDE/quality-gate-registry.md',
'docs/DEVELOPER-GUIDE/quality-gate-registry.md',
'docs/remediation/GATE-CLAIMS.md',
'docs/plans/2026-08-01-rm-02-gate-registry.md',
'docs/SITEMAP.md',
];
try {
await mkdir(path.join(fixture, 'scripts'), { recursive: true });
await copyFile(
path.join(root, 'scripts', 'gate-inventory-claim-control.mjs'),
path.join(fixture, 'scripts', 'gate-inventory-claim-control.mjs'),
);
for (const relativePath of artifacts) {
const target = path.join(fixture, relativePath);
await mkdir(path.dirname(target), { recursive: true });
await copyFile(path.join(root, relativePath), target);
}
const prd = path.join(fixture, 'docs', 'PRD.md');
await writeFile(
prd,
`${await readFile(prd, 'utf8')}\nThis provides an independent seven-gate baseline comparison.\n`,
);
const result = spawnSync(
process.execPath,
[path.join(fixture, 'scripts', 'gate-inventory-claim-control.mjs')],
{ cwd: fixture, encoding: 'utf8' },
);
assert.equal(result.status, 84, output(result));
assert.match(output(result), /INVENTORY_CLAIM_OVERSTATED.*docs\/PRD\.md/i);
} finally {
await rm(fixture, { recursive: true, force: true });
}
});
test('evidence population control depends on production result consumption wiring', async () => {
const fixture = await mkdtemp(path.join(os.tmpdir(), 'rm02-evidence-consumer-inert-'));
try {
+7 -7
View File
@@ -591,20 +591,20 @@ function validateClosedSchema(
rejectDuplicateIds(manifest.gates, 'gate', failures);
if (!fixtureProfile) {
if (!(requiredGateInventory instanceof Map) || requiredGateInventory.size === 0) {
failures.push('independent required-gate baseline is absent or empty');
failures.push('same-checkout required-gate baseline is absent or empty');
} else {
if (!inventoriesEqual(REQUIRED_GATE_INVENTORY, requiredGateInventory)) {
for (const [requiredId, requiredSource] of requiredGateInventory) {
if (REQUIRED_GATE_INVENTORY.get(requiredId) !== requiredSource) {
failures.push(
`independent required-gate baseline rejects verifier inventory drift at ${requiredId}`,
`same-checkout required-gate baseline rejects verifier inventory drift at ${requiredId}`,
);
}
}
for (const [requiredId, requiredSource] of REQUIRED_GATE_INVENTORY) {
if (requiredGateInventory.get(requiredId) !== requiredSource) {
failures.push(
`verifier inventory ${requiredId} is absent or changed in independent required-gate baseline`,
`verifier inventory ${requiredId} is absent or changed in same-checkout required-gate baseline`,
);
}
}
@@ -613,7 +613,7 @@ function validateClosedSchema(
const registered = (manifest.gates ?? []).find((gate) => gate?.id === requiredId);
if (!registered || registered.source !== requiredSource) {
failures.push(
`independent required-gate baseline rejects manifest drift at ${requiredId}: required source ${requiredSource}`,
`same-checkout required-gate baseline rejects manifest drift at ${requiredId}: required source ${requiredSource}`,
);
}
}
@@ -1128,15 +1128,15 @@ export async function verifyRegistry(options) {
gate.source.length === 0,
)
) {
failures.push('independent required-gate baseline has unsupported structure');
failures.push('same-checkout required-gate baseline has unsupported structure');
} else {
requiredGateInventory = new Map(baseline.gates.map((gate) => [gate.id, gate.source]));
if (requiredGateInventory.size !== baseline.gates.length) {
failures.push('independent required-gate baseline has duplicate gate ids');
failures.push('same-checkout required-gate baseline has duplicate gate ids');
}
}
} catch (error) {
failures.push(`independent required-gate baseline cannot be read: ${error.message}`);
failures.push(`same-checkout required-gate baseline cannot be read: ${error.message}`);
}
}
+1 -1
View File
@@ -161,7 +161,7 @@ test('anchored gate inventory and population criteria cannot shrink together', a
assert.notEqual(result.status, 0);
assert.match(
output(result),
/independent required-gate baseline rejects manifest drift at hook-pre-push/i,
/same-checkout required-gate baseline rejects manifest drift at hook-pre-push/i,
);
});