UX phase 3 — make the agent loop visible#14
Merged
Merged
Conversation
Click a suggestion mark (or ghost insert widget) to open an anchored popover
at the text — author chip, kind, −old/+new preview, Accept/Reject, and Withdraw
when it's yours — reusing the shared accept/reject/delete helpers (no model
changes). Positioned via view.coordsAtPos with a scroll-into-view + measure so
it works in long documents; follows the anchor on scroll/resize and closes on
outside click / Escape / scrolling out of view.
The right rail becomes explicit bulk review ("Review N suggestions") with
Accept all / Reject all behind a danger confirm. Accept all re-resolves ranges
between applications (anchor order, skipping orphans) and reports the outcome
in a toast. The concurrent double-accept limitation from the PR #9 review is
documented in a code comment.
Ghost insert widgets now carry their suggestion id so clicks resolve the same
way delete/replace marks do. e2e: popover accept flow + bulk Accept-all.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gnrgu8jdLx12jkWY1B8vb3
Per-project in-memory ring buffer (ActivityLog, ~500 events) exposed at GET /api/projects/:p/activity — deliberately ephemeral (resets on restart, never persisted; unknown project 404s). Events are emitted from the signals already flowing through a room, wired in Room.open after hydration so they die with the room and pre-existing suggestions/comments don't replay: - awareness join/leave and composing↔idle transitions (writing/finished), - suggestions map observer (suggested / accepted / rejected via resolvedBy), - comments map observer (commented / replied; resolved attributed to the socket that applied it → its awareness identity), - snapshot save/restore, driven from the api.ts handlers via Room.recordVersion. Events with no resolvable actor are dropped rather than guessed. Client: an Activity block on the Agents page (polled with peers, doc-linked, newest first) and a compact last-3 strip on Home project cards, sharing an activityLabel() phrasing helper. e2e: Agents-page feed renders alice's activity. API test: join/writing/suggested/commented/resolved in order, saved-version, left, 404. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gnrgu8jdLx12jkWY1B8vb3
A keyboard-first overlay (src/client/palette.ts) opened with ⌘K/Ctrl+K and via a new sidebar Search item. Sources are ranked: documents across all projects (title + path, fetched once per open and cached), full-text hits in the current project for queries ≥3 chars (debounced, "In text" section), and actions (New document, New project, Connect an agent, Settings, Toggle mode, Copy MCP config). Arrow keys move the selection, Enter runs it, Escape/backdrop close. The per-project sidebar search input is removed — the palette absorbs it — and its now-dead search styles/handlers are deleted. e2e replaces the old sidebar search test with a keyboard-driven palette test (⌘K, arrow nav, doc jump, in-text section, action). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gnrgu8jdLx12jkWY1B8vb3
refreshInboxBadge now polls the cross-project inbox on a 60s interval and on focus, keeps the sidebar Inbox badge and the document title (`(2) mdio`) in sync, and toasts a newly-arrived unhandled mention while the app is open (the first poll only primes the seen-set so existing mentions don't nag). The toast is clickable and deep-links to the thread; toast() grew an onClick option and clickable toasts opt back into pointer events over the click-through tray. Explicit non-goals (web push, sounds, per-thread read-state) are noted in code. e2e: tab title/badge reflect the pending count and a fresh @mention pops a deep-linking toast. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gnrgu8jdLx12jkWY1B8vb3
…ts, docs
- History and Versions merge into one two-tab drawer behind a single
"History & versions" ⋯-menu entry; history.ts/versions.ts now fill their tab
pane while the drawer owns visibility, tabs, title, and close.
- A composing agent's presence avatar pulses subtly (reduced-motion aware).
- Empty inbox teaches the core loop ("Nothing needs you — mention @agent…").
- A `?` keyboard-shortcuts dialog (ignored while typing), listing the palette,
mode toggle, and comment affordances.
- Docs: CHANGELOG Unreleased gains the phase-3 summary; CLAUDE.md documents the
ephemeral activity endpoint and its observers.
e2e updated to drive the merged drawer (History tab + Versions tab).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gnrgu8jdLx12jkWY1B8vb3
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.
Phase 3 of the UX rework (
docs/plans/ux-rework/phase-3-agent-loop.md). Makes the human⇄agent loop tangible: act on suggestions where the text is, see what agents did, move anywhere with ⌘K, and get pulled back when you're needed. Builds on phases 1–2 (PRs #11–#13).What's in it
3.1 Inline suggestion popovers. Clicking a suggestion mark (or ghost insert widget) opens an anchored popover at the text — author chip, kind, −old/+new preview, Accept / Reject / Withdraw — reusing the shared accept/reject/delete helpers (no model changes). Positioned via
view.coordsAtPoswith a scroll-into-view + measure so it works in long documents; follows the anchor on scroll/resize, closes on outside click / Escape / scrolling away. The right rail becomes explicit bulk review ("Review N suggestions") with Accept all / Reject all behind a danger confirm; Accept all re-resolves ranges between applications (anchor order, skips orphans) and reports the outcome in a toast. The concurrent double-accept trade-off from the PR #9 review is documented in code.3.2 Agent activity feed. A per-project, ephemeral in-memory ring buffer (
src/server/activity.ts, ~500 events, resets on restart, never persisted) atGET /api/projects/:p/activity. Events come from signals already flowing through a room — join/leave, composing↔idle, suggestions, comments, and version saves/restores — via observers wired inRoom.openthat die with the room; events with no resolvable actor are dropped. Rendered as an Activity block on the Agents page and a compact last-3 strip on Home project cards.3.3 ⌘K command palette (
src/client/palette.ts). Keyboard-first overlay (⌘K/Ctrl+K or the sidebar Search item): jump to any document across projects, full-text-search the current project (≥3 chars, "In text"), and run actions (New document/project, Connect an agent, Settings, Toggle mode, Copy MCP config). Replaces the per-project sidebar search input.3.4 Attention. The inbox polls on a 60s interval and on focus, keeping the sidebar badge and the tab title (
(2) mdio) in sync; a newly-arrived unhandled @mention pops a clickable toast that deep-links to the thread. (Non-goals noted in code: web push, sounds, per-thread read state.)3.5 Polish. History and Versions merged into one two-tab drawer (single
History & versions⋯-menu entry); composing agent avatar pulses; empty-inbox teaching copy;?keyboard-shortcuts dialog.Tests
All of
bun testis green (171 tests across server, MCP, model, CLI, and the Playwright e2e suite). New coverage: popover accept + bulk Accept-all e2e, activity API test (join/writing/suggested/commented/resolved in order, saved-version, left, 404), palette e2e including keyboard nav, attention toast/title e2e, and the merged drawer. Visual flows were screenshot-verified with Playwright.Docs
CHANGELOG.md(Unreleased) andCLAUDE.mdupdated — the activity endpoint is documented as ephemeral, and thesrc/server/api.tsheader route table lists it.🤖 Generated with Claude Code
https://claude.ai/code/session_01Gnrgu8jdLx12jkWY1B8vb3