Extraction surfaces: sidebar coverage block, chat-bar ring, phase un-pill, panel death
The owner-locked extraction-UX redesign (dispatch 2026-09-24), UI chunk over Platform's data layer (eed4b4e — GET /api/chats/[id] carries `coverage`, the threshold is Graph ▸ extractionChunkTokens): 1. SIDEBAR BLOCK (components/extraction-coverage.tsx + sidebar's session menu): the coverage info block at the TOP of the context menu — uncovered tokens, uncovered messages, running state — then the Extract affordance (optimistic "extracting… / Running" until the server says running; 409 = benign, the trigger raced us), fetched ON MENU OPEN (the block mounts with the menu — on-demand, never eagerly), polled at 2s while a run is in flight. Visually separated from Rename/Delete by a hairline; those stay the two session-management actions. Failed read → nothing (never fake zeros). 2. RING METER (CoverageRing, chat top bar, before the PhaseChip): a 16px donut filling uncoveredTokens / extractionChunkTokens — "how close this session is to its next extraction run". Click → the exact numbers (covered/uncovered tokens, messages, the threshold, lastFoldedAt via timeAgo). Refresh chains: mount, the turn-settle bump (chat.tsx coverageTick), the settings signal (threshold/kill-switch re-read live), a 2s drain-poll while a run is in flight, and the ACTIVITY FEED — a run for this session appearing or settling in the dock's feed re-reads coverage (runs fire from other surfaces — the sidebar menu, the turn pipeline — and no turn-settle bump announces them; the runs-empty-transition the graph view rides). Vanishes entirely when the graph is off or before the first honest read. Running = the whole ring PULSES (implementer's visual call: motion is the working-state signal in this app's quiet register). 3. PHASECHIP UN-PILL: the phase label is a flat tag — no border, no rounding, no padding. The Plan chip is the only button-shaped thing in the top bar. Drag-surface (pointer-events-none) and aria semantics unchanged; the transcript PhaseDivider keeps its look. 4. PANEL DEATH: components/graph-coverage.tsx, its graph-view mount, and tests/render-graph-coverage.test.tsx die whole. Confirmed: after this, NOTHING client-side consumes GET /api/graph/coverage — the only remaining client use of the coverage endpoints is the Extract POST (kept, by design); the routes stay (Platform's call). Pure seams exported for tests: ringFill (clamp math), CoverageMenuBody, CoverageRingGlyph, CoverageRingDetail. 901/901. Live-verified on :3001: ring fill arcs match the API byte-for-byte (483/4096 = 4.45/37.70; 1991/4096 = 18.32/37.70); the sidebar block reads "2k uncovered / 4 messages unextracted"; a real Extract run went optimistic → dock run → menu settled "fully extracted" AND the ring drained to the empty arc (the feed chain); graph off → the ring vanishes; the flat phase label renders chrome-free beside the Plan pill.
This commit is contained in:
+20
-8
@@ -8,6 +8,7 @@ import { DeleteSessionDialog } from "@/components/delete-session-dialog";
|
||||
import type { ChatDeleteMode } from "@/src/core";
|
||||
import { PanelLeftCloseIcon, PanelLeftOpenIcon, PlusIcon, SearchIcon, SettingsIcon } from "lucide-react";
|
||||
import { ActivitySection } from "@/components/activity-dock";
|
||||
import { CoverageMenuBlock } from "@/components/extraction-coverage";
|
||||
import { LhMark } from "@/components/lh-mark";
|
||||
import { BrailleSpinner } from "@/components/braille-spinner";
|
||||
import { KeyboardShortcuts } from "@/components/keyboard-shortcuts";
|
||||
@@ -376,11 +377,13 @@ function SessionsSidebar() {
|
||||
const listRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
/* ── Wave 6 chunk A: context menu + inline rename + deletion ──
|
||||
Right-click a session row → MenuShell with exactly two actions
|
||||
(owner ruling): Rename (inline, below) and Delete (the two-option
|
||||
dialog). The anchor is the row that was right-clicked — assigned
|
||||
into a ref before the state flip so the shell measures it on its
|
||||
first (hidden) pass. */
|
||||
Right-click a session row → MenuShell: the extraction coverage
|
||||
block (owner-locked redesign, 2026-09-24 — numbers + the manual
|
||||
Extract affordance, separated by a hairline) above the two
|
||||
session-management actions (owner ruling): Rename (inline, below)
|
||||
and Delete (the two-option dialog). The anchor is the row that was
|
||||
right-clicked — assigned into a ref before the state flip so the
|
||||
shell measures it on its first (hidden) pass. */
|
||||
const [ctxChatId, setCtxChatId] = useState<string | null>(null);
|
||||
const ctxAnchorRef = useRef<HTMLElement | null>(null);
|
||||
const [renamingId, setRenamingId] = useState<string | null>(null);
|
||||
@@ -648,16 +651,25 @@ function SessionsSidebar() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* The context menu (wave 6): exactly two actions (owner
|
||||
ruling — no more). MenuShell owns placement/focus/arrow
|
||||
{/* The context menu (wave 6 + the extraction-UX redesign): the
|
||||
coverage block above, then exactly two management actions
|
||||
(owner ruling — no more). MenuShell owns placement/focus/arrow
|
||||
cycling; the dismissal effect above owns the contract. */}
|
||||
{ctxChatId !== null && (
|
||||
<MenuShell
|
||||
anchorRef={ctxAnchorRef}
|
||||
testid="session-context-menu"
|
||||
preferredSide="down"
|
||||
menuClass="flex w-44 flex-col gap-0.5 rounded-xl border bg-card p-2 text-xs shadow-xl"
|
||||
menuClass="flex w-52 flex-col gap-0.5 rounded-xl border bg-card p-2 text-xs shadow-xl"
|
||||
>
|
||||
{/* The extraction block (owner-locked redesign, 2026-09-24):
|
||||
what the extractor hasn't covered yet + the manual Extract
|
||||
affordance — visually separated from the management
|
||||
actions below by a hairline. Fetched on menu open (the
|
||||
block mounts WITH the menu); 409 = benign (already
|
||||
running). Renders nothing on a failed read. */}
|
||||
<CoverageMenuBlock chatId={ctxChatId} />
|
||||
<div className="my-0.5 border-t border-border/60" aria-hidden="true" />
|
||||
<button
|
||||
type="button"
|
||||
data-testid="ctx-rename"
|
||||
|
||||
Reference in New Issue
Block a user