Ctrl K
ComunidadGuías…

PERFORMANCE_FINDINGS.md

Rama dev · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Homarr performance investigation

Started 2026-10-16. This is the single findings and progress ledger for this work. All measurements below are local and scoped; none is a whole-app or production performance claim.

## Scope and baseline

- Objective: investigate and fix meaningful performance costs across packages, caches, integrations, and especially Custom Widget rendering, request execution, editing, and authoring.
- Working branch: `feat/custom-widget-performance`.
- Baseline: `40341b56d` (`origin/dev`, refreshed before starting).
- Worktree: `/home/habs/.codex/worktrees/cw-performance/homarr`.
- Original checkout `/home/habs/work/homarr` remains on its existing `dev` commit; its pre-existing untracked `.codex/` directory is preserved.
- Existing startup/icon optimizations on current `dev` are part of the baseline, not gains attributed to this work.
- Workers use GPT-6.1 Sol with Extra High reasoning, as requested. File ownership is split to prevent concurrent edits.
- Runtime: Node 24.18.0 and Bun 1.4.2 through `mise exec`; existing dependency files are reused through worktree-local links, with workspace links pointing at this worktree.

## Completion requirements

| Requirement                                       | Status               | Evidence needed                                                                                                                         |
| ------------------------------------------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| Explore rendering/interpreter costs               | Implemented, checked | Session preparation, binding reuse, bounded helpers, analyzer pruning; JSX/runtime checks and browser probes                            |
| Explore server requests and response handling     | Implemented, checked | Direct bounded-byte parsing, JSON traversal; parsing benchmarks and focused policy/transport cases                                      |
| Explore widget client and editor responsiveness   | Implemented, checked | Lazy reference tree, stable projections, less formatting/serialization; actual editor/adapter probes                                    |
| Explore shared cache and integration costs        | Implemented, checked | Declared auth fast path, invocation-local reuse; native auth parity, real router counts, warm-cache revocation checks                   |
| Improve the Custom Widget authoring skill/harness | Implemented, checked | Corrected portable/embedded skill, smaller context, lazy search; resource parity, schema example, skill validator                       |
| Keep findings and speedups locally in one file    | Complete             | This ledger contains all findings, measurements, checks, limitations, and local evidence pointers                                       |
| Present architecture findings visually            | Written, opened      | `/tmp/architecture-review-20261016-custom-widgets.html`, before/after diagrams and recommendations                                      |
| Verify final integrated changes                   | Verified             | Focused checks, measurements, 27-file independent diff review; final architecture/lint/format gates; original checkout status preserved |

## Validation rules

No new test files unless requested. Run relevant existing checks only; no broad test suites, Docker compilation, or blanket E2E runs. Prefer reproducible focused measurements and behavioral checks. Distinguish local operation counts and microbenchmarks from user-visible whole-app speed, production memory, and deployed-image proof. Keep authentication, permission checks, credential isolation, request budgets, cancellation, ordering, freshness and invalidation intact.

## Implemented findings

Paths below are relative to this worktree. Comparisons use the baseline above; scripts and raw samples are listed under Evidence. Timings depend on workload, warmup, host contention and runtime; operation counts are the stronger general evidence.

| ID  | Trigger and affected implementation                                                                                                          | Before → after                                                                                                                                 | Evidence and practical limit                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| --- | -------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| F01 | Closed component reference while typing; `packages/custom-widgets/src/workbench/component-reference.tsx`                                     | Entire catalog/prop JSX constructed on each editor render → content constructed inside the existing dropdown mount seam                        | 36 real editor SSR renders: 11,952 prop resolutions → 0. Thirty timed 49,416-character JSX editor renders: 8,345 → 33.8 ms; identical SSR HTML. Synthetic component measurement, not typing latency in a full Homarr session. Search survives close/reopen.                                                                                                                                                                                                  |
| F02 | JSX/read-only editors; `workbench/code-editor.tsx`                                                                                           | Compute a formatted string that the active mode never uses → skip it; JSX format still uses CodeMirror indentation                             | Thirty read-only renders of a 2.17M-character pretty JSON stress payload: 222.8 → 38.8 ms. Across 36 renders, 36 redundant parse/stringify pairs → 0. Browser Undo/Redo, format, external updates and read-only behavior passed.                                                                                                                                                                                                                             |
| F03 | Response sample edits; `workbench/preview-response-panel.tsx`                                                                                | Pretty-print identical response on every render → memoize by response identity                                                                 | Browser counter stays 1 through parent rerender and editing; becomes 2 on changed sample. Invalid JSON rejected, valid JSON applied.                                                                                                                                                                                                                                                                                                                         |
| F04 | Hidden preview inspectors; management `_custom-widget-preview-panel.tsx`                                                                     | Serialize data and request journal while hidden → serialize only the active inspector                                                          | Source gate is tied to the selected existing tab. Relevant existing preview-panel checks passed; full Homarr preview/journal browsing was not exercised.                                                                                                                                                                                                                                                                                                     |
| F05 | Preview load responses; management `_custom-widget-form-utils.ts`                                                                            | Store full response both in `data[id]` and `status[id].data` → keep payload once and all other status metadata                                 | Synthetic serialized snapshot: 3,555,705 → 1,777,906 bytes. Thirty pretty serializations: 142.3 → 43.9 ms. Existing form utility checks passed.                                                                                                                                                                                                                                                                                                              |
| F06 | Request-body edits without identifier changes; management `_use-custom-widget-form-analysis.ts`                                              | Rerun JSX diagnostics with each request-object change → depend on the existing request-ID signature                                            | Eliminates analysis that only consumes request IDs; definition/schema analysis remains separate. Existing workbench/form checks passed.                                                                                                                                                                                                                                                                                                                      |
| F07 | Runtime input/status/options updates; `runtime/custom-jsx-renderer.tsx`, `jsx/interpreter.tsx`                                               | Reparse unchanged template → one parsed syntax tree per renderer session                                                                       | 300-element template: 2.357 → 1.264 ms per interpreter render in the local benchmark. Every evaluation still creates fresh bindings/environment, warnings, callbacks and execution budgets; no global syntax cache.                                                                                                                                                                                                                                          |
| F08 | Unchanged response during runtime updates; renderer and `packages/widgets/src/custom-api/custom-jsx-display.tsx`                             | Re-sanitize data and rebuild producer projections → memoize bindings and data/status projections independently                                 | Sanitizing the 2,000-row sample alone costs about 5 ms. Actual adapter + renderer DOM: initial + 20 stable parent renders, 21 → 1 binding calls; status/options-only updates, 1 → 0; real data replacement remains 1 → 1. Published overrides and scope clearing passed. Host translation/provider/component ports were stubbed.                                                                                                                             |
| F09 | Repeated formatted dates; `jsx/bindings.ts`                                                                                                  | Construct formatter for every row → 16-entry LRU for primitive locale + explicit timezone                                                      | 100-date template: 5.646 → 0.615 ms. Output/error parity checked across 105 locale/zone/date combinations; LRU eviction checked. Calls using the host's default timezone stay uncached.                                                                                                                                                                                                                                                                      |
| F10 | Authored `Array.from({length: ...})`; `jsx/bindings.ts`                                                                                      | Allocate/consume the entire input before slicing → enforce the existing 2,000-result cap before allocation/iteration                           | Billion-length template returns 2,000 in 5.4 ms, observed heap growth about 256 KiB. Unicode, numeric coercion errors, iterator closing checked. Intentional bounded semantics: infinite/oversized lengths now produce at most 2,000 values, and iterators stop at that cap.                                                                                                                                                                                 |
| F11 | Unknown component names; `jsx/analyzer-language.ts`                                                                                          | Full edit-distance matrix for every registered name → skip impossible length differences, lowercase once                                       | A 5,000-character unknown name: 380.662 → 0.0079 ms; ordinary `Tex`: 0.591 → 0.0315 ms. All 1,003 saved suggestion cases match exactly, including ranking/ties. Pathological input measurement, not ordinary authoring latency.                                                                                                                                                                                                                              |
| F12 | Oversized authoring/preview text; `jsx/analyzer.ts`, `core/custom-jsx-schema.ts`                                                             | Parse/analyze before rejecting length → reject before parser/analysis                                                                          | Direct analyzer accepts the 50,000-character boundary and rejects 50,001/7,000,000-character inputs immediately. Preview normalizes then applies aborting length checks before preparing syntax; invalid lengths never reach parent definition refinements. Manual probes of preview and stored schemas return validation errors for empty/50,001/7,000,000-character inputs and accept the 50,000 boundary without throwing. Existing schema checks passed. |
| F13 | Many load queries sharing an integration; API `widgets/custom-api.ts`, `custom-widget/source-resolver.ts`, `integration/integration-http.ts` | Repeat board access, membership, integration, credential setup and definition hashing → invocation-local reuse + membership subquery           | Actual router + in-memory SQLite + local HTTP, 20 successful queries: relevant reads 61 → 2; including unchanged item/definition reads, total SQL reads 63 → 4. Same counts cold and warm. Four queries: relevant reads 13 → 2; one: 4 → 2. Metadata ordering, logical request limits and cancellation checks retained. No general latency percentage claimed.                                                                                               |
| F14 | Generic declared integration authentication; `packages/integrations/src/base/creator.ts`                                                     | Import/construct full native client → use existing declared-auth implementation; native fallback on error                                      | All 33 kinds / 46 supported credential modes match native output. Thirty-three missing-credential errors also match. Warm Node benchmark, 11,500 calls: 2,309.3 → 117.8 ms (~19.6×). Session/adapter authentication stays native; this excludes network time.                                                                                                                                                                                                |
| F15 | Already buffered HTTP responses; `server/request-executor.ts`, `server/response.ts`                                                          | Response constructor copy + re-stream + full byte copy → bounded direct-byte decoder feeding shared parsing                                    | Removes up to two full-body byte copies (2 MiB transient copies at the 1 MiB response cap). Representative 100/1,000/4,000-record JSON arrays: 1.33–1.44× parser-path speedup on Bun. String payloads: 2.64–7.32×. Network, whole-process peak memory and production latency unmeasured.                                                                                                                                                                     |
| F16 | JSON payload budget traversal; `server/response.ts`                                                                                          | Allocate object-value arrays and callbacks for every node → iterate existing own values                                                        | Preserves node/depth limits on parsed JSON; measured with F15. UTF-8, compression-stage bounds, NDJSON, text fallback, redaction, status validation, HEAD and dispatcher cleanup remain intact.                                                                                                                                                                                                                                                              |
| F17 | Management list/get/migration metadata; API `custom-widget/management-{queries,query-mappers}.ts`                                            | Read unused encrypted secret columns/legacy relations → select only required presence/type/time metadata                                       | Return contracts preserved. Router/persistence checks and package typecheck passed; no byte/latency claim measured. Execution paths still read required secrets.                                                                                                                                                                                                                                                                                             |
| F18 | Every authoring context load; portable skill + `core/authoring-resources.ts`, `core/ai-prompt.ts`                                            | Preload uncommon prop/type details and repeated/conflicting rules → common-prop context, explicit conditional references, consistent lifecycle | Combined Assistant reference payload: 58,499 → 46,440 bytes (20.6% smaller); component reference 43,776 → 31,879; all 332 allowed names and complete lazy docs retained. Offline create prompt 12,000 → 9,952 bytes; Assistant prompt 11,996 → 10,954; lifecycle footer 3,855 → 2,123. These are UTF-8 bytes, not token or provider latency measurements.                                                                                                    |
| F19 | Component search/batch docs; `core/authoring-catalog.ts`, `core/authoring-resources.ts`                                                      | Rebuild static search text / resolve discarded prop documents → lazy index and direct compact projection                                       | Warm local search roughly 7× faster; batches 3–4×. All 475 catalog entries + aliases/missing cases and 483 queries at four limits match baseline outputs/ranking. No extra indexing cost when search is unused.                                                                                                                                                                                                                                              |

