fix(plan): an open MAJOR stops the plan; after the last round the operator decides
voyage-lekerepo trial (2026-10-06) point 6, operator decision 2026-10-08 («samme skala, og du spør»): the critics rated a non-discriminating test minor in round 3, there was no way to fix it after the last round, it was built, and /trekreview called the same weakness MAJOR (MISSING_TEST). - plan-critic, scope-guardian: rate on the review catalogue's tiers; a test that cannot fail on a wrong implementation is major, never minor. - plan-gate: an open MAJOR stops (PLAN_GATE_OPEN_MAJOR: revise and run the next round; PLAN_GATE_OPEN_MAJOR_FINAL after the last round: ask the operator). --accept-open records "build as is" after their yes, bound to the round and the plan hash; never for a blocker. - trekplan Phase 9: REVISE after the last round asks fix now (one extra round) or build as is, instead of carrying the majors silently. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
1b5218e8f4
commit
2d29966f51
7 changed files with 243 additions and 16 deletions
|
|
@ -55,14 +55,24 @@ test('K3: a plan with an open critic BLOCKER exits 1', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('K3: a valid plan whose latest verdict has no blocker exits 0 (majors are warnings)', () => {
|
||||
// Operator decision 2026-10-08 (voyage-lekerepo trial point 6): an open MAJOR
|
||||
// no longer passes as a warning. It stops until it is fixed or the operator
|
||||
// accepts it (tests/validators/plan-gate-open-major.test.mjs).
|
||||
test('K3: a valid plan whose latest verdict has an open MAJOR stops (fix it, or the operator accepts it)', () => {
|
||||
const r0 = rec(buildPlan(), dedupOut(finding('major', 'Step 1 lacks an error path'), finding('minor', 'typo')));
|
||||
withPlan(r0.text, (p) => {
|
||||
const r = run([p, '--json']);
|
||||
assert.equal(r.code, 0, r.out + r.err);
|
||||
assert.equal(r.code, 1, r.out + r.err);
|
||||
const j = JSON.parse(r.out);
|
||||
assert.equal(j.verdict.verdict, 'REVISE');
|
||||
assert.ok(j.warnings.some(w => w.code === 'PLAN_GATE_OPEN_MAJOR'));
|
||||
assert.ok(j.reasons.some(w => w.code === 'PLAN_GATE_OPEN_MAJOR'));
|
||||
});
|
||||
});
|
||||
|
||||
test('K3: a valid plan whose latest verdict has only minors exits 0', () => {
|
||||
const r0 = rec(buildPlan(), dedupOut(finding('minor', 'typo')));
|
||||
withPlan(r0.text, (p) => {
|
||||
assert.equal(run([p, '--json']).code, 0);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -219,7 +229,7 @@ test('CLI: --hash, then --record --reviewed writes in place; malformed stdin or
|
|||
const ok = run(['--record', p, '--reviewed', hash], JSON.stringify(dedupOut(finding('major', 'm'))));
|
||||
assert.equal(ok.code, 0, ok.out + ok.err);
|
||||
assert.equal(JSON.parse(ok.out).verdict, 'REVISE');
|
||||
assert.equal(run([p]).code, 0);
|
||||
assert.equal(run([p]).code, 1, 'the recorded open MAJOR stops the gate (operator decision 2026-10-08)');
|
||||
assert.ok(!existsSync(join(dir, 'plan.md.plan-gate.tmp')));
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue