Skip to content

FE-656: V1.2-E β€” Floating selection menu and active-card chat context#93

Merged
graphite-app[bot] merged 33 commits into
mainfrom
ka/fe-656-side-chat-v1-2e
May 7, 2026
Merged

FE-656: V1.2-E β€” Floating selection menu and active-card chat context#93
graphite-app[bot] merged 33 commits into
mainfrom
ka/fe-656-side-chat-v1-2e

Conversation

@kostandinang
Copy link
Copy Markdown
Contributor

@kostandinang kostandinang commented May 5, 2026

Summary

Implements V1.2-E from memory/PLAN.md Active 1.

  • Floating selection menu (πŸ’¬ Chat / πŸ“ Annotate) appears when text is highlighted inside a knowledge item's content or rationale in the graph view.
  • πŸ“ Annotate instantly creates a span-anchored annotation (DB-persisted with selection_start/end) and lands as an interleaved quote-card in the side-chat thread. Active cards feed the LLM as prompt context (User-pinned snippets: block) on subsequent turns, capped at the 8 most-recent.
  • πŸ’¬ Chat opens the side-chat with a one-shot spanHint. A dismissable chip (πŸ“Ž Β«phraseΒ») surfaces above the composer until the next message is sent or the chip is cleared. No DB write.
  • Form-created annotations also appear as active cards, so all session-born notes feed the chat consistently.
  • "βœ“ Annotation saved" confirmation moved to a non-shifting absolute overlay in the composer footer (between + and send), with 5-second auto-dismiss.

Test plan

  • Highlight text inside any item β€” floating menu appears with Chat / Annotate
  • Click Annotate β€” side-chat opens, quote card lands in thread, notes drawer count increments
  • Send a chat message about the snippet β€” assistant reply demonstrates awareness of the highlighted phrase
  • Dismiss the card with [Γ—] β€” card disappears from thread, drawer entry remains, next prompt omits it
  • Highlight a different phrase, click Chat β€” chip appears above composer; next message includes `spanHint`; chip clears after send
  • Stage 9 highlights β€” oldest card visibly dimmed with "not in context"; only 8 most-recent in payload
  • Switch the side-chat to a different item β€” active cards and chip reset cleanly

Spec / plan

  • Spec: `docs/superpowers/specs/2026-05-05-side-chat-highlight-to-note-design.md`
  • Plan: `docs/superpowers/plans/2026-05-05-side-chat-highlight-to-note.md`

πŸ€– Generated with Claude Code

@cursor
Copy link
Copy Markdown

cursor Bot commented May 5, 2026

PR Summary

Medium Risk
Touches both client and server side-chat/annotation flows and extends LLM prompt-building payloads, so regressions could affect annotation creation and chat request formatting. Risk is mitigated by extensive new unit/integration tests and mostly additive schema changes.

Overview
Adds a floating highlight SelectionMenu in the structured list view to start side-chat from a selected phrase (spanHint, one-shot) or create a span-anchored annotation (selectionStart/End) with a single click.

Introduces active annotation cards interleaved into the side-chat thread, with dismiss/promotion controls and an 8-item cap for what gets sent as activeAnnotations prompt context. Form-created annotations are now promoted into active cards by default, and the notes drawer gains a header and β€œadd to chat context” affordance.

Plumbs selectionStart/selectionEnd through createAnnotation end-to-end (client API β†’ server route β†’ DB), relaxes annotation body validation to allow empty bodies, and extends side-chat streaming and prompt construction to accept activeAnnotations and spanHint.

Reviewed by Cursor Bugbot for commit 66665bc. Bugbot is set up for automated code reviews on this repo. Configure here.

@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 5, 2026

FE-656 Side chat

Side chat β€” graph-launched chat with patch-list staging

TL;DR

Problem / Motivation

  • Given a structured view of the specs, user may want to ask questions or discuss the spec without losing their place

Acceptance criteria

  • From the structured spec view, users can open a popover side chat
  • Users can highlight and attach context from the structured spec view to the chat
  • Users can trigger updates to the spec from the chat

Concept

Popover-to-panel chat anchored to items in the structured spec view. Two entry modes (per-row chat-with button + text-selection floating menu); three user-facing intents (Explore Β· Edit Β· Annotate); proposed changes stage in a persistent top-bar patch list and apply in batch.

The side-chat is the unified user-driven mutation surface. It subsumes three previously-separate horizon items: D128 graph-launched refinement, trigger-popover composer, revisit / edit mode + cascade preview.

