J151: account model and status rows load on demand (critical -5 KB) #330

Closed
opened 2026-11-03 18:01:10 +00:00 by kayg · 2 comments
Owner

J151: load the account model and account status rows on demand (critical class back down ~5 KB).

Related: #322 (deferred/on-demand budgets, J128), #224 (J126, account model; its static import of ./account/model put ~5 KB gzip into the CRITICAL class). Decision: D188 (critical / deferred / on-demand classes).

Problem. apps/tracer/src/canvas/product.ts statically imports ./account/model (identityModel) and the account status rows. Critical is 320,297 of 327,680 B gzip on dev; it was about 315,040 before J126.

Task. Load both on demand when the person card or Settings -> Account first opens, with an idle preload like J128's. Critical down by about 5 KB, nothing moves into deferred. First use must not be visibly slower (extend test/on-demand-first-use.spec.ts). A press on the person pill before the chunk arrives opens the card once mounted.

Every importer of an on-demand module must itself be on demand (J128's gotcha).

J151: load the account model and account status rows on demand (critical class back down ~5 KB). Related: #322 (deferred/on-demand budgets, J128), #224 (J126, account model; its static import of `./account/model` put ~5 KB gzip into the CRITICAL class). Decision: D188 (critical / deferred / on-demand classes). **Problem.** `apps/tracer/src/canvas/product.ts` statically imports `./account/model` (`identityModel`) and the account status rows. Critical is 320,297 of 327,680 B gzip on dev; it was about 315,040 before J126. **Task.** Load both on demand when the person card or Settings -> Account first opens, with an idle preload like J128's. Critical down by about 5 KB, nothing moves into deferred. First use must not be visibly slower (extend `test/on-demand-first-use.spec.ts`). A press on the person pill before the chunk arrives opens the card once mounted. Every importer of an on-demand module must itself be on demand (J128's gotcha).
Author
Owner

Finish: head 311e7bfa864caa3f958e850623607f7e605a4a7c, branch account-on-demand-j151, base origin/dev e81eb5bb4, 3 commits. Pushed, not merged. Related: #322, #224.

Finding (changes the premise). The account model and status rows were never in the critical class. product.ts is a deferred root, so they sat in deferred (the chunk with "Follow the passkey prompts" is deferred on dev). The critical bytes were the card mount account/index.ts: chunk-classes.ts seeds every dynamically imported module not named *.on-demand.ts as a critical entry, with everything only it reaches. I did both: model + rows to account/session.on-demand.ts, and account/index.ts renamed account/mount.on-demand.ts (plus mock/account/index.ts renamed too, J128's gotcha: it imports the mount).

gzip / brotli dev e81eb5bb4 this head change
critical (cap 327,680 / 273,408) 320,523 / 267,629 318,140 / 265,741 -2,383 / -1,888
deferred (cap 61,440 / 55,296) 54,594 / 48,570 54,302 / 48,241 -292 / -329
on-demand largest chunk (cap 20,480 / 18,432) 16,219 / 14,418 16,216 / 14,383 -3 / -35

The task estimated about 5 KB; the account code was 2.4 KB gzip. The rest of critical's growth since J126 (315,040 -> 320,523) is not account code. Nothing moved into deferred. No account module is left in critical (checked by marker strings in the built chunks).

First use (test/on-demand-first-use.spec.ts, 3 new tests, production build on compute01, 300 ms latency proxy; logged, not asserted):

  • person pill pressed before the account chunks arrive: the card is not open and the old menu does not open; 2,115 ms after the held transfer starts the card is open (this includes building the card's own panel chunk + styles).
  • Settings -> Account opened first: rows hidden while the chunk is out, both rows drawn 940 ms after the transfer starts.
  • idle: both chunks requested ~4.08 s after navigation start, arrived 4.97 s (mount) and 5.25 s (model). The two are fetched in parallel (Promise.all), so there is no added serial hop before the card. I did not run a before-change timing of the early press on dev; no extra round trip was added, but that is reasoning, not a measurement.

Browser specs (compute01): first-use + account-summary + account-card + account-captures, 39 of 39 pass.

Gate (compute01, scripts/verify fast, VERIFY_EXIT=0, head 311e7bfa8):

| Rust gate                 | Result       |
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| SSH runtime test helper   | PASS         |
| real-binary fixture paths | PASS         |
| test                      | PASS         |
| SSH inode reuse fixture   | PASS         |
| shim process-per-user     | PASS         |
| cargo-deny                | PASS         |
| gate architecture         | PASS         |
| static builds             | PASS         |
JavaScript transfer, critical: identity=1022293 gzip=318140/327680 brotli=265741/273408 bytes
JavaScript transfer, deferred: identity=152196 gzip=54302/61440 brotli=48241/55296 bytes
JavaScript transfer, onDemand: identity=397614 gzip=158728/20480 brotli=141125/18432 bytes
JavaScript transfer, onDemand largest chunk chunk-yx9nemv9.js: gzip=16216/20480 brotli=14383/18432 bytes (class total gzip=158728 brotli=141125, not limited)
VERIFY_EXIT=0

Not done: no test-server run (no server change; the product path was exercised with the preview server's proto=product).

**Finish: head `311e7bfa864caa3f958e850623607f7e605a4a7c`**, branch `account-on-demand-j151`, base `origin/dev` e81eb5bb4, 3 commits. Pushed, not merged. Related: #322, #224. **Finding (changes the premise).** The account model and status rows were never in the critical class. `product.ts` is a deferred root, so they sat in *deferred* (the chunk with "Follow the passkey prompts" is deferred on dev). The critical bytes were the card mount `account/index.ts`: `chunk-classes.ts` seeds every dynamically imported module not named `*.on-demand.ts` as a critical entry, with everything only it reaches. I did both: model + rows to `account/session.on-demand.ts`, and `account/index.ts` renamed `account/mount.on-demand.ts` (plus `mock/account/index.ts` renamed too, J128's gotcha: it imports the mount). | gzip / brotli | dev e81eb5bb4 | this head | change | |---|---|---|---| | critical (cap 327,680 / 273,408) | 320,523 / 267,629 | 318,140 / 265,741 | **-2,383 / -1,888** | | deferred (cap 61,440 / 55,296) | 54,594 / 48,570 | 54,302 / 48,241 | -292 / -329 | | on-demand largest chunk (cap 20,480 / 18,432) | 16,219 / 14,418 | 16,216 / 14,383 | -3 / -35 | The task estimated about 5 KB; the account code was 2.4 KB gzip. The rest of critical's growth since J126 (315,040 -> 320,523) is not account code. Nothing moved into deferred. No account module is left in critical (checked by marker strings in the built chunks). **First use** (`test/on-demand-first-use.spec.ts`, 3 new tests, production build on compute01, 300 ms latency proxy; logged, not asserted): - person pill pressed before the account chunks arrive: the card is not open and the old menu does not open; 2,115 ms after the held transfer starts the card is open (this includes building the card's own panel chunk + styles). - Settings -> Account opened first: rows hidden while the chunk is out, both rows drawn 940 ms after the transfer starts. - idle: both chunks requested ~4.08 s after navigation start, arrived 4.97 s (mount) and 5.25 s (model). The two are fetched in parallel (`Promise.all`), so there is no added serial hop before the card. I did not run a before-change timing of the early press on dev; no extra round trip was added, but that is reasoning, not a measurement. Browser specs (compute01): first-use + account-summary + account-card + account-captures, 39 of 39 pass. **Gate** (compute01, `scripts/verify fast`, `VERIFY_EXIT=0`, head 311e7bfa8): ``` | Rust gate | Result | | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | SSH runtime test helper | PASS | | real-binary fixture paths | PASS | | test | PASS | | SSH inode reuse fixture | PASS | | shim process-per-user | PASS | | cargo-deny | PASS | | gate architecture | PASS | | static builds | PASS | JavaScript transfer, critical: identity=1022293 gzip=318140/327680 brotli=265741/273408 bytes JavaScript transfer, deferred: identity=152196 gzip=54302/61440 brotli=48241/55296 bytes JavaScript transfer, onDemand: identity=397614 gzip=158728/20480 brotli=141125/18432 bytes JavaScript transfer, onDemand largest chunk chunk-yx9nemv9.js: gzip=16216/20480 brotli=14383/18432 bytes (class total gzip=158728 brotli=141125, not limited) VERIFY_EXIT=0 ``` Not done: no test-server run (no server change; the product path was exercised with the preview server's `proto=product`).
Author
Owner

J210 owner-authorized housekeeping: closing this completed scope because its work is merged on dev in fa7ec56f6. Verified the merge commit is an ancestor of current origin/dev. The implementation reports and evidence remain in this issue.

J210 owner-authorized housekeeping: closing this completed scope because its work is merged on dev in [fa7ec56f6](https://git.kayg.org/kayg/infraternal/commit/fa7ec56f619e2efb5193eb63bc0cdf46ec90317e). Verified the merge commit is an ancestor of current origin/dev. The implementation reports and evidence remain in this issue.
kayg closed this issue 2026-11-04 17:04:49 +00:00
Sign in to join this conversation.
No labels
launch-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/infraternal#330
No description provided.