fix(clients): derive the steer-pending marker from thread state - #186
Merged
Merged
Conversation
The "Waiting for the agent to pick this up" marker lived in an in-memory store that the thread view purged on unmount, so navigating away and back lost it, and it never showed on another device or after a reload. A steer that waits long enough to matter is exactly the one you walk away from. Derive it instead: a user message with a null turn id, created after the running turn was requested and after the last main-agent tool start or assistant message, is an unread steer. Both timestamps are server-stamped (the server replaces the client's createdAt on receipt), so no client clock is involved. The outbox drain no longer records dispatches, and the lease/refcount store is gone. The reveal delay stays as the only local state.
…ity cap Review follow-ups for the derived steer-pending marker. The marker resolves against the running turn's newest main-agent tool start. A long subagent fan-out can push that row past the 500-activity window on both the server snapshot and the client's live retention, at which point every steer newer than the turn would come back as unread. Pin that one row the same way the latest context-window update is pinned: the server's pinned-activity CTE carries it into detail reads while the turn is running, and the client reducer keeps it through the cap. Also from review: null-byte key separator, sync pointer between the two identical hooks, tighter comments, and two more derivation tests.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (16)
📝 WalkthroughWalkthroughThe change replaces client-local steer dispatch tracking with server-derived thread state. It updates activity retention and server projections so parent-agent progress remains available, then adapts web and mobile hooks and documentation to the new behavior. ChangesSteer pending state
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant ServerProjection
participant ClientRuntime
participant WebOrMobileHook
ServerProjection->>ClientRuntime: provide running-turn messages and parent progress
ClientRuntime->>WebOrMobileHook: derive unreadSteerMessageIds(snapshot)
WebOrMobileHook-->>ClientRuntime: reveal pending IDs after delay
Suggested reviewers: ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
Problem
The "Waiting for the agent to pick this up" marker was tracked in an in-memory store that each thread view leased on mount and purged on unmount. Navigating to another thread and back lost the marker, and it never showed on another device or after a reload. A steer that waits long enough to matter is exactly the one you walk away from, so in practice the marker was almost never seen.
Fix
Derive the marker from thread state. A user message with a null turn id, created after the running turn was requested and after the last main-agent tool start or assistant message, is an unread steer. Both timestamps are server-stamped (the server replaces the client's
createdAton receipt, adapters stamp activities with the server clock), so no client clock is involved.packages/client-runtime:unreadSteerMessageIds(snapshot)replaces the dispatch store, lease refcount, and watermark record.readThreadDetailhelper in web, which had no other caller.docs/user/message-queueing.mdupdated to say the marker follows the conversation, not the device.Review follow-up (second commit)
The marker resolves against the running turn's newest main-agent tool start. A long subagent fan-out can push that row past the 500-activity window on both the server snapshot and the client's live retention, and every steer newer than the turn would then come back as unread. That row is now pinned the same way the latest context-window update already is: the server's pinned-activity CTE carries it into detail reads while the turn is running, and the client reducer keeps it through the cap. Plus a null-byte key separator, a sync pointer between the two identical hooks, and two more derivation tests.
Two review findings were considered and not changed:
Verification
vp test runon the steer-pending, thread-reducer, and mobile outbox-drain tests, and the serverProjectionSnapshotQuerytests: all pass.client-runtime,web,mobile,server. Lint and format clean on touched files.Claude Fable 5.1 via Claude Code, with Sol (gpt-5.6) and Opus review passes.
Summary by CodeRabbit