Mobile: long pull to update the app; tell the User when a newer build exists #1059

Open
opened 2026-10-04 14:36:46 +00:00 by kayg · 9 comments
Owner

Owner request (2026-10-04)

"We need a long pull to refresh build / update build on mobile! I still seem to run an older build on the phone."

The installed app (home-screen PWA on iPhone) keeps running an old build: the page stays alive for days and nothing reloads it. There is no service-worker app cache (DESIGN: the service worker is for push only), so the stale code is the long-lived page itself plus any HTTP-cached shell.

Wanted

  1. Long pull to refresh on touch devices, at the top of every scrollable main view (Calendar, Notes, Files, Photos, Mail, Settings): a short pull refreshes the current view's data as today; a long pull (held past a second threshold, with a visible label change such as "Release to update calternal") reloads the app and loads the latest build. Follow platform conventions (iOS pull-to-refresh feel, spinner, haptic-free, reduced motion respected), keyboard/screen-reader equivalent: a "Reload calternal" command in the command palette and the ⋯ menu.
  2. The app tells you when a newer build exists (opinionated default): the server reports its build ID (header on API responses and a tiny /api/v1/version); when the running client's build differs, show a quiet "Update available · Reload" toast, and reload automatically at a safe moment (app returns from background with no unsaved input or open editor). Never lose unsaved input.
  3. The HTML shell is served with no-cache / must-revalidate; hashed assets stay immutable.

Acceptance

WebKit iPhone emulation e2e: old build running → server upgraded → toast appears; long pull reloads to the new build; short pull only refreshes data. Screenshots 390 light/dark of the pull states. Real iPhone check by the owner after deploy.

## Owner request (2026-10-04) "We need a long pull to refresh build / update build on mobile! I still seem to run an older build on the phone." The installed app (home-screen PWA on iPhone) keeps running an old build: the page stays alive for days and nothing reloads it. There is no service-worker app cache (DESIGN: the service worker is for push only), so the stale code is the long-lived page itself plus any HTTP-cached shell. ## Wanted 1. **Long pull to refresh** on touch devices, at the top of every scrollable main view (Calendar, Notes, Files, Photos, Mail, Settings): a short pull refreshes the current view's data as today; a **long pull** (held past a second threshold, with a visible label change such as "Release to update calternal") reloads the app and loads the latest build. Follow platform conventions (iOS pull-to-refresh feel, spinner, haptic-free, reduced motion respected), keyboard/screen-reader equivalent: a "Reload calternal" command in the command palette and the ⋯ menu. 2. **The app tells you when a newer build exists** (opinionated default): the server reports its build ID (header on API responses and a tiny `/api/v1/version`); when the running client's build differs, show a quiet "Update available · Reload" toast, and reload automatically at a safe moment (app returns from background with no unsaved input or open editor). Never lose unsaved input. 3. The HTML shell is served with no-cache / must-revalidate; hashed assets stay immutable. ## Acceptance WebKit iPhone emulation e2e: old build running → server upgraded → toast appears; long pull reloads to the new build; short pull only refreshes data. Screenshots 390 light/dark of the pull states. Real iPhone check by the owner after deploy.
Author
Owner

Starting #1059 on job/appupdate-1059, base c39ffe5d90126527d7aacf2d8b79507929c80616 (the supplied dev/production base). I will trace the existing pull, refresh, version/build, toast, palette and shell caching paths, then implement and verify the update flow with the requested WebKit evidence.

Starting #1059 on `job/appupdate-1059`, base `c39ffe5d90126527d7aacf2d8b79507929c80616` (the supplied dev/production base). I will trace the existing pull, refresh, version/build, toast, palette and shell caching paths, then implement and verify the update flow with the requested WebKit evidence.
Author
Owner

Implemented #1059. No production system was contacted.

Head: 06177e0ae7acc58dd8a50ef78d904a37e1786048

