Severity: Medium.From a frontend deep audit, 2026-06-08. Performance headroom + a few targeted test gaps. The suite is otherwise healthy (175 tests, 0 skipped, strong selectors, parity test).
Problems
[Med] Single ~221 KB gz main chunk, only ~29 KB under the 250 KB budget, and vite build already prints the >500 KB raw warning. vite.config.ts has no build.rollupOptions.output.manualChunks. The chunk is framework code (react-dom + react-router 7 + @tanstack/react-query + @base-ui/react + i18next + both locales) that rarely changes but invalidates on every app edit.
[Med] components/delete-confirm-dialog.tsx — the delete-in-use flow is untested at the UI layer.InUseError → t("actions.inUse", {count}) (:40) is only covered at the query layer (api/queries.test.ts); the dialog's rendering of the in-use message + blocked-delete branch has no .test.tsx.
[Med] objects/prune-fields.ts — non-trivial pure transform tested only indirectly via object-form.test.tsx (localized single-lang filtering, empty/null pruning, nested maps). Ideal direct-unit-test candidate.
[Low] lib/labels.ts + lib/format-date.ts — widely-used pure functions (label-fallback resolution, locale-aware date formatting) with no direct test.
[Low] Story gaps — combobox (composed interactive primitive) lacks a visual/a11y story; also alert-dialog, drawer, label, skeleton, card.
Suggested fix
Add a manualChunks vendor split (e.g. react/react-dom/router together, @base-ui separately) — buys budget headroom + long-term cache stability for the cheapest effort.
Add delete-confirm-dialog.test.tsx (InUseError path), prune-fields.test.ts, and direct tests for labels/format-date.
Add a combobox story.
Source: frontend deep audit (perf/testing dimension), 2026-06-08. Verified-good (no action): tree-shakeable lucide-react, heavy object-form already code-split, native Intl (no heavy date lib).
**Severity: Medium.** _From a frontend deep audit, 2026-06-08. Performance headroom + a few targeted test gaps. The suite is otherwise healthy (175 tests, 0 skipped, strong selectors, parity test)._
## Problems
- **[Med] Single ~221 KB gz main chunk, only ~29 KB under the 250 KB budget**, and `vite build` already prints the >500 KB raw warning. `vite.config.ts` has no `build.rollupOptions.output.manualChunks`. The chunk is framework code (react-dom + react-router 7 + @tanstack/react-query + @base-ui/react + i18next + both locales) that rarely changes but invalidates on every app edit.
- **[Med] `components/delete-confirm-dialog.tsx` — the delete-in-use flow is untested at the UI layer.** `InUseError → t("actions.inUse", {count})` (`:40`) is only covered at the query layer (`api/queries.test.ts`); the dialog's rendering of the in-use message + blocked-delete branch has no `.test.tsx`.
- **[Med] `objects/prune-fields.ts` — non-trivial pure transform tested only indirectly** via `object-form.test.tsx` (localized single-lang filtering, empty/null pruning, nested maps). Ideal direct-unit-test candidate.
- **[Low] `lib/labels.ts` + `lib/format-date.ts`** — widely-used pure functions (label-fallback resolution, locale-aware date formatting) with no direct test.
- **[Low] Story gaps** — `combobox` (composed interactive primitive) lacks a visual/a11y story; also `alert-dialog`, `drawer`, `label`, `skeleton`, `card`.
## Suggested fix
- Add a `manualChunks` vendor split (e.g. react/react-dom/router together, @base-ui separately) — buys budget headroom + long-term cache stability for the cheapest effort.
- Add `delete-confirm-dialog.test.tsx` (InUseError path), `prune-fields.test.ts`, and direct tests for `labels`/`format-date`.
- Add a `combobox` story.
_Source: frontend deep audit (perf/testing dimension), 2026-06-08. Verified-good (no action): tree-shakeable lucide-react, heavy object-form already code-split, native Intl (no heavy date lib)._
Vendor split (vite.config.ts → build.rollupOptions.output.manualChunks): framework deps now split into cache-stable chunks — react (react + react-dom + react-router + react-router-dom, one shared instance), base-ui, query, i18n — and the app entry chunk carries only app code. Largest chunk dropped 216.5 → 90.2 KB gz (budget 250). Note: used the function form of manualChunks (matches pnpm's .pnpm/<pkg>@… layout); the object form is unbuildable here because bare specifiers like react-router aren't root-resolvable under pnpm's strict store.
Test-gap fills:prune-fields.test.ts (localized single-lang + empty-pruning branches), lib/labels.test.ts (fallback chain), lib/format-date.test.ts (locale format + no tz day-shift + edges), components/delete-confirm-dialog.test.tsx (the delete-in-use flow: InUseError(3) → actions.inUse count, dialog stays open; clean confirm closes). Plus a combobox Storybook story.
283 tests pass (existing unchanged); typecheck/lint/build clean; check:size 90.2 KB gz; check:colors clean; no new dependency; no new i18n keys; no codename.
Out of scope → follow-up: the buildkit/Dockerfile CI migration (the robust fix for the resource-starved native runner; overlaps #25).
Done in merge `390f689`.
**Vendor split** (`vite.config.ts` → `build.rollupOptions.output.manualChunks`): framework deps now split into cache-stable chunks — `react` (react + react-dom + react-router + react-router-dom, one shared instance), `base-ui`, `query`, `i18n` — and the app entry chunk carries only app code. **Largest chunk dropped 216.5 → 90.2 KB gz** (budget 250). Note: used the *function form* of `manualChunks` (matches pnpm's `.pnpm/<pkg>@…` layout); the object form is unbuildable here because bare specifiers like `react-router` aren't root-resolvable under pnpm's strict store.
**Test-gap fills:** `prune-fields.test.ts` (localized single-lang + empty-pruning branches), `lib/labels.test.ts` (fallback chain), `lib/format-date.test.ts` (locale format + no tz day-shift + edges), `components/delete-confirm-dialog.test.tsx` (the delete-in-use flow: `InUseError(3)` → `actions.inUse` count, dialog stays open; clean confirm closes). Plus a `combobox` Storybook story.
283 tests pass (existing unchanged); typecheck/lint/build clean; check:size 90.2 KB gz; check:colors clean; no new dependency; no new i18n keys; no codename.
**Out of scope → follow-up:** the buildkit/Dockerfile CI migration (the robust fix for the resource-starved native runner; overlaps #25).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Severity: Medium. From a frontend deep audit, 2026-06-08. Performance headroom + a few targeted test gaps. The suite is otherwise healthy (175 tests, 0 skipped, strong selectors, parity test).
Problems
vite buildalready prints the >500 KB raw warning.vite.config.tshas nobuild.rollupOptions.output.manualChunks. The chunk is framework code (react-dom + react-router 7 + @tanstack/react-query + @base-ui/react + i18next + both locales) that rarely changes but invalidates on every app edit.components/delete-confirm-dialog.tsx— the delete-in-use flow is untested at the UI layer.InUseError → t("actions.inUse", {count})(:40) is only covered at the query layer (api/queries.test.ts); the dialog's rendering of the in-use message + blocked-delete branch has no.test.tsx.objects/prune-fields.ts— non-trivial pure transform tested only indirectly viaobject-form.test.tsx(localized single-lang filtering, empty/null pruning, nested maps). Ideal direct-unit-test candidate.lib/labels.ts+lib/format-date.ts— widely-used pure functions (label-fallback resolution, locale-aware date formatting) with no direct test.combobox(composed interactive primitive) lacks a visual/a11y story; alsoalert-dialog,drawer,label,skeleton,card.Suggested fix
manualChunksvendor split (e.g. react/react-dom/router together, @base-ui separately) — buys budget headroom + long-term cache stability for the cheapest effort.delete-confirm-dialog.test.tsx(InUseError path),prune-fields.test.ts, and direct tests forlabels/format-date.comboboxstory.Source: frontend deep audit (perf/testing dimension), 2026-06-08. Verified-good (no action): tree-shakeable lucide-react, heavy object-form already code-split, native Intl (no heavy date lib).
Done in merge
390f689.Vendor split (
vite.config.ts→build.rollupOptions.output.manualChunks): framework deps now split into cache-stable chunks —react(react + react-dom + react-router + react-router-dom, one shared instance),base-ui,query,i18n— and the app entry chunk carries only app code. Largest chunk dropped 216.5 → 90.2 KB gz (budget 250). Note: used the function form ofmanualChunks(matches pnpm's.pnpm/<pkg>@…layout); the object form is unbuildable here because bare specifiers likereact-routeraren't root-resolvable under pnpm's strict store.Test-gap fills:
prune-fields.test.ts(localized single-lang + empty-pruning branches),lib/labels.test.ts(fallback chain),lib/format-date.test.ts(locale format + no tz day-shift + edges),components/delete-confirm-dialog.test.tsx(the delete-in-use flow:InUseError(3)→actions.inUsecount, dialog stays open; clean confirm closes). Plus acomboboxStorybook story.283 tests pass (existing unchanged); typecheck/lint/build clean; check:size 90.2 KB gz; check:colors clean; no new dependency; no new i18n keys; no codename.
Out of scope → follow-up: the buildkit/Dockerfile CI migration (the robust fix for the resource-starved native runner; overlaps #25).