fix: ghost watch false-positive reactivation on trailing writes
When the lock file is deleted (turn complete) and triggerIdle fires, the transcript file continues receiving writes (the agent's own reply being appended). The ghost watch was firing session-reactivate on these trailing writes, causing an immediate complete→reactivate→complete loop within the same turn. Fix: only emit session-reactivate from ghost watch if the lock file currently exists. A JSONL write without a lock file is a trailing write from the completed turn, not a new user message.
This commit is contained in:
@@ -341,9 +341,21 @@ class StatusWatcher extends EventEmitter {
|
|||||||
// Ghost watch: file changed for a completed session — signal immediate re-detection
|
// Ghost watch: file changed for a completed session — signal immediate re-detection
|
||||||
if (sessionKey.startsWith('\x00ghost:')) {
|
if (sessionKey.startsWith('\x00ghost:')) {
|
||||||
const originalKey = sessionKey.slice(7);
|
const originalKey = sessionKey.slice(7);
|
||||||
|
// Only trigger reactivation if the lock file currently exists.
|
||||||
|
// A JSONL write without a lock file is a trailing write from the just-completed
|
||||||
|
// turn — not a new user message. Emitting reactivation here causes a false
|
||||||
|
// complete→reactivate→complete loop within the same turn.
|
||||||
|
const lockFile = fullPath + '.lock';
|
||||||
|
const lockExists = (() => { try { fs.statSync(lockFile); return true; } catch (_) { return false; } })();
|
||||||
|
if (!lockExists) {
|
||||||
|
if (this.logger) {
|
||||||
|
this.logger.debug({ sessionKey: originalKey }, 'fs.watch: ghost file change but no lock file — skipping reactivation (trailing write)');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Do NOT delete ghost entry here — let caller clean up after pollNow confirms the session
|
// Do NOT delete ghost entry here — let caller clean up after pollNow confirms the session
|
||||||
if (this.logger) {
|
if (this.logger) {
|
||||||
this.logger.info({ sessionKey: originalKey }, 'fs.watch: file change on completed session — triggering reactivation');
|
this.logger.info({ sessionKey: originalKey }, 'fs.watch: file change on completed session (lock file present) — triggering reactivation');
|
||||||
}
|
}
|
||||||
this.emit('session-reactivate', originalKey, fullPath);
|
this.emit('session-reactivate', originalKey, fullPath);
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user