Chrome: sidebar and H1 never repeat each other; Files breadcrumb; Pinned first with drag-to-pin; calm H1 transitions #156

Closed
opened 2026-09-26 09:35:02 +00:00 by kayg · 110 comments
Owner

Owner grill 2026-09-26 (round 1, all answered). Applies to EVERY mode through the shared header/sidebar code (one rule, no per-mode copies). Read DESIGN §34 first.

  1. The H1 sub-view menu (title + chevron dropdown listing Files/Shared/Recent/Trash etc.) exists ONLY when the sidebar is not visible (collapsed on desktop, or the phone sheet closed). With the sidebar open the H1 is a plain title with no chevron and no menu. Make every mode's sidebar behave the same way (Calendar, Photos, Files, Notes, Ask, Analytics).
  2. Files H1 inside a folder is a breadcrumb: Files › Notes › Journal. Each segment is a link and a drop target for drag-to-move. When it would wrap, middle segments fold into an '…' menu, the header stays one row. The last segment carries the sub-view menu only under rule 1.
  3. Remove the Folders tree from the Files sidebar completely. Sidebar = Files / Shared / Recent / Trash, then Pinned, then Smart folders.
  4. Pinned comes BEFORE Smart folders. Both sections stay visible when empty (discoverability) with a short one-line hint, not a paragraph. Drag and drop onto the sidebar where it makes sense: dragging a file or folder from the Files list onto Pinned pins it (drop highlight; keyboard alternative stays the ⋯ Pin action; screen-reader announcement). Reorder pins by drag. Pins persist per user through the existing API (reuse; add an endpoint only if none exists, with adversarial probe coverage).
  5. Sweep Calendar, Photos, Notes, Analytics for the same duplication (sidebar vs H1 menu vs content); lists of real items (albums, calendars) stay, repeats go.
  6. BUG: in Calendar, switching Day ⇄ Agenda (and other sub-views) makes the H1 overlap mid-transition: old and new titles ('September' and '2026') render on top of each other. One title at a time (crossfade with the old one out of layout, or no animation), no overlap in any sub-view switch, reduced motion = instant. Add an e2e assertion that samples the header during a switch and fails if two titles are visible.

Deliver: e2e + layout-sweep coverage (collapsed and open sidebar, 1440/1024/390, light and dark), screenshots attached in the report for Claude to review. Gates as CLAUDE.md.

Owner grill 2026-09-26 (round 1, all answered). Applies to EVERY mode through the shared header/sidebar code (one rule, no per-mode copies). Read DESIGN §34 first. 1. The H1 sub-view menu (title + chevron dropdown listing Files/Shared/Recent/Trash etc.) exists ONLY when the sidebar is not visible (collapsed on desktop, or the phone sheet closed). With the sidebar open the H1 is a plain title with no chevron and no menu. Make every mode's sidebar behave the same way (Calendar, Photos, Files, Notes, Ask, Analytics). 2. Files H1 inside a folder is a breadcrumb: Files › Notes › Journal. Each segment is a link and a drop target for drag-to-move. When it would wrap, middle segments fold into an '…' menu, the header stays one row. The last segment carries the sub-view menu only under rule 1. 3. Remove the Folders tree from the Files sidebar completely. Sidebar = Files / Shared / Recent / Trash, then Pinned, then Smart folders. 4. Pinned comes BEFORE Smart folders. Both sections stay visible when empty (discoverability) with a short one-line hint, not a paragraph. Drag and drop onto the sidebar where it makes sense: dragging a file or folder from the Files list onto Pinned pins it (drop highlight; keyboard alternative stays the ⋯ Pin action; screen-reader announcement). Reorder pins by drag. Pins persist per user through the existing API (reuse; add an endpoint only if none exists, with adversarial probe coverage). 5. Sweep Calendar, Photos, Notes, Analytics for the same duplication (sidebar vs H1 menu vs content); lists of real items (albums, calendars) stay, repeats go. 6. BUG: in Calendar, switching Day ⇄ Agenda (and other sub-views) makes the H1 overlap mid-transition: old and new titles ('September' and '2026') render on top of each other. One title at a time (crossfade with the old one out of layout, or no animation), no overlap in any sub-view switch, reduced motion = instant. Add an e2e assertion that samples the header during a switch and fails if two titles are visible. Deliver: e2e + layout-sweep coverage (collapsed and open sidebar, 1440/1024/390, light and dark), screenshots attached in the report for Claude to review. Gates as CLAUDE.md.
Author
Owner

Starting #156. Branch: job/chrome-sidebar. Base SHA: c2a81aeab9 (dev). Scope: shared mode header/sidebar rules, Files breadcrumb/sidebar pin behavior, Calendar title-switch regression coverage.

Starting #156. Branch: job/chrome-sidebar. Base SHA: c2a81aeab9fd6090cb4eba448af5835c4877e7de (dev). Scope: shared mode header/sidebar rules, Files breadcrumb/sidebar pin behavior, Calendar title-switch regression coverage.
Author
Owner

Finding for #156: apps/web/src/lib/FilesSidebar.svelte (actually apps/web/src/lib/files/FilesSidebar.svelte) still mounts the Folders tree; Smart folders renders before Pinned; the Pinned section is hidden when empty. Pinned file metadata is stored under localStorage key calternal.files.pins in apps/web/src/lib/files/prefs.svelte.ts, so it is not shared across Installations for one User. packages/ui/src/components/ModeHeader.svelte renders a title switcher based on menu presence without checking sidebarVisible or sidebarOpen. I will use the Files plugin API and calternal-fs for per-User storage and retain the existing stable item IDs.

Finding for #156: apps/web/src/lib/FilesSidebar.svelte (actually apps/web/src/lib/files/FilesSidebar.svelte) still mounts the Folders tree; Smart folders renders before Pinned; the Pinned section is hidden when empty. Pinned file metadata is stored under localStorage key calternal.files.pins in apps/web/src/lib/files/prefs.svelte.ts, so it is not shared across Installations for one User. packages/ui/src/components/ModeHeader.svelte renders a title switcher based on menu presence without checking sidebarVisible or sidebarOpen. I will use the Files plugin API and calternal-fs for per-User storage and retain the existing stable item IDs.
Author
Owner

Decision for the design gap: no server API currently stores Files pins; the existing values are browser-local. I am adding GET/PUT /api/v1/files/pins. The User settings file stores only the files.pins list and monotonic files.pins_revision; PUT uses compare-and-swap so a stale Installation cannot overwrite a newer list. Pin IDs stay stable item IDs. Existing browser pins will be imported on first load where the server revision is zero.

Decision for the design gap: no server API currently stores Files pins; the existing values are browser-local. I am adding GET/PUT /api/v1/files/pins. The User settings file stores only the `files.pins` list and monotonic `files.pins_revision`; PUT uses compare-and-swap so a stale Installation cannot overwrite a newer list. Pin IDs stay stable item IDs. Existing browser pins will be imported on first load where the server revision is zero.
Author
Owner

Finding: cargo test -p calternal-plugin-files files_pins -- --nocapture passed (2 tests). The following cargo run -p calternal-server -- openapi failed before compilation completed because sccache tried to create temp directories under the sibling /home/kayg/Developer/calternal-wt/tz-days/target/tmp. I am retrying with the cache temp directory inside this worktree; no endpoint failure was observed.

Finding: `cargo test -p calternal-plugin-files files_pins -- --nocapture` passed (2 tests). The following `cargo run -p calternal-server -- openapi` failed before compilation completed because `sccache` tried to create temp directories under the sibling `/home/kayg/Developer/calternal-wt/tz-days/target/tmp`. I am retrying with the cache temp directory inside this worktree; no endpoint failure was observed.
Author
Owner

Finding: the Files plugin had no server-backed pin endpoint, so sidebar pins were stored in browser localStorage and did not follow the User across Installations. I added authenticated GET/PUT /api/v1/files/pins backed by <home>/.calternal/settings.json, with stable item IDs, a per-User boundary, validation, and revision compare-and-swap. cargo test -p calternal-plugin-files files_pins -- --nocapture passed: 2 passed, 0 failed. The adversarial probe now covers malformed and oversized payloads, hostile paths/IDs, User isolation, and concurrent stale writes.

Finding: the Files plugin had no server-backed pin endpoint, so sidebar pins were stored in browser localStorage and did not follow the User across Installations. I added authenticated GET/PUT `/api/v1/files/pins` backed by `<home>/.calternal/settings.json`, with stable item IDs, a per-User boundary, validation, and revision compare-and-swap. `cargo test -p calternal-plugin-files files_pins -- --nocapture` passed: 2 passed, 0 failed. The adversarial probe now covers malformed and oversized payloads, hostile paths/IDs, User isolation, and concurrent stale writes.
Author
Owner

Finding from the production Files e2e: the pin and drag/move flows passed, but the Trash check timed out because the revised breadcrumb/move sequence left the test on Home while alpha.txt remained in Inbox. I updated the test to reopen Inbox before the Trash action. No product failure was observed in this run; rerunning the full flow now.

Finding from the production Files e2e: the pin and drag/move flows passed, but the Trash check timed out because the revised breadcrumb/move sequence left the test on Home while `alpha.txt` remained in Inbox. I updated the test to reopen Inbox before the Trash action. No product failure was observed in this run; rerunning the full flow now.
Author
Owner

Follow-up e2e finding: the section-order assertion also raced the Files sidebar's first render. A focused production-server check showed the headings in the required order (Pinned, Smart folders) after the sidebar settled. I added waits for both headings before asserting their order, then will rerun the Files flow.

Follow-up e2e finding: the section-order assertion also raced the Files sidebar's first render. A focused production-server check showed the headings in the required order (`Pinned`, `Smart folders`) after the sidebar settled. I added waits for both headings before asserting their order, then will rerun the Files flow.
Author
Owner

Finding for #156: the Files pin store retained the loaded User's pin list after sign-out. The regression test reproduced it: after loading alice-private, dispatching the session-ended signal left that pin in pins.items. I am clearing the in-memory state on sign-out and reloading the server list after an auth change; generation checks will ignore replies from requests started for the prior User.

Finding for #156: the Files pin store retained the loaded User's pin list after sign-out. The regression test reproduced it: after loading `alice-private`, dispatching the session-ended signal left that pin in `pins.items`. I am clearing the in-memory state on sign-out and reloading the server list after an auth change; generation checks will ignore replies from requests started for the prior User.
Author
Owner

Finding for #156: I also reproduced a migration leak before the Files sidebar loaded. The regression test put alice-private in the legacy browser cache, dispatched sign-out, then loaded Pins with an empty revision-0 server list. The store exposed the legacy pin and attempted to save it for the next signed-in User. I am installing the session listeners when the client store is created; initial sign-in remains eligible for the one-time migration, and sign-out clears the legacy cache even if Files was not opened first.

Finding for #156: I also reproduced a migration leak before the Files sidebar loaded. The regression test put `alice-private` in the legacy browser cache, dispatched sign-out, then loaded Pins with an empty revision-0 server list. The store exposed the legacy pin and attempted to save it for the next signed-in User. I am installing the session listeners when the client store is created; initial sign-in remains eligible for the one-time migration, and sign-out clears the legacy cache even if Files was not opened first.
Author
Owner

Finding for #156: the per-User pins GET reused another User's cached response. A focused production-store regression loaded Alice's pins, dispatched sign-out, changed the mocked server list to Bob's pins, then dispatched calternal:auth-changed. The second fetch never reached the mock (call count remained 1), and the client reused the same 750 ms GET snapshot. I am bypassing GET coalescing for this endpoint and retaining the regression check for a fresh request after the User changes.

Finding for #156: the per-User pins GET reused another User's cached response. A focused production-store regression loaded Alice's pins, dispatched sign-out, changed the mocked server list to Bob's pins, then dispatched `calternal:auth-changed`. The second fetch never reached the mock (call count remained 1), and the client reused the same 750 ms GET snapshot. I am bypassing GET coalescing for this endpoint and retaining the regression check for a fresh request after the User changes.
Author
Owner

Finding for #156: the shared API GET coalescer also crossed User sessions outside Files Pins. A focused test completed an authenticated /api/v1/search GET, dispatched calternal:session-ended, and requested the same URL again. The fetch mock stayed at one call and returned the prior snapshot because the cache key cannot distinguish HttpOnly session cookies and the cache was not cleared by the auth event. I am invalidating and aborting pending coalesced requests on both calternal:session-ended and calternal:auth-changed.

Finding for #156: the shared API GET coalescer also crossed User sessions outside Files Pins. A focused test completed an authenticated `/api/v1/search` GET, dispatched `calternal:session-ended`, and requested the same URL again. The fetch mock stayed at one call and returned the prior snapshot because the cache key cannot distinguish HttpOnly session cookies and the cache was not cleared by the auth event. I am invalidating and aborting pending coalesced requests on both `calternal:session-ended` and `calternal:auth-changed`.
Author
Owner

Finding: the folded breadcrumb drag test times out because a top-level Menu's FloatingSurface renders a fixed full-viewport .fs-scrim at z-index 200 with pointer-events: auto. The file list is behind that scrim, so dragging a file while the breadcrumb menu is open cannot reach its drop rows. I am tracing the internal drag lifecycle to allow only that drop menu to receive an active Files drag while keeping normal outside-click dismissal intact.

Finding: the folded breadcrumb drag test times out because a top-level Menu's FloatingSurface renders a fixed full-viewport `.fs-scrim` at z-index 200 with `pointer-events: auto`. The file list is behind that scrim, so dragging a file while the breadcrumb menu is open cannot reach its drop rows. I am tracing the internal drag lifecycle to allow only that drop menu to receive an active Files drag while keeping normal outside-click dismissal intact.
Author
Owner

Finding: bun run check found two type errors in the session-cache regression at apps/web/src/lib/files/prefs.svelte.test.ts: its mock search envelope used a generation property that is not part of the API response type. I changed the mock to return typed search results with session-specific IDs and kept the assertions on the typed results field. The check is running again.

Finding: `bun run check` found two type errors in the session-cache regression at `apps/web/src/lib/files/prefs.svelte.test.ts`: its mock search envelope used a `generation` property that is not part of the API response type. I changed the mock to return typed search results with session-specific IDs and kept the assertions on the typed `results` field. The check is running again.
Author
Owner

Production-build Files E2E passed against a real local server. Output:

PASS drag to pin, keyboard reorder, per-User persistence, and unpin
PASS keyboard selection and Quick Look
PASS rename
PASS drag to move and Undo
PASS trash and restore
PASS upload with progress toast and live refresh
PASS live update from the files event stream
PASS /f/<item-id> deep link and missing-item state
PASS view remembered per folder
PASS public link created in the share dialog and opened without an account
PASS sidebar resizes by its edge
FILES E2E PASSED
Production-build Files E2E passed against a real local server. Output: ``` PASS drag to pin, keyboard reorder, per-User persistence, and unpin PASS keyboard selection and Quick Look PASS rename PASS drag to move and Undo PASS trash and restore PASS upload with progress toast and live refresh PASS live update from the files event stream PASS /f/<item-id> deep link and missing-item state PASS view remembered per folder PASS public link created in the share dialog and opened without an account PASS sidebar resizes by its edge FILES E2E PASSED ```
Author
Owner

Decision for the folded breadcrumb menu: when a menu has drop rows, do not place a full-screen scrim over the draggable source. Handle outside presses in capture phase instead. A normal outside press closes the menu and does not activate the row. A native drag that starts on a draggable row keeps the menu open so the drop rows can receive it. The header E2E will verify both paths.

Decision for the folded breadcrumb menu: when a menu has drop rows, do not place a full-screen scrim over the draggable source. Handle outside presses in capture phase instead. A normal outside press closes the menu and does not activate the row. A native drag that starts on a draggable row keeps the menu open so the drop rows can receive it. The header E2E will verify both paths.
Author
Owner

Resumed after the planned VM restart. Current head: 1bee359433bb5c41de8cb065a660cfb40b4fb175; merged the current dev tip e976bff6 (documentation only). node --check for both layout sweep scripts and git diff --check pass. The production web build is current with the UI fixes.

The final header sweep and adversarial round are waiting because other worktrees currently have Playwright browsers active. I am keeping to one browser run at a time on the shared host. No API or UI change came from the latest dev merge.

Resumed after the planned VM restart. Current head: `1bee359433bb5c41de8cb065a660cfb40b4fb175`; merged the current `dev` tip `e976bff6` (documentation only). `node --check` for both layout sweep scripts and `git diff --check` pass. The production web build is current with the UI fixes. The final header sweep and adversarial round are waiting because other worktrees currently have Playwright browsers active. I am keeping to one browser run at a time on the shared host. No API or UI change came from the latest `dev` merge.
Author
Owner

