LOCATION: one Location setting and its uses — location reminders via Apple Reminders geofencing (grill) #391

Closed
opened 2026-09-29 04:16:15 +00:00 by kayg · 62 comments
Owner

Request (owner, 2026-09-29)

"why is the location permission here? what is it being used for? the sunset thing? for auto theme switching? I feel like we could use the location toggle for much more like location reminders."

Today

Settings → Appearance → Theme & UI → "Use my precise location" feeds only the Auto colour scheme (#324): sunrise/sunset from coordinates rounded to 0.1° (~10 km), otherwise the time-zone reference city.

Constraint

A web app cannot watch location in the background (iOS has no background geolocation for web apps). Arrive/leave reminders on iPhone work through Apple Reminders' native geofencing: a VTODO VALARM with X-APPLE-STRUCTURED-LOCATION and X-APPLE-PROXIMITY:ARRIVE|DEPART over CalDAV (#358 now preserves these properties). A future native app could geofence itself.

Grill (open; do not build until answered and recorded in DESIGN.md)

  • L1 One Location section (Account/Privacy) that lists which features use it; Auto theme reads from it. Recommended: yes.
  • L2 Location reminders on tasks/block reminders via Apple Reminders' native geofencing over CalDAV. Recommended: yes.
  • L3 Saved places (Home, Work, Gym: name, pin, radius) in one plaintext file in Home. Recommended: yes.
  • L4 Saved-place name on log entries from the phone, opt-in, never raw coordinates in notes. Recommended: opt-in, off by default.
  • L5 Travel time-zone detection (confirm switch), weather in the daily note, "near me" photo search. Recommended: time-zone detection now; others later.
  • L6 Precision: rounded for the theme, exact for saved places, nothing precise in notes. Recommended: yes.
## Request (owner, 2026-09-29) "why is the location permission here? what is it being used for? the sunset thing? for auto theme switching? I feel like we could use the location toggle for much more like location reminders." ## Today Settings → Appearance → Theme & UI → "Use my precise location" feeds only the Auto colour scheme (#324): sunrise/sunset from coordinates rounded to 0.1° (~10 km), otherwise the time-zone reference city. ## Constraint A web app cannot watch location in the background (iOS has no background geolocation for web apps). Arrive/leave reminders on iPhone work through Apple Reminders' native geofencing: a VTODO VALARM with `X-APPLE-STRUCTURED-LOCATION` and `X-APPLE-PROXIMITY:ARRIVE|DEPART` over CalDAV (#358 now preserves these properties). A future native app could geofence itself. ## Grill (open; do not build until answered and recorded in DESIGN.md) - L1 One Location section (Account/Privacy) that lists which features use it; Auto theme reads from it. Recommended: yes. - L2 Location reminders on tasks/block reminders via Apple Reminders' native geofencing over CalDAV. Recommended: yes. - L3 Saved places (Home, Work, Gym: name, pin, radius) in one plaintext file in Home. Recommended: yes. - L4 Saved-place name on log entries from the phone, opt-in, never raw coordinates in notes. Recommended: opt-in, off by default. - L5 Travel time-zone detection (confirm switch), weather in the daily note, "near me" photo search. Recommended: time-zone detection now; others later. - L6 Precision: rounded for the theme, exact for saved places, nothing precise in notes. Recommended: yes.
Author
Owner

Decided (owner, 2026-09-29), recorded in DESIGN §47: L1 yes; L2 yes (meant for the iOS app anyway; Apple Reminders geofencing over CalDAV until then); L3 plaintext; L4 yes (on by default with the Location permission, user can turn it off); L5 agreed (travel time-zone detection now); L6 exact precision everywhere: 'what are we hiding from? it's the user's personal cloud'.

Decided (owner, 2026-09-29), recorded in DESIGN §47: L1 yes; L2 yes (meant for the iOS app anyway; Apple Reminders geofencing over CalDAV until then); L3 plaintext; L4 yes (on by default with the Location permission, user can turn it off); L5 agreed (travel time-zone detection now); L6 exact precision everywhere: 'what are we hiding from? it's the user's personal cloud'.
Author
Owner

Starting #391 on branch job/location, based at d5dfcb93d4a5eae67be0311c68554bf94e1ba825 (the current merge-base with dev). I confirmed the owner decision comment and DESIGN §47. Scope: L1, L3–L6; L2 remains with #393. I will inspect the existing location, preferences, log, deep-link, and filesystem patterns before implementing.

Starting #391 on branch `job/location`, based at `d5dfcb93d4a5eae67be0311c68554bf94e1ba825` (the current merge-base with `dev`). I confirmed the owner decision comment and DESIGN §47. Scope: L1, L3–L6; L2 remains with #393. I will inspect the existing location, preferences, log, deep-link, and filesystem patterns before implementing.
Author
Owner

Finding — L6: apps/web/src/lib/appearance/autoScheme.svelte.ts rounded browser coordinates to 0.1°, and crates/calternal-server/src/appearance.rs rounded again on both GET and PUT. The server test expected 28.6139/77.209 to become 28.6/77.2. I removed the client and server rounding and changed the test to require exact values; existing legacy rounded values remain as stored until the User refreshes Location with a precise browser fix.

Finding — L6: `apps/web/src/lib/appearance/autoScheme.svelte.ts` rounded browser coordinates to 0.1°, and `crates/calternal-server/src/appearance.rs` rounded again on both GET and PUT. The server test expected 28.6139/77.209 to become 28.6/77.2. I removed the client and server rounding and changed the test to require exact values; existing legacy rounded values remain as stored until the User refreshes Location with a precise browser fix.
Author
Owner

Implementation decisions where DESIGN §47 is silent:

  • Saved places live in one readable Places.json file in the User's Home. Each place has a stable UUID, a name, exact coordinates and an editable radius. The default radius is 100 m; valid values are 10 m through 100,000 m.
  • A pin uses the current device fix or typed decimal coordinates. There is no local address geocoder in the repository. I will not send an address or coordinates to an outside service because §47 says location data stays in the Instance.
  • The server resolves coordinates to an IANA time zone locally with utz 0.4.1+2026c (MIT; verified with cargo info), so travel detection makes no third-party request.
Implementation decisions where DESIGN §47 is silent: - Saved places live in one readable `Places.json` file in the User's Home. Each place has a stable UUID, a name, exact coordinates and an editable radius. The default radius is 100 m; valid values are 10 m through 100,000 m. - A pin uses the current device fix or typed decimal coordinates. There is no local address geocoder in the repository. I will not send an address or coordinates to an outside service because §47 says location data stays in the Instance. - The server resolves coordinates to an IANA time zone locally with `utz` 0.4.1+2026c (MIT; verified with `cargo info`), so travel detection makes no third-party request.
Author
Owner

Finding — old appearance.auto_scheme.location values were rounded to 0.1°, so their discarded precision cannot be recovered. The migration moves that value into Location, marks it approximate, preserves the prior opt-in and Auto scheme, and replaces it with a full browser fix when Location is enabled and geolocation is available.

Finding — old `appearance.auto_scheme.location` values were rounded to 0.1°, so their discarded precision cannot be recovered. The migration moves that value into Location, marks it approximate, preserves the prior opt-in and Auto scheme, and replaces it with a full browser fix when Location is enabled and geolocation is available.
Author
Owner

Owner (2026-09-29): remove the 'Next switch' row ("Using New Delhi as the reference…" / "Dark at 18:09 your time") from Appearance entirely — there is no reason to show it. Instead, hovering or focusing the Auto segment shows a tooltip: 'Next flip at

Owner (2026-09-29): remove the 'Next switch' row ("Using New Delhi as the reference…" / "Dark at 18:09 your time") from Appearance entirely — there is no reason to show it. Instead, hovering or focusing the **Auto** segment shows a tooltip: 'Next flip at <time>' (the shared warm tooltip; on touch, a long-press shows it).
Author
Owner

Decision — each Log line will carry its Saved place UUID and name snapshot in a trailing HTML comment. It keeps the place label with the Log entry through moves and Saved place renames or removal, and it stores no coordinates in the Daily note. The Calendar Index will project that reference for entry rows and previews. Typed pins accept decimal coordinates; I will not use an outside address geocoder because Location data must stay in this Instance.

Decision — each Log line will carry its Saved place UUID and name snapshot in a trailing HTML comment. It keeps the place label with the Log entry through moves and Saved place renames or removal, and it stores no coordinates in the Daily note. The Calendar Index will project that reference for entry rows and previews. Typed pins accept decimal coordinates; I will not use an outside address geocoder because Location data must stay in this Instance.
Author
Owner

Finding — confirmed timezone reload: LocationStore.load() restored the API client’s day-key zone but left Calendar’s local date/time helpers on the browser zone. This made the same confirmed zone behave differently after a reload. The store now restores both overrides; a regression test checks both setters.

Finding — confirmed timezone reload: `LocationStore.load()` restored the API client’s day-key zone but left Calendar’s local date/time helpers on the browser zone. This made the same confirmed zone behave differently after a reload. The store now restores both overrides; a regression test checks both setters.
Author
Owner

Finding — focused web tests: the Calendar suite calls formatStamp through @calternal/ui; the timezone work used that helper in localNow but the package index did not export it. I added the public export. Verification now passes: Test Files 2 passed (2) and Tests 23 passed (23) for location.test.ts and zones.test.ts.

Finding — focused web tests: the Calendar suite calls `formatStamp` through `@calternal/ui`; the timezone work used that helper in `localNow` but the package index did not export it. I added the public export. Verification now passes: `Test Files 2 passed (2)` and `Tests 23 passed (23)` for `location.test.ts` and `zones.test.ts`.
Author
Owner

After merging dev, the Location server build failed because its settings error match did not cover the new UserSettingsError::InsufficientStorage variant (E0004 at crates/calternal-server/src/location.rs:253). I added HTTP 507 mapping for Location preferences and Saved places writes, documented the response in the Location OpenAPI operations, and added regressions for the Home quota path and server mapping. cargo test -p calternal-location passed (8 tests); the focused server mapping test passed (1 test).

After merging `dev`, the Location server build failed because its settings error match did not cover the new `UserSettingsError::InsufficientStorage` variant (E0004 at `crates/calternal-server/src/location.rs:253`). I added HTTP 507 mapping for Location preferences and Saved places writes, documented the response in the Location OpenAPI operations, and added regressions for the Home quota path and server mapping. `cargo test -p calternal-location` passed (8 tests); the focused server mapping test passed (1 test).
Author
Owner

The one adversarial run passed the 70 KB request-body check (HTTP 413), malformed and invalid-coordinate checks, concurrent place writes, and cross-User isolation. It then reached the oversized Places.json check, which returned 413, but the harness failed while restoring its temp fixture (EACCES on a calternal-fs read-only file). I removed direct writes to the server's private Home from the harness. The API body limit remains in the probe, and crates/calternal-location/tests/places.rs exercises the on-disk size limit through Root. I did not rerun the adversarial round.

The one adversarial run passed the 70 KB request-body check (HTTP 413), malformed and invalid-coordinate checks, concurrent place writes, and cross-User isolation. It then reached the oversized `Places.json` check, which returned 413, but the harness failed while restoring its temp fixture (`EACCES` on a `calternal-fs` read-only file). I removed direct writes to the server's private Home from the harness. The API body limit remains in the probe, and `crates/calternal-location/tests/places.rs` exercises the on-disk size limit through `Root`. I did not rerun the adversarial round.
Author
Owner

Implemented Forgejo #391 on job/location.

Built

  • Account → Location owns consent and feature toggles. Appearance Auto reads shared Location state, shows “Next flip at
  • Saved places use Places.json in the User Home, with exact coordinates, current-fix or typed-coordinate entry, CRUD, radius matching, stable place-ID links, and per-User isolation.
  • Log entries snapshot the matching place ID/name and Calendar projections show that name. Travel time-zone suggestions use local bundled data and require confirmation.
  • Location quota failures map to HTTP 507 and are documented in OpenAPI.

Files

  • Backend: crates/calternal-location/, crates/calternal-server/src/location.rs, crates/calternal-server/src/appearance.rs, crates/calternal-plugin/src/user_settings.rs.
  • Notes and Calendar: crates/calternal-notes-core/, crates/plugins/notes/, crates/plugins/calendar/.
  • Web and API: apps/web/src/lib/location/, apps/web/src/lib/appearance/autoScheme.svelte.ts, Settings and Calendar routes, apps/web/e2e/appearance-review.mjs, packages/api-client/src/generated.ts, contracts/openapi.json.
  • Probes: tests/adversarial/appearance_auto_scheme.mjs and Location tests under crates/calternal-location/tests/places.rs.

Head: 007289ab7972c89a1ca5212b03ec72ddb527663e (worktree clean). The local dev branch was merged once into this branch. No merge into dev was made.

Gate output

CARGO_FMT_EXIT=0
    Checking foldhash v0.2.0

CARGO_CLIPPY_EXIT=130

The four-hour job limit stopped Clippy while it was still checking dependencies. Full cargo test, bun run check, and bun run test were not run within that limit. Focused tests passed: cargo test -p calternal-location (8 passed), and cargo test -p calternal-server location::tests::user_settings_quota_errors_return_insufficient_storage (1 passed). The focused web tests passed earlier. Production web build passed.

Visual review: 12 production screenshots passed at 390/820/1440 px in light/dark for Location and Auto. They are in artifacts/appearance-review/. scripts/fj has no attachment command, so the screenshots remain in the worktree for the visual reviewer.

Adversarial round: The probe reached and passed malformed/bogus input, 70 KB request-body rejection (413), Unicode, 12 concurrent writes, and cross-User checks. The oversized on-disk file returned 413, then the harness failed restoring its read-only temp file with EACCES. I removed direct Home-file mutation from the probe and kept the on-disk size regression in the calternal-location tests. The adversarial round was not rerun.

Known review gap: The existing full Appearance review assertion expects 16 menuitemradio elements in dark mode. Three variant families render as submenu parents, so the observed count is 13 radios plus 3 submenu parents. I kept that expectation unchanged; the focused Location/Auto screenshot review passed.

Decisions: Use Places.json; capture place UUID/name in a trailing Log comment; use exact coordinates; allow typed coordinates without an external geocoder; use local timezone data and require User confirmation; preserve Location item query/hash during Settings canonicalization. L2 remains owned by #393; crates/calternal-dav was not edited by this job.

Implemented Forgejo #391 on `job/location`. **Built** - Account → Location owns consent and feature toggles. Appearance Auto reads shared Location state, shows “Next flip at <time>” on Auto, and no longer has a separate “Next switch” row. - Saved places use `Places.json` in the User Home, with exact coordinates, current-fix or typed-coordinate entry, CRUD, radius matching, stable place-ID links, and per-User isolation. - Log entries snapshot the matching place ID/name and Calendar projections show that name. Travel time-zone suggestions use local bundled data and require confirmation. - Location quota failures map to HTTP 507 and are documented in OpenAPI. **Files** - Backend: `crates/calternal-location/`, `crates/calternal-server/src/location.rs`, `crates/calternal-server/src/appearance.rs`, `crates/calternal-plugin/src/user_settings.rs`. - Notes and Calendar: `crates/calternal-notes-core/`, `crates/plugins/notes/`, `crates/plugins/calendar/`. - Web and API: `apps/web/src/lib/location/`, `apps/web/src/lib/appearance/autoScheme.svelte.ts`, Settings and Calendar routes, `apps/web/e2e/appearance-review.mjs`, `packages/api-client/src/generated.ts`, `contracts/openapi.json`. - Probes: `tests/adversarial/appearance_auto_scheme.mjs` and Location tests under `crates/calternal-location/tests/places.rs`. **Head**: `007289ab7972c89a1ca5212b03ec72ddb527663e` (worktree clean). The local `dev` branch was merged once into this branch. No merge into `dev` was made. **Gate output** ```text CARGO_FMT_EXIT=0 ``` ```text Checking foldhash v0.2.0 CARGO_CLIPPY_EXIT=130 ``` The four-hour job limit stopped Clippy while it was still checking dependencies. Full `cargo test`, `bun run check`, and `bun run test` were not run within that limit. Focused tests passed: `cargo test -p calternal-location` (8 passed), and `cargo test -p calternal-server location::tests::user_settings_quota_errors_return_insufficient_storage` (1 passed). The focused web tests passed earlier. Production web build passed. **Visual review**: 12 production screenshots passed at 390/820/1440 px in light/dark for Location and Auto. They are in `artifacts/appearance-review/`. `scripts/fj` has no attachment command, so the screenshots remain in the worktree for the visual reviewer. **Adversarial round**: The probe reached and passed malformed/bogus input, 70 KB request-body rejection (413), Unicode, 12 concurrent writes, and cross-User checks. The oversized on-disk file returned 413, then the harness failed restoring its read-only temp file with `EACCES`. I removed direct Home-file mutation from the probe and kept the on-disk size regression in the `calternal-location` tests. The adversarial round was not rerun. **Known review gap**: The existing full Appearance review assertion expects 16 `menuitemradio` elements in dark mode. Three variant families render as submenu parents, so the observed count is 13 radios plus 3 submenu parents. I kept that expectation unchanged; the focused Location/Auto screenshot review passed. **Decisions**: Use `Places.json`; capture place UUID/name in a trailing Log comment; use exact coordinates; allow typed coordinates without an external geocoder; use local timezone data and require User confirmation; preserve Location item query/hash during Settings canonicalization. L2 remains owned by #393; `crates/calternal-dav` was not edited by this job.
Author
Owner

Review of job/location head 007289ab: sent back. (1) Saved places move from Places.json to a hand-editable Places.md (one heading per place, list lines, unknown content preserved). (2) Clippy, full tests and the web check did not run before the time limit, so run them now. (3) Fix the probe fixture restore and rerun it. (4) Correct the stale Appearance radio count.

Review of job/location head 007289ab: sent back. (1) Saved places move from Places.json to a hand-editable Places.md (one heading per place, list lines, unknown content preserved). (2) Clippy, full tests and the web check did not run before the time limit, so run them now. (3) Fix the probe fixture restore and rerun it. (4) Correct the stale Appearance radio count.
Author
Owner

Resuming #391 on branch at . The current merge-base with is ; this branch already contains the earlier one-time merge of (). I am completing the Markdown Saved places store, design/test updates, probe fixture restore and rerun, and the Appearance menu count assertion.

Resuming #391 on branch at . The current merge-base with is ; this branch already contains the earlier one-time merge of (). I am completing the Markdown Saved places store, design/test updates, probe fixture restore and rerun, and the Appearance menu count assertion.
Author
Owner

Resuming #391 on branch job/location at 007289ab7972c89a1ca5212b03ec72ddb527663e. The current merge-base with dev is c46515046871936ad681c4d00e8b76de69dde3b7; this branch already contains the earlier one-time merge of dev (56340ec1). I am completing the Markdown Saved places store, design and test updates, probe fixture restore and rerun, and the Appearance menu count assertion.

Resuming #391 on branch `job/location` at `007289ab7972c89a1ca5212b03ec72ddb527663e`. The current merge-base with `dev` is `c46515046871936ad681c4d00e8b76de69dde3b7`; this branch already contains the earlier one-time merge of `dev` (`56340ec1`). I am completing the Markdown Saved places store, design and test updates, probe fixture restore and rerun, and the Appearance menu count assertion.
Author
Owner

Finding during the required dev merge: dev uses Notes migration IDs 16 and 17 for Daily note navigation, while this branch used ID 16 for the Log Saved place projection. I kept dev's migrations at 16/17 and moved the not-yet-deployed Location projection migration to ID 18 (0018_log_place.sql), so the merged migration set has unique, increasing IDs. The shared-theme E2E conflicts now use the dev theme helper; the Location branch's LogPlace exports and dev's set_daily_note_navigation export are both retained.

Finding during the required `dev` merge: `dev` uses Notes migration IDs 16 and 17 for Daily note navigation, while this branch used ID 16 for the Log Saved place projection. I kept `dev`'s migrations at 16/17 and moved the not-yet-deployed Location projection migration to ID 18 (`0018_log_place.sql`), so the merged migration set has unique, increasing IDs. The shared-theme E2E conflicts now use the `dev` theme helper; the Location branch's `LogPlace` exports and `dev`'s `set_daily_note_navigation` export are both retained.
Author
Owner

Finding after the dev merge: cargo clippy --all-targets -- -D warnings stops in crates/calternal-notes-core/src/dayfile.rs with manual_is_multiple_of at line 1419 and chunks_exact_to_as_chunks at line 1424. I will apply Clippy's equivalent suggestions; this affects no Location format behavior.

Finding after the `dev` merge: `cargo clippy --all-targets -- -D warnings` stops in `crates/calternal-notes-core/src/dayfile.rs` with `manual_is_multiple_of` at line 1419 and `chunks_exact_to_as_chunks` at line 1424. I will apply Clippy's equivalent suggestions; this affects no Location format behavior.
Author
Owner

Finding in the second cargo clippy --all-targets -- -D warnings run: crates/calternal-location/src/lib.rs:143 triggers needless_option_as_deref; expected is already an Option<&str>. I will pass it directly to write_checked.

Finding in the second `cargo clippy --all-targets -- -D warnings` run: `crates/calternal-location/src/lib.rs:143` triggers `needless_option_as_deref`; `expected` is already an `Option<&str>`. I will pass it directly to `write_checked`.
Author
Owner

Finding in the latest cargo clippy --all-targets -- -D warnings run: server compilation stops in crates/calternal-server/src/main.rs:67 because the RustEmbed derive cannot find generated apps/web/build/. This is the production web build prerequisite; I will build the web app before the final Clippy rerun and adversarial probe.

Finding in the latest `cargo clippy --all-targets -- -D warnings` run: server compilation stops in `crates/calternal-server/src/main.rs:67` because the `RustEmbed` derive cannot find generated `apps/web/build/`. This is the production web build prerequisite; I will build the web app before the final Clippy rerun and adversarial probe.
Author
Owner

Post-merge bun run check finding: apps/web/src/lib/location/location.svelte.ts treated LocationView.position and LocationView.timezone as required nullable fields, but the merged OpenAPI contract marks both optional. Svelte diagnostics also found an untyped click event in LocationGroup.svelte. I will normalize omitted optional fields to null at the API boundary and type the event as MouseEvent, then rerun the web check and requested test gate.

Post-merge `bun run check` finding: `apps/web/src/lib/location/location.svelte.ts` treated `LocationView.position` and `LocationView.timezone` as required nullable fields, but the merged OpenAPI contract marks both optional. Svelte diagnostics also found an untyped click event in `LocationGroup.svelte`. I will normalize omitted optional fields to `null` at the API boundary and type the event as `MouseEvent`, then rerun the web check and requested test gate.
Author
Owner

Requested apps/web bun run test result: 125 test files passed and 1 failed (805 tests passed, 1 failed). The failure is src/lib/components/analytics/RangeBar.svelte.test.ts > turning pages constructs no new Intl.DateTimeFormat: expected 0 constructions, received 302. This is outside the Location files and the expectation remains unchanged as required. I am recording it as a known gap while completing the Location/API checks.

Requested `apps/web bun run test` result: 125 test files passed and 1 failed (805 tests passed, 1 failed). The failure is `src/lib/components/analytics/RangeBar.svelte.test.ts > turning pages constructs no new Intl.DateTimeFormat`: expected 0 constructions, received 302. This is outside the Location files and the expectation remains unchanged as required. I am recording it as a known gap while completing the Location/API checks.
Author
Owner

Location adversarial probe evidence: the Location API segment passed, including malformed/oversized input, atomic fixture restore, 12 concurrent place writes (all 201), and User isolation. In the subsequent Account → Location UI flow, the server saved enabled=true with the exact browser position, but the switch's aria-checked stayed false (the probe failed at appearance_auto_scheme.mjs:356). The likely race is an in-flight initial LocationStore.load() overwriting the newer preference save. I am fixing this state race and adding a regression test; I will not alter the unrelated RangeBar test expectation.

Location adversarial probe evidence: the Location API segment passed, including malformed/oversized input, atomic fixture restore, 12 concurrent place writes (all 201), and User isolation. In the subsequent Account → Location UI flow, the server saved `enabled=true` with the exact browser position, but the switch's `aria-checked` stayed `false` (the probe failed at `appearance_auto_scheme.mjs:356`). The likely race is an in-flight initial `LocationStore.load()` overwriting the newer preference save. I am fixing this state race and adding a regression test; I will not alter the unrelated RangeBar test expectation.
Author
Owner

Finished Forgejo #391 on job/location.

Head: 449e422368998749638218ee9d670a95d06a2d21

Built: Saved places now use Home/Places.md with one ## <Name> section and id, lat, lon, and radius: 150 m fields. Edits preserve unknown lines, prose, and original line endings; deletion removes only known place fields. DESIGN §47 and Location tests describe this format. The Location client also normalizes omitted optional API fields and ignores older in-flight preference responses after a newer save.

Main files: docs/DESIGN.md, crates/calternal-location/src/lib.rs, crates/calternal-location/tests/places.rs, crates/calternal-server/src/location.rs, crates/calternal-notes-core/src/dayfile.rs, crates/plugins/notes/migrations/0018_log_place.sql, tests/adversarial/appearance_auto_scheme.mjs, apps/web/e2e/appearance-review.mjs, and the Location store, its tests, and LocationGroup.svelte under apps/web.

Gates

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

  • cargo clippy --all-targets -- -D warnings — exit 0:

        Checking calternal-collab v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/calternal-collab)
        Checking calternal-notes-core v0.1.0 (/home/kayg/Developer/calternal-wt/location/crates/calternal-notes-core)
        Checking calternal-fs v0.1.0 (/home/kayg/Developer/calternal-wt/location/crates/calternal-fs)
        Checking calternal-path v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/calternal-path)
        Checking calternal-plugin-notes v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/plugins/notes)
        Checking calternal-embed v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/calternal-embed)
        Checking calternal-dav v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/calternal-dav)
        Checking calternal-location v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/calternal-location)
        Checking calternal-tags v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/calternal-tags)
        Checking calternal-plugin v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/calternal-plugin)
        Checking calternal-db v0.1.0 (/home/kayg/Developer/calternal-wt/location/crates/calternal-db)
        Checking calternal-api v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/calternal-api)
        Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 51s
    
  • cargo test -p calternal-location -p calternal-server -p calternal-notes-core — exit 0. Verbatim suite summaries:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 108m 13s
    test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.62s
    test result: ok. 501 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.24s
    test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.40s
    test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s
    test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.60s
    test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
    test result: ok. 86 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 18.96s
    
  • apps/web bun run check — exit 0 after the Location fixes:

    $ node scripts/check-type-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
    Text sizes use shared role tokens.
    Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/location/apps/web
    Getting Svelte diagnostics...
    
    svelte-check found 0 errors and 0 warnings
    
  • apps/web bun run test — 125 test files passed; one unrelated Analytics test failed:

    Test Files  1 failed | 125 passed (126)
    Tests  1 failed | 805 passed (806)
    AssertionError: expected 302 to be +0 // Object.is equality
    

    Failure: src/lib/components/analytics/RangeBar.svelte.test.ts > turning pages constructs no new Intl.DateTimeFormat. Its existing expectation was not changed. After the final Location race fix, the focused Location suite passed: Test Files 1 passed (1) and Tests 4 passed (4).

  • packages/api-client/check-generated.sh — exit 0 when invoked with Bash (the script is not executable in the worktree):

        Finished `dev` profile [unoptimized + debuginfo] target(s) in 11m 15s
        Running `/mnt/hdd/targets/jobs/location/debug/calternal-server openapi`
    $ bunx --package openapi-typescript@7.13.0 openapi-typescript ../../contracts/openapi.json -o src/generated.ts
    Resolving dependencies
    Resolved, downloaded and extracted [23]
    Saved lockfile
    ✨ openapi-typescript 7.13.0
    🚀 ../../contracts/openapi.json → src/generated.ts [2.2s]
    

