## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Task conversations must show the saved instruction and recent replies quickly. > - Compact task reads already limit the saved message window. > - The conversation still waits for completed run transcripts even when a saved reply contains the result. > - Removing that wait alone can insert activity after the reader starts reading. > - This pull request defers that output until the reader opens history and keeps required output in the initial reveal. > - The benefit is a useful conversation sooner, with a stable first layout and a working composer. ## Linked Issues or Issue Description Refs #17593, #18092, #18312, #18358, #18422. **What happened?** Opening a task with a long saved investigation can wait for native events or legacy logs before showing its existing replies. A slow transcript request can hold the conversation behind the loading screen until the 15-second fallback. **Expected behavior** Show the bounded saved conversation without reading completed output that already has a usable saved reply. Keep that output available through the existing history controls. **Steps to reproduce** 1. Create a task with many completed runs and long saved agent replies. 2. Delay its run events and logs. 3. Open the compact task directly. Before this change, the transcript read blocks the saved replies and composer. ## What Changed - Defer completed successful run transcripts on compact task opens when a usable saved reply is present. Load that output through the existing history controls. - Keep required output on the initial path: live and failed runs, yielded runs, pending interactions, placeholder/progress-only replies, explicit anchors, chats, and full history. Retain output already selected during this visit when its run completes. - Keep saved plans visible when their owning run output is deferred or still loading. - Keep the same composer and draft through history expansion. Offer **More run output** when a single saved run has deferred output. - Position same-task comment links after their target arrives. Wait only for a missing target, with a 15-second limit. Unrelated stalled metadata cannot block an available target after the reveal deadline. - Preserve the reading anchor when a queued scroll event arrives during a properties-pane width transition. - Add a 200-reply/200-run PostgreSQL browser fixture with a saved plan, covering both task views on desktop and mobile. Correct stale browser setup for current routes and the shared mobile scroller. - Remove a random company-prefix collision in the isolated privacy test fixture that failed during CI. ## Verification - Final revision `fba3f2fcbb`: 386 focused thread/scroller unit cases and all 32 production-browser journeys passed. The browser cases cover both task views on desktop/mobile, saved plans, delayed transcripts, history, comment links, Back, drafts, retry, avatar continuity, media and pane resizing. The 25 privacy fixture cases also passed against PostgreSQL. - Workspace typecheck and full build passed with Node 24. A broader local UI run passed 10,220 cases across 849 files before the final navigation/plan review fixes; the changed components were then rechecked in the 386-case focused run. - Five alternating pairs compared master `12b0cc6304` with this revision, using 200 long saved replies and 200 completed native runs. Both production UI builds used the same loopback API/database, Chromium 151.0.7922.34, 1440 × 900, fresh browser contexts, service workers blocked, no CPU throttle, and a controlled 3-second events/log delay. Builds and other suites were stopped during measurement. No page errors occurred. | Useful conversation + editable composer | Baseline median (range) | Fixed median (range) | | --- | --- | --- | | Cold direct open | 3.570s (3.538–3.616s) | 1.056s (1.022–1.141s) | | Task-list navigation | 3.373s (3.342–3.394s) | 0.899s (0.885–0.915s) | | Back | 22ms (22–25ms) | 25ms (25–28ms) | - Median paired savings: 2.519s cold, 2.470s from the list. Completed-output requests: two per baseline sample, zero per fixed sample. Recent-comments API control medians were 13.6ms for both, with ranges 12.1–18.7ms and 11.6–50.8ms. No Back improvement is claimed; an earlier revision's run also included one 1-second Back outlier, retained in the local evidence. - The full local default test command did **not** pass: it stopped on the existing chat test line-selection error. After restoring embedded PostgreSQL library symlinks omitted by an install with scripts disabled, Node 24 passed 672 cases in the first two chat shards, then failed to select the third. This is separate from the passing focused suites and remote CI. - Earlier CI failures were addressed: the privacy prefix collision is fixed; the delegated task-completion reply case passed locally after merging master's reply-recovery fix (#18465). Browser fixture corrections retain the original behavior assertions. Red tests reproduced the loading, navigation, resize and saved-plan regressions before their fixes. - Map, module-boundary, token-gate and added-line token checks passed. The full-tree token scan still finds pre-existing active-username fixtures; this PR adds zero forbidden token lines. - Greptile: **5/5**, final revision, all four review threads resolved. The final-revision PR CI workflow passed, including build, typecheck, all server/chat/workspace test shards, all eight E2E shards, and every Runner lane. GitHub reports 55 successful checks and three skipped checks. The separate **Paperclip Review** check remains queued with **Waiting for the assigned agent**; it has not produced an assessment and has not been bypassed. The branch has no merge conflicts. ## Risks - The default compact task omits completed transcript details when the saved result is sufficient. The reader must open history to inspect them. - Required structural data remains inside the initial reveal boundary. Slow server responses for that data remain visible latency. - Link positioning falls back after 15 seconds when its target never arrives. The conversation remains readable. - The measurements use a controlled local delay. They do not establish a deployed staging speedup. - No API, schema, authorization, or migration changes. ## Model Used OpenAI Codex, GPT-6, 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 - [ ] I have run tests locally and they pass (focused suites pass; the full default wrapper has the existing selection error documented above) - [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 (code CI passed; the separate assigned-agent Paperclip Review remains queued) - [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>
Issue-detail performance baseline
Run the repeatable baseline from the repository root:
pnpm exec playwright test --config tests/perf/issue-detail/playwright.config.ts
The rig starts an isolated seeded Paperclip instance, runs five samples for each scenario/profile, and writes median-ready raw data plus a Markdown table to test-results/issue-detail-perf/.
Scenarios:
- S1 warm in-app navigation: loads the Issues list, clears the waterfall, and clicks the seeded issue.
- S2 cold open: creates a fresh browser context and deep-links to the seeded issue.
Profiles:
- Unthrottled.
- Fast 4G network with 4x CPU slowdown.
Override the sample count (minimum five) or port when needed:
PAPERCLIP_ISSUE_PERF_RUNS=7 PAPERCLIP_ISSUE_PERF_PORT=3210 pnpm exec playwright test --config tests/perf/issue-detail/playwright.config.ts
Outputs include baseline.md, baseline.json, and a Chrome trace for the first run of each scenario/profile. Open *.trace.json in Chrome DevTools Performance to inspect the issue-detail:* user-timing marks.
Set PAPERCLIP_ISSUE_PERF_PROFILE=1 to capture actual Chrome CPU samples and
conversation-readiness transitions in one diagnostic sample per scenario/profile.
Import the resulting *.cpuprofile in DevTools and inspect *.readiness.json for
the task, comments, metadata, activity, runs, runtime, plan and transcript gates.
Each gate records changes with detail.ready; use its last transition before
content paint when a gate becomes pending after mount. These diagnostic runs
include profiler overhead. Run without the flag for before/after latency claims.
Readiness marks stay in the local browser and contain only fixed gate names and
booleans; the harness enables them before navigation.
For bundle comparisons, build the UI and serve the production assets from an
isolated local instance with PAPERCLIP_UI_DEV_MIDDLEWARE=false. The default
managed server above uses development middleware, which does not reproduce
production chunk loading. Keep the server, database, browser profile and sample
count the same for both builds, and avoid concurrent builds or test suites while
measuring latency.
Copy the first run's output outside test-results/issue-detail-perf, then reuse
its persisted task with PAPERCLIP_ISSUE_PERF_SEED_FILE=/path/to/before/baseline.json
and PAPERCLIP_ISSUE_PERF_BASE_URL pointing to that disposable instance. The
harness validates the task identity before measuring. Network spans in the trace
use recorded request start/end timestamps relative to task navigation; they
include completed requests observed during the sample, even after content paint.
Task layout stability
compact-startup.spec.ts keeps a synthetic local reproduction with 24 messages,
a plan, three documents and three saved PR cards. It holds the enriched task
response, records each visible frame's card count and geometry, and rejects
cards inserted after the conversation becomes readable. It also checks document,
older-comment and unknown anchors without full comments/activity/run reads.
Run it with the same loopback-only URL override below. The fixture URL is saved
in test-results/compact-startup-fixture.json for manual inspection and reuse.
It also checks a delayed Coordinator preference with Classic enabled, index-based
Coordinator list navigation, and the responder identity through reassignment,
comment acknowledgement and legacy runtime discovery. The last case uses a
deterministic local process, records identity continuity on each frame, and saves
startup/running screenshots. It does not call a model provider.
Each send fixture uses a unique task title so repeated runs cannot reuse a
previous task and its cancelled run through ordinary task deduplication.
layout-stability.spec.ts exercises the real task route, including Inbox
navigation, with 160 Markdown comments and a resolved interaction. It delays
initial comments, tests failures and retry, tracks a reading anchor across
media growth, composer resizing, properties toggles, older-page loading and
Back navigation, and covers mobile reduced motion and explicit comment links.
The eight scenarios also exercise same-task hash navigation without remounting
on desktop and mobile, and stalled native/log reads that expose Retry after
the 15-second request deadline.
plan-startup.spec.ts opens tasks directly and from the task list, with and
without a saved plan, while holding separate plan reads. The core projection
must reveal the saved conversation and plan before those reads finish. Separate
plan reads are recorded as diagnostics. The hook tests cover fallback reads for
list-only snapshots and responses without a plan projection.
Videos and per-frame layout.json measurements are written under each test's
output directory. The two-pixel assertion measures a logical row's viewport
offset; total scroll offset legitimately changes when history is prepended.
Ordinary task opens defer the concealed history and composer until their initial data is ready. The skeleton and scroll/composer containers retain their geometry. Compact tasks reuse saved replies from completed runs. Their transcript reads start when the reader opens older history through More messages or More run output. Saved Plans from completed runs stay visible while their output is deferred or pending. Live runs, failures, yielded runs, explicit anchors, and runs without a saved reply still load their output. A transcript already shown during this visit stays mounted when the run completes. Comment-link navigation prepares content eagerly so the target can be positioned before reveal. Revealed content stays mounted during refresh. The draft scenario holds a background task read, checks the same editor remains mounted, reloads the saved draft, sends one reply, and independently checks its persisted comment.
To run against an existing disposable local test-drive instance:
PAPERCLIP_ISSUE_PERF_BASE_URL=http://127.0.0.1:3102 \
pnpm exec playwright test --config tests/perf/issue-detail/playwright.config.ts layout-stability.spec.ts
The suite creates its own company and fixtures. The URL override accepts only loopback origins and rejects remote hosts. Use a disposable local instance, not a shared or production instance. Without the override, the harness starts its own isolated instance as before. Live provider walkthroughs additionally require a configured native Paperclip runner and Codex authentication; deterministic browser fixtures do not substitute for watching an actual provider run.
saved-reply-startup.spec.ts adds a PostgreSQL fixture with 200 long saved agent
replies, 200 completed native runs, and a Plan linked to the latest run. It holds
transcript requests, checks both task presentations on desktop and mobile, and measures
reply positions on each frame. Opening older history must start the transcript
reads and preserve the editor and draft. This case is skipped unless
PAPERCLIP_ISSUE_PERF_DATABASE_URL points to a disposable loopback PostgreSQL
database whose name ends in _test. Use the same database as the local server:
PAPERCLIP_ISSUE_PERF_BASE_URL=http://127.0.0.1:3102 \
PAPERCLIP_ISSUE_PERF_DATABASE_URL=postgres://paperclip:paperclip@127.0.0.1:5432/task_loading_test \
pnpm exec playwright test --config tests/perf/issue-detail/playwright.config.ts saved-reply-startup.spec.ts
For the live walkthrough, first assign a disposable task to a native Paperclip
runner configured with the Codex provider. Its scratch project should contain
a small sum.mjs fixture. The script sends a paced job, scrolls up, disconnects
and reconnects, steers a follow-up, and records through completion:
PAPERCLIP_LAYOUT_LIVE_URL=http://127.0.0.1:3102/LAY/issues/LAY-8 \
node tests/perf/issue-detail/live-feed.walkthrough.mjs
Inspect test-results/task-layout/live-acceptance/ for the video, screenshots,
per-frame positions, layout shifts, browser timing counters, and reading-anchor
measurement. The live script rejects non-local URLs and uses real provider
capacity. Review the video as well as the assertions: layout-shift scores alone
do not capture programmatic scrolling or replacement flashes.
Long-running agent chats
The separate agent-chat performance rig covers recent-only startup and scrolling history with long-lived conversations. It is opt-in and does not run in this task-detail rig.