Commit Graph
1613 Commits
Author SHA1 Message Date
scotttongandPaperclip 960b6e8a5d fix(ui): preserve composer drafts through StrictMode
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-08-07 17:14:32 -07:00
scotttong ddcaaebe57 fix(ui): flush pending composer drafts on teardown 2026-08-07 17:09:00 -07:00
scotttongandClaude Fable 5 e907db5926 feat(ui): collapse chat-shell system notices to humanized one-line rows
System comments in the experimental chat shell now render as quiet centered
one-liners (tone icon + plain-English title + relative time + chevron) that
expand on click to the full markdown body and structured metadata sections,
instead of large gray paragraphs of raw recovery text.

- Thread presentation/metadata/createdAtIso through TaskChatMessageItem and
  the comment adapter (system comments only).
- Fix authorKind ordering: authorType system now wins over a derivable
  run->agent linkage, so recovery notices no longer render as agent bubbles.
- New pure classifier system-notice-humanizer.ts covering the recovery
  families (claude_auth_required, configuration_incomplete, workspace
  validation, no-live-execution-path with recovery-owner extraction) plus a
  System update fallback with truncated first sentence.
- New TaskChatSystemNotice component; expanded state reuses the SystemNotice
  metadata-section rows via a newly extracted SystemNoticeMetadataSections.
- Collapse is presentation-only; respects presentation.detailsDefaultOpen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:57:53 -07:00
scotttongandClaude Opus 4.8 c0a31ccf7c feat(ui): persist composer draft in experimental TaskChatComposer
Chat-style task composers now keep unsent body text per task, matching the
default composer. Adds a shared ui/src/lib/composer-draft.ts (loadDraft /
saveDraft / clearDraft + DRAFT_DEBOUNCE_MS) and wires an optional draftKey
through TaskChatThread into TaskChatComposer: restore on mount/key change,
debounced save on change, explicit clear on successful send (so a
send-then-navigate within the debounce window can't resurrect the sent
message), and preserved draft on failed send.

Body text only — no attachments/mode/assignee, no server sync. The legacy
helper copies in CommentThread/IssueChatThread are intentionally left in place.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-07 16:57:53 -07:00
scotttongandClaude Opus 4.8 6f3723de7e fix(ui): white text on light-mode user chat bubbles
The human (blue --liveness-blue) chat bubble set text-white on its
container, but the message body renders through MarkdownBody, whose
Tailwind prose tokens (--tw-prose-body) win over the container color.
prose-invert only flips in dark mode, so light mode showed dark text
on blue while dark mode was already correct.

Add the existing paperclip-markdown-on-accent class (already used by
IssueChatThread for the same accent bubble) to the human-branch
MarkdownBody in TaskChatBubble and TaskChatDescriptionBubble. It maps
prose body/heading/etc. tokens to currentColor in both themes, so the
text follows the bubble's text-white. Agent/neutral bubbles unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-07 16:57:53 -07:00
scotttongandClaude Opus 4.8 38f10c9314 feat(ui): task ID in task-detail breadcrumb header
Render the task identifier (e.g. ) in gray monospace between the
status glyph and the title in the breadcrumb bar. Threads an optional
identifier through Breadcrumb + breadcrumbsEqual, adds a CrumbIdentifier
helper to BreadcrumbBar (font-mono text-muted-foreground design tokens),
and wires issue?.identifier onto the task crumb in IssueDetail.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-07 16:57:47 -07:00
scotttong f95a0ab0f5 fix(ui): show plan diagnostics in planning mode 2026-08-07 16:57:38 -07:00
scotttongandPaperclip 1aaa9eb0c2 fix(ui): restore sticky plan confirmation CTAs
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-08-07 16:57:30 -07:00
scotttongandClaude Fable 5 9445f4fbbe feat(ui): interstitial polish — hover only on gerund line, no leading icon, held line slides away after dwell
- Expand button moves inside TaskChatStatusPill wrapping only the status
  line (new onToggle prop); the interstitial row sits outside the hover/
  click target
- Drop the Responding icon prepending the interstitial text (lead spacer
  keeps column alignment)
- useHeldSelfTalk: a finished update now slides out of the 1lh viewport
  after --motion-interstitial-dwell (~4s) with no successor, instead of
  sitting until pushed out; same .tc-line-scroll transition, unmounts to
  the reserved empty slot

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:57:14 -07:00
scotttongandClaude Fable 5 96037fec6e feat(ui): interstitial held line — hold-until-superseded + ~4s min dwell
useHeldSelfTalk reworked: a finished update stays visible, static and
truncate-ellipsized, until the next update supersedes it or the turn ends
(never fades). Swaps are paced by the new --motion-interstitial-dwell token
(4000ms; deliberately NOT zeroed under reduced motion — it is pacing, not
movement); rapid bursts collapse latest-wins via a queue of one. The
.tc-line-scroll slide now plays ONLY at swap moments (keyed remount); while
streaming, the tail-line offset applies with the transition disabled inline,
killing the per-wrap glide. Lab: responding-burst state + segmented replay
(blank-line-separated updates with gaps) to exercise dwell/swap.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:57:06 -07:00
scotttongandClaude Fable 5 04397ac526 fix(ui): insert comment-less settled turns chronologically at run start — assembleThreadItems replaces bottom-append of unanchored Worked rows
A terminal run with no UI-linked reply comment fell into the unanchored
bucket and out.push(...unanchored) pinned its "Worked · Ns · N tools" row
under every new user bubble. Unanchored turns now interleave into the
backbone at meta.startedAt ?? createdAt (Infinity → tail when no meta yet);
anchored turns and live-turn-last ordering unchanged. 5 regression tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:57:06 -07:00
scotttongandClaude Fable 5 eef40c0347 feat(ui): round-9 polish — reserved interstitial slot + Worked summary attached to the reply timestamp
The interstitial row above the gerund status line is now permanently
reserved while a turn is live: text slides in/out of the always-mounted
1lh slot, so the layout above never jumps as messages appear/disappear.

