From 4546ecf6cd90f9ed390fa75f48aab5eb85d2b0d2 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Mon, 11 May 2026 10:15:48 -0700 Subject: [PATCH] feat: orchestrator OK/ERR verdict parser for batch memory ingest gstack-gbrain-sync.ts: memory-stage parser now picks [memory-ingest] ERR lines preferentially over the latest [memory-ingest] line, strips the prefix and any leading 'ERR: ' for cleaner summary output, and surfaces '(killed by signal / timeout)' when the child exits with status=null. Matches D6's OK/ERR contract: per-file failures (FILE_TOO_LARGE etc.) show in the summary count but only system-level failures (gbrain crash, process kill, missing CLI) mark the stage ERR. Co-Authored-By: Claude Opus 4.7 (1M context) --- bin/gstack-gbrain-sync.ts | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/bin/gstack-gbrain-sync.ts b/bin/gstack-gbrain-sync.ts index 9f8e477c8..36b265e42 100644 --- a/bin/gstack-gbrain-sync.ts +++ b/bin/gstack-gbrain-sync.ts @@ -442,14 +442,30 @@ function runMemoryIngest(args: CliArgs): StageResult { timeout: 35 * 60 * 1000, }); - const summary = (result.stderr || "").split("\n").filter((l) => l.includes("[memory-ingest]")).slice(-1)[0] || "ingest pass complete"; + // D6: parse [memory-ingest] lines from the child's stderr. ERR-prefixed + // lines indicate a system-level failure (gbrain crashed or CLI missing) + // and the child exits non-zero. Per-file failures are summarized in the + // last non-ERR [memory-ingest] line but do NOT make the verdict ERR. + const stderrLines = (result.stderr || "").split("\n"); + const memLines = stderrLines.filter((l) => l.includes("[memory-ingest]")); + const errLine = memLines.find((l) => l.includes("[memory-ingest] ERR")); + const lastMemLine = memLines.slice(-1)[0]; + const rawSummary = errLine || lastMemLine || "ingest pass complete"; + // Strip the "[memory-ingest] " prefix and any leading "ERR: " for cleaner + // verdict output. The orchestrator's own formatStage will prefix with OK/ERR. + const summary = rawSummary + .replace(/^.*\[memory-ingest\]\s*/, "") + .replace(/^ERR:\s*/, ""); + const ok = result.status === 0; return { name: "memory", ran: true, - ok: result.status === 0, + ok, duration_ms: Date.now() - t0, - summary: result.status === 0 ? summary : `memory ingest exited ${result.status}`, + summary: ok + ? summary + : `${summary}${result.status === null ? " (killed by signal / timeout)" : ` (exit ${result.status})`}`, }; }