* 🔧 chore(ci): lower the first-screen chunk gate to 40
The $initial chunking (#19288) brought the web entry graph from ~68 eager
chunks to 17, so the previous ceiling of 100 no longer catches a regression.
Claude-Session: https://claude.ai/code/session_01QKr8CsFLYmrgqbRTSipTNH
* 🔧 chore(ci): gate Vite JS chunks by baseline growth
* ✨ feat(task-dock): promote the upload dock into an app-level task dock
Background work of every kind now shares one dock instead of the
uploads-only one mounted inside the resource manager.
- `features/TaskDock` renders a `DockTask[]` collected from producer
hooks; producers own their copy, actions and results.
- One task renders as a result card, two or more as a panel grouped by
producer. The shape follows the task count and waits 400ms before
shrinking so a burst of dismissals cannot morph it repeatedly.
- A finished task with nothing to hand back clears itself after 3s; one
that left a result waits for the user, and a failure always does.
- File uploads keep their store untouched and are adapted into tasks;
`business/client/features/DockTasks` lets a distribution add its own.
- Mounted in `SPAGlobalProvider`, so the dock outlives the page that
started the work.
Claude-Session: https://claude.ai/code/session_014iyxmqssnrPopmKV1xKJ7k
* 🐛 fix(task-dock): batch a producer's cancel-all and label the expand toggle
- `DockTask.groupCancel` lets a producer cancel its whole set in one
operation. Walking `cancel` per task turned a folder upload's batched
cancel into one full-list update per file.
- The header toggle said "Collapse" while collapsed, i.e. the opposite of
what it does.
Claude-Session: https://claude.ai/code/session_014iyxmqssnrPopmKV1xKJ7k
* 🐛 fix(task-dock): lazy-load the dock and turn the size gate into a review
The dock pulled the upload/file chunks into the first-screen static
graph; it now loads through `lazy()` like the other global hosts.
The web and ASAR size gates no longer fail their jobs. A failing gate
submits a REQUEST_CHANGES review from github-actions that links the
report comment, updates it while still failing, and dismisses it once
the gate passes again.
Claude-Session: https://claude.ai/code/session_01BBCjqExuP6Ux5PRVJbU2ru
* 👷 ci(perf): gate the first-screen static import graph
Total dist size cannot see a lazy chunk being pulled back into the entry's
sync graph. Walk static imports from each SPA entry, gzip the reachable
chunks, and fail a PR when the total grows past the threshold or a chunk
name that was lazy in the canary baseline now sits on the first-screen path.
Claude-Session: https://claude.ai/code/session_01C2wPWhzukH4pniaLy6vkhD
* ⚡️ perf(spa): keep heavy @lobehub/ui members out of the first-screen chunk
Rolldown assigns chunks by static reachability, so the @lobehub/ui barrel
promoted shiki, katex, elkjs, emoji-mart and @pierre/diffs into the entry
chunk as soon as any lazy route used Markdown, Mermaid or EmojiPicker.
Rewrite the ui barrels to deep imports (same approach as lobeIconImports),
stop the tool store from importing the Claude Code render registry, lazy-load
ProfileSetupModal and the error-page Highlighter, and add a boot-path lint
rule for the known heavy members. Desktop entry graph: 3.84 MB -> 2.26 MB gz.
Claude-Session: https://claude.ai/code/session_01C2wPWhzukH4pniaLy6vkhD
* 🐛 fix(vite): resolve bare barrel specifiers from the @lobehub/ui package itself
The virtual proxy re-exported `ErrorBoundary` from "react-error-boundary",
a dependency of @lobehub/ui that pnpm does not hoist to the app root, so the
auth build failed in CI. Resolve such specifiers with the barrel's real path
as the importer.
Claude-Session: https://claude.ai/code/session_01QP9qfw629JNyNeNCwizuHY
* 👷 ci(perf): run the size gates on feature-branch pushes too
skip-duplicate-actions cancels the pull_request run of same-repo PRs in favour
of the push run, and the push run skipped every gate step, so neither the web
dist gate nor the entry-graph gate ever checked a same-repo PR. Gate on a
SIZE_GATE_ENABLED flag that is true for PRs and for pushes to non-release
branches, and resolve the PR number from the commit when commenting.
Claude-Session: https://claude.ai/code/session_01QP9qfw629JNyNeNCwizuHY
* 👷 ci: add bundle size gate for web dist and desktop asar
- measure web dist (dist/desktop|auth|workbench) in e2e workflow builds
- measure app.asar in desktop builds (pr-build-desktop, release-desktop-canary)
- baseline stored as workflow artifacts from latest successful canary runs
- PR runs compare against baseline and fail when increase > max(3%, 512KB)
- upsert PR comment with per-entry size report
* 👷 ci: address codex review on size gate
- add result-encoding: string to baseline finder steps (raw run id,
empty-string check works, graceful degrade no longer broken)
- emit a visible skipped section when baseline/current report is missing
instead of the misleading comment fallback
- per-gate comment identifiers (web / asar) so e2e and desktop workflows
no longer overwrite each other's PR comment