MOTION: route repeated durations and easings through shared tokens #477

Closed
opened 2026-09-30 04:59:51 +00:00 by kayg · 20 comments
Owner

The 2026-09-30 consistency scan found 167 direct non-zero transition or animation times, up from 142 in the 2026-09-28 report (+25). It found 124 direct easing values, up from 105 (+19). The scan covers .css, .svelte, .scss, .less, .tsx and .ts source under apps/web/src, packages/ui/src and packages/editor/src, and excludes tests, generated output and the shared motion file.

Top files include NoteEditorSurface.svelte (6 direct times and 6 easing values), PhotoTimeline.svelte (6 times, 4 easings), GridColumn.svelte (6 and 6), and NoteProperties.svelte (5 and 5). These are source candidates; a one-off effect can remain local when the reason is documented.

Rule: the shared UI contract requires durations and easings to come from packages/ui/src/motion.ts. The shared spring language was set in #291, which is closed. #414 tracks animation performance traces, not token reuse.

Fix: map repeated roles to the shared motion tokens and helpers. Keep a documented local exception only where no shared role fits. Owner: packages/ui/src/motion.ts and the shared UI primitives that use it.

The 2026-09-30 consistency scan found 167 direct non-zero transition or animation times, up from 142 in the 2026-09-28 report (+25). It found 124 direct easing values, up from 105 (+19). The scan covers `.css`, `.svelte`, `.scss`, `.less`, `.tsx` and `.ts` source under `apps/web/src`, `packages/ui/src` and `packages/editor/src`, and excludes tests, generated output and the shared motion file. Top files include `NoteEditorSurface.svelte` (6 direct times and 6 easing values), `PhotoTimeline.svelte` (6 times, 4 easings), `GridColumn.svelte` (6 and 6), and `NoteProperties.svelte` (5 and 5). These are source candidates; a one-off effect can remain local when the reason is documented. Rule: the shared UI contract requires durations and easings to come from `packages/ui/src/motion.ts`. The shared spring language was set in #291, which is closed. #414 tracks animation performance traces, not token reuse. Fix: map repeated roles to the shared motion tokens and helpers. Keep a documented local exception only where no shared role fits. Owner: `packages/ui/src/motion.ts` and the shared UI primitives that use it.
Author
Owner

Starting work on branch job/motion-477, based on 0dc772c369 (base SHA). I am tracing the shared motion tokens, guard, and affected rendered animations before editing.

Starting work on branch job/motion-477, based on 0dc772c3697ea9bd01822c26440c32206d472715 (base SHA). I am tracing the shared motion tokens, guard, and affected rendered animations before editing.
Author
Owner

Source inspection confirms the four reported hotspots: NoteEditorSurface.svelte has six direct timing declarations, PhotoTimeline.svelte six, GridColumn.svelte six, and NoteProperties.svelte five. Shared tokens already cover 120/180/240 ms and the #291 spring, but the app stylesheet duplicates those roles and several repeated local values remain. I will preserve the old timing and CSS keyword easing behavior by centralizing exact existing values; this keeps the refactor visually neutral. Local single-use motion stays only with a nearby reason comment.

Source inspection confirms the four reported hotspots: NoteEditorSurface.svelte has six direct timing declarations, PhotoTimeline.svelte six, GridColumn.svelte six, and NoteProperties.svelte five. Shared tokens already cover 120/180/240 ms and the #291 spring, but the app stylesheet duplicates those roles and several repeated local values remain. I will preserve the old timing and CSS keyword easing behavior by centralizing exact existing values; this keeps the refactor visually neutral. Local single-use motion stays only with a nearby reason comment.
Author
Owner

Clarification after grouping the scanned values: native CSS ease/ease-out keywords will keep their exact curves through shared aliases; the repeated spring-like custom curves will converge on the existing #291 overdamped spring, which is an intended motion change. Single-use bespoke curves will keep their current values with a local exception reason. The before/after strips will cover the shared shell, Calendar, Files and Photos flows across all three widths and both themes.

Clarification after grouping the scanned values: native CSS ease/ease-out keywords will keep their exact curves through shared aliases; the repeated spring-like custom curves will converge on the existing #291 overdamped spring, which is an intended motion change. Single-use bespoke curves will keep their current values with a local exception reason. The before/after strips will cover the shared shell, Calendar, Files and Photos flows across all three widths and both themes.
Author
Owner