Built

  • Vite writes one build id into the SPA bundle and .calternal-build-id; the server embeds that id, sends X-Calternal-Build-Id, and serves public GET /api/v1/version. The HTML shell remains no-cache.
  • The app checks on sign-in and foreground return. It shows an “Update available” toast with Reload, offers “Reload calternal” in the command palette, and reloads on a long pull. A short pull refreshes data. Auto reload waits until no Composer, editable focus, or Note editor can hold work.
  • Added a focused WebKit e2e for stale-to-current build detection, old Log/Event request replay, pull gestures, safe foreground reload, command reload, and screenshot capture. Added /api/v1/version to the route profile.

Files

apps/web/src/lib/appUpdate.svelte.ts, apps/web/src/lib/appUpdate.ts, apps/web/src/lib/appUpdate.test.ts, apps/web/src/routes/+layout.svelte, apps/web/src/routes/layout.css, apps/web/src/lib/search/providers.ts, apps/web/src/lib/gestures.svelte.test.ts, apps/web/src/lib/search/providers.test.ts, apps/web/src/app.d.ts, apps/web/vite.config.ts, apps/web/e2e/app-update-1059.mjs, apps/web/e2e/route-perf.mjs, apps/web/package.json, packages/ui/src/gestures.ts, crates/calternal-server/build.rs, crates/calternal-server/src/main.rs, crates/calternal-server/src/security.rs, contracts/openapi.json, contracts/actions.json, packages/api-client/src/generated.ts, docs/parity-matrix.md.

Gates

cargo fmt --check — exit 0, no output.

cargo clippy -p calternal-server --all-targets -- -D warnings:

Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 52s

cargo test -p calternal-server:

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

Calendar and Notes crate gates also passed:

89 passed; 0 failed; 1 ignored
193 passed; 0 failed; 1 ignored

bun run check:

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

svelte-check found 0 errors and 0 warnings

Focused Vitest (bunx vitest run src/lib/appUpdate.test.ts src/lib/gestures.svelte.test.ts src/lib/search/providers.test.ts --maxWorkers=2):

Test Files  3 passed (3)
     Tests  19 passed (19)

Focused WebKit e2e output:

CSP REPORTS app-update-1059-setup: 0 across 1 pages
BUILD_IDS old=cfee85c6b current=923d450bcfe221ee9dd4735cdeb2d75ccc01ece5
REPLAY previous Log=201 Event=201
LONG_PULL {"oldRequests":106,"latestRequests":52}
SCREENSHOTS phone-390-light
SCREENSHOTS phone-390-dark
SCREENSHOTS tablet-820-light
SCREENSHOTS tablet-820-dark
SCREENSHOTS desktop-1440-light
SCREENSHOTS desktop-1440-dark

UX gaps closed

The short and long pull labels are exposed through a polite status region; refresh failures get an actionable toast. The update can be triggered by touch/pointer or the keyboard command. Auto reload avoids a live Composer, editable input, and Note editor. Screenshots cover the toast and both pull states at 390, 820, and 1440 px in light and dark, with macOS platform and Safari emulation.

UX gaps left

No separate assistive-technology session was available; the status and command path are covered in code and keyboard e2e, but still need a screen-reader check during merge review.

Decisions where DESIGN was silent

The short-pull threshold is 44 px and the long-pull threshold is 82 px of displayed, rubber-banded travel. Foreground checks run when the page returns from hidden state. Auto reload is safe only when there is no Composer, editable focus, or Note editor. A source build without Git metadata uses a random shared id. Please confirm these choices with the owner.

Performance

Added /api/v1/version to the existing route profile. I did not run a performance measurement because this is not a performance issue and the verification policy reserves measurements for perf jobs.

For the merge round

Run bun run test in apps/web and tests/adversarial/run.sh against the merged local server. These prove the full web suite and the combined server robustness/authz matrix still pass with the public version route and build header. Also rerun bun run test:e2e:app-update-1059 with the merged server binary to prove old-build detection, both pull outcomes, and reload safety on the combined branch.

Screenshots attached (macOS Safari emulation; all 18 states are attached to this issue):

READY FOR MERGE: yes, after the merge-round checks above.

