Files
PaperClipAI/ui
DottaandClaude Opus 5.5 28063474d2 fix(ui): show why a queued message edit was not saved (#20583)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - In task chat, a person can edit a queued message before the agent
receives it
> - The server rejects an edit with 409 when the queue changed in
another session
> - The composer kept the text, but it showed no reason, so the edit
looked stuck
> - This pull request shows the reason under the editor
> - The benefit is that the person knows the edit was not saved and what
to do next

## Linked Issues or Issue Description

**What happened**
Two sessions edited the same queued message. The older save got `409
queued_comment_revision_conflict`. The composer still said "Editing
queued message" and showed no error.

**Expected behavior**
The composer tells the person that the queue changed in another session,
keeps the text, and lets them save again.

**Steps to reproduce**
1. Queue a message on a task with a running agent.
2. Open the task in two tabs and start editing the queued message in
both.
3. Save in the second tab, then save in the first tab.
4. See no error in the first tab.

## What Changed

- `TaskChatComposer` shows a save failure for a queued message edit in
its existing `role="alert"` line
(`data-testid="task-chat-queued-edit-error"`). The error clears when the
edit ends or a new save starts.
- `api/errors.ts` has copy for `queued_comment_revision_conflict`,
`queued_comment_stale_queue`, `queued_comment_stale_target` and
`queued_comment_not_pending`.
- The existing queue refresh after a 409 updates the revision, so a
second save works.

## Verification

- Red then green: `cd ui && npx vitest run
src/components/task-chat/TaskChatComposer.test.tsx` (new test `shows why
a concurrent queue change rejected the save and keeps the edit` fails on
`master`; all 146 pass with the change).
- `npx vitest run src/components/TaskChatThread.test.tsx
src/api/errors.test.ts` (479 passed).
- `pnpm check:token-gates`: all gates clean.
- `tsc --noEmit -p ui`: no errors outside unrelated Storybook files.

## Risks

- Low risk. UI copy only, no new API. A stale edit now shows a short
error line in addition to the "Queued message changed" label.

## Model Used

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`), tool use and code
execution in Claude Code.

## 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

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 13:37:31 -06:00
..
…

@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.

Editor dependency identity

Keep the root and workspace overrides for @codemirror/state, @codemirror/view, and @lezer/common aligned. CodeMirror requires shared extension identity, while Lezer parsers and syntax highlighters require shared NodeProp IDs. Multiple Lezer copies can crash code-block highlighting with tags is not iterable. src/lib/codemirror-single-instance.test.ts checks the installed dependency graph and highlights sample code through the editor's real language dependencies. GitHub Actions owns regeneration of pnpm-lock.yaml.