enhance(#1279): RED guards — node-test no-fixture + prover-throws fail-closed, both modes (FF-05/FF-04)

RED-first fail-closed guards on the prove seam, committed BEFORE the producer
change. All inject (or omit) proveFailFirst, which the current producer ignores
— so each FAILS against the attestation-greens code (actual 'green' vs
notStrictEqual 'green'). RED is INTENTIONAL; Plans 02-03 wire the default prover
and no-throw wrap to turn them green.

New tests:
- FF-05 no-fixture: node-test with no violationFixture, default prover (none
  injected) -> fail-closed, never attestation fallback (RED now)
- FF-05 no-throw: a proveFailFirst that THROWS fails closed, never greens (RED)
- FF-04 both-modes: un-provable check hard-gates in interactive AND autonomous,
  mode echoed (RED)

No source edited. 5 total #1279 guards now RED, 2 positive controls green.
Pre-existing 5 attestation-green tests untouched and still pass.
This commit is contained in:
Dave
2026-06-15 22:31:28 -04:00
parent 5b5e5bcf2e
commit 88a1e5da5a

View File

@@ -259,6 +259,61 @@ describe('prohibition-enforcement: deterministic test-tier producer (#1259 / ADR
assert.equal(result.located, true);
});
test('node-test with NO violationFixture fail-closes via the default prover, never falls back to attestation (FF-05)', () => {
const enforce = require(ENFORCEMENT_LIB);
// Decision-layer/default-prover guard: a node-test descriptor with no violationFixture cannot be
// machine-proven (a generic producer cannot synthesize a violation), so the DEFAULT real prover
// returns provenFailFirst:false -> hard-gate. We inject NO proveFailFirst so the default path is
// exercised. It must NEVER silently weaken to attestation. (Default prover lands in Plans 02-03,
// so this is RED now and greens with the producer change.)
const result = enforce.runProhibitionEnforcement(
TEST_TIER,
{ kind: 'node-test', target: 'tests/neg.test.cjs', failFirst: true },
{ runCheck: () => ({ passed: true }) },
);
assert.notEqual(result.status, 'green',
'a node-test with no violationFixture cannot be proven fail-first -> fail-closed (FF-05)');
assert.equal(result.flagged, true, 'an un-provable check is flagged');
assert.equal(result.located, true, 'the descriptor was located; it just could not be proven');
});
test('a proveFailFirst that THROWS fails closed, never propagates and never greens (FF-05 no-throw)', () => {
const enforce = require(ENFORCEMENT_LIB);
// No-throw contract on the prove seam, mirroring the runCheck-throws guard: a prover that blows up
// must fail closed (treated as provenFailFirst:false), never propagate and never green.
const result = enforce.runProhibitionEnforcement(
TEST_TIER,
{ kind: 'node-test', target: 'tests/neg.test.cjs', failFirst: true },
{
runCheck: () => ({ passed: true }),
proveFailFirst: () => { throw new Error('prover blew up'); },
},
);
assert.notEqual(result.status, 'green', 'a throwing prover must never green (FF-05)');
assert.equal(result.flagged, true);
assert.equal(result.located, true);
});
test('an un-provable fail-first check fails closed in BOTH interactive and autonomous modes (FF-04 / ADR-550 D4)', () => {
const enforce = require(ENFORCEMENT_LIB);
// A clean pass + a prover that could not prove fail-first must hard-gate in BOTH modes, with the
// mode echoed for transparency. Mirrors the existing both-modes failing-check guard (:158).
for (const mode of ['interactive', 'autonomous']) {
const result = enforce.runProhibitionEnforcement(
TEST_TIER,
{ kind: 'node-test', target: 'tests/neg.test.cjs', failFirst: true },
{
runCheck: () => ({ passed: true }),
proveFailFirst: () => ({ provenFailFirst: false }),
mode,
},
);
assert.notEqual(result.status, 'green', `un-provable check must not green in ${mode}`);
assert.equal(result.flagged, true, `un-provable check is flagged in ${mode}`);
assert.equal(result.mode, mode, 'mode echoed for transparency');
}
});
test('routeProhibitionEnforcement parses a JSON request file and emits a structured result', (t) => {
const fs = require('node:fs');
const { execFileSync } = require('node:child_process');