Journal: Log lines written as HHMM (no colon) are not recognised; 4,654 imported entries missing from the Calendar #724

Open
opened 2026-10-02 12:22:09 +00:00 by kayg · 29 comments
Owner

Owner report (2026-10-02)

"I don't see a lot of events from the Daily notes that got imported in the Calendar view."

Finding (production, read-only counts)

656 Daily notes were imported from calternal.js (2022-11-20 → 2026-09-27). The Calendar projection (note_calendar_logs) has entries only from 2025-11-17 onwards (2,544 entries on 233 days). The imported notes contain:

  • 4,654 Log lines written as - HHMM - HHMM text #tag (no colon, e.g. - 0900 - 1030 Morning review #area/work). The calternal Log parser does not recognise them, so they never reach the Calendar.
  • 3,078 lines in the - HH:MM form, which work.
  • 120 notes with no timed lines at all (free-form days).

calternal.js accepted the colon-less form (read_time_prefix in calternal.js packages/core/src/dayfile.rs: 09:00, 0900, ranges 0900 - 1030, 0900-1030, and an end equal to the start). This is the format of most of the owner's history and likely of other imported journals.

Expected

  • The shared Log-line parser (calternal-notes-core) recognises HHMM, HH:MM, H:MM, and ranges with -, –, — or to, with or without spaces, plus a single time. Port the calternal.js rules and tests (read calternal.js dayfile.rs and its tests; reuse the logic, keep this repo's code style).
  • Reading never rewrites: recognition is a projection change only. Files keep their bytes until the User edits that entry. An edit of an entry writes it back in the same format it was written in (do not normalise 0900 to 09:00 silently).
  • Rebuild: after deploy, the Notes/Journal projections for existing Daily notes are rebuilt once (resumable, throttled, visible in Settings → Jobs), so the 4,654 entries appear without the User touching files.
  • Tags (#area/work), Tasks sections and the other headings in these notes behave as today.

Tests

  • Unit: every time form above, including midnight crossing and invalid values (2460, 0975) that must stay plain text.
  • Round trip: parse → edit time → serialise keeps the original style.
  • A fixture of real-shaped (synthetic) Daily notes from 2023–2025: the Calendar range API returns the expected counts.
  • A production-shaped rebuild on a 650-note Home finishes within budget and changes no bytes.
## Owner report (2026-10-02) "I don't see a lot of events from the Daily notes that got imported in the Calendar view." ## Finding (production, read-only counts) 656 Daily notes were imported from calternal.js (2022-11-20 → 2026-09-27). The Calendar projection (`note_calendar_logs`) has entries only from **2025-11-17** onwards (2,544 entries on 233 days). The imported notes contain: - **4,654 Log lines written as `- HHMM - HHMM text #tag`** (no colon, e.g. `- 0900 - 1030 Morning review #area/work`). The calternal Log parser does not recognise them, so they never reach the Calendar. - 3,078 lines in the `- HH:MM` form, which work. - 120 notes with no timed lines at all (free-form days). calternal.js accepted the colon-less form (`read_time_prefix` in calternal.js `packages/core/src/dayfile.rs`: `09:00`, `0900`, ranges `0900 - 1030`, `0900-1030`, and an end equal to the start). This is the format of most of the owner's history and likely of other imported journals. ## Expected - The shared Log-line parser (calternal-notes-core) recognises `HHMM`, `HH:MM`, `H:MM`, and ranges with `-`, `–`, `—` or `to`, with or without spaces, plus a single time. Port the calternal.js rules and tests (read calternal.js `dayfile.rs` and its tests; reuse the logic, keep this repo's code style). - **Reading never rewrites:** recognition is a projection change only. Files keep their bytes until the User edits that entry. An edit of an entry writes it back in the **same format** it was written in (do not normalise `0900` to `09:00` silently). - **Rebuild:** after deploy, the Notes/Journal projections for existing Daily notes are rebuilt once (resumable, throttled, visible in Settings → Jobs), so the 4,654 entries appear without the User touching files. - Tags (`#area/work`), Tasks sections and the other headings in these notes behave as today. ## Tests - Unit: every time form above, including midnight crossing and invalid values (`2460`, `0975`) that must stay plain text. - Round trip: parse → edit time → serialise keeps the original style. - A fixture of real-shaped (synthetic) Daily notes from 2023–2025: the Calendar range API returns the expected counts. - A production-shaped rebuild on a 650-note Home finishes within budget and changes no bytes.
Author
Owner

Starting #724 on job/hhmm-724, based on origin/dev at c4a61e8cf090170f35b1bed3350d9de20c83ecd5. I am tracing the shared Log-line parser, projection writers and rebuild path before making the parser and migration changes.

Starting #724 on `job/hhmm-724`, based on `origin/dev` at `c4a61e8cf090170f35b1bed3350d9de20c83ecd5`. I am tracing the shared Log-line parser, projection writers and rebuild path before making the parser and migration changes.
Author
Owner

Finding: the checked-out read-only ~/Developer/calternal.js/packages/core/src/dayfile.rs at its current HEAD has a read_time_prefix implementation for HH:MM with - and –; its tests do not cover HHMM, em dash, or to. I will follow #724's explicit grammar for this repository and preserve the exact original time tokens and range separator when an existing entry is edited.

Finding: the checked-out read-only `~/Developer/calternal.js/packages/core/src/dayfile.rs` at its current HEAD has a `read_time_prefix` implementation for `HH:MM` with `-` and `–`; its tests do not cover `HHMM`, em dash, or `to`. I will follow #724's explicit grammar for this repository and preserve the exact original time tokens and range separator when an existing entry is edited.
Author
Owner

Implementation decision: the one-time rebuild gets its candidate paths from the union of indexed Daily note paths in note_items and note_calendar_logs. It validates every candidate with the Notes path validator, reads it through Root, and saves a per-User cursor after projection. This keeps the job focused on known Daily notes, makes crash recovery idempotent, and does not write Markdown. The job appears in the existing Jobs view and pauses between notes.

The live Composer preview now uses the same leading Log time parser as Daily note reads. I found that the preview endpoint otherwise left compact imported times in the title even though the write parser accepted them.

Implementation decision: the one-time rebuild gets its candidate paths from the union of indexed Daily note paths in `note_items` and `note_calendar_logs`. It validates every candidate with the Notes path validator, reads it through `Root`, and saves a per-User cursor after projection. This keeps the job focused on known Daily notes, makes crash recovery idempotent, and does not write Markdown. The job appears in the existing Jobs view and pauses between notes. The live Composer preview now uses the same leading Log time parser as Daily note reads. I found that the preview endpoint otherwise left compact imported times in the title even though the write parser accepted them.
Author
Owner

Finding during repair review: the rebuild's Index union cannot discover a Daily note whose note_items and note_calendar_logs rows are both missing. Notes::recover replays pending renames and task state but does not reconcile every Home first. I am adding a directory-handle-relative Root walk that checks Daily note filenames without opening unrelated Markdown, plus a regression case with a source file that has no Index rows.

Finding during repair review: the rebuild's Index union cannot discover a Daily note whose `note_items` and `note_calendar_logs` rows are both missing. `Notes::recover` replays pending renames and task state but does not reconcile every Home first. I am adding a directory-handle-relative `Root` walk that checks Daily note filenames without opening unrelated Markdown, plus a regression case with a source file that has no Index rows.
Author
Owner

Gate finding: bun run test reports 1,050 passed and 3 failed out of 1,053 tests. The failures are 5-second timeouts in modeHeader.svelte.test.ts (async ancestor navigation focus), ThemePicker.svelte.test.ts (Auto dark variant), and MailSection.svelte.test.ts (Advanced provider details). This job did not touch those files and did not change their expectations. bun run check passed.

Gate finding: `bun run test` reports 1,050 passed and 3 failed out of 1,053 tests. The failures are 5-second timeouts in `modeHeader.svelte.test.ts` (async ancestor navigation focus), `ThemePicker.svelte.test.ts` (Auto dark variant), and `MailSection.svelte.test.ts` (Advanced provider details). This job did not touch those files and did not change their expectations. `bun run check` passed.
Author
Owner

#724 report — stopped at the four-hour limit

Built

  • Extended the shared Daily Log parser for H:MM, HH:MM, and HHMM; hyphen, en dash, em dash, and to ranges; equal endpoints; and overnight ranges. Invalid tokens remain plain text. Untouched Log lines keep their bytes, and edited times retain source token and separator style.
  • Connected Event Composer previews to the same parser while keeping time-shaped Note titles intact.
  • Added migration 0025 and a low-priority, per-User visible rebuild job. It resumes from a durable cursor, enumerates Daily note filenames through Root to find files missing Index rows, refreshes projections from Markdown, and never writes Markdown.
  • Added tests for parser/write-back styles, a 650-note resumable rebuild with unchanged file bytes, and Calendar range/year rows for 2023–2025. Added the local benchmark runner.

Commits and files

  • abf005941 — parser forms and source-style write-back.
  • 3217d82be — shared prefix export and Composer adapter support.
  • 9b671923b8c90e5b5cda68d5da4153900ed71833 — Notes rebuild, migration, tests, and benchmark runner; this is the head SHA.
  • crates/plugins/calendar/src/view.rs contains the Calendar range/year test but remains uncommitted because its crate gate did not run.

Files changed: crates/calternal-notes-core/src/{dayfile.rs,composer.rs,lib.rs}, crates/plugins/notes/src/{composer_api.rs,lib.rs,store.rs}, crates/plugins/notes/migrations/0025_daily_log_projection_rebuild.sql, crates/plugins/calendar/src/view.rs, and bench/notes-daily-log-rebuild-724.sh.

Gate output

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

Core clippy:

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

cargo test -p calternal-notes-core:

test result: ok. 523 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
19 passed; 0 failed
5 passed; 0 failed
7 passed; 0 failed
12 passed; 0 failed
0 passed; 0 failed

bun run check:

User browser caches use userStorage; only documented device/public-link exceptions remain.
Text sizes and UI shape values use shared role tokens.
UI transitions and animation options use shared motion tokens or documented exceptions.
svelte-check found 0 errors and 0 warnings

bun run test:

Test Files  3 failed | 150 passed (153)
     Tests  3 failed | 1050 passed (1053)
  Duration  527.51s

The three failures timed out at 5 seconds in modeHeader.svelte.test.ts, ThemePicker.svelte.test.ts, and MailSection.svelte.test.ts. This suite started before the origin/dev merge; that merge changed only media deployment scripts. No expectations were changed.

bun run build: ✓ built in 3m 24s and ✔ done.

Notes clippy was still compiling dependencies at the four-hour stop and was interrupted before a result. Notes tests, Calendar clippy/tests, and calternal-server gates were not run. cargo clean ran, and the job target plus web build output are absent.

Gaps

  • No 2024 Calendar screenshots were captured. The prepared Playwright macOS emulation run still needs the before/after 390, 820, and 1440 px light/dark captures and attachment to this issue. The offline Mac VM was not used.
  • The benchmark runner is committed, but it was not run; docs/perf/baseline.json has no #724 measurement.
  • No local-server adversarial round was run.
  • UX review of the Composer preview and Calendar display remains pending with the browser evidence.

Decisions

  • The read-only calternal.js checkout did not contain the imported forms required by #724. I followed the issue’s listed forms, used the shared 24-hour parser, and kept invalid forms as plain title text.
  • The rebuild walks Home directory entries through Root, in addition to indexed candidates, because Notes::recover does not reconcile files whose Note and Calendar rows are both missing. It skips hidden names and opens only Daily note files.
  • The screenshot “before” state is the empty 2024 week before the synthetic API-created Logs; “after” is the same week after import. This uses one production build because an old server binary was not available in this worktree.

UX gaps left

The screenshot matrix and browser interaction review are still pending. The three unrelated Svelte test timeouts remain unchanged.

## #724 report — stopped at the four-hour limit ### Built - Extended the shared Daily Log parser for `H:MM`, `HH:MM`, and `HHMM`; hyphen, en dash, em dash, and `to` ranges; equal endpoints; and overnight ranges. Invalid tokens remain plain text. Untouched Log lines keep their bytes, and edited times retain source token and separator style. - Connected Event Composer previews to the same parser while keeping time-shaped Note titles intact. - Added migration `0025` and a low-priority, per-User visible rebuild job. It resumes from a durable cursor, enumerates Daily note filenames through `Root` to find files missing Index rows, refreshes projections from Markdown, and never writes Markdown. - Added tests for parser/write-back styles, a 650-note resumable rebuild with unchanged file bytes, and Calendar range/year rows for 2023–2025. Added the local benchmark runner. ### Commits and files - `abf005941` — parser forms and source-style write-back. - `3217d82be` — shared prefix export and Composer adapter support. - `9b671923b8c90e5b5cda68d5da4153900ed71833` — Notes rebuild, migration, tests, and benchmark runner; this is the head SHA. - `crates/plugins/calendar/src/view.rs` contains the Calendar range/year test but remains uncommitted because its crate gate did not run. Files changed: `crates/calternal-notes-core/src/{dayfile.rs,composer.rs,lib.rs}`, `crates/plugins/notes/src/{composer_api.rs,lib.rs,store.rs}`, `crates/plugins/notes/migrations/0025_daily_log_projection_rebuild.sql`, `crates/plugins/calendar/src/view.rs`, and `bench/notes-daily-log-rebuild-724.sh`. ### Gate output `cargo fmt --all -- --check`: exit 0, no output. Core clippy: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 51.79s ``` `cargo test -p calternal-notes-core`: ```text test result: ok. 523 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out 19 passed; 0 failed 5 passed; 0 failed 7 passed; 0 failed 12 passed; 0 failed 0 passed; 0 failed ``` `bun run check`: ```text User browser caches use userStorage; only documented device/public-link exceptions remain. Text sizes and UI shape values use shared role tokens. UI transitions and animation options use shared motion tokens or documented exceptions. svelte-check found 0 errors and 0 warnings ``` `bun run test`: ```text Test Files 3 failed | 150 passed (153) Tests 3 failed | 1050 passed (1053) Duration 527.51s ``` The three failures timed out at 5 seconds in `modeHeader.svelte.test.ts`, `ThemePicker.svelte.test.ts`, and `MailSection.svelte.test.ts`. This suite started before the `origin/dev` merge; that merge changed only media deployment scripts. No expectations were changed. `bun run build`: `✓ built in 3m 24s` and `✔ done`. Notes clippy was still compiling dependencies at the four-hour stop and was interrupted before a result. Notes tests, Calendar clippy/tests, and `calternal-server` gates were not run. `cargo clean` ran, and the job target plus web build output are absent. ### Gaps - No 2024 Calendar screenshots were captured. The prepared Playwright macOS emulation run still needs the before/after 390, 820, and 1440 px light/dark captures and attachment to this issue. The offline Mac VM was not used. - The benchmark runner is committed, but it was not run; `docs/perf/baseline.json` has no #724 measurement. - No local-server adversarial round was run. - UX review of the Composer preview and Calendar display remains pending with the browser evidence. ### Decisions - The read-only `calternal.js` checkout did not contain the imported forms required by #724. I followed the issue’s listed forms, used the shared 24-hour parser, and kept invalid forms as plain title text. - The rebuild walks Home directory entries through `Root`, in addition to indexed candidates, because `Notes::recover` does not reconcile files whose Note and Calendar rows are both missing. It skips hidden names and opens only Daily note files. - The screenshot “before” state is the empty 2024 week before the synthetic API-created Logs; “after” is the same week after import. This uses one production build because an old server binary was not available in this worktree. ### UX gaps left The screenshot matrix and browser interaction review are still pending. The three unrelated Svelte test timeouts remain unchanged.
Author
Owner

Correction to the report: the one-off screenshot harness was stored under target/tmp and was removed by the required cargo clean. No PNGs were captured. Regenerate the macOS Playwright harness, build calternal-server, then capture and attach the 12 before/after Calendar Week screenshots listed above.

Correction to the report: the one-off screenshot harness was stored under `target/tmp` and was removed by the required `cargo clean`. No PNGs were captured. Regenerate the macOS Playwright harness, build `calternal-server`, then capture and attach the 12 before/after Calendar Week screenshots listed above.
Author
Owner

Starting the verification round on branch job/hhmm-724 from checkpoint 9b671923b (current WIP checkpoint commit 61df2073d). I will merge origin/dev, run the notes-core, Notes, and Calendar crate gates including the Calendar range/year test, fix any failures, replace the WIP commit, and report the merge-round projection rebuild requirement.

Starting the verification round on branch `job/hhmm-724` from checkpoint `9b671923b` (current WIP checkpoint commit `61df2073d`). I will merge `origin/dev`, run the notes-core, Notes, and Calendar crate gates including the Calendar range/year test, fix any failures, replace the WIP commit, and report the merge-round projection rebuild requirement.
Author
Owner

The Notes Clippy attempt exited 101 while compiling sha2: sccache could not create a temp directory under /home/kayg/Developer/calternal-wt/authfix/target/tmp (ENOENT). Investigation confirmed the shared sccache server process retained TMPDIR=/home/kayg/Developer/calternal-wt/authfix/target/tmp; this worktree's prescribed temp directory exists at hhmm-724/target/tmp, while the retained path does not. I will retry this gate with RUSTC_WRAPPER unset for this command only, leaving the shared daemon running for other jobs.

The Notes Clippy attempt exited 101 while compiling `sha2`: sccache could not create a temp directory under `/home/kayg/Developer/calternal-wt/authfix/target/tmp` (ENOENT). Investigation confirmed the shared sccache server process retained `TMPDIR=/home/kayg/Developer/calternal-wt/authfix/target/tmp`; this worktree's prescribed temp directory exists at `hhmm-724/target/tmp`, while the retained path does not. I will retry this gate with `RUSTC_WRAPPER` unset for this command only, leaving the shared daemon running for other jobs.
Author
Owner

The Notes Clippy retry reached calternal-plugin-notes and exited 101 with E0308 at crates/plugins/notes/src/lib.rs:108 and E0277 at :133 (both introduced by #724 commit 9b671923b). fetch_all returns Vec<String>, but the completion lookup is declared as a HashSet; JobQueue::enqueue returns calternal_db::DbError, while this helper returns the Notes ApiError result type. I will collect the fetched IDs into the existing set and map the enqueue SQLx variant through the existing ApiError::from(sqlx::Error) conversion, with other queue errors mapped to the existing internal response.

The Notes Clippy retry reached `calternal-plugin-notes` and exited 101 with E0308 at `crates/plugins/notes/src/lib.rs:108` and E0277 at `:133` (both introduced by #724 commit `9b671923b`). `fetch_all` returns `Vec<String>`, but the completion lookup is declared as a `HashSet`; `JobQueue::enqueue` returns `calternal_db::DbError`, while this helper returns the Notes `ApiError` result type. I will collect the fetched IDs into the existing set and map the enqueue SQLx variant through the existing `ApiError::from(sqlx::Error)` conversion, with other queue errors mapped to the existing internal response.
Author
Owner

cargo test -p calternal-plugin-notes exited 101: test result: FAILED. 168 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1423.03s. tests::daily_and_composer_preserve_unrelated_bytes asserted 200 but received 404 at crates/plugins/notes/src/lib.rs:9732; tests::legacy_inbox_is_read_without_a_capitalized_tasks_folder unwrapped Sqlx(PoolTimedOut) at :6093. The 650-note resumable projection rebuild test passed. I am investigating the 404 without changing either test expectation; the pool timeout appears during heavy shared-host contention and will be treated separately from code failures.

`cargo test -p calternal-plugin-notes` exited 101: `test result: FAILED. 168 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1423.03s`. `tests::daily_and_composer_preserve_unrelated_bytes` asserted 200 but received 404 at `crates/plugins/notes/src/lib.rs:9732`; `tests::legacy_inbox_is_read_without_a_capitalized_tasks_folder` unwrapped `Sqlx(PoolTimedOut)` at `:6093`. The 650-note resumable projection rebuild test passed. I am investigating the 404 without changing either test expectation; the pool timeout appears during heavy shared-host contention and will be treated separately from code failures.
Author
Owner

The two full-suite Notes failures both passed when run alone: daily_and_composer_preserve_unrelated_bytes passed in 13.43s before the test-fixture fix and 18.57s after it; legacy_inbox_is_read_without_a_capitalized_tasks_folder passed in 1.63s. The first race came from all parallel test fixtures using the same User ID with process-global USER_LOCKS; setup() now allocates unique test User IDs. The pool timeout did not reproduce in isolation and occurred during heavy parallel host I/O. I am not rerunning the full Notes suite under the one-run verification policy; the merge round should run cargo test -p calternal-plugin-notes -- --test-threads=4.

The two full-suite Notes failures both passed when run alone: `daily_and_composer_preserve_unrelated_bytes` passed in 13.43s before the test-fixture fix and 18.57s after it; `legacy_inbox_is_read_without_a_capitalized_tasks_folder` passed in 1.63s. The first race came from all parallel test fixtures using the same User ID with process-global `USER_LOCKS`; `setup()` now allocates unique test User IDs. The pool timeout did not reproduce in isolation and occurred during heavy parallel host I/O. I am not rerunning the full Notes suite under the one-run verification policy; the merge round should run `cargo test -p calternal-plugin-notes -- --test-threads=4`.
Author
Owner

Final report — #724

Branch: job/hhmm-724
Head: d9e2a196b2a69c7a67c8f4f354b4d3d92f550e7a

Built

  • Added Calendar /range and /year coverage for imported Daily Log time formats across years, including overnight ranges.
  • Fixed Notes projection rebuild queue setup: SQL rows are collected as strings and SQL errors use the existing ApiError conversion.
  • Gave each Notes test setup a unique User ID so parallel tests do not contend on process-global user locks.
  • Reworded the WIP test commit to 88198c65c test(calendar): cover imported Daily Log projections.

Files

  • crates/plugins/calendar/src/view.rs
  • crates/plugins/notes/src/lib.rs
  • docs/DESIGN.md changed only by merging origin/dev (c4faf184d).

Gate output

Captured output is quoted below. cargo fmt --check exited 0 with empty stdout and stderr.

cargo clippy -p calternal-notes-core --all-targets -- -D warnings
Finished `dev` profile [unoptimized + debuginfo] target(s) in 8m 28s

cargo test -p calternal-notes-core
test result: ok. 523 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.84s
test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 6.80s
test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.15s
test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.65s
test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
doc-tests: 0 passed; 0 failed; finished in 0.00s

cargo clippy -p calternal-plugin-notes --all-targets -- -D warnings
Finished `dev` profile [unoptimized + debuginfo] target(s) in 11m 33s

cargo test -p calternal-plugin-notes
test result: FAILED. 168 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1423.03s

cargo test -p calternal-plugin-notes daily_and_composer_preserve_unrelated_bytes -- --exact
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 169 filtered out; finished in 18.57s

cargo test -p calternal-plugin-notes legacy_inbox_is_read_without_a_capitalized_tasks_folder -- --exact
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 169 filtered out; finished in 1.63s

cargo clippy -p calternal-plugin-calendar --all-targets -- -D warnings
Finished `dev` profile [unoptimized + debuginfo] target(s) in 10m 28s

cargo test -p calternal-plugin-calendar
test result: ok. 84 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 22.72s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.65s
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.43s
doc-tests: 0 passed; 0 failed; finished in 0.07s

cargo clean
Removed 12126 files, 5.9GiB total

The full Notes run had two failures. The Daily/composer test got a transient 404 because parallel setups shared the process-global lock key; unique test User IDs fixed this, and the test passed alone after the fix. The inbox test hit Sqlx(PoolTimedOut) during Db::connect; it passed alone. I did not rerun the full Notes suite after the fixture fix under the one-run policy.

Known gaps

  • Run the full Notes suite in the merge round with cargo test -p calternal-plugin-notes -- --test-threads=4.
  • The existing rebuild profile uses 650 synthetic notes with - 0900-1030 Focus; it does not model the owner's 656 imported Daily notes or their - HHMM - HHMM text line shape. No performance measurement was run here.
  • UX review is not applicable; this change adds no UI.

For the merge round

Profile the projection rebuild on 656 notes using the owner's imported Markdown shape (- HHMM - HHMM text), including average and burst measurements and the required p50/p95 latency, CPU, and RSS. The current bench/notes-daily-log-rebuild-724.sh fixture and count need to be adjusted for that real shape. Run measurements under flock /root/perf.lock on the perf VM when available and record load while holding the lock; compare with docs/perf/baseline.json.

Decisions

  • For the queue setup, used the existing SQLx-to-ApiError conversion and the existing internal-error fallback for non-SQLx database errors.
  • Used process-local atomic IDs only in the Notes test fixture to isolate test users; production identity behavior is unchanged.
  • No product behavior decision outside docs/DESIGN.md was needed.
# Final report — #724 **Branch:** `job/hhmm-724` **Head:** `d9e2a196b2a69c7a67c8f4f354b4d3d92f550e7a` ## Built - Added Calendar `/range` and `/year` coverage for imported Daily Log time formats across years, including overnight ranges. - Fixed Notes projection rebuild queue setup: SQL rows are collected as strings and SQL errors use the existing `ApiError` conversion. - Gave each Notes test setup a unique User ID so parallel tests do not contend on process-global user locks. - Reworded the WIP test commit to `88198c65c test(calendar): cover imported Daily Log projections`. ## Files - `crates/plugins/calendar/src/view.rs` - `crates/plugins/notes/src/lib.rs` - `docs/DESIGN.md` changed only by merging `origin/dev` (`c4faf184d`). ## Gate output Captured output is quoted below. `cargo fmt --check` exited 0 with empty stdout and stderr. ```text cargo clippy -p calternal-notes-core --all-targets -- -D warnings Finished `dev` profile [unoptimized + debuginfo] target(s) in 8m 28s cargo test -p calternal-notes-core test result: ok. 523 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.84s test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 6.80s test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.15s test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.65s test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s doc-tests: 0 passed; 0 failed; finished in 0.00s cargo clippy -p calternal-plugin-notes --all-targets -- -D warnings Finished `dev` profile [unoptimized + debuginfo] target(s) in 11m 33s cargo test -p calternal-plugin-notes test result: FAILED. 168 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1423.03s cargo test -p calternal-plugin-notes daily_and_composer_preserve_unrelated_bytes -- --exact test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 169 filtered out; finished in 18.57s cargo test -p calternal-plugin-notes legacy_inbox_is_read_without_a_capitalized_tasks_folder -- --exact test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 169 filtered out; finished in 1.63s cargo clippy -p calternal-plugin-calendar --all-targets -- -D warnings Finished `dev` profile [unoptimized + debuginfo] target(s) in 10m 28s cargo test -p calternal-plugin-calendar test result: ok. 84 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 22.72s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.65s test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.43s doc-tests: 0 passed; 0 failed; finished in 0.07s cargo clean Removed 12126 files, 5.9GiB total ``` The full Notes run had two failures. The Daily/composer test got a transient 404 because parallel setups shared the process-global lock key; unique test User IDs fixed this, and the test passed alone after the fix. The inbox test hit `Sqlx(PoolTimedOut)` during `Db::connect`; it passed alone. I did not rerun the full Notes suite after the fixture fix under the one-run policy. ## Known gaps - Run the full Notes suite in the merge round with `cargo test -p calternal-plugin-notes -- --test-threads=4`. - The existing rebuild profile uses 650 synthetic notes with `- 0900-1030 Focus`; it does not model the owner's 656 imported Daily notes or their `- HHMM - HHMM text` line shape. No performance measurement was run here. - UX review is not applicable; this change adds no UI. ## For the merge round Profile the projection rebuild on 656 notes using the owner's imported Markdown shape (`- HHMM - HHMM text`), including average and burst measurements and the required p50/p95 latency, CPU, and RSS. The current `bench/notes-daily-log-rebuild-724.sh` fixture and count need to be adjusted for that real shape. Run measurements under `flock /root/perf.lock` on the perf VM when available and record load while holding the lock; compare with `docs/perf/baseline.json`. ## Decisions - For the queue setup, used the existing SQLx-to-`ApiError` conversion and the existing internal-error fallback for non-SQLx database errors. - Used process-local atomic IDs only in the Notes test fixture to isolate test users; production identity behavior is unchanged. - No product behavior decision outside `docs/DESIGN.md` was needed.
Author
Owner

Started hotfix-724 on job/hotfix-724 at 516faaa698 (current 7a head, includes 61222f456). Merging approved job/hhmm-724 at d9e2a196b; resolving Calendar test and Notes migration registration conflicts, with the rebuild migration renumbered to 0027. Deployment scope is staging only.

Started hotfix-724 on job/hotfix-724 at 516faaa698570bdb468626cf6cd75d9c81b33ac2 (current 7a head, includes 61222f456). Merging approved job/hhmm-724 at d9e2a196b; resolving Calendar test and Notes migration registration conflicts, with the rebuild migration renumbered to 0027. Deployment scope is staging only.
Author
Owner

Read-only production finding from the #719 follow-up: the 428 Daily notes with no current Calendar Log rows contain 4,655 HHMM time-stamped bullet lines inside accepted ## Log sections across 269 notes. The current core parser requires HH:MM in read_time_prefix (crates/calternal-notes-core/src/dayfile.rs), so these lines are unparsed and absent from the projection. This matches #724's parser and rebuild scope. The classifier emitted counts only; no production files or database rows were changed, and no note text, names, or paths are included here.

Read-only production finding from the #719 follow-up: the 428 Daily notes with no current Calendar Log rows contain 4,655 `HHMM` time-stamped bullet lines inside accepted `## Log` sections across 269 notes. The current core parser requires `HH:MM` in `read_time_prefix` (`crates/calternal-notes-core/src/dayfile.rs`), so these lines are unparsed and absent from the projection. This matches #724's parser and rebuild scope. The classifier emitted counts only; no production files or database rows were changed, and no note text, names, or paths are included here.
Author
Owner

Count-definition note for the implementation: #724's existing report counts 4,654 imported lines in the - HHMM - HHMM text range form. The #719 follow-up's broader classifier counted 4,655 HHMM time-stamped bullet candidates inside accepted Log sections among the 428 currently unindexed Daily notes. These are different detectors, and the subset count is one higher than the existing range count. The classifier returned aggregate counts only, so this audit did not single out the candidate behind the difference. Please reconcile the exact syntax and fixture count while implementing #724; do not assume the two numbers mean the same shape.

Count-definition note for the implementation: #724's existing report counts 4,654 imported lines in the `- HHMM - HHMM text` range form. The #719 follow-up's broader classifier counted 4,655 `HHMM` time-stamped bullet candidates inside accepted Log sections among the 428 currently unindexed Daily notes. These are different detectors, and the subset count is one higher than the existing range count. The classifier returned aggregate counts only, so this audit did not single out the candidate behind the difference. Please reconcile the exact syntax and fixture count while implementing #724; do not assume the two numbers mean the same shape.
Author
Owner

Starting the #724 production round on job/hotfix-724 at 7a head 516faaa698570bdb468626cf6cd75d9c81b33ac2 (parent 7a SHA 61222f456d0783500e01d3f18a548403d31b83d0). I am merging approved job/hhmm-724 at d9e2a196b2a69c7a67c8f4f354b4d3d92f550e7a; this branch already contains the #724 implementation, and I will preserve the adapted in-progress 7a patch while resolving migration and test conflicts.

Starting the #724 production round on `job/hotfix-724` at 7a head `516faaa698570bdb468626cf6cd75d9c81b33ac2` (parent 7a SHA `61222f456d0783500e01d3f18a548403d31b83d0`). I am merging approved `job/hhmm-724` at `d9e2a196b2a69c7a67c8f4f354b4d3d92f550e7a`; this branch already contains the #724 implementation, and I will preserve the adapted in-progress 7a patch while resolving migration and test conflicts.
Author
Owner

Finding during rebuild safety review: store::daily_note_paths walks the full Home with Root::list. Root::list_impl returns Error::InvalidPath for any non-UTF-8 filename (crates/calternal-fs/src/root.rs:1017), so one unaddressable POSIX name can stop the scan before valid Daily notes are collected; the queued rebuild then retries and cannot finish. I am adding a separate Root::list_utf8 helper that skips only names the RelPath API cannot address, keeping existing Root::list behavior unchanged, with a raw-byte filename regression test.

Finding during rebuild safety review: `store::daily_note_paths` walks the full Home with `Root::list`. `Root::list_impl` returns `Error::InvalidPath` for any non-UTF-8 filename (`crates/calternal-fs/src/root.rs:1017`), so one unaddressable POSIX name can stop the scan before valid Daily notes are collected; the queued rebuild then retries and cannot finish. I am adding a separate `Root::list_utf8` helper that skips only names the `RelPath` API cannot address, keeping existing `Root::list` behavior unchanged, with a raw-byte filename regression test.
Author
Owner

Finding during the HDD profile attempt: the focused Notes rebuild test failed before it created the fixture. Db::connect(...).await.unwrap() at crates/plugins/notes/src/lib.rs:6459-6461 returned Sqlx(PoolTimedOut) after 30.34 seconds while the test database was under the /mnt/hdd job target. The same Notes test passed earlier on the normal TMPDIR path in 472.22 seconds. The pool acquisition timeout is 30 seconds in crates/calternal-db/src/db.rs; no rebuild timing was produced by this attempt and no user data changed. I am recording this as a local HDD/load limitation and will not change the shared database timeout for this issue.

Finding during the HDD profile attempt: the focused Notes rebuild test failed before it created the fixture. `Db::connect(...).await.unwrap()` at `crates/plugins/notes/src/lib.rs:6459-6461` returned `Sqlx(PoolTimedOut)` after 30.34 seconds while the test database was under the `/mnt/hdd` job target. The same Notes test passed earlier on the normal `TMPDIR` path in 472.22 seconds. The pool acquisition timeout is 30 seconds in `crates/calternal-db/src/db.rs`; no rebuild timing was produced by this attempt and no user data changed. I am recording this as a local HDD/load limitation and will not change the shared database timeout for this issue.
Author
Owner

Server gate finding: cargo test -p calternal-server -- --test-threads=4 completed with 161 passed, 1 failed, and 5 ignored. The only failure was the existing wire::tests::live_apps_run_in_separate_processes wrapper. Its nested full_app_setup_session_config_and_backup case timed out at crates/calternal-server/src/wire.rs:8078-8087: the five-second poll did not observe the already-accepted user archive deletion (Elapsed(())). The failure ran under the shared host load and did not alter any test expectation or production code. I classify it as a slow test/load finding; it needs review in the merge round, not a behavior change for #724.

Server gate finding: `cargo test -p calternal-server -- --test-threads=4` completed with 161 passed, 1 failed, and 5 ignored. The only failure was the existing `wire::tests::live_apps_run_in_separate_processes` wrapper. Its nested `full_app_setup_session_config_and_backup` case timed out at `crates/calternal-server/src/wire.rs:8078-8087`: the five-second poll did not observe the already-accepted user archive deletion (`Elapsed(())`). The failure ran under the shared host load and did not alter any test expectation or production code. I classify it as a slow test/load finding; it needs review in the merge round, not a behavior change for #724.
Author
Owner

Focused E2E finding: the first 7a Files Tus upload returned HTTP 503 before importing any fixture, so the 656-note prepare phase stopped and removed its temporary Home. The shared uploadViaApi helper reports only the status, so this run did not retain a response body or Retry-After value. The Files route maps transient SQLite busy errors to a retryable 503 with Retry-After: 1 (crates/plugins/files/src/lib.rs, database_failure/busy_at); this is consistent with shared-host contention, but needs a diagnostics-enabled focused rerun before I can classify the cause. No production code or assertion changed.

Focused E2E finding: the first 7a Files Tus upload returned HTTP 503 before importing any fixture, so the 656-note prepare phase stopped and removed its temporary Home. The shared `uploadViaApi` helper reports only the status, so this run did not retain a response body or Retry-After value. The Files route maps transient SQLite busy errors to a retryable 503 with `Retry-After: 1` (`crates/plugins/files/src/lib.rs`, `database_failure`/`busy_at`); this is consistent with shared-host contention, but needs a diagnostics-enabled focused rerun before I can classify the cause. No production code or assertion changed.
Author
Owner

The 7a real-server fixture import reached only 10 of 656 Daily notes after about nine minutes on this shared host. Files Tus uploads take tens of seconds each, so the 656-request preparation cannot finish inside the job window. I am changing only the test fixture setup: a test-only Rust helper will write the deterministic fixture bytes through calternal-fs::Root while both servers are stopped; then 7a will restart and reconcile/index those files before the candidate upgrade. This keeps all fixture filesystem operations directory-handle-relative and leaves the running server as the only writer. Calendar checks, the automatic projection rebuild, source-byte hashes, and screenshots remain in the real server flow.

The 7a real-server fixture import reached only 10 of 656 Daily notes after about nine minutes on this shared host. Files Tus uploads take tens of seconds each, so the 656-request preparation cannot finish inside the job window. I am changing only the test fixture setup: a test-only Rust helper will write the deterministic fixture bytes through `calternal-fs::Root` while both servers are stopped; then 7a will restart and reconcile/index those files before the candidate upgrade. This keeps all fixture filesystem operations directory-handle-relative and leaves the running server as the only writer. Calendar checks, the automatic projection rebuild, source-byte hashes, and screenshots remain in the real server flow.
Author
Owner

The first bounded Files retry exposed an idempotency trap. After the server logged Files request answered 503 because the Index database is busy at crates/plugins/files/src/index.rs:1270, the next POST for the same Daily note returned 412 instead of the expected 201. This shows the first request had already reserved or installed the destination before its response failed; a no-Location 503 is not safe to replay. I am removing that retry helper and replacing the slow per-file import with a test-only calternal-fs::Root fixture writer used only while the servers are stopped. The 7a server then reconciles the files before the upgrade.

The first bounded Files retry exposed an idempotency trap. After the server logged `Files request answered 503 because the Index database is busy` at `crates/plugins/files/src/index.rs:1270`, the next POST for the same Daily note returned 412 instead of the expected 201. This shows the first request had already reserved or installed the destination before its response failed; a no-`Location` 503 is not safe to replay. I am removing that retry helper and replacing the slow per-file import with a test-only `calternal-fs::Root` fixture writer used only while the servers are stopped. The 7a server then reconciles the files before the upgrade.
Author
Owner

Finished report — hotfix-724

Head: 7f76bc2d9c0ced62b0ed43be877c6320b2be7ada
Notes migration: 0027_daily_log_projection_rebuild.sql
Built: shared HHMM/colon Log range parsing and style-preserving edits; migration 0027 queues a resumable, throttled Notes/Calendar/Tasks projection rebuild at server start without changing Markdown bytes; Calendar projection coverage; HDD rebuild profile; and a production-build E2E flow with macOS rendering at 390/820/1440 in light/dark. The test-only fixture writer uses calternal-fs::Root while the servers are stopped.

Gate output

cargo fmt --check exited 0 with no output.

cargo clippy -p calternal-plugin-notes --all-targets -- -D warnings:

    Checking calternal-plugin-notes v0.0.1 (/home/kayg/Developer/calternal-wt/hotfix-724/crates/plugins/notes)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 8m 44s

cargo test -p calternal-plugin-notes -- --test-threads=4:

test result: ok. 186 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 382.68s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.58s

cargo clippy -p calternal-plugin-files --all-targets -- -D warnings:

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

cargo test -p calternal-plugin-files -- --test-threads=4:

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

cargo clippy -p calternal-server --all-targets -- -D warnings after merging 7a c82b9aca1:

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

The follow-up cargo test -p calternal-server -- --test-threads=4 was interrupted with exit 130 at the four-hour job limit while it compiled the server/plugin graph. The earlier server run had this exact result:

test result: FAILED. 161 passed; 1 failed; 5 ignored; 0 measured; 0 filtered out; finished in 180.36s

The failure was the existing full_app_setup_session_config_and_backup five-second poll timing out under shared-host load. No test expectation was changed.

bun run check:

$ 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/hotfix-724/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

cargo clean:

     Removed 20008 files, 12.3GiB total

Gaps

The 656-note real-server upgrade did not finish. The initial Files API import reached 10/656 notes after about nine minutes; a replay after a retryable 503 returned 412, showing the first Tus request may already have installed its destination. The replacement calternal-fs::Root fixture attempt wrote 11/656 files after about 30 seconds on the shared HDD and was stopped at the job limit. No projection rebuild timing or Calendar screenshots were captured. The final server build after the late 7a Files merge was also interrupted; the E2E attempt used the previously built candidate binary, before that Files-only merge.

The profile run also did not measure the rebuild: its setup stopped at Db::connect() with Sqlx(PoolTimedOut) after 30.34 seconds, before fixture creation. Staging was not deployed under the shared verification policy. There is no staging tag or screenshot set.

Decisions

  • HHMM and colon ranges share the same parser. Direct edits retain the source token and separator style.
  • The 656-note fixture writer runs only while both servers are stopped and uses calternal-fs::Root; 7a then reconciles the files. The measured HDD write time shows this setup still needs a faster test fixture path.
  • Projection rebuild is automatic at server start. No manual production rebuild command is required.

UX gaps closed: Calendar projection/parser coverage and style-preserving edits are included.
UX gaps left: The real Calendar Week/Year browser walk and the required screenshot review were not completed.

For the merge round

  • Rebuild the candidate from the merged head: cargo build -p calternal-server.
  • Run the upgrade flow: bun apps/web/e2e/daily-log-upgrade-724.mjs. It must prove migration 26→27, all 7,732 Calendar entries and dates/times/Tags, unchanged bytes for all 656 notes, rebuild timing, and the 24 macOS screenshots.
  • Complete the server gate: cargo test -p calternal-server -- --test-threads=4.
  • Run staging only through ~/.local/state/codex-jobs/calternal/deploy-staging.sh <tag> after reading it; build as /mnt/hdd/targets/staging-build/build.sh, then verify the 2023 Calendar Week in 1440 light/dark and attach those screenshots.
  • Production requires no post-deploy command; startup enqueues the projection rebuild automatically.
## Finished report — hotfix-724 **Head:** `7f76bc2d9c0ced62b0ed43be877c6320b2be7ada` **Notes migration:** `0027_daily_log_projection_rebuild.sql` **Built:** shared HHMM/colon Log range parsing and style-preserving edits; migration 0027 queues a resumable, throttled Notes/Calendar/Tasks projection rebuild at server start without changing Markdown bytes; Calendar projection coverage; HDD rebuild profile; and a production-build E2E flow with macOS rendering at 390/820/1440 in light/dark. The test-only fixture writer uses `calternal-fs::Root` while the servers are stopped. ### Gate output `cargo fmt --check` exited 0 with no output. `cargo clippy -p calternal-plugin-notes --all-targets -- -D warnings`: ```text Checking calternal-plugin-notes v0.0.1 (/home/kayg/Developer/calternal-wt/hotfix-724/crates/plugins/notes) Finished `dev` profile [unoptimized + debuginfo] target(s) in 8m 44s ``` `cargo test -p calternal-plugin-notes -- --test-threads=4`: ```text test result: ok. 186 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 382.68s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.58s ``` `cargo clippy -p calternal-plugin-files --all-targets -- -D warnings`: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 3m 21s ``` `cargo test -p calternal-plugin-files -- --test-threads=4`: ```text test result: ok. 158 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 198.65s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` `cargo clippy -p calternal-server --all-targets -- -D warnings` after merging 7a `c82b9aca1`: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 3m 10s ``` The follow-up `cargo test -p calternal-server -- --test-threads=4` was interrupted with exit 130 at the four-hour job limit while it compiled the server/plugin graph. The earlier server run had this exact result: ```text test result: FAILED. 161 passed; 1 failed; 5 ignored; 0 measured; 0 filtered out; finished in 180.36s ``` The failure was the existing `full_app_setup_session_config_and_backup` five-second poll timing out under shared-host load. No test expectation was changed. `bun run check`: ```text $ 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/hotfix-724/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `cargo clean`: ```text Removed 20008 files, 12.3GiB total ``` ### Gaps The 656-note real-server upgrade did not finish. The initial Files API import reached 10/656 notes after about nine minutes; a replay after a retryable 503 returned 412, showing the first Tus request may already have installed its destination. The replacement `calternal-fs::Root` fixture attempt wrote 11/656 files after about 30 seconds on the shared HDD and was stopped at the job limit. No projection rebuild timing or Calendar screenshots were captured. The final server build after the late 7a Files merge was also interrupted; the E2E attempt used the previously built candidate binary, before that Files-only merge. The profile run also did not measure the rebuild: its setup stopped at `Db::connect()` with `Sqlx(PoolTimedOut)` after 30.34 seconds, before fixture creation. Staging was not deployed under the shared verification policy. There is no staging tag or screenshot set. ### Decisions - HHMM and colon ranges share the same parser. Direct edits retain the source token and separator style. - The 656-note fixture writer runs only while both servers are stopped and uses `calternal-fs::Root`; 7a then reconciles the files. The measured HDD write time shows this setup still needs a faster test fixture path. - Projection rebuild is automatic at server start. No manual production rebuild command is required. **UX gaps closed:** Calendar projection/parser coverage and style-preserving edits are included. **UX gaps left:** The real Calendar Week/Year browser walk and the required screenshot review were not completed. ### For the merge round - Rebuild the candidate from the merged head: `cargo build -p calternal-server`. - Run the upgrade flow: `bun apps/web/e2e/daily-log-upgrade-724.mjs`. It must prove migration 26→27, all 7,732 Calendar entries and dates/times/Tags, unchanged bytes for all 656 notes, rebuild timing, and the 24 macOS screenshots. - Complete the server gate: `cargo test -p calternal-server -- --test-threads=4`. - Run staging only through `~/.local/state/codex-jobs/calternal/deploy-staging.sh <tag>` after reading it; build as `/mnt/hdd/targets/staging-build/build.sh`, then verify the 2023 Calendar Week in 1440 light/dark and attach those screenshots. - Production requires no post-deploy command; startup enqueues the projection rebuild automatically.
Author
Owner

Starting staging verification of #724 on job/hotfix-724, base 7f76bc2d9c0ced62b0ed43be877c6320b2be7ada. Staging currently runs staging-c82b9aca1 (image ID dbf16b4d5a45). I will upload 120 generated Daily notes by WebDAV before the candidate starts, then check the automatic rebuild, Calendar range/year counts, unchanged source hashes, and macOS-rendered Week/Year screenshots. Production is outside this job. The staging environment remains unchanged.

Starting staging verification of #724 on `job/hotfix-724`, base `7f76bc2d9c0ced62b0ed43be877c6320b2be7ada`. Staging currently runs `staging-c82b9aca1` (image ID `dbf16b4d5a45`). I will upload 120 generated Daily notes by WebDAV before the candidate starts, then check the automatic rebuild, Calendar range/year counts, unchanged source hashes, and macOS-rendered Week/Year screenshots. Production is outside this job. The staging environment remains unchanged.
Author
Owner

Staging pre-upgrade evidence: all 120 Daily notes uploaded by WebDAV while image staging-c82b9aca1 was running. Calendar range queries return exactly 384 colon-form entries (96 per year, 2022–2025), with every start/end time and Tag verified. The 576 HHMM lines remain absent on 7a, as expected. SHA-256 was captured from WebDAV GET for all 120 source files. Upload plus range checks and baseline reads took 41.824 s. Release image build is running with four jobs and the assigned target.

Staging pre-upgrade evidence: all 120 Daily notes uploaded by WebDAV while image `staging-c82b9aca1` was running. Calendar range queries return exactly 384 colon-form entries (96 per year, 2022–2025), with every start/end time and Tag verified. The 576 HHMM lines remain absent on 7a, as expected. SHA-256 was captured from WebDAV GET for all 120 source files. Upload plus range checks and baseline reads took 41.824 s. Release image build is running with four jobs and the assigned target.
Author
Owner

Verification checkpoint: the pre-upgrade Calendar range and Year APIs both return 384 generated entries; all expected dates, times and Tags pass. Re-reading all 120 WebDAV files matches the saved SHA-256 hashes. The import-window server log has 8,778 lines and zero WARN, ERROR or panic records. cargo fmt --check exited 0 with no output. bun run check exited 0 with:

$ 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/hotfix-724/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

The release image is compiling with four jobs. The candidate server code is unchanged from 7f76bc2d9; the origin/dev merge added only DESIGN text, and this job adds the staging verification scripts.

Verification checkpoint: the pre-upgrade Calendar range and Year APIs both return 384 generated entries; all expected dates, times and Tags pass. Re-reading all 120 WebDAV files matches the saved SHA-256 hashes. The import-window server log has 8,778 lines and zero WARN, ERROR or panic records. `cargo fmt --check` exited 0 with no output. `bun run check` exited 0 with: ```text $ 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/hotfix-724/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` The release image is compiling with four jobs. The candidate server code is unchanged from `7f76bc2d9`; the origin/dev merge added only DESIGN text, and this job adds the staging verification scripts.
Author
Owner

Build checkpoint: the locked release build has reached calternal-plugin-notes, calternal-auth and calternal-embed. It is still running with four jobs and has not reported an error. Staging remains on staging-c82b9aca1; Notes migration is 26 (read-only Index query). The 120-file WebDAV import and pre-upgrade range/year/hash checks are complete. No production action was taken.

Build checkpoint: the locked release build has reached `calternal-plugin-notes`, `calternal-auth` and `calternal-embed`. It is still running with four jobs and has not reported an error. Staging remains on `staging-c82b9aca1`; Notes migration is 26 (read-only Index query). The 120-file WebDAV import and pre-upgrade range/year/hash checks are complete. No production action was taken.
Author
Owner

READY FOR PRODUCTION: yes — HHMM staging upgrade passed.

Built and deployed: staging-564114585 on staging only (https://dev.calternal.com). Image ID: b5945fc97c121373db65f38861d900a9bcb0c7a3d26fc68a8294432606902e3f. Embedded server revision: 5641145854dd3c1cbb94a288a903386464adc744. The server code is the approved hotfix at 7f76bc2d9; later commits add staging tests and DESIGN text. Production was not accessed or changed.

Branch and head: job/hotfix-724, b90ec4b50f1ca79ab56b8c5e031d1e3524100091. origin/dev was fetched and merged once (72f4008cc); that merge added only DESIGN text. The worktree is clean. No push was made.

Files: scripts/staging-724-build.sh, apps/web/e2e/staging-daily-log-724.mjs. docs/DESIGN.md changed only through the required merge. The build script follows the staging image recipe, uses the assigned target and four build jobs, and keeps deployment separate from fixture import.

Upgrade evidence: staging already ran staging-c82b9aca1, so no downgrade was needed. All 120 generated Daily notes were uploaded by WebDAV before the hotfix started. They cover 2022–2025, decorated ## 📝 Log headings, 576 HHMM ranges, 384 colon ranges, 24 free-form days, Tasks, Tags and unrelated text. The import plus baseline checks took 41.824 s.

Year 7a entries Hotfix entries Newly visible HHMM
2022 96 240 144
2023 96 240 144
2024 96 240 144
2025 96 240 144
Total 384 960 576

Both /api/v1/calendar/range and /api/v1/calendar/year matched generated counts on every fixture date. Every returned Log start/end and Tag was checked, not only spot-checked. Example: the 2023-06-12 compact 0915 - 0945 entry appears at 09:15–09:45 with area/personal. All 120 SHA-256 hashes from WebDAV GET are unchanged. A read-only Index check confirms that all 120 fixture Tasks remain indexed. Two HHMM Search targets returned without a timeout.

Notes migration changed from 26 to 27. No manual reconcile or rebuild request was sent. The automatic Jobs API record completed 123/123 Daily notes (120 fixtures plus 3 existing Daily notes), from 2026-10-03T15:16:13.390Z to 2026-10-03T15:16:22.595Z: 9.205 s, including queue scheduling. The staging environment file has the same SHA-256 before and after deployment; the commented Notes IMAP edge settings remain as supplied.

Server log: the pre-upgrade import window had 8,778 lines, zero WARN, zero ERROR and zero panics. The final deployment/verification window had 6240 lines, zero ERROR and zero panics, but 278 WARN records: 276 from the existing empty-title Task filter (#623), and 2 from Tantivy segment management. Thus the log is not warning-free. I filed #1016 with the evidence. No source loss or projection failure was found; this warning-only follow-up does not block under the owner rule. The raw logs stay private.

Gate output (verbatim): cargo fmt --check, node --check apps/web/e2e/staging-daily-log-724.mjs, bash -n scripts/staging-724-build.sh and git diff --check exited 0 with no output. No Rust source changed in this job, so no crate Clippy/test suite was repeated.

bun run --cwd apps/web check:

$ 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/hotfix-724/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

Locked release build:

    Finished `release` profile [optimized] target(s) in 40m 44s

bun apps/web/e2e/staging-daily-log-724.mjs check-before:

Calendar range/year: 384 entries; all dates, times and Tags match (7a)
staging-daily-log-724 check-before: passed

bun apps/web/e2e/staging-daily-log-724.mjs verify:

Automatic rebuild: 123/123 notes, queue-to-completion 9205 ms
Calendar range/year: 960 entries; all dates, times and Tags match (#724)
WebDAV SHA-256: all 120 Daily notes unchanged
Captured week 1440 light (macOS)
Calendar HHMM preview opens; Escape closes it
Captured year 1440 light (macOS)
Captured week 1440 dark (macOS)
Captured year 1440 dark (macOS)
Captured week 820 light (macOS)
Captured year 820 light (macOS)
Captured week 820 dark (macOS)
Captured year 820 dark (macOS)
Captured week 390 light (macOS)
Captured year 390 light (macOS)
Captured week 390 dark (macOS)
Captured year 390 dark (macOS)
staging-daily-log-724 verify: passed

Deployment:

staging deployed localhost/calternal-cloud:staging-564114585: healthy

cargo clean:

     Removed 8045 files, 2.8GiB total

Web build output and the temporary deployment binaries/archive were removed. Screenshots remain in gitignored artifacts/stage-724/ and are attached here, not committed.

UX gaps closed: the old HHMM history now renders in Calendar; its Journal preview opens and closes with Escape; Week/Year deep links restore the requested 2023 view. All 12 screenshots use macOS rendering at 1440, 820 and 390 px, in light/dark. There were no browser runtime errors. Browser plugin not available; the existing Playwright helpers were used. Three test setup errors were corrected without changing production code: the missing User-storage test hook, the current Journal dialog label, and the Year view’s independent readiness selector.

UX gaps left / known gaps: the orchestrator still reviews the attached pixels. This round tested 120 generated staging notes, not the full 656-note local fixture. Warning follow-up #1016 remains open. Production and real macOS client interoperability were not tested in this job.

For the merge round: cargo test -p calternal-server -- --test-threads=4 must complete the previously unfinished server gate; bun run --cwd apps/web test --maxWorkers=2 runs the combined web suite; bun apps/web/e2e/daily-log-upgrade-724.mjs with old/candidate binaries must cover the full 656-note upgrade. Full adversarial matrices and real Mac interoperability remain merge-round work under the shared verification policy.

Decisions: no product design decision was needed. I used 30 June dates per year to make the 2023 Week/Year evidence easy to inspect; each year has 24 timed days and 6 free-form days. Rebuild timing is queue creation to completion, not a pure worker CPU measurement. Existing staging data was retained. Warning-only diagnostics with no observed data loss are filed as a non-blocking follow-up, rather than being described as a warning-free log.

Screenshots:

1440 px, macOS rendering:

820 px, macOS rendering:

390 px, macOS rendering:

**READY FOR PRODUCTION: yes — HHMM staging upgrade passed.** **Built and deployed:** `staging-564114585` on staging only (`https://dev.calternal.com`). Image ID: `b5945fc97c121373db65f38861d900a9bcb0c7a3d26fc68a8294432606902e3f`. Embedded server revision: `5641145854dd3c1cbb94a288a903386464adc744`. The server code is the approved hotfix at `7f76bc2d9`; later commits add staging tests and DESIGN text. Production was not accessed or changed. **Branch and head:** `job/hotfix-724`, `b90ec4b50f1ca79ab56b8c5e031d1e3524100091`. `origin/dev` was fetched and merged once (`72f4008cc`); that merge added only DESIGN text. The worktree is clean. No push was made. **Files:** `scripts/staging-724-build.sh`, `apps/web/e2e/staging-daily-log-724.mjs`. `docs/DESIGN.md` changed only through the required merge. The build script follows the staging image recipe, uses the assigned target and four build jobs, and keeps deployment separate from fixture import. **Upgrade evidence:** staging already ran `staging-c82b9aca1`, so no downgrade was needed. All 120 generated Daily notes were uploaded by WebDAV before the hotfix started. They cover 2022–2025, decorated `## 📝 Log` headings, 576 HHMM ranges, 384 colon ranges, 24 free-form days, Tasks, Tags and unrelated text. The import plus baseline checks took 41.824 s. | Year | 7a entries | Hotfix entries | Newly visible HHMM | |---|---:|---:|---:| | 2022 | 96 | 240 | 144 | | 2023 | 96 | 240 | 144 | | 2024 | 96 | 240 | 144 | | 2025 | 96 | 240 | 144 | | Total | 384 | 960 | 576 | Both `/api/v1/calendar/range` and `/api/v1/calendar/year` matched generated counts on every fixture date. Every returned Log start/end and Tag was checked, not only spot-checked. Example: the 2023-06-12 compact `0915 - 0945` entry appears at `09:15–09:45` with `area/personal`. All 120 SHA-256 hashes from WebDAV GET are unchanged. A read-only Index check confirms that all 120 fixture Tasks remain indexed. Two HHMM Search targets returned without a timeout. Notes migration changed from 26 to 27. No manual reconcile or rebuild request was sent. The automatic Jobs API record completed 123/123 Daily notes (120 fixtures plus 3 existing Daily notes), from `2026-10-03T15:16:13.390Z` to `2026-10-03T15:16:22.595Z`: **9.205 s**, including queue scheduling. The staging environment file has the same SHA-256 before and after deployment; the commented Notes IMAP edge settings remain as supplied. **Server log:** the pre-upgrade import window had 8,778 lines, zero WARN, zero ERROR and zero panics. The final deployment/verification window had 6240 lines, zero ERROR and zero panics, but 278 WARN records: 276 from the existing empty-title Task filter (#623), and 2 from Tantivy segment management. Thus the log is not warning-free. I filed [#1016](https://git.kayg.org/kayg/calternal/issues/1016) with the evidence. No source loss or projection failure was found; this warning-only follow-up does not block under the owner rule. The raw logs stay private. **Gate output (verbatim):** `cargo fmt --check`, `node --check apps/web/e2e/staging-daily-log-724.mjs`, `bash -n scripts/staging-724-build.sh` and `git diff --check` exited 0 with no output. No Rust source changed in this job, so no crate Clippy/test suite was repeated. `bun run --cwd apps/web check`: ```text $ 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/hotfix-724/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` Locked release build: ```text Finished `release` profile [optimized] target(s) in 40m 44s ``` `bun apps/web/e2e/staging-daily-log-724.mjs check-before`: ```text Calendar range/year: 384 entries; all dates, times and Tags match (7a) staging-daily-log-724 check-before: passed ``` `bun apps/web/e2e/staging-daily-log-724.mjs verify`: ```text Automatic rebuild: 123/123 notes, queue-to-completion 9205 ms Calendar range/year: 960 entries; all dates, times and Tags match (#724) WebDAV SHA-256: all 120 Daily notes unchanged Captured week 1440 light (macOS) Calendar HHMM preview opens; Escape closes it Captured year 1440 light (macOS) Captured week 1440 dark (macOS) Captured year 1440 dark (macOS) Captured week 820 light (macOS) Captured year 820 light (macOS) Captured week 820 dark (macOS) Captured year 820 dark (macOS) Captured week 390 light (macOS) Captured year 390 light (macOS) Captured week 390 dark (macOS) Captured year 390 dark (macOS) staging-daily-log-724 verify: passed ``` Deployment: ```text staging deployed localhost/calternal-cloud:staging-564114585: healthy ``` `cargo clean`: ```text Removed 8045 files, 2.8GiB total ``` Web build output and the temporary deployment binaries/archive were removed. Screenshots remain in gitignored `artifacts/stage-724/` and are attached here, not committed. **UX gaps closed:** the old HHMM history now renders in Calendar; its Journal preview opens and closes with Escape; Week/Year deep links restore the requested 2023 view. All 12 screenshots use macOS rendering at 1440, 820 and 390 px, in light/dark. There were no browser runtime errors. Browser plugin not available; the existing Playwright helpers were used. Three test setup errors were corrected without changing production code: the missing User-storage test hook, the current Journal dialog label, and the Year view’s independent readiness selector. **UX gaps left / known gaps:** the orchestrator still reviews the attached pixels. This round tested 120 generated staging notes, not the full 656-note local fixture. Warning follow-up #1016 remains open. Production and real macOS client interoperability were not tested in this job. **For the merge round:** `cargo test -p calternal-server -- --test-threads=4` must complete the previously unfinished server gate; `bun run --cwd apps/web test --maxWorkers=2` runs the combined web suite; `bun apps/web/e2e/daily-log-upgrade-724.mjs` with old/candidate binaries must cover the full 656-note upgrade. Full adversarial matrices and real Mac interoperability remain merge-round work under the shared verification policy. **Decisions:** no product design decision was needed. I used 30 June dates per year to make the 2023 Week/Year evidence easy to inspect; each year has 24 timed days and 6 free-form days. Rebuild timing is queue creation to completion, not a pure worker CPU measurement. Existing staging data was retained. Warning-only diagnostics with no observed data loss are filed as a non-blocking follow-up, rather than being described as a warning-free log. **Screenshots:** 1440 px, macOS rendering: - [Week light](https://git.kayg.org/attachments/bd07fb02-19fc-4162-90bb-ccc0771d1ad1) - [Week dark](https://git.kayg.org/attachments/70f8ddf0-0deb-4e80-9fa8-bfb3430956d9) - [Year light](https://git.kayg.org/attachments/8b08abbd-182d-48f2-b2ca-bdeef0c0a29a) - [Year dark](https://git.kayg.org/attachments/1734b836-971a-486e-a75f-6f4a266dd2a8) 820 px, macOS rendering: - [Week light](https://git.kayg.org/attachments/745b66c9-499a-4d7c-b2fb-f2292331308a) - [Week dark](https://git.kayg.org/attachments/c44ce1a7-800a-45a7-9e33-2fb0f939e19d) - [Year light](https://git.kayg.org/attachments/22b7c713-b3ae-437e-9d7b-39d89ef531bc) - [Year dark](https://git.kayg.org/attachments/f87ca8a2-0c53-4aee-94c5-9bfc24a9b6b9) 390 px, macOS rendering: - [Week light](https://git.kayg.org/attachments/5fa4e8f0-c69a-4da5-8dec-3b96fc44dd5d) - [Week dark](https://git.kayg.org/attachments/1153d56d-227a-4f22-af49-981778479fbb) - [Year light](https://git.kayg.org/attachments/af1f9484-655a-459d-b087-64ca5bcea3f9) - [Year dark](https://git.kayg.org/attachments/c72d7220-1b60-4760-a2ae-ac3047889e58)
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#724
No description provided.