poc: workflow debug visualization - #82
Draft
maxy-shpfy wants to merge 1 commit into
Draft
Conversation
This was referenced Sep 4, 2026
Collaborator
Author
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

TL;DR
Adds a
GET /api/sessions/:id/workflowendpoint and a corresponding sidebar panel that surfaces the live workflow state of a conversation — reactors, open runs, waves, correlations, digests, and structured termination causes — without requiring any new persistent state.What changed?
Shared contracts (
packages/shared/src/contracts.ts)New wire types:
ContextPolicyView,WorkflowMembership,WorkflowReactor,WorkflowRun,WorkflowWave,WorkflowRoom,WorkflowView, andWorkflowViewResponse.Server — engine additions
policyViewForincontext.tsserializes aTranscriptVisibility's policy (budget, summarizer, pins) without the non-serializableclassifyfunction.FanOutEngine.listForSessionenumerates every live reaction chain in a session by scanning the wave map.ConversationRouter.listWavesexposes that list through the router;MAX_WAVE_DEPTHis now exported so the view can report it as the budget.ReactorRegistry.inspectAllreturns each reactor's config, scope, folded state, and whether it would fire now.RunRegistry.listForSessionlists every open run for a session from the in-memory map.Server —
workflowViewfold (conversation/workflowView.ts)A pure async function that assembles all of the above into a
WorkflowView. It accepts an optionalconversationIdto scope reactors, runs, correlations, digests, and causes to one conversation, and an optionalparticipantIdto attach that participant's projected room read (resolved through their membership's visibility, defaulting toopaquefor non-members).Server — HTTP route (
routes/sessions/workflow.ts, registered inroutes/sessions/index.ts)GET /:id/workflowvalidates params and an optionalconversationId/participantIdquery, callsworkflowView, and returns{ workflow }. A 404 is returned for unknown sessions.Web — data layer
sessionsApi.getWorkflowfetches the endpoint, forwarding scope params.SessionQueryKeys.Workflowproduces a scoped cache key.useSessionWorkflowwraps the query with a 5-second polling interval; theSessionChatRoomsocket handlers also invalidate the key on message and resource events.Web — UI
WorkflowListrenders each section (reactors, open runs, waves, correlations, digests, causes, omitted ranges) as a scrollable list with status pills.WorkflowWindowandWorkflowWindowHeaderwrap the list in the window system; the header shows a count of waiting reactors.workflow.tsmodel helpers provide human-readable labels for reactor presets, termination cause kinds, and reactor waiting states.Window layout persistence version bumped to 5 to clear stale layouts that predate the new window.
How to test?
awaitAllwith three participants) and complete only some of them. The reactor row should appear as "Waiting" with the correct seen/total count.GET /api/sessions/:id/workflow?conversationId=Xdirectly and verify the response shape matchesWorkflowViewResponse.404 { error: "Session not found" }response.conversationId=Aand confirm that reactors, runs, and correlations scoped to conversationBare absent.conversationIdandparticipantId; confirm theroomfield appears and that a non-member sees zero messages.Why make this change?
Diagnosing a stalled conversation currently requires reading the raw transcript and guessing at which reactor is still waiting, whether a run is open, or whether a wave has hit its budget. All of that information already exists as in-memory folds across the engines — this change assembles it into a single read and surfaces it in a dedicated panel, making workflow state directly inspectable without adding any new persistent state or changing how the engines operate.