mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-11 05:31:46 +02:00
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - When an agent run ends without a recorded disposition, Paperclip raises a "missing disposition" handoff so the work does not stall silently > - The issue page shows that handoff as an amber alarm: "This task still needs a next step." > - The server tells the UI whether the issue has a live continuation, and an earlier change used that flag to hide the alarm while a correction run is active > - Hiding it removed the false alarm but replaced it with nothing, so a reader cannot tell "nothing is wrong" from "nothing is tracked" > - This pull request puts a quiet informational line where the alarm was, and links the live run > - The benefit is that the page stays honest in both states: it is calm while an agent works, and it is loud only when the issue is really stuck ## Linked Issues or Issue Description No public GitHub issue exists for this gap. Description follows `.github/ISSUE_TEMPLATE/enhancement.yml`: **What existing behavior does this improve?** The missing-disposition handoff notice on the issue page. It is the amber banner that reads "This task still needs a next step." **Subsystem affected** Web UI — `ui/src/components/IssueBlockedNotice.tsx`. **Current behavior** An issue with an outstanding missing-disposition handoff shows nothing at all in the blocked-notice slot while a correction run is live. `IssueBlockedNotice` calls `isSuccessfulRunHandoffRequired()`. That helper returns `false` when `successfulRunHandoff.hasLiveContinuation` is set. The component then renders no handoff content. Two tests asserted the empty render. **Proposed behavior** The page states, quietly, that a correction run is in progress. It also states that the alarm returns if the run stops without choosing a next step. The reader can open the live run from that line. The amber alarm does not change when no run is live. **Reason and benefit** Silence and "healthy" look the same. A user who saw the alarm earlier cannot tell whether the handoff was resolved, whether the alert was withdrawn, or whether an agent is working on it now. One muted line removes that ambiguity. It also keeps the loud state meaningful, because the alarm now appears only when the issue is really stuck. **Breaking changes** None. The change is presentational and adds no API or data-shape change. ## What Changed - Added `SuccessfulRunHandoffInFlightNotice` to `ui/src/components/IssueBlockedNotice.tsx`. It renders a muted row with a pulsing live dot and this copy: "A correction run is in progress — the agent is working. This alert returns if the run stops without choosing a next step." - The notice links the live run when the server sends `liveRunId` and the handoff has an `assigneeAgentId`. It shows the short run id as plain text when no agent id is available, and it shows no run reference when `liveRunId` is absent. - Liveness reads either the server `hasLiveContinuation` flag or the fresher client `liveIssueIds` set. This matches the rule that already suppressed the alarm. - The amber alarm is unchanged when no live continuation exists. The unpromoted scheduled-retry carve-out still shows the alarm, so the "Retry now" control stays reachable. - The calm line also renders above the blocker notice when an issue has blockers and a live run at the same time. - Storybook: added `InFlightNotice` and `LivenessComparison` stories to `ui/storybook/stories/successful-run-handoff.stories.tsx`, and removed a duplicated panel from the overview story. - Tests: the two cases that asserted an empty render now assert the calm line. New cases cover a missing `liveRunId`, a missing agent id, a handoff that is not required, and the two "alarm is unchanged" guards. ## Verification Run the component and helper suites from `ui/`: ``` cd ui && NODE_ENV=test npx vitest run \ src/components/IssueBlockedNotice.test.tsx \ src/components/IssueChatThread.test.tsx \ src/components/IssueChatThreadSystemNotice.test.tsx \ src/lib/successful-run-handoff.test.ts ``` Result: 4 files, 111 tests, all pass. Also run: - `cd ui && npx tsc -b --force` — clean. - `node scripts/check-token-gates.mjs` — all gates clean. Manual check in Storybook (`pnpm --dir ui storybook`), story `Paperclip/Successful Run Handoff → Liveness Comparison`: - The alarm panel keeps its 4 remediation bullets, its amber surface, and its run chips. - The calm panel shows one 39 px muted row, no bullets, and a working link to the live run. - Measured contrast of the calm text against its rendered surface: 4.58:1 in light mode and 6.52:1 in dark mode. Both pass WCAG AA for normal text. ## Risks Low risk. The change is limited to one presentational component and its stories. It adds a render path where the component previously returned `null`, so a surface that expected an empty render now shows one muted row. No server, API, or data-shape change. The amber alarm path and the scheduled-retry carve-out are covered by tests that assert the calm line does not appear. ## Model Used Claude Opus 5 (Anthropic), model id `claude-opus-5[1m]`, 1M context window, extended thinking, with 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 - [ ] 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: ClaudeCoder <claudecoder@paperclip.ing> Co-authored-by: Paperclip <noreply@paperclip.ing>
@paperclipai/ui
Published static assets for the Paperclip board UI.
What gets published
The npm package contains the production build under dist/. It does not ship the UI source tree or workspace-only dependencies.
Storybook
Storybook config, stories, and fixtures live under ui/storybook/.
pnpm --filter @paperclipai/ui storybook
pnpm --filter @paperclipai/ui build-storybook
Typical use
Install the package, then serve or copy the built files from node_modules/@paperclipai/ui/dist.