wip(rm-02): round-4 remediation held at RM-60 boundary
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
|
||||
import { chmod, mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
|
||||
@@ -27,7 +27,6 @@ async function rejectedForEveryGate(mutate, diagnostic) {
|
||||
const result = await verifyRegistry({
|
||||
root,
|
||||
manifest: manifestPath,
|
||||
skipHistory: true,
|
||||
structureOnly: true,
|
||||
fixtureProfile: false,
|
||||
});
|
||||
@@ -41,14 +40,81 @@ async function rejectedForEveryGate(mutate, diagnostic) {
|
||||
|
||||
let rejected;
|
||||
if (mode === 'evidence-subject') {
|
||||
rejected = await rejectedForEveryGate(
|
||||
(gate) => {
|
||||
gate.evidenceSubject = 'different-gate-subject';
|
||||
},
|
||||
(failure, gateId) =>
|
||||
failure.includes(`gate ${gateId}: evidence subject`) &&
|
||||
failure.includes('does not match gate id'),
|
||||
);
|
||||
rejected = true;
|
||||
for (const gateId of expectedGateIds) {
|
||||
const directory = await mkdtemp(path.join(os.tmpdir(), 'gate-evidence-consumption-'));
|
||||
try {
|
||||
await mkdir(path.join(directory, 'gates'), { recursive: true });
|
||||
const probe = path.join(directory, 'gates', 'probe.sh');
|
||||
await writeFile(probe, '#!/bin/sh\necho EVIDENCE_PROBE >&2\nexit 7\n');
|
||||
await chmod(probe, 0o755);
|
||||
const manifest = {
|
||||
schemaVersion: 1,
|
||||
gateRoots: ['gates'],
|
||||
governingClaimFiles: [],
|
||||
coverageBoundary: { included: ['evidence fixture'], excluded: [], trackedBy: 'RM-02' },
|
||||
criteria: [
|
||||
{
|
||||
id: 'EVIDENCE-CONSUMPTION',
|
||||
originalText: 'Consumed evidence stays bound to its gate.',
|
||||
currentText: 'Consumed evidence stays bound to its gate.',
|
||||
claimType: 'integrity',
|
||||
source: 'gate-population-control',
|
||||
meaningChanges: [],
|
||||
caseRefs: [`${gateId}/probe`],
|
||||
},
|
||||
],
|
||||
proseClaims: [],
|
||||
compatibilityScenarios: [],
|
||||
gates: [
|
||||
{
|
||||
id: gateId,
|
||||
source: 'gates/probe.sh',
|
||||
invocation: ['gates/probe.sh'],
|
||||
deployment: { kind: 'none', reason: 'population fixture' },
|
||||
inertMutation: {
|
||||
file: 'gates/probe.sh',
|
||||
find: 'exit 7',
|
||||
replace: 'exit 0',
|
||||
caseId: 'probe',
|
||||
expected: { exitCode: 0 },
|
||||
},
|
||||
cases: [
|
||||
{
|
||||
id: 'probe',
|
||||
criterionIds: ['EVIDENCE-CONSUMPTION'],
|
||||
mustFail: true,
|
||||
required: { exitCode: 7 },
|
||||
actual: { exitCode: 7 },
|
||||
evidence: { subject: 'different-gate-subject' },
|
||||
reasonPattern: 'EVIDENCE_PROBE',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const manifestPath = path.join(directory, 'gates', 'gates.manifest.json');
|
||||
await writeFile(manifestPath, `${JSON.stringify(manifest)}\n`);
|
||||
const result = await verifyRegistry({
|
||||
root: directory,
|
||||
manifest: manifestPath,
|
||||
structureOnly: false,
|
||||
fixtureProfile: true,
|
||||
});
|
||||
if (
|
||||
!result.failures.some(
|
||||
(failure) =>
|
||||
failure.includes(`gate ${gateId}: consumed evidence subject`) &&
|
||||
failure.includes('does not match gate definition'),
|
||||
)
|
||||
) {
|
||||
rejected = false;
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
await rm(directory, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
} else if (mode === 'type-strict') {
|
||||
rejected = await rejectedForEveryGate(
|
||||
(gate) => {
|
||||
|
||||
Reference in New Issue
Block a user