Production screenshots for Claude's visual review are committed at 4b803033. The 20-image subset is in artifacts/chrome-sidebar-review/ and covers Calendar, Files, Notes and Photos at 1440, 1024 and 390 widths, in Paper and Tokyo Night themes, with open/collapsed/phone sidebar states. These are real app screenshots, not mockups. The final interaction matrix remains pending after the folded-breadcrumb drag fix.

Production screenshots for Claude's visual review are committed at `4b803033`. The 20-image subset is in `artifacts/chrome-sidebar-review/` and covers Calendar, Files, Notes and Photos at 1440, 1024 and 390 widths, in Paper and Tokyo Night themes, with open/collapsed/phone sidebar states. These are real app screenshots, not mockups. The final interaction matrix remains pending after the folded-breadcrumb drag fix.
Author
Owner

Finding from the production header sweep: the run captured 148 screenshots. Four header screens calendar-week scrolled captures timed out waiting 5 seconds for the header to collapse: widths 1440 and 1024, in Paper and Tokyo Night. The other captured states completed. I am checking the existing header scroll-collapse assertions to determine whether this is a Calendar Week interaction failure or a screenshot-path timeout under shared-host load before changing code.

Finding from the production header sweep: the run captured 148 screenshots. Four `header screens calendar-week` scrolled captures timed out waiting 5 seconds for the header to collapse: widths 1440 and 1024, in Paper and Tokyo Night. The other captured states completed. I am checking the existing header scroll-collapse assertions to determine whether this is a Calendar Week interaction failure or a screenshot-path timeout under shared-host load before changing code.
Author
Owner

Root cause found: the production ModeHeader intentionally leaves the Calendar Week header expanded when the grid auto-scrolls to the current time. The dedicated collapseProblems check resets large inner scrollers to the top before a synthetic wheel; the screenshot path did not. The focused HEADER_SECTIONS=collapse run then completed with exactly:

checked 0 screens
LAYOUT SWEEP PASSED

This identifies a screenshot-test setup issue, not a Calendar Week collapse failure. I will share the existing scroller reset helper with the screenshot path so it starts from a known scroll position.

Root cause found: the production `ModeHeader` intentionally leaves the Calendar Week header expanded when the grid auto-scrolls to the current time. The dedicated `collapseProblems` check resets large inner scrollers to the top before a synthetic wheel; the screenshot path did not. The focused `HEADER_SECTIONS=collapse` run then completed with exactly: ``` checked 0 screens LAYOUT SWEEP PASSED ``` This identifies a screenshot-test setup issue, not a Calendar Week collapse failure. I will share the existing scroller reset helper with the screenshot path so it starts from a known scroll position.
Author
Owner

The Calendar Week screenshot issue is resolved. I extracted the existing large-scroller reset into one helper and call it before both collapse assertions and scrolled screenshots. The production header sweep then completed with the exact output:

checked 0 screens
LAYOUT SWEEP PASSED

It saved 150 screenshots. The refreshed 27-image review subset is committed at 8beb8f08 under artifacts/chrome-sidebar-review/.

The Calendar Week screenshot issue is resolved. I extracted the existing large-scroller reset into one helper and call it before both collapse assertions and scrolled screenshots. The production header sweep then completed with the exact output: ``` checked 0 screens LAYOUT SWEEP PASSED ``` It saved 150 screenshots. The refreshed 27-image review subset is committed at `8beb8f08` under `artifacts/chrome-sidebar-review/`.
Author
Owner

Finding before the API probes: tests/adversarial/run.sh rebuilt the web app, then Cargo stopped while compiling calternal-db. The compiler tried to write deps.d under another worktree's analytics/target/tmp/sccacheBWHlOC, which was no longer present. No adversarial endpoint ran. I am retrying with SCCACHE_DISABLE=1; the runner sets this worktree's TMPDIR to target/tmp.

Finding before the API probes: `tests/adversarial/run.sh` rebuilt the web app, then Cargo stopped while compiling `calternal-db`. The compiler tried to write `deps.d` under another worktree's `analytics/target/tmp/sccacheBWHlOC`, which was no longer present. No adversarial endpoint ran. I am retrying with `SCCACHE_DISABLE=1`; the runner sets this worktree's `TMPDIR` to `target/tmp`.
Author
Owner

Follow-up on the build blocker: SCCACHE_DISABLE=1 did not bypass the configured RUSTC_WRAPPER=/home/kayg/.nix-profile/bin/sccache; rustc still failed to create temp directories under the Analytics worktree. No endpoint probes ran. The next retry will unset RUSTC_WRAPPER so the build uses rustc directly and the worktree-local TMPDIR.

Follow-up on the build blocker: `SCCACHE_DISABLE=1` did not bypass the configured `RUSTC_WRAPPER=/home/kayg/.nix-profile/bin/sccache`; rustc still failed to create temp directories under the Analytics worktree. No endpoint probes ran. The next retry will unset `RUSTC_WRAPPER` so the build uses rustc directly and the worktree-local `TMPDIR`.
Author
Owner

Adversarial triage update for #156

The local round has surfaced three non-SLOW findings. I am tracing these before deciding whether they are product defects or effects of the shared host load.

  • Photos sharing: after the Share was created and User B opted into Shared/<owner>/Photos, the Photos timeline returned 200 {"days":[]} for the full 12-second poll. The adversarial database later showed the uploaded photo in User B's photos_media, photos_groups, and photos_days rows. The Share was revoked by the time I inspected the database, so I am still tracing the active-read path.
  • Sync: the initial sync did not satisfy the condition that all 11 newly created files appear remotely within 25 seconds. Some expected paths were present; the probe's finding does not include the exact missing count. I am checking the daemon trace and will reproduce this after the active round.
  • Bookmark capture: the 16-request bookmark storm returned 201 for 6 requests and timed out 10 requests at the probe's 10-second client timeout. The single bookmark baseline took 7.0 seconds under the current host load, so I am checking whether this is queueing under load or an endpoint issue.

The hostile-file round reported 0 findings. The server remained alive. The other reported latency notices are SLOW-only and count as host load under the owner rule. No fix is being attempted until the active round finishes and these results are isolated.

Adversarial triage update for #156 The local round has surfaced three non-SLOW findings. I am tracing these before deciding whether they are product defects or effects of the shared host load. - Photos sharing: after the Share was created and User B opted into `Shared/<owner>/Photos`, the Photos timeline returned `200 {"days":[]}` for the full 12-second poll. The adversarial database later showed the uploaded photo in User B's `photos_media`, `photos_groups`, and `photos_days` rows. The Share was revoked by the time I inspected the database, so I am still tracing the active-read path. - Sync: the initial sync did not satisfy the condition that all 11 newly created files appear remotely within 25 seconds. Some expected paths were present; the probe's finding does not include the exact missing count. I am checking the daemon trace and will reproduce this after the active round. - Bookmark capture: the 16-request bookmark storm returned 201 for 6 requests and timed out 10 requests at the probe's 10-second client timeout. The single bookmark baseline took 7.0 seconds under the current host load, so I am checking whether this is queueing under load or an endpoint issue. The hostile-file round reported 0 findings. The server remained alive. The other reported latency notices are SLOW-only and count as host load under the owner rule. No fix is being attempted until the active round finishes and these results are isolated.
Author
Owner

Resuming #156 after the planned VM restart. Branch: job/chrome-sidebar. Current head: db2180cebf338d824d5fe1cb760cd4ab87f2c0da. Current merge base with dev: 116cd780b2b5c175e4728ed229965d3f790fb8df. The worktree is clean. The production UI work and screenshots are committed; I am continuing from the pending adversarial triage and final verification.

Resuming #156 after the planned VM restart. Branch: `job/chrome-sidebar`. Current head: `db2180cebf338d824d5fe1cb760cd4ab87f2c0da`. Current merge base with `dev`: `116cd780b2b5c175e4728ed229965d3f790fb8df`. The worktree is clean. The production UI work and screenshots are committed; I am continuing from the pending adversarial triage and final verification.
Author
Owner

Finding during the required dev merge: cargo test -p calternal-plugin-files initially failed only media::tests::timeout_kills_the_whole_media_process_group (100 passed, 1 failed). The isolated test failed in 1.02 seconds with stale state Some("R"); the 10-second polling loop had exited when /proc/<pid>/stat disappeared after the last R read. I cleared the saved state on NotFound and kept unexpected /proc errors fatal. The focused test then passed, and the full crate rerun passed: 101 passed, 0 failed; doc-tests: 0 passed, 0 failed. The process-group implementation did not change.

Finding during the required `dev` merge: `cargo test -p calternal-plugin-files` initially failed only `media::tests::timeout_kills_the_whole_media_process_group` (100 passed, 1 failed). The isolated test failed in 1.02 seconds with stale state `Some("R")`; the 10-second polling loop had exited when `/proc/<pid>/stat` disappeared after the last `R` read. I cleared the saved state on `NotFound` and kept unexpected `/proc` errors fatal. The focused test then passed, and the full crate rerun passed: 101 passed, 0 failed; doc-tests: 0 passed, 0 failed. The process-group implementation did not change.
Author
Owner

Post-merge Pins probe finding: an unknown field returns Axum's 422 plain-text rejection, but /api/v1/files/pins documents 400 with ErrorEnvelope; tests/adversarial/attack2.py flagged the mismatch. I will map request JSON rejections to the endpoint's standard 400 response and keep a regression check. The separate-User isolation subcheck also reused token B after the earlier share-options section removed that User; its 401 is a probe lifecycle defect, which I will correct by refreshing the probe actor.

Post-merge Pins probe finding: an unknown field returns Axum's 422 plain-text rejection, but `/api/v1/files/pins` documents 400 with `ErrorEnvelope`; `tests/adversarial/attack2.py` flagged the mismatch. I will map request JSON rejections to the endpoint's standard 400 response and keep a regression check. The separate-User isolation subcheck also reused token B after the earlier share-options section removed that User; its 401 is a probe lifecycle defect, which I will correct by refreshing the probe actor.
Author
Owner

Fixed and committed the post-merge Pins findings at ba330d11. PUT /api/v1/files/pins now maps Axum JSON extraction failures to the documented 400 ErrorEnvelope, and keeps oversized requests at 413 with the same envelope. The adversarial per-User check now runs before deletion probes remove its member fixture.

Verification:

cargo test -p calternal-plugin-files files_pins_
3 passed; 0 failed

cargo test -p calternal-plugin-files
102 passed; 0 failed; doc-tests 0 passed; 0 failed

cargo clippy -p calternal-plugin-files --all-targets -- -D warnings
Finished `dev` profile [unoptimized + debuginfo] target(s) in 3m 52s
Fixed and committed the post-merge Pins findings at `ba330d11`. `PUT /api/v1/files/pins` now maps Axum JSON extraction failures to the documented 400 `ErrorEnvelope`, and keeps oversized requests at 413 with the same envelope. The adversarial per-User check now runs before deletion probes remove its member fixture. Verification: ``` cargo test -p calternal-plugin-files files_pins_ 3 passed; 0 failed cargo test -p calternal-plugin-files 102 passed; 0 failed; doc-tests 0 passed; 0 failed cargo clippy -p calternal-plugin-files --all-targets -- -D warnings Finished `dev` profile [unoptimized + debuginfo] target(s) in 3m 52s ```
Author
Owner

Post-merge adversarial finding and fix: attack2.py ran user-deletion probes before the Files share-options section. The transfer probe removed the only member account, so the dot-file share check printed dot files: member probe skipped (no member left). I moved deletion after the share-options section. A focused real-server run now prints dot files: member probe runs and reports no dot-file member leak. The fix is committed as 8b9394b0.

The same run again found no photo thumbnail after 30 seconds; thumbnail endpoints returned 404 because the local media worker is unavailable here. This remains tracked by #209. The feed, sync, isolation, Pins and restart probes reported no non-SLOW failure; latency notices were classified as shared-host load.

Post-merge adversarial finding and fix: `attack2.py` ran user-deletion probes before the Files share-options section. The transfer probe removed the only member account, so the dot-file share check printed `dot files: member probe skipped (no member left)`. I moved deletion after the share-options section. A focused real-server run now prints `dot files: member probe runs` and reports no dot-file member leak. The fix is committed as `8b9394b0`. The same run again found no photo thumbnail after 30 seconds; thumbnail endpoints returned 404 because the local media worker is unavailable here. This remains tracked by #209. The feed, sync, isolation, Pins and restart probes reported no non-SLOW failure; latency notices were classified as shared-host load.
Author
Owner

Finding from production Files E2E after the latest dev merge: pin drag/reorder/persistence, keyboard selection, Quick Look, rename, move/undo, trash/restore, and UI upload passed. The next API upload returned 201, but from-elsewhere.txt did not appear in the already-open Archive view within 10 seconds. I am checking the Files SSE event and refresh path with a focused real-server reproduction before changing code.

Finding from production Files E2E after the latest `dev` merge: pin drag/reorder/persistence, keyboard selection, Quick Look, rename, move/undo, trash/restore, and UI upload passed. The next API upload returned 201, but `from-elsewhere.txt` did not appear in the already-open Archive view within 10 seconds. I am checking the Files SSE event and refresh path with a focused real-server reproduction before changing code.
Author
Owner

Finding after the latest dev merge: the web suite reported 56/57 files and 433/433 tests passing, while notes.test.ts could not resolve @calternal/ui/floating from packages/editor/src/slash.ts. The editor already declared the workspace dependency and the lockfile was current; this worktree was missing the packages/editor/node_modules/@calternal/ui workspace link. bun install --frozen-lockfile reported Checked 267 installs across 312 packages (no changes) and restored the link. The focused Notes suite then passed: 1 file, 9 tests. No source or lockfile change was needed.

Finding after the latest dev merge: the web suite reported 56/57 files and 433/433 tests passing, while `notes.test.ts` could not resolve `@calternal/ui/floating` from `packages/editor/src/slash.ts`. The editor already declared the workspace dependency and the lockfile was current; this worktree was missing the `packages/editor/node_modules/@calternal/ui` workspace link. `bun install --frozen-lockfile` reported `Checked 267 installs across 312 packages (no changes)` and restored the link. The focused Notes suite then passed: 1 file, 9 tests. No source or lockfile change was needed.
Author
Owner

Finding in the merged production Files E2E: the a Files load sends each GET once assertion saw two GETs for entries?path=Inbox&limit=500&sort=name. This was the test's full page.goto reopening EventSource, not a duplicate inside one listing: /api/v1/files/events starts at Last-Event-ID 0 and replays the last 10 minutes; the live-change listener then correctly schedules one no-store reconciliation GET. I am changing the dedupe check to navigate folders within the same SPA session so the event stream does not replay fixture writes; the separate live-update E2E will keep checking catch-up behavior.

Finding in the merged production Files E2E: the `a Files load sends each GET once` assertion saw two GETs for `entries?path=Inbox&limit=500&sort=name`. This was the test's full `page.goto` reopening `EventSource`, not a duplicate inside one listing: `/api/v1/files/events` starts at Last-Event-ID 0 and replays the last 10 minutes; the live-change listener then correctly schedules one `no-store` reconciliation GET. I am changing the dedupe check to navigate folders within the same SPA session so the event stream does not replay fixture writes; the separate live-update E2E will keep checking catch-up behavior.
Author
Owner

Finding from the second production Files E2E run: moving between folders in the same SPA session still observed two GETs for the root listing. The root path intentionally matches any recent file event, so the EventSource catch-up reconciliation can schedule one no-store root reload. The coalescing check now opens Home first and waits for that durable replay to drain before measuring a later folder switch. This is E2E setup behavior; the live root reconciliation is expected. The revised E2E is committed at 8976baa3; its clean rerun is pending while other worktrees are using Chromium.

Finding from the second production Files E2E run: moving between folders in the same SPA session still observed two GETs for the root listing. The root path intentionally matches any recent file event, so the EventSource catch-up reconciliation can schedule one `no-store` root reload. The coalescing check now opens Home first and waits for that durable replay to drain before measuring a later folder switch. This is E2E setup behavior; the live root reconciliation is expected. The revised E2E is committed at `8976baa3`; its clean rerun is pending while other worktrees are using Chromium.
Author
Owner

Files E2E retest after 8976baa3 passed against the production web build and local server. Exact output:

