From 752e65eb5952765ecff1e1ee81559ed571a7d679 Mon Sep 17 00:00:00 2001 From: Merge Sim Date: Fri, 11 Sep 2026 00:36:00 -0700 Subject: [PATCH] fix(agent-status): suppress duplicate child-only row mutation --- src/main/agent-hooks/server/server-ingest-terminal.ts | 2 +- .../agent-hooks/terminal-handle-row-identity.test.ts | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/agent-hooks/server/server-ingest-terminal.ts b/src/main/agent-hooks/server/server-ingest-terminal.ts index af40a1955f4..e7e68115659 100644 --- a/src/main/agent-hooks/server/server-ingest-terminal.ts +++ b/src/main/agent-hooks/server/server-ingest-terminal.ts @@ -87,8 +87,8 @@ export abstract class AgentHookServerIngestTerminal extends AgentHookServerInges event.payload.agentType === 'claude' ) { // Why: OSC has no child identity or lead boundary, so it cannot replace a persisted child-only proof before the lifecycle hook arrives. - this.commitStatusRowMutation(mutationBefore, previous) if (mutationBefore !== undefined) { + this.commitStatusRowMutation(mutationBefore, previous) this.emitEnrichedStatus(previous) } return diff --git a/src/main/agent-hooks/terminal-handle-row-identity.test.ts b/src/main/agent-hooks/terminal-handle-row-identity.test.ts index 35c85d99066..329ffd19958 100644 --- a/src/main/agent-hooks/terminal-handle-row-identity.test.ts +++ b/src/main/agent-hooks/terminal-handle-row-identity.test.ts @@ -200,7 +200,9 @@ describe('the terminal handle a status row is stamped with', () => { it('publishes only the remint observation for a Claude child-only row', () => { const server = new AgentHookServer() const enriched = vi.fn() + const mutations = vi.fn() server.subscribeEnrichedStatus(enriched) + server.subscribeStatusRowMutations(mutations) const payload = { state: 'working' as const, prompt: 'ship it', agentType: 'claude' as const } ingest(server, { payload }) const row = server._getStateForTests().lastStatusByPaneKey.get(PANE_KEY) as @@ -211,12 +213,19 @@ describe('the terminal handle a status row is stamped with', () => { } row.claudeLeadBoundaryChildOnly = true enriched.mockClear() + mutations.mockClear() ingest(server, { payload }) expect(enriched).not.toHaveBeenCalled() + expect(mutations).not.toHaveBeenCalled() ingest(server, { paneKey: NEW_PANE_KEY, tabId: 'tab-reminted', payload }) expect(enriched).toHaveBeenCalledOnce() + expect(mutations).toHaveBeenCalledOnce() + expect(mutations).toHaveBeenCalledWith({ + before: { paneKey: PANE_KEY, worktreeId: 'worktree', terminalHandle: HANDLE }, + after: { paneKey: NEW_PANE_KEY, worktreeId: 'worktree', terminalHandle: HANDLE } + }) expect(enriched).toHaveBeenCalledWith( expect.objectContaining({ paneKey: NEW_PANE_KEY, terminalHandle: HANDLE }) )