fix(terminal): attribute repeated block output by invocation - #7002
fix(terminal): attribute repeated block output by invocation#7002BillLeoutsakosvl346 wants to merge 5 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview The executor now mints a stable Reviewed by Cursor Bugbot for commit 5cd6cc1. Bugbot is set up for automated code reviews on this repo. Configure here. |
Greptile SummaryThis PR introduces a per-invocation block execution identifier and carries it through executor callbacks, streaming events, traces, reconciliation, and terminal-store indexing.
Confidence Score: 4/5The PR should not merge until final selected-output assembly consistently recognizes invocation-keyed streamed content. Production streams are stored under blockExecutionId, while final-result suppression still queries by blockId and can therefore re-emit streamed content or select the first repeated invocation's log. Files Needing Attention: apps/sim/lib/workflows/streaming/streaming.ts
|
| Filename | Overview |
|---|---|
| apps/sim/lib/workflows/streaming/streaming.ts | Invocation-keyed stream accumulation is inconsistent with block-keyed final-result suppression, allowing duplicate or stale final output. |
| apps/sim/executor/execution/block-executor.ts | Mints a distinct invocation ID per block execution and preserves it through retries, callbacks, and streaming. |
| apps/sim/stores/terminal/console/store.ts | Adds direct invocation indexing with validated lookup, legacy fallback, and coherent rebuild/removal paths. |
| apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils/workflow-execution-utils.ts | Reconciles lifecycle events, final logs, and nested spans by invocation ID with strict legacy fallback. |
| apps/sim/lib/workflows/executor/execution-events.ts | Propagates invocation identity across block lifecycle and agent-stream event variants. |
Sequence Diagram
sequenceDiagram
participant Executor
participant Stream as Streaming adapter
participant State as Stream state
participant Final as Final-result builder
Executor->>Stream: onStream(blockId, blockExecutionId)
Stream->>State: "streamedChunks[blockExecutionId] += chunk"
Executor->>Stream: onBlockComplete(blockId, blockExecutionId)
Stream->>State: completedBlockIds.add(blockId)
Final->>State: streamedContent.has(blockId)
State-->>Final: false
Final->>Final: find first log by blockId
Final-->>Stream: Include already-streamed or stale output
Reviews (1): Last reviewed commit: "fix(terminal): attribute repeated block ..." | Re-trigger Greptile
|
Browser E2E evidence (local app, commit 08e9b86): Iteration 1/2 selected — successful output is isolated to
Iteration 2/2 selected — failure is isolated to
|
08e9b86 to
b983bd2
Compare
42c3b4e to
20dc04e
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 20dc04e. Configure here.
Screen.Recording.2026-08-22.at.6.56.46.PM.mov |
|
Closing after validating the reported attribution path directly on clean origin/staging at bbf408b.\n\nBrowser baseline results:\n- Start -> Loop (2) -> Function, with iteration 0 succeeding and iteration 1 failing: each terminal row kept its own output/status.\n- Start -> Loop (2) -> Slack list-channels, with the Slack error port routed through a local Wait so both generic-handler invocations completed: the terminal rendered Slack (iteration 0) at 10ms and Slack (iteration 1) at 9ms as separate rows, and selecting either row retained that invocation's state.\n\nThis confirms the existing executionOrder correlation already covers the reported non-streaming Slack case on staging. The blockExecutionId protocol in this PR is therefore redundant, and its central duplicate-executionOrder fixture does not represent the executor's documented invariant. I am not replacing it with a speculative streaming-only change because there is no failing in-scope reproduction for that path.\n\nAll disposable browser-test workflows were deleted. The branch is being left intact for audit/history. |



Root cause
Workflow-terminal updates identified entries with the static block ID and execution ID. Repeated invocations of the same block can share those values, so later iteration events could update or reconcile multiple terminal rows. Deployment traces remained correct because their final block logs and spans retained per-occurrence ordering.
Fix
blockExecutionIdfor each user-visible block invocation.blockExecutionId-to-entry index to the terminal store.blockIdfor existing UI contracts.The field remains optional for mixed-version reconnects and hydrated legacy data. This does not alter database schemas, public REST APIs, terminal grouping, row ordering, rendering, or deployment-trace grouping.
Focused coverage
The regression coverage verifies colliding loop rows remain isolated, replayed starts are idempotent, ambiguous legacy updates do not fan out, invocation IDs are distinct and stable through retries and lifecycle callbacks, final reconciliation targets the correct invocation, nested traces preserve identity, every agent-stream event variant forwards the ID, legacy child-workflow rows can be enriched safely, and mixed streamed/non-streamed sibling invocations do not duplicate or leak selected output.
Verification
git diff --checkbun run type-checkbun run lint:checkbun run test: 31,061 passed, 46 skippedresult.iteration = 0and iteration 1 contains onlyiteration-1-failurein both terminal and deployment traceAutomated review
Greptile and Bugbot findings covering final stream reconciliation, legacy child-workflow enrichment, deployment mixed-invocation output, and chat mixed-invocation output were resolved with focused tests. The latest Bugbot and required checks are green, with no unresolved review threads.