Files
oh-my-claudecode/scripts/project-memory-posttool.mjs
thesqrldev🐿️ 3a44cfebfe suggestion: use temp+rename when writing session stats, try/catch dist imports (#466)
* suggestion: use temp+rename when writing session stats, try/catch dist imports

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* address review feedback: remove ineffective retry loop, narrow catch scope

- loadStats(): remove delay-less retry loop (no benefit for I/O contention)
- project-memory-posttool: catch only ERR_MODULE_NOT_FOUND, log unexpected errors to stderr

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* address review feedback: unique tmp names, debug logging, narrower import catch

- Add OMC_DEBUG-gated debugLog helper to both hook scripts
- Use PID+timestamp+random suffix for temp files to prevent
  container PID namespace collisions
- Add debug logging to loadStats/saveStats catch blocks
- Narrow import error handling: only silence ERR_MODULE_NOT_FOUND
  when dist/ path is involved, log all other errors via debugLog
- Remove direct console.error call in favor of gated logging

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: split dynamic imports into separate try-catch blocks

Wrap each dynamic import in its own try-catch so a failure in the
first module (learner.js) no longer prevents the second module
(finder.js) from loading. This allows partial availability when
only one dist module is missing or broken.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 11:04:58 +09:00

80 lines
2.2 KiB
JavaScript
Executable File

#!/usr/bin/env node
/**
* PostToolUse Hook: Project Memory Learning
* Learns from tool outputs and updates project memory
*/
import { readStdin } from './lib/stdin.mjs';
// Debug logging helper - gated behind OMC_DEBUG env var
const debugLog = (...args) => {
if (process.env.OMC_DEBUG) console.error('[omc:debug:project-memory]', ...args);
};
// Dynamic imports with graceful fallback (separate try-catch for partial availability)
let learnFromToolOutput = null;
let findProjectRoot = null;
try {
learnFromToolOutput = (await import('../dist/hooks/project-memory/learner.js')).learnFromToolOutput;
} catch (err) {
if (err?.code === 'ERR_MODULE_NOT_FOUND' && /dist\//.test(err?.message)) {
debugLog('dist/ learner module not found, skipping');
} else {
debugLog('Unexpected learner import error:', err?.code, err?.message);
}
}
try {
findProjectRoot = (await import('../dist/hooks/rules-injector/finder.js')).findProjectRoot;
} catch (err) {
if (err?.code === 'ERR_MODULE_NOT_FOUND' && /dist\//.test(err?.message)) {
debugLog('dist/ finder module not found, skipping');
} else {
debugLog('Unexpected finder import error:', err?.code, err?.message);
}
}
/**
* Main hook execution
*/
async function main() {
try {
const input = await readStdin();
const data = JSON.parse(input);
// Early exit if imports failed
if (!learnFromToolOutput || !findProjectRoot) {
console.log(JSON.stringify({ continue: true, suppressOutput: true }));
return;
}
// Extract directory and find project root
const directory = data.cwd || data.directory || process.cwd();
const projectRoot = findProjectRoot(directory);
if (projectRoot) {
// Learn from tool output
await learnFromToolOutput(
data.tool_name || data.toolName || '',
data.tool_input || data.toolInput || {},
data.tool_response || data.toolOutput || '',
projectRoot
);
}
// Return success
console.log(JSON.stringify({
continue: true,
suppressOutput: true
}));
} catch (error) {
// Always continue on error
console.log(JSON.stringify({
continue: true,
suppressOutput: true
}));
}
}
main();