On settle, a turn directly following its own agent's reply bubble
attaches to it (attachSettledTurns, after coalesceSettledTurns): the
"✓ Worked · …" summary renders appended to the bubble's timestamp line
— "2:34 PM · ✓ Worked · 38s · 2 tools" — still expandable to the tool
history. Bubble timestamps are always visible (hover-only reveal
removed). Turns without a reply bubble keep the standalone folded row.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:57:06 -07:00
scotttongandClaude Fable 5 4951e2da0e feat(ui): round-8 amendment — interstitial update gets its own row above the status line (never shares it); gerund rotation uninterrupted; row slides in/out of the 1lh viewport via the same line-scroll transition and unmounts after slide-out
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:55 -07:00
scotttongandClaude Fable 5 354bb822e0 feat(ui): coalesce back-to-back settled agent turns into one "Worked" row — coalesceSettledTurns final pass + buildMergedTurnSummary (summed per-run durations, re-derived counts); user/interaction/live-turn boundaries preserved
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:55 -07:00
scotttongandClaude Fable 5 39e30b51ab feat(ui): interstitial updates on the live line — F10 line-scroll revived (LiveSelfTalkLine, .tc-line-scroll, --motion-line-scroll), ephemeral messages, settled turns slim to tool rows only (thinking rows removed, TaskChatThinkingBlock deleted)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:55 -07:00
scotttongandClaude Fable 5 ad1ed3cca3 feat(ui): mobile document-flow layout for chat-style task thread — thread renders via scroll={false} in the page scroll with window auto-follow, sticky safe-area composer, 16px mobile editor text; desktop bounded chain untouched
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:55 -07:00
scotttongandClaude Fable 5 1178efda8c feat(ui): round-7 polish — pulse dot persists while narrating (no Responding icon swap), thinking block flattened to Brain-led tool-row header with railed body inset
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:55 -07:00
scotttongandClaude Fable 5 b3c082735c feat(ui): ambient self-talk — narration signals via status-word shimmer + Responding icon swap, interstitial text fully suppressed; revert F10 line-scroll and settled nesting, retire P5 interleave
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:55 -07:00
scotttongandClaude Fable 5 7eadf663ad feat(ui): self-talk as a live element of the parent row — streaming text takes the line with 1lh line-scroll, finished self-talk nests like tool rows, settled turns follow
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:50 -07:00
scotttongandClaude Fable 5 1daeef878b feat(ui): round-4 feedback — tool-row-sized muted self-talk, BookOpen/Terminal tool icons, md status glyph in comments
- Interstitial self-talk matches tool rows: text-xs wrapper + scoped
  .tc-interstitial override (prose-sm sets its own font-size on
  .paperclip-markdown, so the utility alone can't shrink it)
- tool-taxonomy: read family Book -> BookOpen, terminal SquareTerminal ->
  Terminal, edit SquarePen -> Terminal (per the letter of the board ask;
  the lucide link was pasted twice, flagged on the thread)
- Inline issue-reference status glyph in markdown bodies steps down
  lg (20px) -> md (16px)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:44 -07:00
scotttongandClaude Fable 5 fe7edd291b chore(ui): lab responding state mirrors live interstitial self-talk tagging
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:44 -07:00
scotttongandClaude Fable 5 2714832c3d feat(ui): task-chat de-emphasized self-talk — bubble-less muted narration with CSS typewriter entry
Mid-run agent messages are tagged interstitial by the transcript adapter and
render bubble-less/avatar-less in muted text; the run's posted reply keeps its
bubble. Settled history keeps the self-talk interleaved at its streamed
timestamp (deduped against posted comment bodies). New --motion-typewriter-*
tokens drive a CSS-only steps() clip reveal per streamed block, zeroed under
prefers-reduced-motion.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:44 -07:00
scotttongandClaude Fable 5 76770ace54 feat(ui): task-chat live turn collapses to one expandable parent row owning all activity
While a run streams, the status line (whimsy/taxonomy gerund + elapsed +
tokens) is now the live turn's single visible row: TaskChatTurnItem gains
liveStatus, TaskChatTurn renders it as an expandable header (chevron, same
grammar as tool rows / the settled Worked line), and expanding nests the
chronological tool/thinking history via the existing .tc-turn-fold motion
with live append while open. On settle the header morphs in place into the
'Worked · …' summary, preserving expand state. Only tool/thinking/usage rows
nest (isNestableLiveChild); mid-run agent text, markers and interaction cards
stay in the thread. Retires the  liveTurnFoldedIds window + tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:37 -07:00
scotttongandClaude Fable 5 61387b20e6 feat(ui): round-2 whimsy curation, informative-status icon pass, composer image chip X
- Claude-Code whimsy pool trimmed to Brewing/Tinkering/Distilling/Deliberating
- analog-office pool drops Cataloguing/Carbon-copying/Archiving, adds Trimming,
  Aligning, Combining, Whiteboarding, Diagramming, Sketching, Labeling, Sticky-noting
- Grep becomes its own informative family: Grepping + search-code icon (never whimsified)
- taxonomy icons: Search, Book, SquarePen, ChevronsLeftRightEllipsis, Network; MCP
  tools now use the official MCP logo (McpIcon) instead of Plug
- Thinking/Responding statuses get Brain / MessageSquareReply glyphs in the live pill
- MDXEditor image chip: settings button removed, delete uses lucide X

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:37 -07:00
scotttongandClaude Fable 5 58a5e1cccb feat(ui): task-chat non-image attachment chips on shadcn base/attachment
Adds ui/attachment.tsx (base-lyra registry port, @base-ui/react — the
current name of @base-ui-components/react) plus the shimmer /
scroll-fade-x / scrollbar-none utilities it expects. Composer chips get
kind icon, name, size, remove x, uploading/error states; file references
now ride as trailing [name](contentPath) lines appended at submit
(MDXEditor insertMarkdown collapses paragraph breaks, so no in-editor
insert), and an attached chip alone enables send. Posted bubbles fold
link-only reference lines back into the same chips (task-chat-attachments
extractor); prose-woven links keep their sentence. MarkdownEditor's
imperative insertMarkdown now focuses before inserting — it silently
no-oped on a never-focused editor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:37 -07:00
scotttongandClaude Fable 5 8bbef4177a feat(ui): task-chat composer swaps textarea for shared MarkdownEditor
Rich composer inside the v7 comp-bar chrome: @-mentions (wired through
TaskChatThread, previously dropped), data-driven /-command autocomplete via
EditorAutocompleteContext, rich lists, and inline pasted/dropped images at
the caret through the editor's image plugin -> issue attachments POST.
Non-image files keep the chip row; the round-13 object-URL thumbnail path
is superseded. Cmd/Ctrl+Enter posts natively; Shift+Tab mode-cycling is
captured on the wrapper ahead of Lexical. Motion-gate comment fix in
TaskChatStatusPill (doc said 100ms).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:14 -07:00
scotttongandClaude Fable 5 edb2812235 feat(ui): task-chat live turns fold older completed tool calls behind '> N earlier steps'
Live (unsettled) turns keep the most recent 3 activity rows visible; older
completed/failed tool rows and finished thinking blocks fold into an
expandable group. Each live row gets its own .tc-turn-fold wrapper so rows
entering the fold animate with the same --motion-turn-fold grid-rows motion
(zeroed under prefers-reduced-motion). In-flight tools, messages, and other
non-activity rows never fold and end the foldable prefix. Settled-turn
summary behavior unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:14 -07:00
scotttongandClaude Fable 5 182e5ab03d feat(ui): task-chat whimsical Running words — analog-office + Claude-Code pools, deterministic 10s rotation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:14 -07:00
scotttongandClaude Fable 5 a14d8992fa fix(ui): task-chat summary counts unique tool calls; composer shows image paste thumbnails
buildTurnSummary now dedupes tool_call entries by toolUseId (with the
parser's tool-${i} fallback) so the folded 'Worked · N tools' line matches
the expanded row count. Composer attachments carry an object-URL preview
created at attach time, rendered as a size-10 thumbnail in the chip and
revoked on clear/unmount.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:10 -07:00
scotttongandClaude Fable 5 81ce69a790 fix(ui): tool rows keep their real names — generic acpx tool_call updates no longer clobber identity
ACP emits tool_call (title "Terminal") → retitle-to-invocation → generic
tool_call_update lines that acpx fills with the literal "tool call". The
task-chat adapter replaced the whole tool item per update, so settled rows
degraded to "Tool call" + Wrench.

- transcript-adapter: merge updates instead of replacing; first real name is
  the call's identity, a retitle becomes the mono target, generic names never
  displace real ones (rows, status pill, tool_result upgrade path)
- tool-taxonomy: isGenericToolName() shared helper; classify multi-word ACP
  titles by first word ("Read File" → read family)
- summarizeToolInput: ignore the { text, status } keys the log parser
  synthesizes onto inputs
- acpx-engine emitRuntimeEvent: remember each call's first real title and
  stamp it onto generic update lines so stored logs keep names durably

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:56:10 -07:00
scotttongandClaude Fable 5 15eb30bb64 feat(ui): task-chat collapsed turn summary lands below the reply bubble
Settled run turns now anchor after the run's last comment instead of
before its first, so the folded "Worked · …" line appears where the
live "Running…" pill sat — the pill reads as being replaced by the
summary in place.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:55:54 -07:00
scotttongandClaude Fable 5 563969612f feat(ui): task-chat composer posts on Cmd/Ctrl+Enter instead of Shift+Enter
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:55:54 -07:00
scotttongandClaude Fable 5 ced262a0da feat(ui): task-chat tool taxonomy — pill verbs/icons, Shift+Enter to send, baseline-aligned elapsed
- new shared tool-taxonomy.ts (family/icon/verb per raw ACP tool name,
  mcp__ prefix collapse) used by the status pill, chat tool rows, and the
  classic transcript's previously hardcoded Wrench sites
- deriveRunStatusLabel: tail tool_call now yields the taxonomy verb
  ("Searching", "Running a command") with "Tool · target" detail and
  the raw toolName so the pill shows the family icon beside the pulse dot
- live status line: label/elapsed/detail/tokens share one baseline row
- TaskChatComposer: Shift+Enter posts, plain Enter inserts a newline
- tests: tool-taxonomy unit tests, deriveRunStatusLabel/toolDisplayName
  tests, composer Enter-behavior tests updated

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:55:54 -07:00
scotttongandClaude Fable 5 67e0713a2a feat(ui): task-chat live status elapsed sits beside the label and ticks in tenths
The running/working status line now shows elapsed time directly to the
right of the label (was pushed to the far right edge) and renders it
with one decimal (24.3s) so the readout visibly moves. The pill ticks
itself every 100ms from the run's start timestamp (new startedAtMs on
TaskChatStatusItem), replacing the 1s whole-thread re-render tick in
TaskChatThread.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:55:49 -07:00
scotttongandClaude Fable 5 0851608168 fix(ui): task-chat pane-tab underline hugs the properties header's bottom border
The Properties/Plan/Artifacts strip portaled into the pane header floated
its active underline ~6px above the header's border-b (list padding + the
bar's py-2). Move the bar's vertical padding onto the window-controls
cluster, stretch the portaled strip to the header's full height, and pin
the trigger underline to bottom-0 so it sits on the border line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:55:49 -07:00
scotttongandClaude Fable 5 af4b0280d2 fix(ui): task-chat drops the previous/next sibling cards below the composer
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:55:49 -07:00
scotttongandClaude Fable 5 61aae371bd feat(ui): task-chat per-request mode chips — drop the header mode badge, tag each agent reply with the mode its request ran under
The header's Ask/Plan badge read as a task-global setting, but mode is a
per-request choice: with the redesign flag ON the badge is gone from the
issue header, and each agent reply's avatar row now shows the work mode
that was in effect when its run started, reconstructed from the activity
feed's workMode change history (issue.updated details + _previous).
Flag OFF is unchanged: the legacy header badge stays and the new
workModeChanges prop is ignored by IssueChatThread.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:55:49 -07:00
scotttongandClaude Fable 5 a96cb271ea fix(ui): task-chat plan/confirmation card primary CTA on the right, secondary on the left
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:55:49 -07:00
scotttongandClaude Fable 5 f56a0d4b97 fix(ui): task-chat agent header uses the agent's assigned icon avatar
Revert the textless gradient capsule in TaskChatBubble to the legacy
Avatar + AgentIcon treatment: the adapter now maps the author agent's
assigned icon (agentMap icon) onto the message item, with an initials
fallback when no icon is set.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:55:49 -07:00
scotttongandClaude Fable 5 111f7bac6a fix(ui): task-chat phase 2e follow-ups — kill outer main scrollbar, restore pane-tab underline, conditional Plan/Artifacts tabs
Flag-gated (enableTaskChatRedesign), flag OFF unchanged:

- Extra scrollbar: with the flag ON the page content used a fixed
  calc(100dvh - 8rem) thread height inside the padded outer <main>
  (overflow-auto), so main itself also scrolled. The IssueDetail root now
  fills main exactly (h-full flex column) and the chain down to the thread
  is flexed with min-h-0, so the thread's internal viewport is the only
  scroll surface. TaskChatThread's dvh height token still applies on
  mobile, where main has no fixed height (flex-basis falls back to it).
- Pane-tab underline: the portal into the pane header bar kept React
  context but broke the DOM ancestry that Tailwind's
  group-data-[orientation]/tabs selectors need, so the active-tab
  underline never applied. A display:contents group/tabs wrapper inside
  the portal restores it.
- Conditional tabs: Plan/Artifacts triggers render only when the issue
  has a plan document/accepted decompositions or attachments (same query
  keys as the tab bodies — shared cache). With neither, the header bar
  shows a plain "Properties" title and the pane body is the plain
  properties stack. Tabs are controlled with a fallback to Properties if
  the selected tab's content disappears.

Verified on :3093 light+dark via Playwright: main scrollHeight ==
clientHeight (923/923) on //; underline opacity 1 on
active portaled tab; Properties|Plan on , all three on ,
title-only on ; portaled tab clicks switch content; flag-off run
scrolls the legacy page (4454px) with no redesign testids. ui tsc clean;
issue-properties/task-chat/IssueDetail/IssueChatThread tests pass (1
pre-existing TZ flake in IssueProperties monitor row, fails on base).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:55:49 -07:00
scotttongandClaude Fable 5 9a5f7e26e4 feat(ui): task-chat phase 2e — pane tabs in header bar, chat-only center, non-sticky header, plan CTA action bar
Flag-gated (enableTaskChatRedesign), flag OFF byte-identical:

- Properties | Plan | Artifacts tab strip portals from IssueProperties into
  the pane's header bar (new slot left of the maximize/close controls).
- Center Chat/Activity/Related-work tab strip hidden — the thread is the page;
  deep links that switched tabs stay on chat.
- Issue header (parent breadcrumb, title/badge block, plugin toolbars, load-
  earlier button) renders INSIDE the thread scroll viewport, so it scrolls
  away with the messages instead of staying pinned.
- --tc-thread-max-h reserve 21rem → 8rem: composer now sits ~26px above the
  viewport bottom.
- New IssuePlanConfirmationActionBar: while a plan confirmation is pending,
  its Confirm/Decline CTAs (with decline-reason flow) pin to a footer slot
  below the pane's scroll area on the Plan tab.

Verified: ui tsc clean; motion gate (25 files) + token gates clean; 218 tests
across task-chat/pane/IssueDetail/IssueChatThread (1 pre-existing TZ flake in
IssueProperties monitor row, fails on base); Playwright on :3093 light+dark —
tabs in pane header, header scrolls away/returns, thread bottom 923/950, plan
bar pinned at pane bottom in footer slot, zero page errors; flag-off run shows
legacy tabs/pane title, 0 redesign testids.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:55:49 -07:00
scotttongandClaude Fable 5 c84224ad08 feat(ui): task-chat phase 2d — drop agent-bubble caret, dedupe Properties header, scrollbar hugs properties pane
Flag-gated under enableTaskChatRedesign; flag-off byte-identical.

- TaskChatBubble: remove the tc-cursor caret from streaming message
  bubbles (thinking-block caret and the blink token stay).
- PropertiesPanel (redesign variant): drop the "Properties" header
  title that duplicated the tab label; header is now a right-aligned
  maximize/close control row. Legacy flag-off header untouched.
- IssueDetail: flag-ON shell wrapper goes full-width and each
  non-thread section re-centers itself at the 60rem cap, so the
  thread's scroll viewport (which already centers its column) reaches
  the properties pane; the chat tab extends under main's horizontal
  padding so the scrollbar sits flush against the pane border
  (gap 99-103px -> 0px light / 8px dark gutter, measured).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:55:31 -07:00
scotttongandClaude Fable 5 a5bdb851ea feat(ui): task-chat phase 2c — center/widen shell, inline interaction cards, plan doc in Plan tab
All flag-gated behind enableTaskChatRedesign; flag OFF stays byte-identical.

- --tc-shell-max-w (60rem) token; IssueDetail wrapper + skeleton become
  mx-auto w-full max-w-(--tc-shell-max-w) when the flag is on, and the
  thread body + pinned composer caps switch to the same token
- interaction kind added to the task-chat model; TaskChatThread merges
  interactions chronologically (same sort keys + same-run handoff shift
  as buildIssueChatMessages) and renders them via TaskChatInteractionCard,
  a v7-grammar wrapper over the shared IssueThreadInteractionCard
  (expired confirmations demote to a marker row)
- useIssuePlanDocument hook (404 → null) shared by the Plan tab, which
  now renders the plan document via MarkdownBody with a revision line
  above the decompositions, and by the thread's Plan updated/created
  marker

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:55:31 -07:00
scotttongandClaude Fable 5 e76584b95b feat(ui): task-chat phase 2b — v7 pixel parity + live streaming
Close the gaps between the flagged redesign and the accepted v7 prototype,
verified against the v7 artifact side-by-side and a REAL streaming agent run:

- Bubbles: human = --liveness-blue #2563eb (was bg-primary near-black) white
  text right; agent comment = borderless gray --bubble-agent bubble (new token,
  light+dark) with v7 header (capsule avatar · bold name · one capitalized
  mode chip). Bubble bodies now render markdown via MarkdownBody (code chips,
  links, mentions) instead of raw text.
- Composer: per-mode v7 placeholders ("Message {agent} — describe what you
  want done…"), neutral focus-within ring, borderless + attach iconbtn,
  full "Agent/Plan/Ask mode" label on the status-chip trigger, icon-only
  32px ArrowUp send with hover scale.
- Full-page chat shell: with enableTaskChatRedesign ON, IssueDetail gates the
  legacy title (compact single-line editor instead) / description / sub-tasks
  table / plan decompositions / Documents (pinned plan) / Output / attachments
  wall / workspace card / artifact chips — thread owns the center column,
  bounded by new --tc-thread-max-h so TaskMessageScroller owns scrolling with
  the composer pinned (scroll viewport = absolute inset-0; percentage heights
  don't resolve against flex-sized block parents). Flag OFF proven legacy:
  0 redesign testids, all legacy sections present.
- Tool rows (v7 flat grammar): [glyph · name · mono target · hover chevron ·
  status]; transcript adapter now emits real tool names (toolDisplayName —
  mcp__ collapse + capitalization, tool_result.toolName backfill), summarized
  primary params (summarizeToolInput probes file_path/command/pattern/…),
  clipped mono result detail, generic "Tool" fallback for legacy stored logs.
- Streaming states: shimmer (.shimmer-text-muted variant) on live Thinking…
  header + flat pulse-dot statusline (running/working no longer card chrome);
  thinking settles to "Thought for Ns" (ts-span derived) and arrives collapsed
  in settled history; turn summary label + mono metrics per v7 runsum.

Verified: motion gate (24 files, seams), token gates, workspace tsc, 177 ui
tests incl. task-chat/PropertiesPanel/IssueChatThread/IssueDetail; live
streaming captured on a real claude_local run on the worktree instance
(:3093 scratch task) — thinking/text deltas, live statusline with elapsed,
auto-follow, and fold-to-summary on completion; flag-off isolation screenshot.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:55:27 -07:00
scotttongandClaude Fable 5 474c4138ac feat(ui): task-chat redesign phase 2 — v5–v7 reconciliation + live-thread completeness
Reconcile the baseline with the accepted v5–v7 prototype decisions and finish
the live-thread work items (, plan §5), all behind enableTaskChatRedesign:

- Composer: v7 comp-bar (attach + far left, rectangle status-chip mode trigger
  via --tc-mode-* hues incl. ask-blue #3b82f6, assignee combobox left of send,
  all controls 32px, no shortcut hints), per-message mode with ⇧⇥ cycling,
  attachments via button/paste/drag-drop, reassign-on-send with implicit reopen.
- Scroll pill: stock shadcn MessageScrollerButton (32px round, arrow-only) with
  tokenized entry/exit motion and easing-aware re-follow (smooth glide cannot
  unpin the follow state; wheel/touch cancels).
- Turn fold: run activity grouped into TaskChatTurn — live turns stream
  expanded, settling folds to a one-line '✓ Worked · 38s · 3 tools · +34 −3'
  summary (--motion-turn-fold 380ms, instant for settled history, reduced-motion
  honored), settled turns interleave before their run's reply comment.
- Bubbles: agent header gains the textless brand-gradient capsule avatar +
  name · mode chip (deterministic agent→gradient hash).
- Properties pane: tab label Plans→Plan; drag-resizable (clamp ≥260px,
  dbl-click reset 322px, width remembered) + maximizable (320ms glide, spacer
  holds flex slot, 840px content cap) — flag-off DOM untouched.
- Motion: new tokens (turn-fold, scroll-pill enter/exit + easings, pane-glide)
  in index.css :root + reduced-motion zeroing + tweak-panel catalog entries.

Verified: workspace tsc clean; check-task-chat-motion + token gates clean;
53 task-chat/PropertiesPanel/gate tests, 29 experimental-settings tests and
21 server instance-settings tests pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:55:27 -07:00
scotttongandClaude Fable 5 d270ee47fd feat(ui): task-chat redesign baseline behind enableTaskChatRedesign
New ui/src/components/task-chat/ surface (model, TASK_CHAT_STATES inventory,
fixtures, adapter, Bubble/Marker/StatusPill/ToolCard/ThinkingBlock/UsageReadout/
Scroller/PlanView/ThreadView, TweakPanel), motion tokens in index.css :root,
useTaskChatRedesignEnabled hook + TaskChatRedesignGate, one-line ThreadComponent
seam in IssueDetail.tsx, flag-scoped tabs in IssueProperties.tsx, dev harness
/dev/task-chat-lab, gate script scripts/check-task-chat-motion.mjs.

Flag wired through the 3 lockstep shared files (types/validators/feature-catalog),
preference tier, default off.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:55:20 -07:00
TonioandPaperclip 384e5f6178 revert(ui): back out onboarding port (#10786) (#11067)
This reverts commit 11e56654f8.

#10786 ported the onboarding flow from a standalone prototype and
repointed `/onboarding` at the new `CloudOnboardingFlow`, deleting the
existing `OnboardingWizard.tsx` in the process. The ported flow is not
ready to be the shipping onboarding experience: it landed as a single
large port rather than an incremental migration, it pulled `motion`,
`three` and `@types/three` onto the UI dependency list for prototype
visuals, and it deleted the wizard that four in-flight pull requests
(#9900, #9501, #8982 and one more) were building on — those went
CONFLICTING the moment the file disappeared.

Rather than keep the half-migrated state on master while that is sorted
out, back the port out whole and re-land it incrementally. This restores
`OnboardingWizard.tsx` and the previous versions of the four e2e specs,
drops the `onboarding-preview.html` Vite entry, the DesignGuide
onboarding section and the `data-viz-misc` storybook story, and removes
the three prototype dependencies from `ui/package.json`.

This is an exact mechanical inverse of the squash commit — 41 files,
+2089/-3647, no hand edits. Reverting this commit restores all 41 files
byte for byte, so the port is recoverable in full when it is ready.

`pnpm-lock.yaml` is deliberately not touched. #10786 never updated it;
bot commit 4683f26c9 (#11036) added the `motion`/`three` entries
afterwards, so the lockfile is now ahead of the manifest. CI owns
lockfile updates (`.github/workflows/pr.yml`) and the policy job
regenerates it from the changed manifest.

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-07 14:55:34 -07:00
DottaandPaperclip 0a511ed1b0 feat(apps): support multiple provider connections (#11060)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The Apps subsystem connects company tools through governed provider
connections.
> - A company can need more than one account for the same provider.
> - The current database constraint and Apps flow assume one named
connection per company.
> - New quarantined actions also need an explicit review decision before
activation.
> - This pull request supports multiple provider connections and
complete action review decisions.
> - The benefit is safer access control and a clear multi-account Apps
workflow.

## Linked Issues or Issue Description

Refs: #11040

**Subsystem affected**

Cross-cutting. This change affects the Apps UI, the tool access API, the
shared request contract, and the database schema.

**Problem or motivation**

The connection name constraint prevents a company from keeping more than
one connection for a provider. The Apps UI also reuses an existing OAuth
connection when a user asks to connect another account. Action review
can enable selected entries without recording a decision for every
quarantined action.

**Proposed solution**

Remove the company and connection name uniqueness constraint. Let users
open, count, edit, and create multiple provider connections. Require the
finish request to cover every quarantined action exactly once before the
server activates reviewed entries.

**Alternatives considered**

The UI could generate unique internal names and keep the database
constraint. This would preserve a one-connection assumption in the data
model and would make display names part of identity. The server could
also infer review decisions from enabled actions. This would not
distinguish a reviewed disabled action from an action that the user did
not review.

**Roadmap alignment**

This change extends the completed MCP Tool Gateway and Apps milestone.
It also supports the Connected Apps roadmap item. It follows the
navigation and connection management work in #11040.

## What Changed

- Remove the company-scoped connection name uniqueness index with an
ordered and idempotent migration.
- Add a reviewed action list to the finish-app contract and reject
incomplete or duplicate review decisions.
- Activate reviewed entries and keep unreviewed quarantined entries
blocked.
- Enable a completed connection and preserve the company and connection
scope in all updates.
- Show provider connection counts and open the provider setup page from
Browse.
- Let users edit existing connections or connect another account without
reusing an active OAuth connection.
- Update focused server and UI coverage for multiple connections and
action review.

## Verification

- Ran the focused Apps UI suite. All 116 tests passed in 11 files.
- Ran the focused server and CLI suite. All 276 tests passed in 3 files.
- Ran `pnpm --filter @paperclipai/db check:migrations`. The migration
safety check passed.
- Ran `pnpm -r typecheck`. All projects passed.
- Ran `pnpm build`. All projects built successfully.
- Ran `pnpm test:run`. It passed 3,735 tests and skipped 4 tests. One
worktree-safety assertion failed because the execution workspace reloads
its worktree marker. The same test passed with an isolated non-worktree
marker.
- Ran `pnpm check:token-gates`. It reports 12 existing violations in the
unchanged `PaperclipOrbit3D.tsx` file from the target branch.
- Started the six affected Playwright specifications. Chromium could not
start because the host does not provide `libatk-1.0.so.0`. The GitHub
e2e jobs will verify these specifications.
- GitHub Actions passed every final-head CI gate, including all three
e2e shards and the aggregate `e2e` and `verify` jobs.
- Greptile reviewed final commit `9af9200426` at 5/5 with zero review
threads.

## Risks

- Removing the name uniqueness index permits duplicate display names.
Stable connection IDs and UIDs remain unique within a company.
- The finish-app endpoint accepts the new review field as optional for
backward compatibility. When clients send it, the server requires a
complete decision for all quarantined actions.
- Multiple OAuth connections depend on the explicit new-connection route
flag. Focused tests cover active and draft connection reuse.
- The migration is ordered after migration 0210. Its `DROP INDEX IF
EXISTS` statement is safe to repeat.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

OpenAI Codex with the `gpt-5.6-sol` model assisted this change. The
agent used repository tools, code execution, test execution, and agentic
reasoning. The Codex runtime manages the context window.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-07 16:28:04 -05:00
DottaandPaperclip b18b0fc39b feat: refine app connections and legacy worktree startup (#11040)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The Apps UI manages app discovery and app connections.
> - The managed worktree runtime starts agent work in repository
worktrees.
> - The Apps routes do not match the main discovery flow, and the
connections view lacks a delete action.
> - Legacy managed worktrees can also start before their pending seed
operation runs.
> - This pull request makes app discovery the main Apps route and makes
connection management explicit.
> - It also seeds legacy managed worktrees before runtime startup and
makes the CLI read the repository-local config.
> - The benefit is a clearer Apps workflow and a safer managed-worktree
startup path.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

This improves the Apps navigation, app connection management, managed
git-worktree startup, and CLI worktree selection.

**Subsystem affected**

Cross-cutting. The change affects `ui/`, `server/`, `cli/`, and
development documentation.

**Current behavior**

The `/apps` route opens the connections list while discovery uses a
nested route. The connections list has no delete action. Some legacy
managed worktrees can start runtime work before their pending seed
operation runs. The CLI can also read an ambient Paperclip config
instead of the repository-local config.

**Proposed behavior**

The `/apps` route opens Browse, and `/apps/connections` opens the
connection list. Users can delete a connection after confirmation.
Runtime startup seeds legacy managed worktrees when required. The CLI
resolves the current worktree from the repository-local
`.paperclip/config.json` file.

**Reason and benefit**

Users can discover apps from the canonical Apps route and can manage
existing connections from a dedicated route. Legacy worktrees receive
their required repository content before agent runtime starts. CLI
worktree selection stays scoped to the current repository.

**Breaking changes**

The `/apps` and `/apps/browse` route behavior changes. Old Browse links
redirect to `/apps`. The change does not modify an API schema or
database schema.

## What Changed

- Make Browse the canonical `/apps` page and move the connection list to
`/apps/connections`.
- Align Apps navigation, redirects, attention links, empty states, and
connection actions with the new routes.
- Add connection deletion with confirmation and clear failure feedback.
- Seed legacy managed git worktrees before runtime startup when their
seed status is pending.
- Read the CLI worktree selection from the repository-local Paperclip
config.
- Update focused UI, server, CLI, and development documentation
coverage.

## Verification

- Ran 202 focused UI, server, and CLI tests. All tests passed.
- Ran `pnpm -r typecheck`. All projects passed.
- Ran `pnpm build`. All projects built successfully.
- Ran `pnpm test:run`. The server and UI stages passed 7,168 tests. The
CLI stage found one environment-sensitive secrets test because this
workspace injects static AWS credentials. The isolated CLI file passed
all 8 tests after those injected variables were unset.
- Ran `pnpm check:token-gates`. It reports 12 existing color-token
violations in the unchanged `PaperclipOrbit3D.tsx` file from the target
branch. This pull request does not modify that file.
- Ran focused regression coverage for repository-root CLI config
resolution and connection deletion state. All tests and affected package
typechecks passed.
- Collected all 27 tests in the six changed Playwright specifications
successfully.
- GitHub Actions passed every latest-head CI gate, including all three
e2e shards and the aggregate `e2e` and `verify` jobs.
- Greptile reviewed the final commit at 5/5 with zero unresolved
threads.

## Risks

- Existing bookmarks for `/apps/browse` redirect to `/apps`.
- Connection deletion changes visible connection state and requires user
confirmation.
- The legacy seed path runs only for managed git worktrees with pending
seed state. Tests cover the startup condition.
- The rebase preserves the target branch's direct OAuth policy for the
Notion connection flow.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

OpenAI Codex with the GPT-5 model family assisted this change. The agent
used reasoning, repository tools, code execution, and test execution.
The runtime does not expose the exact model snapshot or context-window
size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-07 14:26:40 -05:00
Nicky LeachandPaperclip 01b51dc0e5 fix(runtime): stop Live badge and Working shimmer after task teardown (#10985)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The task list and the chat views show a Live badge and a Working
shimmer for an issue that has an active run.
> - A finished task kept the Live badge and the Working shimmer after
the run ended and the sandbox stopped.
> - The user interface reads run liveness from the
`heartbeat_runs.status` row. The run finalizer writes the terminal
status in a step that is separate from the agent `status=done` update.
When the sandbox or the run process stops between the two steps,
`heartbeat_runs.status` stays `running` forever.
> - A run row that stays `running` makes a finished task look
perpetually Live, and the user interface has no guard for an issue that
already reached a terminal status.
> - This pull request closes the invariant "environment lease released
implies the run is terminal" on the server, and adds a user interface
guard that suppresses live state for a terminal issue.
> - The benefit is that a finished task stops showing Live and Working,
both at the source (the run row) and at the surface (the badge and the
shimmer).

## Linked Issues or Issue Description

**Bug description**

- A completed task kept the Live badge and the Working shimmer after its
run ended and the sandbox was torn down.

**Steps to reproduce**

- Run an agent task to completion. Let the sandbox tear down while the
run finalizer is between the `status=done` update and the terminal
run-status write.
- Open the task list or the chat view for the finished task.

**Expected behavior**

- A finished task shows no Live badge and no Working shimmer.

**Actual behavior (before this change)**

- The finished task showed the Live badge and the Working shimmer
because its `heartbeat_runs.status` row stayed `running`.

This pull request supersedes the two separate pull requests #10954
(frontend) and #10955 (backend). It carries all of their changes for the
same race.

## What Changed

Server:

- Run teardown terminalizes a still-running or still-queued run before
it releases the environment lease. It writes `succeeded` when the issue
already reached `done`, `cancelled` when the issue is `cancelled`, and
`interrupted` otherwise. It never overwrites a status that another path
already made terminal.
- The recovery stale-lock sweep terminalizes an orphaned running run to
`interrupted` after it confirms the process and the sandbox are both
gone. It requires recorded process metadata, so it never terminalizes a
live run, a queued run, or a scheduled retry.
- Each terminal transition writes a run event.
- The stale-lock sweep continues and clears the lock when the audit
write fails. It logs the failure loudly.
- New server tests cover both invariants.

User interface:

- A shared guard suppresses the Live badge and the Working shimmer when
the issue status is terminal.
- The guard keeps non-terminal `queued` and `running` issues live.
- The guard prefers the newest issue live-status snapshot.
- New user interface tests cover the guard and the snapshot preference.

## Verification

Server:

- `pnpm --filter @paperclipai/plugin-sdk ensure-build-deps && tsc
--noEmit` in `server/` — 0 errors.
- `pnpm --filter server test
heartbeat-run-lease-release-terminalization.test.ts
recovery-stale-issue-lock-sweep.test.ts` — 12 tests pass.

User interface:

- `pnpm --filter @paperclipai/ui typecheck` — 0 errors.
- `pnpm exec vitest run ui/src/lib/liveIssueIds.test.ts
ui/src/lib/issue-chat-messages.test.ts` — 40 tests pass.

## Risks

- Low risk. The server change only forces a still-live run row to a
terminal status when the lease releases or when the recovery sweep
confirms the process is dead. It never overwrites an existing terminal
status, and it guards the recovery path with process metadata to avoid
terminalizing a live run.
- The user interface change is additive. The guard only suppresses live
state for a terminal issue and keeps queued and running issues live.
- No database migration. No change to any external endpoint.

## Model Used

- Claude Opus 4.8 (`claude-opus-4-8`), extended thinking, tool use, and
code execution.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` /
`Closes: #` / `Refs: #` OR (b) described the issue in-PR following the
relevant issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-07 07:23:56 -07:00