PASS drag to pin, keyboard reorder, per-User persistence, and unpin
PASS keyboard selection and Quick Look
PASS rename
PASS drag to move and Undo
PASS trash and restore
PASS upload with progress toast and live refresh
PASS live update from the files event stream
PASS /f/<item-id> deep link and missing-item state
PASS view remembered per folder
PASS public link created in the share dialog and opened without an account
PASS sidebar resizes by its edge
FILES E2E PASSED

The root-listing SSE catch-up adjustment lets the same-session coalescing assertion pass; live reconciliation remains covered by the dedicated live-update checks.

Files E2E retest after `8976baa3` passed against the production web build and local server. Exact output: ``` PASS drag to pin, keyboard reorder, per-User persistence, and unpin PASS keyboard selection and Quick Look PASS rename PASS drag to move and Undo PASS trash and restore PASS upload with progress toast and live refresh PASS live update from the files event stream PASS /f/<item-id> deep link and missing-item state PASS view remembered per folder PASS public link created in the share dialog and opened without an account PASS sidebar resizes by its edge FILES E2E PASSED ``` The root-listing SSE catch-up adjustment lets the same-session coalescing assertion pass; live reconciliation remains covered by the dedicated live-update checks.
Author
Owner

Finding from the production layout sweep: all 336 main-matrix screenshots were captured before the final offline check failed. layout-sweep.mjs waited for the You are offline heading, then read #route-content as Name / Modified / Size / Kind / Loading 0 items… / 0 items instead of the expected “not loaded on your device yet” message. No layout assertion failed. I am isolating this offline state to determine whether the assertion races the route error render or the product leaves stale Files content visible.

Finding from the production layout sweep: all 336 main-matrix screenshots were captured before the final offline check failed. `layout-sweep.mjs` waited for the `You are offline` heading, then read `#route-content` as `Name / Modified / Size / Kind / Loading 0 items… / 0 items` instead of the expected “not loaded on your device yet” message. No layout assertion failed. I am isolating this offline state to determine whether the assertion races the route error render or the product leaves stale Files content visible.
Author
Owner

Resuming #156 after the VM restart. Branch: job/chrome-sidebar. Original base SHA: c2a81aeab9fd6090cb4eba448af5835c4877e7de (dev). Current head: 182817ee93c938cd0674689733b85783135c7efe. The prior run was stopped while isolating the production layout sweep offline-state assertion. I am reviewing that checkpoint, merging current dev before final gates, then I will finish the remaining UI/E2E and adversarial verification.

Resuming #156 after the VM restart. Branch: `job/chrome-sidebar`. Original base SHA: `c2a81aeab9fd6090cb4eba448af5835c4877e7de` (`dev`). Current head: `182817ee93c938cd0674689733b85783135c7efe`. The prior run was stopped while isolating the production layout sweep offline-state assertion. I am reviewing that checkpoint, merging current `dev` before final gates, then I will finish the remaining UI/E2E and adversarial verification.
Author
Owner

Finding after merging the current dev tip f6418fc7: the new Analytics mode has a Ranges sidebar and a period title menu, but the explicit #156 sidebar/title matrix only covered Files, Calendar, Photos, Notes, and Ask. Analytics was present in the general layout sweep, but this shared rule had no focused coverage for Analytics with the sidebar open, collapsed, or as a phone sheet. I am adding it to the same real-route matrix.

Finding after merging the current `dev` tip `f6418fc7`: the new Analytics mode has a Ranges sidebar and a period title menu, but the explicit #156 sidebar/title matrix only covered Files, Calendar, Photos, Notes, and Ask. Analytics was present in the general layout sweep, but this shared rule had no focused coverage for Analytics with the sidebar open, collapsed, or as a phone sheet. I am adding it to the same real-route matrix.
Author
Owner

Finding during final web check after the dev merge: bun run check stopped with svelte-check found 497 errors and 0 warnings in 59 files. The first and representative errors are unresolved modules from the Analytics work merged from dev (react, @visx/scale, @testing-library/svelte, torph/svelte); the source changes in this branch are not implicated. I am restoring the worktree dependency links with the frozen lockfile, then rerunning check.

Finding during final web check after the `dev` merge: `bun run check` stopped with `svelte-check found 497 errors and 0 warnings in 59 files`. The first and representative errors are unresolved modules from the Analytics work merged from `dev` (`react`, `@visx/scale`, `@testing-library/svelte`, `torph/svelte`); the source changes in this branch are not implicated. I am restoring the worktree dependency links with the frozen lockfile, then rerunning check.
Author
Owner

The offline-state check now passes against the rebuilt production app when run directly with bun e2e/layout-sweep.mjs --only offline:\n\n\nchecked 0 screens\nLAYOUT SWEEP PASSED\n\n\nThe broad screenshot-enabled sweep captured all 336 main layout screens but exceeded a 30-minute time box in its later interaction section, so I stopped that run. I am running the pending title/sidebar matrix and review captures as focused header sections.

The offline-state check now passes against the rebuilt production app when run directly with `bun e2e/layout-sweep.mjs --only offline`:\n\n```\nchecked 0 screens\nLAYOUT SWEEP PASSED\n```\n\nThe broad screenshot-enabled sweep captured all 336 main layout screens but exceeded a 30-minute time box in its later interaction section, so I stopped that run. I am running the pending title/sidebar matrix and review captures as focused header sections.
Author
Owner

Correction with the line breaks preserved: the offline-state check passes against the rebuilt production app when run directly with bun e2e/layout-sweep.mjs --only offline:

checked 0 screens
LAYOUT SWEEP PASSED

The broad screenshot-enabled sweep captured all 336 main layout screens but exceeded a 30-minute time box in its later interaction section, so I stopped that run. I am running the pending title/sidebar matrix and review captures as focused header sections.

Correction with the line breaks preserved: the offline-state check passes against the rebuilt production app when run directly with `bun e2e/layout-sweep.mjs --only offline`: ``` checked 0 screens LAYOUT SWEEP PASSED ``` The broad screenshot-enabled sweep captured all 336 main layout screens but exceeded a 30-minute time box in its later interaction section, so I stopped that run. I am running the pending title/sidebar matrix and review captures as focused header sections.
Author
Owner

The offline assertion passed. The focused title/sidebar matrix did not reach its checks: I found a live menu-icons layout sweep on the shared host, stopped this job's browser to honor the one-browser limit, and removed this run's server/browser process. Its Target page, context or browser has been closed output is from that intentional stop. I will retry the matrix when the other sweep exits; no product failure was observed.

The offline assertion passed. The focused title/sidebar matrix did not reach its checks: I found a live `menu-icons` layout sweep on the shared host, stopped this job's browser to honor the one-browser limit, and removed this run's server/browser process. Its `Target page, context or browser has been closed` output is from that intentional stop. I will retry the matrix when the other sweep exits; no product failure was observed.
Author
Owner

Current-branch Files regression run passed after merging dev:

test result: ok. 102 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 70.47s

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

This includes the Pins JSON rejection, size-limit, per-User isolation and settings-preservation tests.

Current-branch Files regression run passed after merging `dev`: ``` test result: ok. 102 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 70.47s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` This includes the Pins JSON rejection, size-limit, per-User isolation and settings-preservation tests.
Author
Owner

dev advanced from f6418fc7 to 8b8e5cc9 while the shared-host checks were running. I am merging the latest dev tip before final gates, as requested; this tip includes the sync-root guard, toast and share-edit merges.

`dev` advanced from `f6418fc7` to `8b8e5cc9` while the shared-host checks were running. I am merging the latest `dev` tip before final gates, as requested; this tip includes the sync-root guard, toast and share-edit merges.
Author
Owner

Merged the latest dev tip 21ee397d into job/chrome-sidebar in 1f36b255. Resolved the layout-sweep.mjs conflict by preserving the breadcrumb upload fixture and incoming Agenda seed, and by retaining the exact offline fallback text with an explicit visible-state wait. node --check, git diff --check, and the merged web gates pass so far: bun run check reports 0 errors and 0 warnings; bun run test reports 71 files and 547 tests passed. I am continuing with production-build screenshot review and the remaining workspace gates.

Merged the latest `dev` tip `21ee397d` into `job/chrome-sidebar` in `1f36b255`. Resolved the `layout-sweep.mjs` conflict by preserving the breadcrumb upload fixture and incoming Agenda seed, and by retaining the exact offline fallback text with an explicit visible-state wait. `node --check`, `git diff --check`, and the merged web gates pass so far: `bun run check` reports 0 errors and 0 warnings; `bun run test` reports 71 files and 547 tests passed. I am continuing with production-build screenshot review and the remaining workspace gates.
Author
Owner

The post-merge --only offline browser run passed the offline fallback assertion but the runner's unconditional Agenda stress tail reported:

checked 0 screens
FAIL agenda 320: waitFor: Timeout 30000ms exceeded.
FAIL agenda zoom200: waitFor: Timeout 30000ms exceeded.

The same Agenda stress checks passed in the immediately prior post-merge --only headers run, which also captured the 16 Agenda screenshots. At least four other worktrees had active cargo test processes during the timeout run. I am treating this as an intermittent timing result pending one retry after the shared CPU load clears; no application code change has been made for it.

The post-merge `--only offline` browser run passed the offline fallback assertion but the runner's unconditional Agenda stress tail reported: ``` checked 0 screens FAIL agenda 320: waitFor: Timeout 30000ms exceeded. FAIL agenda zoom200: waitFor: Timeout 30000ms exceeded. ``` The same Agenda stress checks passed in the immediately prior post-merge `--only headers` run, which also captured the 16 Agenda screenshots. At least four other worktrees had active `cargo test` processes during the timeout run. I am treating this as an intermittent timing result pending one retry after the shared CPU load clears; no application code change has been made for it.
Author
Owner

The focused production browser sweep against the merged tree passed. The command ran Calendar title and shared sidebar matrix checks, Agenda adversarial checks, and screenshots. Exact stdout:

checked 0 screens
LAYOUT SWEEP PASSED

checked 0 screens is expected for --only headers; the mode-header checks still ran. It captured 170 header review screenshots and 16 Agenda review screenshots. The Agenda screenshots are committed in ca9d6c26062add2a0aa208beaef83da8ca38f155 under artifacts/chrome-sidebar-review/.

The focused production browser sweep against the merged tree passed. The command ran Calendar title and shared sidebar matrix checks, Agenda adversarial checks, and screenshots. Exact stdout: ``` checked 0 screens LAYOUT SWEEP PASSED ``` `checked 0 screens` is expected for `--only headers`; the mode-header checks still ran. It captured 170 header review screenshots and 16 Agenda review screenshots. The Agenda screenshots are committed in `ca9d6c26062add2a0aa208beaef83da8ca38f155` under `artifacts/chrome-sidebar-review/`.
Author
Owner

Root cause confirmed: agendaAdversarial() ran unconditionally after every --only section, so --only offline also exercised the 320px and 200% zoom Agenda checks. I gated it to the full sweep or --only agenda in b2b01bbc.

After the fix, the isolated merged-tree offline run passed with exact stdout:

checked 0 screens
LAYOUT SWEEP PASSED

The earlier full --only headers run passed the Agenda adversarial checks before the selector fix. No application behavior changed for this finding.

Root cause confirmed: `agendaAdversarial()` ran unconditionally after every `--only` section, so `--only offline` also exercised the 320px and 200% zoom Agenda checks. I gated it to the full sweep or `--only agenda` in `b2b01bbc`. After the fix, the isolated merged-tree offline run passed with exact stdout: ``` checked 0 screens LAYOUT SWEEP PASSED ``` The earlier full `--only headers` run passed the Agenda adversarial checks before the selector fix. No application behavior changed for this finding.
Author
Owner

dev advanced to cf142cb4 during the shared-host wait, so I merged it before final gates in 0374bd18. The merge was clean. It adds the media sandbox runtime probe and changes thumbnail reads to use the open descriptor; I am including those changes in the remaining E2E, adversarial, and workspace gate runs.

`dev` advanced to `cf142cb4` during the shared-host wait, so I merged it before final gates in `0374bd18`. The merge was clean. It adds the media sandbox runtime probe and changes thumbnail reads to use the open descriptor; I am including those changes in the remaining E2E, adversarial, and workspace gate runs.
Author
Owner

dev advanced again to eb9acfcc; I merged it cleanly in b147a205 before proceeding. This tip adds generated OpenAPI contract and API client entries. I am rerunning the final web checks and will include the merged contract in the workspace and adversarial validation.

`dev` advanced again to `eb9acfcc`; I merged it cleanly in `b147a205` before proceeding. This tip adds generated OpenAPI contract and API client entries. I am rerunning the final web checks and will include the merged contract in the workspace and adversarial validation.
Author
Owner

Merged current dev tip c82549b9 in f507d9f5 with a clean worktree and no conflict resolution needed. Post-merge web gates:

bun run check
svelte-check found 0 errors and 0 warnings

bun run test
Test Files  73 passed (73)
Tests  553 passed (553)

bun run build exited 0 and wrote apps/web/build. It still emits the existing vendored Analytics use client module-level directive warnings. I am waiting for the active shared-host adversarial/browser runs to finish before starting this branch's required real-server adversarial round.

Merged current `dev` tip `c82549b9` in `f507d9f5` with a clean worktree and no conflict resolution needed. Post-merge web gates: ``` bun run check svelte-check found 0 errors and 0 warnings bun run test Test Files 73 passed (73) Tests 553 passed (553) ``` `bun run build` exited 0 and wrote `apps/web/build`. It still emits the existing vendored Analytics `use client` module-level directive warnings. I am waiting for the active shared-host adversarial/browser runs to finish before starting this branch's required real-server adversarial round.
Author
Owner

dev advanced to f170d4e9 during the shared-host checks; merged it in e3bcb076 before final gates. This tip changes the o2 deployment names and single-instance wording in docs/DESIGN.md; it adds no API surface. The previous merged API work and Files pins remain in scope for the adversarial round. The worktree is clean and dev is an ancestor of this branch.

`dev` advanced to `f170d4e9` during the shared-host checks; merged it in `e3bcb076` before final gates. This tip changes the o2 deployment names and single-instance wording in `docs/DESIGN.md`; it adds no API surface. The previous merged API work and Files pins remain in scope for the adversarial round. The worktree is clean and `dev` is an ancestor of this branch.
Author
Owner

The merged-tree production header sweep is still pending. Two attempts were stopped after other worktrees launched Chromium during our browser session. The latest title-only run was interrupted when menu-icons opened its browser and printed:

checked 0 screens
FAIL Files breadcrumbs: waitFor: Target page, context or browser has been closed

This is the harness reporting the controlled browser stop; the run did not reach a product assertion. I will retry after the shared browser sessions clear.

The merged-tree production header sweep is still pending. Two attempts were stopped after other worktrees launched Chromium during our browser session. The latest title-only run was interrupted when `menu-icons` opened its browser and printed: ``` checked 0 screens FAIL Files breadcrumbs: waitFor: Target page, context or browser has been closed ``` This is the harness reporting the controlled browser stop; the run did not reach a product assertion. I will retry after the shared browser sessions clear.
Author
Owner

dev advanced to 32b115dc; merged the README-only deployment note in 3110d9cd before gates. This tip adds no API surface. The worktree is clean, dev is an ancestor, and git diff --check dev..HEAD exits 0.

`dev` advanced to `32b115dc`; merged the README-only deployment note in `3110d9cd` before gates. This tip adds no API surface. The worktree is clean, `dev` is an ancestor, and `git diff --check dev..HEAD` exits 0.
Author
Owner

Starting the required full real-server adversarial round on job/chrome-sidebar at 3110d9cd, based on merged dev 32b115dc. It covers the Files Pins API and the current merged server/API changes. The browser slot is clear at launch. I will classify SLOW-only results as shared-host load and fix or file any other finding.

Starting the required full real-server adversarial round on `job/chrome-sidebar` at `3110d9cd`, based on merged `dev` `32b115dc`. It covers the Files Pins API and the current merged server/API changes. The browser slot is clear at launch. I will classify SLOW-only results as shared-host load and fix or file any other finding.
Author
Owner

Adversarial round progress on 3110d9cd:

Authorization matrix: 231 OpenAPI operations x 4 identities = 924 requests
Appearance PUT burst: p95=3.456s (31 concurrent requests)
search storm: 0 failures, p50=546.0ms p95=749.0ms
concurrent PATCH: 1 succeeded of 20
rename race: 1 succeeded, 0 errors

