mirror of
https://github.com/glittercowboy/get-shit-done
synced 2026-05-15 11:36:37 +02:00
* fix(3264): document cross-wave-deviation cleanup tail in execute-phase step 5.5 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(changeset): add fragment for #3273 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
141 lines
4.9 KiB
JavaScript
141 lines
4.9 KiB
JavaScript
// allow-test-rule: source-text-is-the-product
|
|
// The workflow .md file is the installed AI contract — its text IS what the orchestrator
|
|
// executes at runtime. Testing structural content of step 5.5 guards against accidental
|
|
// deletion of the cross-wave-deviation cleanup documentation (#3264).
|
|
|
|
/**
|
|
* Regression tests for #3264: cross-wave-dependency deviation cleanup documentation
|
|
*
|
|
* Guards that step 5.5 of execute-phase.md documents both skip conditions and
|
|
* contains a self-contained cleanup-tail snippet for the deviation path.
|
|
*/
|
|
|
|
const { describe, test } = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const WORKFLOW_PATH = path.join(
|
|
__dirname,
|
|
'..',
|
|
'get-shit-done',
|
|
'workflows',
|
|
'execute-phase.md',
|
|
);
|
|
|
|
/**
|
|
* Locate the step 5.5 block in the workflow file.
|
|
* Returns the substring from "5.5." up to (but not including) "5.6.".
|
|
* Throws if the block cannot be found.
|
|
*/
|
|
function extractStep55Block(content) {
|
|
const start = content.indexOf('\n5.5.');
|
|
assert.ok(start !== -1, 'execute-phase.md must contain a step 5.5 block');
|
|
|
|
const end = content.indexOf('\n5.6.', start + 1);
|
|
assert.ok(end !== -1, 'execute-phase.md must contain a step 5.6 block after 5.5');
|
|
|
|
return content.slice(start, end);
|
|
}
|
|
|
|
describe('execute-phase step 5.5: cross-wave-deviation cleanup documentation (#3264)', () => {
|
|
const content = fs.readFileSync(WORKFLOW_PATH, 'utf-8');
|
|
|
|
test('workflow file exists', () => {
|
|
assert.ok(fs.existsSync(WORKFLOW_PATH), 'workflows/execute-phase.md should exist');
|
|
});
|
|
|
|
test('step 5.5 block exists and is bounded', () => {
|
|
// extractStep55Block throws on failure — this test validates the helper itself
|
|
const block = extractStep55Block(content);
|
|
assert.ok(block.length > 0, 'step 5.5 block must be non-empty');
|
|
});
|
|
|
|
test('step 5.5 documents the standard wave contract', () => {
|
|
const block = extractStep55Block(content);
|
|
assert.ok(
|
|
block.includes('Standard wave contract'),
|
|
'step 5.5 must name the standard wave contract explicitly',
|
|
);
|
|
});
|
|
|
|
test('step 5.5 names cross-wave dependency deviation as a supported execution mode', () => {
|
|
const block = extractStep55Block(content);
|
|
assert.ok(
|
|
block.includes('Cross-wave dependency deviation'),
|
|
'step 5.5 must name the cross-wave dependency deviation as a supported mode',
|
|
);
|
|
});
|
|
|
|
test('cleanup-tail snippet contains git worktree prune', () => {
|
|
const block = extractStep55Block(content);
|
|
assert.ok(
|
|
block.includes('git worktree prune'),
|
|
'step 5.5 cleanup-tail snippet must include git worktree prune',
|
|
);
|
|
});
|
|
|
|
test('cleanup-tail snippet contains git worktree remove --force', () => {
|
|
const block = extractStep55Block(content);
|
|
assert.ok(
|
|
block.includes('git worktree remove') && block.includes('--force'),
|
|
'step 5.5 cleanup-tail snippet must include git worktree remove --force',
|
|
);
|
|
});
|
|
|
|
test('cleanup-tail snippet contains git worktree unlock', () => {
|
|
const block = extractStep55Block(content);
|
|
assert.ok(
|
|
block.includes('git worktree unlock'),
|
|
'step 5.5 cleanup-tail snippet must include git worktree unlock',
|
|
);
|
|
});
|
|
|
|
test('cleanup-tail snippet contains git branch -D', () => {
|
|
const block = extractStep55Block(content);
|
|
assert.ok(
|
|
block.includes('git branch -D'),
|
|
'step 5.5 cleanup-tail snippet must include git branch -D',
|
|
);
|
|
});
|
|
|
|
test('skip conditions enumerate empty-WAVE_WORKTREE_PLANS case', () => {
|
|
const block = extractStep55Block(content);
|
|
assert.ok(
|
|
block.includes('WAVE_WORKTREE_PLANS'),
|
|
'step 5.5 must document the empty-WAVE_WORKTREE_PLANS skip condition',
|
|
);
|
|
});
|
|
|
|
test('skip conditions enumerate custom-merge-deviation case', () => {
|
|
const block = extractStep55Block(content);
|
|
// The deviation skip condition must reference the cleanup-tail as the alternative
|
|
assert.ok(
|
|
block.includes('cleanup-tail'),
|
|
'step 5.5 must document the custom-merge-deviation skip condition with a pointer to the cleanup-tail',
|
|
);
|
|
});
|
|
|
|
test('cleanup-tail uses inclusion-based filter for agent namespace', () => {
|
|
const block = extractStep55Block(content);
|
|
// Must use .claude/worktrees/agent- inclusion filter, not exclusion (per #2774 precedent)
|
|
assert.ok(
|
|
block.includes('.claude/worktrees/agent-'),
|
|
'cleanup-tail must use inclusion-based filter matching .claude/worktrees/agent- namespace',
|
|
);
|
|
});
|
|
|
|
test('cleanup-tail reads git worktree list --porcelain line-by-line', () => {
|
|
const block = extractStep55Block(content);
|
|
assert.ok(
|
|
block.includes('git worktree list --porcelain'),
|
|
'cleanup-tail must parse git worktree list --porcelain output',
|
|
);
|
|
// Line-by-line reading requires IFS= read -r pattern
|
|
assert.ok(
|
|
block.includes('IFS= read -r'),
|
|
'cleanup-tail must read line-by-line to preserve paths with whitespace',
|
|
);
|
|
});
|
|
});
|