story-kit: create 173_bug_pipeline_board_lozenges_dont_update_on_agent_state_changes
This commit is contained in:
@@ -7,22 +7,35 @@ title: Pipeline board lozenges don't update on agent state changes
|
|||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
The pipeline board (`LozengeFlyContext`) only refreshes on `WorkItemChanged` and `PipelineState` WebSocket events (file moves between stages). It does not react to `AgentStateChanged` events. This means lozenge colors (amber=unassigned, green=agent working) don't update in real-time when agents are assigned or complete.
|
When an agent is assigned to a work item (coder, QA, mergemaster), the pipeline board lozenge should turn from amber (unassigned) to green (agent working). This works inconsistently — sometimes the lozenge goes green, sometimes it stays amber until a full page refresh. The server data is always correct (the agent IS assigned), so the issue is in the WebSocket push or frontend rendering.
|
||||||
|
|
||||||
The coder assignment appeared to work because the file moved from `1_upcoming` to `2_current` at the same time, triggering a `WorkItemChanged` refresh. But QA assignment doesn't move the file (it's already in `3_qa`), so the lozenge stays amber until a full page refresh.
|
## Investigation findings
|
||||||
|
|
||||||
## Root cause
|
**Server side is correct**: `notify_agent_state_changed()` fires on every `start_agent` call. The WS handler sends both an `AgentStateChanged` message and a `PipelineState` refresh (ws.rs:192-206). The `PipelineState` includes agent assignments via `build_active_agent_map` (workflow.rs:53-83) which correctly filters for Pending/Running agents.
|
||||||
|
|
||||||
`LozengeFlyContext.tsx` does not consume `agentStateVersion` (or any equivalent signal from `AgentStateChanged` WebSocket events). Only `AgentPanel.tsx` reacts to that signal via `stateVersion`.
|
**Likely race condition**: When a story advances stages (e.g. coder passes → moves to QA → QA agent assigned), two events fire close together:
|
||||||
|
1. File move (`WorkItemChanged`) → triggers `PipelineState` push (no agent yet)
|
||||||
|
2. Agent assignment (`AgentStateChanged`) → triggers `PipelineState` push (with agent)
|
||||||
|
|
||||||
|
If the first push overwrites or interferes with the second, the lozenge stays amber. This is inconsistent — sometimes the second push wins (green), sometimes the first push wins (amber).
|
||||||
|
|
||||||
|
**Frontend animation complexity**: `LozengeFlyContext.tsx` uses `useLayoutEffect` to diff previous vs current pipeline state and trigger fly-in/fly-out animations (lines 160-240). When a story changes stage AND agent simultaneously, the animation system processes both a fly-out (coder leaving) and fly-in (QA arriving), which may interfere.
|
||||||
|
|
||||||
|
**The pipeline board DOES receive `PipelineState` updates** — it's passed as a prop from `Chat.tsx:1071` (`<LozengeFlyProvider pipeline={pipeline}>`). So the data reaches the component. The issue is either:
|
||||||
|
- The second `PipelineState` (with agent) is being lost or arrives before the agent is in the HashMap
|
||||||
|
- React batches the two rapid state updates and the `useLayoutEffect` diff misses the agent change
|
||||||
|
- The fly-in/fly-out animation logic interferes when stage and agent change simultaneously
|
||||||
|
|
||||||
## Key files
|
## Key files
|
||||||
|
|
||||||
- `frontend/src/components/LozengeFlyContext.tsx` — needs to react to `AgentStateChanged`
|
- `server/src/http/ws.rs:188-215` — WS handler that sends both `AgentStateChanged` and `PipelineState`
|
||||||
- `frontend/src/components/Chat.tsx:1074` — passes `stateVersion={agentStateVersion}` to `AgentPanel` but not to the pipeline board
|
- `server/src/http/workflow.rs:42-84` — `load_pipeline_state` and `build_active_agent_map`
|
||||||
- `frontend/src/components/AgentPanel.tsx:312` — example of how `stateVersion` triggers a re-fetch
|
- `server/src/agents.rs:447` — where `notify_agent_state_changed` fires in `start_agent`
|
||||||
|
- `frontend/src/components/LozengeFlyContext.tsx:160-240` — `useLayoutEffect` pipeline diff and animation logic
|
||||||
|
- `frontend/src/components/Chat.tsx:237-238` — `onPipelineState` handler that sets `pipeline` state
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
- [ ] Pipeline board re-fetches and updates lozenge colors when an `AgentStateChanged` event is received
|
- [ ] Agent assignment reliably turns lozenges green for all agent types (coder, QA, mergemaster)
|
||||||
- [ ] QA agent assignment turns the lozenge green without a page refresh
|
- [ ] No full page refresh required to see agent state changes on the pipeline board
|
||||||
- [ ] All tests pass
|
- [ ] All tests pass
|
||||||
|
|||||||
Reference in New Issue
Block a user