Phasing

  • V1 β€” panel + Explore + Annotate. Annotation-only patches. β†’ FE-672
  • V2 β€” Edit (router) + Drill-down + Propose-edge. Soft-impact edits apply directly; hard defers to V3. β†’ FE-673
  • V3 β€” Hard edit absorbs REVISIT_MODULE β€” cascade preview inline + batch secondary-thread. β†’ FE-674
  • V4 β€” patch / event-stream model, item versioning, architect-loop integration, multi-thread (depends on upstream A71/A72).

Acceptance-criteria mapping

  • From the structured spec view, users can open a popover side chat β†’ V1 (FE-672)
  • Users can highlight and attach context from the structured spec view β†’ V1 (FE-672)
  • Users can trigger updates to the spec from the chat β†’ V2 + V3 (FE-673, FE-674)

Design doc & PR

Updates

FE-656: Side-chat

Review in Linear

Copy link
Copy Markdown
Contributor Author

kostandinang commented May 5, 2026

@kostandinang kostandinang changed the title FE-656: V1.2-E spec β€” highlight-to-note design FE-656: V1.2-E β€” Floating selection menu and active-card chat context May 5, 2026
@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented May 5, 2026

πŸ€– Augment PR Summary

Summary: Implements V1.2-E β€œhighlight-to-note” for side-chat by letting users select text in the structured list view and either chat about it (one-shot hint) or instantly save it as an annotation that becomes prompt context.

Changes:

  • Adds a floating SelectionMenu (Chat / Annotate) and a useTextSelection hook to capture selection snapshot + offsets + item anchor.
  • Introduces interleaved side-chat threadItems with a new <ActiveCard> UI for β€œactive” annotations, including dismiss and an 8-item in-context cap.
  • Extends patch applying to return optional applied metadata and plumbs it through reducer events (appliedMeta) so the side-chat can auto-activate newly-created annotations.
  • Plumbs annotation span ranges end-to-end via selectionStart/selectionEnd in client API + server route validation and persistence.
  • Extends the side-chat stream payload with activeAnnotations and a one-shot spanHint, and updates prompt building to incorporate both.
  • Updates the notes drawer UX (sticky header, promote-to-context β€œ+”) and moves the β€œAnnotation saved” toast to an absolute overlay with timed auto-dismiss.

Technical Notes: Side-chat state is now session-scoped (active cards + pending span hint reset on item switch/dismiss), and prompt context is capped to avoid request/prompt bloat.

πŸ€– Was this summary useful? React with πŸ‘ or πŸ‘Ž

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread src/client/components/side-chat-host.tsx
Comment thread src/client/routes/specification/$id/-structured-list-view.tsx
Comment thread docs/superpowers/plans/2026-05-05-side-chat-highlight-to-note.md Outdated
@kostandinang kostandinang marked this pull request as draft May 5, 2026 18:40
@kostandinang kostandinang force-pushed the ka/fe-656-side-chat-v1-2e branch from 54727e5 to 9fbf42a Compare May 5, 2026 18:43
@kostandinang kostandinang self-assigned this May 6, 2026
@kostandinang kostandinang marked this pull request as ready for review May 6, 2026 12:28
@kostandinang kostandinang requested a review from lunelson May 6, 2026 12:28
Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 3 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread src/client/components/side-chat-host.tsx
Comment thread src/client/components/side-chat-host.tsx Outdated
Comment thread src/client/lib/use-text-selection.ts Outdated
Comment thread src/client/components/side-chat-popover.tsx Outdated
Comment thread src/client/components/side-chat-host.tsx
Comment thread src/client/components/side-chat-popover.tsx Outdated
Comment thread src/client/components/side-chat-host.tsx Outdated
lunelson
lunelson previously approved these changes May 6, 2026
Copy link
Copy Markdown
Contributor Author

kostandinang commented May 6, 2026

Merge activity

@kostandinang kostandinang force-pushed the ka/fe-656-side-chat-v1-2g branch from 275f434 to 673feef Compare May 6, 2026 16:27
@kostandinang kostandinang force-pushed the ka/fe-656-side-chat-v1-2e branch from 8dbbb48 to 292b62a Compare May 6, 2026 16:27
@github-actions github-actions Bot dismissed lunelson’s stale review May 6, 2026 16:28

Latest approval commit 8dbbb48 is not an ancestor of 292b62a, indicating rewritten history after approval

