fix(mode): a failed flush re-parks the pending intent instead of dropping it
Review hardening (the finding's ordering premise did not hold — see the PR thread — but its failure-path kernel did): onBoundary cleared the pending intent BEFORE appending the mode/set, so a backend rejecting that one write lost the switch forever while the picker kept showing it optimistically. The intent is now cleared only after the append lands; a failed flush stays parked and the next healthy boundary converges the log with the picker. The containment test extends to pin the re-park and the retry. The bridge's re-notify keeps deriving from the logged event's value — now documented in place: the service holds ONE coalesced pending slot (every flush reads the latest selection, so a stale flush cannot exist), and for any other writer the logged value is the truth the picker should track, in log order.
This commit is contained in:
@@ -511,6 +511,11 @@ export function apply(ctx: Context, config: AcpConfig): void {
|
||||
enabled: rec.terminalEnabled,
|
||||
cwd: session.header.cwd,
|
||||
}, { includeUserMessages: false })
|
||||
// Re-notify from the EVENT's value, not from modes.get(): the service
|
||||
// holds one coalesced pending slot (every flush reads the latest
|
||||
// selection, so a flush can never be stale against the picker), and for
|
||||
// any other writer — the exit tool, a test, a foreign plugin — the logged
|
||||
// value IS the truth the picker should track, in log order.
|
||||
if (event.type === 'mode/set' && event.data.mode !== rec.lastModeId) {
|
||||
rec.lastModeId = event.data.mode
|
||||
notify({ sessionId: rec.sessionId, update: { sessionUpdate: 'current_mode_update', currentModeId: event.data.mode } })
|
||||
|
||||
Reference in New Issue
Block a user