Files
msd-core/tests/bug-2994-verify-reapply-patches-installed-path.test.cjs
Tom Boucher 4277f7d7e8 fix(#2994): move verify-reapply-patches.cjs to get-shit-done/bin/ so it ships to user installs (#3000)
* fix(#2994): move verify-reapply-patches.cjs to get-shit-done/bin/ so installer ships it

scripts/verify-reapply-patches.cjs (added in #2972 to close the
verified-yes-without-checking gap from #2969) shipped in the npm tarball
but never reached user installs: bin/install.js copies get-shit-done/
recursively but does not copy the top-level scripts/ directory.

Effect: every fresh install hit `Cannot find module …/scripts/verify-reapply-patches.cjs`
on Step 5 of /gsd-reapply-patches. The whole point of moving
verification out of LLM-driven prose into a deterministic script is
undone if the script does not resolve at runtime.

Fix: move the script to get-shit-done/bin/verify-reapply-patches.cjs
(same pattern as gsd-tools.cjs and other runtime bin scripts that the
installer ships) and update reapply-patches.md Step 5 to invoke
${GSD_HOME}/get-shit-done/bin/verify-reapply-patches.cjs.

Tests:
- bug-2969 SCRIPT path updated to the new location
- New bug-2994-verify-reapply-patches-installed-path.test.cjs parses
  reapply-patches.md into structured invocation records and asserts
  every node ${GSD_HOME}/... reference lives under get-shit-done/
  (the installed tree). Catches future regressions where someone moves
  a runtime-needed script back to scripts/.

Closes #2994

* chore(#2994): add changeset fragment for PR #3000

* chore(#2994): add changeset fragment for PR #3000

* docs(#2994): update verifier-script-location comment to reflect new path (CR)

CodeRabbit on PR #3000: the parenthetical at line 278 still said the
script ships under scripts/, but this PR moved it to get-shit-done/bin/.
Updated the prose to reference the new location and the installer
target path.

* chore(#3000): drop direct CHANGELOG.md edit; release entry now lives in .changeset/

The changeset-fragment workflow (#2975) renders fragments into
CHANGELOG.md at release time. Direct edits to [Unreleased] on
each PR caused merge conflicts on every concurrent PR. This commit
restores CHANGELOG.md to match origin/main; the release entry for
this fix is preserved in the .changeset/*.md fragment(s) on this
branch, which the release workflow consolidates.
2026-05-02 00:29:34 -04:00

82 lines
3.6 KiB
JavaScript

'use strict';
process.env.GSD_TEST_MODE = '1';
/**
* Bug #2994: scripts/verify-reapply-patches.cjs ships in tarball but is
* not installed at ${GSD_HOME}/scripts/.
*
* Root cause: bin/install.js copies the get-shit-done/ source tree to
* ${configDir}/get-shit-done/ but does NOT copy the top-level scripts/
* directory. The verifier script lived under scripts/ so /gsd-reapply-patches
* Step 5 hit `Cannot find module …/scripts/verify-reapply-patches.cjs`.
*
* Fix: move the script to get-shit-done/bin/verify-reapply-patches.cjs
* (which IS installed) and update reapply-patches.md to point there.
*
* This test enforces the structural invariant that prevents regression.
*/
const { test, describe } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const ROOT = path.join(__dirname, '..');
const RUNTIME_SCRIPT_PATH = path.join(ROOT, 'get-shit-done', 'bin', 'verify-reapply-patches.cjs');
const STALE_SCRIPT_PATH = path.join(ROOT, 'scripts', 'verify-reapply-patches.cjs');
const REAPPLY_WORKFLOW = path.join(ROOT, 'get-shit-done', 'workflows', 'reapply-patches.md');
describe('Bug #2994: verify-reapply-patches.cjs lives at the runtime-installed path', () => {
test('the script exists under get-shit-done/bin/ (installed by copyWithPathReplacement)', () => {
assert.equal(fs.existsSync(RUNTIME_SCRIPT_PATH), true,
`Expected verifier script at ${RUNTIME_SCRIPT_PATH} -- installer copies get-shit-done/ recursively`);
});
test('the script does NOT live at the legacy scripts/ path (not installed)', () => {
assert.equal(fs.existsSync(STALE_SCRIPT_PATH), false,
`scripts/ is not copied by installer; verifier must be under get-shit-done/bin/ instead`);
});
test('the script is requireable (loads without throwing)', () => {
const mod = require(RUNTIME_SCRIPT_PATH);
assert.equal(typeof mod.REASON, 'object');
assert.notEqual(mod.REASON, null);
});
});
// Parse reapply-patches.md to extract every `node "${GSD_HOME}/...cjs"`
// invocation as structured records. Assertions go against the parsed
// records, not against the markdown text.
function extractScriptInvocations(markdown) {
const invocations = [];
const re = /node\s+"\$\{GSD_HOME\}\/([^"]+\.cjs)"/g;
let match;
while ((match = re.exec(markdown)) !== null) {
invocations.push({ relPath: match[1] });
}
return invocations;
}
describe('Bug #2994: reapply-patches workflow references the runtime-installed path', () => {
test('every node ${GSD_HOME}/... invocation in reapply-patches.md uses an installed runtime path', () => {
const md = fs.readFileSync(REAPPLY_WORKFLOW, 'utf-8');
const invocations = extractScriptInvocations(md);
assert.ok(invocations.length > 0, 'sanity: expected at least one node ${GSD_HOME}/... invocation in reapply-patches.md');
const violations = invocations.filter(inv => !inv.relPath.startsWith('get-shit-done/'));
assert.deepEqual(violations, [], `invocations under non-installed paths: ${JSON.stringify(violations)}`);
});
test('reapply-patches.md references the verifier at get-shit-done/bin/verify-reapply-patches.cjs', () => {
const md = fs.readFileSync(REAPPLY_WORKFLOW, 'utf-8');
const invocations = extractScriptInvocations(md);
const verifierInvocations = invocations.filter(inv => inv.relPath.endsWith('verify-reapply-patches.cjs'));
assert.deepEqual(
verifierInvocations.map(i => i.relPath),
['get-shit-done/bin/verify-reapply-patches.cjs'],
'workflow must call the runtime-installed verifier path exactly once',
);
});
});