Commit Graph
5 Commits
Author SHA1 Message Date
DottaandPaperclip fa50cab568 perf(ui): speed task loading without shifting the conversation (#16849)
## Thinking Path

> - Paperclip's board should open a task quickly while keeping its
conversation and composer stable.
> - The browser currently downloads unrelated screens and unopened
dialog implementations before task content appears.
> - Splitting routes alone creates many shared requests and did not
improve measured cold loading.
> - This change groups the startup and task dependency trees, preloads
the task chunk, and defers optional routes and dialogs.
> - Existing coordinated history reveal stays intact so late data does
not insert content above the reader.
> - Hidden routes must not overwrite saved scroll positions with
zero-height geometry.
> - Repeated browser measurements and delayed-response tests establish
the result independently of bundle-file size.

## Linked Issues or Issue Description

Refs #14758. Related prior work: #10463 and #14727.

**What existing behavior does this improve?**

Cold task-page opening downloads and evaluates code for other screens
and globally mounted, unopened dialogs. A direct task link should reach
its saved conversation sooner without moving already-visible messages or
the composer.

**Subsystem affected**

Board UI startup, route boundaries, dialog loading, task scroll
restoration, and the issue-detail performance harness.

**Proposed behavior**

Load optional screens and dialogs when needed, keep startup requests
bounded, and preload the task route. Preserve the current history reveal
policy. Keep the shell mounted during route loading and preserve the
reader's position when a route is temporarily hidden.

**Additional context**

The older bundle-splitting attempt in #10463 is still open from August.
This implementation targets current master and deliberately preserves
today's editor, composer, and transcript reveal behavior. It does not
implement the alternative transcript-row design discussed in #14758.
ROADMAP.md does not describe overlapping startup-bundle work.

## What Changed

- Lazy-load board routes, standalone screens, the legacy layout,
onboarding, and unopened create dialogs.
- Keep activated dialogs mounted across close/reopen to retain their
existing draft lifecycle.
- Group startup and issue dependencies and preload the emitted issue
chunk from the production HTML.
- Contain route loading within the shell and retain existing chunk-error
recovery.
- Contain dialog import failures locally, support cancellation, and keep
setup dismissed after a late download. Warm the task module from task
lists and keep the small chat redirect eager.
- Wait for task-creation dialog fields in the browser fixture before
filling an explicit title.
- Ignore zero-height scroll geometry while a route is hidden.
- Reuse the same persisted performance fixture between builds, record
actual network spans, and distinguish concealed loading content from the
ready thread in browser assertions.

## Verification

- Production UI build and UI TypeScript check passed.
- Recovery follow-up: 74 focused UI tests passed; the cancellation
change passed 23 focused tests plus all 131 onboarding tests (the latter
with a 15-second per-test timeout on the contended local host).
- Setup cancellation was reproduced against the prior production build
and verified fixed after releasing the held real wizard download.
- 91 focused UI tests passed; the final route registrations were checked
again after making standalone screens lazy (33 routing tests passed).
- All eight real-browser layout scenarios passed: delayed comments, late
media, properties changes, growing drafts, older history, Back
navigation, deep links, desktop/mobile same-task links, request
failure/retry, and stalled native/log reads.
- Browser walkthrough: read a populated task, submit one reply, refresh,
navigate to Projects, and return. The reply persisted once and the
normal composer remained usable.
- Token design gates passed. The separate repository-wide publish-token
scan fails on pre-existing references to the local maintainer username
in unchanged files; this change adds none.
- Production-build measurements use the same persisted task, local
API/database, fresh browser contexts for cold opens, and five samples
per scenario/profile. These measurements do not establish deployed
staging latency.
- Final head `076466816a`, consecutive before/after production builds:
five samples per scenario/profile, same saved task and server. Cold Fast
4G/4x CPU content paint: **5,775 → 4,248 ms (26%)**; issue API server
timing was 23 ms in both sets. Warm Fast 4G: 989 → 971 ms. JavaScript
transferred before content: **2,596 → 1,722 KiB (34%)**.
- Unthrottled cold content paint: 1,306 → 676 ms; warm: 269 → 224 ms.
These local timings vary with host load. Earlier measurements showed
about 20% cold improvement, and a contended intermediate run had
substantially higher API latency; those runs are retained in the local
evidence. The final matched pair meets the proposed 25% target, but it
does not establish a guaranteed 25% improvement across environments.
- All four browser scenarios that failed on the first CI run passed
locally after the readiness fixes; the subsequent CI run passed all
eight browser shards.
- Fault-injection browser checks: delayed route loading preserves shell
geometry; a failed route recovers through Back; cancelled or failed
dialog loading preserves an unsent reply; Back dismisses pending setup
and contains its late failure.

- Final head `076466816a`: all CI gates green (55 successful checks, no
pending or failed checks); Greptile 5/5 with no actionable findings and
all review threads resolved.

## Risks

- Dynamic chunks add a loading state on first entry to optional screens
and dialogs. Route failures use the existing error boundary. Optional
dialog failures are dismissible without unmounting the board; retrying a
rejected import requires a reload.
- The task preload prioritizes the primary board journey, including when
another screen is opened first.
- Chunk grouping should be revisited when the dependency graph changes;
bundle size alone does not establish a speedup.
- No API, authorization, migration, editor semantics, or
transcript-reveal policy changes.

## Model Used

OpenAI Codex, GPT-6, with reasoning, repository tools, code execution,
and browser verification. The runtime does not expose a more precise
model identifier 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>
2026-10-19 10:16:23 -05:00
DottaandPaperclip 3b03c4b9eb perf(ui): keep long task chat responsive during streaming (#13229)
## Thinking Path

> - Paperclip lets operators manage agent work through tasks.
> - Task chat keeps responses and run history together.
> - A live update rendered every historical bubble and hidden tool row
again.
> - New image callbacks also forced unchanged markdown to parse again.
> - Long conversations saturated the browser main thread.
> - This change reuses unchanged history and mounts folded tools on
first inspection.
> - Operators can read and reply while work continues.

## Linked Issues or Issue Description

**What happened?**

Chat-style tasks with substantial scrollback became almost unusable. A
deterministic browser reproduction with 200 long responses and 4,000
tools consumed 97.8% of the main thread during live updates. It
delivered only 8 updates during the sample.

**Expected behavior**

The task should remain responsive during streaming. Historical markdown
and unopened run details should not repeat expensive render work.

**Steps to reproduce**

1. Install dependencies with `pnpm install`.
2. Run `pnpm exec playwright test --config
tests/perf/task-chat/playwright.config.ts`.
3. Compare the attached performance JSON. The new test fails against the
original rendering code.

**Paperclip version or commit**

Reproduced at `a05b828bc`. The branch is rebased on current master.

**Deployment mode**

Local Chromium and Vite with deterministic fixtures. No database or
agent credentials are required.

Related work: #10463 reduces the issue-page bundle. This change
addresses repeated rendering after the page loads. No duplicate
scrollback fix was found.

## What Changed

- Keep the bubble image callback stable so unchanged markdown can skip
parsing.
- Memoize the settled history separately from the header and streaming
tail. Keep the brief renderer and default attachment array stable.
- Mount folded tool history on first expansion. Keep it mounted
afterward to preserve child state and closing motion. Runtime request
receipts remain visible.
- Add deterministic rendering tests to the normal Vitest suite and an
opt-in Chromium regression fixture.
- Document the reproduction, commands, scope, and local measurements.

## Verification

- Browser reproduction: 97.8% main-thread utilization before; 11.6%
after for tail-only updates; 31.5% after when projection recreates
history objects. Both fixed cases delivered 32 updates.
- Browser checks pass for scroll-position retention, typing, return to
latest, tool inspection, and retained expansion state.
- Focused component suite: 155 tests passed. Post-rebase
thread/performance rerun: 101 tests passed.
- Recursive typecheck, build, Storybook build, and token gates passed.
UI typecheck passed after the final edits.
- Local UI/CLI lane: 5,910 tests passed; ten files hit worker-start
timeouts, then all ten passed with two workers (20 tests).
Shared/adapter lane: 3,128 tests passed.
- Full local `pnpm test:run` was attempted and is **not green**: its
server lane recorded 10,517 passes and 11 failures plus fixture/setup
errors. Queue (31 tests), Cursor/Git-load (9 tests), and missing-binary
failures cleared on isolated reruns / building the runner test binaries.
Two native suites still cannot initialize embedded PostgreSQL on this
host.
- The remaining native-session recovery assertion was reproduced in a
clean worktree at base `a20ecce40` (1 failed, 67 passed across the
native/queue suites). It expects a settled-session error but receives a
semantic-tool-input digest error. No server or runner files changed in
this PR.
- All substantive CI jobs have passed, including build, typecheck, all
server/workspace test shards, all three e2e shards, and the canary dry
run. The unchanged Slack ordering test exhausted its one-second wait on
the first run; its shard passed on rerun. Final aggregate verification
passed: **31 passing checks**, no failures or pending checks; two
optional Storybook deployment/visual checks were skipped. Greptile is
**5/5**, with no unresolved review threads.
- The supplemental local serialized route run was stopped after CI
passed all five serialized shards; it had reported no failures.
- The browser fixture uses the real chat rendering components with a
plain textarea. It does not test the full composer or server transport.
Timing results are local samples; deterministic render-count tests
provide normal CI coverage.

## Risks

- Closed tool content becomes available to DOM search only after first
expansion. Visible run summaries and runtime request receipts remain
available immediately.
- Opened run history remains mounted to preserve child state. The first
full markdown render still scales with conversation size.
- Memo dependencies must stay current when adding render inputs. Tests
check content edits and replacement gallery callbacks.
- No API, database, or permission changes.

## Model Used

OpenAI GPT-6 (Codex). Exact serving variant and context-window size are
not exposed in this session. Used reasoning, repository tools, code
execution, and browser testing. No sub-agents were used.

## 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 — targeted/UI/workspace
checks pass; the full local server suite has the baseline/host failures
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
- [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-09-11 10:15:00 -05:00
DottaandPaperclip cd4c4ed205 fix(ui): stabilize task loading and live feeds (#13095)
Coordinate initial conversation reveal, preserve message identity and reading anchors during live updates, and bound transcript reads with recoverable retries. Cover desktop/mobile navigation and rich task loading with actual-route browser tests.

Verified all Linux CI gates, 5,575 local UI tests, eight layout browser scenarios, and recorded native Codex walkthroughs. Greptile: 5/5; all review findings resolved.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-09-09 10:00:37 -05:00
Dotta e3eed3a3ae Keep browser startup explicitly opt-in (#12435)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The CLI can save a configuration and start the local server in one
command.
> - The onboarding path set a browser-open environment variable without
an explicit user request.
> - Headless test servers use the same onboarding path.
> - Each server restart could therefore open a system browser.
> - This pull request removes the implicit browser-open request and
fixes test servers to disable it explicitly.
> - The benefit is predictable foreground and test startup without
unsolicited browser windows.

## Linked Issues or Issue Description

This is stack 11 of 11. It depends on stack 10.

**What happened?**

`paperclipai onboard --yes --run` set `PAPERCLIP_OPEN_ON_LISTEN=true`.
Headless server users, including browser test runners, opened the system
browser on each server restart.

**Expected behavior**

Server startup must not open a browser unless the caller explicitly sets
`PAPERCLIP_OPEN_ON_LISTEN=true`.

**Steps to reproduce**

1. Run `paperclipai onboard --yes --run` from a clean source checkout.
2. Wait for the server to listen.
3. Observe that the default system browser opens.

**Paperclip version or commit**

Reproduced on `dbf052577` plus the dependent stack.

**Deployment mode**

Local dev from source.

## What Changed

- Stop onboarding from setting `PAPERCLIP_OPEN_ON_LISTEN=true` for
foreground startup.
- Set `PAPERCLIP_OPEN_ON_LISTEN=false` in E2E and issue-detail
performance test servers as defense in depth.
- Preserve the existing explicit environment opt-in in the server.

## Verification

- `pnpm exec vitest run cli/src/__tests__/onboard.test.ts` — 10 tests
passed.
- `pnpm --filter paperclipai typecheck` — passed.
- `pnpm -r typecheck` — passed on the stacked head.
- `pnpm build` — passed on the stacked head.
- Playwright was not run locally by request.

## Risks

- Low risk. The only behavior change removes an unsolicited side effect.
- A caller that wants browser startup can still set
`PAPERCLIP_OPEN_ON_LISTEN=true` explicitly.
- No database or migration change exists in this layer.

> 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 exact deployment suffix and context window
are not exposed. The model used reasoning, repository tools, code
execution, Git, and GitHub API access.

## 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
2026-08-29 12:08:35 -05:00
2494a2a0fe perf: add repeatable issue-detail baseline rig (#10409)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The issue detail page is a core operator surface where perceived
latency directly affects task navigation
> - Performance work needs repeatable evidence so later optimizations
can be compared against the same scenarios
> - The page did not expose stable user-timing marks for its header or
first useful content
> - There was also no isolated seeded browser rig that measured warm
navigation, cold deep links, waterfalls, or server time
> - This pull request adds the instrumentation and a one-command
Playwright baseline harness
> - The benefit is that issue-page performance changes can be validated
with reproducible median measurements instead of anecdotes

## Linked Issues or Issue Description

**Subsystem affected**

Cross-cutting: `ui/`, `server/`, and browser performance tooling.

**Problem or motivation**

The issue detail page performs a large client bootstrap and request
fan-out, but the repository lacks stable user-timing boundaries and a
repeatable benchmark. That makes performance changes difficult to
compare and allows regressions to be judged from anecdotes instead of
consistent evidence.

**Proposed solution**

Add stable header/content paint measures, development/QA-only lifecycle
vital reporting, aggregate server timing for the issue endpoint, and a
seeded Playwright command that runs warm/cold scenarios under throttled
and unthrottled profiles with N≥5 median reporting.

**Alternatives considered**

Ad hoc DevTools recordings were rejected because they are not repeatable
or reviewable. Production telemetry was rejected because this baseline
should not change production data collection. A unit-only harness was
rejected because it cannot capture browser bootstrap, rendering, and
network waterfall costs.

**Roadmap alignment**

The roadmap calls for agent performance to be measurable over time. This
change applies that evidence-first principle to a core operator page and
does not duplicate a listed roadmap deliverable.

**Additional context**

The generated report includes warm and cold medians, TTFB/FCP/LCP where
applicable, request and byte totals before first useful content,
JavaScript bytes, and issue endpoint server timing.

## What Changed

- Added `issue-detail:navigate→header-paint` and
`issue-detail:navigate→content-paint` user-timing measures to the issue
detail page.
- Added development/QA-only TTFB, LCP, and INP console reporting without
production telemetry delivery.
- Added `Server-Timing` for `GET /api/issues/:id`.
- Added `pnpm exec playwright test --config
tests/perf/issue-detail/playwright.config.ts`, which seeds an isolated
instance and runs N≥5 warm/cold samples under unthrottled and Fast 4G/4x
CPU profiles.
- Added Markdown, raw JSON, and Chrome-trace outputs with median
baseline tables and waterfall data.

## Verification

- `pnpm --filter @paperclipai/ui typecheck`
- `pnpm --filter @paperclipai/server typecheck`
- `pnpm check:token-gates`
- `npx playwright test --config
tests/perf/issue-detail/playwright.config.ts --list`
- `pnpm exec playwright test --config
tests/perf/issue-detail/playwright.config.ts` — passed 20 samples in 9.4
minutes (5 runs × 2 scenarios × 2 profiles) for the baseline;
post-review integrity reruns also exercised the corrected paths, while
this shared runner intermittently killed Chromium processes, so the rig
now performs one bounded browser-crash retry per sample.
- Baseline medians: warm unthrottled 278/447 ms header/content; cold
unthrottled 646/646 ms; warm throttled 1240/2060 ms; cold throttled
3932/3933 ms.

## Risks

- Low product risk: the new browser measurements are development/QA
tooling and the UI timing work does not change visible layout.
- `Server-Timing` exposes only aggregate handler duration, not query
contents or private identifiers.
- Native INP reporting uses supported browser event timing entries and
silently no-ops where unsupported.

> 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.4, tool-assisted coding and browser execution with
reasoning enabled; context-window size is not exposed in this
environment.

## 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: Dev Agent <dev@paperclip.ing>
2026-08-11 15:18:29 -04:00