mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-27 19:35:13 +01:00
1aaa9eb0c23996322fec6d4bd1e8911a2d053fcd
1606
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1aaa9eb0c2 |
fix(ui): restore sticky plan confirmation CTAs
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
fe7edd291b |
chore(ui): lab responding state mirrors live interstitial self-talk tagging
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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>
|
||
|
|
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>
|
||
|
|
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> |
||
|
|
563969612f |
feat(ui): task-chat composer posts on Cmd/Ctrl+Enter instead of Shift+Enter
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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> |
||
|
|
af4b0280d2 |
fix(ui): task-chat drops the previous/next sibling cards below the composer
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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> |
||
|
|
384e5f6178 |
revert(ui): back out onboarding port (#10786) (#11067)
This reverts commit |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
11e56654f8 |
feat(ui): port onboarding flow from prototype; add cloud + local variants (#10786)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - First-run onboarding is the subsystem that turns a brand-new install
into a working company: it creates the company, its goal, a lead agent,
and that agent's first task
> - The existing `OnboardingWizard` carried all of that wiring
correctly, but its UI had drifted from the current design direction, and
a separate design prototype (`paperclip-onboard`) existed as a
standalone visual mock with no backend
> - Porting the prototype's *logic* would have thrown away working,
well-tested backend orchestration; leaving the two apart meant the
design never shipped
> - Separately, cloud and local (self-hosted) installs need meaningfully
different first runs — local has no sign-in and must let the user pick a
locally-installed CLI adapter — so a single linear wizard could not
serve both
> - This pull request rebuilds the presentational layer from the
prototype on top of the existing backend orchestration, and splits it
into two thin flow containers over a shared core
> - The benefit is that the shipped onboarding matches the intended
design, cloud and local can diverge without duplicating logic, and each
can later ship to a different app version while sharing one set of step
components
## Linked Issues or Issue Description
No existing issue — describing inline (feature request).
**What problem does this solve?**
Onboarding is the first thing a new user sees, and the shipped wizard
had drifted from the current design. In parallel, cloud and local
installs need different first-run paths: local has no hosted sign-in,
and its agent runs on a CLI adapter installed on the user's machine,
which the cloud path never has to ask about. There was no way to express
that difference without either forking the whole wizard or bolting
conditionals onto a single linear flow.
**Proposed solution**
Extract the onboarding step views and shell into a shared core, then
compose two thin flow containers (cloud and local) over it. Keep all
backend orchestration in the existing `useOnboardingFlow` hook so no
working logic is rewritten.
**Alternatives considered**
- *Single flow with a `variant` prop* — most DRY, but the two flows are
intended to ship on different app versions, and a shared file would have
to be split later anyway.
- *Two fully independent copies* — simplest per-flow, but every shared
refinement (spacing, motion, copy) would have to be made twice and would
drift.
## What Changed
- **Shared core** under `ui/src/components/onboarding/`:
`OnboardingScaffold` owns the full-screen shell and the single
`AnimatePresence` step crossfade, so both flows transition identically;
step views (Start / Company / Agent / Task), `FooterNav`, `AgentPreview`
and the motion constants are extracted for reuse.
- **`CloudOnboardingFlow`** — `start → company → agent → task`; mounted
in the real app via `OnboardingWizardVariant`. Behaviour matches the
retired wizard, including `previewMock` and the existing-company ("add
an agent") entry point.
- **`LocalOnboardingFlow`** — skips sign-in and adds an optional email
ask (with a privacy assurance), a local model/adapter step that hires
with `requireEnvProbe: true`, and a "star us on GitHub" interstitial
before completing. **Harness-only for now** — the real app still mounts
the cloud flow.
- **Deleted `OnboardingWizard.tsx`** (1,786 lines); updated its
Storybook stories and the `OnboardingWizardVariant` test to the new
components.
- **Orbiting 3D paperclip backdrop** behind the auth and welcome screens
(`three`), code-split so it only downloads on those screens; honours
`prefers-reduced-motion` and disposes its GL context on unmount.
- **`motion`** added for step transitions and the agent-capsule
choreography.
- Visual values routed through design tokens per `DESIGN.md`; `Stepper`
generalized to take a step total (backward compatible); `/design-guide`
page and the component index updated.
- **Standalone preview harness** (`ui/onboarding-preview.html`) with
`?flow=` and `?step=` for backend-free review, wired as a second Vite
rollup input.
- **Adapter env probe bound to the adapter it ran against.**
`hireLeadAgent` reused `adapterEnvResult` for any adapter, so when a
hire failed and the user picked a *different* local adapter and retried,
the previous adapter's verdict satisfied the `requireEnvProbe` guard
while the hire posted the new adapter's config — hiring it unprobed. The
cache is now keyed on the adapter type plus the exact config posted to
the test endpoint, the config is built once and shared by probe and
hire, a failed probe clears the cache, and `clearAdapterEnvResult()`
(called on adapter change) stops the step displaying a stale verdict.
Cloud is unaffected — it hires with `requireEnvProbe: false`. Reported
by Greptile.
- **E2E specs re-pointed at the new flow.** Four specs still drove the
deleted wizard (`onboarding`, `conference-room-typing-intro`,
`planning-mode-visual-verification`, `nux-phase4-screenshots`) and
failed with `element(s) not found` on `"Name your company"` /
`input[placeholder="Acme Corp"]`. Rather than repeat the new drive
sequence four times, `tests/e2e/onboarding-flow.ts` adds one driver per
step (`startCloudOnboarding`, `completeCompanyStep`,
`completeAgentStep`, `completeTaskStep`, `completeCloudOnboarding`) and
the specs import it, so the next flow change touches a single file. Two
now-dead `**/test-environment` route stubs went with it — the cloud flow
hires with `requireEnvProbe: false`, so that probe never fires.
## Verification
- `pnpm --filter @paperclipai/ui typecheck` — clean.
- `npx vitest run` over the onboarding suites
(`OnboardingWizardVariant`, `AgentCapsule`, `onboarding-launch`,
`onboarding-goal`, `onboarding-route`, `onboarding-adapter-config`) — 33
tests pass.
- `pnpm --filter @paperclipai/ui build` — succeeds; the three.js chunk
splits out separately (522 kB raw / 133 kB gzip) rather than entering
the main bundle.
- Both flows driven end-to-end in the preview harness in `previewMock`
(no database writes), plus the cloud flow rendered in the real
authenticated app at `/onboarding` to confirm the mount swap.
- The four re-pointed e2e specs pass locally against the new flow.
- New `ui/src/hooks/useOnboardingFlow.test.tsx` — 4 cases pinning the
adapter-probe cache (switch-adapter retry, cold path, explicit clear,
and the cloud flow's `requireEnvProbe: false`). Verified non-vacuous:
the switch-adapter case fails against the pre-fix code.
- Rebased onto current `master`; `pnpm-lock.yaml` is deliberately
**not** committed — `.github/workflows/pr.yml` regenerates it when a
manifest changes and shares it with downstream jobs as the `pr-lockfile`
artifact.
## Risks
- **Deleting `OnboardingWizard.tsx` is the one change that alters
existing app behaviour.** The cloud flow is intended to be
behaviour-equivalent, and its entry points are covered by the updated
`OnboardingWizardVariant` test, but this is the area to review most
closely.
- **Conflict risk with open PRs that touch the old wizard**: #9900,
#9501, #8982 and #6636 all modify
`ui/src/components/OnboardingWizard.tsx`, which this PR removes.
Whichever lands second will need its change re-applied to the new step
components. Flagging so ordering can be decided deliberately.
- **New dependencies**: `motion` and `three` (+ `@types/three`). `three`
is large, so it is lazily imported and code-split — it does not affect
the main bundle. Both are MIT.
- The **local flow is not reachable in the app** yet (harness/canary
only), so it carries no runtime risk today; wiring it up is a follow-up.
- The auth screens remain **presentational only** — they are not wired
to real auth, unchanged from before this PR.
- **Pre-existing, not introduced here:** `OnboardingWizardVariant`
renders outside `<Routes>` in `App.tsx`, so its `useParams()` never
resolves `:companyPrefix` and `/{prefix}/onboarding` opens the welcome
screen instead of jumping to the agent step. `master` has the identical
structure, so this PR faithfully ports existing behaviour; the working
"add an agent" entry is the launcher card behind the overlay, which is
what the screenshot spec drives. Worth a separate fix.
## Model Used
Claude Opus 5 (`claude-opus-5`) via Claude Code, with extended thinking
and tool use (repo search/edit, local test + build execution, and
browser-driven visual verification of the rendered flows). Portions of
the session also ran on `claude-opus-4-8` and `claude-fable-5`.
## 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
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [ ] I will address all Greptile and reviewer comments before
requesting merge
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
b67c512f82 |
feat(ui): live run label → run detail, running row → task detail (#11034)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The agent detail page has a Dashboard tab. The Dashboard tab shows a "Live Run" section for the agent's current heartbeat. > - The "Live Run" section has two clickable pieces: the section heading and the running row. Both pieces linked to the same run detail page. > - Two controls that go to the same place waste a navigation affordance and hide the task the agent runs. > - This pull request splits the two destinations. The heading goes to the run. The running row goes to the task. > - The benefit is that a user reaches the run internals from the label and the work item from the row, in one click each. ## Linked Issues or Issue Description No public GitHub issue exists for this change. The description follows the enhancement issue template. **What existing behavior does this improve?** The "Live Run" section on the agent detail page, Dashboard tab (the `LatestRunCard` component in `ui/src/pages/AgentDetail.tsx`). **Current behavior** The "Live Run" heading and the running row both link to the run detail page (`/agents/:agentId/runs/:runId`). The row shows the run code and an invocation-source chip. There is a separate "View details →" link that also goes to the run detail page. A user cannot reach the task the run works on from this section. **Proposed behavior** The heading becomes a link to the run detail page and appends the short run code, shown as `Live Run · <run code>`. The redundant "View details →" link is removed. The running row links to the task detail page when the run's context snapshot resolves to a known issue, and the row then shows the task status glyph, the task slug, and the task title. A pure timer heartbeat with no resolvable task keeps the previous behavior: run code plus source chip, linking to the run detail page. **Reason and benefit** The heading and the row now go to distinct, intuitive destinations. A user reaches the run internals from the label and the work item from the row, each in a single click. The fallback keeps heartbeats with no task readable and avoids a blank or broken row. ## What Changed - Made the "Live Run" / "Latest Run" heading a `Link` to the run detail page and appended the short run code (`run.id.slice(0, 8)`) in a mono span, formatted `Live Run · <run code>`. Kept the pulsing live dot. - Removed the redundant "View details →" link. - Changed the running row `Link` target to the task detail page (`/issues/:identifier`) when a task resolves, falling back to the run detail page otherwise. - Resolved the task from the run context snapshot (`contextSnapshot.issueId`, falling back to `contextSnapshot.taskId`) against a `Map` of the agent's assigned issues threaded in from `AgentOverview`. - When a task resolves, replaced the run code and source chip in the row with the task status glyph (`StatusGlyph`), the task slug, and the task title. Kept the running spinner, the run status badge, and the timestamp. ## Verification - `pnpm check:token-gates` → 3/3 gates clean. - `pnpm --filter ui typecheck` → passes. - `pnpm --filter ui exec vitest run src/pages/AgentDetail.progress.test.ts src/pages/AgentDetail.instructions.test.tsx` → 10/10 pass. - Manual (needs a reviewer with a browser): open an agent detail page → Dashboard tab. - For a live issue-execution run: the heading reads `Live Run · <run code>` and opens the run detail page; the row shows the task status icon, slug, and title and opens the task detail page. - For a pure timer heartbeat with no task: the row falls back to run code + source chip and opens the run detail page. No blank row. - Confirm both states in light and dark mode. ## Risks Low risk. The change is presentational and scoped to one component. The task lookup is defensive: it reads the context snapshot with a fallback key and only renders the task row when the issue is present in the already-loaded assigned-issue set, so an unknown or missing issue degrades to the previous run-detail behavior rather than breaking. ## Model Used - Provider: Anthropic (Claude). - Model: claude-opus-4-8 (Opus 4.8). - Context window: 200K. - Reasoning mode: extended thinking, tool use. ## 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 - [ ] All Paperclip CI gates are green - [ ] 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> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
5da382fd59 |
feat(skills): require explicit merge modes (#10978)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agents can select company skills and synchronize them to adapter runtimes > - The skill sync API replaced the complete selection without an explicit destructive choice > - Company package import also replaced conflicting skills by default > - These defaults could remove operator edits during setup and import reruns > - This pull request adds explicit assignment merge modes and safe package conflict handling > - The benefit is that reruns preserve operator work unless the caller explicitly requests replacement ## Linked Issues or Issue Description **What existing behavior does this improve?** This change improves agent skill synchronization and company package import. **Subsystem affected** This is a cross-cutting change across the shared contracts, server, CLI, and UI. **Current behavior** Agent skill synchronization replaces the full desired skill set from a modeless request. Package import replaces a conflicting skill when the caller does not select a conflict mode. **Proposed behavior** Agent skill synchronization requires `add`, `remove`, or `replace`. Package import skips conflicts by default. Each imported skill reports whether it was created, renamed, replaced, or skipped. **Reason and benefit** Setup and import reruns must preserve operator edits by default. Explicit destructive modes make data loss less likely and make each outcome inspectable. **Breaking changes** Callers of the agent skill sync API must now send `mode`. Callers that need the former behavior must send `replace`. Package import now uses `skip` when `onConflict` is absent. ## What Changed - Added required `add`, `remove`, and `replace` modes to the shared agent skill sync contract. - Added actionable `422` validation for missing or invalid modes. - Updated first-party UI and CLI callers with explicit modes. - Changed package skill conflict handling to use `skip` by default. - Kept plugin-owned and built-in stock skill imports on explicit `replace`. - Added created, renamed, replaced, and skipped results to company imports. - Added regression coverage for merge modes and package conflict outcomes. ## Verification - `pnpm check:token-gates` - `pnpm -r typecheck` - `pnpm build` - `pnpm test:run:serialized` (128 suites passed) - `pnpm --filter @paperclipai/skills-catalog test` (20 tests passed) - Focused agent skill route, company skill service, portability, CLI, and UI tests passed. - GitHub CI passed build, typecheck, canary, all general and serialized test shards, all browser shards, policy, security, and final verification on commit `2cfbb3e4c5`. - Greptile reviewed the latest commit at 5/5 with zero unresolved threads. ## Risks - This change intentionally rejects modeless agent skill sync requests. - The safe package default can leave an existing skill unchanged where the old default overwrote it. - All first-party callers now select a mode. Regression tests cover each outcome. > 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 `gpt-5.6-sol` through Codex. The runtime used agentic reasoning, tool use, code execution, and repository editing. The runtime did not expose the 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> |
||
|
|
03cfad7ceb |
feat(apps): connect Notion through MCP OAuth (#11009)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Apps give agents governed access to external tools. > - The Apps gallery lists Notion, but the server required manually configured OAuth credentials. > - Notion's hosted MCP server supports OAuth discovery and dynamic client registration. > - Notion also requires HTTPS or a loopback HTTP redirect URI. > - This pull request adds a direct Notion MCP OAuth path with PKCE and reusable dynamic clients. > - It also adds the current Apps UI states for connect and reauthorization. > - The benefit is a secure Notion connection with no manual client credential setup. ## Linked Issues or Issue Description **What existing behavior does this improve?** The Apps gallery, Apps connect route, OAuth token lifecycle, and managed MCP gateway. **Subsystem affected** `server/`, `packages/shared/`, `scripts/`, and `ui/`. **Current behavior** The Notion gallery cards are disabled. The server uses the classic Notion OAuth endpoints and requires operator-supplied client credentials. It does not register an OAuth client from provider metadata. Concurrent refreshes can also replay a rotating refresh token. **Proposed behavior** Enable the Notion Apps flow. Discover OAuth metadata from `https://mcp.notion.com/mcp`. Register and reuse a public RFC 7591 client with PKCE. Require HTTPS or loopback HTTP callbacks. Serialize refreshes, store each rotated refresh token before the new access token can be used, and show a reconnect state for `invalid_grant`. **Reason and benefit** Operators can connect the built-in Notion MCP app without creating or copying OAuth credentials. Paperclip keeps dynamic clients and rotating tokens in the company secret store. **Breaking changes** None. Explicit environment client credentials still take priority. Existing Slack and Linear OAuth endpoint hints remain unchanged. Other OAuth apps remain disabled unless they are allowlisted. **Additional context** PR #10910 is a related, broader Connections v3 wizard replacement. This PR is the focused current Apps flow. The MCP Tool Gateway and Connected Apps items in `ROADMAP.md` cover this planned capability. ## What Changed - Classify all 20 reviewed Notion MCP tools with provider-scoped read and write defaults. - Require approval for selected Notion mutations, including move, duplicate, and convert actions that generic verb matching missed. - Preserve company-scoped connection and catalog resolution for Notion profiles and policies. - Add RFC 7591 dynamic client registration with `token_endpoint_auth_method=none` and mandatory PKCE. - Store the dynamic client ID on the connection and store any returned client secret in the company secret store. - Reuse the registered client for later connects and keep explicit environment credentials as the first choice. - Discover protected-resource and authorization-server metadata from the Notion MCP endpoint. - Add `redirectConstraints: "https-or-loopback-http"` to the generated Notion app definition and shared contract. - Reject non-loopback plain HTTP callbacks before network access with a TLS setup error. - Serialize client registration and token refresh operations within the server process. - Store a rotated refresh token before publishing the refreshed access token. - Treat `invalid_grant` as terminal and move the connection to a clear reauthorization state. - Add focused coverage for registration reuse, callback constraints, refresh rotation, and terminal grants. - Enable the Notion Apps route and add connect, redirect, success, error, and reconnect UI states. - Keep non-allowlisted OAuth apps blocked and cover the UI policy with regression tests. ## Verification - The focused Notion policy integration test passed with embedded PostgreSQL. - The focused 20-tool classification test passed. - The server typecheck passed on the governance head. - `pnpm -r typecheck` passed on the rebased head. - `pnpm --filter @paperclipai/server typecheck` passed after the security follow-up. - `pnpm exec vitest run server/src/__tests__/tool-access-service.test.ts -t \u0027DCR|refresh tokens|invalid_grant|abandoned lease\u0027` passed 10 focused security tests. - `pnpm build` passed on the rebased head. - `pnpm exec vitest run server/src/__tests__/tool-access-service.test.ts -t 'OAuth|oauth'` passed 14 tests. - `pnpm exec vitest run packages/shared/src/app-definitions.test.ts` passed 5 tests. - The complete server group passed 3,686 tests with 4 skipped. - The complete UI group passed 3,656 tests. - The full local runner found one environment-only CLI failure because this agent runtime injects static AWS credentials into a test that expects `AWS_PROFILE` only. `env -u AWS_ACCESS_KEY_ID -u AWS_SECRET_ACCESS_KEY pnpm exec vitest run cli/src/__tests__/secrets.test.ts` passed all 8 tests. - The prior UI verification passed 55 focused tests, `pnpm check:token-gates`, the Storybook build, and review of six 1440 x 1000 screenshots. - OAuth request sequence: protected-resource metadata `GET https://mcp.notion.com/.well-known/oauth-protected-resource/mcp`; authorization metadata `GET https://mcp.notion.com/.well-known/oauth-authorization-server`; dynamic registration `POST https://mcp.notion.com/register`; authorization `GET https://mcp.notion.com/authorize`; token exchange and refresh `POST https://mcp.notion.com/token`; MCP traffic `POST https://mcp.notion.com/mcp`. - The live metadata and registration probe confirmed that Notion accepts HTTPS and loopback HTTP redirects. It rejects a plain HTTP private hostname. - A later QA task owns the full browser consent and managed gateway tool-list dry run against a configured HTTPS deployment. ## Risks - Notion can add tools. Unrecognized names use the generic classifier, and new or changed risky tools stay quarantined after connection activation. - A deployment that uses a private non-loopback hostname must configure HTTPS before it can connect Notion. - Dynamic registration creates a provider-side client. Paperclip reuses it because registration does not provide a standard delete operation. - Refresh coordination uses a database CAS lease across service instances. An unclean crash leaves an uncertain lease and requires reconnect instead of risking refresh-token replay. - The current Apps surface overlaps with PR #10910. Merge order can require a small conflict resolution if that PR lands first. > 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 on a GPT-5 runtime. The exact deployment ID and context window are not exposed. The runtime used reasoning, repository tools, code execution, and network tools. ## 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> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
ea83c5c822 |
feat(task-chat): bring back copy/👍/👎 actions on the agent bubble footer (#11025)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The task view shows a threaded conversation between the user and the agent, with agent replies rendered as bubbles that carry a "✓ Worked · N tools" summary line. > - The conference-room chat already offers per-message copy and thumbs-up / thumbs-down feedback, but the redesigned task thread dropped these controls from the agent bubble footer. > - Users lose a quick way to copy an agent reply or send feedback on it, and the redesign silently ignored the feedback-vote props it was already given. > - This pull request prepends a copy · thumbs-up · thumbs-down cluster to the bubble summary line and wires the existing feedback-vote props through. > - The benefit is a consistent feedback surface across both chat views, with no new API. ## Linked Issues or Issue Description No public GitHub issue exists for this change; the underlying issue is described inline below following the feature template (`.github/ISSUE_TEMPLATE/feature_request.yml`). #### Problem or motivation The redesigned task thread renders each agent reply with a "✓ Worked · N tools · <timestamp>" summary line, but it dropped the copy and thumbs-up / thumbs-down controls that the conference-room chat still shows. Users can no longer copy an agent reply or vote feedback from the task thread. The redesign component already received `feedbackVotes` and `onVote` props but ignored them. #### Proposed solution Prepend a copy · 👍 · 👎 cluster to the summary line, leading the always-visible timestamp, reusing the shared `IssueChatFeedbackButtons` so both chat views speak the same feedback language. Anchor the cluster to the turn's summary row (a sibling of the expandable tool-history fold) so it stays on the summary line whether the tool history is collapsed or expanded. #### Alternatives considered Placing the cluster inside the expandable fold — rejected because expanding the tool history then re-centered the actions to the middle of the tall fold. #### Roadmap alignment UI polish to the task thread; no core-roadmap overlap. ## What Changed - Add `TaskChatBubbleActions`: a copy · thumbs-up · thumbs-down cluster built on the shared `IssueChatFeedbackButtons`. - Render the cluster on the agent bubble's "✓ Worked · …" summary line, leading the timestamp; runless agent replies get the same cluster with the timestamp trailing. Human and system bubbles are unchanged. - Add a `leading` slot to `TaskChatTurn` so the actions sit on the summary row, a sibling of the tool-history fold, and stay anchored when the fold expands. - Wire the redesign to the `feedbackVotes` / `onVote` props it already received. - Add a demo binding in the `TaskChatLab` dev harness. ## Verification - `pnpm check:token-gates` — 3/3 gates CLEAN. - `pnpm typecheck` — clean across all packages. - `cd ui && pnpm vitest run src/components/task-chat/TaskChatBubble.test.tsx src/components/task-chat/TaskChatTurn.test.tsx` — 31/31 pass. - Manual: open a task thread, confirm the copy / 👍 / 👎 cluster shows on the agent bubble summary line before the timestamp, copy works, votes toggle, and the cluster stays on the summary line when the tool history is expanded. Visual change: snapshot baselines are intentionally not updated, per the `doc/design/DECISION-SHEET.md` entry "Per-change snapshot verification demoted to dormant (Jul 13 2026)". ## Risks Low risk. UI-only change scoped to the redesigned task-chat bubble footer. It reuses an existing shared feedback component and existing vote props; no API, schema, or server change. Human and system bubbles are untouched. ## Model Used Claude Opus 4.8 (Anthropic), model id `claude-opus-4-8`, extended thinking enabled, tool use. ## 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: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
d84c5eae7a |
feat(ui): hide task priority from the UI (keep data model) (#11024)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Tasks and issues carry a `priority` field that renders across many product surfaces: the detail header, the Triage properties panel, Kanban and thread cards, the New Task composer, list Sort/Group/Filter menus, search filters, and the dashboard chart. > - Product feedback found the priority level adds visual noise and decision cost without clear value in day-to-day task flow. > - We want to remove priority from the interface, but keep the data model, API, validation, and search DSL fully intact so the choice is reversible with no migration. > - This pull request hides every priority indicator and control behind one compile-time flag, `SHOW_TASK_PRIORITY_UI`, set to `false`. > - The benefit is a calmer, simpler UI now, with a single-boolean revive path and zero data loss. ## Linked Issues or Issue Description <!-- No public GitHub issue exists. Describing in-PR per the feature template. --> **Subsystem affected** The web UI (`ui/src`): issue detail, properties panel, Kanban/thread cards, New Task dialog, issues list Sort/Group/Filter menus, search filter bar/sheet, dashboard charts, and the design-guide showcase. **Problem or motivation** The task/issue priority level appears across many surfaces and adds visual clutter and decision overhead without pulling its weight in normal task flow. We want it gone from the interface without discarding the underlying data or breaking anything that depends on it. **Proposed solution** Add a single compile-time UI flag, `SHOW_TASK_PRIORITY_UI` (default `false`), and gate every priority indicator and control behind it. Leave the data model, API params, Zod validation (including the `"medium"` default), and the search filter DSL untouched. Reviving priority is a one-line flip of the flag back to `true`. **Alternatives considered** Deleting the priority code and schema outright. Rejected: it is irreversible, needs a data migration, and throws away a field the API and search still support. A gated flag keeps the change reversible and low risk. **Roadmap alignment** UI simplification. This is a presentation-only change; it does not alter core agent or data behavior. ## What Changed - Added `ui/src/lib/ui-flags.ts` exporting `SHOW_TASK_PRIORITY_UI: boolean = false` (typed `boolean` so gated branches are not flagged as dead code). - Gated the priority row in the Triage properties panel and the editable priority control in the issue detail header (plus its skeleton seed). - Gated the per-card priority icon in `KanbanBoard` and in `IssueThreadInteractionCard`. - Hid the priority chip and the mobile "more" menu priority section in the New Task dialog. The submit path still sends the `"medium"` default. - Removed the Priority options from the issues list Sort and Group-by menus; the comparator and grouping logic stay dormant. - Hid the Priority sections in the issue filters popover and in the search filter bar and sheet. The `priority:` search DSL and filter state stay functional at the data layer. - Suppressed active-filter priority pills for consistency. - Gated the "Tasks by Priority" dashboard chart and the design-guide priority showcase subsection. - Left activity-feed "changed priority" history text intact as a historical record. - Updated call-site tests to assert priority UI is absent while the flag is off, added focused hidden-surface tests, and added a test that proves creating a task still persists `priority: "medium"`. ## Verification - `pnpm check:token-gates` — all 3 gates clean. - `pnpm --filter @paperclipai/ui typecheck` — clean. - `pnpm --filter @paperclipai/ui exec vitest run` on the touched surfaces (IssueProperties, IssueFiltersPopover, IssuesList, NewIssueDialog, IssueDetail, PriorityIcon and its interaction test) — all green under `TZ=UTC`. - Manual: with the flag off, priority does not appear in the detail header, Triage panel, New Task composer, Sort/Group/Filter menus, or the dashboard chart. Creating a task still persists `priority: "medium"`, and the `priority:` search token still filters at the data layer. ## Risks Low risk. The change is presentation-only and additive: no data model, API, validation, or search-DSL changes. The priority code paths remain compiled and tested; flipping `SHOW_TASK_PRIORITY_UI` to `true` restores the full UI. Visual snapshot baselines are intentionally not updated per the `doc/design/DECISION-SHEET.md` entry "Per-change snapshot verification demoted to dormant (Jul 13 2026)". ## Model Used Claude Opus 4.8 (Anthropic), model id `claude-opus-4-8`, extended thinking enabled, with tool use / code execution in an agentic coding harness. ## 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 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 - [ ] 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> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
f258b34bbd |
fix(ui): unify cloud-managed sign-out (#10994)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Paperclip can run as a self-hosted app or as a Cloud-managed tenant. > - These modes need different sign-out sequences because Cloud owns three sessions. > - Several visible controls implemented sign-out separately and could choose different paths. > - This pull request adds one Cloud-aware sign-out action and moves every visible control to it. > - The benefit is one safe sign-out path in Cloud and unchanged local sign-out in self-hosted deployments. ## Linked Issues or Issue Description Refs #2073. That older PR adds a separate company-settings sign-out surface. This change centralizes the existing account, company, and instance-settings surfaces and preserves the self-hosted behavior described there. **What happened?** Visible sign-out controls used separate implementations. A Cloud-managed control could call the app-local sign-out endpoint and open the local auth page. That path did not enter the Cloud-owned logout sequence for the tenant, Cloud, and identity sessions. **Expected behavior** Every visible sign-out control must use one action. Cloud-managed instances must navigate the top-level window to the same-origin `/cloud/logout` route without a local sign-out call first. Authenticated self-hosted instances must keep the local sign-out API and cache invalidation behavior. **Steps to reproduce** 1. Open a Cloud-managed tenant. 2. Use the account menu, company menu, or instance-settings sign-out control. 3. Observe that independently implemented controls can enter different sign-out paths. **Paperclip version or commit** The problem reproduces at `656ecfa585b31938e2685ffab3db22e794474803`. **Deployment mode** Cloud-managed tenant built from source. The regression tests also cover authenticated self-hosted mode. ## What Changed - Added `useSignOut` as the shared Cloud-aware sign-out action. - Navigated Cloud-managed sessions to `/cloud/logout` exactly once without calling local auth first. - Preserved local API sign-out and cache invalidation for authenticated self-hosted sessions. - Migrated the account menu, company menu, and instance general settings to the shared action. - Added focused tests for mode selection, menu closure, pending state, failure state, and settings behavior. ## Verification - `pnpm exec vitest run ui/src/hooks/useSignOut.test.tsx ui/src/components/SidebarAccountMenu.test.tsx ui/src/components/SidebarCompanyMenu.test.tsx ui/src/pages/InstanceGeneralSettings.test.tsx` — 26 tests passed. - `pnpm --filter @paperclipai/ui typecheck` — passed. - `pnpm check:token-gates` — passed. - `git diff --check origin/master..HEAD` — passed. ## Risks - Low risk. The change centralizes existing behavior and adds no schema, API, telemetry, or style-token changes. - Cloud mode depends on the existing health decision. Tests pin both mode branches. - The change does not alter Fetch Metadata, CSRF, cookie, prefetch, or return-URL protections owned by the Cloud logout route. > 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, GPT-5. The runtime does not expose a more specific model ID or context-window size. The agent used high-reasoning mode, shell tools, and API tools. ## 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 - [ ] 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> |