fix: harden error handling, fix TOCTOU races, and improve test accuracy

Core library fixes:
- session-manager.js: wrap all statSync calls in try-catch to prevent
  TOCTOU crashes when files are deleted between readdir and stat
- session-manager.js: use birthtime||ctime fallback for Linux compat
- session-manager.js: remove redundant existsSync before readFile
- utils.js: fix findFiles TOCTOU race on statSync inside readdir loop

Hook improvements:
- Add 1MB stdin buffer limits to all PostToolUse hooks to prevent
  unbounded memory growth from large payloads
- suggest-compact.js: use fd-based atomic read+write for counter file
  to reduce race window between concurrent invocations
- session-end.js: log when transcript file is missing, check
  replaceInFile return value for failed timestamp updates
- start-observer.sh: log claude CLI failures instead of silently
  swallowing them, check observations file exists before analysis

Test fixes:
- Fix blocking hook tests to send matching input (dev server command)
  and expect correct exit code 2 instead of 1
This commit is contained in:
Affaan Mustafa
2026-02-12 13:40:14 -08:00
parent f375171b13
commit 36864ea11a
11 changed files with 113 additions and 44 deletions

View File

@@ -99,17 +99,24 @@ async function main() {
const transcriptPath = process.env.CLAUDE_TRANSCRIPT_PATH;
let summary = null;
if (transcriptPath && fs.existsSync(transcriptPath)) {
summary = extractSessionSummary(transcriptPath);
if (transcriptPath) {
if (fs.existsSync(transcriptPath)) {
summary = extractSessionSummary(transcriptPath);
} else {
log(`[SessionEnd] Transcript not found: ${transcriptPath}`);
}
}
if (fs.existsSync(sessionFile)) {
// Update existing session file
replaceInFile(
const updated = replaceInFile(
sessionFile,
/\*\*Last Updated:\*\*.*/,
`**Last Updated:** ${currentTime}`
);
if (!updated) {
log(`[SessionEnd] Failed to update timestamp in ${sessionFile}`);
}
// If we have a new summary and the file still has the blank template, replace it
if (summary) {