Implemented #1059. No production system was contacted. **Head:** `06177e0ae7acc58dd8a50ef78d904a37e1786048` **Built** - Vite writes one build id into the SPA bundle and `.calternal-build-id`; the server embeds that id, sends `X-Calternal-Build-Id`, and serves public `GET /api/v1/version`. The HTML shell remains `no-cache`. - The app checks on sign-in and foreground return. It shows an “Update available” toast with Reload, offers “Reload calternal” in the command palette, and reloads on a long pull. A short pull refreshes data. Auto reload waits until no Composer, editable focus, or Note editor can hold work. - Added a focused WebKit e2e for stale-to-current build detection, old Log/Event request replay, pull gestures, safe foreground reload, command reload, and screenshot capture. Added `/api/v1/version` to the route profile. **Files** `apps/web/src/lib/appUpdate.svelte.ts`, `apps/web/src/lib/appUpdate.ts`, `apps/web/src/lib/appUpdate.test.ts`, `apps/web/src/routes/+layout.svelte`, `apps/web/src/routes/layout.css`, `apps/web/src/lib/search/providers.ts`, `apps/web/src/lib/gestures.svelte.test.ts`, `apps/web/src/lib/search/providers.test.ts`, `apps/web/src/app.d.ts`, `apps/web/vite.config.ts`, `apps/web/e2e/app-update-1059.mjs`, `apps/web/e2e/route-perf.mjs`, `apps/web/package.json`, `packages/ui/src/gestures.ts`, `crates/calternal-server/build.rs`, `crates/calternal-server/src/main.rs`, `crates/calternal-server/src/security.rs`, `contracts/openapi.json`, `contracts/actions.json`, `packages/api-client/src/generated.ts`, `docs/parity-matrix.md`. **Gates** `cargo fmt --check` — exit 0, no output. `cargo clippy -p calternal-server --all-targets -- -D warnings`: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 52s ``` `cargo test -p calternal-server`: ```text test result: ok. 165 passed; 0 failed; 6 ignored; 0 measured; 0 filtered out; finished in 62.00s ``` Calendar and Notes crate gates also passed: ```text 89 passed; 0 failed; 1 ignored 193 passed; 0 failed; 1 ignored ``` `bun run check`: ```text User browser caches use userStorage; only documented device/public-link exceptions remain. Text sizes and UI shape values use shared role tokens. UI transitions and animation options use shared motion tokens or documented exceptions. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/appupdate-1059/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` Focused Vitest (`bunx vitest run src/lib/appUpdate.test.ts src/lib/gestures.svelte.test.ts src/lib/search/providers.test.ts --maxWorkers=2`): ```text Test Files 3 passed (3) Tests 19 passed (19) ``` Focused WebKit e2e output: ```text CSP REPORTS app-update-1059-setup: 0 across 1 pages BUILD_IDS old=cfee85c6b current=923d450bcfe221ee9dd4735cdeb2d75ccc01ece5 REPLAY previous Log=201 Event=201 LONG_PULL {"oldRequests":106,"latestRequests":52} SCREENSHOTS phone-390-light SCREENSHOTS phone-390-dark SCREENSHOTS tablet-820-light SCREENSHOTS tablet-820-dark SCREENSHOTS desktop-1440-light SCREENSHOTS desktop-1440-dark ``` **UX gaps closed** The short and long pull labels are exposed through a polite status region; refresh failures get an actionable toast. The update can be triggered by touch/pointer or the keyboard command. Auto reload avoids a live Composer, editable input, and Note editor. Screenshots cover the toast and both pull states at 390, 820, and 1440 px in light and dark, with macOS platform and Safari emulation. **UX gaps left** No separate assistive-technology session was available; the status and command path are covered in code and keyboard e2e, but still need a screen-reader check during merge review. **Decisions where DESIGN was silent** The short-pull threshold is 44 px and the long-pull threshold is 82 px of displayed, rubber-banded travel. Foreground checks run when the page returns from hidden state. Auto reload is safe only when there is no Composer, editable focus, or Note editor. A source build without Git metadata uses a random shared id. Please confirm these choices with the owner. **Performance** Added `/api/v1/version` to the existing route profile. I did not run a performance measurement because this is not a performance issue and the verification policy reserves measurements for perf jobs. **For the merge round** Run `bun run test` in `apps/web` and `tests/adversarial/run.sh` against the merged local server. These prove the full web suite and the combined server robustness/authz matrix still pass with the public version route and build header. Also rerun `bun run test:e2e:app-update-1059` with the merged server binary to prove old-build detection, both pull outcomes, and reload safety on the combined branch. **Screenshots attached** (macOS Safari emulation; all 18 states are attached to this issue): - 390 light: [toast](https://git.kayg.org/attachments/0103e48c-f1d0-47ca-b582-a0e20bb2b181), [short pull](https://git.kayg.org/attachments/4605f455-4643-45ef-b942-5092c424cbec), [long pull](https://git.kayg.org/attachments/b84f400c-b7c5-4668-b906-bb104123962d) - 390 dark: [toast](https://git.kayg.org/attachments/9847d0d2-70c4-4479-8be1-6c4b80166a12), [short pull](https://git.kayg.org/attachments/bbb9e1de-dab5-4c02-abc6-df59c7252951), [long pull](https://git.kayg.org/attachments/2a20558c-6955-479f-829e-8f19961e7b7e) - 820 light: [toast](https://git.kayg.org/attachments/a08dbd1c-b695-4364-bf43-ffae3defe86a), [short pull](https://git.kayg.org/attachments/b5cc424e-8dc0-44ce-a9e6-785e3f621d0f), [long pull](https://git.kayg.org/attachments/0afa6a2f-00ee-4a66-a984-a23e88d34d77) - 820 dark: [toast](https://git.kayg.org/attachments/c7a2668c-87bc-4a95-950d-f0716ba5db5a), [short pull](https://git.kayg.org/attachments/908ae31d-250a-4f39-b62d-79c4cfb48304), [long pull](https://git.kayg.org/attachments/c8c341e3-5c6b-485c-b94d-8ce8fb6e827a) - 1440 light: [toast](https://git.kayg.org/attachments/5be792e8-41a7-465e-be8f-edaec163fce3), [short pull](https://git.kayg.org/attachments/edbb3a83-8e24-4cc5-8c48-4c62b0ade462), [long pull](https://git.kayg.org/attachments/07f848e7-203b-4c9e-9372-46a87863faf7) - 1440 dark: [toast](https://git.kayg.org/attachments/14c4c6d6-e0a7-4d6c-9ce1-e952a9cd1748), [short pull](https://git.kayg.org/attachments/da1ec361-b26e-4417-9399-d8efb61d2da2), [long pull](https://git.kayg.org/attachments/aae5f62d-3006-4f51-8df5-b01e734cd8f3) **READY FOR MERGE:** yes, after the merge-round checks above.
Author
Owner