Adversarial probe: The Location API segment passed malformed and oversized payloads, Unicode places, exact coordinates, 12 concurrent writes, cross-User isolation, and oversized-file fixture restoration. The full probe then found a client race: the server saved Location as enabled, but an earlier load left the Settings switch off. I fixed it with a preference revision guard and regression test. The focused Location suite passes after that fix; I did not repeat the one time-boxed probe. The generated screenshot remains under ignored artifacts/ and is not committed.

Decisions: calternal-notes-core Markdown serializers normalize some source formatting, so the Saved place file uses a small byte-span parser to retain unknown text and line endings. No Places.json migration is needed because nothing is deployed. The merged dev branch already uses migration numbers 16 and 17, so the Saved place projection migration uses 18. Optional Location API fields become null in the client store to keep its existing complete local type.

dev was merged into this branch once as required. This job was not merged into dev and was not pushed. cargo clean removed 14,566 files (7.5 GiB), and the web build output was deleted. The worktree is clean.

Finished Forgejo #391 on `job/location`. **Head:** `449e422368998749638218ee9d670a95d06a2d21` **Built:** Saved places now use `Home/Places.md` with one `## <Name>` section and `id`, `lat`, `lon`, and `radius: 150 m` fields. Edits preserve unknown lines, prose, and original line endings; deletion removes only known place fields. DESIGN §47 and Location tests describe this format. The Location client also normalizes omitted optional API fields and ignores older in-flight preference responses after a newer save. **Main files:** `docs/DESIGN.md`, `crates/calternal-location/src/lib.rs`, `crates/calternal-location/tests/places.rs`, `crates/calternal-server/src/location.rs`, `crates/calternal-notes-core/src/dayfile.rs`, `crates/plugins/notes/migrations/0018_log_place.sql`, `tests/adversarial/appearance_auto_scheme.mjs`, `apps/web/e2e/appearance-review.mjs`, and the Location store, its tests, and `LocationGroup.svelte` under `apps/web`. **Gates** - `cargo fmt --check` — exit 0, no output. - `cargo clippy --all-targets -- -D warnings` — exit 0: ```text Checking calternal-collab v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/calternal-collab) Checking calternal-notes-core v0.1.0 (/home/kayg/Developer/calternal-wt/location/crates/calternal-notes-core) Checking calternal-fs v0.1.0 (/home/kayg/Developer/calternal-wt/location/crates/calternal-fs) Checking calternal-path v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/calternal-path) Checking calternal-plugin-notes v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/plugins/notes) Checking calternal-embed v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/calternal-embed) Checking calternal-dav v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/calternal-dav) Checking calternal-location v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/calternal-location) Checking calternal-tags v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/calternal-tags) Checking calternal-plugin v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/calternal-plugin) Checking calternal-db v0.1.0 (/home/kayg/Developer/calternal-wt/location/crates/calternal-db) Checking calternal-api v0.0.1 (/home/kayg/Developer/calternal-wt/location/crates/calternal-api) Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 51s ``` - `cargo test -p calternal-location -p calternal-server -p calternal-notes-core` — exit 0. Verbatim suite summaries: ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 108m 13s test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.62s test result: ok. 501 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.24s test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.40s test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.60s test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s test result: ok. 86 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 18.96s ``` - `apps/web bun run check` — exit 0 after the Location fixes: ```text $ node scripts/check-type-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json Text sizes use shared role tokens. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/location/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` - `apps/web bun run test` — 125 test files passed; one unrelated Analytics test failed: ```text Test Files 1 failed | 125 passed (126) Tests 1 failed | 805 passed (806) AssertionError: expected 302 to be +0 // Object.is equality ``` Failure: `src/lib/components/analytics/RangeBar.svelte.test.ts > turning pages constructs no new Intl.DateTimeFormat`. Its existing expectation was not changed. After the final Location race fix, the focused Location suite passed: `Test Files 1 passed (1)` and `Tests 4 passed (4)`. - `packages/api-client/check-generated.sh` — exit 0 when invoked with Bash (the script is not executable in the worktree): ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 11m 15s Running `/mnt/hdd/targets/jobs/location/debug/calternal-server openapi` $ bunx --package openapi-typescript@7.13.0 openapi-typescript ../../contracts/openapi.json -o src/generated.ts Resolving dependencies Resolved, downloaded and extracted [23] Saved lockfile ✨ openapi-typescript 7.13.0 🚀 ../../contracts/openapi.json → src/generated.ts [2.2s] ``` **Adversarial probe:** The Location API segment passed malformed and oversized payloads, Unicode places, exact coordinates, 12 concurrent writes, cross-User isolation, and oversized-file fixture restoration. The full probe then found a client race: the server saved Location as enabled, but an earlier load left the Settings switch off. I fixed it with a preference revision guard and regression test. The focused Location suite passes after that fix; I did not repeat the one time-boxed probe. The generated screenshot remains under ignored `artifacts/` and is not committed. **Decisions:** `calternal-notes-core` Markdown serializers normalize some source formatting, so the Saved place file uses a small byte-span parser to retain unknown text and line endings. No `Places.json` migration is needed because nothing is deployed. The merged `dev` branch already uses migration numbers 16 and 17, so the Saved place projection migration uses 18. Optional Location API fields become `null` in the client store to keep its existing complete local type. `dev` was merged into this branch once as required. This job was not merged into `dev` and was not pushed. `cargo clean` removed 14,566 files (7.5 GiB), and the web build output was deleted. The worktree is clean.
Author
Owner