### Authoring quality corrections

- Portable and embedded skill/reference text now agree; the baseline had a runtime-reference mismatch.
- Persisted delivery reports the actual result concisely; a complete JSON artifact remains the fallback when tools are unavailable or the user asks for one.
- Removed blanket UTC guidance that conflicted with preserving the documented API timezone.
- Added conditional schema/runtime/security reference pointers and aligned pagination examples with actual manual parameters/defaults.
- The combined portable example passes the actual definition/JSX schema. Existing authoring checks pass without changing tests, including the two failures observed at baseline.
- This is an authoring-harness/source evaluation. No paid provider run, model-quality comparison, or actual tool-count reduction is claimed.

## Retained and deferred findings

| Candidate                                                   | Decision and evidence                                                                                                                                                                                                  |
| ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Parallel manual-source metadata with load requests          | Rejected: metadata shares the four-active-request item capacity and cannot wait; racing it against loads can turn previously successful metadata into `unavailable`. Preserve ordering.                                |
| Wider integration permission/credential caching             | Rejected: authorization must precede warm response-cache access. New maps end with one invocation; later invocations re-read database state. Revocation and cross-user denial were manually verified.                  |
| Connection/DNS pooling                                      | Deferred: per-request pinned addresses, TLS settings, credential isolation and deadlines need separate proof before changing dispatcher reuse.                                                                         |
| Pi-hole session reuse                                       | Deferred: generic HTTP currently lacks authentication-failure retry, so cached session expiry could change behavior. Adapter-owned auth remains native.                                                                |
| Redis/request-handler cache rewrites                        | No justified new change: current code already has bounded L1/cache expiry, generation reads/coalescing and lock renewal. Retain invalidation contracts. Small pub/sub serialization was not a demonstrated bottleneck. |
| Cross-request stored-definition/schema cache                | Deferred: returned definitions are mutable, and auth/secret/freshness boundaries make broad caching unsafe without a stronger interface.                                                                               |
| Renderer boundary serialization/hash                        | Retained: content-based keys drive equivalent-data error recovery. A cheaper identity-only key changes those semantics; no such substitution made.                                                                     |
| Plain versus input-bound runtime wrappers; emitter contexts | Deferred pending actual React profiling and markup proof. Avoid expanding the implementation merely to remove small allocations.                                                                                       |
| Splitting Mantine Core/Charts/Dates runtime imports         | Deferred: existing dynamic widget loading remains enforced; a larger component-loader redesign needs production bundle evidence.                                                                                       |

## Validation

No new or modified test files. No Docker builds, production builds, broad test suites, or blanket E2E runs. Counts below overlap; do not add them into a claimed distinct total.

