Files
PaperClipAI/ui
DottaandPaperclip 4d92589799 perf(ui): defer hidden task rendering until history is ready (#16878)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People open a task to read saved work and reply.
> - The conversation waits for its initial data so messages do not move
after reveal.
> - The hidden conversation and editor still render while those reads
are pending.
> - Profiling showed a useful cold-load gain when that hidden rendering
was delayed.
> - Prepare ordinary task content after its initial data is ready. Keep
the existing preparation path for comment links.
> - Keep the skeleton, measured reveal, timeout, and mounted
conversation during refresh.

## Linked Issues or Issue Description

Follow-up to #16862 and #16849. Related task-layout work: #14758.
Searches found no overlapping open rendering change.

**What existing behavior does this improve?**

Opening a task mounts hidden message rows and the rich editor while
supporting reads are still pending. These trees can render again as data
arrives before the user can see or use them.

**Subsystem affected**

UI task conversation startup and its browser acceptance suite.

**Proposed behavior**

Keep the existing skeleton and outer layout containers. Prepare the
hidden conversation and composer when initial history is ready, then use
the existing measured reveal. Keep content mounted after reveal. Hash
navigation retains eager preparation so older comment targets can be
positioned before reveal. The existing 15-second timeout still reveals
available history and the composer.

## What Changed

- Gate concealed history and composer children with the existing history
readiness, revealed-task latch, timeout, and scroll-navigation hash.
- Keep data queries, shell geometry, scroll ownership, and the reveal
frame unchanged.
- Update unit coverage for deferred content, comment-link preparation,
task changes, history timeout, and mounted editor identity during
refresh.
- Add a real browser journey that holds a background task read, retains
the same editor and draft, reloads the saved draft, sends one reply, and
checks the persisted comment independently.
- Document the loading and draft acceptance paths.

## Verification

- Repository-wide `pnpm -r typecheck` and `pnpm build` passed locally.
Token gates and all 231 task-thread unit cases passed.
- Seven regression cases failed against the old rendering behavior
before the source change.
- All 14 loading and layout browser cases passed again against the final
production UI and API build at
`15c360aa63e01ad9318aaf7865c07d1ee0d36968`. Coverage includes delayed
initial data, reading anchors, media growth, composer sizing, older
history, cold comment links, desktop/mobile same-task links and Back,
rapid switching, reduced motion, failed reads and retry, stalled
history, plan reuse, and cached-task profiling.
- The new draft journey retained the same editor during a blocked
background task refresh, restored the draft after reload, and persisted
exactly one reply.
- Final performance comparison used current master
`249ab47d41834f174ddd5e9523dc07fa8ebd8e4c` and implementation
`15c360aa63e01ad9318aaf7865c07d1ee0d36968` against the same local
160-message Markdown conversation and API process. Conditions: 50 ms
network latency, 9 Mbps down/1.5 Mbps up, 4x CPU slowdown, fresh
browsers, five alternating pairs per scenario, no CPU profiler, and no
concurrent local build/test work. Warm task navigation improved in all
five pairs: median paired saving **405 ms**; variant medians **1,787 →
1,456 ms**. Cold results were mixed: paired saving **−89 ms** (slower),
despite variant medians **3,188 → 3,021 ms**. There is no consistent
cold-load gain established by this comparison.
- Earlier prototype comparisons showed paired cold savings of 259–283
ms. Those gains did not consistently reproduce in the final comparison.
These are bounded local measurements and do not establish deployed
staging latency.
- The first prototype delayed comment-link preparation too and failed
the older-comment anchor check by 240.5 px. The narrowed implementation
keeps hash navigation on the existing eager path. That case and the full
suite now pass. The original failure trace is retained locally.
- A visual browser walkthrough read the saved conversation and plan,
restored a draft after reload, sent it once, reloaded again, and
independently checked that exactly one reply was saved.
- Greptile reviewed this exact commit at 5/5, with no actionable
findings or inline comments.
- The duplicate local `pnpm test:run` attempt was interrupted while the
same suites were completing in sharded CI so local performance could be
measured on an idle host. It is not counted as a local full-suite pass.
- All current-head [CI jobs
passed](https://github.com/paperclipai/paperclip/actions/runs/39296740548),
including the server, workspace, Runner, serialized, browser, typecheck,
build, canary, and final verification gates. The first run failed one
native-process supervision test (`preserves a real listening process and
its marker when a health RPC times out`). Its unchanged shard and
dependent gate passed on retry. The specific test also passed locally.
No source change was made for that transient failure.

## Risks

Delaying preparation can change initial scroll geometry. Hash navigation
keeps the existing preparation path because it needs the target present
before positioning. The revealed-task latch keeps refreshes from
removing history or the editor. The existing timeout still makes saved
content and the composer accessible when reads stall. No API, database,
permission, or provider changes.

## Model Used

OpenAI Codex, GPT-6, with reasoning, repository tools, code execution,
and browser verification. A more precise runtime model identifier and
context-window size are unavailable.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-19 14:01:37 -05: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.