Starting merge round 8 in job/merge-round-8 from production dev SHA 9fb9a4bfb2. I have confirmed the worktree is clean and am reading the incoming branch deltas before integration.

Starting merge round 8 in job/merge-round-8 from production dev SHA 9fb9a4bfb2488152c83d50c55441ff5f43b572b2. I have confirmed the worktree is clean and am reading the incoming branch deltas before integration.
Author
Owner

Finding during contract regeneration: the new GET /api/v1/version operation made calternal-server openapi panic at action_contract.rs:74 because operationId version had no reviewed action policy. I added a public read-only safe_read policy and excluded the web-only build check from agent adapters. Regeneration now completes; the action registry reports 390 operations and 367 generated tools.

Finding during contract regeneration: the new GET /api/v1/version operation made calternal-server openapi panic at action_contract.rs:74 because operationId version had no reviewed action policy. I added a public read-only safe_read policy and excluded the web-only build check from agent adapters. Regeneration now completes; the action registry reports 390 operations and 367 generated tools.
Author
Owner

The production Mac WebKit capture at 390 px exposed overlapping pull-label glyphs even though the one-line Range check passed. Waiting for the pull transition did not remove it. I am tracing the live rendered nodes and computed styles before closing this visual defect. The affected captures are in the ignored artifacts/appupdate-1059/ directory in this worktree.