Starting resumed round 3 on job/location, based at 449e422368998749638218ee9d670a95d06a2d21; current dev is 02be0946d2a4908cdf323f1e9a6ed643b455795e. Worktree was clean. I am merging dev once as requested, then will resolve the Notes migration number and the listed conflicts while preserving both sides' behavior.

Starting resumed round 3 on `job/location`, based at `449e422368998749638218ee9d670a95d06a2d21`; current `dev` is `02be0946d2a4908cdf323f1e9a6ed643b455795e`. Worktree was clean. I am merging `dev` once as requested, then will resolve the Notes migration number and the listed conflicts while preserving both sides' behavior.
Author
Owner

Rust gate finding during this merge: cargo clippy -p calternal-location --all-targets -- -D warnings reported byte_char_slices at crates/calternal-fs/src/root.rs:379 in the per-User Index readiness marker added on dev (#400, a89649008). I changed [b'1'] to Clippy's equivalent *b"1" form; this does not change behavior and lets the requested per-crate gates continue.

Rust gate finding during this merge: `cargo clippy -p calternal-location --all-targets -- -D warnings` reported `byte_char_slices` at `crates/calternal-fs/src/root.rs:379` in the per-User Index readiness marker added on `dev` (#400, `a89649008`). I changed `[b'1']` to Clippy's equivalent `*b"1"` form; this does not change behavior and lets the requested per-crate gates continue.
Author
Owner

Round 3 status — stopped at the owner’s four-hour timebox

Head: 7bd2defd8e0376cb72ef334162de528b142d47bc

Built and committed

  • Saved-place identity and name are stored on each Log projection in Notes migration 20, after Reminders 18 and area calendars 19. The migration comment records why historical Logs retain the captured place name.
  • Updated the Location consent and precision copy to plain words.
  • Added an e2e assertion that the phone sheet title is “Location”.
  • Preserved full tag paths in a Log’s accessible name while compact block text uses tag leaves.
  • Clippy-required equivalent byte comparison fix in calternal-fs.
  • Commits: 4b1375a59 (dev merge and resolved Location changes), 7bd2defd8 (calendar accessible-name fix).

Gate output recorded

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

cargo clippy -p calternal-location --all-targets -- -D warnings: passed; Finished dev profile [unoptimized + debuginfo] target(s) in 1m 48s.

cargo test -p calternal-location:

running 11 tests
test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.63s

cargo clippy -p calternal-plugin-notes --all-targets -- -D warnings: passed; Finished dev profile [unoptimized + debuginfo] target(s) in 42m 23s.

cargo test -p calternal-plugin-notes:

running 124 tests
test result: ok. 124 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 79.17s

cargo clippy -p calternal-server --all-targets -- -D warnings: passed; Finished dev profile [unoptimized + debuginfo] target(s) in 45.65s.

cargo test -p calternal-server:

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

bun run check passed:

$ node scripts/check-type-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
Text sizes use shared role tokens.
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/location/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

The full bun run test run before the tag-name fix reported:

Test Files  2 failed | 125 passed (127)
Tests  2 failed | 815 passed (817)

The TimeGrid tag-name failure was fixed; its focused rerun passed:

Test Files  1 passed (1)
Tests  8 passed (8)

The Analytics RangeBar assertion still fails in isolation on this job branch:

AssertionError: expected 302 to be +0 // Object.is equality
- 0
+ 302

On the current dev worktree, the same focused assertion passed:

Test Files  1 passed (1)
Tests  1 passed | 6 skipped (7)

The RangeBar source and test are identical to current dev. I did not alter the expectation. The full web suite was not rerun after fixing the TimeGrid issue.

Remaining work / evidence gaps

  • Screenshots were not captured; artifacts/location/ does not have the requested 390/820/1440 light/dark matrix.
  • The Location adversarial probe was not rerun after the race fix.
  • The current local dev ref is 369ab6a2f; this branch’s one merge commit has 02be0946d as its dev parent. I did not merge again.
  • The web build and bun run check passed before the final one-line accessible-name adjustment; the current full web suite and production screenshots remain unverified.

Decisions

  • Assigned the Saved-place projection migration number 20 to follow the merged Notes migrations.
  • Kept full tag paths for assistive technology and tag leaves for compact visual labels, as required by the existing calendar behavior.
  • The phone sheet title follows the visible Account → Location section.

No push, deploy, or issue closure was performed.

## Round 3 status — stopped at the owner’s four-hour timebox Head: `7bd2defd8e0376cb72ef334162de528b142d47bc` ### Built and committed - Saved-place identity and name are stored on each Log projection in Notes migration 20, after Reminders 18 and area calendars 19. The migration comment records why historical Logs retain the captured place name. - Updated the Location consent and precision copy to plain words. - Added an e2e assertion that the phone sheet title is “Location”. - Preserved full tag paths in a Log’s accessible name while compact block text uses tag leaves. - Clippy-required equivalent byte comparison fix in calternal-fs. - Commits: `4b1375a59` (dev merge and resolved Location changes), `7bd2defd8` (calendar accessible-name fix). ### Gate output recorded `cargo fmt --check`: exit 0, no output. `cargo clippy -p calternal-location --all-targets -- -D warnings`: passed; `Finished dev profile [unoptimized + debuginfo] target(s) in 1m 48s`. `cargo test -p calternal-location`: ``` running 11 tests test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.63s ``` `cargo clippy -p calternal-plugin-notes --all-targets -- -D warnings`: passed; `Finished dev profile [unoptimized + debuginfo] target(s) in 42m 23s`. `cargo test -p calternal-plugin-notes`: ``` running 124 tests test result: ok. 124 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 79.17s ``` `cargo clippy -p calternal-server --all-targets -- -D warnings`: passed; `Finished dev profile [unoptimized + debuginfo] target(s) in 45.65s`. `cargo test -p calternal-server`: ``` test result: ok. 87 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 12.43s ``` `bun run check` passed: ``` $ node scripts/check-type-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json Text sizes use shared role tokens. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/location/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` The full `bun run test` run before the tag-name fix reported: ``` Test Files 2 failed | 125 passed (127) Tests 2 failed | 815 passed (817) ``` The TimeGrid tag-name failure was fixed; its focused rerun passed: ``` Test Files 1 passed (1) Tests 8 passed (8) ``` The Analytics RangeBar assertion still fails in isolation on this job branch: ``` AssertionError: expected 302 to be +0 // Object.is equality - 0 + 302 ``` On the current `dev` worktree, the same focused assertion passed: ``` Test Files 1 passed (1) Tests 1 passed | 6 skipped (7) ``` The RangeBar source and test are identical to current dev. I did not alter the expectation. The full web suite was not rerun after fixing the TimeGrid issue. ### Remaining work / evidence gaps - Screenshots were not captured; `artifacts/location/` does not have the requested 390/820/1440 light/dark matrix. - The Location adversarial probe was not rerun after the race fix. - The current local `dev` ref is `369ab6a2f`; this branch’s one merge commit has `02be0946d` as its dev parent. I did not merge again. - The web build and `bun run check` passed before the final one-line accessible-name adjustment; the current full web suite and production screenshots remain unverified. ### Decisions - Assigned the Saved-place projection migration number 20 to follow the merged Notes migrations. - Kept full tag paths for assistive technology and tag leaves for compact visual labels, as required by the existing calendar behavior. - The phone sheet title follows the visible Account → Location section. No push, deploy, or issue closure was performed.
Author
Owner

Report supplement: files edited during this round:

  • crates/plugins/notes/migrations/0020_log_place.sql (renamed from 0018)
  • crates/plugins/notes/src/store.rs
  • crates/plugins/notes/src/lib.rs
  • crates/calternal-server/src/wire.rs
  • crates/calternal-fs/src/root.rs
  • packages/ui/src/components/calendar/GridColumn.svelte
  • apps/web/src/routes/settings/account/LocationGroup.svelte
  • apps/web/e2e/appearance-review.mjs

Cleanup output: Removed 15626 files, 7.0GiB total from cargo clean; apps/web/build was removed.

Report supplement: files edited during this round: - `crates/plugins/notes/migrations/0020_log_place.sql` (renamed from 0018) - `crates/plugins/notes/src/store.rs` - `crates/plugins/notes/src/lib.rs` - `crates/calternal-server/src/wire.rs` - `crates/calternal-fs/src/root.rs` - `packages/ui/src/components/calendar/GridColumn.svelte` - `apps/web/src/routes/settings/account/LocationGroup.svelte` - `apps/web/e2e/appearance-review.mjs` Cleanup output: `Removed 15626 files, 7.0GiB total` from `cargo clean`; `apps/web/build` was removed.
Author
Owner

Starting resumed round 4 on branch job/location. Rebuilding from origin/dev at 369ab6a2f9 (old branch head 7bd2defd8e). The old branch includes merge 02be0946 (#400); I will replay only the #391 first-parent commits and retain the accepted Places.md, plain wording, migration 20, and Location sheet title.

Starting resumed round 4 on branch job/location. Rebuilding from origin/dev at 369ab6a2f9fc673e3564b94857fbecfeb04df404 (old branch head 7bd2defd8e0376cb72ef334162de528b142d47bc). The old branch includes merge 02be0946 (#400); I will replay only the #391 first-parent commits and retain the accepted Places.md, plain wording, migration 20, and Location sheet title.
Author
Owner

Finding during the branch rebuild: origin/dev added App Surfaces wiring and Daily note navigation migrations 16–19. The Location API/Log replay conflicted in wire.rs, notes-core exports, and the Notes migration list. I kept both API routes and exports, retained migrations 16–19, and assigned the Saved-place projection migration 20 as required.

Finding during the branch rebuild: origin/dev added App Surfaces wiring and Daily note navigation migrations 16–19. The Location API/Log replay conflicted in wire.rs, notes-core exports, and the Notes migration list. I kept both API routes and exports, retained migrations 16–19, and assigned the Saved-place projection migration 20 as required.
Author
Owner

Finding after the branch rebuild: bun run check reports two missing LocationGroup imports because origin/dev moved AccountRow and SettingsGroup out of settings/parts. I am locating and reusing the current Settings components before rerunning the check.

Finding after the branch rebuild: bun run check reports two missing LocationGroup imports because origin/dev moved AccountRow and SettingsGroup out of settings/parts. I am locating and reusing the current Settings components before rerunning the check.
Author
Owner

Resolved: LocationGroup now uses the current SettingsCard/AccountList/SettingsRow components. The shared-components guard showed the stale wrappers before the edit, then passed after it (2 tests); bun run check now reports 0 errors and 0 warnings. The Location copy and phone sheet title assertion match the accepted text.

Resolved: LocationGroup now uses the current SettingsCard/AccountList/SettingsRow components. The shared-components guard showed the stale wrappers before the edit, then passed after it (2 tests); bun run check now reports 0 errors and 0 warnings. The Location copy and phone sheet title assertion match the accepted text.
Author
Owner

Finding: cargo fmt --check reported one formatting difference in the merged Notes core exports. I am applying rustfmt's line wrap; no behavior change is involved.

Finding: cargo fmt --check reported one formatting difference in the merged Notes core exports. I am applying rustfmt's line wrap; no behavior change is involved.
Author
Owner

Finding: the existing generic adversarial checks still expected Appearance to store and return coordinates. #391 moved coordinates to /api/v1/location, so I updated those checks to expect mode-only Appearance data and reject the retired field; the dedicated Location probe covers coordinate bounds.

Finding: the existing generic adversarial checks still expected Appearance to store and return coordinates. #391 moved coordinates to /api/v1/location, so I updated those checks to expect mode-only Appearance data and reject the retired field; the dedicated Location probe covers coordinate bounds.
Author
Owner

The adversarial suite still treated Location coordinates as Appearance fields. I updated its valid, hostile, and concurrency checks to assert that Appearance stores only the mode; Python AST parsing passed, commit 93ca20a2.

The adversarial suite still treated Location coordinates as Appearance fields. I updated its valid, hostile, and concurrency checks to assert that Appearance stores only the mode; Python AST parsing passed, commit 93ca20a2.
Author
Owner

Resume round 4 started from job/location at d0a15308af (origin/dev: 369ab6a2f9). I verified 02be0946 is not reachable from this branch or origin/dev; I will rebuild on current origin/dev and replay only the #391 commits before running the remaining gates.

Resume round 4 started from job/location at d0a15308afcc1c0e842a541a6a50834fa284b9cf (origin/dev: 369ab6a2f9fc673e3564b94857fbecfeb04df404). I verified 02be0946 is not reachable from this branch or origin/dev; I will rebuild on current origin/dev and replay only the #391 commits before running the remaining gates.
Author
Owner

Finding on reconstructed origin/dev: the full web suite reports 302 Intl.DateTimeFormat constructions while paging RangePicker. The #391 change made formatDateRange resolve systemTimeZone() for each visible week cell; systemTimeZone constructs a formatter directly. I changed the no-override path to compare Installation-local years directly and kept explicit User-zone comparisons cached. I am verifying the existing RangeBar regression assertion now; no test expectation changed.

Finding on reconstructed origin/dev: the full web suite reports 302 Intl.DateTimeFormat constructions while paging RangePicker. The #391 change made formatDateRange resolve systemTimeZone() for each visible week cell; systemTimeZone constructs a formatter directly. I changed the no-override path to compare Installation-local years directly and kept explicit User-zone comparisons cached. I am verifying the existing RangeBar regression assertion now; no test expectation changed.
Author
Owner

Starting resume round 4 on branch job/location. The worktree was clean at head 3d10a0203d. I fetched origin/dev at 55a2f90feb; I am rebuilding from that base and will replay only the #391 commits before running the requested gates and probes.

Starting resume round 4 on branch job/location. The worktree was clean at head 3d10a0203d7106dfa984f17841660d768ec44f33. I fetched origin/dev at 55a2f90feb8a52d91f8bbc1347889b509af02260; I am rebuilding from that base and will replay only the #391 commits before running the requested gates and probes.
Author
Owner

Resumed #391 on job/location. Fresh base: origin/dev at dfb5964a2fcf13dc8b9a50a319eee09bc386f322. The original branch had 27 ahead commits; all were #391 changes, and fetched refs showed 02be0946 was not an ancestor of the checkout. Replaying onto current origin/dev hit a conflict where the Location Log fields overlap the newer #468 batch Log API. I am keeping both behaviors and will verify the combined API before final gates.

Resumed #391 on `job/location`. Fresh base: `origin/dev` at `dfb5964a2fcf13dc8b9a50a319eee09bc386f322`. The original branch had 27 ahead commits; all were #391 changes, and fetched refs showed `02be0946` was not an ancestor of the checkout. Replaying onto current `origin/dev` hit a conflict where the Location Log fields overlap the newer #468 batch Log API. I am keeping both behaviors and will verify the combined API before final gates.
Author
Owner

Location #391 — round 4 final report

Built

  • Added the User-scoped Location API and Saved places storage in Home Places.md, with exact coordinates, stable place IDs, bounded parsing, and filesystem writes through the server-owned root.
  • Added Account → Location consent and Saved places UI, deep links, and the mobile sheet title Location.
  • Added Saved place name snapshots to Notes Logs and migration 0020_log_place.sql. Integrated Location capture with the current log/batch API.
  • Updated the production screenshot helper to wait for server-owned Appearance state after navigation. It captures only the six requested Location states in review-only mode.

Main files: crates/calternal-server/src/location.rs, crates/calternal-location/src/lib.rs, crates/calternal-location/tests/places.rs, crates/plugins/notes/migrations/0020_log_place.sql, crates/plugins/notes/src/lib.rs, crates/calternal-notes-core/src/dayfile.rs, apps/web/src/lib/location/location.svelte.ts, apps/web/src/routes/settings/account/LocationGroup.svelte, apps/web/e2e/appearance-review.mjs, and tests/adversarial/appearance_auto_scheme.mjs.

Branch

Head: 30294e17bff42d35a96945be1e124842d1ad203f (test(location): wait for settings state before review). git log origin/dev..HEAD lists only the 27 #391 commits; it has no #400 merge commit. The clean rebuild started at dfb5964. The final fetch found origin/dev had advanced to 6c87f5ff9442cd658572139bc536d018fd5222a4 during this long run. Notes migrations on that fetched origin/dev still end at 0019, so 0020 remains the next free number. Rebase onto the newer origin/dev and rerun gates before merge; I did not add a merge commit because the branch must contain only #391 commits.

Gate output

cargo fmt --check exited 0 with no output.

Clippy passed for calternal-location, calternal-plugin-notes, calternal-notes-core, calternal-plugin-calendar, and calternal-server:

Finished dev profile [unoptimized + debuginfo] target(s) in 1m 03s
Finished dev profile [unoptimized + debuginfo] target(s) in 4m 17s
Finished dev profile [unoptimized + debuginfo] target(s) in 51.23s
Finished dev profile [unoptimized + debuginfo] target(s) in 28m 20s
Finished dev profile [unoptimized + debuginfo] target(s) in 20m 37s

Crate tests passed:

test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.77s
 test result: ok. 130 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 182.86s
 test result: ok. 506 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.47s
 test result: ok. 51 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 9.26s
 test result: ok. 90 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 43.63s

cargo build -p calternal-server passed:

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

bun run check passed:

$ node scripts/check-type-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
Text sizes use shared role tokens.
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/location/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

Full bun run test result:

Test Files  1 failed | 136 passed (137)
Tests  1 failed | 884 passed (885)

The only failure was the slow timezone test keeps dates and Log instants in the selected zone when the browser zone differs; its focused run passed (1 passed | 20 skipped). The Analytics RangeBar test passed.

The Location adversarial probe passed its malformed/oversized payload, exact coordinate, Unicode place, concurrency, fixture restore, and cross-User checks. Its UI consent assertion now waits for API/UI agreement across two rendered frames; the final run passed and captured the Auto review screenshots.

Location API probe: malformed and oversized payloads and file, exact coordinates, Unicode place, concurrent writes, fixture restore, and cross-User isolation passed
Appearance Auto/Fonts/Background burst: 48 concurrent writes, all 200
PASS Auto appearance adversarial and production captures: /home/kayg/Developer/calternal-wt/location/artifacts/auto-scheme
PASS appearance review captures: 6 screenshots in /home/kayg/Developer/calternal-wt/location/artifacts/location

The six files are location-light-{1440,820,390}.png and location-dark-{1440,820,390}.png under artifacts/location/. They remain untracked and were not committed. scripts/fj issue has no attachment command, so the images are available in the worktree rather than attached to this comment.

Cleanup output:

Removed 18693 files, 10.8GiB total

Known gaps

  • Rebase the 27 #391 commits onto fetched origin/dev 6c87f5ff and rerun required gates. The current branch is still based on dfb5964 because origin/dev advanced during the long gate run and the four-hour job limit was reached.
  • The full web suite had the one SLOW timezone timeout above; the focused rerun passed. RangeBar passed.
  • Screenshot PNGs are local in the worktree and are not attached to Forgejo.

Decisions not specified by DESIGN

  • Use one timezone lookup and one browser-position sample for each log/batch request, then apply that sample to the batch. This keeps the batched request consistent and avoids repeated lookups or prompts.
  • Keep Places.md lossless for unknown prose and line endings, and do not add migration from the earlier unshipped Places.json format.
  • Keep migration 20 for the Notes Log place snapshot; fetched origin/dev uses 18 and 19 and has no 20.
## Location #391 — round 4 final report ### Built - Added the User-scoped Location API and Saved places storage in Home `Places.md`, with exact coordinates, stable place IDs, bounded parsing, and filesystem writes through the server-owned root. - Added Account → Location consent and Saved places UI, deep links, and the mobile sheet title `Location`. - Added Saved place name snapshots to Notes Logs and migration `0020_log_place.sql`. Integrated Location capture with the current `log/batch` API. - Updated the production screenshot helper to wait for server-owned Appearance state after navigation. It captures only the six requested Location states in review-only mode. Main files: `crates/calternal-server/src/location.rs`, `crates/calternal-location/src/lib.rs`, `crates/calternal-location/tests/places.rs`, `crates/plugins/notes/migrations/0020_log_place.sql`, `crates/plugins/notes/src/lib.rs`, `crates/calternal-notes-core/src/dayfile.rs`, `apps/web/src/lib/location/location.svelte.ts`, `apps/web/src/routes/settings/account/LocationGroup.svelte`, `apps/web/e2e/appearance-review.mjs`, and `tests/adversarial/appearance_auto_scheme.mjs`. ### Branch Head: `30294e17bff42d35a96945be1e124842d1ad203f` (`test(location): wait for settings state before review`). `git log origin/dev..HEAD` lists only the 27 #391 commits; it has no #400 merge commit. The clean rebuild started at `dfb5964`. The final fetch found `origin/dev` had advanced to `6c87f5ff9442cd658572139bc536d018fd5222a4` during this long run. Notes migrations on that fetched `origin/dev` still end at 0019, so 0020 remains the next free number. Rebase onto the newer `origin/dev` and rerun gates before merge; I did not add a merge commit because the branch must contain only #391 commits. ### Gate output `cargo fmt --check` exited 0 with no output. Clippy passed for `calternal-location`, `calternal-plugin-notes`, `calternal-notes-core`, `calternal-plugin-calendar`, and `calternal-server`: ```text Finished dev profile [unoptimized + debuginfo] target(s) in 1m 03s Finished dev profile [unoptimized + debuginfo] target(s) in 4m 17s Finished dev profile [unoptimized + debuginfo] target(s) in 51.23s Finished dev profile [unoptimized + debuginfo] target(s) in 28m 20s Finished dev profile [unoptimized + debuginfo] target(s) in 20m 37s ``` Crate tests passed: ```text test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.77s test result: ok. 130 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 182.86s test result: ok. 506 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.47s test result: ok. 51 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 9.26s test result: ok. 90 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 43.63s ``` `cargo build -p calternal-server` passed: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 32m 04s ``` `bun run check` passed: ```text $ node scripts/check-type-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json Text sizes use shared role tokens. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/location/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` Full `bun run test` result: ```text Test Files 1 failed | 136 passed (137) Tests 1 failed | 884 passed (885) ``` The only failure was the slow timezone test `keeps dates and Log instants in the selected zone when the browser zone differs`; its focused run passed (`1 passed | 20 skipped`). The Analytics RangeBar test passed. The Location adversarial probe passed its malformed/oversized payload, exact coordinate, Unicode place, concurrency, fixture restore, and cross-User checks. Its UI consent assertion now waits for API/UI agreement across two rendered frames; the final run passed and captured the Auto review screenshots. ```text Location API probe: malformed and oversized payloads and file, exact coordinates, Unicode place, concurrent writes, fixture restore, and cross-User isolation passed Appearance Auto/Fonts/Background burst: 48 concurrent writes, all 200 PASS Auto appearance adversarial and production captures: /home/kayg/Developer/calternal-wt/location/artifacts/auto-scheme PASS appearance review captures: 6 screenshots in /home/kayg/Developer/calternal-wt/location/artifacts/location ``` The six files are `location-light-{1440,820,390}.png` and `location-dark-{1440,820,390}.png` under `artifacts/location/`. They remain untracked and were not committed. `scripts/fj issue` has no attachment command, so the images are available in the worktree rather than attached to this comment. Cleanup output: ```text Removed 18693 files, 10.8GiB total ``` ### Known gaps - Rebase the 27 #391 commits onto fetched `origin/dev` `6c87f5ff` and rerun required gates. The current branch is still based on `dfb5964` because `origin/dev` advanced during the long gate run and the four-hour job limit was reached. - The full web suite had the one SLOW timezone timeout above; the focused rerun passed. RangeBar passed. - Screenshot PNGs are local in the worktree and are not attached to Forgejo. ### Decisions not specified by DESIGN - Use one timezone lookup and one browser-position sample for each `log/batch` request, then apply that sample to the batch. This keeps the batched request consistent and avoids repeated lookups or prompts. - Keep `Places.md` lossless for unknown prose and line endings, and do not add migration from the earlier unshipped `Places.json` format. - Keep migration 20 for the Notes Log place snapshot; fetched `origin/dev` uses 18 and 19 and has no 20.
Author
Owner

Started merge-round-2 on branch job/merge-round-2, base 6c87f5ff9442cd658572139bc536d018fd5222a4 (origin/dev). Integrating the five requested branches in order, regenerating contracts, then checking migrations and running per-crate and web gates. No push or deployment.

Started merge-round-2 on branch `job/merge-round-2`, base `6c87f5ff9442cd658572139bc536d018fd5222a4` (`origin/dev`). Integrating the five requested branches in order, regenerating contracts, then checking migrations and running per-crate and web gates. No push or deployment.
Author
Owner

All five branches are committed on job/merge-round-2. Final git fetch origin and git merge origin/dev returned Already up to date. Migration numbers are unique in every migrations folder: Notes adds 0020 above dev 0019; Calendar adds 0004 above dev 0003.

Conflict resolution preserves Maintenance query redirects and saved-place UUID/fragment links; authenticated Location routing and public calendar feed routing; current Mail reader regression cases and the full-history performance fixture; canonical Daily note lookup plus filename search restricted to the selected User Home. Contracts are being regenerated, not hand-merged.

First web check exposed shared-token violations in LocationGroup: three literal line heights and one literal radius. Replaced these with existing leading and radius tokens; check rerun pending.

Safemode prevents execution of hostile-input, race-exploitation, and request-storm probes. These will be listed as unrun gates; normal integration and offline classification checks remain in scope.

All five branches are committed on `job/merge-round-2`. Final `git fetch origin` and `git merge origin/dev` returned `Already up to date.` Migration numbers are unique in every migrations folder: Notes adds 0020 above dev 0019; Calendar adds 0004 above dev 0003. Conflict resolution preserves Maintenance query redirects and saved-place UUID/fragment links; authenticated Location routing and public calendar feed routing; current Mail reader regression cases and the full-history performance fixture; canonical Daily note lookup plus filename search restricted to the selected User Home. Contracts are being regenerated, not hand-merged. First web check exposed shared-token violations in LocationGroup: three literal line heights and one literal radius. Replaced these with existing leading and radius tokens; check rerun pending. Safemode prevents execution of hostile-input, race-exploitation, and request-storm probes. These will be listed as unrun gates; normal integration and offline classification checks remain in scope.
Author
Owner

Offline classification initially failed with RuntimeError: OpenAPI operation has no authorization policy: GET /api/v1/location (location_get). Added explicit policies for the eight Location operations and caller-Home saved-place IDs; no prefix-wide allowance. Added one offline policy regression; existing assertions were not changed. Commit a4c5cbd82.

Fresh output:

Cross-User classification gate: 316 operations classified
....
----------------------------------------------------------------------
Ran 4 tests in 0.779s

OK
Offline classification initially failed with `RuntimeError: OpenAPI operation has no authorization policy: GET /api/v1/location (location_get)`. Added explicit policies for the eight Location operations and caller-Home saved-place IDs; no prefix-wide allowance. Added one offline policy regression; existing assertions were not changed. Commit `a4c5cbd82`. Fresh output: ```text Cross-User classification gate: 316 operations classified .... ---------------------------------------------------------------------- Ran 4 tests in 0.779s OK ```
Author
Owner

Location token fix is committed as 8cd11376f. Shared-token guard passes; Settings registry: 8 passed. Production bun run build returned exit 0. bun run test first run: 897 passed, 2 failed; both failures were Test timed out in 5000ms. The isolated one-worker reruns passed: Calendar zones 21 passed; KeyboardShortcutsCard 1 passed. Both first and rerun output will be in the final report.

Svelte check currently reports the expected stale pre-regeneration Calendar fields/routes. Contract generation is compiling the final merged server before regenerating the client. calternal-cli clippy has passed. Offline benchmark helpers (12), DAV probe contract helpers (7), and Appearance probe contract helpers (4) pass. These offline helper tests are not the live adversarial round.

Location token fix is committed as `8cd11376f`. Shared-token guard passes; Settings registry: 8 passed. Production `bun run build` returned exit 0. `bun run test` first run: 897 passed, 2 failed; both failures were `Test timed out in 5000ms.` The isolated one-worker reruns passed: Calendar zones 21 passed; KeyboardShortcutsCard 1 passed. Both first and rerun output will be in the final report. Svelte check currently reports the expected stale pre-regeneration Calendar fields/routes. Contract generation is compiling the final merged server before regenerating the client. `calternal-cli` clippy has passed. Offline benchmark helpers (12), DAV probe contract helpers (7), and Appearance probe contract helpers (4) pass. These offline helper tests are not the live adversarial round.
Author
Owner

Merged server generation completed:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 61m 42s
     Running `/mnt/hdd/targets/jobs/merge-round-2/debug/calternal-server openapi`

The OpenAPI contract and TypeScript client were regenerated from this binary; all 328 operation IDs are unique. Offline cross-User classification now covers 328 operations and all four guard tests pass.

Reviewed and regenerated the parity inventory. Newly visible static adapter gaps: eight Location operations (CLI/MCP/WebMCP), eleven calendar feed/subscription operations (MCP), and the existing batch Log route (MCP/WebMCP). The Location, feeds and subscriptions Settings groups are added to the form inventory. Decision: retain the imported branch adapter scope and record these gaps in the source-backed inventory. This merge does not add adapter features.

Parity matrix: 206 web API actions, 113 shortcuts, 2 static commands, 131 menu actions, 33 settings groups, 188 actions with adapter gaps

Normal production browser checks are now running sequentially. Rust per-crate gates continue.

Merged server generation completed: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 61m 42s Running `/mnt/hdd/targets/jobs/merge-round-2/debug/calternal-server openapi` ``` The OpenAPI contract and TypeScript client were regenerated from this binary; all 328 operation IDs are unique. Offline cross-User classification now covers 328 operations and all four guard tests pass. Reviewed and regenerated the parity inventory. Newly visible static adapter gaps: eight Location operations (CLI/MCP/WebMCP), eleven calendar feed/subscription operations (MCP), and the existing batch Log route (MCP/WebMCP). The Location, feeds and subscriptions Settings groups are added to the form inventory. Decision: retain the imported branch adapter scope and record these gaps in the source-backed inventory. This merge does not add adapter features. ```text Parity matrix: 206 web API actions, 113 shortcuts, 2 static commands, 131 menu actions, 33 settings groups, 188 actions with adapter gaps ``` Normal production browser checks are now running sequentially. Rust per-crate gates continue.
Author
Owner

Normal production browser proof passed: Calendar feeds and Location at 390, 820 and 1440 px in light and dark. Full matrices are attached, with representative phone and desktop PNGs. No review artifacts are committed.

merge-round-2-location-review.zip

merge-round-2-calendar-feeds-review.zip

Local one-item Photos/Home smoke: allIndexedMs 4060; serverUpMs 1101; mean RSS 350938740 bytes; peak RSS 432443392 bytes; mean CPU 25.24%; peak CPU 132.98%. The one-item run is not comparable with the larger baseline datasets.

Generated-contract check passed with no diff. Current head: 19186f8e2. Per-crate Rust gates remain in progress.

Normal production browser proof passed: Calendar feeds and Location at 390, 820 and 1440 px in light and dark. Full matrices are attached, with representative phone and desktop PNGs. No review artifacts are committed. [merge-round-2-location-review.zip](https://git.kayg.org/attachments/6078bc47-ceb1-4566-9b5e-63ef5c52b9a1) [merge-round-2-calendar-feeds-review.zip](https://git.kayg.org/attachments/03f5976a-28a3-4384-9aae-a995bac45409) Local one-item Photos/Home smoke: allIndexedMs 4060; serverUpMs 1101; mean RSS 350938740 bytes; peak RSS 432443392 bytes; mean CPU 25.24%; peak CPU 132.98%. The one-item run is not comparable with the larger baseline datasets. Generated-contract check passed with no diff. Current head: `19186f8e2`. Per-crate Rust gates remain in progress.
Author
Owner

Correction to the earlier generated-check status: its tool wrapper returned 143 after generation, so that wrapper is not a confirmed pass. I reran the same generation, unique-operation-ID and Git diff checks with the freshly built merged server binary. All commands returned exit 0 and no generated diff remains.

$ /mnt/hdd/targets/jobs/merge-round-2/debug/calternal-server openapi
exit=0
$ bun run --cwd packages/api-client generate
$ 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 [3s]
exit=0
$ git diff --exit-code -- contracts/openapi.json packages/api-client/src/generated.ts
exit=0
OpenAPI operation IDs: 328 unique

Review archives and representative PNGs are attached to #391 and #431. Current head is 19186f8e2b3f5f8d315c0819c93f30ff277ca054. CLI clippy and both test binaries passed; remaining per-crate Rust gates continue.

Correction to the earlier generated-check status: its tool wrapper returned 143 after generation, so that wrapper is not a confirmed pass. I reran the same generation, unique-operation-ID and Git diff checks with the freshly built merged server binary. All commands returned exit 0 and no generated diff remains. ```text $ /mnt/hdd/targets/jobs/merge-round-2/debug/calternal-server openapi exit=0 $ bun run --cwd packages/api-client generate $ 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 [3s] exit=0 $ git diff --exit-code -- contracts/openapi.json packages/api-client/src/generated.ts exit=0 OpenAPI operation IDs: 328 unique ``` Review archives and representative PNGs are attached to #391 and #431. Current head is `19186f8e2b3f5f8d315c0819c93f30ff277ca054`. CLI clippy and both test binaries passed; remaining per-crate Rust gates continue.
Author
Owner

Rust gates remain serial on the shared host. Completed so far: CLI, DAV, Location, and Notes core clippy/test, all exit 0. Location: 11 tests passed; DAV: 41 unit and 33 integration tests passed; Notes core: 12 tests passed. Plugin clippy is compiling dependencies. No Rust failure so far. Browser checks and the explicit generated-contract, parity and offline cross-User classification checks are complete. The live adversarial round remains unrun under this session's safety limits.

Rust gates remain serial on the shared host. Completed so far: CLI, DAV, Location, and Notes core clippy/test, all exit 0. Location: 11 tests passed; DAV: 41 unit and 33 integration tests passed; Notes core: 12 tests passed. Plugin clippy is compiling dependencies. No Rust failure so far. Browser checks and the explicit generated-contract, parity and offline cross-User classification checks are complete. The live adversarial round remains unrun under this session's safety limits.
Author
Owner

The additional full Appearance review found an imported test regression: job/location changed origin/dev's existing 16-family menu assertion to 13 families plus 3 submenu parents, although the production menu still has 16 families. Restoring origin/dev's exact expectation and retaining Location-specific checks. No production behavior change and no weakened existing dev assertion. The initial full review also observed stored Light with server System; the instrumented normal-request rerun showed ordered System migration then Light save and passed that check, then stopped at the stale menu assertion. Both logs are preserved; the final full review is pending.

The additional full Appearance review found an imported test regression: job/location changed origin/dev's existing 16-family menu assertion to 13 families plus 3 submenu parents, although the production menu still has 16 families. Restoring origin/dev's exact expectation and retaining Location-specific checks. No production behavior change and no weakened existing dev assertion. The initial full review also observed stored Light with server System; the instrumented normal-request rerun showed ordered System migration then Light save and passed that check, then stopped at the stale menu assertion. Both logs are preserved; the final full review is pending.
Author
Owner

Additional production Appearance evidence exposed stale review selectors, not a change to the 16-family contract. The menu has 16 radio families in Light, and 13 radio families plus 3 variant submenu parents in Dark. Dev's expected total remains exactly 16; the selector now counts both family representations. Existing ThemePicker component tests require Catppuccin variants in a keyboard submenu, so the review now uses that interaction and retains its Frappé assertion. Capture guard regressions: 8 passed, 0 failed (committed f57954466). The review seeds System through the real Appearance API before the first SPA navigation, so fixture setup does not leave a null-value migration unfinished. The full capture rerun is in progress. Earlier unseeded runs showed browser Light with server System; those failures remain preserved and are not a certified cold-start migration result. Calendar clippy is green; tests are compiling.

Additional production Appearance evidence exposed stale review selectors, not a change to the 16-family contract. The menu has 16 radio families in Light, and 13 radio families plus 3 variant submenu parents in Dark. Dev's expected total remains exactly 16; the selector now counts both family representations. Existing ThemePicker component tests require Catppuccin variants in a keyboard submenu, so the review now uses that interaction and retains its Frappé assertion. Capture guard regressions: 8 passed, 0 failed (committed f57954466). The review seeds System through the real Appearance API before the first SPA navigation, so fixture setup does not leave a null-value migration unfinished. The full capture rerun is in progress. Earlier unseeded runs showed browser Light with server System; those failures remain preserved and are not a certified cold-start migration result. Calendar clippy is green; tests are compiling.
Author
Owner

Head 84d4258f130ebebe748a9b3a08f03c8741d01c45. Appearance review: PASS appearance review captures: 71 screenshots in /home/kayg/Developer/calternal-wt/merge-web/artifacts/location. Notes/Photos/Log review: PASS Notes and Photos review: 18 production screenshots, 390/820/1440 px, light/dark. Combined archive (89 PNGs): https://git.kayg.org/attachments/2a0c2168-6199-4d45-9ff2-ad676518e88e . The original Calendar archive remains attached to #431. Visual quality review stays with the orchestrator. The Appearance fixes retain dev's 16-family and Frappé expectations; count submenu parents as families, use the existing keyboard submenu behavior, distinguish saved Auto/System preferences from rendered Light/Dark phases, and await API persistence outside Playwright's synchronous predicate. Guard regression tests: 8 pass, 0 fail. Notes clippy/tests and Photos clippy now pass. Remaining main Rust gates: Photos tests and server clippy/tests. Live adversarial probes remain unrun under this session's safety limits.

Head `84d4258f130ebebe748a9b3a08f03c8741d01c45`. Appearance review: `PASS appearance review captures: 71 screenshots in /home/kayg/Developer/calternal-wt/merge-web/artifacts/location`. Notes/Photos/Log review: `PASS Notes and Photos review: 18 production screenshots, 390/820/1440 px, light/dark`. Combined archive (89 PNGs): https://git.kayg.org/attachments/2a0c2168-6199-4d45-9ff2-ad676518e88e . The original Calendar archive remains attached to #431. Visual quality review stays with the orchestrator. The Appearance fixes retain dev's 16-family and Frappé expectations; count submenu parents as families, use the existing keyboard submenu behavior, distinguish saved Auto/System preferences from rendered Light/Dark phases, and await API persistence outside Playwright's synchronous predicate. Guard regression tests: 8 pass, 0 fail. Notes clippy/tests and Photos clippy now pass. Remaining main Rust gates: Photos tests and server clippy/tests. Live adversarial probes remain unrun under this session's safety limits.
Author
Owner

All five branches are committed on job/merge-round-2. Validation remains incomplete at the four-hour limit.
Head: 84d4258f130ebebe748a9b3a08f03c8741d01c45. Base: 6c87f5ff9442cd658572139bc536d018fd5222a4.
No push, deploy, or change to dev. No branch was dropped: no included branch produced a Rust code/test failure; unfinished validation is listed below.

Included: job/location (#391), job/webcal-431 (#431), job/small-bugs-4 (#459/#463/#464), job/photos-470 (#470), job/perf-367 (#367). All five heads are ancestors. The required final fetch and origin/dev merge returned Already up to date.

Integration fixes and files:

  • Settings canonical links preserve Maintenance query state and stable Saved place UUID fragments (apps/web/src/routes/settings/[...path]/+page.svelte, registry tests).
  • Authenticated Location routing coexists with public Calendar feeds (crates/calternal-server/src/wire.rs).
  • Mail fixtures retain MIME reader regressions and the full-history profile (crates/plugins/mail/src/sync.rs). Calendar benchmarks use the canonical Daily note first, then search only that User's Home (apps/web/e2e/calendar-perf.mjs).
  • Location uses shared leading and shape tokens (apps/web/src/routes/settings/account/LocationGroup.svelte).
  • Location operations and Saved place identities have explicit fail-closed classifications with regression tests (tests/adversarial/authz_matrix.py, xuser_matrix.py, test_xuser_classification.py).
  • Updated the shared capture harness and its regression tests (apps/web/e2e/harness.mjs, harness.test.mjs, appearance-review.mjs). Earlier failing capture output is preserved; no existing numeric assertion was weakened.
  • Regenerated contracts/openapi.json, packages/api-client/src/generated.ts, and docs/parity-*. No generated files were hand-merged.
  • Reviewed module/function comments were updated with the merge fixes. Imported feature files remain in the five branch histories. The complete changed-file list is artifacts/merge-round-2/files.txt.

Migrations: no duplicate numeric prefixes in any migrations folder. Notes adds 0020 after origin/dev's 0019; Calendar adds 0004 after origin/dev's 0003. Notes bridge is excluded.

Decisions:

  • Keep the existing API adapters' scope. Record the new Location/Calendar adapter gaps in the generated parity inventory rather than invent new CLI/MCP/WebMCP behavior in this merge.
  • Keep both Mail fixture behaviors in one helper. Keep the Calendar fallback scoped to the current User's Home.
  • Preserve dev's existing test expectations. The two web failures were timeouts and were rerun alone. Restore the exact 16-family theme expectation from dev; count dark variant submenu parents as families and use the existing keyboard submenu interaction.
  • In the capture harness, check the saved Auto/System preference separately from its rendered Light/Dark CSS phase. Eight regressions verify both phases and reject wrong persistence or rendering.
  • Seed the review's initial preference through the real API before SPA navigation. Wait for hydration before choosing a mode, and await persistence with bounded API reads on the host. Playwright 1.63 treats the former async predicate as truthy before its Promise resolves.

Known gaps:

  • calternal-server tests were stopped during compilation at the approximately four-hour limit (exit -15). Server clippy passed. No server test assertion result was produced. Run cargo test -p calternal-server before merge.
  • Standalone vendored async-imap clippy/test were initially cancelled while waiting for the build lock and were not completed before the limit. Mail clippy and tests checked/exercised its Tokio dependency path.
  • The ignored large Mail history and worst-case performance profiles were not rerun. The requested local one-item Photos smoke completed; the imported baseline remains unchanged.
  • The live hostile-input and race adversarial round was not run under this session's safety limits. Offline classification and probe-helper tests do not replace it. This branch is not certified ready to merge until that round is completed.
  • Static parity records 188 actions with adapter gaps. New Location operations lack CLI/MCP/WebMCP adapters; Calendar feeds/subscriptions lack MCP adapters. These imported scope gaps remain documented.
  • The official generated-check wrapper returned 143 after its build/generation output. The equivalent OpenAPI generation, client generation, unique-operation check, and clean generated diff were rerun explicitly and all returned 0.
  • The local one-photo debug smoke is not comparable with the 5,000-photo baseline; no regression verdict was made. Its JSON commit field is unknown.

Browser evidence: Calendar feeds passed with 36 screenshots. Location passed with six screenshots, including stable Saved place link restoration and cap-height assertions. The full Appearance review passed with 71 screenshots. Notes, Photos and the Log with its Saved place passed with 18 more screenshots. All required surface matrices cover 390/820/1440 px and light/dark. The additional Unsplash previews use third-party test fixtures; ordinary Notes/Photos/Location/Calendar data comes from the real local API. The production app supplied the screenshots; visual quality review remains with the orchestrator.
Appearance, Notes, Photos and Log matrix. Location full matrix. Calendar full matrix.

Local performance smoke (photos-perf.mjs --items 1 --home-only): server start 1101 ms; all indexed 4060 ms; rebuild requested 2582 ms; mean/peak RSS 350938740/432443392 bytes; mean/peak CPU 25.24/132.98%; CPU 23.74 s. Load after: 33.2/38.3/40.6. Baseline docs/perf/baseline.json, commit 369ab6a2f9fc673e3564b94857fbecfeb04df404, 5000 photos: server start 290 ms; indexed 63230 ms; rebuild 719 ms; mean/peak RSS 360533602/495759360 bytes; mean/peak CPU 63.05/235.82%; CPU 113.24 s. Different dataset and environment: these numbers show the smoke completed, not a regression comparison.

Gate outputs follow. Full logs are under artifacts/merge-round-2/ in the worktree; screenshots and logs are not committed.

Required environment: CARGO_PROFILE_DEV_DEBUG=line-tables-only CARGO_INCREMENTAL=0 CARGO_BUILD_JOBS=4 TMPDIR=$PWD/target/tmp; the preset CARGO_TARGET_DIR was retained. Rust gates ran per crate.

cargo fmt --check: exit 0, no output. git diff --check: exit 0, no output.

Per-crate exit statuses, verbatim:

calternal-cli	clippy	0
calternal-cli	test	0
calternal-dav	clippy	0
calternal-dav	test	0
calternal-location	clippy	0
calternal-location	test	0
calternal-notes-core	clippy	0
calternal-notes-core	test	0
calternal-plugin	clippy	0
calternal-plugin	test	0
calternal-plugin-calendar	clippy	0
calternal-plugin-calendar	test	0
calternal-plugin-files	clippy	0
calternal-plugin-files	test	0
calternal-plugin-mail	clippy	0
calternal-plugin-mail	test	0
calternal-plugin-notes	clippy	0
calternal-plugin-notes	test	0
calternal-plugin-photos	clippy	0
calternal-plugin-photos	test	0
calternal-server	clippy	0
calternal-server	test	-15

calternal-cli clippy:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 16m 25s

calternal-cli test:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 57m 13s
test result: ok. 27 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.76s
test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.09s

calternal-dav clippy:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 12m 25s

calternal-dav test:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 6m 06s
test result: ok. 41 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.46s
test result: ok. 33 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.10s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

calternal-location clippy:

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

calternal-location test:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 57.00s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.47s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

calternal-notes-core clippy:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 29s

calternal-notes-core test:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 2m 31s
test result: ok. 506 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.74s
test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 6.47s
test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.07s
test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.53s
test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

calternal-plugin clippy:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 9m 55s

calternal-plugin test:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 4m 21s
test result: ok. 23 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 8.05s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

calternal-plugin-calendar clippy:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 29m 42s

calternal-plugin-calendar test:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 10m 46s
test result: ok. 79 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 8.33s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.24s
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.23s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

calternal-plugin-files clippy:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 4m 08s

calternal-plugin-files test:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 6m 35s
test result: ok. 129 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 220.28s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

calternal-plugin-mail clippy:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 3m 36s

calternal-plugin-mail test:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 3m 49s
test result: ok. 35 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 1.17s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

calternal-plugin-notes clippy:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 5m 36s

calternal-plugin-notes test:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 7m 40s
test result: ok. 130 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 223.97s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.83s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

calternal-plugin-photos clippy:

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

calternal-plugin-photos test:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 6m 06s
test result: ok. 44 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 25.16s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

calternal-server clippy:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 18m 02s

Server test run: cancelled during compilation; no test result. Last compiler output, verbatim:

   Compiling calternal-plugin-money v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/plugins/money)
   Compiling rmcp v3.5.0
   Compiling calternal-plugin-files v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/plugins/files)
   Compiling calternal-collab v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/calternal-collab)
   Compiling calternal-plugin-calendar v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/plugins/calendar)
   Compiling calternal-plugin-ai v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/plugins/ai)
   Compiling calternal-plugin-photos v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/plugins/photos)
   Compiling calternal-plugin-video v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/plugins/video)
   Compiling calternal-plugin-notifications v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/plugins/notifications)
   Compiling calternal-plugin-analytics v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/plugins/analytics)

Web, contract, classification, parity, offline helper and browser output excerpts follow verbatim. Full output, including earlier failures and isolated reruns, is in the attached log archive.

bun-install.log

Checked 631 installs across 749 packages (no changes) [25.76s]

web-check-final.log

Text sizes and UI shape values use shared role tokens.
svelte-check found 0 errors and 0 warnings

web-test.log

 ❯ |component| src/lib/components/KeyboardShortcutsCard.svelte.test.ts (1 test | 1 failed) 5696ms
 ❯ |unit| src/lib/calendar/zones.test.ts (21 tests | 1 failed) 6881ms
⎯⎯⎯⎯⎯⎯⎯ Failed Tests 2 ⎯⎯⎯⎯⎯⎯⎯
Error: Test timed out in 5000ms.
If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout".
Error: Test timed out in 5000ms.
If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout".
 Test Files  2 failed | 137 passed (139)
      Tests  2 failed | 897 passed (899)
   Duration  416.06s (transform 66%, import 12%, environment 12%, tests 7%, setup 3%)

web-zones-alone.log

 Test Files  1 passed (1)
      Tests  21 passed (21)
   Duration  88.80s (transform 94%, import 6%)

web-shortcuts-alone.log

 Test Files  1 passed (1)
      Tests  1 passed (1)
   Duration  126.01s (transform 79%, environment 11%, import 5%, setup 3%, tests 2%)

settings-alone.log

 Test Files  1 passed (1)
      Tests  8 passed (8)
   Duration  6.85s (transform 85%, import 10%, tests 4%)

api-client-tests.log

(pass) apiFetch > keeps a typed failure body that is not an error envelope [0.23ms]
 9 pass
 0 fail
 31 expect() calls

bench-tests.log

............
----------------------------------------------------------------------
Ran 12 tests in 1.213s

OK

dav-probe-contract-tests.log

.......
----------------------------------------------------------------------
Ran 7 tests in 0.029s

OK

appearance-probe-contract-tests.log

....
----------------------------------------------------------------------
Ran 4 tests in 0.008s

OK

classification-final-tests.log

....
----------------------------------------------------------------------
Ran 4 tests in 0.284s

OK

classify-final.log

Cross-User classification gate: 328 operations classified

parity-final.log

Parity matrix: 206 web API actions, 113 shortcuts, 2 static commands, 131 menu actions, 33 settings groups, 188 actions with adapter gaps

generated-check-confirmed.log

$ /mnt/hdd/targets/jobs/merge-round-2/debug/calternal-server openapi
exit=0
$ bun run --cwd packages/api-client generate
$ 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 [3s]
exit=0
$ git diff --exit-code -- contracts/openapi.json packages/api-client/src/generated.ts
exit=0
OpenAPI operation IDs: 328 unique

calendar-feeds.log

Calendar feeds proof passed; screenshots: /home/kayg/Developer/calternal-wt/merge-web/artifacts/merge-round-2/calendar-feeds

location-review.log

PASS appearance review captures: 6 screenshots in /home/kayg/Developer/calternal-wt/merge-web/artifacts/location

photos-home-local.log

  indexed: {
{"items":1,"commit":"unknown","recordedAt":"2026-09-30T10:14:15.246Z","homeOnly":true,"environment":{"host":"calternal-dev","platform":"linux","architecture":"x64"},"homeFixtures":{"photos":1,"photoDays":1,"files":0,"folderItems":0,"notes":0,"logEntries":0,"dailyNotes":0,"largeNoteBytes":0},"homeFixtureWriteMs":10277,"indexing":{"serverUpMs":1101,"allIndexedMs":4060,"photoRebuildRequestedMs":2582,"indexed":{"photos":1,"folderItems":0,"restItems":0,"notes":0,"logEntries":0}},"homeRenders":{"cpuThrottle":4,"runs":3,"order":[["files5k","analyticsYear","note1MiB"],["analyticsYear","note1MiB","files5k"],["note1MiB","files5k","analyticsYear"]],"files5k":{"skipped":true},"analyticsYear":{"skipped":true},"note1MiB":{"skipped":true}},"loadAverageAfter":[33.2,38.3,40.6],"homeResources":{"meanRssBytes":350938740,"peakRssBytes":432443392,"meanCpuPercent":25.24,"peakCpuPercent":132.98,"cpuSeconds":23.74,"samples":186}}

harness-test-final.log:


 8 pass
 0 fail
Ran 8 tests across 1 file. [474.00ms]

appearance-review-awaited.log:

PASS appearance review captures: 71 screenshots in /home/kayg/Developer/calternal-wt/merge-web/artifacts/location

reconcile-review-normal-note.log:

PASS Notes and Photos review: 18 production screenshots, 390/820/1440 px, light/dark

cargo-clean.log:

     Removed 23900 files, 14.0GiB total

migrations.log:

crates/calternal-auth/migrations: 10 numbered migrations; no duplicates
crates/calternal-db/src/migrations: 6 numbered migrations; no duplicates
crates/calternal-plugin/migrations: 1 numbered migrations; no duplicates
crates/calternal-search/migrations: 3 numbered migrations; no duplicates
crates/calternal-tags/migrations: 2 numbered migrations; no duplicates
crates/plugins/ai/migrations: 4 numbered migrations; no duplicates
crates/plugins/analytics/migrations: 2 numbered migrations; no duplicates
crates/plugins/calendar/migrations: 4 numbered migrations; no duplicates
crates/plugins/files/migrations: 15 numbered migrations; no duplicates
crates/plugins/mail/migrations: 8 numbered migrations; no duplicates
crates/plugins/notes/migrations: 20 numbered migrations; no duplicates
crates/plugins/notifications/migrations: 4 numbered migrations; no duplicates
crates/plugins/photos/migrations: 6 numbered migrations; no duplicates
crates/plugins/video/migrations: 1 numbered migrations; no duplicates
PASS: 14 migration folders have unique numeric prefixes

bun run build: exit 0. Output, verbatim:

✓ built in 2m 29s
✓ built in 527ms
✓ built in 4m 52s
> Using @sveltejs/adapter-static

Official generated-check wrapper exit: 143. Confirmed equivalent generation/uniqueness/diff steps: all exit 0, quoted above.
Standalone vendor attempt statuses, verbatim:

async-imap	clippy	-15
async-imap	test	-15

Cleanup: cargo clean exit 0; web build and Svelte build output deleted. Screenshots and logs remain uncommitted. Final git status is clean.

Full gate output, earlier failures, isolated reruns, performance smoke and changed-file manifest.

All five branches are committed on `job/merge-round-2`. Validation remains incomplete at the four-hour limit. Head: `84d4258f130ebebe748a9b3a08f03c8741d01c45`. Base: `6c87f5ff9442cd658572139bc536d018fd5222a4`. No push, deploy, or change to dev. No branch was dropped: no included branch produced a Rust code/test failure; unfinished validation is listed below. Included: `job/location` (#391), `job/webcal-431` (#431), `job/small-bugs-4` (#459/#463/#464), `job/photos-470` (#470), `job/perf-367` (#367). All five heads are ancestors. The required final fetch and origin/dev merge returned `Already up to date.` Integration fixes and files: - Settings canonical links preserve Maintenance query state and stable Saved place UUID fragments (`apps/web/src/routes/settings/[...path]/+page.svelte`, registry tests). - Authenticated Location routing coexists with public Calendar feeds (`crates/calternal-server/src/wire.rs`). - Mail fixtures retain MIME reader regressions and the full-history profile (`crates/plugins/mail/src/sync.rs`). Calendar benchmarks use the canonical Daily note first, then search only that User's Home (`apps/web/e2e/calendar-perf.mjs`). - Location uses shared leading and shape tokens (`apps/web/src/routes/settings/account/LocationGroup.svelte`). - Location operations and Saved place identities have explicit fail-closed classifications with regression tests (`tests/adversarial/authz_matrix.py`, `xuser_matrix.py`, `test_xuser_classification.py`). - Updated the shared capture harness and its regression tests (`apps/web/e2e/harness.mjs`, `harness.test.mjs`, `appearance-review.mjs`). Earlier failing capture output is preserved; no existing numeric assertion was weakened. - Regenerated `contracts/openapi.json`, `packages/api-client/src/generated.ts`, and `docs/parity-*`. No generated files were hand-merged. - Reviewed module/function comments were updated with the merge fixes. Imported feature files remain in the five branch histories. The complete changed-file list is `artifacts/merge-round-2/files.txt`. Migrations: no duplicate numeric prefixes in any migrations folder. Notes adds 0020 after origin/dev's 0019; Calendar adds 0004 after origin/dev's 0003. Notes bridge is excluded. Decisions: - Keep the existing API adapters' scope. Record the new Location/Calendar adapter gaps in the generated parity inventory rather than invent new CLI/MCP/WebMCP behavior in this merge. - Keep both Mail fixture behaviors in one helper. Keep the Calendar fallback scoped to the current User's Home. - Preserve dev's existing test expectations. The two web failures were timeouts and were rerun alone. Restore the exact 16-family theme expectation from dev; count dark variant submenu parents as families and use the existing keyboard submenu interaction. - In the capture harness, check the saved Auto/System preference separately from its rendered Light/Dark CSS phase. Eight regressions verify both phases and reject wrong persistence or rendering. - Seed the review's initial preference through the real API before SPA navigation. Wait for hydration before choosing a mode, and await persistence with bounded API reads on the host. Playwright 1.63 treats the former async predicate as truthy before its Promise resolves. Known gaps: - `calternal-server` tests were stopped during compilation at the approximately four-hour limit (exit -15). Server clippy passed. No server test assertion result was produced. Run `cargo test -p calternal-server` before merge. - Standalone vendored `async-imap` clippy/test were initially cancelled while waiting for the build lock and were not completed before the limit. Mail clippy and tests checked/exercised its Tokio dependency path. - The ignored large Mail history and worst-case performance profiles were not rerun. The requested local one-item Photos smoke completed; the imported baseline remains unchanged. - The live hostile-input and race adversarial round was not run under this session's safety limits. Offline classification and probe-helper tests do not replace it. This branch is not certified ready to merge until that round is completed. - Static parity records 188 actions with adapter gaps. New Location operations lack CLI/MCP/WebMCP adapters; Calendar feeds/subscriptions lack MCP adapters. These imported scope gaps remain documented. - The official generated-check wrapper returned 143 after its build/generation output. The equivalent OpenAPI generation, client generation, unique-operation check, and clean generated diff were rerun explicitly and all returned 0. - The local one-photo debug smoke is not comparable with the 5,000-photo baseline; no regression verdict was made. Its JSON commit field is `unknown`. Browser evidence: Calendar feeds passed with 36 screenshots. Location passed with six screenshots, including stable Saved place link restoration and cap-height assertions. The full Appearance review passed with 71 screenshots. Notes, Photos and the Log with its Saved place passed with 18 more screenshots. All required surface matrices cover 390/820/1440 px and light/dark. The additional Unsplash previews use third-party test fixtures; ordinary Notes/Photos/Location/Calendar data comes from the real local API. The production app supplied the screenshots; visual quality review remains with the orchestrator. [Appearance, Notes, Photos and Log matrix](https://git.kayg.org/attachments/2a0c2168-6199-4d45-9ff2-ad676518e88e). [Location full matrix](https://git.kayg.org/attachments/6078bc47-ceb1-4566-9b5e-63ef5c52b9a1). [Calendar full matrix](https://git.kayg.org/attachments/03f5976a-28a3-4384-9aae-a995bac45409). Local performance smoke (`photos-perf.mjs --items 1 --home-only`): server start 1101 ms; all indexed 4060 ms; rebuild requested 2582 ms; mean/peak RSS 350938740/432443392 bytes; mean/peak CPU 25.24/132.98%; CPU 23.74 s. Load after: 33.2/38.3/40.6. Baseline `docs/perf/baseline.json`, commit `369ab6a2f9fc673e3564b94857fbecfeb04df404`, 5000 photos: server start 290 ms; indexed 63230 ms; rebuild 719 ms; mean/peak RSS 360533602/495759360 bytes; mean/peak CPU 63.05/235.82%; CPU 113.24 s. Different dataset and environment: these numbers show the smoke completed, not a regression comparison. Gate outputs follow. Full logs are under `artifacts/merge-round-2/` in the worktree; screenshots and logs are not committed. Required environment: `CARGO_PROFILE_DEV_DEBUG=line-tables-only CARGO_INCREMENTAL=0 CARGO_BUILD_JOBS=4 TMPDIR=$PWD/target/tmp`; the preset CARGO_TARGET_DIR was retained. Rust gates ran per crate. `cargo fmt --check`: exit 0, no output. `git diff --check`: exit 0, no output. Per-crate exit statuses, verbatim: ```text calternal-cli clippy 0 calternal-cli test 0 calternal-dav clippy 0 calternal-dav test 0 calternal-location clippy 0 calternal-location test 0 calternal-notes-core clippy 0 calternal-notes-core test 0 calternal-plugin clippy 0 calternal-plugin test 0 calternal-plugin-calendar clippy 0 calternal-plugin-calendar test 0 calternal-plugin-files clippy 0 calternal-plugin-files test 0 calternal-plugin-mail clippy 0 calternal-plugin-mail test 0 calternal-plugin-notes clippy 0 calternal-plugin-notes test 0 calternal-plugin-photos clippy 0 calternal-plugin-photos test 0 calternal-server clippy 0 calternal-server test -15 ``` calternal-cli clippy: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 16m 25s ``` calternal-cli test: ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 57m 13s test result: ok. 27 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.76s test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.09s ``` calternal-dav clippy: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 12m 25s ``` calternal-dav test: ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 6m 06s test result: ok. 41 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.46s test result: ok. 33 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.10s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` calternal-location clippy: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 05s ``` calternal-location test: ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 57.00s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.47s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` calternal-notes-core clippy: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 29s ``` calternal-notes-core test: ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 2m 31s test result: ok. 506 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.74s test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 6.47s test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.07s test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.53s test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` calternal-plugin clippy: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 9m 55s ``` calternal-plugin test: ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 4m 21s test result: ok. 23 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 8.05s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` calternal-plugin-calendar clippy: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 29m 42s ``` calternal-plugin-calendar test: ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 10m 46s test result: ok. 79 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 8.33s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.24s test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.23s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` calternal-plugin-files clippy: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 4m 08s ``` calternal-plugin-files test: ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 6m 35s test result: ok. 129 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 220.28s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` calternal-plugin-mail clippy: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 3m 36s ``` calternal-plugin-mail test: ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 3m 49s test result: ok. 35 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 1.17s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` calternal-plugin-notes clippy: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 5m 36s ``` calternal-plugin-notes test: ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 7m 40s test result: ok. 130 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 223.97s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.83s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` calternal-plugin-photos clippy: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 48s ``` calternal-plugin-photos test: ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 6m 06s test result: ok. 44 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 25.16s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` calternal-server clippy: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 18m 02s ``` Server test run: cancelled during compilation; no test result. Last compiler output, verbatim: ```text Compiling calternal-plugin-money v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/plugins/money) Compiling rmcp v3.5.0 Compiling calternal-plugin-files v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/plugins/files) Compiling calternal-collab v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/calternal-collab) Compiling calternal-plugin-calendar v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/plugins/calendar) Compiling calternal-plugin-ai v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/plugins/ai) Compiling calternal-plugin-photos v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/plugins/photos) Compiling calternal-plugin-video v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/plugins/video) Compiling calternal-plugin-notifications v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/plugins/notifications) Compiling calternal-plugin-analytics v0.0.1 (/home/kayg/Developer/calternal-wt/merge-web/crates/plugins/analytics) ``` Web, contract, classification, parity, offline helper and browser output excerpts follow verbatim. Full output, including earlier failures and isolated reruns, is in the attached log archive. ### bun-install.log ```text Checked 631 installs across 749 packages (no changes) [25.76s] ``` ### web-check-final.log ```text Text sizes and UI shape values use shared role tokens. svelte-check found 0 errors and 0 warnings ``` ### web-test.log ```text ❯ |component| src/lib/components/KeyboardShortcutsCard.svelte.test.ts (1 test | 1 failed) 5696ms ❯ |unit| src/lib/calendar/zones.test.ts (21 tests | 1 failed) 6881ms ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 2 ⎯⎯⎯⎯⎯⎯⎯ Error: Test timed out in 5000ms. If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout". Error: Test timed out in 5000ms. If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout". Test Files 2 failed | 137 passed (139) Tests 2 failed | 897 passed (899) Duration 416.06s (transform 66%, import 12%, environment 12%, tests 7%, setup 3%) ``` ### web-zones-alone.log ```text Test Files 1 passed (1) Tests 21 passed (21) Duration 88.80s (transform 94%, import 6%) ``` ### web-shortcuts-alone.log ```text Test Files 1 passed (1) Tests 1 passed (1) Duration 126.01s (transform 79%, environment 11%, import 5%, setup 3%, tests 2%) ``` ### settings-alone.log ```text Test Files 1 passed (1) Tests 8 passed (8) Duration 6.85s (transform 85%, import 10%, tests 4%) ``` ### api-client-tests.log ```text (pass) apiFetch > keeps a typed failure body that is not an error envelope [0.23ms] 9 pass 0 fail 31 expect() calls ``` ### bench-tests.log ```text ............ ---------------------------------------------------------------------- Ran 12 tests in 1.213s OK ``` ### dav-probe-contract-tests.log ```text ....... ---------------------------------------------------------------------- Ran 7 tests in 0.029s OK ``` ### appearance-probe-contract-tests.log ```text .... ---------------------------------------------------------------------- Ran 4 tests in 0.008s OK ``` ### classification-final-tests.log ```text .... ---------------------------------------------------------------------- Ran 4 tests in 0.284s OK ``` ### classify-final.log ```text Cross-User classification gate: 328 operations classified ``` ### parity-final.log ```text Parity matrix: 206 web API actions, 113 shortcuts, 2 static commands, 131 menu actions, 33 settings groups, 188 actions with adapter gaps ``` ### generated-check-confirmed.log ```text $ /mnt/hdd/targets/jobs/merge-round-2/debug/calternal-server openapi exit=0 $ bun run --cwd packages/api-client generate $ 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 [3s] exit=0 $ git diff --exit-code -- contracts/openapi.json packages/api-client/src/generated.ts exit=0 OpenAPI operation IDs: 328 unique ``` ### calendar-feeds.log ```text Calendar feeds proof passed; screenshots: /home/kayg/Developer/calternal-wt/merge-web/artifacts/merge-round-2/calendar-feeds ``` ### location-review.log ```text PASS appearance review captures: 6 screenshots in /home/kayg/Developer/calternal-wt/merge-web/artifacts/location ``` ### photos-home-local.log ```text indexed: { {"items":1,"commit":"unknown","recordedAt":"2026-09-30T10:14:15.246Z","homeOnly":true,"environment":{"host":"calternal-dev","platform":"linux","architecture":"x64"},"homeFixtures":{"photos":1,"photoDays":1,"files":0,"folderItems":0,"notes":0,"logEntries":0,"dailyNotes":0,"largeNoteBytes":0},"homeFixtureWriteMs":10277,"indexing":{"serverUpMs":1101,"allIndexedMs":4060,"photoRebuildRequestedMs":2582,"indexed":{"photos":1,"folderItems":0,"restItems":0,"notes":0,"logEntries":0}},"homeRenders":{"cpuThrottle":4,"runs":3,"order":[["files5k","analyticsYear","note1MiB"],["analyticsYear","note1MiB","files5k"],["note1MiB","files5k","analyticsYear"]],"files5k":{"skipped":true},"analyticsYear":{"skipped":true},"note1MiB":{"skipped":true}},"loadAverageAfter":[33.2,38.3,40.6],"homeResources":{"meanRssBytes":350938740,"peakRssBytes":432443392,"meanCpuPercent":25.24,"peakCpuPercent":132.98,"cpuSeconds":23.74,"samples":186}} ``` harness-test-final.log: ```text 8 pass 0 fail Ran 8 tests across 1 file. [474.00ms] ``` appearance-review-awaited.log: ```text PASS appearance review captures: 71 screenshots in /home/kayg/Developer/calternal-wt/merge-web/artifacts/location ``` reconcile-review-normal-note.log: ```text PASS Notes and Photos review: 18 production screenshots, 390/820/1440 px, light/dark ``` cargo-clean.log: ```text Removed 23900 files, 14.0GiB total ``` migrations.log: ```text crates/calternal-auth/migrations: 10 numbered migrations; no duplicates crates/calternal-db/src/migrations: 6 numbered migrations; no duplicates crates/calternal-plugin/migrations: 1 numbered migrations; no duplicates crates/calternal-search/migrations: 3 numbered migrations; no duplicates crates/calternal-tags/migrations: 2 numbered migrations; no duplicates crates/plugins/ai/migrations: 4 numbered migrations; no duplicates crates/plugins/analytics/migrations: 2 numbered migrations; no duplicates crates/plugins/calendar/migrations: 4 numbered migrations; no duplicates crates/plugins/files/migrations: 15 numbered migrations; no duplicates crates/plugins/mail/migrations: 8 numbered migrations; no duplicates crates/plugins/notes/migrations: 20 numbered migrations; no duplicates crates/plugins/notifications/migrations: 4 numbered migrations; no duplicates crates/plugins/photos/migrations: 6 numbered migrations; no duplicates crates/plugins/video/migrations: 1 numbered migrations; no duplicates PASS: 14 migration folders have unique numeric prefixes ``` `bun run build`: exit 0. Output, verbatim: ```text ✓ built in 2m 29s ✓ built in 527ms ✓ built in 4m 52s > Using @sveltejs/adapter-static ``` Official generated-check wrapper exit: 143. Confirmed equivalent generation/uniqueness/diff steps: all exit 0, quoted above. Standalone vendor attempt statuses, verbatim: ```text async-imap clippy -15 async-imap test -15 ``` Cleanup: cargo clean exit 0; web build and Svelte build output deleted. Screenshots and logs remain uncommitted. Final git status is clean. [Full gate output, earlier failures, isolated reruns, performance smoke and changed-file manifest](https://git.kayg.org/attachments/bd32de61-0a7d-4999-b66c-134546087c66).
Author
Owner

Resuming merge round 2 on job/merge-round-2, base/head 84d4258f130ebebe748a9b3a08f03c8741d01c45. I will merge the current origin/dev once, then job/bg-422, and run the missing final-tree gates and ordinary local functional/performance checks. Hostile-input, race and cross-User exploitation probes remain unrun under this session’s safety limits. No push or deployment. Fresh output will be reported on #391 #431 #459 #470 #367 #422.

Resuming merge round 2 on `job/merge-round-2`, base/head `84d4258f130ebebe748a9b3a08f03c8741d01c45`. I will merge the current `origin/dev` once, then `job/bg-422`, and run the missing final-tree gates and ordinary local functional/performance checks. Hostile-input, race and cross-User exploitation probes remain unrun under this session’s safety limits. No push or deployment. Fresh output will be reported on #391 #431 #459 #470 #367 #422.
Author
Owner

Fetched origin once. origin/dev merged as e3bb4b1f5; its only conflict was the GridColumn module comment, resolved with both #431 subscription Event and #410 pile invariants. The #422 merge conflicts are an import list and a Photos index module comment: retain both Location and BACKGROUND_FOLDER imports, targeted/startup refresh (#470), and Backgrounds exclusion (#422). Final-tree server clippy/test and web check/test are running. Fresh origin/dev also contains CRLF CSV lines and Markdown hard breaks under docs/perf/runs/2026-09-30-asr-ab*, which make the staged diff whitespace check report trailing whitespace; I preserved these imported research files.

Fetched `origin` once. `origin/dev` merged as `e3bb4b1f5`; its only conflict was the GridColumn module comment, resolved with both #431 subscription Event and #410 pile invariants. The #422 merge conflicts are an import list and a Photos index module comment: retain both Location and BACKGROUND_FOLDER imports, targeted/startup refresh (#470), and Backgrounds exclusion (#422). Final-tree server clippy/test and web check/test are running. Fresh `origin/dev` also contains CRLF CSV lines and Markdown hard breaks under `docs/perf/runs/2026-09-30-asr-ab*`, which make the staged diff whitespace check report trailing whitespace; I preserved these imported research files.
Author
Owner

Both requested merges are committed: e3bb4b1f5 (origin/dev 5d6d22e6047e902213980f88df8c77bba463fe10) and 272139628 (#422 head 59a232b4d43aa77c274dd180454d5bd8e6ab617c). Final-tree web check: svelte-check found 0 errors and 0 warnings. Web tests: Test Files 139 passed (139) / Tests 905 passed (905). Offline classification and harness regressions passed. Parity regeneration removes one stale PhotosView.svelte:upload menu inventory entry; no new adapter gaps. Rust gates and production build continue.

Both requested merges are committed: `e3bb4b1f5` (origin/dev `5d6d22e6047e902213980f88df8c77bba463fe10`) and `272139628` (#422 head `59a232b4d43aa77c274dd180454d5bd8e6ab617c`). Final-tree web check: `svelte-check found 0 errors and 0 warnings`. Web tests: `Test Files 139 passed (139)` / `Tests 905 passed (905)`. Offline classification and harness regressions passed. Parity regeneration removes one stale `PhotosView.svelte:upload` menu inventory entry; no new adapter gaps. Rust gates and production build continue.
Author
Owner

Final-tree cargo fmt --check exit 0 (no output). Server clippy exit 0:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 13m 00s

Server tests now compile. The production web build passed. Unique migration-prefix checks passed in all 14 folders. Browser plugin not available; the existing Playwright harness will run ordinary local checks against the final-tree server and production SPA.

Final-tree `cargo fmt --check` exit 0 (no output). Server clippy exit 0: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 13m 00s ``` Server tests now compile. The production web build passed. Unique migration-prefix checks passed in all 14 folders. Browser plugin not available; the existing Playwright harness will run ordinary local checks against the final-tree server and production SPA.
Author
Owner

Final-tree server clippy and tests passed (both exit 0). The #422 explicit 2 MiB stack regression passed. Output, verbatim:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 11m 33s
test appearance::tests::uploaded_image_backgrounds_must_be_decodable_files_in_the_backgrounds_folder ... ok
test result: ok. 93 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 29.40s

The runnable server build and sequential IMAP/Files/Photos/filesystem gates are next.

Final-tree server clippy and tests passed (both exit 0). The #422 explicit 2 MiB stack regression passed. Output, verbatim: ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 11m 33s test appearance::tests::uploaded_image_backgrounds_must_be_decodable_files_in_the_backgrounds_folder ... ok test result: ok. 93 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 29.40s ``` The runnable server build and sequential IMAP/Files/Photos/filesystem gates are next.
Author
Owner

Standalone async-imap clippy passed; tests failed one existing expectation. The unchanged client::tests::test_parsing_error expects the SMTP fixture greeting in Display; the existing ParseError::Invalid display at src/error.rs says only unable to parse status response. Both came from c54be68ad (2026-09-28). No merge altered either. I keep the old expectation and current display unchanged under the owner rule; the orchestrator must decide the intended diagnostic contract.

    Finished `test` profile [unoptimized + debuginfo] target(s) in 1m 18s
test client::tests::test_parsing_error ... FAILED
---- client::tests::test_parsing_error stdout ----
thread 'client::tests::test_parsing_error' (890668) panicked at crates/plugins/mail/vendor/async-imap/src/client.rs:2724:9:
assertion failed: session.noop().await.unwrap_err().to_string().contains("220 mail.example.org ESMTP Postcow")
    client::tests::test_parsing_error
test result: FAILED. 69 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.40s

Location review passed six screenshots and Calendar feeds passed 36 screenshots on the final production build. Settings effects initially failed to load Sharp because the Nix Bun runtime could not find libstdc++; resolving the runtime path is in progress.

Standalone `async-imap` clippy passed; tests failed one existing expectation. The unchanged `client::tests::test_parsing_error` expects the SMTP fixture greeting in `Display`; the existing `ParseError::Invalid` display at `src/error.rs` says only `unable to parse status response`. Both came from `c54be68ad` (2026-09-28). No merge altered either. I keep the old expectation and current display unchanged under the owner rule; the orchestrator must decide the intended diagnostic contract. ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 1m 18s test client::tests::test_parsing_error ... FAILED ---- client::tests::test_parsing_error stdout ---- thread 'client::tests::test_parsing_error' (890668) panicked at crates/plugins/mail/vendor/async-imap/src/client.rs:2724:9: assertion failed: session.noop().await.unwrap_err().to_string().contains("220 mail.example.org ESMTP Postcow") client::tests::test_parsing_error test result: FAILED. 69 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.40s ``` Location review passed six screenshots and Calendar feeds passed 36 screenshots on the final production build. Settings effects initially failed to load Sharp because the Nix Bun runtime could not find libstdc++; resolving the runtime path is in progress.
Author
Owner

Starting resumed validation on job/merge-round-2 at 42c63668fd (merge base: 5d6d22e604). I am reconciling origin/dev and job/bg-422, then running the remaining gates and live probes.

Starting resumed validation on job/merge-round-2 at 42c63668fdfb5cc43bf6a790cf002023eddd7f89 (merge base: 5d6d22e6047e902213980f88df8c77bba463fe10). I am reconciling origin/dev and job/bg-422, then running the remaining gates and live probes.
Author
Owner

Merge finding: origin/dev conflicted in AppearanceSection.svelte and the #367 benchmark recorder/runner. The incoming Appearance version put the precise-location toggle back in Appearance, while DESIGN §47 L1 assigns location consent to Account → Location; I kept that ownership and merged the #506 schemePreference/variant behavior. The incoming benchmark files lacked #367's locking and workload coverage; I retained those paths and added the #506 Theme menu profile to the locked probe and shared report schema.

Merge finding: origin/dev conflicted in AppearanceSection.svelte and the #367 benchmark recorder/runner. The incoming Appearance version put the precise-location toggle back in Appearance, while DESIGN §47 L1 assigns location consent to Account → Location; I kept that ownership and merged the #506 schemePreference/variant behavior. The incoming benchmark files lacked #367's locking and workload coverage; I retained those paths and added the #506 Theme menu profile to the locked probe and shared report schema.
Author
Owner

The first Location probe run exposed a flaky test harness wait, not a server defect: the async page.waitForFunction predicate could resolve early under Playwright 1.63, while checking the DOM and API in one predicate. I updated the probe to await the Location write response, read authoritative API state on the host, then wait with synchronous DOM predicates. The existing consent expectation remains unchanged. The corrected real-server probe passed, including hostile payloads, exact coordinates, concurrent writes, and cross-User isolation.

The first Location probe run exposed a flaky test harness wait, not a server defect: the async `page.waitForFunction` predicate could resolve early under Playwright 1.63, while checking the DOM and API in one predicate. I updated the probe to await the Location write response, read authoritative API state on the host, then wait with synchronous DOM predicates. The existing consent expectation remains unchanged. The corrected real-server probe passed, including hostile payloads, exact coordinates, concurrent writes, and cross-User isolation.
Author
Owner

Merge round 2 final report

Head: 192ea5457f1fc17735d876e70b41cb506b2a8274 on job/merge-round-2. origin/dev was fetched and merged at 1389119e33831275e6b56b9181ef42838003a4b3; job/bg-422 was already an ancestor (git merge --no-edit job/bg-422 → Already up to date.). No push, deploy, or merge to dev.

Built

Integrated the #391 Location/Appearance, #431 calendar feeds, #459 bug fixes, #470 Photos and #367 performance changes. Follow-up 76d1e71e1 makes Location probes await settled server state. Follow-up 192ea5457 fixes the Photos/Backgrounds SSE ordering race: preserve one event invalidation while the stable folder ID resolves, then refetch once. Updated the production Settings sweep to cover Account → Location and real Photos folder actions.

Files changed by the follow-up:

  • apps/web/src/lib/photos/BackgroundsFolderView.svelte
  • apps/web/e2e/settings-effects.mjs
  • tests/adversarial/appearance_auto_scheme.mjs

Full integration manifest: artifacts/merge-round-2/files.txt.

Gates (output verbatim)

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

cargo clippy -p calternal-server --all-targets -- -D warnings
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 6m 06s

cargo test -p calternal-server
    Finished `test` profile [unoptimized + debuginfo] target(s) in 9m 02s
test result: ok. 93 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 22.86s

async-imap clippy
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 11.21s

async-imap test
---- client::tests::test_parsing_error stdout ----
thread 'client::tests::test_parsing_error' panicked at crates/plugins/mail/vendor/async-imap/src/client.rs:2724:9:
assertion failed: session.noop().await.unwrap_err().to_string().contains("220 mail.example.org ESMTP Postcow")
test client::tests::test_parsing_error ... FAILED
test result: FAILED. 69 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.40s

bun run check
Text sizes and UI shape values use shared role tokens.
svelte-check found 0 errors and 0 warnings

bun run build
✓ built in 1m 37s
> Using @sveltejs/adapter-static
  Wrote site to "build"
  ✔ done

bun run test (final run)
 ❯ |component| src/lib/themePicker.svelte.test.ts (7 tests | 1 failed) 11924ms
 FAIL |component| src/lib/themePicker.svelte.test.ts > theme menu > reveals the trigger in the sheet scrollport before opening
Error: Test timed out in 5000ms.
 Test Files  1 failed | 138 passed (139)
      Tests  1 failed | 909 passed (910)
   Start at  18:24:29
   Duration  271.28s (transform 61%, environment 16%, import 10%, tests 10%, setup 3%)

generated contract
Finished `dev` profile [unoptimized + debuginfo] target(s) in 13m 26s
Running `/mnt/hdd/targets/jobs/merge-round-2/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 [1.9s]

parity check
Parity matrix: 206 web API actions, 113 shortcuts, 2 static commands, 131 menu actions, 33 settings groups, 188 actions with adapter gaps

Live probes

  • Location: Location API probe: malformed and oversized payloads and file, exact coordinates, Unicode place, concurrent writes, fixture restore, and cross-User isolation passed; Appearance Auto/Fonts/Background burst: 48 concurrent writes, all 200.
  • Webcal: Calendar feeds proof passed; screenshots: /home/kayg/Developer/calternal-wt/merge-web/artifacts/webcal-431.
  • WebDAV race: WebDAV scripted probes passed.
  • Settings and Photos/Backgrounds: PASS settings effects: Appearance, Photos/Backgrounds, Calendar time preview; screenshots in /home/kayg/Developer/calternal-wt/merge-web/artifacts/bg-422.
  • Two-User matrix: 328 operations classified; 157 operations replayed; 565 A-ID vs missing-ID comparisons across B, C, D and anonymous; median absolute timing delta 6.1 ms; ownership: 77 comparisons; 0 denial failures.
  • Media had one SLOW-only finding: the PDF worker list took 5.39 s with HTTP 200 against the probe's 5.0 s threshold. No hostile-input or 5xx finding remained.
  • Local photos-perf.mjs --items 1 --home-only: at load average 38.2/42.8/43, server start 2850 ms, indexed 4790 ms, mean/peak RSS 335424222/425738240 bytes, mean/peak CPU 23.37/95.95%, CPU 22.16 s. This one-photo local smoke is not comparable to the 5,000-photo perf VM baseline.

Known gaps and decisions

  • Standalone IMAP tests retain the existing display expectation and fail client::tests::test_parsing_error; clippy passes. No test expectation was changed.
  • The final web test gate has the single five-second ThemePicker timeout above. The component and test are unchanged from origin/dev; this is reported as a gate failure.
  • Media's 5.39-second response is SLOW-only shared-host load.
  • DESIGN §35 does not specify an SSE event arriving before stable folder identity resolves. Decision: coalesce early events into one list refresh after resolution. DESIGN §47 L1 defines Account as Location consent owner; Auto uses the exact saved location.
  • Settings effects used Node 22 because Bun could not load host Sharp (libstdc++.so.6 missing). No app code changed for the host workaround.

Production screenshots

The new Settings/Photos/Backgrounds matrix covers 390/820/1440 px in light and dark: download review ZIP. Existing full matrices: Location, Appearance/Notes/Photos/Log, Calendar feeds. Screenshots and logs are not committed.

## Merge round 2 final report **Head:** `192ea5457f1fc17735d876e70b41cb506b2a8274` on `job/merge-round-2`. `origin/dev` was fetched and merged at `1389119e33831275e6b56b9181ef42838003a4b3`; `job/bg-422` was already an ancestor (`git merge --no-edit job/bg-422` → `Already up to date.`). No push, deploy, or merge to dev. ### Built Integrated the #391 Location/Appearance, #431 calendar feeds, #459 bug fixes, #470 Photos and #367 performance changes. Follow-up `76d1e71e1` makes Location probes await settled server state. Follow-up `192ea5457` fixes the Photos/Backgrounds SSE ordering race: preserve one event invalidation while the stable folder ID resolves, then refetch once. Updated the production Settings sweep to cover Account → Location and real Photos folder actions. Files changed by the follow-up: - `apps/web/src/lib/photos/BackgroundsFolderView.svelte` - `apps/web/e2e/settings-effects.mjs` - `tests/adversarial/appearance_auto_scheme.mjs` Full integration manifest: `artifacts/merge-round-2/files.txt`. ### Gates (output verbatim) `cargo fmt --check`: exit 0, no output. ```text cargo clippy -p calternal-server --all-targets -- -D warnings Finished `dev` profile [unoptimized + debuginfo] target(s) in 6m 06s cargo test -p calternal-server Finished `test` profile [unoptimized + debuginfo] target(s) in 9m 02s test result: ok. 93 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 22.86s async-imap clippy Finished `dev` profile [unoptimized + debuginfo] target(s) in 11.21s async-imap test ---- client::tests::test_parsing_error stdout ---- thread 'client::tests::test_parsing_error' panicked at crates/plugins/mail/vendor/async-imap/src/client.rs:2724:9: assertion failed: session.noop().await.unwrap_err().to_string().contains("220 mail.example.org ESMTP Postcow") test client::tests::test_parsing_error ... FAILED test result: FAILED. 69 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.40s bun run check Text sizes and UI shape values use shared role tokens. svelte-check found 0 errors and 0 warnings bun run build ✓ built in 1m 37s > Using @sveltejs/adapter-static Wrote site to "build" ✔ done bun run test (final run) ❯ |component| src/lib/themePicker.svelte.test.ts (7 tests | 1 failed) 11924ms FAIL |component| src/lib/themePicker.svelte.test.ts > theme menu > reveals the trigger in the sheet scrollport before opening Error: Test timed out in 5000ms. Test Files 1 failed | 138 passed (139) Tests 1 failed | 909 passed (910) Start at 18:24:29 Duration 271.28s (transform 61%, environment 16%, import 10%, tests 10%, setup 3%) generated contract Finished `dev` profile [unoptimized + debuginfo] target(s) in 13m 26s Running `/mnt/hdd/targets/jobs/merge-round-2/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 [1.9s] parity check Parity matrix: 206 web API actions, 113 shortcuts, 2 static commands, 131 menu actions, 33 settings groups, 188 actions with adapter gaps ``` ### Live probes - Location: `Location API probe: malformed and oversized payloads and file, exact coordinates, Unicode place, concurrent writes, fixture restore, and cross-User isolation passed`; `Appearance Auto/Fonts/Background burst: 48 concurrent writes, all 200`. - Webcal: `Calendar feeds proof passed; screenshots: /home/kayg/Developer/calternal-wt/merge-web/artifacts/webcal-431`. - WebDAV race: `WebDAV scripted probes passed`. - Settings and Photos/Backgrounds: `PASS settings effects: Appearance, Photos/Backgrounds, Calendar time preview; screenshots in /home/kayg/Developer/calternal-wt/merge-web/artifacts/bg-422`. - Two-User matrix: `328 operations classified; 157 operations replayed; 565 A-ID vs missing-ID comparisons across B, C, D and anonymous; median absolute timing delta 6.1 ms`; ownership: `77 comparisons; 0 denial failures`. - Media had one SLOW-only finding: the PDF worker list took 5.39 s with HTTP 200 against the probe's 5.0 s threshold. No hostile-input or 5xx finding remained. - Local `photos-perf.mjs --items 1 --home-only`: at load average 38.2/42.8/43, server start 2850 ms, indexed 4790 ms, mean/peak RSS 335424222/425738240 bytes, mean/peak CPU 23.37/95.95%, CPU 22.16 s. This one-photo local smoke is not comparable to the 5,000-photo perf VM baseline. ### Known gaps and decisions - Standalone IMAP tests retain the existing display expectation and fail `client::tests::test_parsing_error`; clippy passes. No test expectation was changed. - The final web test gate has the single five-second ThemePicker timeout above. The component and test are unchanged from origin/dev; this is reported as a gate failure. - Media's 5.39-second response is SLOW-only shared-host load. - DESIGN §35 does not specify an SSE event arriving before stable folder identity resolves. Decision: coalesce early events into one list refresh after resolution. DESIGN §47 L1 defines Account as Location consent owner; Auto uses the exact saved location. - Settings effects used Node 22 because Bun could not load host Sharp (`libstdc++.so.6` missing). No app code changed for the host workaround. ### Production screenshots The new Settings/Photos/Backgrounds matrix covers 390/820/1440 px in light and dark: [download review ZIP](https://git.kayg.org/attachments/ef08eb55-75be-4234-a946-b5557db27745). Existing full matrices: [Location](https://git.kayg.org/attachments/6078bc47-ceb1-4566-9b5e-63ef5c52b9a1), [Appearance/Notes/Photos/Log](https://git.kayg.org/attachments/2a0c2168-6199-4d45-9ff2-ad676518e88e), [Calendar feeds](https://git.kayg.org/attachments/03f5976a-28a3-4384-9aae-a995bac45409). Screenshots and logs are not committed.
Author
Owner

Merged into dev and deployed to calternal.cloud at aa372eef6 via merge round 2 (server tests 93 passed, web 914/914, live location/webcal/WebDAV/Settings-Photos/two-User probes passed).

Merged into dev and deployed to calternal.cloud at aa372eef6 via merge round 2 (server tests 93 passed, web 914/914, live location/webcal/WebDAV/Settings-Photos/two-User probes passed).
kayg closed this issue 2026-09-30 17:20:52 +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#391
No description provided.