Skip to content

Commit f74e3e7

Browse files
oalanicolasclaude
andauthored
fix: resolve ConfigCache.has() stat inflation and hook system errors (#582)
* fix: resolve ConfigCache.has() stat inflation and hook system errors (#497, #528) Reimplemented has() to check Map directly without touching metrics. Applied to both core/config/ and infrastructure/scripts/ copies. runner path didn't account for node_modules layout. Added path resolution with fallback candidates. Also fixed: - synapse-engine.cjs: replaced process.exit() with process.exitCode for clean stdout flush - hook-runtime.js: create session file on first prompt when loadSession returns null (prevents silent updateSession failures) Updated tests to match new behavior (process.exitCode, createSession export). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: regenerate manifest with updated entity-registry hash Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address CodeRabbit review issues for PR #582 - precompact-session-digest.cjs: spawn detached child process instead of require()-ing runner in-process. The runner uses setImmediate internally which kept the event loop alive and caused the hook to block (wait for the 9 s safety timeout) instead of being fire-and-forget. Context is forwarded via AIOX_HOOK_CONTEXT env var to the inline Node script. - synapse-engine.cjs: replace process.exitCode = 0 with process.exit(0) in the timeout callback. process.exitCode alone does not terminate the process when active handles remain (e.g. stdout backpressure), defeating the 5 s hard limit that protects Claude Code from a blocking hook. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add error handling for spawn and JSON serialization in precompact hook Addresses CodeRabbit review: handle spawn 'error' event and JSON.stringify failures to prevent unhandled exceptions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: regenerate install manifest after rebase Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 602b149 commit f74e3e7

File tree

8 files changed

+1198
-1141
lines changed

8 files changed

+1198
-1141
lines changed

.aiox-core/core/config/config-cache.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,16 @@ class ConfigCache {
7272
* @returns {boolean} True if key exists and is valid
7373
*/
7474
has(key) {
75-
return this.get(key) !== null;
75+
if (!this.cache.has(key)) {
76+
return false;
77+
}
78+
const timestamp = this.timestamps.get(key);
79+
if (Date.now() - timestamp > this.ttl) {
80+
this.cache.delete(key);
81+
this.timestamps.delete(key);
82+
return false;
83+
}
84+
return true;
7685
}
7786

7887
/**

.aiox-core/core/synapse/runtime/hook-runtime.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,24 @@ function resolveHookRuntime(input) {
4646
if (!fs.existsSync(synapsePath)) return null;
4747

4848
try {
49-
const { loadSession, cleanStaleSessions } = require(
49+
const { loadSession, createSession, cleanStaleSessions } = require(
5050
path.join(cwd, '.aiox-core', 'core', 'synapse', 'session', 'session-manager.js'),
5151
);
5252
const { SynapseEngine } = require(
5353
path.join(cwd, '.aiox-core', 'core', 'synapse', 'engine.js'),
5454
);
5555

5656
const sessionsDir = path.join(synapsePath, 'sessions');
57-
const session = loadSession(sessionId, sessionsDir) || { prompt_count: 0 };
57+
58+
// Create session file on first prompt if it doesn't exist.
59+
// Without this, updateSession() silently fails because loadSession() returns null.
60+
let session = loadSession(sessionId, sessionsDir);
61+
if (!session && sessionId) {
62+
session = createSession(sessionId, cwd, sessionsDir);
63+
}
64+
if (!session) {
65+
session = { prompt_count: 0 };
66+
}
5867
const engine = new SynapseEngine(synapsePath);
5968

6069
// AC3: Run cleanup on first prompt only (fire-and-forget)

0 commit comments

Comments
 (0)