The production Mac WebKit capture at 390 px exposed overlapping pull-label glyphs even though the one-line Range check passed. Waiting for the pull transition did not remove it. I am tracing the live rendered nodes and computed styles before closing this visual defect. The affected captures are in the ignored `artifacts/appupdate-1059/` directory in this worktree.
Author
Owner

The media probe preflight exited before starting a server. Evidence: XUSER_CLASSIFY_ONLY=1 python3 tests/adversarial/xuser_matrix.py raised OpenAPI operation has no authorization policy: GET /api/v1/version (version). The generated action policy already marks version as public, and the handler returns only build metadata; the adversarial classifier omitted that public operation. I am adding the missing classifier entry, then will rerun the requested probes.

The media probe preflight exited before starting a server. Evidence: `XUSER_CLASSIFY_ONLY=1 python3 tests/adversarial/xuser_matrix.py` raised `OpenAPI operation has no authorization policy: GET /api/v1/version (version)`. The generated action policy already marks `version` as public, and the handler returns only build metadata; the adversarial classifier omitted that public operation. I am adding the missing classifier entry, then will rerun the requested probes.
Author
Owner

The 390 px capture now identifies the overlap: Release to refresh sits directly over Calendar's Show earlier days control while the pull pill is translucent. Its rendered DOM contains only one pull label, and the tablet/desktop captures do not collide. I am making the transient pull pill's tint nearly opaque so the control underneath cannot show through it; the regular StatusPill material stays unchanged.

The 390 px capture now identifies the overlap: `Release to refresh` sits directly over Calendar's `Show earlier days` control while the pull pill is translucent. Its rendered DOM contains only one pull label, and the tablet/desktop captures do not collide. I am making the transient pull pill's tint nearly opaque so the control underneath cannot show through it; the regular StatusPill material stays unchanged.
Author
Owner

Merge-round 8 is complete on job/merge-round-8 at 2b6c77c14be78e7d1e1030e23b14c63a6772fca7 (base dev at 9fb9a4bfb). READY FOR STAGING: yes. No push, merge or deploy was made.

Integrated #1059 long-pull refresh/update and stale-build notification with build-ID response and previous-release compatibility; #1053 invite access toggle; #1045 retryable PDF previews; #1044 NFC/NFD analyzer version bump and one bounded startup reindex; and 6153d62d0 Notes idle event-rate probe. Regenerated the API contract from the server and TypeScript client:

$ CALTERNAL_SERVER_BIN=... bash packages/api-client/check-generated.sh
$ 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 [572.6ms]

No generated contract diff remained.

Gates: cargo fmt --check exited 0 with no output. cargo clippy -p <crate> --all-targets -- -D warnings and cargo test -p <crate> passed for calternal-plugin, calternal-plugin-files, calternal-fs, calternal-search, calternal-server, calternal-plugin-calendar and calternal-plugin-notes. Recorded test totals: 39; 238 passed/3 ignored; 85 unit plus storage integration 48; 55 unit plus indexer 25; server 212 unit plus perf-guard and private-index tests; calendar 100 unit plus cache 1 and protocol 3; Notes 265 unit plus Apple replay 2.

Verbatim retained web gate summaries:

svelte-check found 0 errors and 4 warnings in 3 files
 Test Files  224 passed (224)
      Tests  1517 passed (1517)
   Start at  02:12:16
   Duration  235.06s (transform 34%, environment 23%, import 19%, tests 19%, setup 5%)
 Test Files  21 passed (21)
      Tests  433 passed (433)
   Start at  23:39:12
   Duration  23.94s (transform 3.99s, setup 328ms, import 9.40s, tests 10.09s, environment 23.03s)

app-update-1059 passed against the final server and stale/current production SPAs; previous-release Log/Event replay returned 201. The final Mac Safari capture reports:

