From c280015bb4bf0ca2081d4849e84594871cd5187f Mon Sep 17 00:00:00 2001 From: antfleet-ops <285575208+antfleet-ops@users.noreply.github.com> Date: Fri, 19 Jun 2026 13:38:25 +0300 Subject: [PATCH] Preserve events appended during drain Constraint: keep the file-based listen/drain protocol and output shape.\nRejected: truncating the recreated output file | loses events appended after rename.\nConfidence: medium\nScope-risk: narrow\nDirective: future drain changes must treat the original path as producer-owned after rename.\nTested: npm run typecheck; npm run build\nNot-tested: concurrent filesystem integration test. --- src/commands/events.ts | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/commands/events.ts b/src/commands/events.ts index 2c126d8..6332914 100644 --- a/src/commands/events.ts +++ b/src/commands/events.ts @@ -62,6 +62,15 @@ function phaseToEventType(phase: AcpJobPhases): string { } } +function readEventLines(file: string): string[] { + try { + const content = readFileSync(file, "utf-8").trim(); + return content ? content.split("\n") : []; + } catch { + return []; + } +} + export function registerEventsCommand(program: Command): void { const events = program .command("events") @@ -311,13 +320,7 @@ export function registerEventsCommand(program: Command): void { const lockFile = file + ".lock"; renameSync(file, lockFile); - let lines: string[]; - try { - const content = readFileSync(lockFile, "utf-8").trim(); - lines = content ? content.split("\n") : []; - } catch { - lines = []; - } + const lines = readEventLines(lockFile); const takeCount = limit !== undefined && limit > 0 @@ -326,10 +329,14 @@ export function registerEventsCommand(program: Command): void { const taken = lines.slice(0, takeCount); const remaining = lines.slice(takeCount); - // Write remaining events back to original path, then remove lock file + const concurrentlyAppended = readEventLines(file); + const mergedRemaining = [...remaining, ...concurrentlyAppended]; + + // Write remaining events back to original path, preserving events + // appended by a listener after the original file was renamed. writeFileSync( file, - remaining.length > 0 ? remaining.join("\n") + "\n" : "" + mergedRemaining.length > 0 ? mergedRemaining.join("\n") + "\n" : "" ); try { unlinkSync(lockFile); @@ -347,7 +354,7 @@ export function registerEventsCommand(program: Command): void { }) .filter(Boolean); - outputResult(json, { events, remaining: remaining.length }); + outputResult(json, { events, remaining: mergedRemaining.length }); } catch (err) { outputError(json, err instanceof Error ? err : String(err)); }