Finding: the baseline frame harness used the current wall time for “Motion spring evidence log” while its drag fixture occupied 09:00–10:30. At 10:25, a real local-server reproduction returned both log writes as 201 but rendered only the overlapping drag block; .block.actual did not expose the showcase log. I will pin the showcase fixture to 08:00, outside the drag interval, and keep the existing selector/assertion unchanged. This makes the required before/after strips stable across start times.

Finding: the baseline frame harness used the current wall time for “Motion spring evidence log” while its drag fixture occupied 09:00–10:30. At 10:25, a real local-server reproduction returned both log writes as 201 but rendered only the overlapping drag block; `.block.actual` did not expose the showcase log. I will pin the showcase fixture to 08:00, outside the drag interval, and keep the existing selector/assertion unchanged. This makes the required before/after strips stable across start times.
Author
Owner

Follow-up finding: the fixture fix allowed the baseline run to pass the Calendar and Files interactions at 390 px. It then stopped at the existing reduced-motion assertion: expected five navigation rows, got seven. The baseline bundle was built from the job's original 0dc772c base, while the capture harness is now from the merged origin/dev source. I will rebuild the before bundle from origin/dev and rerun the unchanged harness so both frame sets use the same UI revision; I will not change the assertion.

Follow-up finding: the fixture fix allowed the baseline run to pass the Calendar and Files interactions at 390 px. It then stopped at the existing reduced-motion assertion: expected five navigation rows, got seven. The baseline bundle was built from the job's original 0dc772c base, while the capture harness is now from the merged origin/dev source. I will rebuild the before bundle from origin/dev and rerun the unchanged harness so both frame sets use the same UI revision; I will not change the assertion.
Author
Owner

Finding: after rebuilding the baseline from origin/dev, the full capture hit the existing Settings scroll assertion (sawCollapsing false). A focused 390 px real-server reproduction showed the static Settings heading could appear before OverlaySurface's first scroll-effect update. The same scroll probe observed the collapse after two animation frames. I will add a two-frame settle before the existing capture action and keep its assertion unchanged.

Finding: after rebuilding the baseline from origin/dev, the full capture hit the existing Settings scroll assertion (`sawCollapsing` false). A focused 390 px real-server reproduction showed the static Settings heading could appear before OverlaySurface's first scroll-effect update. The same scroll probe observed the collapse after two animation frames. I will add a two-frame settle before the existing capture action and keep its assertion unchanged.
Author
Owner

Finding: the latest baseline run passed Calendar, Files and Settings, then timed out at upload-toast-dismiss. Playwright found the real Close button but kept waiting for pointer stability while UploadToast's 4-second success timer removed it (element was detached from the DOM). I will force-click the visible Close control in this capture-only action so its real handler runs before the short auto-dismiss; no UI code or assertion changes.

Finding: the latest baseline run passed Calendar, Files and Settings, then timed out at upload-toast-dismiss. Playwright found the real Close button but kept waiting for pointer stability while UploadToast's 4-second success timer removed it (`element was detached from the DOM`). I will force-click the visible Close control in this capture-only action so its real handler runs before the short auto-dismiss; no UI code or assertion changes.
Author
Owner

Finding: the latest baseline run passed the Calendar, Settings and upload-toast captures, then the existing reduced-motion check saw seven Search rows instead of five. The same exercise filled motion-spring earlier and reopens the shared Search window without clearing its retained win.query, so this was a result group from the prior query rather than the five-item empty-query Navigation group the assertions describe. I will clear the query before measuring and keep both expectations unchanged.

Finding: the latest baseline run passed the Calendar, Settings and upload-toast captures, then the existing reduced-motion check saw seven Search rows instead of five. The same exercise filled `motion-spring` earlier and reopens the shared Search window without clearing its retained `win.query`, so this was a result group from the prior query rather than the five-item empty-query Navigation group the assertions describe. I will clear the query before measuring and keep both expectations unchanged.
Author
Owner

Correction to the Search capture diagnosis: the empty query was correct. The real local production replay returned a “Navigate” group count of 7 with 5 visible rows because upstream added Mail and Money to the shell routes after this five-destination assertion was written. The existing assertion remains unchanged. API diagnostics showed that disabling Mail and Money for the capture user returns 204 for both; the empty-query state then reports Navigate 5 and 5 rendered rows. I updated the capture fixture to keep those optional modes disabled, select the Navigate group by label, and load the worktree production bundle through the local E2E asset route while the real server owns API data.

