Description
After a run completes and the user clicks "View Summary", the phase timeline only shows the most recent top-level node instead of all completed phases.
Investigation Findings
The server-side computeSummary() (run-manager.ts:667-798) uses a Map<nodeId, phase> to accumulate phases. The RunSummary component renders all summary.phases. The logic appears correct for normal runs.
Possible causes:
-
Map key collision on retry — phaseMap.set(e.nodeId, ...) at line 689 overwrites on duplicate nodeId. If the same node ran twice (e.g., retry from failure), only the last execution shows.
-
Incomplete events.ndjson — getRunEvents() uses in-memory events for active runs, or loadEventsFromDisk() for completed runs. If the active run is garbage collected before summary is requested, events load from NDJSON on disk. A partial write or truncation would result in missing phases.
-
Child nodes excluded by design — child_started/child_completed events are NOT captured in phaseMap, only top-level phase_started/phase_completed. If users expect child node phases in the summary, this is a feature gap.
Reproduction Needed
Please share the events.ndjson file from a run where the summary was incomplete:
~/.forgeflow/runs/{runId}/events.ndjson
This will confirm whether all phase events were persisted.
Files Involved
packages/server/src/services/run-manager.ts — lines 667-798 (computeSummary, phaseMap)
packages/ui/src/components/run-dashboard/RunSummary.tsx — lines 265-283 (phase rendering)
packages/server/src/services/run-manager.ts — line 656 (getRunEvents)
Description
After a run completes and the user clicks "View Summary", the phase timeline only shows the most recent top-level node instead of all completed phases.
Investigation Findings
The server-side
computeSummary()(run-manager.ts:667-798) uses aMap<nodeId, phase>to accumulate phases. TheRunSummarycomponent renders allsummary.phases. The logic appears correct for normal runs.Possible causes:
Map key collision on retry —
phaseMap.set(e.nodeId, ...)at line 689 overwrites on duplicatenodeId. If the same node ran twice (e.g., retry from failure), only the last execution shows.Incomplete events.ndjson —
getRunEvents()uses in-memory events for active runs, orloadEventsFromDisk()for completed runs. If the active run is garbage collected before summary is requested, events load from NDJSON on disk. A partial write or truncation would result in missing phases.Child nodes excluded by design —
child_started/child_completedevents are NOT captured inphaseMap, only top-levelphase_started/phase_completed. If users expect child node phases in the summary, this is a feature gap.Reproduction Needed
Please share the
events.ndjsonfile from a run where the summary was incomplete:This will confirm whether all phase events were persisted.
Files Involved
packages/server/src/services/run-manager.ts— lines 667-798 (computeSummary,phaseMap)packages/ui/src/components/run-dashboard/RunSummary.tsx— lines 265-283 (phase rendering)packages/server/src/services/run-manager.ts— line 656 (getRunEvents)