The authorization matrix printed no policy failures. The passkey fixture line 28/30 is its setup budget counter. The Appearance latency result exceeds the 0.500s target and is classified as SLOW-only shared-host load per the owner rule. The runner is continuing through the media, hostile-file, round 2 and restart probes.

Adversarial round progress on `3110d9cd`: ``` Authorization matrix: 231 OpenAPI operations x 4 identities = 924 requests Appearance PUT burst: p95=3.456s (31 concurrent requests) search storm: 0 failures, p50=546.0ms p95=749.0ms concurrent PATCH: 1 succeeded of 20 rename race: 1 succeeded, 0 errors ``` The authorization matrix printed no policy failures. The passkey fixture line `28/30` is its setup budget counter. The Appearance latency result exceeds the 0.500s target and is classified as SLOW-only shared-host load per the owner rule. The runner is continuing through the media, hostile-file, round 2 and restart probes.
Author
Owner

The active round has two additional SLOW-only notices:

!! Files Note rename: SLOW 5.7s status 204
!! DAV Basic app password: SLOW 6.0s status 207

They are latency notices with successful 204/207 responses. Along with the Appearance PUT burst p95=3.456s, these are classified as shared-host load under the owner rule. No non-SLOW finding has appeared in the output so far; media and hostile-file probes are still running.

The active round has two additional SLOW-only notices: ``` !! Files Note rename: SLOW 5.7s status 204 !! DAV Basic app password: SLOW 6.0s status 207 ``` They are latency notices with successful 204/207 responses. Along with the Appearance PUT burst p95=3.456s, these are classified as shared-host load under the owner rule. No non-SLOW finding has appeared in the output so far; media and hostile-file probes are still running.
Author
Owner

Additional DAV results from the active adversarial round:

!! DAV discovery: SLOW 5.4s status 207
!! DAV initial sync: SLOW 16.5s status 207
!! DAV create: SLOW 6.0s status 201
!! DAV cross-date move: SLOW 6.0s status 201

All reported statuses are successful DAV responses; these are SLOW-only latency notices under the owner rule. The rest of the round is still running.

Additional DAV results from the active adversarial round: ``` !! DAV discovery: SLOW 5.4s status 207 !! DAV initial sync: SLOW 16.5s status 207 !! DAV create: SLOW 6.0s status 201 !! DAV cross-date move: SLOW 6.0s status 201 ``` All reported statuses are successful DAV responses; these are SLOW-only latency notices under the owner rule. The rest of the round is still running.
Author
Owner

Cross-plugin adversarial progress:

calendar duplicate account storm: 20 conflicts, 0 unexpected statuses
!! calendar Event from Note: SLOW 10.4s status 201
!! calendar linked Log create: SLOW 5.6s status 201
!! calendar Event from Log: SLOW 17.3s status 201
!! Journal PATCH storm: SLOW 5.8–5.9s status 412
!! Journal DELETE stale condition: SLOW 5.6s status 412
!! template create daily folder: SLOW 6.4s status 400
!! template file chunk Oversized.md: SLOW 13.6s status 204
!! template file chunk Invalid YAML.md: SLOW 7.3s status 204

The status codes match the probe's expected conflict, rejection, and upload results. The latency lines are SLOW-only shared-host load. The full round is still running; no non-SLOW finding has appeared in the output so far.

Cross-plugin adversarial progress: ``` calendar duplicate account storm: 20 conflicts, 0 unexpected statuses !! calendar Event from Note: SLOW 10.4s status 201 !! calendar linked Log create: SLOW 5.6s status 201 !! calendar Event from Log: SLOW 17.3s status 201 !! Journal PATCH storm: SLOW 5.8–5.9s status 412 !! Journal DELETE stale condition: SLOW 5.6s status 412 !! template create daily folder: SLOW 6.4s status 400 !! template file chunk Oversized.md: SLOW 13.6s status 204 !! template file chunk Invalid YAML.md: SLOW 7.3s status 204 ``` The status codes match the probe's expected conflict, rejection, and upload results. The latency lines are SLOW-only shared-host load. The full round is still running; no non-SLOW finding has appeared in the output so far.
Author
Owner

Round 1 completed on the real local server:

==== FINDINGS 31
server alive at end: True
HEIF/AVIF upload probe passed
thumbnail: none generated in 10 s (media worker busy or missing); header check skipped
==== HOSTILE BYTES FINDINGS 0

All 31 entries printed in FINDINGS were SLOW-only latency notices. The hostile-byte probe found no issue. The thumbnail check was skipped because this host's media worker is busy or unavailable; that remains the existing local-runtime gap tracked by #209. Pins isolation and subsequent sections are in progress.

Round 1 completed on the real local server: ``` ==== FINDINGS 31 server alive at end: True HEIF/AVIF upload probe passed thumbnail: none generated in 10 s (media worker busy or missing); header check skipped ==== HOSTILE BYTES FINDINGS 0 ``` All 31 entries printed in `FINDINGS` were SLOW-only latency notices. The hostile-byte probe found no issue. The thumbnail check was skipped because this host's media worker is busy or unavailable; that remains the existing local-runtime gap tracked by #209. Pins isolation and subsequent sections are in progress.
Author
Owner

The deep-link and logrewrite probes have only produced SLOW latency notices on successful responses:

!! deep link: create log entry: SLOW 5.1s status 201
!! logrewrite: seed 09:00 - 10:30 Mornin: SLOW 8.3s status 201
!! logrewrite: seed 14:00 - 15:30 Wrote : SLOW 6.5s status 201
!! logrewrite: seed 12:00 Café ☕ 会議 🧪 ou: SLOW 6.0s status 201
!! logrewrite: resize first: SLOW 5.7s status 200

These are shared-host load notices. The deep-link and logrewrite sections continue.

The deep-link and logrewrite probes have only produced SLOW latency notices on successful responses: ``` !! deep link: create log entry: SLOW 5.1s status 201 !! logrewrite: seed 09:00 - 10:30 Mornin: SLOW 8.3s status 201 !! logrewrite: seed 14:00 - 15:30 Wrote : SLOW 6.5s status 201 !! logrewrite: seed 12:00 Café ☕ 会議 🧪 ou: SLOW 6.0s status 201 !! logrewrite: resize first: SLOW 5.7s status 200 ``` These are shared-host load notices. The deep-link and logrewrite sections continue.
Author
Owner

Adversarial round complete on 3110d9cd5cb8c40581ff5ec25804ba03e6f26445 against dev base 32b115dc6338b262d7c5a313a24d25f24d3c2637.

The runner exited 1 because its threshold treats latency outliers as findings: round 1 reported 31 findings and round 2 reported 5. Every reported item was marked SLOW; there were no 5xx responses, crashes, accepted hostile input, or inconsistent outcomes. Both rounds ended with the server alive. Hostile-byte checks reported 0 findings, the 924-request authorization matrix printed no policy failures, and the restart probe reported 0 findings. The thumbnail probe did not produce a thumbnail within 10 seconds, so its header check was skipped; this local media-worker gap is tracked by #209.

Other concurrency evidence: search storm 0 failures (p50 546ms, p95 749ms); 200 mkdir operations and rename races completed without errors; calendar duplicate-account storm had 20 expected conflicts; one of 20 concurrent PATCH requests won; 64 SSE streams and 63 collaboration sockets were accepted.

Adversarial round complete on `3110d9cd5cb8c40581ff5ec25804ba03e6f26445` against `dev` base `32b115dc6338b262d7c5a313a24d25f24d3c2637`. The runner exited 1 because its threshold treats latency outliers as findings: round 1 reported 31 findings and round 2 reported 5. Every reported item was marked `SLOW`; there were no 5xx responses, crashes, accepted hostile input, or inconsistent outcomes. Both rounds ended with the server alive. Hostile-byte checks reported `0` findings, the 924-request authorization matrix printed no policy failures, and the restart probe reported `0 findings`. The thumbnail probe did not produce a thumbnail within 10 seconds, so its header check was skipped; this local media-worker gap is tracked by #209. Other concurrency evidence: search storm 0 failures (p50 546ms, p95 749ms); 200 mkdir operations and rename races completed without errors; calendar duplicate-account storm had 20 expected conflicts; one of 20 concurrent PATCH requests won; 64 SSE streams and 63 collaboration sockets were accepted.
Author
Owner

Merged current dev tip 65265f87ffcc9c44c05e577b4e2ea9c27de130b2 in merge commit a73bfe925caf3fc8d8ffa993452f1ca4858cda93 . The merge contains accessibility, search, settings and Files keyboard movement work. It did not change server or API files, so the completed API adversarial round remains current.

On the merged tree, bun run check passed with 0 errors and 0 warnings; bun run test passed (73 files, 554 tests); cargo fmt --check and cargo clippy --all-targets -- -D warnings passed. The full cargo test gate is running.

Merged current `dev` tip `65265f87ffcc9c44c05e577b4e2ea9c27de130b2` in merge commit `a73bfe925caf3fc8d8ffa993452f1ca4858cda93` . The merge contains accessibility, search, settings and Files keyboard movement work. It did not change server or API files, so the completed API adversarial round remains current. On the merged tree, `bun run check` passed with 0 errors and 0 warnings; `bun run test` passed (73 files, 554 tests); `cargo fmt --check` and `cargo clippy --all-targets -- -D warnings` passed. The full `cargo test` gate is running.
Author
Owner

Merged latest dev tip fbecfbc6f0662d36ac3fcbb870a8d04cb88a4e3e; merge commit is 31192bc7afb673d50db1e20838599d46bac9c150. The merge adds date/time preference APIs and shared UI changes. Conflict resolution retained both Files PinsView and TimeFormat schemas/types; sign-out now resets preference cache and sends the existing session-ended event; the media timeout test keeps its NotFound handling and also checks process identity to avoid PID reuse.

The full cargo test attempt on the preceding merged tree exited 101. Three collaboration timing tests failed: continuous_typing_is_saved_within_the_maximum_wait did not save within 5 seconds, primitive_value_in_fragment_cannot_truncate_the_note did not observe the later edit within 4 seconds, and reconnect_storm_does_not_cancel_pending_save missed its 4-second persistence deadline. Other worktrees had concurrent Cargo jobs during the run, and the affected crate was unchanged by this branch. I will rerun these tests serially to determine whether contention explains the failures.

Merged latest `dev` tip `fbecfbc6f0662d36ac3fcbb870a8d04cb88a4e3e`; merge commit is `31192bc7afb673d50db1e20838599d46bac9c150`. The merge adds date/time preference APIs and shared UI changes. Conflict resolution retained both Files `PinsView` and `TimeFormat` schemas/types; sign-out now resets preference cache and sends the existing session-ended event; the media timeout test keeps its NotFound handling and also checks process identity to avoid PID reuse. The full `cargo test` attempt on the preceding merged tree exited 101. Three collaboration timing tests failed: `continuous_typing_is_saved_within_the_maximum_wait` did not save within 5 seconds, `primitive_value_in_fragment_cannot_truncate_the_note` did not observe the later edit within 4 seconds, and `reconnect_storm_does_not_cancel_pending_save` missed its 4-second persistence deadline. Other worktrees had concurrent Cargo jobs during the run, and the affected crate was unchanged by this branch. I will rerun these tests serially to determine whether contention explains the failures.
Author
Owner

Follow-up to the full Cargo run: I reran the already-built calternal-collab hostile-client integration binary with --test-threads=1. It passed all 11 tests in 14.01 seconds, including the three persistence deadline tests that failed during the parallel workspace run. No calternal-collab source changed on this branch. This supports scheduling contention as the cause of the first run; I will use a serial test harness for the full workspace rerun.

Follow-up to the full Cargo run: I reran the already-built `calternal-collab` hostile-client integration binary with `--test-threads=1`. It passed all 11 tests in 14.01 seconds, including the three persistence deadline tests that failed during the parallel workspace run. No `calternal-collab` source changed on this branch. This supports scheduling contention as the cause of the first run; I will use a serial test harness for the full workspace rerun.
Author
Owner

dev advanced to 2a379b185677fd6d85980900c5e757af990d9527; I merged it in 8394a547d7275d11bdd4d15f11e2f7fd30ea6ee8. The merge adds collaboration room-save behavior, WebSocket probe changes, and the upstream 60-second wait for a newly opted-in Photos shared-library index refresh. I am running a fresh adversarial round because the collaboration API behavior changed.

The prior round on 31192bc7 passed the 924-operation authorization matrix, kept the server alive, and reported no hostile-byte findings. It found one Photos shared-timeline probe result after only 12 seconds; the merged upstream probe now allows 60 seconds for the documented asynchronous refresh. All other findings were SLOW-only, and the restart probe reported 0 findings.

`dev` advanced to `2a379b185677fd6d85980900c5e757af990d9527`; I merged it in `8394a547d7275d11bdd4d15f11e2f7fd30ea6ee8`. The merge adds collaboration room-save behavior, WebSocket probe changes, and the upstream 60-second wait for a newly opted-in Photos shared-library index refresh. I am running a fresh adversarial round because the collaboration API behavior changed. The prior round on `31192bc7` passed the 924-operation authorization matrix, kept the server alive, and reported no hostile-byte findings. It found one Photos shared-timeline probe result after only 12 seconds; the merged upstream probe now allows 60 seconds for the documented asynchronous refresh. All other findings were SLOW-only, and the restart probe reported 0 findings.
Author
Owner

Adversarial round after merge 8394a547d7 (dev base 2a379b1856): first API round and hostile-byte checks completed; server remained alive and hostile-byte findings were 0.

Findings under investigation:

  • Editor restart coordination: the editor suite reported that the runner did not restart the server. run.sh waits 60 seconds for restart-ready-3; the marker appeared only after the editor's earlier multi-minute probes. The missing restart-go-3 marker confirms the runner had left the wait loop. This is a harness timing defect.
  • Recovery-key rotation: the API returned 403. The handler requires a fresh passkey assertion; the adversarial runner does not refresh the owner assertion before this round-1 check, which follows the editor probes. I will correct the probe setup and verify it.
  • Bookmark capture storm: 9 of 16 requests timed out at the probe's 10-second client deadline, while the server remained alive. Host load was 36.69 at the time, and other requests were taking 5–12 seconds. I will rerun this case after the full round to determine whether it reproduces when the server is idle.

Round 2 is still running. SLOW-only latency reports are load under the owner rule; I am checking every non-SLOW finding before final gates.

Adversarial round after merge 8394a547d7275d11bdd4d15f11e2f7fd30ea6ee8 (dev base 2a379b185677fd6d85980900c5e757af990d9527): first API round and hostile-byte checks completed; server remained alive and hostile-byte findings were 0. Findings under investigation: - Editor restart coordination: the editor suite reported that the runner did not restart the server. `run.sh` waits 60 seconds for `restart-ready-3`; the marker appeared only after the editor's earlier multi-minute probes. The missing `restart-go-3` marker confirms the runner had left the wait loop. This is a harness timing defect. - Recovery-key rotation: the API returned 403. The handler requires a fresh passkey assertion; the adversarial runner does not refresh the owner assertion before this round-1 check, which follows the editor probes. I will correct the probe setup and verify it. - Bookmark capture storm: 9 of 16 requests timed out at the probe's 10-second client deadline, while the server remained alive. Host load was 36.69 at the time, and other requests were taking 5–12 seconds. I will rerun this case after the full round to determine whether it reproduces when the server is idle. Round 2 is still running. SLOW-only latency reports are load under the owner rule; I am checking every non-SLOW finding before final gates.
Author
Owner

The full adversarial run for merge 8394a547 completed with exit 1. The local server stayed alive at the ends of both API rounds, the hostile-byte probe reported 0 findings, and the room-restart probe reported restart probe: 0 findings. Most reports were latency-only under a host load average of 25–37.

Remaining non-SLOW reports and evidence:

  • Round 1: recovery-key rotation returned 403; the handler requires a fresh passkey assertion, and round 1 runs after the editor suite without refreshing the Owner assertion.
  • Round 1: the 16-request bookmark burst returned only 7 responses before the probe's 10-second timeout (the other statuses were connection timeouts); this ran while other local endpoints took 5–12 seconds. I will retry the capture burst when load is lower and inspect whether timed-out writes completed.
  • Round 2: slowloris and the 70 KB analytics URL are sent to ADVERSARIAL_PORT, which is the Node editor test proxy, not the Rust server on ADVERSARIAL_BACKEND_PORT. The proxy's HTTP parser closes the oversized request and has no request-header timeout. These checks need to target the backend directly.
  • Round 2: one analytics request timed out in a 24-request burst; the others completed in 20–29 seconds and /readyz still returned 200. I will retry under lower load.
  • Round 2: a public collaboration socket stayed open 10 seconds after 301 empty frames. This probe already connects to the Rust backend; I will retry it when the test server is idle.
  • The editor restart runner's 60-second readiness wait expires before the long editor suite reaches its restart case. The room restart probe passed.

