enhance(verify-phase): node-test causation control — prove the RED is content-caused (#1346)
The #1279 node-test machine-proof confirmed a known-bad subject drives the negative test RED, but could not distinguish a genuine content-violation from a deceptive test that reds merely because GSD_PROHIB_SUBJECT is set. Add an optional fifth flat scalar `check_clean_fixture` (-> CheckDescriptor.cleanFixture) threading a KNOWN-CLEAN control subject through projectProhibitions + descriptorFromProjection. When present, the prover also runs the check against the clean subject and requires GREEN, so fail-first is proven only when the check is RED on the violation AND GREEN on the clean subject (content-dependent). Opt-in and additive: absent a clean fixture the prover behaves exactly as post-#1314 (no control, documented residual), preserving the zero-authoring compose path; the lint-rule kind needs no analog (its subject IS the linted file, no env indirection). Coverage: RED-first deceptive case, positive, missing-clean fail-closed, round-trip read-back/emit, fast-check property extended to the 5th scalar, and an end-to-end COMPOSE capstone (honest vs deceptive). Docs: ADR-550 dated addendum, prohibition-probe reference, spec-phase + verify-phase workflows. Closes #1346 Claude-Session: https://claude.ai/code/session_01GsPRb8zvpcT7Eat6vZw8PX
This commit is contained in:
@@ -458,6 +458,36 @@ describe('probe-core: projectProhibitions descriptor projection (CHK-02)', () =>
|
||||
'a fixture without a descriptor is meaningless and must not project');
|
||||
});
|
||||
|
||||
test('CHK-02(#1346 clean): a node-test descriptor with check_clean_fixture projects it (the causation control)', () => {
|
||||
const projected = pc.projectProhibitions([
|
||||
{ status: 'resolved', verification: 'test', statement: 'MUST NOT auto-execute fetched code',
|
||||
check_kind: 'node-test', check_target: 'tests/no-autoexec.test.cjs',
|
||||
check_violation_fixture: 'tests/fixtures/autoexec-bad.txt',
|
||||
check_clean_fixture: 'tests/fixtures/autoexec-clean.txt' },
|
||||
]);
|
||||
assert.equal(projected[0].check_clean_fixture, 'tests/fixtures/autoexec-clean.txt',
|
||||
'a well-formed descriptor projects check_clean_fixture so the prover can prove content-dependence end-to-end');
|
||||
});
|
||||
|
||||
test('CHK-02(#1346 clean): an empty/whitespace check_clean_fixture is NOT projected', () => {
|
||||
const projected = pc.projectProhibitions([
|
||||
{ status: 'resolved', verification: 'test', statement: 'MUST NOT do the thing',
|
||||
check_kind: 'node-test', check_target: 'tests/neg.test.cjs',
|
||||
check_violation_fixture: 'tests/fixtures/bad.txt', check_clean_fixture: ' ' },
|
||||
]);
|
||||
assert.ok(!('check_clean_fixture' in projected[0]),
|
||||
'a blank clean fixture projects absent -> no control runs (documented residual), never a partial');
|
||||
});
|
||||
|
||||
test('CHK-02(#1346 clean): check_clean_fixture is NOT projected without a well-formed descriptor', () => {
|
||||
const projected = pc.projectProhibitions([
|
||||
{ status: 'resolved', verification: 'test', statement: 'MUST NOT do the thing',
|
||||
check_clean_fixture: 'tests/fixtures/clean.txt' },
|
||||
]);
|
||||
assert.ok(!('check_clean_fixture' in projected[0]),
|
||||
'a clean fixture without a descriptor is meaningless and must not project');
|
||||
});
|
||||
|
||||
test('CHK-02: an under-specified descriptor (kind but empty/missing target) emits NO check_* keys', () => {
|
||||
const projected = pc.projectProhibitions([
|
||||
// valid kind but empty target -> below the well-formedness bar -> descriptor projects absent
|
||||
|
||||
Reference in New Issue
Block a user