@kostandinang kostandinang requested a review from lunelson May 6, 2026 16:29
lunelson
lunelson previously approved these changes May 6, 2026
kostandinang and others added 18 commits May 7, 2026 09:21
…a, constant

- threadItems: messages and cards now both timestamp via Date.now() (parallel
  messageTimestamps array on ActiveSideChat), so the chronological sort actually
  interleaves; previously messages used `index` and cards used Date.now() so cards
  always landed after messages regardless of when they were created. Pending
  assistant timestamps are preserved across replacePendingText / finalizePending.
- dismiss now clears activeCards and pendingSpanHint; openFor clears them when the
  target item differs from the current pinned (kind, id) pair. Prevents single-pin
  state from leaking across close/reopen and item switches.
- annotate applier returns the server-normalized summary/body (created.summary,
  created.body) under `applied`, so the rendered card matches what was persisted
  rather than the patch the client sent.
- Extracted MAX_ACTIVE_ANNOTATIONS = 8 used in both the request-payload slice and
  the threadItems inContext flag, so the cap has a single source of truth.

Tests added: dismiss-clears-cards (close then reopen same item) and
item-switch-clears-cards (open A β†’ save β†’ open B). annotation-api `applied`
test rewritten to assert the server values, not the patch values.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…the composer

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… canUndo

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces center-pill positioning (left-1/2 + translateX) with anchored
left-9 right-9 so the toast bar fills the available area between the +
and send buttons. Content stays centered inside via justify-between
(check + label on the left, Undo on the right).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…em heights

- Put h-72 directly on the <ul> for guaranteed scroll (the flex-1 + min-h-0
  pattern wasn't propagating height through the absolute-positioned wrapper).
- Drop px-2 from the <ul> so each item spans the full popover width and the
  hover background paints edge-to-edge.
- Move horizontal padding inside each item (px-3 on summary/div); body section
  uses pl-7 to stay aligned with summary text after the chevron.
- Tighten vertical rhythm: py-2.5 β†’ py-2 between items.
- Bump body text size to text-sm with leading-relaxed and pt-1 spacing for
  comfortable reading when an item is expanded.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@lunelson lunelson force-pushed the ka/fe-656-side-chat-v1-2e branch from a44c6bb to 33b2082 Compare May 7, 2026 09:21
@github-actions github-actions Bot dismissed lunelson’s stale review May 7, 2026 09:21

Latest approval commit a44c6bb is not an ancestor of 33b2082, indicating rewritten history after approval

@kostandinang kostandinang requested a review from lunelson May 7, 2026 09:25
Comment thread src/client/components/side-chat-host.tsx Outdated
Comment thread src/client/components/side-chat-host.tsx
lunelson
lunelson previously approved these changes May 7, 2026
Join applied annotation metadata back to its source patch so cards are only promoted for the currently pinned item, and keep openFor state updaters pure.

Co-authored-by: Cursor <cursoragent@cursor.com>
@graphite-app graphite-app Bot merged commit 0efe73d into main May 7, 2026
6 checks passed
@graphite-app graphite-app Bot deleted the ka/fe-656-side-chat-v1-2e branch May 7, 2026 09:51
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 66665bc. Configure here.

setActiveSideChat((active) =>
active && active.itemKind === item.kind && active.itemId === item.id ? nextActiveSideChat : active,
);
return;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same-item openFor discards pending state from streaming

Medium Severity

When openFor is called for the already-open item, nextActiveSideChat is built from activeRef.current (which lags behind queued state updates). The functional setActiveSideChat callback receives the up-to-date active state but ignores it, returning nextActiveSideChat instead. During streaming, queued replacePendingText updates are silently discarded. The next streaming delta self-corrects (because buffered accumulates all text), but intermediate message state and messageTimestamps can briefly regress.

Fix in CursorΒ Fix in Web

Reviewed by Cursor Bugbot for commit 66665bc. Configure here.

}
let cancelled = false;
const batchId = patchListState.lastBatchId;
setAnnotations(null);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Annotations cleared during refetch causes drawer flash

Low Severity

setAnnotations(null) is called eagerly at the start of every annotation refetch (triggered by lastBatchId changes). This immediately clears existingAnnotations to an empty array, causing the notes drawer count to flash to zero and back on every successful annotation save. If the drawer is open, the annotation list visibly disappears and reappears after the fetch resolves.

Fix in CursorΒ Fix in Web

Reviewed by Cursor Bugbot for commit 66665bc. Configure here.

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