| Check                                                                              | Result                                                                                                                                                     |
| ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Existing `jsx-policy.spec.ts`, `runtime.spec.tsx`                                  | 138 passed after final JSX/analyzer changes                                                                                                                |
| Existing `schema.spec.ts`                                                          | 57 passed; final schema + preview-authoring rerun passed 66 after aborting length failures before downstream refinements                                   |
| Existing server-policy, request-deadline, API Custom Widget request-executor files | 52 passed                                                                                                                                                  |
| Existing selected transport/compression/HEAD/redaction integration-request cases   | 14 passed                                                                                                                                                  |
| Existing integration HTTP auth coverage + integration request files                | 101 passed                                                                                                                                                 |
| Existing Custom Widget router + definition persistence files                       | 37 passed                                                                                                                                                  |
| Existing selected native integration authorization cases                           | 6 passed; 58 unrelated cases skipped                                                                                                                       |
| Existing workbench UI, preview panel and form utility files                        | 12 passed; UI-only final extraction rerun 4 passed                                                                                                         |
| Existing authoring-resources, ai-prompt and component-catalog files                | 17 passed; no assertion rewrites                                                                                                                           |
| Existing CustomJsxDisplay spec                                                     | 51 passed; 8 fail before rendering because referenced bundled seed fixtures are absent at baseline. Catalog and spec unchanged; recorded separately below. |
| Custom Widgets / integrations / API / widgets package typechecks                   | Passed; API requires the local resolution workaround described below                                                                                       |
| Skill-creator validator + portable/embedded parity + combined example              | Passed                                                                                                                                                     |
| Targeted oxlint/oxfmt and whitespace                                               | Passed for all 28 changed source/skill/ledger files in the combined gate                                                                                   |
| Independent Standards / Spec reviews                                               | No actionable findings in either axis across all 27 source/skill files, including final four-file delta                                                    |
| Architecture/dynamic-loading checker                                               | Passed: 195 production modules; dynamic renderer/editor loading contracts intact                                                                           |

### Focused browser and DOM proof

Real renderer/runtime/workbench source ran in a temporary Vite browser fixture; a separate DOM fixture exercised the actual CustomJsxDisplay adapter. Verified:

- Renderer updates on data/status/options; input registration; pagination resets; refresh; template errors recover after repair.
- Manual SubFetch loading, captured parameters, parameter changes hiding stale results, refresh, failure and retry.
- Response serialization reuse, invalid/valid sample edits, tree path/raw viewer.
- Real CodeMirror Undo/Redo, formatting, external prop updates, read-only rendering, schema tabs, unmount/remount cleanup.
- Mobile 390px rendering without horizontal overflow.
- Adapter publication override display and clearing when query scope changes.

The browser fixture stubs host transport/translation ports. It does not prove full-Homarr hydration, persistence, deployed images, or production performance. Its server/browser were stopped. Startup lazy dependency optimization needed a warm retry; browser clipboard-read permission and a blob-tab CDP cleanup issue limited those auxiliary probes, not the changed renderer paths.

### Baseline/environment limitations

- Eight existing display tests reference removed seed widgets such as `seed-dispatcharr`; those fixtures are absent in baseline `BUNDLED_CUSTOM_WIDGETS` and the unchanged test fails before rendering. The actual adapter/renderer DOM probe covers this change independently.
- Initial API typecheck hit undeclared `@homarr/auth/client` in existing `packages/modals-collection/src/apps/app-select-modal.tsx`. An ignored worktree-only `packages/modals-collection/node_modules/@homarr/auth` symlink to this worktree's auth package resolved validation. No manifest/lockfile or original checkout change was made; this underlying declaration issue remains outside the performance diff.
- Context7 monthly quota interrupted the Intl lookup. Official formatter/Zod documentation and installed Zod check definitions were used; `npx ctx7@latest login` or `CONTEXT7_API_KEY` provides higher limits. React and Acorn documentation lookups succeeded.
- SQLite router behavior was exercised; no live PostgreSQL run or external integration installation was used.

## Persistent artifacts and primary references

Saved visual report: `/home/habs/.codex/visualizations/2026/10/16/01a142fc-0fcf-7913-b52a-58d0534d3919/custom-widget-performance/architecture-review.html` (8 before/after cards, browser-verified). The adjacent `architecture-review.png` captures the report.

Raw evidence, temporary benchmark scripts/baselines and browser fixtures/captures are retained in the adjacent `evidence.tar.gz` (dependency symlinks excluded). Extract with `tar -xzf <archive> -C /tmp` to restore the temporary paths used below. The code remains in this isolated worktree.

