refactor: simplify pass (trekexecute)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-10-24 22:22:18 +02:00
commit af90e82794
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
12 changed files with 303 additions and 186 deletions

View file

@ -25,10 +25,10 @@
// shell; a git call that fails is a stale review (fails closed), never ok.
import { spawnSync } from 'node:child_process';
import { MARK_START, MARK_END, withPointer } from './recurrence.mjs';
import { LESSONS_FILE_NAME, MARK_START, MARK_END, withPointer } from './recurrence.mjs';
const SHA_RE = /^[0-9a-f]{7,40}$/i;
const LESSONS_REL = '.claude/rules/voyage-review-lessons.md';
const LESSONS_REL = `.claude/rules/${LESSONS_FILE_NAME}`; // posix, as `git diff` prints it
const CLAUDE_REL = 'CLAUDE.md';
const SYMLINK_MODE = '120000';
@ -42,7 +42,7 @@ export function reviewedSha(reviewText) {
const m = fm && /^scope_sha_end:[ \t]*(["']?)([^"'\s#]*)\1[ \t]*(?:#.*)?$/m.exec(fm[1]);
// A commit sha only: a ref name (HEAD, main, a tag) resolves to whatever it
// points at now, and coverage would pass whatever was reviewed (round 4).
return m && /^[0-9a-f]{7,40}$/i.test(m[2]) ? m[2] : '';
return m && SHA_RE.test(m[2]) ? m[2] : '';
}
function git(repo, args) {
@ -53,10 +53,14 @@ function stale(reason) {
return { ok: false, reason: `review-stale: ${reason}` };
}
/** What a git call said: its spawn error, else the first line of its stderr. */
function gitNote(r) {
return r.error?.message ?? String(r.stderr ?? '').trim().split('\n')[0];
}
/** A failed git call as a stale reason: fails closed. */
function gitFailed(what, r) {
const note = (r.error?.message ?? String(r.stderr ?? '').trim().split('\n')[0]) || `exit ${r.status}`;
return stale(`git ${what} failed (${note})`);
return stale(`git ${what} failed (${gitNote(r) || `exit ${r.status}`})`);
}
const short = (c) => c.slice(0, 12);
@ -74,18 +78,18 @@ function outsideBlock(text) {
}
/**
* One file in one tree: `{ ok, absent, mode, text }`; absent reads as ''.
* 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.
*/
function blobAt(repo, rev, path) {
const ls = git(repo, ['ls-tree', '--full-tree', '-z', rev, '--', path]);
if (ls.status !== 0) return { ok: false, fail: gitFailed(`ls-tree ${rev}`, ls) };
const entry = ls.stdout.split('\0').find(Boolean);
if (!entry) return { ok: true, absent: true, mode: null, text: '' };
if (!entry) return { ok: true, mode: null, text: '' };
const mode = entry.split(' ')[0];
const blob = git(repo, ['cat-file', 'blob', `${rev}:${path}`]);
if (blob.status !== 0) return { ok: false, fail: gitFailed(`cat-file ${rev}:${path}`, blob) };
return { ok: true, absent: false, mode, text: blob.stdout };
return { ok: true, mode, text: blob.stdout };
}
/**
@ -101,7 +105,7 @@ export function checkReviewedCommit({ repo, sha } = {}) {
if (!SHA_RE.test(given)) return stale(notCommit);
const resolved = git(repo, ['rev-parse', '--verify', '--quiet', `${given}^{commit}`]);
if (resolved.status !== 0) {
const note = (resolved.error?.message ?? String(resolved.stderr ?? '').trim().split('\n')[0]);
const note = gitNote(resolved);
return stale(note ? `${notCommit} (${note})` : notCommit);
}
const full = resolved.stdout.trim();
@ -123,14 +127,14 @@ export function checkReviewedCommit({ repo, sha } = {}) {
const lessons = `${prefix}${LESSONS_REL}`;
const claude = `${prefix}${CLAUDE_REL}`;
const roots = git(repo, ['rev-list', '--max-parents=0', `${full}..HEAD`]);
if (roots.status !== 0) return gitFailed('rev-list --max-parents=0', roots);
const root = roots.stdout.split('\n').find(Boolean);
if (root) return stale(`commit ${short(root)} has no parent`);
// One line per commit, `<commit> <parent>...`; a line with one field is a root.
const list = git(repo, ['rev-list', '--parents', `${full}..HEAD`]);
if (list.status !== 0) return gitFailed('rev-list --parents', list);
const lines = list.stdout.split('\n').filter(Boolean).map((l) => l.split(' '));
const root = lines.find((f) => f.length === 1);
if (root) return stale(`commit ${short(root[0])} has no parent`);
const list = git(repo, ['rev-list', `${full}..HEAD`]);
if (list.status !== 0) return gitFailed('rev-list', list);
for (const c of list.stdout.split('\n').filter(Boolean)) {
for (const [c] of lines) {
// `--no-relative` and `--ignore-submodules=none`: neither `diff.relative`
// nor an `ignore =` setting (config or .gitmodules) may hide a changed path.
const names = git(repo, ['diff', '--no-relative', '--ignore-submodules=none', '--name-only', '-z', '--no-renames', `${c}^1`, c]);