Files
msd-core/hooks/msd-check-update.js
Jakub Zych a9a7a328e6 refactor: hard-fork GSD -> MSD (Make Software Done)
Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD
across contents and paths, upstream package/repo coordinates -> @golem15/msd-core
and golem15com/msd-core. Deep links into upstream history, sibling upstream
packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is.

Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line,
package/plugin identity, regenerated lockfile, install-tree fixtures, derived
registries and benchmark baseline; migration checksum baseline re-locked
(MSD keeps its own install state, so no install had applied the old sums);
sort-order and regex-escaped expectations in tests adjusted.
2026-10-06 01:47:40 +02:00

85 lines
3.5 KiB
JavaScript
Executable File

#!/usr/bin/env node
// msd-hook-version: {{MSD_VERSION}}
// Check for MSD updates in background, write result to cache
// Called by SessionStart hook - runs once per session
const fs = require('fs');
const path = require('path');
const os = require('os');
const { spawn } = require('child_process');
// #3582: msd-core/bin/lib/package-identity.cjs is a tsc build artifact
// (ADR-457), gitignored and absent on a raw plugin-marketplace / git-clone
// install that never ran `npm run build:lib`. This SessionStart hook must
// DEGRADE (fall back to a generic cache filename) rather than crash session
// start. msd-check-update-worker.js — the process this hook spawns — degrades
// identically and independently, so the shared fallback literal keeps the
// cache path consistent between writer and reader even in the (rare)
// doubly-degraded case. This try/require/ensureRuntimeBuild/require/catch
// shape is deliberately duplicated (not extracted to hooks/lib/) — see
// msd-check-update-worker.js's identical #3582 comment for why.
let updateCacheFileName = 'msd-update-check.json';
try {
const { ensureRuntimeBuild } = require('../msd-core/bin/ensure-runtime-build.cjs');
ensureRuntimeBuild();
({ updateCacheFileName } = require('../msd-core/bin/lib/package-identity.cjs'));
} catch (e) {
// Runtime library missing/broken and could not self-build — degrade to the
// fallback filename above rather than crash the SessionStart hook.
}
const homeDir = os.homedir();
const cwd = process.cwd();
// Detect runtime config directory (supports Claude, OpenCode, Kilo, Gemini)
// Respects CLAUDE_CONFIG_DIR for custom config directory setups
function detectConfigDir(baseDir) {
// Check env override first (supports multi-account setups)
const envDir = process.env.CLAUDE_CONFIG_DIR;
if (envDir && fs.existsSync(path.join(envDir, 'msd-core', 'VERSION'))) {
return envDir;
}
for (const dir of ['.claude', '.gemini', '.config/kilo', '.kilo', '.config/opencode', '.opencode']) {
if (fs.existsSync(path.join(baseDir, dir, 'msd-core', 'VERSION'))) {
return path.join(baseDir, dir);
}
}
return envDir || path.join(baseDir, '.claude');
}
const globalConfigDir = detectConfigDir(homeDir);
const projectConfigDir = detectConfigDir(cwd);
// Use a shared, tool-agnostic cache directory to avoid multi-runtime
// resolution mismatches where check-update writes to one runtime's cache
// but statusline reads from another (#1421).
const cacheDir = path.join(homeDir, '.cache', 'msd');
const cacheFile = path.join(cacheDir, updateCacheFileName);
// VERSION file locations (check project first, then global)
const projectVersionFile = path.join(projectConfigDir, 'msd-core', 'VERSION');
const globalVersionFile = path.join(globalConfigDir, 'msd-core', 'VERSION');
// Ensure cache directory exists
if (!fs.existsSync(cacheDir)) {
fs.mkdirSync(cacheDir, { recursive: true });
}
// Run check in background via a dedicated worker script.
// Spawning a file (rather than node -e '<inline code>') keeps the worker logic
// in plain JS with no template-literal regex-escaping concerns, and makes the
// worker independently testable.
const workerPath = path.join(__dirname, 'msd-check-update-worker.js');
const child = spawn(process.execPath, [workerPath], {
stdio: 'ignore',
windowsHide: true,
detached: true, // Required on Windows for proper process detachment
env: {
...process.env,
MSD_CACHE_FILE: cacheFile,
MSD_PROJECT_VERSION_FILE: projectVersionFile,
MSD_GLOBAL_VERSION_FILE: globalVersionFile,
},
});
child.unref();