fix(verdict-gate): free text added inside the lessons block makes the review stale
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
77544841d7
commit
5ddbcd3de6
4 changed files with 70 additions and 4 deletions
|
|
@ -61,7 +61,7 @@ export const DEFAULT_BUDGET_CHARS = 6000;
|
|||
export const LINE_MAX = 700;
|
||||
export const RECURRENCE_THRESHOLD = 2;
|
||||
|
||||
const BLOCK_HEADER = 'Each line: a finding class /trekreview saw in two reviews, approved by the operator. Format: mistake · fix · how to check.';
|
||||
export const BLOCK_HEADER = 'Each line: a finding class /trekreview saw in two reviews, approved by the operator. Format: mistake · fix · how to check.';
|
||||
|
||||
/** How to check a mechanical class. Judgement classes get the review itself. */
|
||||
const CHECK_HINTS = Object.freeze({
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@
|
|||
// where {prefix} is the project's place in the repo (`git rev-parse
|
||||
// --show-prefix`);
|
||||
// - in each such commit the lessons file is unchanged outside its managed
|
||||
// block, and CLAUDE.md is unchanged or gains exactly the pointer block
|
||||
// block, every line its block gains is a lesson line (`validateLessonLine`)
|
||||
// or exactly `BLOCK_HEADER` (m4), and CLAUDE.md is unchanged or gains exactly the pointer block
|
||||
// (`withPointer` in lib/review/recurrence.mjs);
|
||||
// - a commit with no parent in that range fails closed, and so does a
|
||||
// symlinked CLAUDE.md (the pointer write goes through the link, so its
|
||||
|
|
@ -34,7 +35,7 @@
|
|||
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { existsSync } from 'node:fs';
|
||||
import { LESSONS_FILE_NAME, MARK_START, MARK_END, withPointer } from './recurrence.mjs';
|
||||
import { LESSONS_FILE_NAME, MARK_START, MARK_END, BLOCK_HEADER, withPointer, validateLessonLine } from './recurrence.mjs';
|
||||
|
||||
/**
|
||||
* A full commit id: 40 hex (SHA-1) or 64 hex (SHA-256), nothing shorter (M11).
|
||||
|
|
@ -97,6 +98,31 @@ function outsideBlock(text) {
|
|||
return text.slice(0, s) + text.slice(end);
|
||||
}
|
||||
|
||||
/** The non-blank lines inside the managed block (the same block `outsideBlock` takes out); none without one. */
|
||||
function blockLines(text) {
|
||||
const s = text.indexOf(MARK_START);
|
||||
if (s === -1) return [];
|
||||
const e = text.indexOf(MARK_END, s + MARK_START.length);
|
||||
if (e === -1) return [];
|
||||
return text.slice(s + MARK_START.length, e).split(/\r?\n/).filter((l) => l.trim() !== '');
|
||||
}
|
||||
|
||||
/**
|
||||
* The lines in `after`'s block that `before`'s block does not hold, counted as
|
||||
* a multiset (a second copy of a line already there is added).
|
||||
*/
|
||||
function addedBlockLines(before, after) {
|
||||
const left = new Map();
|
||||
for (const l of blockLines(before)) left.set(l, (left.get(l) ?? 0) + 1);
|
||||
const added = [];
|
||||
for (const l of blockLines(after)) {
|
||||
const n = left.get(l) ?? 0;
|
||||
if (n > 0) left.set(l, n - 1);
|
||||
else added.push(l);
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
/**
|
||||
* One file in one tree: `{ ok, mode, text }`; absent reads as mode null, text ''.
|
||||
* `--full-tree`: the path is from the repo root, as `git diff` prints it.
|
||||
|
|
@ -188,6 +214,13 @@ export function checkReviewedCommit({ repo, sha } = {}) {
|
|||
if (outsideBlock(before.text).trimEnd() !== outsideBlock(after.text).trimEnd()) {
|
||||
return stale(`${path} changed outside the managed block (commit ${short(c)})`);
|
||||
}
|
||||
// 5b. What the block gains is lesson lines, or the header applyLesson
|
||||
// writes with the first lesson; free text there is an instruction (m4).
|
||||
const free = addedBlockLines(before.text, after.text)
|
||||
.find((l) => l !== BLOCK_HEADER && !validateLessonLine(l).valid);
|
||||
if (free !== undefined) {
|
||||
return stale(`free text added inside the lessons block (commit ${short(c)})`);
|
||||
}
|
||||
} else if (after.text !== before.text && after.text !== withPointer(before.text)) {
|
||||
// 6. CLAUDE.md: unchanged, or exactly the pointer block added.
|
||||
return stale(`${path} changed other than the review-lessons pointer (commit ${short(c)})`);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue