-
Notifications
You must be signed in to change notification settings - Fork 2
plat 254
PLAT-254 — Execution Logs panel showed misleading recency data; execute_step never stated which run_folder/group it actually used
| Coordination | Value |
|---|---|
| Assigned agent | Claude Code |
| Ticket state | implemented |
| Last synchronized | 2026-08-30 |
-
Priority: P1 — reported live by the user while actively debugging a real
workflow (
confida-login), with screenshots at each step. -
Owner:
frontend/src/components/workflow/ExecutionLogsPopup.tsx,frontend/src/components/workflow/canvas/WorkflowCanvas.tsx,agent_go/pkg/orchestrator/agents/workflow/step_based_workflow/interactive_workshop_manager.go.
The user pinned a step's LLM to gemini-3.7-flash via update_step_config,
re-ran it, and the Execution Logs panel's step-summary row kept showing the
old model (claude-haiku-4-5) instead. Investigation (with live disk reads
against the real workflow, not guesses) found four separate, real defects
under one umbrella — a step's "Attempt N" number is a fixed retry-slot
label, not chronological order: a fresh top-level re-run overwrites the
"attempt 1" slot's file while an unrelated, much older "attempt 2" from a
completely different run can sit right next to it, hours or days apart.
Confirmed live: execution-attempt-1-iteration-0.json had completed_at
2026-08-30T04:44:02Z (the new gemini-3.7-flash run) while
execution-attempt-2-iteration-0.json still held 2026-08-29T17:43:22Z
(the old claude-haiku run) — attempt 2 was ~11 hours older than attempt 1.
-
getStepModel()picked the wrong attempt. It walked the executions array backwards and returned the first non-fast-path model found, assuming the last array element was newest. It wasn't — it returned attempt 2's (older) model instead of attempt 1's (actually newest). -
The "Validations" section labeled every entry "Validation attempt 1"
regardless of which of several genuinely different validation phases/
executions it was. Real workflow data showed 5 validation records
spanning
initial-check,saved-script, and two separatefinal-gateexecutions (execution_001,execution_002) — all rendered with the same useless "1", because the field used (validation_attempt) is nearly always 1 and doesn't distinguish phase or execution slot at all. -
No datetime shown anywhere in the attempt/validation lists, so
recency was unverifiable from the UI at all — the only way to tell which
attempt was actually newest was to read the raw JSON files'
started_at/completed_at/timestampfields directly on disk. -
execute_step's response never stated whichrun_folder/group it resolved to.group_nameis optional on the tool; when omitted, the handler silently falls back toenabledGroupNames[0]or the first variables-manifest group. If that differs from the group the user actually meant, the run writes real logs into a sibling folder (runs/iteration-0/<other-group>/) with zero indication anything went to the "wrong" place.
Separately, but discovered investigating the same "stale panel" report: the
panel's own refresh icon (RefreshCw in the header) only ever re-fetches
logs for the currently selected run folder — it never refreshes the
run-folder list itself (runFolders/the dropdown). That list comes from
workspaceState.run_folders in the parent canvas, cached by
useWorkspaceState() and only invalidated by the outer canvas "Refresh"
button — a different control entirely. A run folder that appeared after the
panel last loaded stayed invisible in the dropdown no matter how many times
the panel's own refresh was clicked.
Two live-checked reports that turned out not to be bugs, worth recording
so they aren't re-litigated: (a) a step's description length shown in the
panel ("9.4k instr") exactly matched the current on-disk plan.json value
(9362 chars) — the user had believed they'd edited that step's description
down, but the changelog showed no such edit; they'd actually edited a
different step. (b) That different step's description length (7096 chars,
"7.1k instr") also exactly matched two real, changelog-recorded edits in
sequence (9173→10256→7096) — the panel was accurate both times, not stale.
-
getStepModel()(ExecutionLogsPopup.tsx) now compares each execution's realcompleted_at/started_attimestamp and returns the model from the one with the latest timestamp, not the last array element. - "Attempt N" rows (
ExecutionLogsPopup.tsx) now show a real datetime chip (completed_atfalling back tostarted_at), so recency is never a guess. - Validation rows now label with the real distinguishing fields —
validation_phase(initial-check/saved-script/final-gate) andexecution_attempt— plus a real datetime, instead of avalidation_attemptnumber that's nearly always 1. -
execute_step's immediate response (interactive_workshop_manager.go) now includesrun_folder: "<resolved>"explicitly, with an inline note when no group could be resolved at all (no defined variable groups in the workspace). - The panel's refresh button now also calls a new optional
onRefreshRunFoldersprop (wired toWorkflowCanvas.tsx's existingrefreshWorkspaceState()— the same function the outer canvas "Refresh" button already used), so a newly-appeared run folder is discoverable from the panel's own refresh, not only the outer canvas one.
Also folded into the same pass (found while reading this component's
ConversationViewer.tsx sibling): the "FULL CALL TIMELINE" summary inside
each execution's conversation view previously showed only timing metadata
per call (name/duration/tokens) with no way to see the actual tool-call
arguments or LLM response — every row is now expandable in place, reusing
the same ConversationToolCallDisplay/ConversationToolResponseDisplay
components the full conversation history already uses, matched back to the
real content by tool_call_id. The "Back to all steps" sticky header (a
separate, earlier live report) was also made to shrink on scroll instead of
permanently eating vertical space, with hysteresis (different scroll
thresholds to shrink vs. re-expand) after the first version was reported to
flicker on tiny scroll movements.
-
onRefreshRunFolderswas wired only intoWorkflowCanvas.tsx's embedded panel usage — the three other call sites (WorkflowsOverviewPage.tsx,EmployeeDashboard.tsx,WorkflowScheduleRunsPanel.tsx) have their own, different run-folder data flows and were left unwired; the prop is optional so nothing regresses there, they just don't get the same refresh-scope fix yet. - Did not add stricter validation rejecting an ambiguous/omitted
group_namewhen a workspace has multiple groups — only surfaced what was actually resolved. A hard requirement was considered but not requested; this ticket scoped to "never silently ambiguous," not "never optional."
-
go build ./...clean;pkg/orchestrator/agents/workflow/step_based_workflowfull test suite passes (0 failures) after theexecute_stepresponse change. -
npx tsc --noEmit -p .andnpm run buildclean after every frontend change in this ticket. - Root cause for the model-recency bug confirmed against real, live
confida-loginworkflow data (not synthetic) — actualcompleted_attimestamps read directly from the two attempt files before writing the fix.
Re-run a step whose LLM config was just changed, confirm the step-summary
row's model chip shows the new model immediately (no manual attempt-order
reasoning required), and confirm a standalone execute_step run's folder
shows up in the panel's dropdown after clicking the panel's own refresh
button, without needing the outer canvas refresh.
Execution Logs now includes a separate Pulse reviews section for the
selected retained run. Each manual or scheduled Pulse pass remains a distinct,
timestamped entry and exposes its background review agents, status, duration,
provider/model, parent orchestrator execution ID, original instruction,
assistant messages, tool calls, result, and errors from the durable structured
transcript. Ordinary workflow step sub-agents are excluded: scheduled sessions
use the full-run completion boundary, while manual Pulse sessions use their
explicit manual-pulse schedule identity. Transcript read/parse failures are
shown instead of being mistaken for an empty review.
Verification added in workflow_pulse_execution_logs_test.go covers scheduled
post-run selection, group-aware retained-folder matching, transcript loading,
and manual Pulse runs without a full-run lifecycle marker. go test ./cmd/server and frontend TypeScript compilation pass.
Auto-synced from docs/ on main. Edit there, not here.