mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-22 00:30:19 +02:00
## Thinking Path > - Paperclip users open tasks to read saved work and reply. > - Faster startup must preserve message positions and composer state. > - Chrome CPU samples showed unused shared schemas and catalog indexes being initialized before task content. > - The shared package exports definitions and module-local data, with no required import-time registrations. > - Let the browser bundler discard unused shared modules. > - Readiness marks also exposed a duplicate plan read even though full task detail contains that plan. > - Keep both improvements measurable through CPU profiles, gate transitions and real browser acceptance. ## Linked Issues or Issue Description Follow-up to #16849. Related layout work: #14758. Searches found no overlapping plan-cache PR. **What existing behavior does this improve?** Task startup evaluates unused schemas and catalog indexes reached through the shared package barrel. The task also waits for a second plan-document request after full task detail arrives, even when that response already includes the plan or an explicit absent-plan value. Profiling showed that removing the request alone gave a small and variable total gain; unused initialization was the larger cold-load opportunity. **Subsystem affected** Board task loading, shared-package bundling metadata, plan-query caching, and local issue-detail profiling. **Proposed behavior** Discard unused shared modules during browser bundling. Fill an unused plan query when a full task response arrives. List-only snapshots keep their normal plan fetch. Keep the existing coordinated reveal. ## What Changed - Declare the shared package side-effect free so the bundler can drop unused module initialization. Used schemas and catalog data still initialize normally. - Seed an absent plan query at the successful full-task HTTP response boundary. Use a 30-second plan-query freshness window. List cache merges do not update this plan cache, and a later detail response never overwrites an existing plan query. - Preserve document-scope invalidation for plan creation, edits and deletion. - Add opt-in Chrome CPU profiles and readiness transitions to the existing performance harness. Diagnostic runs use one sample per scenario/profile and are labelled separately from latency benchmarks. - Record only fixed gate names and readiness booleans in local browser marks. Reset the gate effects on task changes so fully cached navigation is profiled too. ## Verification - Production UI build, UI typecheck and token design gates passed. - 258 focused unit tests passed. The final freshness follow-up passed 14 tests, including query eviction followed by a list refresh, preserving a separately fetched newer plan, missing projection, task isolation, and document-event refresh/deletion. - Two focused reuse tests fail with the original HTTP cache function and pass with the fix. The original production browser case makes redundant plan reads and fails. - All 13 final browser cases passed serially: eight layout scenarios, four plan-present/absent and direct/list startup cases, and a cached-task switch that records every gate. The cached-switch case failed before the identity dependencies were added. - One earlier concurrent browser run failed a properties-resize reading-anchor assertion. Two isolated repeats and the final serial suite passed. This outlier is retained in the local logs; it was not treated as a reason to change the unchanged scroll owner speculatively. - Actual CPU samples and readiness artifacts were captured on a disposable local production preview. This is browser timing data, not exported telemetry. - Audited 247 non-test shared modules for required import-time registration. The four top-level loops construct exported local catalog data. No required registration or side-effect-only shared imports were found. - A compiled browser-library contract accepted valid task input, rejected an empty title, retained all seven agent statuses, and retained GitHub metadata plus 1,576 catalog entries. All 13 browser scenarios passed against the initialization candidate too. - Plan reuse alone did not establish a reliable total gain: a final local run was 4,356 ms cold and 1,116 ms warm on Fast 4G/4x CPU. - The next five-sample run with unused shared initialization removed measured **3,298 ms cold (24% faster)** and 1,079 ms warm. Median issue API server time was 35 versus 39 ms. First contentful paint fell from 2,808 to 1,648 ms. JavaScript before content fell from 1,722 to 1,670 KiB; CPU initialization mattered more than byte size. - Final alternating comparison: five samples per variant for both cold and warm navigation, same persisted task and Fast 4G/4x CPU settings, fresh browser per sample, order alternated between variants. **Cold content paint: 4,588 → 3,688 ms (20% faster). Warm: 996 → 1,030 ms (+35 ms).** No CPU profiler was active. The final initialization commit is the only source difference between these two builds. - These local measurements do not establish deployed staging latency or a speedup across every profile. Unthrottled timings varied with API latency. - Actual UI walkthrough on the final bundle: read the saved plan and conversation, submit one unassigned reply, refresh, navigate to Projects and Back, and inspect the new-task dialog. The reply persisted exactly once, confirmed independently through the comments API. No paid agent was woken. - Final head `a7043c474d`: Greptile 5/5, all review threads resolved, and all 56 checks passed, including full typecheck, build, unit and E2E suites. ## Risks Bundlers can discard unreferenced shared modules. Future required registrations or global initialization must be declared in the package side-effects metadata. Current module-local catalog construction remains when its exports are used. Merged list snapshots can retain old plan fields while receiving a new task-cache timestamp. This change seeds only from a new full HTTP response, rather than inferring plan freshness from those merged snapshots. Existing plan-query state is never overwritten. List-only, stale, invalidated, or incomplete data still uses the normal plan read. Existing document invalidations refresh the query. No API, database, permission or reveal-policy 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>