PERF: bound Calendar drag geometry reads and snap candidate lookup (#663) #751

Open
opened 2026-10-02 13:08:54 +00:00 by kayg · 10 comments
Owner

Parent: #663. Related: #669 (Calendar adoption), #536 (snap behavior), #612 (ghost), #608 (hover), #714 (snap correctness). Preserve those decisions and fixes. This is a pointer-path complexity finding, not evidence of forced reflow or a measured latency violation.

Source
origin/dev c4a61e8cf0. TimeGrid is unchanged on merge-round-7a 2f4482ded0. The geometry loop remains on queued dragghost-612 bc08062b16.

  • packages/ui/src/components/calendar/TimeGrid.svelte:936–942: columnDateAt queries rendered columns and reads each rectangle until it finds the target.
  • :1035–1047 and :1112–1124: each move event calls it and reads the source column height again. The handlers are not coalesced to one frame.
  • packages/ui/src/components/calendar/snap.ts:54–68: each snap scans every item edge, including after an exact match is found. Move snapping can resolve both start and end. snapEdges is correctly precomputed in TimeGrid:190–195; do not move candidate construction onto the pointer path.

Reasoned and counted impact
The pointer path is O(rendered columns + same-day item edges) per event. Production resolveTimeSnap was called directly with instrumented iterators: 100/1,000/10,000 edges produced exactly 100/1,000/10,000 edge visits per snap. This is an operation count, not browser timing. Geometry reads may force layout if styles are dirty, but no forced-layout claim is made without a trace. Existing preview equality guards and narrow per-day preview props already avoid rebuilding the overlap layout on every drag.

Concrete fix
Reuse the uniform-column geometry already held by TimeGrid, or capture rendered rectangles and hour scale once per drag. Invalidate only on real scroll, resize or zoom. Coalesce pointer movement to the latest sample per animation frame. Build sorted per-day edge candidates when day data changes, then search only candidates inside the magnetic radius. Preserve deterministic ties, exclusion of the moving item, item > Now > grid priority, Alt bypass, overnight ranges and all input modes. Avoid runtime measurement for alignment.

Acceptance tests
Instrument geometry and resolver visits across a long drag: counts must stay bounded per painted frame instead of growing with all columns/edges. Add resolver equivalence tests for equal-distance ties, exclusion, nearest edges, Now/grid priority and Alt. Extend the existing drag-snap and Calendar render profiles with dense days plus high-rate pointer input. Capture production drag traces before claiming forced-layout or frame-budget improvement. Keep #714 assertions; do not weaken snap expectations.

Duplicate search
Searched all issue titles for Calendar drag, snap, hover and performance. #608 covers hover intent and #612 covers ghost appearance; neither covers drag geometry and edge lookup work. No product edits were made in the audit.

Parent: #663. Related: #669 (Calendar adoption), #536 (snap behavior), #612 (ghost), #608 (hover), #714 (snap correctness). Preserve those decisions and fixes. This is a pointer-path complexity finding, not evidence of forced reflow or a measured latency violation. Source origin/dev c4a61e8cf090170f35b1bed3350d9de20c83ecd5. TimeGrid is unchanged on merge-round-7a 2f4482ded066d9c5d9c59130377907f7fd2916c9. The geometry loop remains on queued dragghost-612 bc08062b167e59ca7ac39426a96481b2664b2e75. - packages/ui/src/components/calendar/TimeGrid.svelte:936–942: columnDateAt queries rendered columns and reads each rectangle until it finds the target. - :1035–1047 and :1112–1124: each move event calls it and reads the source column height again. The handlers are not coalesced to one frame. - packages/ui/src/components/calendar/snap.ts:54–68: each snap scans every item edge, including after an exact match is found. Move snapping can resolve both start and end. snapEdges is correctly precomputed in TimeGrid:190–195; do not move candidate construction onto the pointer path. Reasoned and counted impact The pointer path is O(rendered columns + same-day item edges) per event. Production resolveTimeSnap was called directly with instrumented iterators: 100/1,000/10,000 edges produced exactly 100/1,000/10,000 edge visits per snap. This is an operation count, not browser timing. Geometry reads may force layout if styles are dirty, but no forced-layout claim is made without a trace. Existing preview equality guards and narrow per-day preview props already avoid rebuilding the overlap layout on every drag. Concrete fix Reuse the uniform-column geometry already held by TimeGrid, or capture rendered rectangles and hour scale once per drag. Invalidate only on real scroll, resize or zoom. Coalesce pointer movement to the latest sample per animation frame. Build sorted per-day edge candidates when day data changes, then search only candidates inside the magnetic radius. Preserve deterministic ties, exclusion of the moving item, item > Now > grid priority, Alt bypass, overnight ranges and all input modes. Avoid runtime measurement for alignment. Acceptance tests Instrument geometry and resolver visits across a long drag: counts must stay bounded per painted frame instead of growing with all columns/edges. Add resolver equivalence tests for equal-distance ties, exclusion, nearest edges, Now/grid priority and Alt. Extend the existing drag-snap and Calendar render profiles with dense days plus high-rate pointer input. Capture production drag traces before claiming forced-layout or frame-budget improvement. Keep #714 assertions; do not weaken snap expectations. Duplicate search Searched all issue titles for Calendar drag, snap, hover and performance. #608 covers hover intent and #612 covers ghost appearance; neither covers drag geometry and edge lookup work. No product edits were made in the audit.
Author
Owner

Starting work on job/webperf, based on 2f4482ded066d9c5d9c59130377907f7fd2916c9 (job/merge-round-7a). I am reading the matching audit evidence and will report the concrete finding, regression coverage, measurements, and gate output here when finished.

Starting work on `job/webperf`, based on `2f4482ded066d9c5d9c59130377907f7fd2916c9` (`job/merge-round-7a`). I am reading the matching audit evidence and will report the concrete finding, regression coverage, measurements, and gate output here when finished.
Author
Owner

Finding for #751: CalendarSnapEdges is precomputed and sorted, but every drag resolution scanned the full list. I added a regression test that counts indexed reads on 10,000 edges: it failed on the old resolver with 10,000 reads (limit: 100) and passes after the resolver binary-searches the sorted snap window. Commit: cb7abeee7.

Local profile (node bench/calendar-snap-536.mjs --json target/calendar-snap-local.json): 400 edges, 2,000 calls: p50 1.10 µs, p95 2.46 µs, CPU 0.0081 s, RSS 68.8→72.0 MB. 10,000 edges, 1,000 calls: p50 0.95 µs, p95 13.83 µs, CPU 0.0093 s; 2,000-call burst CPU 0.0028 s, RSS 80.5 MB. Host load average was 113.39/115.37/117.19, so these local timings are directional only; locked perf-VM comparison remains to run.

Finding for #751: CalendarSnapEdges is precomputed and sorted, but every drag resolution scanned the full list. I added a regression test that counts indexed reads on 10,000 edges: it failed on the old resolver with 10,000 reads (limit: 100) and passes after the resolver binary-searches the sorted snap window. Commit: cb7abeee7. Local profile (`node bench/calendar-snap-536.mjs --json target/calendar-snap-local.json`): 400 edges, 2,000 calls: p50 1.10 µs, p95 2.46 µs, CPU 0.0081 s, RSS 68.8→72.0 MB. 10,000 edges, 1,000 calls: p50 0.95 µs, p95 13.83 µs, CPU 0.0093 s; 2,000-call burst CPU 0.0028 s, RSS 80.5 MB. Host load average was 113.39/115.37/117.19, so these local timings are directional only; locked perf-VM comparison remains to run.
Author
Owner

Follow-up for #751: I also addressed the audited per-pointer DOM work. TimeGrid now captures rendered column bounds once per gesture, uses a binary x lookup, adjusts the snapshot for native scroll offsets, and drops it after resize, zoom, or a rendered date-window change. Create/move/resize pointer handlers keep the latest sample and update once per animation frame; pointerup flushes the final sample and touch still calls preventDefault synchronously. The new pure hot-path tests passed (2/2). Commit: fb636034d. The Calendar profile now includes average and 10,000-column lookup cases; locked perf-VM measurements remain pending.

Follow-up for #751: I also addressed the audited per-pointer DOM work. TimeGrid now captures rendered column bounds once per gesture, uses a binary x lookup, adjusts the snapshot for native scroll offsets, and drops it after resize, zoom, or a rendered date-window change. Create/move/resize pointer handlers keep the latest sample and update once per animation frame; pointerup flushes the final sample and touch still calls preventDefault synchronously. The new pure hot-path tests passed (2/2). Commit: fb636034d. The Calendar profile now includes average and 10,000-column lookup cases; locked perf-VM measurements remain pending.
Author
Owner

#751 evidence and profile

The old Calendar resolver scanned every same-day edge; the current resolver binary-searches the sorted edge array and scans only candidates in the snap radius. The current drag snapshot also finds a rendered column by binary search instead of a full scan.

Measured under flock -w 14400 /root/perf.lock on root@10.69.69.63 with bench/hdd-emu.sh run-limited. Load inside the lock was 0.00, 0.00, 0.32 (1-minute, 5-minute, 15-minute averages). The same profile measured base resolver vs current code:

  • 400 edges, p95: 9.21 µs → 1.47 µs; CPU: 0.0222 s → 0.0046 s.
  • 10,000 edges, p95: 103.60 µs → 2.51 µs; CPU: 0.0774 s → 0.0022 s.
  • 28 columns, p95: 0.81 µs → 0.25 µs; CPU: 0.0025 s → 0.0016 s.
  • 10,000 columns, p95: 9.83 µs → 0.27 µs; CPU: 0.0181 s → 0.0010 s.

The profile output is in the worktree at target/perf; screenshots remain uncommitted review evidence. Regression coverage includes dense edges and frame-coalesced pointer geometry.

#751 evidence and profile The old Calendar resolver scanned every same-day edge; the current resolver binary-searches the sorted edge array and scans only candidates in the snap radius. The current drag snapshot also finds a rendered column by binary search instead of a full scan. Measured under `flock -w 14400 /root/perf.lock` on `root@10.69.69.63` with `bench/hdd-emu.sh run-limited`. Load inside the lock was `0.00, 0.00, 0.32` (1-minute, 5-minute, 15-minute averages). The same profile measured base resolver vs current code: - 400 edges, p95: 9.21 µs → 1.47 µs; CPU: 0.0222 s → 0.0046 s. - 10,000 edges, p95: 103.60 µs → 2.51 µs; CPU: 0.0774 s → 0.0022 s. - 28 columns, p95: 0.81 µs → 0.25 µs; CPU: 0.0025 s → 0.0016 s. - 10,000 columns, p95: 9.83 µs → 0.27 µs; CPU: 0.0181 s → 0.0010 s. The profile output is in the worktree at `target/perf`; screenshots remain uncommitted review evidence. Regression coverage includes dense edges and frame-coalesced pointer geometry.
Author
Owner

webperf job report

Branch: job/webperf
Head: b2a463b923b682ee83c4349012ad104f56cad98a

Built

  • Calendar drag work uses captured column geometry, binary lookups and one queued update per animation frame. The double-click create path now uses the same geometry snapshot. The 10,000-edge resolver p95 changed from 103.60 µs to 2.51 µs; the 10,000-column lookup p95 changed from 9.83 µs to 0.27 µs. Measured under /root/perf.lock; load average inside the lock was 0.00, 0.00, 0.32.
  • PDF Quick Look renders page one as soon as its dimensions are known. It does not wait for later page sizes.
  • The production build creates Brotli and gzip sidecars. Static responses negotiate encodings and include representation ETags, Vary, HEAD/304 behavior and font revalidation headers. The build reported: Compressed 464 static variants; saved 7260772 bytes.
  • Unsplash thumbnail bytes now use a shared immutable buffer and a bounded LRU: 12 MiB per User and 64 MiB process-wide.
  • Analytics requests share identical in-flight misses, cap unique computations at 16 and use one best-effort background cache writer. A warm-year and 24-request burst profile was added but not run.
  • HLS reads release the eviction lock after opening the confined file. Access-time updates use a single best-effort background writer.
  • Money parse hits share immutable documents. LRU accounting includes retained line structures, with 16 MiB per User, 128 MiB process-wide and 512 entries per User.
  • Tag suggestion counts now aggregate nested distinct counts in SQLite and filter hidden paths. The signed keyset cursor and response byte-cap portion of #784 remains open.

Files

Calendar: packages/ui/src/components/calendar/TimeGrid.svelte, drag-frame.ts, drag-geometry.ts, snap.ts, apps/web/src/lib/calendar/TimeGrid.svelte.test.ts, drag-performance.test.ts, apps/web/e2e/calendar.mjs, bench/calendar-snap-536.mjs.

PDF and static assets: packages/ui/src/components/viewer/PdfView.svelte, pdf-page-sizes.ts, apps/web/src/lib/viewer/pdf-page-sizes.test.ts, apps/web/src/lib/server/static-assets.test.ts, apps/web/scripts/compress-static-assets.mjs, apps/web/package.json, and crates/calternal-server/src/main.rs.

Other issue slices: crates/calternal-server/src/appearance.rs; crates/plugins/analytics/src/{cache.rs,routes.rs,tests.rs}; apps/web/e2e/analytics.mjs; crates/plugins/video/src/{lib.rs,routes.rs,transcode.rs}; crates/calternal-tags/src/{index.rs,lib.rs}; crates/plugins/money/src/{store.rs,tests.rs}.

Gate output

cargo fmt --check passed with no output (exit 0).

bun run check output:

User browser caches use userStorage; only documented device/public-link exceptions remain.
Text sizes and UI shape values use shared role tokens.
UI transitions and animation options use shared motion tokens or documented exceptions.
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/webperf/apps/web
Getting Svelte diagnostics...
svelte-check found 0 errors and 0 warnings

bun run test summary:

 Test Files  157 passed (157)
      Tests  1078 passed (1078)
   Start at  19:20:20
   Duration  165.70s (transform 41%, environment 32%, import 16%, tests 7%, setup 4%)

bun run build completed and reported:

Wrote site to "build"
  ✔ done
Compressed 464 static variants; saved 7260772 bytes.

Rust test status: the focused cargo test -p calternal-server static_assets_vary_by_accept_encoding -- --nocapture was stopped at the four-hour limit while Cargo was compiling dependencies. Its last output was Compiling ureq v3.4.2 and Compiling iso6709parse v0.1.2; it exited 130. No Rust tests or Clippy gates completed. No adversarial round completed.

UX gaps closed / left

Closed: page one of a PDF can render before the rest of the document is read; Calendar drag paths use captured geometry for pointer, touch and double-click interactions.

Left: no production screenshots were captured. The required macOS-emulated phone/tablet/desktop light/dark matrix and visual review remain outstanding.

Decisions for owner confirmation

The design documents did not set cache limits or admission counts. I chose 16 concurrent Analytics computations, a 256-entry weak flight registry and one cache writer; 16 MiB per User and 128 MiB process-wide for Money parsed data; and 12 MiB per User and 64 MiB process-wide for thumbnail bytes. HLS access-time writes are disposable, so a busy writer skips a hint and may make eviction less precise. Tag path filtering uses SQLite GLOB for dot-prefixed path components; this follows the current is_not_user_activity rule because all hidden and internal namespaces use dot-prefixed components.

Known gaps

The full #784 cursor and response-size work is not implemented. Analytics, thumbnail, HLS, Tag and Money performance profiles were not measured; only Calendar has before/after measurements. Per-crate Rust Clippy/test gates, the real-server adversarial round, and screenshots remain to run. cargo clean removed 2.3 GiB, and the web build and .svelte-kit output were deleted. No push, deploy or merge to dev was performed.

## webperf job report Branch: `job/webperf` Head: `b2a463b923b682ee83c4349012ad104f56cad98a` ### Built - Calendar drag work uses captured column geometry, binary lookups and one queued update per animation frame. The double-click create path now uses the same geometry snapshot. The 10,000-edge resolver p95 changed from 103.60 µs to 2.51 µs; the 10,000-column lookup p95 changed from 9.83 µs to 0.27 µs. Measured under `/root/perf.lock`; load average inside the lock was `0.00, 0.00, 0.32`. - PDF Quick Look renders page one as soon as its dimensions are known. It does not wait for later page sizes. - The production build creates Brotli and gzip sidecars. Static responses negotiate encodings and include representation ETags, `Vary`, HEAD/304 behavior and font revalidation headers. The build reported: `Compressed 464 static variants; saved 7260772 bytes.` - Unsplash thumbnail bytes now use a shared immutable buffer and a bounded LRU: 12 MiB per User and 64 MiB process-wide. - Analytics requests share identical in-flight misses, cap unique computations at 16 and use one best-effort background cache writer. A warm-year and 24-request burst profile was added but not run. - HLS reads release the eviction lock after opening the confined file. Access-time updates use a single best-effort background writer. - Money parse hits share immutable documents. LRU accounting includes retained line structures, with 16 MiB per User, 128 MiB process-wide and 512 entries per User. - Tag suggestion counts now aggregate nested distinct counts in SQLite and filter hidden paths. The signed keyset cursor and response byte-cap portion of #784 remains open. ### Files Calendar: `packages/ui/src/components/calendar/TimeGrid.svelte`, `drag-frame.ts`, `drag-geometry.ts`, `snap.ts`, `apps/web/src/lib/calendar/TimeGrid.svelte.test.ts`, `drag-performance.test.ts`, `apps/web/e2e/calendar.mjs`, `bench/calendar-snap-536.mjs`. PDF and static assets: `packages/ui/src/components/viewer/PdfView.svelte`, `pdf-page-sizes.ts`, `apps/web/src/lib/viewer/pdf-page-sizes.test.ts`, `apps/web/src/lib/server/static-assets.test.ts`, `apps/web/scripts/compress-static-assets.mjs`, `apps/web/package.json`, and `crates/calternal-server/src/main.rs`. Other issue slices: `crates/calternal-server/src/appearance.rs`; `crates/plugins/analytics/src/{cache.rs,routes.rs,tests.rs}`; `apps/web/e2e/analytics.mjs`; `crates/plugins/video/src/{lib.rs,routes.rs,transcode.rs}`; `crates/calternal-tags/src/{index.rs,lib.rs}`; `crates/plugins/money/src/{store.rs,tests.rs}`. ### Gate output `cargo fmt --check` passed with no output (exit 0). `bun run check` output: ```text User browser caches use userStorage; only documented device/public-link exceptions remain. Text sizes and UI shape values use shared role tokens. UI transitions and animation options use shared motion tokens or documented exceptions. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/webperf/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `bun run test` summary: ```text Test Files 157 passed (157) Tests 1078 passed (1078) Start at 19:20:20 Duration 165.70s (transform 41%, environment 32%, import 16%, tests 7%, setup 4%) ``` `bun run build` completed and reported: ```text Wrote site to "build" ✔ done Compressed 464 static variants; saved 7260772 bytes. ``` Rust test status: the focused `cargo test -p calternal-server static_assets_vary_by_accept_encoding -- --nocapture` was stopped at the four-hour limit while Cargo was compiling dependencies. Its last output was `Compiling ureq v3.4.2` and `Compiling iso6709parse v0.1.2`; it exited 130. No Rust tests or Clippy gates completed. No adversarial round completed. ### UX gaps closed / left Closed: page one of a PDF can render before the rest of the document is read; Calendar drag paths use captured geometry for pointer, touch and double-click interactions. Left: no production screenshots were captured. The required macOS-emulated phone/tablet/desktop light/dark matrix and visual review remain outstanding. ### Decisions for owner confirmation The design documents did not set cache limits or admission counts. I chose 16 concurrent Analytics computations, a 256-entry weak flight registry and one cache writer; 16 MiB per User and 128 MiB process-wide for Money parsed data; and 12 MiB per User and 64 MiB process-wide for thumbnail bytes. HLS access-time writes are disposable, so a busy writer skips a hint and may make eviction less precise. Tag path filtering uses SQLite GLOB for dot-prefixed path components; this follows the current `is_not_user_activity` rule because all hidden and internal namespaces use dot-prefixed components. ### Known gaps The full #784 cursor and response-size work is not implemented. Analytics, thumbnail, HLS, Tag and Money performance profiles were not measured; only Calendar has before/after measurements. Per-crate Rust Clippy/test gates, the real-server adversarial round, and screenshots remain to run. `cargo clean` removed 2.3 GiB, and the web `build` and `.svelte-kit` output were deleted. No push, deploy or merge to `dev` was performed.
Author
Owner

Correction to my earlier benchmark note: the local profile result is target/calendar-snap-perf-vm.json, not target/perf. It remains untracked review evidence. Screenshots were not captured in this run.

Correction to my earlier benchmark note: the local profile result is `target/calendar-snap-perf-vm.json`, not `target/perf`. It remains untracked review evidence. Screenshots were not captured in this run.
Author
Owner

Independent read-only review of job/webperf

Reviewed head: b2a463b923b682ee83c4349012ad104f56cad98a.
Review branch: job/rev2-webperf, base 440e19dce23040ac8ebaae88f0469b6535b1afcb.
Review head: ae92f11d64c263ea515646650be5fbb26c64b16a.
Committed files: audit-findings.md and review-webperf.md.

Seven findings: three P1, three P2 and one P3. Fix the P1 findings before merge.
Evidence comes from source only; no build, test, server or browser was run.

  • P1 / #807: crates/plugins/money/src/store.rs:169,177 returns
    Result<&Arc<Document>, _> where Result<&Document, _> is required.
    routes.rs:311,659 also mixes Arc and owned Document values; check the
    ledger input at store.rs:926. Use as_deref() for borrowed inputs and
    clone the inner Document where an edit needs an owned value. The Arc
    migration is incomplete and introduces source-level type errors.
  • P1 / #784: crates/calternal-tags/src/index.rs:592,599 uses continued
    Rust string lines without SQL separators. The final query contains
    ALLSELECT, remainingELSE and prefixesGROUP. GET /api/v1/tags maps
    the query failure to an internal error. Use a raw multiline literal or
    explicit spaces; run nested-count and empty-Home route regressions.
  • P1 / #805: packages/ui/src/components/viewer/PdfView.svelte:64,77,101
    reads doc synchronously from its load effect, then updates doc after loading.
    Svelte tracks reads in called functions. This subscribes the effect to its
    own result and can repeatedly destroy and reload the PDF. Track src/headers
    explicitly and keep cleanup untracked. Add a mounted component regression;
    the helper test cannot catch this failure.
  • P2 / #805: pdf-page-sizes.ts:41 copies the full page array every eight
    pages; PdfView.svelte:34,35 queries all canvases and scans rectangles to
    find the anchor. At the final page, N pages can cause O(N squared) work.
    Update changed geometry only and retain an indexed visible anchor. These
    are reasoned operation counts, not frame times or forced-layout evidence.
  • P2 / #751: packages/ui/src/components/calendar/snap.ts:70 still scans
    every edge inside the radius after finding an exact match. For 10,000
    edges at minute 720 and a pointer at 720, it visits all 10,000 edges.
    The new test at apps/web/src/lib/calendar/TimeGrid.svelte.test.ts:105
    spreads edges evenly and misses the case. Stop when sorted distances cannot
    improve, or group equal-minute candidates with deterministic alternatives
    for exclusion. Add co-timed edges and equal-distance tie tests; preserve
    #714 and #536 assertions. No timing claim is made.
  • P2 / #782: crates/plugins/analytics/src/cache.rs:239 detaches the cache
    writer, but tests.rs:303,688 immediately requires a warm second report.
    Scheduled rows do not prove committed rows. Wait for test-visible commit
    completion without changing old expectations or blocking production reads.
    The profile warmup at apps/web/e2e/analytics.mjs:1147 needs the same fence.
  • P3 / #803: crates/calternal-server/src/main.rs:1373 accepts identity
    with *;q=0 and prefers it over gzip;q=0.5, *;q=0. Apply wildcard-zero
    exclusion unless an explicit identity value overrides it. Add negotiation
    tests. This is an uncommon-input protocol defect, not a security blocker.

Duplicate searches were completed. Detailed evidence was added to existing
#807, #784, #805, #782 and #803. No new issue or duplicate fix owner was created.
This comment records the #751 follow-up and the summary.

The 281-file diff includes inherited merge-round-7a work. The review checked
the inventory and history, then examined the webperf performance slices in
detail. It does not approve the security of all inherited features. In the
reviewed slices, HLS still uses the authorized source lookup and confined
cache opens; Unsplash rechecks photo validity and shares capped cached bytes.
No new incompatible licence was found: sha2 0.10.9 is MIT OR Apache-2.0, the
inherited standardwebhooks 1.0.1 test dependency is MIT, and package licences
remain AGPL-3.0-only. No new JavaScript dependency was added by these slices.

Gates: not run. The LIGHT brief prohibits builds, tests, servers and
browsers. There is no Rust/web gate output to quote. git diff --check passed
with no output (exit 0). The fetched origin/dev merge returned, verbatim:

Already up to date.

For the merge round: follow the commands and proof boundaries in
review-webperf.md: per-crate Rust gates, web check and focused regressions,
one combined full test/adversarial round, real Calendar drag and PDF opening,
and macOS-emulated 390/820/1440 light/dark screenshots. The source job reports
no completed Rust gates and no captured screenshots. Extend the Calendar
profile with clustered edges under the perf VM lock; pure lookup timings
cannot establish a browser frame-budget improvement.

Known gaps: runtime and visual behavior remain unverified; inherited
feature branches were not fully audited again. #784 keyset/byte caps and
precomputed counts remain incomplete. Non-Calendar profile measurements are
still missing from the source job.

Decisions: documentation-only review; reuse existing fix owners; separate
P1 functional/build defects from P2 performance/test gaps and P3 protocol
handling. No product design decision or product code change was made.

# Independent read-only review of job/webperf Reviewed head: `b2a463b923b682ee83c4349012ad104f56cad98a`. Review branch: `job/rev2-webperf`, base `440e19dce23040ac8ebaae88f0469b6535b1afcb`. Review head: `ae92f11d64c263ea515646650be5fbb26c64b16a`. Committed files: `audit-findings.md` and `review-webperf.md`. Seven findings: three P1, three P2 and one P3. Fix the P1 findings before merge. Evidence comes from source only; no build, test, server or browser was run. - **P1 / #807:** `crates/plugins/money/src/store.rs:169,177` returns `Result<&Arc<Document>, _>` where `Result<&Document, _>` is required. `routes.rs:311,659` also mixes Arc and owned Document values; check the ledger input at `store.rs:926`. Use `as_deref()` for borrowed inputs and clone the inner Document where an edit needs an owned value. The Arc migration is incomplete and introduces source-level type errors. - **P1 / #784:** `crates/calternal-tags/src/index.rs:592,599` uses continued Rust string lines without SQL separators. The final query contains `ALLSELECT`, `remainingELSE` and `prefixesGROUP`. `GET /api/v1/tags` maps the query failure to an internal error. Use a raw multiline literal or explicit spaces; run nested-count and empty-Home route regressions. - **P1 / #805:** `packages/ui/src/components/viewer/PdfView.svelte:64,77,101` reads doc synchronously from its load effect, then updates doc after loading. Svelte tracks reads in called functions. This subscribes the effect to its own result and can repeatedly destroy and reload the PDF. Track src/headers explicitly and keep cleanup untracked. Add a mounted component regression; the helper test cannot catch this failure. - **P2 / #805:** `pdf-page-sizes.ts:41` copies the full page array every eight pages; `PdfView.svelte:34,35` queries all canvases and scans rectangles to find the anchor. At the final page, N pages can cause O(N squared) work. Update changed geometry only and retain an indexed visible anchor. These are reasoned operation counts, not frame times or forced-layout evidence. - **P2 / #751:** `packages/ui/src/components/calendar/snap.ts:70` still scans every edge inside the radius after finding an exact match. For 10,000 edges at minute 720 and a pointer at 720, it visits all 10,000 edges. The new test at `apps/web/src/lib/calendar/TimeGrid.svelte.test.ts:105` spreads edges evenly and misses the case. Stop when sorted distances cannot improve, or group equal-minute candidates with deterministic alternatives for exclusion. Add co-timed edges and equal-distance tie tests; preserve #714 and #536 assertions. No timing claim is made. - **P2 / #782:** `crates/plugins/analytics/src/cache.rs:239` detaches the cache writer, but `tests.rs:303,688` immediately requires a warm second report. Scheduled rows do not prove committed rows. Wait for test-visible commit completion without changing old expectations or blocking production reads. The profile warmup at `apps/web/e2e/analytics.mjs:1147` needs the same fence. - **P3 / #803:** `crates/calternal-server/src/main.rs:1373` accepts identity with `*;q=0` and prefers it over `gzip;q=0.5, *;q=0`. Apply wildcard-zero exclusion unless an explicit identity value overrides it. Add negotiation tests. This is an uncommon-input protocol defect, not a security blocker. Duplicate searches were completed. Detailed evidence was added to existing #807, #784, #805, #782 and #803. No new issue or duplicate fix owner was created. This comment records the #751 follow-up and the summary. The 281-file diff includes inherited merge-round-7a work. The review checked the inventory and history, then examined the webperf performance slices in detail. It does not approve the security of all inherited features. In the reviewed slices, HLS still uses the authorized source lookup and confined cache opens; Unsplash rechecks photo validity and shares capped cached bytes. No new incompatible licence was found: sha2 0.10.9 is MIT OR Apache-2.0, the inherited standardwebhooks 1.0.1 test dependency is MIT, and package licences remain AGPL-3.0-only. No new JavaScript dependency was added by these slices. **Gates:** not run. The LIGHT brief prohibits builds, tests, servers and browsers. There is no Rust/web gate output to quote. `git diff --check` passed with no output (exit 0). The fetched origin/dev merge returned, verbatim: ```text Already up to date. ``` **For the merge round:** follow the commands and proof boundaries in `review-webperf.md`: per-crate Rust gates, web check and focused regressions, one combined full test/adversarial round, real Calendar drag and PDF opening, and macOS-emulated 390/820/1440 light/dark screenshots. The source job reports no completed Rust gates and no captured screenshots. Extend the Calendar profile with clustered edges under the perf VM lock; pure lookup timings cannot establish a browser frame-budget improvement. **Known gaps:** runtime and visual behavior remain unverified; inherited feature branches were not fully audited again. #784 keyset/byte caps and precomputed counts remain incomplete. Non-Calendar profile measurements are still missing from the source job. **Decisions:** documentation-only review; reuse existing fix owners; separate P1 functional/build defects from P2 performance/test gaps and P3 protocol handling. No product design decision or product code change was made.
Author
Owner

Starting review fixes on branch job/webperf. Worktree HEAD is b2a463b923; branch base is 440e19dce2. I am reviewing the requested P1 and P2 findings and their existing issue comments before editing.

Starting review fixes on branch job/webperf. Worktree HEAD is b2a463b923b682ee83c4349012ad104f56cad98a; branch base is 440e19dce23040ac8ebaae88f0469b6535b1afcb. I am reviewing the requested P1 and P2 findings and their existing issue comments before editing.
Author
Owner

Completed

Fixed the requested independent review findings:

  • Money now completes the shared Arc<Document> migration in its Store and routes. Reads borrow parsed documents; edits clone only where they need an owned document. The property test compares the full owned and shared-document ledger projections over generated transaction sets.
  • Tags keeps recursive-count SQL separators intact. The regression covers empty Homes and nested tag counts.
  • Analytics tests wait for the detached cache writer to commit. The performance profile now waits for a real server-timing cache hit before measuring warm reads.
  • The PDF load effect no longer tracks its own document writes. Source and header changes replace the document once, stale loads are fenced, and old documents are destroyed once. Page geometry updates touch only each changed batch, and the scroll anchor uses the visible page index rather than scanning all page canvases.
  • Calendar snap lookup now bounds equal-minute groups and skips excluded items with binary searches. Tie order remains the same as the prior sorted scan.
  • Fixed two behavior-preserving server type errors so a local production server could be built for screenshot evidence.

Files

  • crates/plugins/money/src/{store.rs,routes.rs,tests.rs}
  • crates/calternal-tags/src/{index.rs,lib.rs}
  • crates/plugins/analytics/src/tests.rs
  • apps/web/e2e/{analytics.mjs,calendar.mjs}
  • packages/ui/src/components/viewer/{PdfView.svelte,pdf-page-sizes.ts}
  • apps/web/src/lib/viewer/{PdfView.svelte.test.ts,pdf-page-sizes.test.ts}
  • packages/ui/src/components/calendar/snap.ts
  • apps/web/src/lib/calendar/{TimeGrid.svelte.test.ts,model.test.ts}
  • bench/calendar-snap-536.mjs
  • crates/calternal-server/src/{appearance.rs,main.rs}

UX gaps closed

  • PDF reloads now settle after the requested source or password header changes. The visible first page remains mounted, and size refinement preserves the current viewport anchor.
  • Calendar drag snapping remains responsive when many item edges share a minute, including when the active item is excluded.
  • Captured production screenshots cover macOS shortcut rendering at phone (390 px), tablet (820 px), and desktop (1440 px) widths in light and dark themes.

UX gaps left

  • This job did not run the full keyboard, touch, and screen-reader interaction sweep. The merge round should cover those paths in the complete Files and Calendar E2E runs.
  • Review P3 finding #803 (Money identity wildcard behavior) remains outside this round's requested P1/P2 fixes.

Verification

cargo fmt --check exited 0 with no output.

The final bun run check output was:

$ node scripts/check-user-storage.mjs && node scripts/check-type-tokens.mjs && node scripts/check-motion-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
User browser caches use userStorage; only documented device/public-link exceptions remain.
Text sizes and UI shape values use shared role tokens.
UI transitions and animation options use shared motion tokens or documented exceptions.
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/webperf/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

Rust gates passed for every changed Rust crate. The following are the exact final gate result lines:

cargo clippy -p calternal-plugin-money --all-targets -- -D warnings
Finished `dev` profile [unoptimized + debuginfo] target(s) in 6m 48s
cargo test -p calternal-plugin-money
Finished `test` profile [unoptimized + debuginfo] target(s) in 15m 45s
test result: ok. 28 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 73.98s

cargo clippy -p calternal-tags --all-targets -- -D warnings
Finished `dev` profile [unoptimized + debuginfo] target(s) in 10m 39s
cargo test -p calternal-tags
Finished `test` profile [unoptimized + debuginfo] target(s) in 17m 00s
test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 91.47s

cargo clippy -p calternal-plugin-analytics --all-targets -- -D warnings
Finished `dev` profile [unoptimized + debuginfo] target(s) in 3m 30s
cargo test -p calternal-plugin-analytics
Finished `test` profile [unoptimized + debuginfo] target(s) in 8m 54s
test result: ok. 34 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 23.44s

cargo clippy -p calternal-server --all-targets -- -D warnings
Finished `dev` profile [unoptimized + debuginfo] target(s) in 10m 17s
cargo test -p calternal-server
Finished `test` profile [unoptimized + debuginfo] target(s) in 22m 43s
test result: ok. 169 passed; 0 failed; 5 ignored; 0 measured; 0 filtered out; finished in 30.42s

Focused Vitest passed in split runs under host load: 3 files / 35 tests passed, then TimeGrid.svelte.test.ts and PdfView.svelte.test.ts passed (2 files / 13 tests). The targeted retry output was:

Test Files  2 passed (2)
Tests  13 passed (13)
Duration 111.69s (transform 63%, environment 28%, import 5%, setup 2%, tests 2%)

An earlier combined focused run hit a worker startup timeout on the shared host; its three completed files passed. The successful split runs cover the changed PDF page-size and document-effect tests and the Calendar snap tests.

The production web build passed (✓ built in 4m 31s; adapter-static wrote build; ✔ done). Production screenshot runs passed:

FILES SCREENSHOTS PASSED
CSP REPORTS files: 0 across 23 pages
calendar header e2e: all geometry checks passed

Calendar snap benchmark ran locally because flock -n /root/perf.lock true reported that the perf VM was busy. On the loaded local host, 400-edge p50/p95 was 2.14/3.15 µs (baseline 4.36/13.27 µs); 10k-edge p50/p95 was 1.23/2.12 µs (baseline 41.44/70.17 µs). The 10k co-timed case was 0.51/0.71 µs versus the linear reference at 134.38/222.17 µs. Load average was 69.51/72.98/72.73 before and 69.41/72.84/72.69 after. Treat these local numbers as directional; no perf-VM measurement was available.

cargo clean removed 17,628 files (9.7 GiB). apps/web/build and apps/web/.svelte-kit were removed after verification.

Decisions not covered by DESIGN.md

  • Use lower/upper bounds over the existing sorted Calendar edges, then expand minute groups outward. This keeps the existing tie behavior and gives a bounded exact-match lookup.
  • Track the visible PDF anchor with the existing browser observer mechanism and update only changed page-size batches. This avoids a document-wide DOM scan or repeated full-array copies.
  • Use the Analytics response's server-timing cache-hit counter as the readiness condition; it proves the async cache commit without relying on a fixed delay.
  • The server changes only make existing mutex and q-value types explicit for compilation. They do not change behavior or an API contract.

For the merge round

Run the full checks excluded by the branch verification policy:

  • bun run test — full web test suite.
  • bun e2e/files.mjs — full Files/PDF interaction flow.
  • bun e2e/calendar.mjs — full Calendar interaction flow.
  • bun e2e/analytics.mjs — real cache-commit warm-up and performance profile.
  • tests/adversarial/run.sh — the configured API adversarial matrix after the Tags and Money route changes.

Production screenshots

PDF viewer, macOS emulation, phone/tablet/desktop, light/dark (attached on #805):

PDF phone light
PDF phone dark
PDF tablet light
PDF tablet dark
PDF desktop light
PDF desktop dark

Calendar Day and Week, macOS emulation, phone/tablet/desktop, light/dark:

Calendar Day phone light
Calendar Day phone dark
Calendar Day tablet light
Calendar Day tablet dark
Calendar Day desktop light
Calendar Day desktop dark
Calendar Week phone light
Calendar Week phone dark
Calendar Week tablet light
Calendar Week tablet dark
Calendar Week desktop light
Calendar Week desktop dark

Head SHA: 5ed6d0ecf7c8dd6bf71db36ce9244af93d18797d.

## Completed Fixed the requested independent review findings: - Money now completes the shared `Arc<Document>` migration in its Store and routes. Reads borrow parsed documents; edits clone only where they need an owned document. The property test compares the full owned and shared-document ledger projections over generated transaction sets. - Tags keeps recursive-count SQL separators intact. The regression covers empty Homes and nested tag counts. - Analytics tests wait for the detached cache writer to commit. The performance profile now waits for a real `server-timing` cache hit before measuring warm reads. - The PDF load effect no longer tracks its own document writes. Source and header changes replace the document once, stale loads are fenced, and old documents are destroyed once. Page geometry updates touch only each changed batch, and the scroll anchor uses the visible page index rather than scanning all page canvases. - Calendar snap lookup now bounds equal-minute groups and skips excluded items with binary searches. Tie order remains the same as the prior sorted scan. - Fixed two behavior-preserving server type errors so a local production server could be built for screenshot evidence. ## Files - `crates/plugins/money/src/{store.rs,routes.rs,tests.rs}` - `crates/calternal-tags/src/{index.rs,lib.rs}` - `crates/plugins/analytics/src/tests.rs` - `apps/web/e2e/{analytics.mjs,calendar.mjs}` - `packages/ui/src/components/viewer/{PdfView.svelte,pdf-page-sizes.ts}` - `apps/web/src/lib/viewer/{PdfView.svelte.test.ts,pdf-page-sizes.test.ts}` - `packages/ui/src/components/calendar/snap.ts` - `apps/web/src/lib/calendar/{TimeGrid.svelte.test.ts,model.test.ts}` - `bench/calendar-snap-536.mjs` - `crates/calternal-server/src/{appearance.rs,main.rs}` ## UX gaps closed - PDF reloads now settle after the requested source or password header changes. The visible first page remains mounted, and size refinement preserves the current viewport anchor. - Calendar drag snapping remains responsive when many item edges share a minute, including when the active item is excluded. - Captured production screenshots cover macOS shortcut rendering at phone (390 px), tablet (820 px), and desktop (1440 px) widths in light and dark themes. ## UX gaps left - This job did not run the full keyboard, touch, and screen-reader interaction sweep. The merge round should cover those paths in the complete Files and Calendar E2E runs. - Review P3 finding #803 (Money identity wildcard behavior) remains outside this round's requested P1/P2 fixes. ## Verification `cargo fmt --check` exited 0 with no output. The final `bun run check` output was: ```text $ node scripts/check-user-storage.mjs && node scripts/check-type-tokens.mjs && node scripts/check-motion-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json User browser caches use userStorage; only documented device/public-link exceptions remain. Text sizes and UI shape values use shared role tokens. UI transitions and animation options use shared motion tokens or documented exceptions. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/webperf/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` Rust gates passed for every changed Rust crate. The following are the exact final gate result lines: ```text cargo clippy -p calternal-plugin-money --all-targets -- -D warnings Finished `dev` profile [unoptimized + debuginfo] target(s) in 6m 48s cargo test -p calternal-plugin-money Finished `test` profile [unoptimized + debuginfo] target(s) in 15m 45s test result: ok. 28 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 73.98s cargo clippy -p calternal-tags --all-targets -- -D warnings Finished `dev` profile [unoptimized + debuginfo] target(s) in 10m 39s cargo test -p calternal-tags Finished `test` profile [unoptimized + debuginfo] target(s) in 17m 00s test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 91.47s cargo clippy -p calternal-plugin-analytics --all-targets -- -D warnings Finished `dev` profile [unoptimized + debuginfo] target(s) in 3m 30s cargo test -p calternal-plugin-analytics Finished `test` profile [unoptimized + debuginfo] target(s) in 8m 54s test result: ok. 34 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 23.44s cargo clippy -p calternal-server --all-targets -- -D warnings Finished `dev` profile [unoptimized + debuginfo] target(s) in 10m 17s cargo test -p calternal-server Finished `test` profile [unoptimized + debuginfo] target(s) in 22m 43s test result: ok. 169 passed; 0 failed; 5 ignored; 0 measured; 0 filtered out; finished in 30.42s ``` Focused Vitest passed in split runs under host load: 3 files / 35 tests passed, then `TimeGrid.svelte.test.ts` and `PdfView.svelte.test.ts` passed (2 files / 13 tests). The targeted retry output was: ```text Test Files 2 passed (2) Tests 13 passed (13) Duration 111.69s (transform 63%, environment 28%, import 5%, setup 2%, tests 2%) ``` An earlier combined focused run hit a worker startup timeout on the shared host; its three completed files passed. The successful split runs cover the changed PDF page-size and document-effect tests and the Calendar snap tests. The production web build passed (`✓ built in 4m 31s`; adapter-static wrote `build`; `✔ done`). Production screenshot runs passed: ```text FILES SCREENSHOTS PASSED CSP REPORTS files: 0 across 23 pages calendar header e2e: all geometry checks passed ``` Calendar snap benchmark ran locally because `flock -n /root/perf.lock true` reported that the perf VM was busy. On the loaded local host, 400-edge p50/p95 was 2.14/3.15 µs (baseline 4.36/13.27 µs); 10k-edge p50/p95 was 1.23/2.12 µs (baseline 41.44/70.17 µs). The 10k co-timed case was 0.51/0.71 µs versus the linear reference at 134.38/222.17 µs. Load average was 69.51/72.98/72.73 before and 69.41/72.84/72.69 after. Treat these local numbers as directional; no perf-VM measurement was available. `cargo clean` removed 17,628 files (9.7 GiB). `apps/web/build` and `apps/web/.svelte-kit` were removed after verification. ## Decisions not covered by DESIGN.md - Use lower/upper bounds over the existing sorted Calendar edges, then expand minute groups outward. This keeps the existing tie behavior and gives a bounded exact-match lookup. - Track the visible PDF anchor with the existing browser observer mechanism and update only changed page-size batches. This avoids a document-wide DOM scan or repeated full-array copies. - Use the Analytics response's `server-timing` cache-hit counter as the readiness condition; it proves the async cache commit without relying on a fixed delay. - The server changes only make existing mutex and q-value types explicit for compilation. They do not change behavior or an API contract. ## For the merge round Run the full checks excluded by the branch verification policy: - `bun run test` — full web test suite. - `bun e2e/files.mjs` — full Files/PDF interaction flow. - `bun e2e/calendar.mjs` — full Calendar interaction flow. - `bun e2e/analytics.mjs` — real cache-commit warm-up and performance profile. - `tests/adversarial/run.sh` — the configured API adversarial matrix after the Tags and Money route changes. ## Production screenshots PDF viewer, macOS emulation, phone/tablet/desktop, light/dark (attached on #805): ![PDF phone light](https://git.kayg.org/attachments/88916a8f-807e-4db5-aefc-9b414f251e91) ![PDF phone dark](https://git.kayg.org/attachments/cf09e657-4951-49ba-9e6b-9af816f939bf) ![PDF tablet light](https://git.kayg.org/attachments/ddf5842f-7b7b-49e4-b0dd-f5eddea44228) ![PDF tablet dark](https://git.kayg.org/attachments/7a7995c6-634c-4ad7-a2ae-9c951ea0f72e) ![PDF desktop light](https://git.kayg.org/attachments/e94bbeb3-4f3e-4627-9dd3-05e04c94ec1d) ![PDF desktop dark](https://git.kayg.org/attachments/32ed65e1-d89b-41ef-838e-fbb8a677df95) Calendar Day and Week, macOS emulation, phone/tablet/desktop, light/dark: ![Calendar Day phone light](https://git.kayg.org/attachments/d626aa36-6540-4c99-882c-d8b060b5c9ab) ![Calendar Day phone dark](https://git.kayg.org/attachments/08ea3d0d-294c-4452-b47d-3382ba7044b0) ![Calendar Day tablet light](https://git.kayg.org/attachments/74ce13c9-ac93-4602-941c-32db11151cb4) ![Calendar Day tablet dark](https://git.kayg.org/attachments/7761445d-426b-44f2-a4f1-bd8455fe5e34) ![Calendar Day desktop light](https://git.kayg.org/attachments/b1bd94f4-b08b-464d-b24e-ceab38a05e01) ![Calendar Day desktop dark](https://git.kayg.org/attachments/107485db-43b8-4b01-8fdf-5bca87be0b8c) ![Calendar Week phone light](https://git.kayg.org/attachments/90d7736a-b8b3-496a-b7dd-5add8d920e4a) ![Calendar Week phone dark](https://git.kayg.org/attachments/b999de5f-c1ae-4559-b06c-8fbede644f57) ![Calendar Week tablet light](https://git.kayg.org/attachments/de5685e2-7761-4ae2-9a69-88ea7e055c76) ![Calendar Week tablet dark](https://git.kayg.org/attachments/eabfb2df-6d56-43a4-b03f-4b1a4babb558) ![Calendar Week desktop light](https://git.kayg.org/attachments/0f4ed382-fca8-47b4-ad7a-00947b0025ec) ![Calendar Week desktop dark](https://git.kayg.org/attachments/17b80954-a9fe-4b25-aac8-d8052618c60d) Head SHA: `5ed6d0ecf7c8dd6bf71db36ce9244af93d18797d`.
Author
Owner

Money break-the-numbers review (job/webperf, ccd0fa98e + 59d90de6c, shared Arc<Document>, #807): GO for the Money part.

The earlier P1 (incomplete Arc migration) is fixed: borrowed sites use as_deref(), edit sites clone the inner Document. No leaks between Users, Budgets or months: each User has its own cache, and keys are Home-relative paths. Every hit is checked against the full file fingerprint. The ledger is projected again on each load. Reads and writes keep the per-User RwLock. Nothing mutates through the Arc.

Non-blocking findings:

  • P2 crates/plugins/money/src/tests.rs:866-881: the new owned-vs-shared proptest calls the same generic ledger::project on the same single parsed month. It proves only that Borrow derefs. It has no multiple months, no edits between reads, and no store-cache path. Add a store-level test: load, edit through replace, load again, then compare Ready to Assign, Activity and Available to a cache-free fresh parse, with a second User on the same index. The #462 replay assertions are intact.
  • P3 store.rs:324-339: a failed global reserve still evicts this User's warm entries first (performance only).
  • P3 store.rs:700-710: an external-writer race can overwrite a newer cache entry with an older one. It is re-parsed on the next read, so no stale value is served.
  • P3 (inherited): a same-size, same-inode, same-mtime replacement could serve a stale parse. This is not new in #807, and CAS still protects writes.

Full report: rev2-webperf/review-webperf-money.md. The Money MCP Events commits (#491) were out of scope.

Money break-the-numbers review (job/webperf, `ccd0fa98e` + `59d90de6c`, shared `Arc<Document>`, #807): **GO for the Money part.** The earlier P1 (incomplete Arc migration) is fixed: borrowed sites use `as_deref()`, edit sites clone the inner Document. No leaks between Users, Budgets or months: each User has its own cache, and keys are Home-relative paths. Every hit is checked against the full file fingerprint. The ledger is projected again on each load. Reads and writes keep the per-User RwLock. Nothing mutates through the Arc. Non-blocking findings: - P2 `crates/plugins/money/src/tests.rs:866-881`: the new owned-vs-shared proptest calls the same generic `ledger::project` on the same single parsed month. It proves only that `Borrow` derefs. It has no multiple months, no edits between reads, and no store-cache path. Add a store-level test: load, edit through `replace`, load again, then compare Ready to Assign, Activity and Available to a cache-free fresh parse, with a second User on the same index. The #462 replay assertions are intact. - P3 `store.rs:324-339`: a failed global reserve still evicts this User's warm entries first (performance only). - P3 `store.rs:700-710`: an external-writer race can overwrite a newer cache entry with an older one. It is re-parsed on the next read, so no stale value is served. - P3 (inherited): a same-size, same-inode, same-mtime replacement could serve a stale parse. This is not new in #807, and CAS still protects writes. Full report: `rev2-webperf/review-webperf-money.md`. The Money MCP Events commits (#491) were out of scope.
Sign in to join this conversation.
No labels
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/calternal#751
No description provided.