Skip to content

Conversation

@ammar-agent
Copy link
Collaborator

@ammar-agent ammar-agent commented Dec 20, 2025

Summary

Fix several issues causing compaction (/compact) and workspace refresh to fail:

  1. Stream replay blocking caught-up: replayStream() iterated a live parts array that continued growing during an active stream. This could delay the caught-up event indefinitely, leaving the UI stuck on "Loading workspace…". Fixed by snapshotting parts before iteration.

  2. ORPC validation failures for stream mode: Compaction used mode: "compact" in stream-start events, but the schema only allowed plan | exec. This caused EVENT_ITERATOR_VALIDATION_FAILED errors, triggering resubscribe loops. Fixed by allowing any string for mode.

  3. Malformed init-output during replay: Persisted init state could contain malformed entries that failed schema validation when replayed. Added defensive checks to skip invalid entries.

  4. Compaction tool policy bug: toolPolicy: [] was intended to disable tools but actually allowed all tools (empty policy = allow all). Fixed by using an explicit disable-all regex.

Changes

  • src/node/services/streamManager.ts: Snapshot parts array before replay iteration
  • src/common/orpc/schemas/stream.ts: Loosen mode to z.string().optional()
  • src/common/orpc/schemas/workspaceStats.ts: Loosen ModeSchema to string
  • src/node/services/sessionTimingService.ts: Update mode type to string | undefined
  • src/node/services/initStateManager.ts: Skip malformed init-output entries during replay
  • src/browser/utils/messages/compactionOptions.ts: Use explicit disable-all tool policy
  • src/browser/utils/messages/StreamingMessageAggregator.ts: Remove unnecessary type assertion

Testing

  • Added unit test verifying replayStream() snapshots parts and terminates promptly
  • Manual testing of /compact with workspace refresh

Generated with mux • Model: anthropic:claude-opus-4-5 • Thinking: high

@ammar-agent ammar-agent force-pushed the compaction-2z47 branch 4 times, most recently from a2c0256 to 11a3b11 Compare December 20, 2025 21:30
@ammar-agent ammar-agent changed the title 🤖 fix: prevent replayStream from blocking caught-up on reconnect 🤖 fix: compaction stream validation and replay blocking Dec 20, 2025
## Problem 1: Stream replay blocking caught-up
When refreshing a workspace mid-stream (e.g., during compaction), the UI
could get stuck on "Loading workspace…" until the stream completes.

Root cause: `StreamManager.replayStream()` iterates `streamInfo.parts`
directly while calling async `emitPartAsEvent()`. Since `streamInfo.parts`
is mutated as new deltas arrive, the replay loop kept "chasing" newly
appended parts and wouldn't terminate until the stream ended.

Fix: Snapshot `streamInfo.parts` before iterating so replay only processes
parts that existed when replay started.

## Problem 2: ORPC validation failures during compaction
Compaction streams failed ORPC schema validation because:
1. `mode: "compact"` wasn't in the allowed enum (`plan | exec`)
2. Malformed `init-output` events from corrupted persisted state

Fixes:
- Changed `mode` field to `z.string()` instead of enum to support any mode
- Added defensive checks for malformed init-output entries in replay

---
_Generated with `mux` • Model: `anthropic:claude-opus-4-5` • Thinking: `high`_
@ammario ammario merged commit cb30e65 into main Dec 21, 2025
20 checks passed
@ammario ammario deleted the compaction-2z47 branch December 21, 2025 00:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants