Calendar e2e: composer snapshot gets a stray 'n' ('05:18 nFrozen snapshot'); drag label off by snapping #569

Open
opened 2026-10-01 03:42:41 +00:00 by kayg · 14 comments
Owner

Found by esc-537 (2026-10-01), in the full Calendar e2e on a branch from dev cc25c441b

  1. Composer snapshot: expected Frozen snapshot, got 05:18 nFrozen snapshot. A stray n appears after the time. This looks like a literal \n being unescaped as the letter n (an escape bug in the composer's serialisation or the test's input), or a time-prefix parse leak. The owner reported a related composer title bug earlier ("on and off working on calternal.js
  2. Drag-only run: time label 08:45 – 09:45, expected 08:30 – 09:15. Is this the new snapping (#536 snaps to item edges and "now") changing a drag the test assumed snaps to 15 min, or a real bug? If it is the snapping, update the test to place the drag away from other items, or turn snapping off for that case, and assert the snapped result explicitly.
    Job: reproduce both on dev (after merge round 4 lands), fix the product if it is a product bug (with a regression test against the written Markdown), or fix the test with an explanation. Web gates + the Calendar e2e.
## Found by esc-537 (2026-10-01), in the full Calendar e2e on a branch from dev cc25c441b 1. **Composer snapshot:** expected ` Frozen snapshot`, got `05:18 nFrozen snapshot`. A stray `n` appears after the time. This looks like a literal `\n` being unescaped as the letter `n` (an escape bug in the composer's serialisation or the test's input), or a time-prefix parse leak. The owner reported a related composer title bug earlier ("on and off working on calternal.js <time> <tags>" lost words). Find out whether the product writes `n` into the Log (a data bug: check the Markdown written to Home), or only the test input is wrong. 2. **Drag-only run:** time label `08:45 – 09:45`, expected `08:30 – 09:15`. Is this the new snapping (#536 snaps to item edges and "now") changing a drag the test assumed snaps to 15 min, or a real bug? If it is the snapping, update the test to place the drag away from other items, or turn snapping off for that case, and assert the snapped result explicitly. **Job:** reproduce both on dev (after merge round 4 lands), fix the product if it is a product bug (with a regression test against the written Markdown), or fix the test with an explanation. Web gates + the Calendar e2e.
Author
Owner

#427 confirms the Calendar full E2E stops at the same nFrozen snapshot assertion after passing both corrected stored-Tag edit checks. #569 already reproduces this on production cc25c441b: classify as pre-existing, leave the snapshot expectation unchanged. The focused edit test passed both paths with the real canonical #area/work Tag value (DESIGN §31, CONTEXT); the old #work assertion discarded its stored namespace.

#427 confirms the Calendar full E2E stops at the same `nFrozen snapshot` assertion after passing both corrected stored-Tag edit checks. #569 already reproduces this on production cc25c441b: classify as pre-existing, leave the snapshot expectation unchanged. The focused edit test passed both paths with the real canonical `#area/work` Tag value (DESIGN §31, CONTEXT); the old `#work` assertion discarded its stored namespace.
Author
Owner

Started issue #569 on branch job/cal-e2e-569, based at 1af8ead262daf0a4ad22a60564dc75bab0005cf4 (merge-round-4 snapshot). I will reproduce the Composer Markdown output and Calendar drag snapping on current origin/dev, then fix the product or e2e assertions based on the evidence.

Started issue #569 on branch `job/cal-e2e-569`, based at `1af8ead262daf0a4ad22a60564dc75bab0005cf4` (merge-round-4 snapshot). I will reproduce the Composer Markdown output and Calendar drag snapping on current `origin/dev`, then fix the product or e2e assertions based on the evidence.
Author
Owner

Current origin/dev reproduction (production SPA, real local server, browser clock 05:18 Europe/Berlin) fails with the exact payload 05:18 nFrozen snapshot. In apps/web/e2e/calendar.mjs, the test leaves the empty Composer open after the assertion at line 1360, then calls openComposer() again at line 1379; that helper presses n while the text box is already focused. The test is likely typing its own shortcut into the Log title. I am checking the resulting Daily note Markdown before fixing the test.

Current `origin/dev` reproduction (production SPA, real local server, browser clock 05:18 Europe/Berlin) fails with the exact payload `05:18 nFrozen snapshot`. In `apps/web/e2e/calendar.mjs`, the test leaves the empty Composer open after the assertion at line 1360, then calls `openComposer()` again at line 1379; that helper presses `n` while the text box is already focused. The test is likely typing its own shortcut into the Log title. I am checking the resulting Daily note Markdown before fixing the test.
Author
Owner

Confirmed the bad n is written only because the test puts it in the field. The failing e2e's real GET /api/v1/files/download?path=Notes/20260930-dailynote.md returned - 05:18 [tz=Europe/Berlin] nFrozen snapshot ^…. The redundant openComposer() call presses n while the existing Composer is focused. I will keep that Composer open, assert its input before Send, and check the saved Markdown line against the projected Log entry ID.

Confirmed the bad `n` is written only because the test puts it in the field. The failing e2e's real `GET /api/v1/files/download?path=Notes/20260930-dailynote.md` returned `- 05:18 [tz=Europe/Berlin] nFrozen snapshot ^…`. The redundant `openComposer()` call presses `n` while the existing Composer is focused. I will keep that Composer open, assert its input before Send, and check the saved Markdown line against the projected Log entry ID.
Author
Owner

After the #569 Composer-input correction, the full production Calendar e2e passes the frozen request and Daily note Markdown checks. It then reaches the existing inline Log edit and times out at the assertion waiting for Morning review of the plan (apps/web/e2e/calendar.mjs, the Save changes flow in section 6b). I am checking the captured PATCH and saved Journal bytes because this may be the related title bug in the issue description.

After the #569 Composer-input correction, the full production Calendar e2e passes the frozen request and Daily note Markdown checks. It then reaches the existing inline Log edit and times out at the assertion waiting for `Morning review of the plan` (`apps/web/e2e/calendar.mjs`, the `Save changes` flow in section 6b). I am checking the captured PATCH and saved Journal bytes because this may be the related title bug in the issue description.
Author
Owner

The inline edit diagnosis is specific: the saved Log was on 2026-10-01; its Save changes PATCH carries title Morning review of the plan and times 09:00–11:00 but changes date to 2026-10-02. The Journal projection and Markdown for 2026-10-01 therefore do not contain the edited entry. This is a real edit behavior issue; I am tracing the Composer's source-date handling before fixing it.

The inline edit diagnosis is specific: the saved Log was on `2026-10-01`; its `Save changes` PATCH carries title `Morning review of the plan` and times 09:00–11:00 but changes `date` to `2026-10-02`. The Journal projection and Markdown for 2026-10-01 therefore do not contain the edited entry. This is a real edit behavior issue; I am tracing the Composer's source-date handling before fixing it.
Author
Owner

Root cause found: Calendar's Log edit callback used entry.date ?? date. The parser returns today's date for a bare time, so a time-only edit of an older Log moved it to today. I changed the callback to reuse the existing landingDate rule: the source Daily note stays selected unless the parsed date is a different explicit day. This is a small behavior choice not stated directly in DESIGN; it matches new Log date handling and the Composer's momentOf rule.

Root cause found: Calendar's Log edit callback used `entry.date ?? date`. The parser returns today's date for a bare time, so a time-only edit of an older Log moved it to today. I changed the callback to reuse the existing `landingDate` rule: the source Daily note stays selected unless the parsed date is a different explicit day. This is a small behavior choice not stated directly in DESIGN; it matches new Log date handling and the Composer's `momentOf` rule.
Author
Owner

E2E finding for #569: the pre-existing repair fixture downloaded Notes/<date>-dailynote.md but uploaded it under Notes/Journal/. This made a second Daily note for the same date; the journal endpoint then returned HTTP 409 (multiple Daily notes use the same date), so the repair action could not appear. The fixture now replaces the source Daily note under Notes/.

E2E finding for #569: the pre-existing repair fixture downloaded `Notes/<date>-dailynote.md` but uploaded it under `Notes/Journal/`. This made a second Daily note for the same date; the journal endpoint then returned HTTP 409 (`multiple Daily notes use the same date`), so the repair action could not appear. The fixture now replaces the source Daily note under `Notes/`.
Author
Owner

Follow-up #569 test finding: after fixing the wrong folder, replacing the already-edited Daily note received HTTP 412 (upload destination changed). The Files API correctly rejected the stale revision rather than overwriting it. The repair test now creates a fresh Daily note through tus under Notes/ and uses that file for the repair action, so it tests the same behavior without racing a checked overwrite.

Follow-up #569 test finding: after fixing the wrong folder, replacing the already-edited Daily note received HTTP 412 (`upload destination changed`). The Files API correctly rejected the stale revision rather than overwriting it. The repair test now creates a fresh Daily note through tus under `Notes/` and uses that file for the repair action, so it tests the same behavior without racing a checked overwrite.
Author
Owner

Calendar e2e finding for #569: the full run now passes the Composer Markdown regression, source-day inline edit and repair fixture. It then stopped because the cross-midnight test selected both rendered parts of the same Log entry (current day and adjacent-day continuation). The test now scopes the block to the night date column, preserving its midnight-boundary assertions.

Calendar e2e finding for #569: the full run now passes the Composer Markdown regression, source-day inline edit and repair fixture. It then stopped because the cross-midnight test selected both rendered parts of the same Log entry (current day and adjacent-day continuation). The test now scopes the block to the `night` date column, preserving its midnight-boundary assertions.
Author
Owner

Calendar e2e progress for #569: the Composer snapshot, inline edit's written Markdown, repair action and cross-midnight checks passed. The full run then stopped at the existing future-Composer assertion in apps/web/e2e/calendar.mjs:1692: it expects “A log entry is for now or earlier”, while apps/web/src/lib/composer/Composer.svelte:1091 currently announces “A Journal entry is for now or earlier”. I left the assertion unchanged because the #569 issue does not change that behavior.

Calendar e2e progress for #569: the Composer snapshot, inline edit's written Markdown, repair action and cross-midnight checks passed. The full run then stopped at the existing future-Composer assertion in `apps/web/e2e/calendar.mjs:1692`: it expects “A log entry is for now or earlier”, while `apps/web/src/lib/composer/Composer.svelte:1091` currently announces “A Journal entry is for now or earlier”. I left the assertion unchanged because the #569 issue does not change that behavior.
Author
Owner

Finished #569.

Head: 96908cbef8bbf078ce73bbc1a51f432ba8c416c8 (fix Calendar Log edits retain source Daily note).

Built:

  • Calendar Log inline edits now use the existing landingDate rule. An edit with only a time stays on its source Daily note; an explicitly entered date still applies.
  • The Composer snapshot e2e no longer sends a second n shortcut into the open title field. It checks the field before sending, waits for the server write, then verifies the saved Daily note Markdown by block ID.
  • Calendar e2e geometry cases set snapping explicitly, wait for the rendered range after writes, and scope the overnight block to its source date. The repair fixture now creates a fresh Daily note under Notes/ through Files and reconciles it.

Files: apps/web/src/routes/calendar/[view]/[date]/+page.svelte, apps/web/e2e/calendar.mjs.

Web gates:

bun run check output:

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

svelte-check found 0 errors and 0 warnings

bun run test final output:

 Test Files  148 passed (148)
      Tests  1011 passed (1011)
   Start at  02:00:25
   Duration  45.07s (transform 46%, environment 20%, import 18%, tests 12%, setup 4%)

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

Calendar e2e:

  • Focused drag run at 2026-10-02T06:45:00Z passed: calendar drag e2e: live labels and touch drag passed.
  • The full Calendar run passed the #569 Composer Markdown, source-day edit, repair, and cross-midnight checks. It then stopped at the existing future-Composer assertion. Output:
TimeoutError: waitFor: Timeout 30000ms exceeded.
Call log:
  - waiting for getByText('A log entry is for now or earlier') to be visible

The assertion expects “A log entry is for now or earlier”; current Composer source says “A Journal entry is for now or earlier” (Composer.svelte:1091). I left the existing assertion unchanged because #569 does not change that behavior.

Local Calendar snap profile (host load average 13.6, 12.84, 16.5): average 400 edges / 2,000 calls p50 4.24 µs, p95 17.98 µs, CPU 0.0193 s, RSS 23.0→32.4 MB; worst 10,000 edges / 1,000 calls p50 42.36 µs, p95 86.16 µs, CPU 0.0538 s; 2,000-call burst CPU 0.0924 s, RSS 35.5 MB. The snap resolver did not change; this local profile is contextual.

Decisions: For a time-only inline edit, keep the source Daily note date, matching the existing Composer landingDate rule. The empty-grid drag baseline disables snap-to-now; the dedicated snap-to-now case continues to cover that preference. No Rust files or API contracts changed. cargo clean completed: Removed 7237 files, 4.6GiB total.

Finished #569. Head: `96908cbef8bbf078ce73bbc1a51f432ba8c416c8` (`fix Calendar Log edits retain source Daily note`). Built: - Calendar Log inline edits now use the existing `landingDate` rule. An edit with only a time stays on its source Daily note; an explicitly entered date still applies. - The Composer snapshot e2e no longer sends a second `n` shortcut into the open title field. It checks the field before sending, waits for the server write, then verifies the saved Daily note Markdown by block ID. - Calendar e2e geometry cases set snapping explicitly, wait for the rendered range after writes, and scope the overnight block to its source date. The repair fixture now creates a fresh Daily note under `Notes/` through Files and reconciles it. Files: `apps/web/src/routes/calendar/[view]/[date]/+page.svelte`, `apps/web/e2e/calendar.mjs`. Web gates: `bun run check` output: ``` $ node scripts/check-user-storage.mjs && node scripts/check-type-tokens.mjs && node scripts/check-motion-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json User browser caches use userStorage; only documented device/public-link exceptions remain. Text sizes and UI shape values use shared role tokens. UI transitions and animation options use shared motion tokens or documented exceptions. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/cal-e2e-569/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `bun run test` final output: ``` Test Files 148 passed (148) Tests 1011 passed (1011) Start at 02:00:25 Duration 45.07s (transform 46%, environment 20%, import 18%, tests 12%, setup 4%) Environment |component| jsdom was created 46 times · 47.26s total, 29% of tracked time create it once per worker with pool: 'vmThreads' (keeps per-file isolation) or isolate: false (shares state across files) learn more: https://vitest.dev/guide/improving-performance#test-environments ``` Calendar e2e: - Focused drag run at `2026-10-02T06:45:00Z` passed: `calendar drag e2e: live labels and touch drag passed`. - The full Calendar run passed the #569 Composer Markdown, source-day edit, repair, and cross-midnight checks. It then stopped at the existing future-Composer assertion. Output: ``` TimeoutError: waitFor: Timeout 30000ms exceeded. Call log: - waiting for getByText('A log entry is for now or earlier') to be visible ``` The assertion expects “A log entry is for now or earlier”; current Composer source says “A Journal entry is for now or earlier” (`Composer.svelte:1091`). I left the existing assertion unchanged because #569 does not change that behavior. Local Calendar snap profile (host load average 13.6, 12.84, 16.5): average 400 edges / 2,000 calls p50 4.24 µs, p95 17.98 µs, CPU 0.0193 s, RSS 23.0→32.4 MB; worst 10,000 edges / 1,000 calls p50 42.36 µs, p95 86.16 µs, CPU 0.0538 s; 2,000-call burst CPU 0.0924 s, RSS 35.5 MB. The snap resolver did not change; this local profile is contextual. Decisions: For a time-only inline edit, keep the source Daily note date, matching the existing Composer `landingDate` rule. The empty-grid drag baseline disables snap-to-now; the dedicated snap-to-now case continues to cover that preference. No Rust files or API contracts changed. `cargo clean` completed: `Removed 7237 files, 4.6GiB total`.
Author
Owner

#569 performance addendum, compared with docs/perf/baseline.json → calendar_snap_536:

  • Average (400 edges, 2,000 calls): p50 4.24 µs vs 4.36 µs baseline; p95 17.98 µs vs 13.27 µs; CPU 0.0193 s vs 0.0176 s; RSS 23,031,808→32,395,264 bytes vs 21,917,696→31,207,424 bytes.
  • Worst (10,000 edges, 1,000 calls): p50 42.36 µs vs 41.44 µs; p95 86.16 µs vs 70.17 µs; CPU 0.0538 s vs 0.0494 s. The 2,000-call burst used 0.0924 s CPU vs 0.1011 s and 35,495,936 bytes RSS vs 35,512,320 bytes.

This is one local run of the existing snap resolver profile. The resolver was not changed in #569, and this profile has no configured threshold; record these as contextual measurements rather than a regression attribution.

#569 performance addendum, compared with `docs/perf/baseline.json` → `calendar_snap_536`: - Average (400 edges, 2,000 calls): p50 4.24 µs vs 4.36 µs baseline; p95 17.98 µs vs 13.27 µs; CPU 0.0193 s vs 0.0176 s; RSS 23,031,808→32,395,264 bytes vs 21,917,696→31,207,424 bytes. - Worst (10,000 edges, 1,000 calls): p50 42.36 µs vs 41.44 µs; p95 86.16 µs vs 70.17 µs; CPU 0.0538 s vs 0.0494 s. The 2,000-call burst used 0.0924 s CPU vs 0.1011 s and 35,495,936 bytes RSS vs 35,512,320 bytes. This is one local run of the existing snap resolver profile. The resolver was not changed in #569, and this profile has no configured threshold; record these as contextual measurements rather than a regression attribution.
Author
Owner

Owner decision (2026-10-03): changing only the time of a Log entry never moves it to another day; it moves only when the User picks a different date. Keep dev's rule (merge round 7b resolution).

Owner decision (2026-10-03): changing only the time of a Log entry never moves it to another day; it moves only when the User picks a different date. Keep dev's rule (merge round 7b resolution).
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#569
No description provided.