BUILD_IDS old=1059dead current=2b6c77c14be78e7d1e1030e23b14c63a6772fca7
REPLAY previous Log=201 Event=201
LONG_PULL {"oldRequests":128,"latestRequests":66}
SCREENSHOTS phone-390-light
SCREENSHOTS phone-390-dark
SCREENSHOTS tablet-820-light
SCREENSHOTS tablet-820-dark
SCREENSHOTS desktop-1440-light
SCREENSHOTS desktop-1440-dark

invite-1035 --notes passed: 5 Guests granted one item; sixth refused; revocation preserves grants; policy hides invite tick; Chromium + WebKit evidence captured. The API classification gate passed: 392 operations, 1101 tools, 47 reviewed admin operations.

The focused Search chaos run hit its 5-second indexing deadline:

FAIL search chaos: search did not find uploaded marker unicodenfcsentinel
FAIL search chaos: search did not find uploaded marker unicodenfdsentinel
FAIL search chaos: NFD canonical Unicode query missed expected filenames: []

A direct live-server follow-up found the NFC filename in 64ms and all NFC/NFD filename/body searches by 14.6s; the startup probe completed its v2 rebuild in 18.212s, served 16/16 concurrent searches successfully, and returned HTTP 200 for NFC/NFD Search. Classified as load-sensitive indexing delay (SLOW), not a missing result after indexing.

The PDF probe's 15-second wait also expired under a 7-document burst. The valid one-page PDF reached a terminal successful job at 20.3s and produced 256px and 1024px WebP previews; malformed and oversized PDFs produced no previews. Classified SLOW. Notes idle probe: 0 events/min across the 60-second idle windows before and after one Log write; the write returned HTTP 201 in 350.73ms and emitted 4 events. No non-SLOW adversarial finding remains.

UX gaps closed: pull feedback now hides both the Agenda pager and its explicitly visible child label, then restores them on cancel; the e2e checks both states on the 390px Agenda and captures update/pull states at 390/820/1440 in light/dark with Mac platform emulation. Invite captures cover the invite section in light/dark, empty/created/policy states, Chromium and WebKit. UX gaps left: Search indexing and PDF preview can exceed the focused probes' 5s/15s deadlines under burst load, as measured above.

Decision not specified by DESIGN: keep the Agenda pager's slot stable but hide its button and label during pull feedback, to prevent overlap without shifting the day list. Wider responsive Calendar views use Week layout and have no Agenda pager, so the pager visibility assertion runs only where that control exists.

Screenshots remain in ignored worktree paths: artifacts/appupdate-1059/ (18 PNGs), artifacts/invite-1035/ (78 PNGs). scripts/fj issue has no attachment command, so these were not uploaded. The branch diff covers 52 files across app update, invitation sharing, search, previews, Notes, contracts and adversarial/performance coverage.