I will correct the harness issues, then verify the remaining timeout and frame-limit reports before final gates.

The full adversarial run for merge 8394a547 completed with exit 1. The local server stayed alive at the ends of both API rounds, the hostile-byte probe reported 0 findings, and the room-restart probe reported `restart probe: 0 findings`. Most reports were latency-only under a host load average of 25–37. Remaining non-SLOW reports and evidence: - Round 1: recovery-key rotation returned 403; the handler requires a fresh passkey assertion, and round 1 runs after the editor suite without refreshing the Owner assertion. - Round 1: the 16-request bookmark burst returned only 7 responses before the probe's 10-second timeout (the other statuses were connection timeouts); this ran while other local endpoints took 5–12 seconds. I will retry the capture burst when load is lower and inspect whether timed-out writes completed. - Round 2: slowloris and the 70 KB analytics URL are sent to `ADVERSARIAL_PORT`, which is the Node editor test proxy, not the Rust server on `ADVERSARIAL_BACKEND_PORT`. The proxy's HTTP parser closes the oversized request and has no request-header timeout. These checks need to target the backend directly. - Round 2: one analytics request timed out in a 24-request burst; the others completed in 20–29 seconds and `/readyz` still returned 200. I will retry under lower load. - Round 2: a public collaboration socket stayed open 10 seconds after 301 empty frames. This probe already connects to the Rust backend; I will retry it when the test server is idle. - The editor restart runner's 60-second readiness wait expires before the long editor suite reaches its restart case. The room restart probe passed. I will correct the harness issues, then verify the remaining timeout and frame-limit reports before final gates.
Author
Owner

Focused real-server verification after the harness changes:

  • Editor suite: PASS editor server restart with a live editor and PASS editor all areas.
  • Recovery probe: owner installation session assertion refreshed; rotation returned the expected key shape and the old key was rejected.
  • Bookmark burst: 16/16 created; 16 unique IDs with the longer bounded wait.
  • Backend-targeted slowloris, oversized-URL and public collaboration frame-limit probes produced no findings.

The selected Analytics run still ended with three request timeouts and analytics storm consistency: two reads after the storm disagree. The server remained alive. Host load averaged 39.41 during that round; neighboring Analytics responses took 20.8–30.0 seconds. I am rerunning Analytics under lower load to distinguish in-flight timed-out writes from a cache inconsistency.

Focused real-server verification after the harness changes: - Editor suite: `PASS editor server restart with a live editor` and `PASS editor all areas`. - Recovery probe: `owner installation session assertion refreshed`; rotation returned the expected key shape and the old key was rejected. - Bookmark burst: `16/16 created; 16 unique IDs` with the longer bounded wait. - Backend-targeted slowloris, oversized-URL and public collaboration frame-limit probes produced no findings. The selected Analytics run still ended with three request timeouts and `analytics storm consistency: two reads after the storm disagree`. The server remained alive. Host load averaged 39.41 during that round; neighboring Analytics responses took 20.8–30.0 seconds. I am rerunning Analytics under lower load to distinguish in-flight timed-out writes from a cache inconsistency.
Author
Owner

Continuing the VM-restart checkpoint on branch job/chrome-sidebar. Checkpoint was 6b73dc8d; latest dev was f1c07669. I merged dev in commit 1650686e. The merge had generated OpenAPI conflicts: I kept Files FilePin/PinsView, retained FirstDayOfWeek, and deduplicated the identical TimeFormat schema. openapi-typescript 7.13.0 generation passed. Next I will rerun the real-server adversarial coverage after host load and Chromium sessions clear.

Continuing the VM-restart checkpoint on branch `job/chrome-sidebar`. Checkpoint was `6b73dc8d`; latest `dev` was `f1c07669`. I merged `dev` in commit `1650686e`. The merge had generated OpenAPI conflicts: I kept Files `FilePin`/`PinsView`, retained `FirstDayOfWeek`, and deduplicated the identical `TimeFormat` schema. `openapi-typescript 7.13.0` generation passed. Next I will rerun the real-server adversarial coverage after host load and Chromium sessions clear.
Author
Owner

Post-merge adversarial finding on 1650686e: Round 2 printed public collab frame rate limit: the 301st frame did not close the socket. At the observation, host load averages were 38.48, 36.26, 32.11, and two other adversarial runners were active. The earlier focused replay passed this probe. The Rust limiter uses a fixed 300-frame-per-minute bucket keyed by public link and client IP; I am checking whether the 301-frame send crossed the minute boundary, then I will rerun this probe against a fresh local server.

Post-merge adversarial finding on `1650686e`: Round 2 printed `public collab frame rate limit: the 301st frame did not close the socket`. At the observation, host load averages were `38.48, 36.26, 32.11`, and two other adversarial runners were active. The earlier focused replay passed this probe. The Rust limiter uses a fixed 300-frame-per-minute bucket keyed by public link and client IP; I am checking whether the 301-frame send crossed the minute boundary, then I will rerun this probe against a fresh local server.
Author
Owner

Post-merge adversarial run on 1650686e completed (runner exit 1): Round 1 reported 48 SLOW-only entries, hostile-byte checks reported 0 findings, and the server stayed alive. Round 2 reported 80 entries: 79 were SLOW-only; the remaining report was the public collaboration 301-frame socket not closing within 10 seconds. The Analytics storm completed with successful 201 writes and no timeout or report mismatch. Room restart reported restart probe: 0 findings. I committed diagnostic timing output for the public frame burst in 583db399; the targeted repeat is waiting for other Chromium sessions to finish.

Post-merge adversarial run on `1650686e` completed (runner exit 1): Round 1 reported 48 SLOW-only entries, hostile-byte checks reported 0 findings, and the server stayed alive. Round 2 reported 80 entries: 79 were SLOW-only; the remaining report was the public collaboration 301-frame socket not closing within 10 seconds. The Analytics storm completed with successful `201` writes and no timeout or report mismatch. Room restart reported `restart probe: 0 findings`. I committed diagnostic timing output for the public frame burst in `583db399`; the targeted repeat is waiting for other Chromium sessions to finish.
Author
Owner

Merged newly advanced dev tip 6495aaf7 in commit ebc25d3d. The merge kept the Files pins API and all 85 artifacts/chrome-sidebar-review screenshots. I combined the layout-sweep --only behavior so Agenda variants run the shared adversarial pass. The merge result has no changes under crates/, contracts/, packages/api-client/ or tests/adversarial/; it does not change the API behavior covered by the completed post-1650686e adversarial run. The public frame-limit targeted replay and final gates remain.

Merged newly advanced `dev` tip `6495aaf7` in commit `ebc25d3d`. The merge kept the Files pins API and all 85 `artifacts/chrome-sidebar-review` screenshots. I combined the `layout-sweep --only` behavior so Agenda variants run the shared adversarial pass. The merge result has no changes under `crates/`, `contracts/`, `packages/api-client/` or `tests/adversarial/`; it does not change the API behavior covered by the completed post-`1650686e` adversarial run. The public frame-limit targeted replay and final gates remain.
Author
Owner

Merged the latest dev tip 74d6072643e59cf8668a0cbd9e02b3e36b79736e in merge commit 97b1ccf4772c8baa1d71d3ebe3077c5c9c754499. The merge adds Notes parser/path handling and fuzz coverage, and updates Files Share/upload handlers. It preserves the Files pins API, the 85 production review screenshots, and the targeted replay modes. I resolved the adversarial helper conflicts so the slowloris and oversized-URL probes reach the Rust backend, the runner supports the upstream per-call editor wait, and the 301-frame diagnostic remains. Syntax and targeted whitespace checks pass. A fresh real-server adversarial round is next because this merge changes API behavior.

Merged the latest `dev` tip `74d6072643e59cf8668a0cbd9e02b3e36b79736e` in merge commit `97b1ccf4772c8baa1d71d3ebe3077c5c9c754499`. The merge adds Notes parser/path handling and fuzz coverage, and updates Files Share/upload handlers. It preserves the Files pins API, the 85 production review screenshots, and the targeted replay modes. I resolved the adversarial helper conflicts so the slowloris and oversized-URL probes reach the Rust backend, the runner supports the upstream per-call editor wait, and the 301-frame diagnostic remains. Syntax and targeted whitespace checks pass. A fresh real-server adversarial round is next because this merge changes API behavior.
Author
Owner

dev advanced to 235073a6318b9a0b96818ab7f0f1b595e9555744 with synchronization engine/API changes and a revised sync-chaos probe. I merged it in b0548a79. The merge is clean and the worktree has no uncommitted changes. I am including this API change in the pending real-server adversarial round.

`dev` advanced to `235073a6318b9a0b96818ab7f0f1b595e9555744` with synchronization engine/API changes and a revised sync-chaos probe. I merged it in `b0548a79`. The merge is clean and the worktree has no uncommitted changes. I am including this API change in the pending real-server adversarial round.
Author
Owner

Merged dev tip 57d1752c990e1509dfdb7faed55815158dbb2c57 in 5ea882bc8d7865be25b6e9bbf90068728a445178. I retained this job's Files pins implementation and UI, OpenAPI operation, and client types alongside the upstream Files and SQLite retry hardening. The media timeout probe keeps the upstream process-group/start-time identity checks and its missing-process handling. The bookmark storm probe retains the longer bounded wait, accepts only 201, 429, or 503 with Retry-After: 1, and still flags 5xx responses and timeouts. The 85 review screenshots remain. Adversarial script syntax and conflict-file whitespace checks pass. A fresh real-server round is pending because the merge changes Files, Notes, Calendar, AI, Photos, and sync APIs.

Merged `dev` tip `57d1752c990e1509dfdb7faed55815158dbb2c57` in `5ea882bc8d7865be25b6e9bbf90068728a445178`. I retained this job's Files pins implementation and UI, OpenAPI operation, and client types alongside the upstream Files and SQLite retry hardening. The media timeout probe keeps the upstream process-group/start-time identity checks and its missing-process handling. The bookmark storm probe retains the longer bounded wait, accepts only `201`, `429`, or `503` with `Retry-After: 1`, and still flags 5xx responses and timeouts. The 85 review screenshots remain. Adversarial script syntax and conflict-file whitespace checks pass. A fresh real-server round is pending because the merge changes Files, Notes, Calendar, AI, Photos, and sync APIs.
Author
Owner

The post-merge Files crate unit suite passed serially after 5ea882bc:

test result: 108 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 252.12s

This includes all three Files pins tests, both SQLite busy/retry cases, and the media timeout process-identity test. The full workspace gates and real-server adversarial round remain pending.

The post-merge Files crate unit suite passed serially after `5ea882bc`: ``` test result: 108 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 252.12s ``` This includes all three Files pins tests, both SQLite busy/retry cases, and the media timeout process-identity test. The full workspace gates and real-server adversarial round remain pending.
Author
Owner

Merged latest dev tip 895d34792de9cb56e2b31f5272bc50925fdc05b7 in 957db8a7. The sweep updates are retained, including the agenda selection and the newer select-mode layout checks. Conflict resolution keeps the title-menu screenshot limited to collapsed or phone-sheet-closed states, as required by this issue, while the toast screenshot uses the updated active-capsule dock. The branch still has all 85 artifacts/chrome-sidebar-review images needed for Claude's review; the upstream cleanup of other review-artifact directories is retained. node --check for both sweep scripts and targeted whitespace checks pass. This merge changes UI and e2e behavior only; the API adversarial round after the previous API merge remains applicable.

Merged latest `dev` tip `895d34792de9cb56e2b31f5272bc50925fdc05b7` in `957db8a7`. The sweep updates are retained, including the agenda selection and the newer select-mode layout checks. Conflict resolution keeps the title-menu screenshot limited to collapsed or phone-sheet-closed states, as required by this issue, while the toast screenshot uses the updated active-capsule dock. The branch still has all 85 `artifacts/chrome-sidebar-review` images needed for Claude's review; the upstream cleanup of other review-artifact directories is retained. `node --check` for both sweep scripts and targeted whitespace checks pass. This merge changes UI and e2e behavior only; the API adversarial round after the previous API merge remains applicable.
Author
Owner

Merged the latest dev history before final verification. 1073eff5aeb89e3c0ae3255b10e47b50ee2c6bc9 (filesystem identity, server wire and API probe runner changes) is included in 4cf7f920; its adversarial scripts pass py_compile and bash -n. Then merged 5af2ff7830ebf36e13e768adeddea015f3c8b23b in c2889f76cfcf2765a57d49cac863460df512d8a6; that change moves deployment files and updates deployment guidance, with no API behavior changes. dev is an ancestor of HEAD, the worktree is clean, and all 85 Chrome-sidebar review screenshots and the Files pins API remain present. A real-server adversarial round is still pending for the API changes from 1073eff5.

Merged the latest `dev` history before final verification. `1073eff5aeb89e3c0ae3255b10e47b50ee2c6bc9` (filesystem identity, server wire and API probe runner changes) is included in `4cf7f920`; its adversarial scripts pass `py_compile` and `bash -n`. Then merged `5af2ff7830ebf36e13e768adeddea015f3c8b23b` in `c2889f76cfcf2765a57d49cac863460df512d8a6`; that change moves deployment files and updates deployment guidance, with no API behavior changes. `dev` is an ancestor of HEAD, the worktree is clean, and all 85 Chrome-sidebar review screenshots and the Files pins API remain present. A real-server adversarial round is still pending for the API changes from `1073eff5`.
Author
Owner

The serial filesystem tests passed on c2889f76 after the latest calternal-fs merge:

test result: 35 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 70.92s

test result: 35 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 51.50s

test result: 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

The unit and storage tests include split-root confinement and the existing recovery/path guarantees. The real-server adversarial round and full workspace gates remain pending.

The serial filesystem tests passed on `c2889f76` after the latest `calternal-fs` merge: ``` test result: 35 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 70.92s test result: 35 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 51.50s test result: 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` The unit and storage tests include split-root confinement and the existing recovery/path guarantees. The real-server adversarial round and full workspace gates remain pending.
Author
Owner

Merged newly advanced dev tip 357df78096917bc2f22dd81bad219a6863ab27db in 4f9251ba074834174fb15630d9ee10ac25373a14. This commit only pins the Node multi-architecture image and sets the cloud image build architecture; it does not change API behavior. The existing adversarial round for the previous filesystem/server API merge remains current. dev is an ancestor of HEAD and the worktree is clean.

Merged newly advanced `dev` tip `357df78096917bc2f22dd81bad219a6863ab27db` in `4f9251ba074834174fb15630d9ee10ac25373a14`. This commit only pins the Node multi-architecture image and sets the cloud image build architecture; it does not change API behavior. The existing adversarial round for the previous filesystem/server API merge remains current. `dev` is an ancestor of HEAD and the worktree is clean.
Author
Owner

Merged dev tip 4b4df8d368bf6bf36bc5e38ebefd1eedfe831c65 in 43b47812115e16c681eebd0323c9b52776542296. It changes only the cloud deployment script's D-Bus session handling and does not alter API behavior. dev is an ancestor of HEAD; the worktree is clean.

Merged `dev` tip `4b4df8d368bf6bf36bc5e38ebefd1eedfe831c65` in `43b47812115e16c681eebd0323c9b52776542296`. It changes only the cloud deployment script's D-Bus session handling and does not alter API behavior. `dev` is an ancestor of HEAD; the worktree is clean.
Author
Owner

Merged dev tip c10fd91e60ffc632cd6a8d04d9a358eff6dc7fb9 in c7b9a5b5f7323ac9dd271acf3c97c2b026a2477f. The update only changes cloud deployment SSH identity handling, so it does not alter API behavior. dev is an ancestor of HEAD and the worktree is clean.

Merged `dev` tip `c10fd91e60ffc632cd6a8d04d9a358eff6dc7fb9` in `c7b9a5b5f7323ac9dd271acf3c97c2b026a2477f`. The update only changes cloud deployment SSH identity handling, so it does not alter API behavior. `dev` is an ancestor of HEAD and the worktree is clean.
Author
Owner

Merged dev tip 0558cc4ecaeb7f51af1e06acd31870b5f87b9f00 in 338d77aa3146a1c4ffe30b2b52b4b754dbebcfb5. This only changes how the cloud deployment script writes its environment file, with no API behavior change. dev is an ancestor of HEAD and the worktree is clean.