Primary references consulted: [React useMemo](https://react.dev/reference/react/useMemo), [Acorn parser](https://github.com/acornjs/acorn/blob/master/acorn/README.md), [Undici Dispatcher](https://github.com/nodejs/undici/blob/main/docs/docs/api/Dispatcher.md), [Zod aborting checks](https://zod.dev/api#abort), and [Intl.DateTimeFormat specification](https://tc39.es/ecma402/#datetimeformat-objects). Installed implementation/types and focused runtime probes determine compatibility with this checkout's pinned versions.

## Evidence and reproduction

Run from this worktree with the pinned `mise exec` runtime. Temporary evidence is local and may be cleaned by the OS; the measurements and conclusions are retained in this ledger.

| Evidence                                  | Local artifact / command                                                                                                                                              |
| ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| JSX renderer, date, bounded-helper probes | `/tmp/homarr-jsx-perf.ts`, `/tmp/homarr-jsx-probe.ts`; `mise exec -- node --import tsx /tmp/homarr-jsx-perf.ts`                                                       |
| Suggestion parity                         | `/tmp/homarr-jsx-suggestions.ts`, `/tmp/homarr-jsx-suggestions-before.json`                                                                                           |
| Response parser comparison                | `/tmp/cw-server-performance.mts`, `/tmp/cw-server-performance-results.jsonl`; `mise exec -- bun /tmp/cw-server-performance.mts`                                       |
| Native authentication parity/timing       | `/tmp/homarr-auth-parity.mts`, `/tmp/homarr-auth-parity-final.log`; `mise exec -- node --import tsx /tmp/homarr-auth-parity.mts`                                      |
| Real router/database counts               | `/tmp/cw-api-orchestration-benchmark.mts`, `/tmp/cw-api-orchestration-{before,after}.jsonl`; `mise exec -- node --import tsx /tmp/cw-api-orchestration-benchmark.mts` |
| Authorization/limits/ordering probes      | `/tmp/cw-api-orchestration-validation.mts`, `/tmp/cw-api-orchestration-validation.jsonl`; `mise exec -- node --import tsx /tmp/cw-api-orchestration-validation.mts`   |
| Editor/snapshot/adapter measurements      | `/tmp/cw-client-performance/{editor-benchmark-final,snapshot-benchmark-results,adapter-benchmark-results}.jsonl`                                                      |
| Baseline display fixtures                 | `/tmp/cw-client-performance/display-fixture-baseline.json`                                                                                                            |
| Authoring bytes/parity/timing             | `/tmp/cw-authoring-context-metrics.ts`, `/tmp/cw-authoring-benchmark.ts`; `mise exec -- bun /tmp/cw-authoring-context-metrics.ts`                                     |
| Browser evidence and captures             | `/tmp/homarr-cw-browser-20261016/evidence.json`, `source-sha256.txt`, `runtime-success.png`, `runtime-error.png`, `runtime-mobile.png`, `response.png`, `editor.png`  |
| Architecture visuals                      | `/tmp/architecture-review-20261016-custom-widgets.html`                                                                                                               |

Relevant existing checks use explicit paths, for example:

```bash
mise exec -- node node_modules/vitest/vitest.mjs run --project custom-widgets-node packages/custom-widgets/src/test/jsx-policy.spec.ts packages/custom-widgets/src/test/runtime.spec.tsx
mise exec -- node node_modules/vitest/vitest.mjs run --project custom-widgets-node packages/custom-widgets/src/test/schema.spec.ts
mise exec -- bun x vitest run --project api-node packages/api/src/router/test/widgets/custom-api-v2.spec.ts packages/api/src/router/test/custom-widget/definition-persistence.spec.ts
mise exec -- node node_modules/typescript/bin/tsc --noEmit --incremental false -p packages/custom-widgets/tsconfig.json
mise exec -- bun x tsc --project packages/api/tsconfig.json --noEmit --incremental false --pretty false
mise exec -- node packages/custom-widgets/scripts/check-architecture.mjs
```

## Progress

- Refreshed the remote and isolated changes on current `origin/dev` without updating the user's checkout.
- Read repository/domain rules and the architecture, Custom Widget, skill-creation, and agent-writing guidance.
- Dispatched five independent investigations: JSX execution; server request/response work; client/editor work; shared cache/integrations; authoring skill and harness. Primary agent handles cross-package orchestration, additional findings, integration, and this ledger.
- Added a dedicated API worker, a focused browser worker, and independent Standards/Spec reviewers, all using the requested model/effort.
- Confirmed the original checkout remains on `dc2662d9f2eaabf9b7ba14693f8ddda8a56aeeff` (`dev`, behind the refreshed remote by 10) with only its pre-existing untracked `.codex/` directory.
- Implemented the findings above without adding dependencies or test files. Final combined format, lint, whitespace and architecture checks passed. Both independent review axes reported no actionable findings across all 27 source/skill files.

## Evidence limits

All reported gains are local source/operation-count/component/parser measurements. Do not combine ratios across stages, infer whole-app speed from them, or treat removed transient copies as measured whole-process RAM. No production system, provider-backed authoring evaluation, published image, or full-app browser acceptance has been exercised.

## Wave 2: app-wide performance and package reuse

Continued on 2026-10-16 from `40cda745e`, on the same isolated branch. User scope expanded to every app area, loading, shared UI reuse, and moving reusable behavior into Homarr packages. All twelve areas below were assigned to GPT-6.1 Sol / Extra High subagents; primary coordinates package manifests, review, evidence and this ledger. Completed: combined source checks, both review axes and focused browser lifecycle probes passed; implementation and evidence are finalized locally on this branch.

| Area                        | Owned paths                                                                             | Implementation and current evidence                                                                                                                                                                                                                                                                                                                           |
| --------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Shared UI foundations       | `packages/{ui,form,modals,notifications,settings}`                                      | MD5 leaf import; static Tabler icon; stable settings context; defer rich selector/flag content while retaining keyboard option shells. Actual Chromium keyboard/focus/ref/context parity passed; UI/settings typechecks passed.                                                                                                                               |
| Board rendering/layout      | Next board surfaces; `packages/boards`                                                  | Shared `@homarr/boards/layout-data` projections/types and minima; preserve unchanged placement identity; remove unused readiness provider. 25 parity fixtures, 16 existing checks passed.                                                                                                                                                                     |
| Management/forms/modals     | Next manage surfaces; `packages/{forms-collection,modals-collection}`                   | Move 10 access modules into public `@homarr/forms-collection/access`, migrate all five consumers; lazy selectors/tabs, icon picker, search integration controls; cache app sorting; independent user reads parallel. 21 existing checks and both package typechecks passed; actual moved-access Chromium lifecycle and combined Next.js source checks passed. |
| Native/custom widgets       | `packages/{widgets,custom-widgets}`                                                     | Shared Beszel time grid, skip hidden metric/table work, indexed Stats order, cached locale formatting, shared Speedtest sort, evaluation-local JSX helper context. 171 focused existing checks and both typechecks passed.                                                                                                                                    |
| Shell/auth/onboarding       | Next shell/header/onboarding routes; `packages/{onboarding,translation}`                | Lazy steps/interactive wordmark/confetti/sound, step-scoped RSC slots/board context, lazy Docker table, request-cached SEO settings, cancellable DOM tour waits. 16 checks and onboarding typecheck passed.                                                                                                                                                   |
| Assistant/Spotlight         | Next Assistant route/UI; `packages/spotlight`                                           | Bounded relevance buckets, normalize sources once, parallel independent owner-filtered DB reads. 10 existing checks, 480 catalog and 106 metadata parity fixtures passed.                                                                                                                                                                                     |
| API/data/auth               | `packages/{api,db,auth,validation}`                                                     | Batch media authorization, shared relational board access context, SQL group-membership subqueries. 77 existing checks, API/auth typechecks, SQLite revocation/parity, PostgreSQL query generation passed.                                                                                                                                                    |
| Integrations/request/cache  | `packages/{integrations,request-handler,redis}`                                         | Geometric Docker log buffering, dependency-ready Audiobookshelf requests, serialize persisted pub/sub once. 5 existing decoder checks, 1,317 parity fixtures, three typechecks passed.                                                                                                                                                                        |
| Infrastructure/common       | `packages/{common,core,icons,image-proxy,ping,docker,server-settings,definitions}`      | Index responsive grids, single-projection bestMatch/icon paths, native image UUIDs, release ping bodies. 31 common checks + 2 ping checks, package typechecks, algorithm parity, real local HTTP lifecycle probes passed.                                                                                                                                     |
| Background/Workshop         | Tasks/WebSocket/Workshop runtimes; cron/status, Workshop client, analytics/CLI packages | Single-statement session cleanup, checksum-only icon reads, auth-refresh single-flight, parallel detail reads and narrow summary/report fields. 13 checks plus Workshop/cron/tasks typechecks passed.                                                                                                                                                         |
| Docs/developer tools        | `apps/docs`, `tools/homarr-dev`, scripts                                                | Defer submission/detail code; skip repeated CLI log viewport parsing. 6 routing checks, existing sidebar checks, docs typecheck with image declaration setup passed.                                                                                                                                                                                          |
| Remaining Next features/API | Backup, integration, custom CSS/widget, Workshop surfaces; non-Assistant API routes     | Step-gated queries/forms, parallel invalidations, preserve intentional preview pacing, lazy thumbnails/SVG sanitizer, Buffer views, async unique-request backup compression, linear manifest merge. 11 focused existing checks passed; source typing plus two concurrent real SQLite export fixtures passed.                                                  |

### New measured findings

These are scoped synthetic/local fixtures. Timings vary with concurrent workers; deterministic call/read/allocation counts are preferred. None establishes production app load time or aggregate RAM savings.

| Finding                                     | Before → after                                                                         | Limits and evidence                                                                                                                                                     |
| ------------------------------------------- | -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Shared access ownership                     | 10 app-local modules → `@homarr/forms-collection/access`; 5 consumers migrated         | One maintained implementation for board/integration/user/group access. Public subpath + declared Tabler dependency. No app aliases remain in the package.               |
| Access picker work, 2,000 options           | Closed scans 2,000 → 0; common match scans 2,000 → 5                                   | Exact ordering/output parity; worst-case search still scans all. Rich option JSX limited to displayed rows.                                                             |
| Repeated app sorting, 8 searches            | 21,800 → 4,230 comparisons                                                             | Same selected/search output; sort memoized independently of search.                                                                                                     |
| Board projection/minima                     | 20,700 → 0 section comparisons; 7,200 → 3,600 layout comparisons                       | 200 containers/1,000 items; 25 exact geometry fixtures incl cycles/scrollable/missing layout. Cache tied to immutable board identity and layout.                        |
| Stable board placement                      | 1,000 → 0 copies for 1,000 unchanged placements                                        | Changed placements retain exact geometry.                                                                                                                               |
| Avatar MD5 dependency graph                 | 36 → 2 crypto modules; isolated minified 72,484 → 8,226 bytes; gzip 26,034 → 3,203     | Six hash/normalization parity samples. This is the isolated hash graph, not an app bundle.                                                                              |
| Runtime SVG parser                          | `svgson` + parser helper → existing Tabler static nodes                                | SSR and Chromium icon markup/ref parity. Unused parser dependency subtree removed from lockfile.                                                                        |
| Settings context                            | 21 → 1 consumer renders during 20 stable parent updates                                | Real Chromium fixture; changed settings still propagate.                                                                                                                |
| Hidden selector content                     | 100 → 0 custom option renders; 36 → 0 language option contents                         | Native option shells remain for first ArrowDown/Enter and ARIA. Rejected unmounting after a real first-key regression.                                                  |
| Conditional auth shell                      | Own-source static closure 80,137 → 4,119 bytes                                         | Package dependencies external; active interactive branch loads separately. Not Next production transfer proof.                                                          |
| Onboarding Welcome                          | Own-source static closure 127,869 → 8,357 bytes                                        | Step-specific chunks remain available; not total onboarding bytes. Optional board context skips 2 DB reads outside setup/finish.                                        |
| Spotlight, 10,000 entries                   | 3.81 → 1.15 ms                                                                         | Bounded exact/prefix/substring buckets; 480 parity cases incl ties/limits.                                                                                              |
| Assistant metadata, 100 source-heavy turns  | 13.52 → 8.24 ms                                                                        | 106 parity cases including callback ordering; no provider call.                                                                                                         |
| Media authorization, 60 integrations        | 144 → 1 SQL statements                                                                 | Same 36 accessible IDs; anonymous/owner/global access and immediate user/group grant revocation checked. Large inputs chunk at 500 boards; 1,100 board IDs → 3 queries. |
| Board/integration server access             | Board search 4 → 2 reads; shared board context 3 → 1; integration catalog/action 2 → 1 | Fresh relational permission reads, unchanged public contracts, no global auth cache. PostgreSQL SQL generation checked; live execution unverified.                      |
| Responsive grid, 100 sections/2,600 items   | 5.18 → 0.47 ms                                                                         | Shared common helper indexes membership once; small 26-item case unchanged around 0.006 ms.                                                                             |
| bestMatch, 25,000 icons                     | Name projections 99,995 → 25,000; 3.32 → 1.60 ms                                       | Existing helper, stable winner/ties.                                                                                                                                    |
| Icon repository, 25,000 paths               | Path parses 75,000 → 25,000; 13.47 → 7.39 ms                                           | GitHub/jsDelivr share the existing repository implementation.                                                                                                           |
| Image IDs                                   | 0.173 → 0.000248 ms per ID                                                             | Single registration adopts native UUID already used by bulk registration; opaque IDs, TTL/auth/encryption unchanged.                                                    |
| Infinite GET ping body, 250ms observation   | 400–416 KiB and open stream → 16 KiB and closed stream in about 2–5 ms                 | Real local HTTP/Undici fixture. GET/status/TLS/timing and 10-second no-header timeout unchanged; cleanup rejection handled.                                             |
| Fragmented Docker frame, 1MiB/1KiB chunks   | 538,443,784 → 3,143,688 copied bytes; 1,025 → 11 allocations; 71.44 → 0.67 ms          | 1,317 output parity cases incl raw/fragmented/oversize; 1MiB limit intact.                                                                                              |
| Audiobookshelf scheduling                   | 121.6 → 80.3 ms synthetic schedule                                                     | Same five requests and ordered output; library branch may overlap a later-failing sibling request.                                                                      |
| Persisted Redis publishing, 10,000 messages | 20,000 → 10,000 serializations                                                         | Identical SET-before-PUBLISH and identical payload bytes.                                                                                                               |
| Session cleanup, 20,000 sessions            | 2 → 1 queries; 46.91 → 13.89 ms                                                        | Same 10,000 removed; all providers enabled 2 → 0 queries. SQLite fixture, nine-run median.                                                                              |
| Icon refresh, 50,000 icons                  | 5 → 1 columns; 10,216,735 → 2,400,065 serialized bytes; 130.53 → 36.61 ms              | Actual SQLite fixture; no claim of full job/network speed.                                                                                                              |
| Workshop concurrent auth refresh            | 10 → 1 HTTP requests                                                                   | Same backend/token, pending promise removed after settlement; actual SDK with mocked transport.                                                                         |
| Workshop summary/report projection          | 1,214,091 → 8,643 fallback listing bytes; 1,221,007 → 6,751 moderation report bytes    | 24 fixture records with 50KB content; only fields consumed by summary/report mapping retained. Independent detail reads overlap.                                        |
| Deferred docs import graphs                 | Workshop listing 115 → 67 eager modules; generic 404 157 → 10                          | Workspace source graph, npm internals/tree-shaking excluded. No production bundle claim.                                                                                |
| CLI unchanged log content                   | 60.48 ms / 184 allocations → 13.7µs / 0 allocations                                    | Exact sidebar method, 2,000 lines / 432KB / 40-column soft wrap; resize invalidates reuse.                                                                              |
| Beszel chart preparation                    | 11 preparations → 2; 13.60 → 4.05 ms                                                   | 500-record/11-chart fixture; 20 scenarios × 11 datasets exactly match.                                                                                                  |
| Cached widget date formatting               | 30.71 → 1.90 ms / 1,000 calls                                                          | Reuses existing formatter in Speedtest/Umami/Wazuh; 520 exact locale/range/timestamp comparisons.                                                                       |
| JSX evaluation helper context               | 2.04 → 1.56 ms for 500 items                                                           | One context per evaluation rather than per node/callback; fresh budget/bindings/warnings preserved; 138 policy/runtime cases passed.                                    |
| Backup response preparation                 | One 32MiB TypedArray copy → view of existing bytes                                     | Framework Response may still copy; not a zero-copy full response claim. Async zip fixture preserves entries and allows event-loop heartbeat.                            |
| Version manifest merge                      | 1.74 → 0.92 ms; eager glob import 1 → 0                                                | Same 228 dependencies from 45 actual frozen manifests.                                                                                                                  |

### Additional shipped work without a separate latency claim

- Access permission option data is shared per provider; selected-user/group maps initialize lazily. Group/inherited panels mount on first visit and keep later drafts.
- Icon picker queries/results are deferred while closed or using a direct URL. Generic search-engine forms avoid integration queries and load their integration selector only when needed. Independent authorized user-settings reads run concurrently.
- Integration creation defers its form module and loads catalog/completion data only in their consuming steps. Four independent Custom Widget source invalidations run concurrently.
- Management and Workshop editors reuse one translated message adapter; Workshop JSON pretty-printing is memoized by definition identity. Preview/thumbnail images use native lazy loading; raster image requests avoid loading the SVG sanitizer.
- Beszel skips hidden Docker/GPU/disk work; Stats avoids table-row formatting in card mode and reuses parsed/indexed ordering; Speedtest shares its history sort. Content-based renderer error recovery is retained.
- Shared confetti defers its dependency and exits for reduced motion. Docker quick-access table loads on opening; SEO reuses request-cached settings. Tour observer cleanup covers route changes, stop and unmount.
- Workshop detail's two independent requests now overlap (mocked-SDK fixture88.87 → 42.56ms), with unchanged result schema. Concurrent refreshes coalesce only for the same backend/token and release the pending entry on settlement.

### Wave 2 integrated validation

- Independent Standards and Spec reviews found no actionable issues across all 87 tracked source diffs and 16 new files (before the ledger update). Final backup/language/ping deltas were independently re-read.
- Combined Next.js source typecheck passed with ignored standard Next/image references in this isolated worktree (generated route validators absent). Final combined format, lint, architecture (195 modules), whitespace, and frozen offline lockfile consistency checks passed. Existing lint warnings remain unchanged.
- Actual Chromium moved-access checks passed: opening fetch/loading/focus, owner/existing exclusions, bounded five-row results, email lookup beyond initial rows, expected save arguments and unsaved User/Group drafts across first-visit/Inherited tabs. Actual TourShell with real MutationObserver passed insertion/attribute waits, replacement/start=false/unmount cancellation, five-second timeout and input-aware keyboard behavior. Router/controller/transport ports were stubbed; full overlays and full-app persistence are outside this proof. Shared selectors/icon/settings also passed Chromium checks.
- No test sources added or modified. The original checkout remains unchanged; final source/artifact hashes and the local commit are recorded by the completion audit.

### Wave 2 validation details

Existing focused checks (counts overlap; do not sum): shared common31; board16; icon picker21; widget/date/Beszel33 + JSX policy/runtime138; onboarding16; Assistant metadata10; authorization/API77; Docker decoding5; ping2; Workshop13; docs routing6; backup/Workshop-feature11; Go CLI existing `TestSidebar*`. No broad suite, production/Docker build, or blanket E2E run.

Typechecks passed for UI, settings, boards through the app integration, forms collection, modals collection, widgets, Custom Widgets, onboarding, API, auth, integrations, request-handler, Redis, common, icons, image proxy, ping, Workshop, cron jobs, tasks, docs (temporary installed image declarations), and the combined Next.js source project. Unrelated baseline lint warnings remain, with zero new lint errors. The first-wave missing-seed display fixtures remain an explicitly recorded baseline limitation.

The package move/export/dependency changes were checked against frozen offline Bun1.4.2 lockfile resolution. Removing the static-icon parser also removes its unused dependency subtree. The combined Next.js source compiler exited0 with no diagnostics; its command/result are in `nextjs-typecheck-result.json`. The app source check uses only ignored standard Next/image declarations; no generated Next route validators or production bundles are claimed.

### Wave 2 evidence

Raw fixtures/results, source hashes and coverage notes are under `/tmp/homarr-perf-wave2/{shared-ui,boards,widgets,shell-onboarding,assistant-spotlight,api-auth,infrastructure-common,integrations-cache,background-workshop,docs-devtools,nextjs-features,browser}`; management uses `/tmp/homarr-perf-wave2/management-results.json`. Durable report is refreshed at the existing Tailscale URL; `evidence-wave2.tar.gz` retains fixture sources/results after integration. The assignment inventory covers all 34 current package manifests, all five app runtimes, and the developer CLI; this does not claim line-by-line review of every source file.

The configured keyless Mantine MCP server was invoked successfully through stdio. Its documentation calls currently return upstream HTTP404 for the requested core component JSON. Installed Mantine9.6.0 implementations/types and focused DOM/browser probes were used instead. Context7 monthly quota remains exhausted; no blind retry loop or dependency upgrade was used.

Wave 2 browser completion also verified actual OnboardingStudio module selection (Welcome then Finish; Account/Setup remained unloaded), Beszel all11 chart rendering and nonempty area paths, Docker/hidden/live/locale transitions, async access-submit locking, permission search and expected save arguments. The source fixture uses thin host ports, so it establishes component/lifecycle behavior rather than full Homarr deployment or persistence. Browser/fixture processes stopped; the requested report HTTP server remains running at `http://100.111.30.70:41816/architecture-review.html`.

Wave 2 durable evidence: `/home/habs/.codex/visualizations/2026/10/16/01a142fc-0fcf-7913-b52a-58d0534d3919/custom-widget-performance/evidence-wave2.tar.gz`. The adjacent report and `architecture-review.png` now include18 before/after pairs. All original checkout state remains preserved. No PR, push, production deployment, or production performance claim is part of this local delivery.

User correction (2026-10-16): backup migration preview pacing is intentional UI/UX. Restored the original 250ms applying phase + 100ms completion phase and per-migration success sound, exactly matching `40cda745e`. This is preserved behavior, not a claimed speedup. Future performance work must retain this pacing.

## Wave 3: Docker, CI, build caching, dependency patches, shared UI

Continued locally from `e4e2f4d73` on 2026-10-16. The user explicitly expanded scope to Docker base images, workflow removal/consolidation, build caching, Turbo, dependency upgrades and moving more reusable UI into packages. Five implementation agents and two independent reviewers covered these areas. No push, workflow dispatch, image publication or deployment is included.

### Before and after

| Area                                     | Before                                                                                          | After and evidence                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Container base                           | Alpine/musl production image                                                                    | Debian Trixie slim/glibc, Node 24.18.0; runtime omits npm/yarn and compilers. Real amd64 SQLite, CLI binding, sharp and bcrypt checks pass. This is a compatibility/support tradeoff, not an image-size reduction.                                                                                                                                                                                                                                       |
| Redis persistence across the base switch | Alpine Redis 8.8 writes RDB14; Debian's Redis 8.0.2 cannot read it                              | Retain official Redis 8.8 binaries on Debian; actual RDB14 read succeeds. Internal/external modes, protected mode, arbitrary UID/GID, `_FILE` handling and clean shutdown checked.                                                                                                                                                                                                                                                                       |
| Docker context                           | 40,592,748 bytes                                                                                | 30,245,120 bytes, down 10,347,628 bytes (25.49%). Runtime configuration is copied after the application build; a real nginx-only edit keeps install, application COPY and compile cached.                                                                                                                                                                                                                                                                |
| Workflow configuration                   | 22 workflows, 44 job definitions, 13 full-install call sites                                    | 17 workflows,35 jobs, 9 installs. Ordinary PR example saves 3 runners and 1 full install; publication saves 2 runners. These are graph counts, not measured Actions minutes.                                                                                                                                                                                                                                                                             |
| Required checks                          | `Fast gate`, `Check formatting`                                                                 | Exact live-required names preserved. Database selection/checks feed the CI gate; formatting shares planning setup. Nine failure/skip gate cases and nine database-selection cases pass.                                                                                                                                                                                                                                                                  |
| Environment-validation flag              | Toggling it invalidates 79 executable task hashes                                               | 74 lint/typecheck tasks and 2 pure bundles retain their hashes: 76 unnecessary invalidations removed. An intermediate pre-deferred-hashing probe changed only 3 Next build task hashes; final deferred hashes can also preserve the dependency stage. Empty transit tasks are excluded.                                                                                                                                                                  |
| Standalone dependency cache              | Application source changes repack dependencies                                                  | Turbo 2.11.8 deferred `dependencyOutputs` hashes a deterministic traced dependency manifest. Reuse requires that entire traced manifest remain unchanged. Source/public reuse is proven in a bounded fixture; the real Next traces include app source, so the final backup source edit correctly invalidates the real dependency artifact. Native bytes, paths, dependency source, environment files, architecture and glibc changes also invalidate it. |
| Warm-cache consistency                   | Manually changed installed native bytes could survive two cache hits and produce mixed bindings | Uncached final assembly validates current dependency bytes/paths/types against the compiled manifest before touching output. The reproduced mismatch now exits1, preserving the previous output; restoring bytes succeeds.                                                                                                                                                                                                                               |
| More shared UI                           | Five reusable modules owned by Next app folders                                                 | `NoResults` and `SectionCard` live in `@homarr/ui`; source setup, localized editor/messages live in `@homarr/forms-collection/custom-widgets`.217 lines moved; 31 consumer files use public exports.                                                                                                                                                                                                                                                     |
| Backup preview                           | Original animated migration steps                                                               | Intentionally preserved:250ms applying + 100ms completion and success sound per migration. The file exactly matches `40cda745e`; this is not a performance finding.                                                                                                                                                                                                                                                                                      |

### Dependency and toolchain patch set

| Dependency                 | Before             | After           |
| -------------------------- | ------------------ | --------------- |
| Next.js                    | 16.3.6             | 16.3.8          |
| React / React DOM          | 19.2.7             | 19.2.9          |
| Turbo / generator          | 2.11.7 catalog     | 2.11.8          |
| Bun                        | 1.4.2              | 1.4.3           |
| Direct Undici7 / scoped v8 | prior patched pins | 7.30.1 / 8.12.2 |

Versions were selected from current official registry/release/engine/peer information. Existing linked dependencies contained stale Turbo 2.10.4; only this isolated worktree's links were replaced with a fresh Bun 1.4.3 install (1,991 packages). The original checkout's dependencies were not changed. Actual installed versions, native binding probes, frozen offline lockfile consistency and Next.js source typecheck passed. Existing `@homarr/auth` usage is now declared in the modals package; the new forms subpath and its Custom Widgets dependency are declared.

Keep Node 24.18.0, Mantine 9.6.0, SQLite 12.11.1 and the Assistant/AI cohort. Major upgrades need their own migration scope. Both Undici versions pass 13 real local HTTP lifecycle/deadline cases each. Release-note fixes do not imply measured whole-app speedups.

### Cache behavior and native archives

The platform wrapper derives operating system, architecture, libc **version**, and Node. Host Ubuntu glibc2.39 and Docker Debian glibc2.41 cannot share native artifacts. It preserves explicit overrides, process arguments, inherited stdio, exit codes and signals. BuildKit cache identifiers also include architecture, libc, Node and Bun. `NEXT_SERVER_ACTIONS_ENCRYPTION_KEY` participates in compile hashing. Formatting/lint fix scripts force execution so a previous mutating-task cache hit cannot skip repairing a reintroduced input.

Irrelevant Markdown no longer invalidates source lint/typecheck/transit tasks; docs MDX still invalidates docs. The real Next NFT manifest includes 776 raw app files, with 129 traced files previously excluded from compile hashing, including README/spec files and all three packaging helpers. Final compile-input coverage is 776/776 with zero gaps. Mutating the real builder's README or spec file reproduced an assembly rejection before this correction. Restored all default app compile inputs so those edits cannot produce a false manifest mismatch after warm compilation. Packaging helpers remain compile inputs; avoiding that requires a separate tracing change. All 29 bounded scenarios executed through real Turbo pass (the original 14 plus README/spec/helper edit, expired-dependency and restoration cases), including cold/warm, source/public changes, native bytes/new trace paths, dependency source, `.env`, architecture/glibc, server-action key, deleting all generated artifacts, and expired dependency artifacts. The additional both-cache-hit mutation rejection is recorded separately. Remote cache transport was not enabled for the local builds. The real full app includes source files in its external NFT traces; do not infer actual dependency-artifact cache hits for ordinary app edits from the bounded fixture.

Both Alpine and Debian release asset names remain supported. Switching the production image to glibc exposed an old extraction assumption: labeling the direct glibc tree Alpine fails in a real Alpine container. Extraction now detects source CPU/libc, copies from a stopped container, builds only the opposite SQLite binding, replaces both app/CLI bindings, and validates SQLite, sharp and bcrypt before upload. The current trace includes both sharp/libvips libc variants. Legacy Alpine-image and inverse-Debian fixtures both pass native amd64 execution. nginx's custom writable PID location is supplied only by the container command; exported nginx configuration retains its distro-default PID behavior.

### Focused validation and limits

- Fresh upgraded graph: 190 existing checks pass across five explicit JSX policy/runtime, server policy/deadline and API request-executor files. No test sources were added or modified.
- Shared UI/forms typechecks pass; 14 SSR fixtures match the prior implementations. 12 cold Chromium lifecycle checks pass for permission filtering, loading/errors, callbacks, locale, CodeMirror editing/undo/redo, with no browser errors. Thin transport/translation adapters were used.
- Workflow YAML/dependency/action-reference/trigger checks, Bash syntax, maintenance-script byte parity without node_modules, native helper builds and actionlint pass. Actionlint suppresses only verified stale `create-github-app-token@v3` metadata diagnostics; official action inputs were checked.
- Initial full current application candidate built in 204.54s; a fully warm rerun took 3.09s. A runtime-only nginx change took 3.36s with application/install layers cached. These are local wall times, not a before/after speed ratio.
- That full candidate passed fresh/internal Redis, persisted arbitrary UID/GID, and external Redis runtime cells: ready/live HTTP 200, 41 SQLite tables, app/CLI native bindings, sharp/bcrypt, CLI help and SIGTERM. The final UX/PID/cache-guard source refresh is validated separately below.
- Native-only fixture size increases 230,116,970 → 297,552,334 uncompressed bytes (+67,435,364). The initial full image is 575,050,524 bytes; no equivalent baseline full image size was measured.
- Independent Standards and Spec reviews report no actionable findings, including the final backup restoration, assembly guard, container-only PID override and release script changes.

Only amd64 executes locally. ARM64 base manifests and architecture-specific workflow paths were checked; ARM64 runtime, live Actions publication/cache behavior, and production acceptance remain unverified. Documentation retrieval hit the Context7 monthly quota; installed matching Turbo docs and official primary sources were used. Focused final lint has zero errors and two sorting warnings (the existing certificate page and deterministic dependency-manifest ordering). No tests or builds outside the relevant expanded scope were run.

Wave 3 raw evidence is under `/tmp/homarr-perf-wave3/{docker,turbo,workflows,dependencies,ui-packages}`. The guard measured against a full application builder checks 3,854 external files / 84,808,365 bytes in 129.9 / 101.1 / 132.0 ms across three runs. Mutating the actual installed SQLite binding causes exit 1 before changing the existing standalone directory inode/mtime or native bytes. Restoring the binding allows assembly to finish with matching bytes. `turbo/real-builder-guard-proof.json` records this proof. Final image, archive, report/browser and completion records follow after the source freeze.

### Wave 3 final source and image acceptance

The exact final source image is `homarr:performance-debian-candidate`, ID `sha256:a6ef628a4576d49262575041a43080bd8ec728f9cb7e02fba77ab017ffb466e5`, 575,050,731 uncompressed bytes. It is local and unpublished (`RepoDigests: []`). The final source build completed in 106.35s. An unchanged build took 2.06s, all 23 workdir/run/copy instructions cached, and returned the same image ID. The Next compile/dependency stages missed during the source refresh; no real app-source dependency-artifact hit is claimed. Intermediate ENOSPC attempts and scoped cleanup logs are retained; only this task's identified caches and superseded extracted artifacts were removed.

All three exact-final-image runtime cells pass: root/internal Redis (3.900s to ready), UID 1234/GID 2345 on the persisted volume (2.807s), root/external Redis (2.291s). Each returns ready/live HTTP 200, retains 41 SQLite tables, executes app/CLI SQLite bindings, bcrypt, sharp and CLI help, has a live writable PID file, and stops cleanly on SIGTERM. Redis persistence/protected mode and no internal Redis process in external mode are verified. These startup times are local observations, not production page-load measurements.

Exact final image extraction also passes native Node 24.18.0 amd64 execution for both archive variants: Debian 84,026,525 bytes and Alpine 84,256,163 bytes. Each contains 10,621 root-owned entries; SQLite app/CLI, sharp PNG and bcrypt pass. Both exported nginx configurations match the portable baseline with no PID directive. Immutable image IDs, archive hashes and source snapshots are in `workflows/final-candidate-archive-manifests.json`.

Final source assertions include root manifest SHA256 `453c80b8e71f97f4fd7426e019947a06d8b7649cbce84edfc47a7cd0d87d15cc`, corrected Next Turbo config `9f7214898367c5fb5345fef4f0acc6f5f3839ac2c1a925a4774cc5d41d1dfb7a`, and restored backup hook `b7d8a4ddaafca0bec175a6f6c910fa18c266669d61839788e71e6c9e7042b20c`. The hook byte-matches `40cda745e`. All changed source hashes and deleted paths are saved in `final-source-manifest.json`; no test sources changed.

The live report now has 10 plain-language TLDR rows, 23 technical before/after pairs and a six-node diagram. Actual Chromium at 1440px and 390px verifies readable grids, no horizontal overflow, working anchors and the intentional backup pacing/sounds note. The same HTTP server remains running at `http://100.111.30.70:41816/architecture-review.html`. Durable evidence is `evidence-wave3.tar.gz` in the served report directory; final local commit/worktree checks are stored in its completion manifest. Original checkout remains `dc2662d9f2eaabf9b7ba14693f8ddda8a56aeeff` with only its pre-existing untracked `.codex/` directory. No push, PR, workflow dispatch, upload or production deployment occurred.

## Wave 4: shared UI architecture and translation ownership

Implemented the user-selected architecture improvements from the read-only audit at `ca3d6d62a`, on the same isolated branch. The user explicitly authorized implementation across candidates and common translation consolidation, overriding the architecture skill's interactive selection pause. The root glossary and ADR0001 were read; no persistence/permission decision was changed. No new dependencies, test files, workflows, Docker builds or production deployments were added.

### Shared modules and real adapters

| Area                | Before                                                                                                | Implemented result                                                                                                                                                                                                                               |
| ------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Board appearance    | Board settings and Assistant independently assemble colors, corners and opacity                       | One `BoardAppearanceFields` module in forms-collection, two adapters. It owns translated fields, swatches, clearing and opacity presentation; form state, lock policy, preview and saving remain explicit.                                       |
| Corner styles       | Five independent value declarations, a further Assistant option list and three translated choice maps | One definitions-owned tuple/type; four validators share it. Picker owns one common namespace. UI/branding exports remain compatible aliases. Board invalid-input issue arrays, optional behavior, JSON schema and inferred types match baseline. |
| Color scheme        | Server settings rebuild icons/options already owned by shared UI                                      | Server settings use `ColorSchemeCombobox`, alongside onboarding/user preferences. Shared field supports form metadata and merges caller helper IDs with Mantine-generated error/description IDs.                                                 |
| Management layout   | 14 pages repeat title/breadcrumb/container assembly                                                   | All 14 pages / 15 render branches adopt `ManagePageLayout`. Three existing frame variants, widths, custom titles, breadcrumb mappings and the Kubernetes context selector are preserved.                                                         |
| Unsaved changes     | Existing shared bar plus two group-management copies                                                  | One bar serves four flows. Optional visibility preserves the group slide-up animations; callbacks/permissions/dirty state stay in their adapters. Default markup/dimensions match baseline under Homarr's theme.                                 |
| Password fields     | Invite registration duplicates the existing password pair                                             | Invite and create-user use `UserCreatePasswordFields`; ids/names/autocomplete/requirements/validation and md/lg spacing are preserved.                                                                                                           |
| Widget presentation | Six contextual empty views plus duplicated Tdarr panel tables                                         | Six views use the existing `WidgetEmptyState` with a message; its 43 default sites remain unchanged. One local Tdarr table module owns empty/scroll/header/cell presentation; columns, ETA/progress and tiny mode remain specific.               |
| Wazuh query policy  | Five identical minute freshness/polling objects                                                       | One feature-owned options constant; all 11 inspected queries retain their previous effective settings.                                                                                                                                           |
| Theme adoption      | 95 native Card/Paper props repeat the current border default                                          | 69 props removed across 41 files; 26 explicit contracts retained. Warning/selection/preview/accent borders and the five portable Custom Widget workbench borders remain explicit. Card.Section and authored JSX are untouched.                   |

Shared defaults continue to live in the theme; shared presentation and field behavior live in their deepest owning modules. Authentication, mutations, navigation and feature state remain in their adapters. No universal form/table engine or artificial common abstraction was introduced.

### Translation audit and consolidation

| Measurement                    |     Before |      After |
| ------------------------------ | ---------: | ---------: |
| English leaf keys              |      4,686 |      4,615 |
| Keys per locale (36 catalogs)  |      4,686 |      4,615 |
| Stored locale entries          |    168,696 |    166,140 |
| English source bytes           |    314,196 |    311,258 |
| All locale source bytes        | 12,312,887 | 12,191,072 |
| Extra identical English copies |        620 |        557 |
| Strict ICU parser errors       |         28 |          0 |

88 retired leaves are replaced by 17 canonical leaves, removing 71 keys per locale and 2,556 stored entries overall. The catalogs shrink 121,815 bytes. The English serialized dictionary shrinks 221,549 → 219,898 bytes. These are source/dictionary measurements, not measured page transfer, process RAM or whole-app speed improvements.

Standalone field headings and ordinary actions now use common namespaces; downloads and Docker use explicit typed label maps for dynamic column/sort choices. All 15 download columns and 12 sort options are preserved. Caller titles, warning bodies, named accessibility actions and destructive migration confirmations remain contextual.

Examples: `Save user permission`, `Save group permission`, `Save configuration` and `Save API configuration` use common `Save`; `Cancel import` uses `Cancel`; ordinary `Import widget` uses `Import`. The legacy replacement confirmation remains explicit.

The semantic audit corrected generic Name labels that said Job name in 33 human locale catalogs, generic Source labels previously copied as Integration, and the Swiss German operational State wording. Existing same-locale translations provide provenance; two Finnish corrections are explicitly reviewed localized copy (Lähde/Tuo). Existing Crowdin live-translation tokens are preserved.

28 malformed/corrupted messages in 18 locales are repaired: eight path-help messages escape literal option/parameter tokens, 16 shortcut messages replace corrupt unknown tokens with the command symbol, three Japanese labels are restored, and a Korean action loses trailing garbage. The original no-argument production path returned raw strings without error callbacks; forced formatting exposed28 errors. Repaired plain and forced-format output both match expected text with zero errors. 159,464 final nonblank messages pass the actual ICU parser; retained argument/plural/tag signatures are unchanged.

No keys were removed merely because grep found no use. The audit records static calls, typed namespace helpers and dynamic label maps; all retained and retired keys are checked against the final catalogs. 684 provenance records document canonical values and repairs. All 69 widget kinds have corresponding catalog namespaces; the five additional widget namespaces are used shared family/common namespaces, not deletion candidates.

### Validation and limits

- Six relevant TypeScript projects pass with no diagnostics: definitions, translation, UI, forms-collection, widgets and combined Next.js source. No app production build or generated-route-validator acceptance is claimed.
- Changed-source formatting, lint and whitespace checks pass. Existing unrelated lint warnings remain; new unused hooks and memo dependencies from the migration were fixed.
- Existing focused run: 226 passed, 8 failed across 10 explicit files. The eight failures require bundled integration seed IDs absent from the unchanged baseline fixture list; test and bundled fixture sources byte-match `ca3d6d62a`. Evidence: `baseline-test-failures.json`. No test sources are added, changed or disabled in the final diff.
- Manual checks cover 14 page contracts, eight layout/bar SSR cases, appearance/radius/schema contracts, all 36 catalogs, and real Chromium controls with actual Homarr theme and real Mantine form state. Browser ports for transport/router/notifications are local fixtures, not full server or persistence acceptance.
- Chromium verifies pointer/keyboard color/corner/scheme/opacity behavior, primary lock, icon clearing, focus/blur, linked errors/helper IDs, invite mismatch/submission/pending state, exact default save-bar DOM/layout and optional 250ms transitions. A theme override proves newly inherited borders follow the central default.
- Independent Standards and Spec reviews find no remaining actionable findings. Final localized copy, explicit dynamic maps and ARIA helper-ID handling were rechecked.
- The first translation codemod used an unsafe inherited-key lookup and touched unrelated literals. Review rejected it before delivery. All 12 affected files and three specs were restored byte-for-byte; the codemod now uses Map and resolved translation calls with a negative-literal probe. Failed-pass evidence and repair hashes are retained outside the repository.
- Backup preview's intentional 250ms+100ms pacing and per-step success sound remain byte-identical to the prior reference. No application runtime security policy or integration error handling changed.

The architecture grade is an editorial assessment of shared UI ownership/adoption, not a runtime or security score: 7.5 → 8.5/10 for this scope. The remaining distinctions between management tables, compact widget tables, field descriptions and feature workflows are intentional. No claim of eliminating every similar-looking line is made.

Wave 4 evidence: `/tmp/homarr-perf-wave4`. Durable report/evidence is served at `http://100.111.30.70:41816/architecture-improvements.html`. Its report metadata identifies the fresh absolute temporary HTML path. The original checkout remains untouched; source hashes, local commit and final state are captured in the completion manifest. The prior Docker image acceptance belongs to `ca3d6d62a`; this UI/translation pass has source, focused-check and component-browser evidence only.