Merge-round 8 is complete on `job/merge-round-8` at `2b6c77c14be78e7d1e1030e23b14c63a6772fca7` (base `dev` at `9fb9a4bfb`). READY FOR STAGING: **yes**. No push, merge or deploy was made. Integrated #1059 long-pull refresh/update and stale-build notification with build-ID response and previous-release compatibility; #1053 invite access toggle; #1045 retryable PDF previews; #1044 NFC/NFD analyzer version bump and one bounded startup reindex; and `6153d62d0` Notes idle event-rate probe. Regenerated the API contract from the server and TypeScript client: ``` $ CALTERNAL_SERVER_BIN=... bash packages/api-client/check-generated.sh $ 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 [572.6ms] ``` No generated contract diff remained. Gates: `cargo fmt --check` exited 0 with no output. `cargo clippy -p <crate> --all-targets -- -D warnings` and `cargo test -p <crate>` passed for `calternal-plugin`, `calternal-plugin-files`, `calternal-fs`, `calternal-search`, `calternal-server`, `calternal-plugin-calendar` and `calternal-plugin-notes`. Recorded test totals: 39; 238 passed/3 ignored; 85 unit plus storage integration 48; 55 unit plus indexer 25; server 212 unit plus perf-guard and private-index tests; calendar 100 unit plus cache 1 and protocol 3; Notes 265 unit plus Apple replay 2. Verbatim retained web gate summaries: ``` svelte-check found 0 errors and 4 warnings in 3 files Test Files 224 passed (224) Tests 1517 passed (1517) Start at 02:12:16 Duration 235.06s (transform 34%, environment 23%, import 19%, tests 19%, setup 5%) Test Files 21 passed (21) Tests 433 passed (433) Start at 23:39:12 Duration 23.94s (transform 3.99s, setup 328ms, import 9.40s, tests 10.09s, environment 23.03s) ``` `app-update-1059` passed against the final server and stale/current production SPAs; previous-release Log/Event replay returned 201. The final Mac Safari capture reports: ``` BUILD_IDS old=1059dead current=2b6c77c14be78e7d1e1030e23b14c63a6772fca7 REPLAY previous Log=201 Event=201 LONG_PULL {"oldRequests":128,"latestRequests":66} SCREENSHOTS phone-390-light SCREENSHOTS phone-390-dark SCREENSHOTS tablet-820-light SCREENSHOTS tablet-820-dark SCREENSHOTS desktop-1440-light SCREENSHOTS desktop-1440-dark ``` `invite-1035 --notes` passed: `5 Guests granted one item; sixth refused; revocation preserves grants; policy hides invite tick; Chromium + WebKit evidence captured`. The API classification gate passed: 392 operations, 1101 tools, 47 reviewed admin operations. The focused Search chaos run hit its 5-second indexing deadline: ``` FAIL search chaos: search did not find uploaded marker unicodenfcsentinel FAIL search chaos: search did not find uploaded marker unicodenfdsentinel FAIL search chaos: NFD canonical Unicode query missed expected filenames: [] ``` A direct live-server follow-up found the NFC filename in 64ms and all NFC/NFD filename/body searches by 14.6s; the startup probe completed its v2 rebuild in 18.212s, served 16/16 concurrent searches successfully, and returned HTTP 200 for NFC/NFD Search. Classified as load-sensitive indexing delay (SLOW), not a missing result after indexing. The PDF probe's 15-second wait also expired under a 7-document burst. The valid one-page PDF reached a terminal successful job at 20.3s and produced 256px and 1024px WebP previews; malformed and oversized PDFs produced no previews. Classified SLOW. Notes idle probe: 0 events/min across the 60-second idle windows before and after one Log write; the write returned HTTP 201 in 350.73ms and emitted 4 events. No non-SLOW adversarial finding remains. UX gaps closed: pull feedback now hides both the Agenda pager and its explicitly visible child label, then restores them on cancel; the e2e checks both states on the 390px Agenda and captures update/pull states at 390/820/1440 in light/dark with Mac platform emulation. Invite captures cover the invite section in light/dark, empty/created/policy states, Chromium and WebKit. UX gaps left: Search indexing and PDF preview can exceed the focused probes' 5s/15s deadlines under burst load, as measured above. Decision not specified by DESIGN: keep the Agenda pager's slot stable but hide its button and label during pull feedback, to prevent overlap without shifting the day list. Wider responsive Calendar views use Week layout and have no Agenda pager, so the pager visibility assertion runs only where that control exists. Screenshots remain in ignored worktree paths: `artifacts/appupdate-1059/` (18 PNGs), `artifacts/invite-1035/` (78 PNGs). `scripts/fj issue` has no attachment command, so these were not uploaded. The branch diff covers 52 files across app update, invitation sharing, search, previews, Notes, contracts and adversarial/performance coverage.
Author
Owner

Deployed to production 2026-10-05 03:12 CEST in round 8 (2b6c77c14). Staging healthy first; production healthy in 33 s; /api/v1/version reports the build ID; change events 0/30 s.

Deployed to production 2026-10-05 03:12 CEST in round 8 (2b6c77c14). Staging healthy first; production healthy in 33 s; `/api/v1/version` reports the build ID; change events 0/30 s.
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#1059
No description provided.