Correction to the Search capture diagnosis: the empty query was correct. The real local production replay returned a “Navigate” group count of 7 with 5 visible rows because upstream added Mail and Money to the shell routes after this five-destination assertion was written. The existing assertion remains unchanged. API diagnostics showed that disabling Mail and Money for the capture user returns 204 for both; the empty-query state then reports Navigate 5 and 5 rendered rows. I updated the capture fixture to keep those optional modes disabled, select the Navigate group by label, and load the worktree production bundle through the local E2E asset route while the real server owns API data.
Author
Owner

Capture finding: the sticky-title probe used a 700 ms time ramp and could skip the short overlap state when Chromium dropped frames. At 820 px in dark mode, a 639 px scroll with 16 px steps and two animation frames per step observed 13 collapse-marker updates; both 820 px baseline themes then completed. The probe still requires sawCollapsing === true.

The desktop upload close can race the toast's four-second auto-dismiss. I kept the completed-ring wait before frame sampling and shortened only the idle tail after the strip's final 780 ms sample (to 850 ms); the sampled frame times remain unchanged. The 1440 px baseline replay is running now.

Capture finding: the sticky-title probe used a 700 ms time ramp and could skip the short overlap state when Chromium dropped frames. At 820 px in dark mode, a 639 px scroll with 16 px steps and two animation frames per step observed 13 collapse-marker updates; both 820 px baseline themes then completed. The probe still requires `sawCollapsing === true`. The desktop upload close can race the toast's four-second auto-dismiss. I kept the completed-ring wait before frame sampling and shortened only the idle tail after the strip's final 780 ms sample (to 850 ms); the sampled frame times remain unchanged. The 1440 px baseline replay is running now.
Author
Owner

The upload close probe now arms a one-shot timer wrapper only after real ring progress starts. It extends the next four-second toast timeout to 30 seconds, restores the native setTimeout immediately, and leaves the toast DOM and 0–780 ms sampled frames unchanged. A real 1440×900 production-bundle replay completed a throttled 5 MiB upload, kept the Close button connected and visible after a 2.2 second frame interval, and dismissed the toast through its actual click handler.

The upload close probe now arms a one-shot timer wrapper only after real ring progress starts. It extends the next four-second toast timeout to 30 seconds, restores the native `setTimeout` immediately, and leaves the toast DOM and 0–780 ms sampled frames unchanged. A real 1440×900 production-bundle replay completed a throttled 5 MiB upload, kept the Close button connected and visible after a 2.2 second frame interval, and dismissed the toast through its actual click handler.
Author
Owner

Finished the #477 motion-token migration and committed the work on job/motion-477.

Built

  • Shared durations and easing roles in packages/ui/src/motion.ts and packages/ui/src/tokens.css. Reused the existing #236/#291 spring.
  • Routed repeated motion values in the web, UI and editor packages through those roles. Removed the duplicate web motion module and added a guard plus CSS/TypeScript parity tests.
  • Added production-build capture fixture repairs for the newly added Mail/Money routes, the Settings title probe and the upload toast timer. Those changes only affect E2E capture behavior.

Files

Key files: packages/ui/src/motion.ts, packages/ui/src/tokens.css, apps/web/src/calternal-app.css, apps/web/scripts/check-motion-tokens.mjs, apps/web/src/lib/styles/motion-token-check.test.js, and apps/web/e2e/motion-spring-evidence.mjs. Motion values were migrated across 83 source files in apps/web, packages/ui, and packages/editor; apps/web/src/lib/motion.ts was removed.

Visual evidence

Before strips attached:

Evidence is incomplete: the 1440 px dark baseline strip and all after strips were not captured within the job time limit. I cannot claim that the before/after visuals match.

Gates

bun run check:

$ node scripts/check-type-tokens.mjs && node scripts/check-motion-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
Text sizes and UI shape values use shared role tokens.
UI transitions and animation options use shared motion tokens or documented exceptions.
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/motion-477/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

bun run test:

$ vitest run

 RUN  v5.0.1 /home/kayg/Developer/calternal-wt/motion-477/apps/web

Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Could not parse CSS stylesheet
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
Not implemented: Window's scrollTo() method
 ❯ |component| src/routes/settings/mail/MailSection.svelte.test.ts (4 tests | 1 failed) 14708ms
   ❯ Settings → Mail account form (4)
     × keeps provider connection details behind Advanced 6087ms

⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯

 FAIL  |component| src/routes/settings/mail/MailSection.svelte.test.ts > Settings → Mail account form > keeps provider connection details behind Advanced
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".
 ❯ src/routes/settings/mail/MailSection.svelte.test.ts:17:3
     15|
     16| describe('Settings → Mail account form', () => {
     17|   it('keeps provider connection details behind Advanced', async () => {
       |   ^
     18|   apiFetch.mockImplementation((path: string) => path === '/api/v1/mail…
     19|    ? Promise.resolve({ read_marking: 'after_one_second' })

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯


 Test Files  1 failed | 137 passed (138)
      Tests  1 failed | 892 passed (893)
   Start at  14:02:48
   Duration  210.42s (transform 51%, environment 20%, import 15%, tests 9%, setup 4%)

Environment  |component| jsdom was created 43 times · 238.36s total, 28% of tracked time
             create it once per worker with pool: 'vmThreads' (keeps per-file isolation) or isolate: false (shares it across files)
             learn more: https://vitest.dev/guide/improving-performance#test-environments

error: script "test" exited with code 1

The full suite had one 5-second timeout in the unrelated Mail settings test. The isolated file passed all four tests:

$ vitest run src/routes/settings/mail/MailSection.svelte.test.ts

 RUN  v5.0.1 /home/kayg/Developer/calternal-wt/motion-477/apps/web


 Test Files  1 passed (1)
      Tests  4 passed (4)
   Start at  14:07:56
   Duration  26.25s (transform 80%, environment 8%, tests 5%, import 4%, setup 2%)

  Transform  |component| transforming modules took 19.20s · 80% of tracked time, re-done on every run
             persist transforms across runs with fsModuleCache: true
             learn more: https://vitest.dev/guide/improving-performance#caching-between-reruns

Commits and branch

Head: 70e6d4cdbee301b0859fd757798ed4acef3ddceb

Feature and capture commits: a83ec8484, a12de24fb, 7e8f68060, 70e6d4cdb.

The required upstream sync merged origin/dev through 5896bf2bc in 141b133f6. origin/dev advanced during this job; the current tracking status is 35 commits behind. I did not chase subsequent upstream changes.

Decisions

  • The production capture user disables optional Mail and Money plugins through the real API so the existing five-destination Search assertion remains unchanged after those routes were added upstream.
  • The E2E capture extends only the next four-second upload-toast timeout in the test page, then restores native setTimeout; the rendered UI and captured sample times remain unchanged.
  • No product motion decisions outside the existing DESIGN motion roles were introduced.

cargo clean completed and removed 4.4 GiB. I removed apps/web/build, .svelte-kit, and the temporary baseline worktree. The issue remains open.

Finished the #477 motion-token migration and committed the work on `job/motion-477`. **Built** - Shared durations and easing roles in `packages/ui/src/motion.ts` and `packages/ui/src/tokens.css`. Reused the existing #236/#291 spring. - Routed repeated motion values in the web, UI and editor packages through those roles. Removed the duplicate web motion module and added a guard plus CSS/TypeScript parity tests. - Added production-build capture fixture repairs for the newly added Mail/Money routes, the Settings title probe and the upload toast timer. Those changes only affect E2E capture behavior. **Files** Key files: `packages/ui/src/motion.ts`, `packages/ui/src/tokens.css`, `apps/web/src/calternal-app.css`, `apps/web/scripts/check-motion-tokens.mjs`, `apps/web/src/lib/styles/motion-token-check.test.js`, and `apps/web/e2e/motion-spring-evidence.mjs`. Motion values were migrated across 83 source files in `apps/web`, `packages/ui`, and `packages/editor`; `apps/web/src/lib/motion.ts` was removed. **Visual evidence** Before strips attached: - [390 px · light](https://git.kayg.org/attachments/916547b9-744b-4b68-9099-f33cffba13ea) - [390 px · dark](https://git.kayg.org/attachments/4588c84c-9f82-45cc-9aa7-751377e94685) - [820 px · light](https://git.kayg.org/attachments/53ccabe1-1af7-4e4c-be94-dd9a1f41024a) - [820 px · dark](https://git.kayg.org/attachments/459d6da4-55ff-4df6-b7a2-1f5ca94c951c) - [1440 px · light](https://git.kayg.org/attachments/646a619f-09fe-4346-9323-eb62800fe706) Evidence is incomplete: the 1440 px dark baseline strip and all after strips were not captured within the job time limit. I cannot claim that the before/after visuals match. **Gates** `bun run check`: ```text $ node scripts/check-type-tokens.mjs && node scripts/check-motion-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json Text sizes and UI shape values use shared role tokens. UI transitions and animation options use shared motion tokens or documented exceptions. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/motion-477/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `bun run test`: ```text $ vitest run RUN v5.0.1 /home/kayg/Developer/calternal-wt/motion-477/apps/web Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Could not parse CSS stylesheet Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method Not implemented: Window's scrollTo() method ❯ |component| src/routes/settings/mail/MailSection.svelte.test.ts (4 tests | 1 failed) 14708ms ❯ Settings → Mail account form (4) × keeps provider connection details behind Advanced 6087ms ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯ FAIL |component| src/routes/settings/mail/MailSection.svelte.test.ts > Settings → Mail account form > keeps provider connection details behind Advanced 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". ❯ src/routes/settings/mail/MailSection.svelte.test.ts:17:3 15| 16| describe('Settings → Mail account form', () => { 17| it('keeps provider connection details behind Advanced', async () => { | ^ 18| apiFetch.mockImplementation((path: string) => path === '/api/v1/mail… 19| ? Promise.resolve({ read_marking: 'after_one_second' }) ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯ Test Files 1 failed | 137 passed (138) Tests 1 failed | 892 passed (893) Start at 14:02:48 Duration 210.42s (transform 51%, environment 20%, import 15%, tests 9%, setup 4%) Environment |component| jsdom was created 43 times · 238.36s total, 28% of tracked time create it once per worker with pool: 'vmThreads' (keeps per-file isolation) or isolate: false (shares it across files) learn more: https://vitest.dev/guide/improving-performance#test-environments error: script "test" exited with code 1 ``` The full suite had one 5-second timeout in the unrelated Mail settings test. The isolated file passed all four tests: ```text $ vitest run src/routes/settings/mail/MailSection.svelte.test.ts RUN v5.0.1 /home/kayg/Developer/calternal-wt/motion-477/apps/web Test Files 1 passed (1) Tests 4 passed (4) Start at 14:07:56 Duration 26.25s (transform 80%, environment 8%, tests 5%, import 4%, setup 2%) Transform |component| transforming modules took 19.20s · 80% of tracked time, re-done on every run persist transforms across runs with fsModuleCache: true learn more: https://vitest.dev/guide/improving-performance#caching-between-reruns ``` **Commits and branch** Head: `70e6d4cdbee301b0859fd757798ed4acef3ddceb` Feature and capture commits: `a83ec8484`, `a12de24fb`, `7e8f68060`, `70e6d4cdb`. The required upstream sync merged `origin/dev` through `5896bf2bc` in `141b133f6`. `origin/dev` advanced during this job; the current tracking status is 35 commits behind. I did not chase subsequent upstream changes. **Decisions** - The production capture user disables optional Mail and Money plugins through the real API so the existing five-destination Search assertion remains unchanged after those routes were added upstream. - The E2E capture extends only the next four-second upload-toast timeout in the test page, then restores native `setTimeout`; the rendered UI and captured sample times remain unchanged. - No product motion decisions outside the existing DESIGN motion roles were introduced. `cargo clean` completed and removed 4.4 GiB. I removed `apps/web/build`, `.svelte-kit`, and the temporary baseline worktree. The issue remains open.
Author
Owner

Correction: the final local status check refreshed the tracking ref and now shows ahead 11, behind 38 on (the posted report recorded behind 35). I did not merge further upstream changes.

Correction: the final local status check refreshed the tracking ref and now shows ahead 11, behind 38 on (the posted report recorded behind 35). I did not merge further upstream changes.
Author
Owner

Correction: the final local status check refreshed the tracking ref and now shows job/motion-477 ahead 11, behind 38 on origin/dev (the posted report recorded behind 35). I did not merge further upstream changes.

Correction: the final local status check refreshed the tracking ref and now shows `job/motion-477` ahead 11, behind 38 on `origin/dev` (the posted report recorded behind 35). I did not merge further upstream changes.
Author
Owner

Resuming #477 on job/motion-477 at 70e6d4cdb. The fetched merge target is origin/dev at 1aaefe288f306498e7757848c50e9988b0e08044. I am merging that branch now, preserving the settings route changes on both sides, then I will rerun the motion token guard, web checks, and the requested animation frame comparisons.

Resuming #477 on `job/motion-477` at `70e6d4cdb`. The fetched merge target is `origin/dev` at `1aaefe288f306498e7757848c50e9988b0e08044`. I am merging that branch now, preserving the settings route changes on both sides, then I will rerun the motion token guard, web checks, and the requested animation frame comparisons.
Author
Owner

Adversarial finding: tests/adversarial/search_chaos.py expected the admin staged rebuild request to return HTTP 200. It received HTTP 202 with a job_id and inserted: true, so the probe reported FAIL search chaos. I left the existing status assertion unchanged. I am checking the merged API contract and implementation before treating this as a product regression; the expected status may be stale after the upstream rebuild behavior change.

Adversarial finding: `tests/adversarial/search_chaos.py` expected the admin staged rebuild request to return HTTP 200. It received HTTP 202 with a `job_id` and `inserted: true`, so the probe reported `FAIL search chaos`. I left the existing status assertion unchanged. I am checking the merged API contract and implementation before treating this as a product regression; the expected status may be stale after the upstream rebuild behavior change.
Author
Owner

Adversarial finding from the one local round: the server log records thread 'tokio-rt-worker' has overflowed its stack followed by fatal runtime error: stack overflow, aborting at 2026-09-30 13:53:19 UTC. The server exited. Later probes returned 502 because the local server was unavailable, so those are cascade failures. I stopped the runner after the cascade; the captured, redacted log is being attached to the existing watcher-overflow issue #325 for comparison. The shared host had other build and server-test jobs running, and the broad round did not isolate the triggering request.

The search chaos probe also expects HTTP 200 from admin staged rebuild. contracts/openapi.json documents 202 JobTriggerReceipt, and rebuild_search_index returns 202. I left the old assertion unchanged, as required, and am reporting it for owner review. I created #519 before finding the existing #325; #519 may be a duplicate and is cross-referenced there.

Adversarial finding from the one local round: the server log records `thread 'tokio-rt-worker' has overflowed its stack` followed by `fatal runtime error: stack overflow, aborting` at 2026-09-30 13:53:19 UTC. The server exited. Later probes returned 502 because the local server was unavailable, so those are cascade failures. I stopped the runner after the cascade; the captured, redacted log is being attached to the existing watcher-overflow issue #325 for comparison. The shared host had other build and server-test jobs running, and the broad round did not isolate the triggering request. The search chaos probe also expects HTTP 200 from admin staged rebuild. `contracts/openapi.json` documents 202 `JobTriggerReceipt`, and `rebuild_search_index` returns 202. I left the old assertion unchanged, as required, and am reporting it for owner review. I created #519 before finding the existing #325; #519 may be a duplicate and is cross-referenced there.
Author
Owner

Built

Merged the fetched origin/dev snapshot (1aaefe288f306498e7757848c50e9988b0e08044) and resolved the settings conflict. The phone list keeps the upstream FloatingSidebar and focus behavior; the duplicate .master/.row rules are removed. The deep-link opt-flash keeps the shared motion roles --dur-highlight and --ease-standard-out, with reduced-motion handling intact. The post-merge scan found no unconverted transition or animation literals.

Owned resolution file: apps/web/src/routes/settings/[...path]/+page.svelte. Head: b62297fa0d5e22dd70b1263027d3a6527c5dc476.

Visual evidence

Settings screenshots cover admin and member at 390, 820 and 1440 px in light and dark themes:

Width Admin Member
390 light · dark light · dark
820 light · dark light · dark
1440 light · dark light · dark

Before/after strips for three representative animations are attached: segmented control before / after, search open before / after, composer open before / after. The pre-merge set did not include 1440 px dark mode, so its comparisons contain five viewport/theme pairs; the post-merge set contains all six. These are attached for the visual reviewer.

Gates

bun run check:

$ node scripts/check-type-tokens.mjs && node scripts/check-motion-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
Text sizes and UI shape values use shared role tokens.
UI transitions and animation options use shared motion tokens or documented exceptions.
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/motion-477/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

bun run test:

$ vitest run

 RUN  v5.0.1 /home/kayg/Developer/calternal-wt/motion-477/apps/web

 Test Files  138 passed (138)
      Tests  897 passed (897)
   Start at  14:32:01
   Duration  85.72s (transform 53%, import 18%, environment 15%, tests 10%, setup 3%)

Environment  |component| jsdom was created 43 times · 71.49s total, 26% of tracked time
   create it once per worker with pool: 'vmThreads' (keeps per-file isolation) or isolate: false (shares it across files)
   learn more: https://vitest.dev/guide/improving-performance#test-environments

bun run build completed and wrote the site. It emitted existing module-level use client directive warnings from framer-motion and bklit. The server binary build also succeeded for local E2E work. No Rust crate was changed, so per-crate Rust clippy/test gates did not apply. cargo clean removed 7,067 files (4.4 GiB), and web build output was removed.

Adversarial findings and gaps

The single local hostile-input round ran for about 25 minutes. Its captured log records thread 'tokio-rt-worker' has overflowed its stack and fatal runtime error: stack overflow, aborting at 2026-09-30 13:53:19 UTC. Later requests cascaded into 502 responses because the server was unavailable. Other jobs were compiling and testing on the shared host. I stopped the round after the crash cascade; later probe results are incomplete. The redacted log is attached to #325. A new issue, #519, may duplicate #325; I left both open and cross-referenced them.

The search chaos probe expects HTTP 200 from staged rebuild, but the OpenAPI contract and rebuild_search_index route both specify HTTP 202 with JobTriggerReceipt; the run returned 202. I left the test expectation unchanged and filed #520 for owner review. The run later attempted dedup CLI probes, but calternal was not built because only calternal-server was supplied; those probes did not run successfully. No server fix is included in this UI job.

No bench/ profile was added: this job consolidates existing motion roles and does not add a route, background job, or product feature. No performance numbers were taken.

Decisions

The merged phone settings list uses the upstream shared FloatingSidebar; its duplicate local row styles were removed. Motion values remain on shared roles and the opt-flash still disables under reduced motion. The absent pre-merge 1440 px dark strip is reported above rather than inferred from the post-merge capture.

## Built Merged the fetched `origin/dev` snapshot (`1aaefe288f306498e7757848c50e9988b0e08044`) and resolved the settings conflict. The phone list keeps the upstream `FloatingSidebar` and focus behavior; the duplicate `.master`/`.row` rules are removed. The deep-link opt-flash keeps the shared motion roles `--dur-highlight` and `--ease-standard-out`, with reduced-motion handling intact. The post-merge scan found no unconverted transition or animation literals. Owned resolution file: `apps/web/src/routes/settings/[...path]/+page.svelte`. Head: `b62297fa0d5e22dd70b1263027d3a6527c5dc476`. ## Visual evidence Settings screenshots cover admin and member at 390, 820 and 1440 px in light and dark themes: | Width | Admin | Member | | --- | --- | --- | | 390 | [light](https://git.kayg.org/attachments/7a160304-0302-4382-9c78-903d6ac18979) · [dark](https://git.kayg.org/attachments/5af7425b-6338-42e4-984e-afb5aa2756eb) | [light](https://git.kayg.org/attachments/a7120891-4cd0-46bd-a4a2-64c7286007de) · [dark](https://git.kayg.org/attachments/ef573686-3cb2-4f31-966e-7dd74dbcf434) | | 820 | [light](https://git.kayg.org/attachments/f426734f-46db-432b-b93b-a3f08f6c638f) · [dark](https://git.kayg.org/attachments/1351b5c4-9e87-447b-8666-ab9c5828b41b) | [light](https://git.kayg.org/attachments/2f3d9761-9f64-477b-8bc4-5c60d4ef9863) · [dark](https://git.kayg.org/attachments/af69a6eb-c310-4e72-8500-c647d287cd5b) | | 1440 | [light](https://git.kayg.org/attachments/1133aeeb-f0ef-4b46-b1cc-fb7144d37fd9) · [dark](https://git.kayg.org/attachments/98f71e9a-83a3-4220-b18b-3ecb7bf6e7ca) | [light](https://git.kayg.org/attachments/931634f8-a1a1-4d46-b9bb-f928404258d9) · [dark](https://git.kayg.org/attachments/7a3e665a-f91c-45aa-8cbd-bc8bb1a90d00) | Before/after strips for three representative animations are attached: segmented control [before](https://git.kayg.org/attachments/cd36d090-1867-4a69-b499-3700b1b3887a) / [after](https://git.kayg.org/attachments/cbb2200d-ce61-41e6-a47a-5d7787a3b52f), search open [before](https://git.kayg.org/attachments/07c6971f-1989-4af9-8733-865dd766069a) / [after](https://git.kayg.org/attachments/878d208b-33f8-4955-8275-f4bb06a9b959), composer open [before](https://git.kayg.org/attachments/d5387008-0ac8-4e26-b24c-b5bb18d94cda) / [after](https://git.kayg.org/attachments/57cec6d1-df5d-4904-b295-57c9bf14e57d). The pre-merge set did not include 1440 px dark mode, so its comparisons contain five viewport/theme pairs; the post-merge set contains all six. These are attached for the visual reviewer. ## Gates `bun run check`: ```text $ node scripts/check-type-tokens.mjs && node scripts/check-motion-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json Text sizes and UI shape values use shared role tokens. UI transitions and animation options use shared motion tokens or documented exceptions. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/motion-477/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `bun run test`: ```text $ vitest run RUN v5.0.1 /home/kayg/Developer/calternal-wt/motion-477/apps/web Test Files 138 passed (138) Tests 897 passed (897) Start at 14:32:01 Duration 85.72s (transform 53%, import 18%, environment 15%, tests 10%, setup 3%) Environment |component| jsdom was created 43 times · 71.49s total, 26% of tracked time create it once per worker with pool: 'vmThreads' (keeps per-file isolation) or isolate: false (shares it across files) learn more: https://vitest.dev/guide/improving-performance#test-environments ``` `bun run build` completed and wrote the site. It emitted existing module-level `use client` directive warnings from `framer-motion` and `bklit`. The server binary build also succeeded for local E2E work. No Rust crate was changed, so per-crate Rust clippy/test gates did not apply. `cargo clean` removed 7,067 files (4.4 GiB), and web build output was removed. ## Adversarial findings and gaps The single local hostile-input round ran for about 25 minutes. Its captured log records `thread 'tokio-rt-worker' has overflowed its stack` and `fatal runtime error: stack overflow, aborting` at 2026-09-30 13:53:19 UTC. Later requests cascaded into 502 responses because the server was unavailable. Other jobs were compiling and testing on the shared host. I stopped the round after the crash cascade; later probe results are incomplete. The redacted log is attached to [#325](https://git.kayg.org/kayg/calternal/issues/325). A new issue, [#519](https://git.kayg.org/kayg/calternal/issues/519), may duplicate #325; I left both open and cross-referenced them. The search chaos probe expects HTTP 200 from staged rebuild, but the OpenAPI contract and `rebuild_search_index` route both specify HTTP 202 with `JobTriggerReceipt`; the run returned 202. I left the test expectation unchanged and filed [#520](https://git.kayg.org/kayg/calternal/issues/520) for owner review. The run later attempted dedup CLI probes, but `calternal` was not built because only `calternal-server` was supplied; those probes did not run successfully. No server fix is included in this UI job. No `bench/` profile was added: this job consolidates existing motion roles and does not add a route, background job, or product feature. No performance numbers were taken. ## Decisions The merged phone settings list uses the upstream shared `FloatingSidebar`; its duplicate local row styles were removed. Motion values remain on shared roles and the opt-flash still disables under reduced motion. The absent pre-merge 1440 px dark strip is reported above rather than inferred from the post-merge capture.
Author
Owner

Correction to the gate note in my previous report: the merged origin/dev tree changed contracts/openapi.json, so the calternal-server gates applied. I ran them after noticing the contract change.

The first clippy attempt failed because I had removed apps/web/build, which the server embeds with RustEmbed. I rebuilt the web bundle and reran clippy successfully. This was a missing build prerequisite, not a Rust diagnostic.

cargo fmt --check completed with exit 0 and no output.

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

Finished `dev` profile [unoptimized + debuginfo] target(s) in 57.10s

cargo test -p calternal-server:

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

Final cargo clean output:

Removed 12965 files, 5.5GiB total
removed apps/web/build
removed apps/web/.svelte-kit/output
Correction to the gate note in my previous report: the merged `origin/dev` tree changed `contracts/openapi.json`, so the `calternal-server` gates applied. I ran them after noticing the contract change. The first clippy attempt failed because I had removed `apps/web/build`, which the server embeds with `RustEmbed`. I rebuilt the web bundle and reran clippy successfully. This was a missing build prerequisite, not a Rust diagnostic. `cargo fmt --check` completed with exit 0 and no output. `cargo clippy -p calternal-server --all-targets -- -D warnings`: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 57.10s ``` `cargo test -p calternal-server`: ```text test result: ok. 85 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 50.48s ``` Final `cargo clean` output: ```text Removed 12965 files, 5.5GiB total removed apps/web/build removed apps/web/.svelte-kit/output ```
Author
Owner

Merged into dev at 9ecde429a (merged-tree web gates 0 errors, 904/904).

Merged into dev at 9ecde429a (merged-tree web gates 0 errors, 904/904).
kayg closed this issue 2026-09-30 15:10:20 +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#477
No description provided.