Merged `dev` tip `0558cc4ecaeb7f51af1e06acd31870b5f87b9f00` in `338d77aa3146a1c4ffe30b2b52b4b754dbebcfb5`. This only changes how the cloud deployment script writes its environment file, with no API behavior change. `dev` is an ancestor of HEAD and the worktree is clean.
Author
Owner

Starting finalization on branch job/chrome-sidebar. Current branch head: 338d77aa3146a1c4ffe30b2b52b4b754dbebcfb5; base dev: 0558cc4ecaeb7f51af1e06acd31870b5f87b9f00. Ran the required one-time git merge dev; Git reported Already up to date.

Starting finalization on branch `job/chrome-sidebar`. Current branch head: `338d77aa3146a1c4ffe30b2b52b4b754dbebcfb5`; base `dev`: `0558cc4ecaeb7f51af1e06acd31870b5f87b9f00`. Ran the required one-time `git merge dev`; Git reported `Already up to date.`
Author
Owner

Finalization finding: 93 review PNGs are tracked by this branch (89 under artifacts/chrome-sidebar-review/ and 4 under apps/web/e2e/review/), contrary to the owner rule that review images stay outside Git. I will keep local copies for review, remove these binaries from the branch tip, and attach the fresh production screenshots to this issue.

Finalization finding: 93 review PNGs are tracked by this branch (89 under `artifacts/chrome-sidebar-review/` and 4 under `apps/web/e2e/review/`), contrary to the owner rule that review images stay outside Git. I will keep local copies for review, remove these binaries from the branch tip, and attach the fresh production screenshots to this issue.
Author
Owner

Correction to my previous artifact count: the total is 89 tracked PNGs, not 93 (85 under artifacts/chrome-sidebar-review/ and 4 under apps/web/e2e/review/). All 89 are now removed from the branch tip in commit 90272900; local copies remain under ignored artifacts/ for review.

Correction to my previous artifact count: the total is 89 tracked PNGs, not 93 (85 under `artifacts/chrome-sidebar-review/` and 4 under `apps/web/e2e/review/`). All 89 are now removed from the branch tip in commit `90272900`; local copies remain under ignored `artifacts/` for review.
Author
Owner

#156 final report

Built: shared sidebar/H1 rules, Files breadcrumbs with folded parents, pinned and smart folder ordering, per-User pin persistence, and Calendar title transition coverage. The API client/OpenAPI contract and adversarial pins probes are included.

