mirror of
https://github.com/glittercowboy/get-shit-done
synced 2026-04-25 17:25:23 +02:00
* chore: ignore .worktrees directory Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(install): remove marketing taglines from runtime selection prompt Closes #1654 The runtime selection menu had promotional copy appended to some entries ("open source, the #1 AI coding platform on OpenRouter", "open source, free models"). Replaced with just the name and path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(kilo): update test to assert marketing tagline is removed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(tests): use process.execPath so tests pass in shells without node on PATH Three test patterns called bare `node` via shell, which fails in Claude Code sessions where `node` is not on PATH: - helpers.cjs string branch: execSync(`node ...`) → execFileSync(process.execPath) with a shell-style tokenizer that handles quoted args and inner-quote stripping - hooks-opt-in.test.cjs: spawnSync('bash', ...) for hooks that call `node` internally → spawnHook() wrapper that injects process.execPath dir into PATH - concurrency-safety.test.cjs: exec(`node ...`) for concurrent patch test → exec(`"${process.execPath}" ...`) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: resolve #1656 and #1657 — bash hooks missing from dist, SDK install prompt #1656: Community bash hooks (gsd-session-state.sh, gsd-validate-commit.sh, gsd-phase-boundary.sh) were never included in HOOKS_TO_COPY in build-hooks.js, so hooks/dist/ never contained them and the installer could not copy them to user machines. Fixed by adding the three .sh files to the copy array with chmod +x preservation and skipping JS syntax validation for shell scripts. #1657: promptSdk() called installSdk() which ran `npm install -g @gsd-build/sdk` — a package that does not exist on npm, causing visible errors during interactive installs. Removed promptSdk(), installSdk(), --sdk flag, and all call sites. Regression tests in tests/bugs-1656-1657.test.cjs guard both fixes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: sort runtime list alphabetically after Claude Code - Claude Code stays pinned at position 1 - Remaining 10 runtimes sorted A-Z: Antigravity(2), Augment(3), Codex(4), Copilot(5), Cursor(6), Gemini(7), Kilo(8), OpenCode(9), Trae(10), Windsurf(11) - Updated runtimeMap, allRuntimes, and prompt display in promptRuntime() - Updated multi-runtime-select, kilo-install, copilot-install tests to match Also fix #1656 regression test: run build-hooks.js in before() hook so hooks/dist/ is populated on CI (directory is gitignored; build runs via prepublishOnly before publish, not during npm ci). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
94 lines
2.6 KiB
JavaScript
94 lines
2.6 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Copy GSD hooks to dist for installation.
|
|
* Validates JavaScript syntax before copying to prevent shipping broken hooks.
|
|
* See #1107, #1109, #1125, #1161 — a duplicate const declaration shipped
|
|
* in dist and caused PostToolUse hook errors for all users.
|
|
*/
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const vm = require('vm');
|
|
|
|
const HOOKS_DIR = path.join(__dirname, '..', 'hooks');
|
|
const DIST_DIR = path.join(HOOKS_DIR, 'dist');
|
|
|
|
// Hooks to copy (pure Node.js, no bundling needed)
|
|
const HOOKS_TO_COPY = [
|
|
'gsd-check-update.js',
|
|
'gsd-context-monitor.js',
|
|
'gsd-prompt-guard.js',
|
|
'gsd-read-guard.js',
|
|
'gsd-statusline.js',
|
|
'gsd-workflow-guard.js',
|
|
// Community hooks (bash, opt-in via .planning/config.json hooks.community)
|
|
'gsd-session-state.sh',
|
|
'gsd-validate-commit.sh',
|
|
'gsd-phase-boundary.sh'
|
|
];
|
|
|
|
/**
|
|
* Validate JavaScript syntax without executing the file.
|
|
* Catches SyntaxError (duplicate const, missing brackets, etc.)
|
|
* before the hook gets shipped to users.
|
|
*/
|
|
function validateSyntax(filePath) {
|
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
try {
|
|
// Use vm.compileFunction to check syntax without executing
|
|
new vm.Script(content, { filename: path.basename(filePath) });
|
|
return null; // No error
|
|
} catch (e) {
|
|
if (e instanceof SyntaxError) {
|
|
return e.message;
|
|
}
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
function build() {
|
|
// Ensure dist directory exists
|
|
if (!fs.existsSync(DIST_DIR)) {
|
|
fs.mkdirSync(DIST_DIR, { recursive: true });
|
|
}
|
|
|
|
let hasErrors = false;
|
|
|
|
// Copy hooks to dist with syntax validation
|
|
for (const hook of HOOKS_TO_COPY) {
|
|
const src = path.join(HOOKS_DIR, hook);
|
|
const dest = path.join(DIST_DIR, hook);
|
|
|
|
if (!fs.existsSync(src)) {
|
|
console.warn(`Warning: ${hook} not found, skipping`);
|
|
continue;
|
|
}
|
|
|
|
// Validate JS syntax before copying (.sh files skip — not Node.js)
|
|
if (hook.endsWith('.js')) {
|
|
const syntaxError = validateSyntax(src);
|
|
if (syntaxError) {
|
|
console.error(`\x1b[31m✗ ${hook}: SyntaxError — ${syntaxError}\x1b[0m`);
|
|
hasErrors = true;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
console.log(`\x1b[32m✓\x1b[0m Copying ${hook}...`);
|
|
fs.copyFileSync(src, dest);
|
|
// Preserve executable bit for shell scripts
|
|
if (hook.endsWith('.sh')) {
|
|
try { fs.chmodSync(dest, 0o755); } catch (e) { /* Windows */ }
|
|
}
|
|
}
|
|
|
|
if (hasErrors) {
|
|
console.error('\n\x1b[31mBuild failed: fix syntax errors above before publishing.\x1b[0m');
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log('\nBuild complete.');
|
|
}
|
|
|
|
build();
|