feat(desktop): surface buried agent-to-human replies to channel timeline#1057
Draft
wpfleger96 wants to merge 1 commit into
Draft
feat(desktop): surface buried agent-to-human replies to channel timeline#1057wpfleger96 wants to merge 1 commit into
wpfleger96 wants to merge 1 commit into
Conversation
Collaborator
Author
Surfaced reply appears in timelineAgent (alice) replies nested to a human's root message, mentioning the user — a pointer row surfaces in the channel timeline at the reply's own timestamp. Multiple surfaced replies interleave chronologicallyTwo threads, each with an agent reply mentioning a human — both surface as pointer rows, sorted by createdAt among root messages. Agent-to-agent reply does NOT surfaceA nested agent reply that only mentions another agent — no pointer row appears. The surfacing filter correctly requires a human p-tag. Click navigates to nested messageClicking a surfaced-reply pointer opens the thread panel and highlights the actual nested reply in context. |
wpfleger96
pushed a commit
that referenced
this pull request
Jun 15, 2026
28322ec to
6682de8
Compare
The channel timeline renders only root-level entries, making agent
replies to humans in threads invisible to the humans who read the
channel. Added a surfaceReplies projection that identifies nested
agent-to-human replies and a mergeSurfacedReplies helper that
interleaves pointer rows into the root timeline by (createdAt, id).
SurfacedReplyRow renders each pointer and navigates via the existing
goChannel({messageId, threadRootId}) mechanism — the same path search
hits use. De-dupe is strict body-match so an agent's unrelated earlier
root post cannot suppress a genuinely new nested reply. Agent-to-agent
replies are explicitly excluded.
Includes E2E screenshot spec covering the four key scenarios (surfaced
reply present, multiple replies interleaved, agent-to-agent suppressed,
click-to-navigate) and hardened settle() to race animation promises
against a 1s timeout so AbortError on cancelled animations can't tear
down the page.evaluate context mid-await.
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
e4cb25c to
d76caa9
Compare
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.




Summary
Buried agent-to-human replies from nested sub-threads now surface to the channel timeline as read-time pointer rows, inserted at the reply's own
createdAt— where the reader's eye actually is. The real message is never moved or copied; clicking the pointer navigates down to the still-nested original and highlights it.This is the read-side complement to the reply-routing tree: it makes mis-routed (buried) agent-to-human replies visible without altering routing or the underlying event graph.
Design
surfaceRepliesis a pure projection that identifies agent-to-human replies nested below the root and emits a synthetic pointer at each reply's owncreatedAt. The original message stays nested.mergeSurfacedRepliesconcatenates pointers with the main timeline and sorts by(createdAt, id)on the real message id, so a pointer lands chronologically where the human is reading.SurfacedReplyRowreuses the thread-summary pill visual (rounded button, avatar, muted "replied" label) without forcing synthetic summary semantics throughMessageThreadSummaryRow.goChannel(channelId, { messageId, threadRootId })— opens the thread at its root, scrolls to and highlights the specific nested reply.threadRootIdgates the root-event prefetch inChannelRouteScreenso the open never dead-clicks when the thread root sits outside the loaded window. This is the same path search hits use.Classification fail-safe
The human/agent classifier resolves unknown pubkeys to human (
pubkey == null || !agentPubkeys?.has(pubkey)), so an unrecognized author under-surfaces rather than mis-surfaces — honoring the pure-core's documented contract end to end.Quality
Both phases certified 9/9/9 on minimalism, elegance, and correctness across a two-pass review:
threadKey; empty-body and malformed-tag edge cases pinned;isRootLeveldrift contract locked with a broadcast-branch test.isHumanfail-safe restored end to end;threadRootIdprefetch confirmed load-bearing for the distant-root navigate-down case.just desktop-typecheckexit 0,just desktop-checkclean (2 pre-existing unownedgetMockProfilewarnings),just desktop-test734/734.