fix: close the six defects an independent review found in the trial fixes
Independent read-only review of c56f852..2d29966 (2026-10-08), each defect reproduced by the reviewer; each new test fails on that code. - test-lock green ran ANY allowlisted command: `green --cmd "git status"` marked a red step green and the stop guard let it stop. The lock now stores the step's test command (`lock --cmd`); `green` runs only that one (a different --cmd, or a lock without one, exits 2). trekexecute D1 calls `green` with no command, which also removes the quoting hazard. - plan-gate --accept-open worked at round 1 and passed the gate; it now refuses while rounds are left. - findings-schema --repo-root swallowed a following flag, or took a root that does not exist, and silently skipped the line check: exit 2. - brief-review-stamp hashed only the body, so a changed `framing` or `research_topics` stayed "current"; it now covers the reviewed frontmatter too (only the post-review stamps are left out). - red-proof red_kind read an assertion message naming SyntaxError as a load error; the signatures are now specific. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2d29966f51
commit
5f9faeed4a
12 changed files with 192 additions and 35 deletions
|
|
@ -10,10 +10,10 @@
|
|||
// test-lock.json), so it can never be committed, and each worktree has its own.
|
||||
//
|
||||
// Usage:
|
||||
// node lib/util/test-lock.mjs lock --files <a,b> --step <N> [--cwd <dir>]
|
||||
// node lib/util/test-lock.mjs lock --files <a,b> --step <N> [--cmd "<test command>"] [--cwd <dir>]
|
||||
// node lib/util/test-lock.mjs unlock [--cwd <dir>]
|
||||
// node lib/util/test-lock.mjs status [--cwd <dir>] (JSON on stdout)
|
||||
// node lib/util/test-lock.mjs green --cmd "<test command>" [--cwd <dir>]
|
||||
// node lib/util/test-lock.mjs green [--cmd "<test command>"] [--cwd <dir>]
|
||||
// node lib/util/test-lock.mjs pending [--cwd <dir>]
|
||||
// Exit: 0 = done, 1 = refused (another step holds the lock; for green: no
|
||||
// lock, or the test command did not exit 0), 2 = could not run (not a
|
||||
|
|
@ -24,7 +24,10 @@
|
|||
// three times while the executor waited for its controller, with the step's
|
||||
// test already green (voyage-lekerepo trial, 2026-10-06). `green` RUNS the
|
||||
// step's test command (the same allowlist and denylist as done-line.mjs) and
|
||||
// records `green_at` only on exit 0; the stop guard then lets the session
|
||||
// records `green_at` only on exit 0. The command is the one stored at `lock
|
||||
// --cmd` time, never one chosen at mark time: an independent review showed
|
||||
// `green --cmd "git status"` marking a red step green. A lock without a
|
||||
// stored command is never marked (exit 2); a --cmd that differs is refused; the stop guard then lets the session
|
||||
// stop, while the write guard keeps refusing the locked files. `pending`
|
||||
// clears the mark when a fix round starts; a new `lock` starts without one.
|
||||
// Paths in --files are relative to the --cwd (default: the current directory).
|
||||
|
|
@ -157,7 +160,7 @@ function main(argv) {
|
|||
const l = cur.lock || {};
|
||||
process.stdout.write(JSON.stringify({
|
||||
locked: cur.state === 'locked', step: l.step ?? null, files: l.files ?? [], session: l.session ?? null,
|
||||
locked_at: l.locked_at ?? null, green_at: l.green_at ?? null, lock_path: cur.path,
|
||||
locked_at: l.locked_at ?? null, cmd: l.cmd ?? null, green_at: l.green_at ?? null, lock_path: cur.path,
|
||||
}, null, 2) + '\n');
|
||||
process.exit(0);
|
||||
}
|
||||
|
|
@ -169,12 +172,14 @@ function main(argv) {
|
|||
if (cmd === 'pending') {
|
||||
delete lock.green_at;
|
||||
} else {
|
||||
if (!args.cmd) fail(2, 'green needs --cmd "<the step\'s test command>"');
|
||||
const allowed = allowedCommand(args.cmd, { cwd: cur.repo.root });
|
||||
const testCmd = typeof lock.cmd === 'string' && lock.cmd.trim() !== '' ? lock.cmd : null;
|
||||
if (!testCmd) fail(2, 'the lock names no test command (lock with --cmd "<Verify>"); never marked green');
|
||||
if (args.cmd !== undefined && args.cmd !== testCmd) fail(2, `--cmd is not the step's test command stored in the lock (${testCmd})`);
|
||||
const allowed = allowedCommand(testCmd, { cwd: cur.repo.root });
|
||||
if (!allowed.allowed) fail(2, `command not run: ${allowed.reason}`);
|
||||
const screen = screenCommand(args.cmd);
|
||||
const screen = screenCommand(testCmd);
|
||||
if (!screen.allowed) fail(2, `command blocked: ${screen.rule}`);
|
||||
const r = spawnSync('/bin/sh', ['-c', args.cmd], {
|
||||
const r = spawnSync('/bin/sh', ['-c', testCmd], {
|
||||
cwd: cur.repo.root, env: commandEnv(), encoding: 'utf8', timeout: DEFAULT_TIMEOUT_MS, maxBuffer: 64 * 1024 * 1024,
|
||||
});
|
||||
if (r.error || r.status === null || r.status === 126 || r.status === 127) {
|
||||
|
|
@ -211,6 +216,10 @@ function main(argv) {
|
|||
session: process.env.CLAUDE_CODE_SESSION_ID || null,
|
||||
locked_at: new Date().toISOString(),
|
||||
};
|
||||
if (args.cmd !== undefined) {
|
||||
if (String(args.cmd).trim() === '') fail(2, '--cmd is empty');
|
||||
lock.cmd = String(args.cmd);
|
||||
}
|
||||
mkdirSync(dirname(cur.path), { recursive: true });
|
||||
writeFileSync(cur.path, JSON.stringify(lock, null, 2) + '\n');
|
||||
writeSessionPointer(lock.session, cur.path);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue