- intel-index.js → gsd-intel-index.js - intel-session.js → gsd-intel-session.js - intel-prune.js → gsd-intel-prune.js Consistent naming allows installer to manage GSD hooks easily. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
79 lines
2.1 KiB
JavaScript
79 lines
2.1 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Intel Prune Hook (Stop event)
|
|
*
|
|
* Removes stale entries from index.json when files no longer exist.
|
|
* Runs after each Claude response to keep intel fresh.
|
|
*
|
|
* Fast: Only does fs.existsSync checks, no file reading.
|
|
* Silent: Never blocks or errors, always exits 0.
|
|
*/
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
function pruneIndex() {
|
|
const intelDir = path.join(process.cwd(), '.planning', 'intel');
|
|
const indexPath = path.join(intelDir, 'index.json');
|
|
|
|
// Only run if intel directory exists (opt-in check)
|
|
if (!fs.existsSync(intelDir)) {
|
|
return { pruned: 0, total: 0 };
|
|
}
|
|
|
|
// Read existing index
|
|
let index;
|
|
try {
|
|
const content = fs.readFileSync(indexPath, 'utf8');
|
|
index = JSON.parse(content);
|
|
} catch (e) {
|
|
// No index or invalid JSON
|
|
return { pruned: 0, total: 0 };
|
|
}
|
|
|
|
if (!index.files || typeof index.files !== 'object') {
|
|
return { pruned: 0, total: 0 };
|
|
}
|
|
|
|
// Check each file and collect deleted ones
|
|
const filePaths = Object.keys(index.files);
|
|
const deleted = filePaths.filter(filePath => !fs.existsSync(filePath));
|
|
|
|
if (deleted.length === 0) {
|
|
return { pruned: 0, total: filePaths.length };
|
|
}
|
|
|
|
// Remove deleted entries
|
|
for (const filePath of deleted) {
|
|
delete index.files[filePath];
|
|
}
|
|
index.updated = Date.now();
|
|
|
|
// Write updated index
|
|
fs.writeFileSync(indexPath, JSON.stringify(index, null, 2));
|
|
|
|
// Regenerate conventions and summary after pruning
|
|
// Import detection logic from intel-index.js would be complex,
|
|
// so we just update the index. Conventions/summary stay until
|
|
// next PostToolUse or /gsd:analyze-codebase refresh.
|
|
|
|
return { pruned: deleted.length, total: filePaths.length };
|
|
}
|
|
|
|
// Read JSON from stdin (standard hook pattern)
|
|
let input = '';
|
|
process.stdin.setEncoding('utf8');
|
|
process.stdin.on('data', chunk => input += chunk);
|
|
process.stdin.on('end', () => {
|
|
try {
|
|
// Stop hook receives session data, but we don't need it
|
|
// Just prune stale entries
|
|
pruneIndex();
|
|
process.exit(0);
|
|
} catch (error) {
|
|
// Silent failure - never block Claude
|
|
process.exit(0);
|
|
}
|
|
});
|