* feat(#1137): migrate review verification hooks to capabilities * chore(#1147): add changeset
90 lines
3.5 KiB
JavaScript
90 lines
3.5 KiB
JavaScript
// allow-test-rule: source-text-is-the-product
|
|
// Workflow .md / agent .md / command .md / reference .md files — their text
|
|
// IS what the runtime loads. Testing text content tests the deployed contract.
|
|
// Per CONTRIBUTING.md exception matrix.
|
|
'use strict';
|
|
|
|
|
|
/**
|
|
* verify-work auto-transition tests (#2018)
|
|
*
|
|
* Validates that verify-work.md calls the transition workflow to mark the
|
|
* phase complete in ROADMAP.md and STATE.md when UAT passes with 0 issues.
|
|
*/
|
|
|
|
const { test, describe } = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const VERIFY_WORK = path.join(__dirname, '..', 'gsd-core', 'workflows', 'verify-work.md');
|
|
|
|
describe('verify-work.md — auto-transition after UAT passes with 0 issues', () => {
|
|
test('workflow reads transition.md when issues == 0 and security gate cleared', () => {
|
|
const content = fs.readFileSync(VERIFY_WORK, 'utf-8');
|
|
assert.ok(
|
|
content.includes('transition.md'),
|
|
'verify-work.md must reference transition.md for phase completion when issues == 0'
|
|
);
|
|
});
|
|
|
|
test('transition call appears after complete_session section', () => {
|
|
const content = fs.readFileSync(VERIFY_WORK, 'utf-8');
|
|
const completeSessionIdx = content.indexOf('complete_session');
|
|
const transitionIdx = content.indexOf('transition.md');
|
|
assert.ok(
|
|
completeSessionIdx !== -1,
|
|
'verify-work.md must contain a complete_session section'
|
|
);
|
|
assert.ok(
|
|
transitionIdx !== -1,
|
|
'verify-work.md must reference transition.md'
|
|
);
|
|
assert.ok(
|
|
transitionIdx > completeSessionIdx,
|
|
'transition.md reference must appear after the complete_session section'
|
|
);
|
|
});
|
|
|
|
test('security gate check gates the transition (no auto-transition when security pending)', () => {
|
|
const content = fs.readFileSync(VERIFY_WORK, 'utf-8');
|
|
// The capability-resolved security check must appear before the transition reference.
|
|
const securityHookIdx = content.indexOf('loop render-hooks verify:post');
|
|
const transitionIdx = content.indexOf('transition.md');
|
|
assert.ok(
|
|
securityHookIdx !== -1,
|
|
'verify-work.md must resolve verify:post capability hooks before transitioning'
|
|
);
|
|
assert.ok(
|
|
securityHookIdx < transitionIdx,
|
|
'verify:post capability hook check must appear before transition.md reference'
|
|
);
|
|
});
|
|
|
|
test('transition is only invoked when security gate is cleared or disabled', () => {
|
|
const content = fs.readFileSync(VERIFY_WORK, 'utf-8');
|
|
// Transition must be guarded by security check:
|
|
// Either no active secure-phase hook exists, or security file exists with 0 open threats.
|
|
const hasGuardedTransition =
|
|
content.includes('transition.md') &&
|
|
(
|
|
content.includes('loop render-hooks verify:post') &&
|
|
content.includes('ref.skill == "secure-phase"') &&
|
|
(content.includes('threats_open') || content.includes('SECURITY_FILE'))
|
|
);
|
|
assert.ok(
|
|
hasGuardedTransition,
|
|
'transition.md invocation must be guarded by security gate checks'
|
|
);
|
|
});
|
|
|
|
test('transition is NOT suggested when security enforcement is enabled and no SECURITY.md exists', () => {
|
|
const content = fs.readFileSync(VERIFY_WORK, 'utf-8');
|
|
// The workflow should suggest /gsd-secure-phase when security is enabled but no file exists
|
|
assert.ok(
|
|
content.includes('gsd-secure-phase') || content.includes('gsd:secure-phase'),
|
|
'verify-work.md must suggest /gsd:secure-phase when security gate blocks transition'
|
|
);
|
|
});
|
|
});
|