test(intent): M3–M7 — halt pinned where it acts, allowlist guarded, header claims pinned

M4: the halt regex matched any **halt** in a 2500-char window, so the PM's
mutant (first **halt** → "continue anyway") survived. Two new tests pin the
sentence right after the gate command and the could-not-run halt. Mutant
run: old test ok, both new tests not ok.
M5: nothing guarded 2045432's allowlist line. New test: trekbrief keeps
intent_approved, drops task/project_dir. Mutant (line removed): not ok.
M3 (red): the header claims a reflow keeps the approval; joining lines is
STALE. Pins the honest wording + the STALE behaviour.
M7 (red): the trekreview exemption is not documented as a bypass of the
same trust class as self-stamping (header, HANDOVER-CONTRACTS, trekplan).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-23 09:23:04 +02:00
commit 097bae8a02
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
2 changed files with 62 additions and 0 deletions

View file

@ -209,6 +209,24 @@ test('field-allowlist: trekplan DROPS task / project_dir / brief_path (PII)', ()
assert.equal(out.profile, 'premium');
});
// M5: 2045432 added intent_approved to the trekbrief allowlist and no test
// guarded it — removing the line left the suite green.
test('field-allowlist: trekbrief KEEPS intent_approved (veikart steg 1) and drops task / project_dir', () => {
const record = {
ts: '2026-09-23T10:00:00.000Z',
task: 'private user prose',
slug: 'dark-mode-toggle',
project_dir: '/home/user/secret/project',
intent_approved: true,
};
const out = applyFieldAllowlist(record, 'trekbrief');
assert.equal(out.intent_approved, true);
assert.equal(out.slug, 'dark-mode-toggle');
assert.equal('task' in out, false);
assert.equal('project_dir' in out, false);
assert.equal(applyFieldAllowlist({ ...record, intent_approved: false }, 'trekbrief').intent_approved, false);
});
test('field-allowlist: event-emit applies sub-allowlist to payload', () => {
const record = {
ts: '2026-05-09T08:00:00.000Z',

View file

@ -440,3 +440,47 @@ test('M2: the gate names a remedy that works for --brief too (/trekbrief --appro
} finally { rmSync(dir, { recursive: true, force: true }); }
assert.match(read('docs/HANDOVER-CONTRACTS.md'), /--approve <project-dir \| brief-file>/);
});
// ---- M4: the halt sentence is pinned where it acts, not anywhere in a 2500-char window ----
// (PM mutant: the first "**halt**" → "continue anyway" survived the window regex above)
test('M4: the sentence right after the gate command halts on any non-zero exit', () => {
const text = read('commands/trekplan.md');
const gateIdx = text.indexOf(commandLine('commands/trekplan.md', '--check'));
const fenceEnd = text.indexOf('```', gateIdx);
const after = text.slice(fenceEnd + 3).replace(/^\s+/, '');
assert.match(after,
/^Exit 0 → continue\. Any other exit → \*\*halt\*\* — do not read further, spawn no\s+agent, write no plan\./,
'the first sentence after the gate command must be the halt rule, verbatim');
});
test('M4: a check that could not run halts too (never a pass)', () => {
const text = read('commands/trekplan.md');
const section = text.slice(text.indexOf('### Read the brief'), text.indexOf('Read the brief file and parse'));
assert.match(section,
/does not print the JSON report[\s\S]{0,120}\*\*halt\*\* as well[\s\S]{0,60}approval check that could not run is never a pass/);
assert.doesNotMatch(section, /continue anyway/i);
});
// ---- M3 + M7: the header says only what is true ----
test('M3: the header does not claim a reflow keeps the approval; joining lines is STALE (fails safe)', async () => {
const src = readFileSync(MODULE, 'utf8');
const header = src.slice(0, src.indexOf('\nimport '));
assert.doesNotMatch(header, /Reflowing a paragraph keeps the approval/);
assert.match(header, /joining or splitting lines[\s\S]{0,80}stale/i);
const { stampIntentApproval, checkIntentApprovalContent } = await load();
const stamped = stampIntentApproval(BRIEF, STAMP_AT).text;
const joined = stamped.replace('glares.\nThey want', 'glares. They want');
assert.deepEqual(checkIntentApprovalContent(joined).errors.map((e) => e.code), ['BRIEF_INTENT_APPROVAL_STALE']);
});
test('M7: the trekreview exemption is documented as the same trust class as self-stamping', () => {
const src = readFileSync(MODULE, 'utf8');
const header = src.slice(0, src.indexOf('\nimport '));
assert.match(header, /type: trekreview[\s\S]{0,400}same trust class as self-stamping/);
assert.match(read('docs/HANDOVER-CONTRACTS.md'), /`trekreview` briefs are exempt[^.]*\.[^.]*same trust class as self-stamping/);
const plan = read('commands/trekplan.md');
const section = plan.slice(plan.indexOf('### Read the brief'), plan.indexOf('Read the brief file and parse'));
assert.match(section, /same trust class as self-stamping/);
});