Files: packages/ui/src/components/ModeHeader.svelte, packages/ui/src/components/calendar/CalendarTitle.svelte, packages/ui/src/components/pageChrome.ts; apps/web/src/lib/files/*, apps/web/e2e/{files,header-sweep,layout-sweep}.mjs; crates/plugins/files/src/{lib.rs,pins.rs}; contracts/openapi.json; packages/api-client/src/*; tests/adversarial/{attack.py,attack2.py,run.sh}.

Head: 90272900bc3367e72e820d6e1bb04768b9327928 on job/chrome-sidebar. Pushed; origin/job/chrome-sidebar matches. The cleanup commit removes 89 tracked review PNGs from the branch tip and keeps local copies under ignored artifacts/.

Gates:

  • cargo fmt --check — exit 0, no output.
  • cargo clippy --all-targets -- -D warnings — exit 0. Verbatim final line: Finished \dev` profile [unoptimized + debuginfo] target(s) in 1m 08s`
  • cargo test --workspace --quiet — exit 0; aggregate from the 72 test-binary summaries: 1,278 passed, 0 failed, 12 ignored. Verbatim example: test result: ok. 480 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.89s
  • bun run check — svelte-check found 0 errors and 0 warnings
  • bun run test — Test Files 82 passed (82); Tests 593 passed (593); exit 0.
  • bun run build — ✓ built in 46.09s; Wrote site to "build"; ✔ done. The existing vendor "use client" directive notices remain.
  • Adversarial round: ROUND 2 FINDINGS 0; server alive at end: True.

Production screenshots: 168 captures are in ignored artifacts/chrome-sidebar-final/. Five representative captures are attached below. The HEADER_SECTIONS=sidebar-matrix,title,shots run was stopped during its optional 720 px / 200% review captures at the job cutoff. The issue matrix and title sections ran before capture, but the command did not print LAYOUT SWEEP PASSED; its final output was:

checked 0 screens
FAIL header screens note 720-zoom200: screenshot: Target page, context or browser has been closed
FAIL header screens notes 720-zoom200: goto: Target page, context or browser has been closed

Files open, 1440, Paper
Files collapsed, 1440, Tokyo Night
Calendar Week open, 1024, Paper
Files phone, 390, Paper
Notes sheet, 390, Tokyo Night

Known gap: the header screenshot sweep ended before the supplemental 720 px / 200% captures and has no final pass line. Its interruption produced the page-closed messages above. All requested 1440, 1024, and 390 screenshots needed for review were captured; five representative images are attached.

Decisions: no new product design decision was needed; the owner grill in #156 settled the requested behavior. I used the existing HEADER_SECTIONS selector for the final task-specific matrix, title, and screenshot pass to stay inside the cutoff.

## #156 final report **Built:** shared sidebar/H1 rules, Files breadcrumbs with folded parents, pinned and smart folder ordering, per-User pin persistence, and Calendar title transition coverage. The API client/OpenAPI contract and adversarial pins probes are included. **Files:** `packages/ui/src/components/ModeHeader.svelte`, `packages/ui/src/components/calendar/CalendarTitle.svelte`, `packages/ui/src/components/pageChrome.ts`; `apps/web/src/lib/files/*`, `apps/web/e2e/{files,header-sweep,layout-sweep}.mjs`; `crates/plugins/files/src/{lib.rs,pins.rs}`; `contracts/openapi.json`; `packages/api-client/src/*`; `tests/adversarial/{attack.py,attack2.py,run.sh}`. **Head:** `90272900bc3367e72e820d6e1bb04768b9327928` on `job/chrome-sidebar`. Pushed; `origin/job/chrome-sidebar` matches. The cleanup commit removes 89 tracked review PNGs from the branch tip and keeps local copies under ignored `artifacts/`. **Gates:** - `cargo fmt --check` — exit 0, no output. - `cargo clippy --all-targets -- -D warnings` — exit 0. Verbatim final line: `Finished \`dev\` profile [unoptimized + debuginfo] target(s) in 1m 08s` - `cargo test --workspace --quiet` — exit 0; aggregate from the 72 test-binary summaries: 1,278 passed, 0 failed, 12 ignored. Verbatim example: `test result: ok. 480 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.89s` - `bun run check` — `svelte-check found 0 errors and 0 warnings` - `bun run test` — `Test Files 82 passed (82)`; `Tests 593 passed (593)`; exit 0. - `bun run build` — `✓ built in 46.09s`; `Wrote site to "build"`; `✔ done`. The existing vendor `"use client"` directive notices remain. - Adversarial round: `ROUND 2 FINDINGS 0`; `server alive at end: True`. **Production screenshots:** 168 captures are in ignored `artifacts/chrome-sidebar-final/`. Five representative captures are attached below. The `HEADER_SECTIONS=sidebar-matrix,title,shots` run was stopped during its optional 720 px / 200% review captures at the job cutoff. The issue matrix and title sections ran before capture, but the command did not print `LAYOUT SWEEP PASSED`; its final output was: ```text checked 0 screens FAIL header screens note 720-zoom200: screenshot: Target page, context or browser has been closed FAIL header screens notes 720-zoom200: goto: Target page, context or browser has been closed ``` ![Files open, 1440, Paper](https://git.kayg.org/attachments/836d6f30-c2e9-4194-8f46-8203d26dd094) ![Files collapsed, 1440, Tokyo Night](https://git.kayg.org/attachments/2c5c0030-5f5a-4679-831a-e59b80fd9051) ![Calendar Week open, 1024, Paper](https://git.kayg.org/attachments/2f6618ca-5634-4edd-9ffc-dc07e69ce038) ![Files phone, 390, Paper](https://git.kayg.org/attachments/fad69343-2ad0-40c6-9967-b1d43bcf9138) ![Notes sheet, 390, Tokyo Night](https://git.kayg.org/attachments/4c2c329a-5899-4576-a9ff-ea001945a371) **Known gap:** the header screenshot sweep ended before the supplemental 720 px / 200% captures and has no final pass line. Its interruption produced the page-closed messages above. All requested 1440, 1024, and 390 screenshots needed for review were captured; five representative images are attached. **Decisions:** no new product design decision was needed; the owner grill in #156 settled the requested behavior. I used the existing `HEADER_SECTIONS` selector for the final task-specific matrix, title, and screenshot pass to stay inside the cutoff.
Author
Owner

Starting merge reconciliation on job/chrome-sidebar. Branch head: 90272900bc3367e72e820d6e1bb04768b9327928; local dev base to merge: 21d985bf7ac8d4e13f2eb93bdc600198412df038. The worktree is clean. I have read CLAUDE.md, CONTEXT.md, and DESIGN §§33–34.

Starting merge reconciliation on `job/chrome-sidebar`. Branch head: `90272900bc3367e72e820d6e1bb04768b9327928`; local `dev` base to merge: `21d985bf7ac8d4e13f2eb93bdc600198412df038`. The worktree is clean. I have read `CLAUDE.md`, `CONTEXT.md`, and DESIGN §§33–34.
Author
Owner

Merge finding: MENU_ICONS.folder is an SVG inner-markup string (apps/web/src/lib/notes/icons.ts), but the dev MenuItem renderer treated every string icon as one path's d attribute. Using the shared map in the Files title menu would therefore create an invalid SVG path. I kept the static shared map and rendered its trusted inner SVG markup; component icons remain supported. The same MenuItem reconciliation preserves the branch's breadcrumb drop handlers and dev's aligned trailing glyph slot.

Merge finding: `MENU_ICONS.folder` is an SVG inner-markup string (`apps/web/src/lib/notes/icons.ts`), but the dev `MenuItem` renderer treated every string icon as one path's `d` attribute. Using the shared map in the Files title menu would therefore create an invalid SVG path. I kept the static shared map and rendered its trusted inner SVG markup; component icons remain supported. The same `MenuItem` reconciliation preserves the branch's breadcrumb drop handlers and dev's aligned trailing glyph slot.
Author
Owner

Merge finding: the merged server source contains the Files Pins API used by FilesBrowser, but dev's OpenAPI/client output does not include PinsView or /api/v1/files/pins. Evidence: the initial bun run check reported 5 type errors in apps/web/src/lib/files/prefs.svelte.ts for the missing schema and path. I am regenerating both artifacts with packages/api-client/check-generated.sh from the merged source before validating the web types again.

Merge finding: the merged server source contains the Files Pins API used by `FilesBrowser`, but `dev`'s OpenAPI/client output does not include `PinsView` or `/api/v1/files/pins`. Evidence: the initial `bun run check` reported 5 type errors in `apps/web/src/lib/files/prefs.svelte.ts` for the missing schema and path. I am regenerating both artifacts with `packages/api-client/check-generated.sh` from the merged source before validating the web types again.
Author
Owner

Web test finding: the reconciled title menu now names both views and folder destinations. The existing header test still expected the old Files views label, while ModeHeader emitted Files views and folders; bun run test had 600 passing tests and this one stale expectation failure. I updated the fixture assertion to the merged accessible name and am rerunning the web suite once against that correction.

Web test finding: the reconciled title menu now names both views and folder destinations. The existing header test still expected the old `Files views` label, while `ModeHeader` emitted `Files views and folders`; `bun run test` had 600 passing tests and this one stale expectation failure. I updated the fixture assertion to the merged accessible name and am rerunning the web suite once against that correction.
Author
Owner

The one-time real-server adversarial round found a non-load editor data inconsistency: with seed 25608414, the browser paste and 500-step undo/redo probe saved repeated ^duplicate-id and ^icjf8j block anchors; the uniqueness check failed (4 !== 7). I filed the reproducible finding and kept its regression probe in #262. The chrome-sidebar merge does not modify the editor implementation.

The one-time real-server adversarial round found a non-load editor data inconsistency: with seed `25608414`, the browser paste and 500-step undo/redo probe saved repeated `^duplicate-id` and `^icjf8j` block anchors; the uniqueness check failed (`4 !== 7`). I filed the reproducible finding and kept its regression probe in [#262](https://git.kayg.org/kayg/calternal/issues/262). The chrome-sidebar merge does not modify the editor implementation.
Author
Owner

The editor restart probe also reported an unexpected socket closure during the live-editor restart check. The 10-minute outer timebox expired during this area, so load/timeout effects are possible and the remainder of the adversarial script did not run. I filed the qualified observation in #263; the duplicate-block-ID defect is tracked separately in #262.

The editor restart probe also reported an unexpected socket closure during the live-editor restart check. The 10-minute outer timebox expired during this area, so load/timeout effects are possible and the remainder of the adversarial script did not run. I filed the qualified observation in [#263](https://git.kayg.org/kayg/calternal/issues/263); the duplicate-block-ID defect is tracked separately in #262.
Author
Owner

Completed the one-time dev merge on job/chrome-sidebar.

Head: d9ebe5b5e076cee27520517f692be99443aa2b7c (parents: 90272900bc3367e72e820d6e1bb04768b9327928, 21d985bf7ac8d4e13f2eb93bdc600198412df038). The branch was pushed; origin/job/chrome-sidebar matches this SHA. Worktree is clean.

Built

  • Kept the Files breadcrumb links and drag targets while retaining the collapsed H1 folder destinations from dev.
  • Kept component menu icons and breadcrumb drop handlers; reused the shared MENU_ICONS map for folder destinations.
  • Kept the revised header fixture, regenerated the OpenAPI contract and API client from merged Rust source, and preserved both adversarial runner paths.
  • Merged dev’s Home, Calendar tag, data split, and shared menu changes. No screenshots were retaken.

Files reconciled

  • apps/web/src/lib/files/FilesBrowser.svelte
  • apps/web/src/lib/modeHeader.svelte.test.ts
  • packages/ui/src/components/menu/MenuItem.svelte
  • contracts/openapi.json
  • packages/api-client/src/generated.ts
  • tests/adversarial/run.sh
  • Cargo.lock (merged from dev)

Gates

cargo fmt --check exited 0 with no stdout.

cargo clippy --all-targets -- -D warnings exited 0. Verbatim output:

   Compiling calternal-server v0.0.1 (/home/kayg/Developer/calternal-wt/chrome-sidebar/crates/calternal-server)
    Checking calternal-collab v0.0.1 (/home/kayg/Developer/calternal-wt/chrome-sidebar/crates/calternal-collab)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 20.98s

cargo test exited 0. Verbatim output excerpt:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 28m 20s

test result: ok. 44 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 7.65s

test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.50s

bun run check exited 0. Verbatim output:

$ svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/chrome-sidebar/apps/web
Getting Svelte diagnostics...
svelte-check found 0 errors and 0 warnings

bun run test exited 0. Verbatim output:

 Test Files  84 passed (84)
      Tests  601 passed (601)
   Start at  21:15:41
   Duration  157.57s (transform 64%, environment 13%, import 13%, tests 7%, setup 2%)

packages/api-client/check-generated.sh exited 0 after staging the regenerated files. Verbatim output tail:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 34s
     Running `target/debug/calternal-server openapi`
$ bunx --package openapi-typescript@7.13.0 openapi-typescript ../../contracts/openapi.json -o src/generated.ts
✨ openapi-typescript 7.13.0
🚀 ../../contracts/openapi.json → src/generated.ts [3.5s]

The first clippy attempt needed the production web build for RustEmbed; after building the web app, clippy passed. The first web check ran against stale generated API types; after regeneration, it passed. The first web test run found the old accessible-name expectation; I updated it to Files views and folders, and the full suite then passed.

Adversarial round

One 10-minute real-server round ran. The Event tag probe passed, and the authorization matrix completed all 932 requests. The editor probe found duplicate block IDs after hostile paste and undo/redo history; I filed #262. The live-editor restart probe reported an unexpected socket close as the timebox expired; I filed the qualified observation in #263. The round exited 124 at the time limit, so later probes did not run. No screenshot retakes were made.

Decisions

  • The collapsed Files title menu now has the accessible name Files views and folders, because it includes both sub-views and folder destinations.
  • String icons from MENU_ICONS are static inner SVG markup, not path d values. MenuItem renders that trusted map markup and still supports component icons.

Cleanup

cargo clean output:

     Removed 18321 files, 14.6GiB total

Removed apps/web/build and apps/web/.svelte-kit.

Completed the one-time `dev` merge on `job/chrome-sidebar`. Head: `d9ebe5b5e076cee27520517f692be99443aa2b7c` (parents: `90272900bc3367e72e820d6e1bb04768b9327928`, `21d985bf7ac8d4e13f2eb93bdc600198412df038`). The branch was pushed; `origin/job/chrome-sidebar` matches this SHA. Worktree is clean. ## Built - Kept the Files breadcrumb links and drag targets while retaining the collapsed H1 folder destinations from `dev`. - Kept component menu icons and breadcrumb drop handlers; reused the shared `MENU_ICONS` map for folder destinations. - Kept the revised header fixture, regenerated the OpenAPI contract and API client from merged Rust source, and preserved both adversarial runner paths. - Merged `dev`’s Home, Calendar tag, data split, and shared menu changes. No screenshots were retaken. ## Files reconciled - `apps/web/src/lib/files/FilesBrowser.svelte` - `apps/web/src/lib/modeHeader.svelte.test.ts` - `packages/ui/src/components/menu/MenuItem.svelte` - `contracts/openapi.json` - `packages/api-client/src/generated.ts` - `tests/adversarial/run.sh` - `Cargo.lock` (merged from `dev`) ## Gates `cargo fmt --check` exited 0 with no stdout. `cargo clippy --all-targets -- -D warnings` exited 0. Verbatim output: ```text Compiling calternal-server v0.0.1 (/home/kayg/Developer/calternal-wt/chrome-sidebar/crates/calternal-server) Checking calternal-collab v0.0.1 (/home/kayg/Developer/calternal-wt/chrome-sidebar/crates/calternal-collab) Finished `dev` profile [unoptimized + debuginfo] target(s) in 20.98s ``` `cargo test` exited 0. Verbatim output excerpt: ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 28m 20s test result: ok. 44 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 7.65s test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.50s ``` `bun run check` exited 0. Verbatim output: ```text $ svelte-kit sync && svelte-check --tsconfig ./tsconfig.json Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/chrome-sidebar/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `bun run test` exited 0. Verbatim output: ```text Test Files 84 passed (84) Tests 601 passed (601) Start at 21:15:41 Duration 157.57s (transform 64%, environment 13%, import 13%, tests 7%, setup 2%) ``` `packages/api-client/check-generated.sh` exited 0 after staging the regenerated files. Verbatim output tail: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 34s Running `target/debug/calternal-server openapi` $ bunx --package openapi-typescript@7.13.0 openapi-typescript ../../contracts/openapi.json -o src/generated.ts ✨ openapi-typescript 7.13.0 🚀 ../../contracts/openapi.json → src/generated.ts [3.5s] ``` The first clippy attempt needed the production web build for `RustEmbed`; after building the web app, clippy passed. The first web check ran against stale generated API types; after regeneration, it passed. The first web test run found the old accessible-name expectation; I updated it to `Files views and folders`, and the full suite then passed. ## Adversarial round One 10-minute real-server round ran. The Event tag probe passed, and the authorization matrix completed all 932 requests. The editor probe found duplicate block IDs after hostile paste and undo/redo history; I filed [#262](https://git.kayg.org/kayg/calternal/issues/262). The live-editor restart probe reported an unexpected socket close as the timebox expired; I filed the qualified observation in [#263](https://git.kayg.org/kayg/calternal/issues/263). The round exited 124 at the time limit, so later probes did not run. No screenshot retakes were made. ## Decisions - The collapsed Files title menu now has the accessible name `Files views and folders`, because it includes both sub-views and folder destinations. - String icons from `MENU_ICONS` are static inner SVG markup, not path `d` values. `MenuItem` renders that trusted map markup and still supports component icons. ## Cleanup `cargo clean` output: ```text Removed 18321 files, 14.6GiB total ``` Removed `apps/web/build` and `apps/web/.svelte-kit`.
Author
Owner

Started #156 on branch job/chrome-sidebar. Worktree HEAD: d9ebe5b5e0. Fetched origin/dev for the one required reconciliation merge: 3ad937ec88.

Started #156 on branch job/chrome-sidebar. Worktree HEAD: d9ebe5b5e076cee27520517f692be99443aa2b7c. Fetched origin/dev for the one required reconciliation merge: 3ad937ec888c1fe45ce6e1d3052383e024dc5220.
Author
Owner

Finding during verification: phone-chrome.mjs reused the phone session's local storage for its desktop Files check, so the sidebar remained open while the assertion expected the collapsed-only breadcrumb menu. The run timed out waiting for .mh-switch; the app reads calternal.sidebar-collapsed during page initialization. I updated the desktop E2E context to set that preference before navigation and am rerunning the scenario.

Finding during verification: `phone-chrome.mjs` reused the phone session's local storage for its desktop Files check, so the sidebar remained open while the assertion expected the collapsed-only breadcrumb menu. The run timed out waiting for `.mh-switch`; the app reads `calternal.sidebar-collapsed` during page initialization. I updated the desktop E2E context to set that preference before navigation and am rerunning the scenario.
Author
Owner

Finding in the focused Files E2E: the inline rename check saw delta.md in the list but an immediate stat returned 404. FilesBrowser.svelte updates the row optimistically, then awaits the rename API; the row's Enter callback discards that promise. The E2E therefore queried persisted state before it knew the POST had completed. I am updating the E2E to await the rename response before checking stat.

Finding in the focused Files E2E: the inline rename check saw `delta.md` in the list but an immediate stat returned 404. `FilesBrowser.svelte` updates the row optimistically, then awaits the rename API; the row's Enter callback discards that promise. The E2E therefore queried persisted state before it knew the POST had completed. I am updating the E2E to await the rename response before checking stat.
Author
Owner

Finding in the header sweep: #219 replaced the header's .mh-blur element with the shared ProgressiveBlur component (.progressive-blur.top), but the older header metrics and collapse probes still queried .mh-blur. The sweep therefore raised getComputedStyle(null) across routes and later timed out waiting for the old selector. I am updating those probes to use the current component selector and will rerun the issue-specific matrix, title transition, and screenshot sections.

Finding in the header sweep: #219 replaced the header's `.mh-blur` element with the shared `ProgressiveBlur` component (`.progressive-blur.top`), but the older header metrics and collapse probes still queried `.mh-blur`. The sweep therefore raised `getComputedStyle(null)` across routes and later timed out waiting for the old selector. I am updating those probes to use the current component selector and will rerun the issue-specific matrix, title transition, and screenshot sections.
Author
Owner

Adversarial finding triage: the standard-user PUT /api/v1/admin/config case sent the result of GET /api/v1/admin/config as its body. The GET result is AdminConfigView (including a structured dedup schedule), while PUT requires InstanceConfig (a cron string); Axum rejected the mismatched JSON as 422 before the handler's admin check. This is a matrix fixture error, not an authorization bypass. I am keeping the OpenAPI InstanceConfig body for that operation so the probe checks the intended 403 path.

Adversarial finding triage: the standard-user `PUT /api/v1/admin/config` case sent the result of `GET /api/v1/admin/config` as its body. The GET result is `AdminConfigView` (including a structured dedup schedule), while PUT requires `InstanceConfig` (a cron string); Axum rejected the mismatched JSON as 422 before the handler's admin check. This is a matrix fixture error, not an authorization bypass. I am keeping the OpenAPI `InstanceConfig` body for that operation so the probe checks the intended 403 path.
Author
Owner

Built

Reconciled the desktop and phone chrome rules. Desktop keeps Files breadcrumbs while the sidebar is open; the Files ▾ title menu appears only when the sidebar is collapsed. Files sidebar pins remain before Smart folders. On nested phone pages, the header shows Back + the active page H1 and suppresses desktop breadcrumbs. The phone sheet keeps ProgressiveBlur.

Also fixed three test-fixture issues found during verification: the phone E2E now sets its desktop sidebar state explicitly, the Files E2E waits for the optimistic rename request to persist, and the header sweep uses the shared .progressive-blur.top component introduced by #219. The adversarial authz matrix now keeps the OpenAPI InstanceConfig body instead of sending the differently shaped GET AdminConfigView to PUT.

Files

Key files: packages/ui/src/components/ModeHeader.svelte, packages/ui/src/components/pageChrome.ts, apps/web/src/lib/files/FilesBrowser.svelte, apps/web/src/lib/modeHeader.svelte.test.ts, apps/web/e2e/{phone-chrome.mjs,files.mjs,layout-sweep.mjs,header-sweep.mjs}, tests/adversarial/{authz_matrix.py,attack2.py,run.sh}, and regenerated packages/api-client/src/generated.ts. The merge commit also brings the other latest origin/dev changes.

Commits and push

Head: b392a4fcf3406528b3b10e7b6d231fc322eb46b5

Commits: 82097609 merge reconciliation; b0c6f64c explicit chrome test states; 52947538 rename persistence wait; 4c11fd37 shared blur probe; b392a4fc authz request fixture.

Pushed job/chrome-sidebar; git push reported Everything up-to-date.

Gates

cargo fmt --check exited 0 with no output.

cargo clippy --all-targets -- -D warnings output:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 8m 32s

cargo test exited 0. Final output:

   Doc-tests calternal_tags

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

bun run --cwd apps/web check output:

svelte-check found 0 errors and 0 warnings

bun run --cwd apps/web test output:

 Test Files  88 passed (88)
      Tests  612 passed (612)
   Start at  22:33:36
   Duration  145.24s (transform 62%, environment 15%, import 12%, tests 8%, setup 2%)

packages/api-client/check-generated.sh output:

🚀 ../../contracts/openapi.json → src/generated.ts [1.5s]

The updated ModeHeader unit test passed: Test Files 1 passed (1) / Tests 12 passed (12). phone-chrome.mjs, files.mjs, and the focused sidebar-matrix,title header sweep passed. The header sweep printed checked 0 screens because --only headers skips the separate general screen pass; its header matrix/title sections ran and passed.

Adversarial round and gaps

One adversarial round was capped at 45 minutes and stopped with exit 143 before the last attack2 sections completed. It reported no 5xx or crash in the collected output; the server remained alive after the attack.py section. Two 30-second timeouts occurred: DAV initial sync and Calendar Event-from-Log. I added this evidence to existing investigation #269. Most other reports were SLOW responses under concurrent host load.

The authz matrix reported 422 for non-admin config PUT before I corrected its mismatched GET-view request body. That was a probe-fixture false positive: JSON extraction rejected the AdminConfigView before the handler's admin check. I documented this on #268 and did not repeat the full matrix, honoring the single-round rule.

The phone sheet blur measurement remains an XFAIL tracked by #246 (light ratio 1.013, dark ratio 0.969; expected <0.3). The full unfiltered header sweep first exposed its stale blur selector; after fixing it, the issue-specific matrix and title sections passed.

Decisions

Nested phone Files uses Back + H1 without the desktop breadcrumb row. Desktop keeps full breadcrumbs and exposes the Files title menu only with the sidebar collapsed. These choices preserve both #156 and #219 behavior.

Screenshots

## Built Reconciled the desktop and phone chrome rules. Desktop keeps Files breadcrumbs while the sidebar is open; the `Files ▾` title menu appears only when the sidebar is collapsed. Files sidebar pins remain before Smart folders. On nested phone pages, the header shows Back + the active page H1 and suppresses desktop breadcrumbs. The phone sheet keeps ProgressiveBlur. Also fixed three test-fixture issues found during verification: the phone E2E now sets its desktop sidebar state explicitly, the Files E2E waits for the optimistic rename request to persist, and the header sweep uses the shared `.progressive-blur.top` component introduced by #219. The adversarial authz matrix now keeps the OpenAPI `InstanceConfig` body instead of sending the differently shaped GET `AdminConfigView` to PUT. ## Files Key files: `packages/ui/src/components/ModeHeader.svelte`, `packages/ui/src/components/pageChrome.ts`, `apps/web/src/lib/files/FilesBrowser.svelte`, `apps/web/src/lib/modeHeader.svelte.test.ts`, `apps/web/e2e/{phone-chrome.mjs,files.mjs,layout-sweep.mjs,header-sweep.mjs}`, `tests/adversarial/{authz_matrix.py,attack2.py,run.sh}`, and regenerated `packages/api-client/src/generated.ts`. The merge commit also brings the other latest `origin/dev` changes. ## Commits and push Head: `b392a4fcf3406528b3b10e7b6d231fc322eb46b5` Commits: `82097609` merge reconciliation; `b0c6f64c` explicit chrome test states; `52947538` rename persistence wait; `4c11fd37` shared blur probe; `b392a4fc` authz request fixture. Pushed `job/chrome-sidebar`; `git push` reported `Everything up-to-date`. ## Gates `cargo fmt --check` exited 0 with no output. `cargo clippy --all-targets -- -D warnings` output: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 8m 32s ``` `cargo test` exited 0. Final output: ```text Doc-tests calternal_tags running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` `bun run --cwd apps/web check` output: ```text svelte-check found 0 errors and 0 warnings ``` `bun run --cwd apps/web test` output: ```text Test Files 88 passed (88) Tests 612 passed (612) Start at 22:33:36 Duration 145.24s (transform 62%, environment 15%, import 12%, tests 8%, setup 2%) ``` `packages/api-client/check-generated.sh` output: ```text 🚀 ../../contracts/openapi.json → src/generated.ts [1.5s] ``` The updated ModeHeader unit test passed: `Test Files 1 passed (1)` / `Tests 12 passed (12)`. `phone-chrome.mjs`, `files.mjs`, and the focused `sidebar-matrix,title` header sweep passed. The header sweep printed `checked 0 screens` because `--only headers` skips the separate general screen pass; its header matrix/title sections ran and passed. ## Adversarial round and gaps One adversarial round was capped at 45 minutes and stopped with exit 143 before the last attack2 sections completed. It reported no 5xx or crash in the collected output; the server remained alive after the attack.py section. Two 30-second timeouts occurred: DAV initial sync and Calendar Event-from-Log. I added this evidence to existing investigation #269. Most other reports were SLOW responses under concurrent host load. The authz matrix reported 422 for non-admin config PUT before I corrected its mismatched GET-view request body. That was a probe-fixture false positive: JSON extraction rejected the `AdminConfigView` before the handler's admin check. I documented this on #268 and did not repeat the full matrix, honoring the single-round rule. The phone sheet blur measurement remains an XFAIL tracked by #246 (light ratio 1.013, dark ratio 0.969; expected <0.3). The full unfiltered header sweep first exposed its stale blur selector; after fixing it, the issue-specific matrix and title sections passed. ## Decisions Nested phone Files uses Back + H1 without the desktop breadcrumb row. Desktop keeps full breadcrumbs and exposes the Files title menu only with the sidebar collapsed. These choices preserve both #156 and #219 behavior. ## Screenshots - [Files 1440, Paper, sidebar open](https://git.kayg.org/attachments/52ea8b7f-36d2-452a-8463-fe39a9c0d0c7) - [Files 1440, Tokyo Night, sidebar collapsed](https://git.kayg.org/attachments/2a2bdd96-c2d9-4494-8fe2-8122d701eed6) - [Files 1024, Paper, sidebar open](https://git.kayg.org/attachments/8fa7b200-3741-437c-88e2-c62d941478a4) - [Files 1024, Tokyo Night, sidebar collapsed](https://git.kayg.org/attachments/4f1a0090-3eda-43ba-aae1-b28b2a0073aa) - [Files 390, Paper, sheet closed](https://git.kayg.org/attachments/832109bc-c86b-461c-a617-7d278a200787) - [Files 390, Tokyo Night, sheet open](https://git.kayg.org/attachments/e16b8de1-6d04-4588-b8b0-ca1d1c0072f6) - [Desktop nested Files breadcrumbs](https://git.kayg.org/attachments/0144fadf-ba40-41ad-98a0-4e3389a74294) - [Phone nested Files, Paper](https://git.kayg.org/attachments/761f39c6-9c77-41be-a13f-3663f348ba84) - [Phone nested Files, dark](https://git.kayg.org/attachments/51d36c5f-bc9f-43f3-8bea-6a47aecdf9a2)
Author
Owner

Starting Forgejo #156 on branch job/chrome-sidebar, based at 088e17d4fe49d6a7b41f03fcc13f5f4959346be9 (origin/dev). Working tree was clean.

Starting Forgejo #156 on branch `job/chrome-sidebar`, based at `088e17d4fe49d6a7b41f03fcc13f5f4959346be9` (`origin/dev`). Working tree was clean.
Author
Owner

Merge review finding: the incoming Files first-page cache can return a still-fresh cached page even when FilesBrowser requests cache: 'no-store' after a live change. That can hide an external Home write for the 2-second cache window. I am merging the preload cache with an explicit fresh-read bypass and a regression test.

Merge review finding: the incoming Files first-page cache can return a still-fresh cached page even when `FilesBrowser` requests `cache: 'no-store'` after a live change. That can hide an external Home write for the 2-second cache window. I am merging the preload cache with an explicit fresh-read bypass and a regression test.
Author
Owner

Review finding: deep Files pages put ancestor folders in the last segment's view menu while also showing those ancestors as breadcrumb links. On phones, the same page hid the breadcrumb and menu and rendered Back plus a second content H1. This conflicts with #156's rule that the last breadcrumb carries the view menu when the sidebar is closed. I am applying that rule at phone widths too; it supersedes the earlier phone Back/content-H1 behavior in DESIGN §38 for Files.

Review finding: deep Files pages put ancestor folders in the last segment's view menu while also showing those ancestors as breadcrumb links. On phones, the same page hid the breadcrumb and menu and rendered Back plus a second content H1. This conflicts with #156's rule that the last breadcrumb carries the view menu when the sidebar is closed. I am applying that rule at phone widths too; it supersedes the earlier phone Back/content-H1 behavior in DESIGN §38 for Files.
Author
Owner

Production E2E finding: bun e2e/files.mjs passed drag-to-pin, keyboard pin reordering, persistence, unpin, breadcrumb link, and middle-segment drop checks. It then timed out after 30 seconds waiting for Quick Look to advance from alpha.txt to beta.txt after ArrowRight. The run reported 0 CSP violations. I am tracing the viewer's ordered items and focused key target before rerunning this flow.

Production E2E finding: `bun e2e/files.mjs` passed drag-to-pin, keyboard pin reordering, persistence, unpin, breadcrumb link, and middle-segment drop checks. It then timed out after 30 seconds waiting for Quick Look to advance from `alpha.txt` to `beta.txt` after `ArrowRight`. The run reported 0 CSP violations. I am tracing the viewer's ordered items and focused key target before rerunning this flow.
Author
Owner

Follow-up evidence: Quick Look's .ql was visible after opening, but document.activeElement was BODY (insideQuickLook: false). Thus ArrowRight never reached its key handler. The overlay's focus trap runs as its surface mounts while the shared portal also relocates the overlay branch. I will defer the initial focus move by one animation frame for OverlaySurface, after that branch is connected at its final location.

Follow-up evidence: Quick Look's `.ql` was visible after opening, but `document.activeElement` was `BODY` (`insideQuickLook: false`). Thus `ArrowRight` never reached its key handler. The overlay's focus trap runs as its surface mounts while the shared portal also relocates the overlay branch. I will defer the initial focus move by one animation frame for `OverlaySurface`, after that branch is connected at its final location.
Author
Owner

Finding and fix: the Files production E2E showed that Quick Look received the overlay portal after its initial synchronous focus attempt, leaving document.activeElement on BODY and preventing ArrowRight navigation. OverlaySurface now defers initial focus by one animation frame; the regression flow waits for the close control to own focus. The same run exposed that the watcher E2E wrote under server.data, while Home files are under server.userData; corrected the fixture to use the Home data root. bun e2e/files.mjs now passes all flows with zero CSP reports.

Finding and fix: the Files production E2E showed that Quick Look received the overlay portal after its initial synchronous focus attempt, leaving `document.activeElement` on BODY and preventing ArrowRight navigation. OverlaySurface now defers initial focus by one animation frame; the regression flow waits for the close control to own focus. The same run exposed that the watcher E2E wrote under `server.data`, while Home files are under `server.userData`; corrected the fixture to use the Home data root. `bun e2e/files.mjs` now passes all flows with zero CSP reports.
Author
Owner

Phone E2E reconciliation: the existing phone test expected every parent crumb to remain visible at 390 px, and later expected folder names inside the Files view switcher. The header correctly folds unavailable parent crumbs into “Show folders in this path” and keeps the view switcher limited to Files, Shared, Recent, and Trash. Updated assertions to check each control's own entries. bun e2e/phone-chrome.mjs --screenshots artifacts/chrome-sidebar-review/phone passes and captures light/dark Files, selection, drawer, and desktop screenshots.

Phone E2E reconciliation: the existing phone test expected every parent crumb to remain visible at 390 px, and later expected folder names inside the Files view switcher. The header correctly folds unavailable parent crumbs into “Show folders in this path” and keeps the view switcher limited to Files, Shared, Recent, and Trash. Updated assertions to check each control's own entries. `bun e2e/phone-chrome.mjs --screenshots artifacts/chrome-sidebar-review/phone` passes and captures light/dark Files, selection, drawer, and desktop screenshots.
Author
Owner

Finding and fix: the real production header matrix showed that phone Files breadcrumbs missed the 44×44 hit test: the “Files” link was 21×44, and the rounded crumb controls missed corner points. ModeHeader now gives short links a 44px minimum width, clips only the inner text span, and supplies square transparent hit surfaces. phone-chrome.mjs now checks the eight points of each breadcrumb control on nested and Home routes; it passes on the production build. The matrix also exposed unrelated Calendar, Notes, and Analytics layout failures; I will list their exact evidence in the final report.

Quick Look regression coverage now waits for the portaled close control to own focus before sending Escape. bun e2e/files.mjs passes all flows with zero CSP reports.

Finding and fix: the real production header matrix showed that phone Files breadcrumbs missed the 44×44 hit test: the “Files” link was 21×44, and the rounded crumb controls missed corner points. ModeHeader now gives short links a 44px minimum width, clips only the inner text span, and supplies square transparent hit surfaces. `phone-chrome.mjs` now checks the eight points of each breadcrumb control on nested and Home routes; it passes on the production build. The matrix also exposed unrelated Calendar, Notes, and Analytics layout failures; I will list their exact evidence in the final report. Quick Look regression coverage now waits for the portaled close control to own focus before sending Escape. `bun e2e/files.mjs` passes all flows with zero CSP reports.
Author
Owner

Adversarial context: the Photos shared-timeline probe reported 200 {"days":[]} after 60 seconds. This local round used ADVERSARIAL_ROUND2_ONLY=1 on a fresh server, so attack.py did not seed its photo fixture; in attack2.py, the owner timeline's a_item is therefore absent before the share. I am treating this probe result as an invalid fixture setup, not a Photos regression. The same adversarial run continues through the remaining round-2 checks.

Adversarial context: the Photos shared-timeline probe reported `200 {"days":[]}` after 60 seconds. This local round used `ADVERSARIAL_ROUND2_ONLY=1` on a fresh server, so `attack.py` did not seed its photo fixture; in `attack2.py`, the owner timeline's `a_item` is therefore absent before the share. I am treating this probe result as an invalid fixture setup, not a Photos regression. The same adversarial run continues through the remaining round-2 checks.
Author
Owner

Finished — job/chrome-sidebar pushed

Merged origin/dev once at 088e17d4fe49d6a7b41f03fcc13f5f4959346be9, preserving the intent from #243, #259, #261, and #246. Final head: 96ed2474bbec26565560e0168f0fa50071e9ae4c.

Built

  • The shared H1 sub-view menu is hidden while the sidebar is visible. Files uses a one-row breadcrumb at every width; each segment links and accepts file drops. Narrow paths fold middle segments into a menu. Crumb and ellipsis hit areas are 44×44 px.
  • Files sidebar has Files / Shared / Recent / Trash, then Pinned, then Smart folders. Pins persist through the per-user API, support drag-to-pin and reordering, and keep the keyboard Pin action and announcement path.
  • Shared chrome and mode headers remove repeated sidebar/H1 choices across Calendar, Photos, Files, Notes, and Analytics. Calendar H1 transitions keep one title visible. Added phone and header E2E coverage.
  • Kept the merged Files cache/preload behavior and bypassed cached/coalesced reads for no-store, reload, and no-cache. Fixed deferred focus for portaled overlays and the Files watcher E2E fixture.
  • Reconciled API client cache declarations. Regenerated the OpenAPI contract and types for the server’s three 503 stream-limit responses.

Key files: apps/web/src/lib/files/FilesBrowser.svelte, FilesSidebar.svelte, api.ts, api.test.ts, prefs.svelte.ts, prefs.svelte.test.ts; packages/ui/src/components/ModeHeader.svelte and menu/chrome components; apps/web/src/lib/a11y/focusTrap.ts; apps/web/e2e/files.mjs, phone-chrome.mjs, header-sweep.mjs, and layout-sweep.mjs; crates/plugins/files/src/{lib.rs,pins.rs}; packages/api-client/src/{index.ts,index.test.ts,generated.ts}; contracts/openapi.json; docs/DESIGN.md.

Gates

All required commands completed successfully. Verbatim terminal output excerpts:

$ cargo fmt --check
[exit status 0; no output]

$ cargo clippy --all-targets -- -D warnings
Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 57s

$ cargo test
[exit status 0]
test result: ok. 117 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 26.49s
test result: ok. 93 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 37.51s

$ bun run check
svelte-check found 0 errors and 0 warnings

$ bun run test
 Test Files  90 passed (90)
      Tests  629 passed (629)
   Start at  02:09:48
   Duration  44.69s (transform 59%, environment 16%, import 13%, tests 9%, setup 3%)

$ bash packages/api-client/check-generated.sh
Finished `dev` profile [unoptimized + debuginfo] target(s) in 20.50s
Running `target/debug/calternal-server openapi`
$ bunx --package openapi-typescript@7.13.0 openapi-typescript ../../contracts/openapi.json -o src/generated.ts
✨ openapi-typescript 7.13.0
🚀 ../../contracts/openapi.json → src/generated.ts [433.1ms]

bun e2e/files.mjs and bun e2e/phone-chrome.mjs --screenshots artifacts/chrome-sidebar-review/phone passed. The phone run verifies 44×44 crumb hit areas on Files Home and nested folders. Rust build output and apps/web/build / .svelte-kit were removed after the gates.

Known gaps

  • The optional header layout sweep was run once and reported failures outside the Files breadcrumb changes: Calendar label alignment, Analytics spacing and hit sizes, Notes/recent-row alignment, and 320 px / RTL / sheet-scroll cases. The initial Files crumb hit-area failure was fixed and covered by the passing phone E2E; the full sweep was not rerun.
  • The time-boxed adversarial run is inconclusive. The selected ADVERSARIAL_ROUND2_ONLY=1 mode omitted the Photos fixture seeding and dedup restart coordinator, so Photos 404s and restart/dedup reports were harness artifacts. Pin isolation checks completed without findings; the only load finding was SLOW zip streaming. No valid non-SLOW API regression was confirmed.

Decisions

The issue’s “Files breadcrumb at every width” requirement takes precedence over the older phone Back/H1 behavior in DESIGN §38. At 390 px, middle path segments can fold into the path menu; they remain available there, with 44×44 px touch targets.

Screenshots

Latest production screenshots are attached here:

## Finished — `job/chrome-sidebar` pushed Merged `origin/dev` once at `088e17d4fe49d6a7b41f03fcc13f5f4959346be9`, preserving the intent from #243, #259, #261, and #246. Final head: `96ed2474bbec26565560e0168f0fa50071e9ae4c`. ### Built - The shared H1 sub-view menu is hidden while the sidebar is visible. Files uses a one-row breadcrumb at every width; each segment links and accepts file drops. Narrow paths fold middle segments into a menu. Crumb and ellipsis hit areas are 44×44 px. - Files sidebar has Files / Shared / Recent / Trash, then Pinned, then Smart folders. Pins persist through the per-user API, support drag-to-pin and reordering, and keep the keyboard Pin action and announcement path. - Shared chrome and mode headers remove repeated sidebar/H1 choices across Calendar, Photos, Files, Notes, and Analytics. Calendar H1 transitions keep one title visible. Added phone and header E2E coverage. - Kept the merged Files cache/preload behavior and bypassed cached/coalesced reads for `no-store`, `reload`, and `no-cache`. Fixed deferred focus for portaled overlays and the Files watcher E2E fixture. - Reconciled API client cache declarations. Regenerated the OpenAPI contract and types for the server’s three 503 stream-limit responses. Key files: `apps/web/src/lib/files/FilesBrowser.svelte`, `FilesSidebar.svelte`, `api.ts`, `api.test.ts`, `prefs.svelte.ts`, `prefs.svelte.test.ts`; `packages/ui/src/components/ModeHeader.svelte` and menu/chrome components; `apps/web/src/lib/a11y/focusTrap.ts`; `apps/web/e2e/files.mjs`, `phone-chrome.mjs`, `header-sweep.mjs`, and `layout-sweep.mjs`; `crates/plugins/files/src/{lib.rs,pins.rs}`; `packages/api-client/src/{index.ts,index.test.ts,generated.ts}`; `contracts/openapi.json`; `docs/DESIGN.md`. ### Gates All required commands completed successfully. Verbatim terminal output excerpts: ```text $ cargo fmt --check [exit status 0; no output] $ cargo clippy --all-targets -- -D warnings Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 57s $ cargo test [exit status 0] test result: ok. 117 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 26.49s test result: ok. 93 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 37.51s $ bun run check svelte-check found 0 errors and 0 warnings $ bun run test Test Files 90 passed (90) Tests 629 passed (629) Start at 02:09:48 Duration 44.69s (transform 59%, environment 16%, import 13%, tests 9%, setup 3%) $ bash packages/api-client/check-generated.sh Finished `dev` profile [unoptimized + debuginfo] target(s) in 20.50s Running `target/debug/calternal-server openapi` $ bunx --package openapi-typescript@7.13.0 openapi-typescript ../../contracts/openapi.json -o src/generated.ts ✨ openapi-typescript 7.13.0 🚀 ../../contracts/openapi.json → src/generated.ts [433.1ms] ``` `bun e2e/files.mjs` and `bun e2e/phone-chrome.mjs --screenshots artifacts/chrome-sidebar-review/phone` passed. The phone run verifies 44×44 crumb hit areas on Files Home and nested folders. Rust build output and `apps/web/build` / `.svelte-kit` were removed after the gates. ### Known gaps - The optional header layout sweep was run once and reported failures outside the Files breadcrumb changes: Calendar label alignment, Analytics spacing and hit sizes, Notes/recent-row alignment, and 320 px / RTL / sheet-scroll cases. The initial Files crumb hit-area failure was fixed and covered by the passing phone E2E; the full sweep was not rerun. - The time-boxed adversarial run is inconclusive. The selected `ADVERSARIAL_ROUND2_ONLY=1` mode omitted the Photos fixture seeding and dedup restart coordinator, so Photos 404s and restart/dedup reports were harness artifacts. Pin isolation checks completed without findings; the only load finding was `SLOW` zip streaming. No valid non-SLOW API regression was confirmed. ### Decisions The issue’s “Files breadcrumb at every width” requirement takes precedence over the older phone Back/H1 behavior in DESIGN §38. At 390 px, middle path segments can fold into the path menu; they remain available there, with 44×44 px touch targets. ### Screenshots Latest production screenshots are attached here: - Files Home: [light](https://git.kayg.org/attachments/635e55a6-f39e-4f03-98fa-0b72a7911ded), [dark](https://git.kayg.org/attachments/bcbae263-a3d6-41e2-b232-12d46a68706a) - Nested Files path: [light](https://git.kayg.org/attachments/4f04f38b-0ce8-4cc5-b56e-582e9d14594f), [dark](https://git.kayg.org/attachments/2a2e2a11-aef5-457e-bd00-b51f90461065) - Folded path menu: [light](https://git.kayg.org/attachments/04b5a9da-cbdc-44d2-9841-6bb6a2fc2a1a), [dark](https://git.kayg.org/attachments/6241aa23-f41f-414e-9348-db82ded73b82) - Selection: [light](https://git.kayg.org/attachments/ccb6f320-b2f8-4c22-9846-2f74df1af5f5), [dark](https://git.kayg.org/attachments/acacaa75-a4e6-4229-a854-08008f371e76) - Desktop Files breadcrumbs: [screenshot](https://git.kayg.org/attachments/f5da712b-a1f8-4d86-9db5-870c9a3eb3f4)
Author
Owner

Merged in 71ff5e11 (svelte-check 0/0, web 629/629, generated client OK). Merge freeze lifted.

Merged in 71ff5e11 (svelte-check 0/0, web 629/629, generated client OK). Merge freeze lifted.
kayg closed this issue 2026-09-28 00:20:09 +00:00
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#156
No description provided.