fix(park): park from a CRLF diff and say that a staged new file is parked
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
bf4736a254
commit
afe56899a9
4 changed files with 59 additions and 6 deletions
|
|
@ -1562,7 +1562,7 @@ finding 4):
|
|||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/util/park-attempt-files.mjs --diff {report dir}/step-{N}-upward.diff --step {N} --attempt {attempts}
|
||||
```
|
||||
It moves every file the attempt created that is still untracked to the git
|
||||
It moves every file new in the attempt's diff that is untracked, or staged but not in HEAD, to the git
|
||||
dir (`voyage/parked/step-{N}-attempt-{attempts}/`, outside the work tree, so
|
||||
Sub-step C.2 never registers it again): moved, never deleted, never over a file
|
||||
already parked. Name the `parked` paths and every `kept` path with its reason
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
// rejected line would have passed Verify, the manifest and the success
|
||||
// criterion. Only the plan critic caught it.
|
||||
//
|
||||
// Before the fresh build the executor parks them: every file the attempt
|
||||
// created (a `new file mode` entry in step-{N}-upward.diff) that is still
|
||||
// untracked on disk moves to <git dir>/voyage/parked/step-<N>-attempt-<k>/
|
||||
// under its own path. The git dir, like the test lock's, is outside the work
|
||||
// Before the fresh build the executor parks them: it parks every file new in
|
||||
// the attempt's diff (a `new file mode` entry in step-{N}-upward.diff) that is
|
||||
// untracked, or staged but not in HEAD; it moves to
|
||||
// <git dir>/voyage/parked/step-<N>-attempt-<k>/ under its own path. The git dir, like the test lock's, is outside the work
|
||||
// tree, so a parked file never comes back as a new file of the next build.
|
||||
// Moved, never deleted, and never over a file already parked there.
|
||||
// A new file the helper registered --intent-to-add is in the index, not in
|
||||
|
|
@ -56,7 +56,7 @@ export function newFilesInDiff(diffText) {
|
|||
const unread = [];
|
||||
let header = null;
|
||||
let sawHeader = false;
|
||||
const lines = String(diffText).split('\n').map((l) => l.replace(ANSI_RE, ''));
|
||||
const lines = String(diffText).split(/\r?\n/).map((l) => l.replace(ANSI_RE, ''));
|
||||
for (const line of lines) {
|
||||
if (line.startsWith('diff --git ')) {
|
||||
sawHeader = true;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@
|
|||
// prefix and lists review_version 1.1 as current, and /trekexecute's
|
||||
// main-merge gate maps it to "not measured" with the merge locked.
|
||||
// M11 Handover 6 states that only a full 40- or 64-hex reviewed commit is read.
|
||||
// E22e The park tool parks every file new in the attempt's diff, untracked or
|
||||
// staged but not in HEAD: its header and /trekexecute's resume paragraph
|
||||
// no longer say "still untracked".
|
||||
// No static import of a new export: the file must load at be0b631.
|
||||
// Fix the SOURCE a pin guards, not the pin.
|
||||
|
||||
|
|
@ -101,3 +104,29 @@ test('[M11] Handover 6 states the full 40- or 64-hex reviewed commit', () => {
|
|||
assert.match(gateParagraph(), /`scope_sha_end`[^.]*full 40- or 64-hex/,
|
||||
'the verdict-gate paragraph of Handover 6 does not state that only a full 40- or 64-hex scope_sha_end is read');
|
||||
});
|
||||
|
||||
// --- E22e --------------------------------------------------------------------------
|
||||
|
||||
/** The sentences of `text` (flattened) that say what the park tool moves or parks. */
|
||||
function parkSentences(text) {
|
||||
return flat(text).split(/(?<=\.)\s+(?=[A-Z`"*(])/).filter((s) => /\b(moves|parks)\b/.test(s) && /\bfile\b/.test(s));
|
||||
}
|
||||
|
||||
test('[E22e] the park header says untracked or staged but not in HEAD', () => {
|
||||
const src = read('lib/util/park-attempt-files.mjs');
|
||||
const header = src.slice(0, src.indexOf('\nimport '));
|
||||
assert.ok(header.length > 0, 'lib/util/park-attempt-files.mjs has no header before its imports');
|
||||
const comment = header.split('\n').map((l) => l.replace(/^\/\/ ?/, '')).join('\n');
|
||||
assert.doesNotMatch(flat(comment), /still untracked/, 'the park header still says the tool parks only files "still untracked"');
|
||||
const hits = parkSentences(comment);
|
||||
assert.ok(hits.some((s) => /new in the attempt's diff/.test(s) && /untracked, or staged but not in HEAD/.test(s)),
|
||||
`no header sentence says every file new in the attempt's diff is parked, untracked, or staged but not in HEAD: ${hits.join(' | ')}`);
|
||||
});
|
||||
|
||||
test('[E22e] the execute command says the same', () => {
|
||||
const para = between('commands/trekexecute.md', 'A step at `fix_rounds` 4 on `--resume` was re-planned', 'Then launch a fresh');
|
||||
assert.doesNotMatch(flat(para), /still untracked/, 'the /trekexecute resume paragraph still says the tool moves only files "still untracked"');
|
||||
const hits = parkSentences(para);
|
||||
assert.ok(hits.some((s) => /new in the attempt's diff/.test(s) && /untracked, or staged but not in HEAD/.test(s)),
|
||||
`no /trekexecute sentence says every file new in the attempt's diff is parked, untracked, or staged but not in HEAD: ${hits.join(' | ')}`);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -488,3 +488,27 @@ test('[M7] an unborn HEAD parks the attempt\'s files', () => {
|
|||
rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
// --- fix round 4-5b: E22c --------------------------------------------------------
|
||||
// [E22c] The diff was split on '\n' only: in a CRLF diff every line kept its '\r',
|
||||
// so no `new file mode` line matched and nothing was parked, with exit 0.
|
||||
|
||||
test('[E22c] a CRLF diff parks its new files', async () => {
|
||||
const mod = await import('../../lib/util/park-attempt-files.mjs');
|
||||
assert.equal(typeof mod.newFilesInDiff, 'function', 'newFilesInDiff is not exported');
|
||||
const crlf = DIFF.split('\n').join('\r\n');
|
||||
assert.ok(crlf.includes('new file mode 100755\r\n'), 'control: the diff has CRLF line ends');
|
||||
assert.deepEqual(mod.newFilesInDiff(crlf).paths, ['tests/batch.sh', 'tests/cli-stdin.test.mjs'],
|
||||
'a CRLF diff did not yield its new files');
|
||||
const dir = repo();
|
||||
try {
|
||||
attemptFiles(dir);
|
||||
const r = run(dir, crlf);
|
||||
assert.equal(r.status, 0, r.stdout + r.stderr);
|
||||
assert.deepEqual(JSON.parse(r.stdout).parked, ['tests/batch.sh', 'tests/cli-stdin.test.mjs'], `a CRLF diff parked nothing: ${r.stdout}`);
|
||||
assert.equal(existsSync(join(dir, 'tests/batch.sh')), false, 'the file is still in the tree');
|
||||
assert.equal(readFileSync(parkedPath(dir, 'tests/batch.sh'), 'utf8'), 'stale | cat\n', 'the file is not under the parked directory');
|
||||
} finally {
|
||||
rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue