TASKS: Tasks mode (TickTick ease, Obsidian plaintext): views, board/list/matrix (grill in progress) #430

Open
opened 2026-09-29 11:42:14 +00:00 by kayg · 50 comments
Owner

Goal (owner, 2026-09-29)

A Tasks mode with "the ease of use and versatility of TickTick and the plaintextness of Obsidian (our tasks model basically)". Default modes in the tray: Calendar, Tasks, Notes, Files, Photos, Analytics. Other plugin modes (Mail, Money …) are hidden from the tray and added from Settings → Plugins (T9 = a).

The model (already decided, DESIGN §31, §43)

  • A task is a note with task frontmatter.
  • Fields: title, status (todo, doing, blocked, waiting, done, cancelled), priority (4 levels), start, scheduled, due (date plus optional time), recurrence, estimate, area, created, completed.
  • #x inside a task becomes #task/x.
  • Tasks show in Calendar and sync to Apple Reminders over CalDAV VTODO.

Decisions so far (grill in progress)

  • T1: no "lists". Tags appear as they are, and the User makes views (saved searches, smart lists) over plaintext tasks.
  • T2: the sidebar is all views: built-in smart views (Inbox, Today, Next 7 days, Upcoming, Someday, Completed, Won't do), the tag tree, and saved views. Views are stored as plaintext (format pending T10). Storage: user files live on the HDD root; calternal reads through its Index on the SSD state root (DESIGN §20), so small view files cost nothing at read time.
  • T3: the default layout is a Kanban board. The layouts are List, Board and Matrix (Eisenhower), all views over plaintext tasks. Timeline comes later.
  • T4: subtasks are checkboxes inside the task's note, and each can be promoted to a full task.
  • T5: checkbox lines anywhere ("dumb tasks") appear in Tasks, can be ticked there, and can be promoted to a full task.
  • T6: add tasks through the composer's Task mode (NLP), plus a "+ Add task" row per view that pre-fills the view's filter values.
  • T7: recurrence is written readably and mapped to RRULE; completing creates the next occurrence in the same file, and each completion is written to the Journal. The date fields and the Reminders mapping are pending T12.
  • T8: time logging must be "dead easy" (TickTick's is annoying), but it comes later.
## Goal (owner, 2026-09-29) A Tasks mode with "the ease of use and versatility of TickTick and the plaintextness of Obsidian (our tasks model basically)". Default modes in the tray: **Calendar, Tasks, Notes, Files, Photos, Analytics**. Other plugin modes (Mail, Money …) are hidden from the tray and added from Settings → Plugins (T9 = a). ## The model (already decided, DESIGN §31, §43) - A task is a note with task frontmatter. - Fields: `title`, `status` (todo, doing, blocked, waiting, done, cancelled), `priority` (4 levels), `start`, `scheduled`, `due` (date plus optional time), `recurrence`, `estimate`, `area`, `created`, `completed`. - `#x` inside a task becomes `#task/x`. - Tasks show in Calendar and sync to Apple Reminders over CalDAV VTODO. ## Decisions so far (grill in progress) - **T1:** no "lists". Tags appear as they are, and the User makes **views** (saved searches, smart lists) over plaintext tasks. - **T2:** the sidebar is all views: built-in smart views (Inbox, Today, Next 7 days, Upcoming, Someday, Completed, Won't do), the tag tree, and saved views. Views are stored as plaintext (format pending T10). Storage: user files live on the HDD root; calternal reads through its Index on the SSD state root (DESIGN §20), so small view files cost nothing at read time. - **T3:** the default layout is a **Kanban board**. The layouts are List, Board and Matrix (Eisenhower), all views over plaintext tasks. Timeline comes later. - **T4:** subtasks are checkboxes inside the task's note, and each can be promoted to a full task. - **T5:** checkbox lines anywhere ("dumb tasks") appear in Tasks, can be ticked there, and can be promoted to a full task. - **T6:** add tasks through the composer's Task mode (NLP), plus a "+ Add task" row per view that pre-fills the view's filter values. - **T7:** recurrence is written readably and mapped to RRULE; completing creates the next occurrence in the same file, and each completion is written to the Journal. The date fields and the Reminders mapping are pending T12. - **T8:** time logging must be "dead easy" (TickTick's is annoying), but it comes later.
Author
Owner

Owner decisions, round 2 (2026-09-29):

  • T11 agreed: the default board columns are Todo · Doing · Waiting · Blocked · Done, with Cancelled hidden; dragging changes status; any view can group by priority, tag or due bucket.
  • T15 agreed: a finished task stays in place with status done and a completed date; files are never moved or archived.
  • T16 agreed: the glossary has Checkbox (a - [ ] line anywhere) and Task (a note with task frontmatter); the UI says 'Make task'.
  • T14: the composer's NLP must also run on checkbox lines. Still open: whether a checkbox auto-converts to a Task (the orchestrator proposes converting only when it gets metadata; see T14b).
  • T13: open. How do contexts appear in Reminders? Apple Reminders tags over CalDAV are untested (#393 matrix row 'Tags': not run).
  • T12: open. Does Reminders expose a start date? Its UI shows none; the DTSTART behaviour over CalDAV is untested.
  • T10: open. Bases is extensible: Obsidian's registerBasesView API lets plugins add view types, and Obsidian 1.14 has a native Kanban view type.
Owner decisions, round 2 (2026-09-29): - T11 agreed: the default board columns are Todo · Doing · Waiting · Blocked · Done, with Cancelled hidden; dragging changes status; any view can group by priority, tag or due bucket. - T15 agreed: a finished task stays in place with status done and a completed date; files are never moved or archived. - T16 agreed: the glossary has **Checkbox** (a `- [ ]` line anywhere) and **Task** (a note with task frontmatter); the UI says 'Make task'. - T14: the composer's NLP must also run on checkbox lines. Still open: whether a checkbox auto-converts to a Task (the orchestrator proposes converting only when it gets metadata; see T14b). - T13: open. How do contexts appear in Reminders? Apple Reminders tags over CalDAV are untested (#393 matrix row 'Tags': not run). - T12: open. Does Reminders expose a start date? Its UI shows none; the DTSTART behaviour over CalDAV is untested. - T10: open. Bases is extensible: Obsidian's registerBasesView API lets plugins add view types, and Obsidian 1.14 has a native Kanban view type.
Author
Owner

Owner decisions, round 3 (2026-09-29):

  • T10: views are Obsidian Bases .base YAML files in a visible Views/ folder. Board and Matrix are additional view types; where Obsidian's native Kanban view type matches, use its format.
  • T14b: a Checkbox converts to a Task note automatically when it gets metadata (date, priority, repeat, reminder, notes). The line becomes - [ ] → [Title](Notes/…) and mirrors the status both ways; Undo reverts the conversion. The composer NLP runs on Checkbox lines. The Obsidian Tasks inline format (📅 ⏫ …) is read only, and converted to Task notes on demand ('Convert to tasks'), never written.
  • T13: contexts use the fallback (the owner's exact choice between 'not in Reminders' and 'appended to notes' is being confirmed).
  • T12: open. The owner asked whether start is needed next to scheduled (GTD view) and what alerts are.
Owner decisions, round 3 (2026-09-29): - T10: views are Obsidian **Bases** `.base` YAML files in a visible `Views/` folder. Board and Matrix are additional view types; where Obsidian's native Kanban view type matches, use its format. - T14b: a Checkbox converts to a Task note automatically **when it gets metadata** (date, priority, repeat, reminder, notes). The line becomes `- [ ] → [Title](Notes/…)` and mirrors the status both ways; Undo reverts the conversion. The composer NLP runs on Checkbox lines. The Obsidian Tasks inline format (📅 ⏫ …) is **read only**, and converted to Task notes on demand ('Convert to tasks'), never written. - T13: contexts use the fallback (the owner's exact choice between 'not in Reminders' and 'appended to notes' is being confirmed). - T12: open. The owner asked whether `start` is needed next to `scheduled` (GTD view) and what alerts are.
Author
Owner

Owner decisions, round 4 (2026-09-29):

  • T12b: only two dates: scheduled: (shown as When: the day the task appears in Today and on the Calendar, hidden from Today before then) and due: (shown as Deadline). start: is read-only for Obsidian imports (treated as scheduled when no scheduled is set) and never written.
  • T13 (a): contexts (#context/…) are a calternal-only filter and do not appear in Reminders at all.
  • Reminders: no separate reminder date. Being refined (proposal R1–R3 in the next grill round, based on the owner's calternal.js design: remind: true/false applies to the task's dates, with the lead time in Settings → Tasks).
Owner decisions, round 4 (2026-09-29): - T12b: **only two dates**: `scheduled:` (shown as When: the day the task appears in Today and on the Calendar, hidden from Today before then) and `due:` (shown as Deadline). `start:` is read-only for Obsidian imports (treated as scheduled when no scheduled is set) and never written. - T13 (a): contexts (`#context/…`) are a calternal-only filter and do not appear in Reminders at all. - Reminders: no separate reminder date. Being refined (proposal R1–R3 in the next grill round, based on the owner's calternal.js design: `remind: true/false` applies to the task's dates, with the lead time in Settings → Tasks).
Author
Owner

Owner decisions, reminders (2026-09-29):

  • R1: a separate remind: property exists, because blocks (Checkbox lines and other blocks) can carry a reminder without being converted to a Task. This is the block-reminder design, DESIGN §'reminders', calternal-reminders keyed by block ^id. It is an exception to T14b: a reminder alone never converts a Checkbox to a Task; a date, priority, repeat or notes still does. On a Task, remind: is auto-filled from the When (scheduled) and Deadline (due) dates, and the User may change or add instants.
  • R2: remind: false switches reminders off for a Task; the default is on and is not written.
  • R3: Settings → Tasks → Reminders holds the lead time (default: at the time), the time for all-day dates (default 09:00), and a Deadline heads-up the day before (default on). A per-Task override is allowed.
  • Apple Reminders: these map to VALARMs; edits on the phone are read back into remind:.
Owner decisions, reminders (2026-09-29): - R1: a **separate `remind:` property** exists, because blocks (Checkbox lines and other blocks) can carry a reminder **without being converted to a Task**. This is the block-reminder design, DESIGN §'reminders', `calternal-reminders` keyed by block ^id. It is an **exception to T14b**: a reminder alone never converts a Checkbox to a Task; a date, priority, repeat or notes still does. On a Task, `remind:` is **auto-filled** from the When (`scheduled`) and Deadline (`due`) dates, and the User may change or add instants. - R2: `remind: false` switches reminders off for a Task; the default is on and is not written. - R3: Settings → Tasks → Reminders holds the lead time (default: at the time), the time for all-day dates (default 09:00), and a Deadline heads-up the day before (default on). A per-Task override is allowed. - Apple Reminders: these map to VALARMs; edits on the phone are read back into `remind:`.
Author
Owner

Found by #424's benchmark: the live tray on dev shows only five modes; Notes and Tasks are absent. The owner's default tray (T9 and the default-modes decision) is Calendar, Tasks, Notes, Files, Photos, Analytics, with other plugin modes (Mail, Money …) hidden and added from Settings → Plugins. The Tasks mode job must set this default order and make Notes visible. Check why Notes is missing today: is it disabled by default, or missing from MODE list?

Found by #424's benchmark: the live tray on dev shows only five modes; **Notes and Tasks are absent**. The owner's default tray (T9 and the default-modes decision) is Calendar, Tasks, Notes, Files, Photos, Analytics, with other plugin modes (Mail, Money …) hidden and added from Settings → Plugins. The Tasks mode job must set this default order and make Notes visible. Check why Notes is missing today: is it disabled by default, or missing from MODE list?
Author
Owner

Starting #430 on job/tasks-mode at base SHA 369ab6a2f9fc673e3564b94857fbecfeb04df404. I read the full issue thread and the binding repo docs. Existing task model/parser and Notes API are in calternal-notes-core and calternal-plugin-notes; I’m tracing the current gaps before making the first test-backed slice.

Starting #430 on `job/tasks-mode` at base SHA `369ab6a2f9fc673e3564b94857fbecfeb04df404`. I read the full issue thread and the binding repo docs. Existing task model/parser and Notes API are in `calternal-notes-core` and `calternal-plugin-notes`; I’m tracing the current gaps before making the first test-backed slice.
Author
Owner

Finding: the web shell does not yet expose a Tasks mode or a .base Views implementation. apps/web/src/lib/navigation.ts has no tasks navigation item and maps /notes into Calendar; apps/web/src/routes has no Tasks route; no .base files or Bases reader/writer are present. The Notes plugin already provides real Task collection and mutation routes (GET /tasks, /tasks/day, /tasks/standalone, /tasks/by-id, PATCH /tasks/properties, POST /tasks/tick), so the UI can use the real Index data while I add the missing view model and screen.

Finding: the web shell does not yet expose a Tasks mode or a `.base` Views implementation. `apps/web/src/lib/navigation.ts` has no `tasks` navigation item and maps `/notes` into Calendar; `apps/web/src/routes` has no Tasks route; no `.base` files or Bases reader/writer are present. The Notes plugin already provides real Task collection and mutation routes (`GET /tasks`, `/tasks/day`, `/tasks/standalone`, `/tasks/by-id`, `PATCH /tasks/properties`, `POST /tasks/tick`), so the UI can use the real Index data while I add the missing view model and screen.
Author
Owner

Finding: the Task writer used the imported start_time whenever scheduled_time was absent, even when an explicit scheduled: date existed. The added regression test failed on that case. Commit 1fd173d26 now uses start_time only when start: supplies the effective When date; cargo test -p calternal-notes-core --quiet passes (503 + 13 + 5 + 7 + 12 tests).

Finding: the Task writer used the imported `start_time` whenever `scheduled_time` was absent, even when an explicit `scheduled:` date existed. The added regression test failed on that case. Commit `1fd173d26` now uses `start_time` only when `start:` supplies the effective When date; `cargo test -p calternal-notes-core --quiet` passes (503 + 13 + 5 + 7 + 12 tests).
Author
Owner

Resuming #430 after the usage-limit interruption. Branch: job/tasks-mode; current HEAD: 261a8ff0ff2ba18403ee35408fc431bbfe33aa97; original branch base recorded on start: 369ab6a2f9fc673e3564b94857fbecfeb04df404. The worktree has an uncommitted Notes saved-views API and mode-navigation slice; I am validating it before committing and continuing from there.

Resuming #430 after the usage-limit interruption. Branch: `job/tasks-mode`; current HEAD: `261a8ff0ff2ba18403ee35408fc431bbfe33aa97`; original branch base recorded on start: `369ab6a2f9fc673e3564b94857fbecfeb04df404`. The worktree has an uncommitted Notes saved-views API and mode-navigation slice; I am validating it before committing and continuing from there.
Author
Owner

Finding: the first Notes route-test build failed at compile time because the test passed an owned String to RelPath::join, which accepts &str (error[E0308] at crates/plugins/notes/src/lib.rs:5944). I changed the test to borrow the formatted path and am rerunning the focused route tests.

Finding: the first Notes route-test build failed at compile time because the test passed an owned `String` to `RelPath::join`, which accepts `&str` (`error[E0308]` at `crates/plugins/notes/src/lib.rs:5944`). I changed the test to borrow the formatted path and am rerunning the focused route tests.
Author
Owner

Resuming #430 implementation on branch job/tasks-mode.

  • Original branch base: 369ab6a2f9fc673e3564b94857fbecfeb04df404
  • Current head before resume: 261a8ff0ff2ba18403ee35408fc431bbfe33aa97
  • origin/dev observed at resume: dfb5964a2fcf13dc8b9a50a319eee09bc386f322

I am preserving the existing committed task model/parser work and inspecting the interrupted saved-view/API and Tasks mode changes before continuing.

Resuming #430 implementation on branch `job/tasks-mode`. - Original branch base: `369ab6a2f9fc673e3564b94857fbecfeb04df404` - Current head before resume: `261a8ff0ff2ba18403ee35408fc431bbfe33aa97` - `origin/dev` observed at resume: `dfb5964a2fcf13dc8b9a50a319eee09bc386f322` I am preserving the existing committed task model/parser work and inspecting the interrupted saved-view/API and Tasks mode changes before continuing.
Author
Owner

Finding from the full Notes crate gate: cargo test -p calternal-plugin-notes ran 123 tests and reported 121 passed, 2 failed. macos27_daily_repeat_persists_markdown_and_dav_fields still expects recurrence: FREQ=DAILY, but #430's committed repeat writer now stores readable repeat: text; I will update that assertion to the issue-approved representation while keeping its RRULE projection checks. vtodo_wire_upgrade_rotates_sync_epoch_once removes the last registered migration, which is now Notes migration 19; the wire epoch migration is version 18. I will make the test construct its pre-wire state by version so the existing epoch assertions still exercise migration 18.

Finding from the full Notes crate gate: `cargo test -p calternal-plugin-notes` ran 123 tests and reported 121 passed, 2 failed. `macos27_daily_repeat_persists_markdown_and_dav_fields` still expects `recurrence: FREQ=DAILY`, but #430's committed repeat writer now stores readable `repeat:` text; I will update that assertion to the issue-approved representation while keeping its RRULE projection checks. `vtodo_wire_upgrade_rotates_sync_epoch_once` removes the last registered migration, which is now Notes migration 19; the wire epoch migration is version 18. I will make the test construct its pre-wire state by version so the existing epoch assertions still exercise migration 18.
Author
Owner

The full Notes test rerun now passes the VTODO epoch test, but macos27_daily_repeat_persists_markdown_and_dav_fields still fails because a supported incoming FREQ=DAILY value is stored in Markdown without being rendered as the required readable repeat: phrase. I am adding a bounded RRULE-to-Task conversion and keeping the existing RRULE read-back assertions.

The full Notes test rerun now passes the VTODO epoch test, but `macos27_daily_repeat_persists_markdown_and_dav_fields` still fails because a supported incoming `FREQ=DAILY` value is stored in Markdown without being rendered as the required readable `repeat:` phrase. I am adding a bounded RRULE-to-Task conversion and keeping the existing RRULE read-back assertions.
Author
Owner

Progress on job/tasks-mode: committed c600e6e35 (from the resumed branch head). The mode registry now keeps Tasks and Notes separate, applies the six owner-selected default modes, and exposes the built-in Task views from the sidebar. The Task view date rules treat imported start as scheduled, and focused web tests passed: 3 files, 20 tests. The first Svelte check found no errors and three accessibility/CSS warnings in the new Board/Matrix files; I corrected those and will include the clean result with final gates.

Progress on `job/tasks-mode`: committed `c600e6e35` (from the resumed branch head). The mode registry now keeps Tasks and Notes separate, applies the six owner-selected default modes, and exposes the built-in Task views from the sidebar. The Task view date rules treat imported `start` as `scheduled`, and focused web tests passed: 3 files, 20 tests. The first Svelte check found no errors and three accessibility/CSS warnings in the new Board/Matrix files; I corrected those and will include the clean result with final gates.
Author
Owner

Progress on job/tasks-mode: 1bf0c4ebf adds the real-data Tasks workspace with Board (virtual status lanes, drag/drop and keyboard Status control), List and priority-by-Deadline Matrix layouts. The Board is the default and cancelled Tasks stay out of its workflow lanes. Verification so far:

svelte-check found 0 errors and 0 warnings
Test Files  3 passed (3)
     Tests  20 passed (20)

Saved .base view loading and route integration remain in progress.

Progress on `job/tasks-mode`: `1bf0c4ebf` adds the real-data Tasks workspace with Board (virtual status lanes, drag/drop and keyboard Status control), List and priority-by-Deadline Matrix layouts. The Board is the default and cancelled Tasks stay out of its workflow lanes. Verification so far: ``` svelte-check found 0 errors and 0 warnings Test Files 3 passed (3) Tests 20 passed (20) ``` Saved `.base` view loading and route integration remain in progress.
Author
Owner

While wiring the Tasks saved-view client, I found that the API returned each per-view object but omitted the file-level filters: value that TaskBase already parses. This would make a valid hand-edited .base appear unfiltered in Tasks. The #430 API now includes base_filters with each saved view, and a regression test covers an externally written file. I also added a literal-only client evaluator so these filters do not execute file expressions.

While wiring the Tasks saved-view client, I found that the API returned each per-view object but omitted the file-level `filters:` value that `TaskBase` already parses. This would make a valid hand-edited `.base` appear unfiltered in Tasks. The #430 API now includes `base_filters` with each saved view, and a regression test covers an externally written file. I also added a literal-only client evaluator so these filters do not execute file expressions.
Author
Owner

A second live-update gap showed up while setting up the disk-edit proof: the server's filesystem bridge emits Home changes under plugin fs, but /api/v1/notes/events previously forwarded only plugin notes events. A hand-edited Views/*.base therefore did not reach Tasks. The Notes event stream now forwards only Notes/ and Views/ filesystem paths, with a regression test; the Tasks client also skips its short GET coalescing window for view-list reloads.

A second live-update gap showed up while setting up the disk-edit proof: the server's filesystem bridge emits Home changes under plugin `fs`, but `/api/v1/notes/events` previously forwarded only plugin `notes` events. A hand-edited `Views/*.base` therefore did not reach Tasks. The Notes event stream now forwards only `Notes/` and `Views/` filesystem paths, with a regression test; the Tasks client also skips its short GET coalescing window for view-list reloads.
Author
Owner

Web gate finding: bun run test completed in 427.42 seconds with 825 passing tests and 6 failures out of 831. The failures are 5-second timeouts in existing calendar agenda/TimeGrid, composer highlighting, analytics RangeBar/StatRow, and menu opening focus tests. The Tasks tests passed in this run. I did not change their expectations; the host was running several concurrent build and test jobs during this run.

Web gate finding: `bun run test` completed in 427.42 seconds with 825 passing tests and 6 failures out of 831. The failures are 5-second timeouts in existing calendar agenda/TimeGrid, composer highlighting, analytics RangeBar/StatRow, and menu opening focus tests. The Tasks tests passed in this run. I did not change their expectations; the host was running several concurrent build and test jobs during this run.
Author
Owner

Rust gate finding: cargo test -p calternal-plugin-notes ran 125 tests; 124 passed and the existing tests::journal_patch_storm_finishes_with_one_winner_and_stale_preconditions timed out. Its fixed 12-second tokio::time::timeout returned Elapsed(()); the full suite took 403.32 seconds on the shared build host. I left the test expectation unchanged. The new Notes filesystem event test and saved-view hostile input, round-trip, and global-filter tests all passed.

Rust gate finding: `cargo test -p calternal-plugin-notes` ran 125 tests; 124 passed and the existing `tests::journal_patch_storm_finishes_with_one_winner_and_stale_preconditions` timed out. Its fixed 12-second `tokio::time::timeout` returned `Elapsed(())`; the full suite took 403.32 seconds on the shared build host. I left the test expectation unchanged. The new Notes filesystem event test and saved-view hostile input, round-trip, and global-filter tests all passed.
Author
Owner

Production E2E findings and fixes for #430:

  • The keyboard status test issued its indexed GET immediately after selectOption('todo'); it read the previous doing value while the UI's async write was still in flight. The test now polls the authoritative API for the exact expected status. It does not relax the assertion.
  • Editing a saved .base file in place failed with EACCES because Notes files use immutable content-addressed inodes. The E2E now models an editor save with a sibling temporary file and atomic rename, which also preserves the shared blob.
  • The tablet/desktop screenshot flow queried #app-sidebar, which is only mounted by the phone drawer. It now targets .desktop-sidebar at 820/1440 px and moves the pointer off screenshot targets to avoid tooltip overlays.

The final production E2E passed: composer creation, Add task row, Board drag and status persistence, a disk-edited Bases view, and all 24 Board/List/Matrix/sidebar screenshots at 390/820/1440 px in light/dark. Output: tasks e2e: composer, Add task, Board drag, live Bases file edit, and screenshots passed in /home/kayg/Developer/calternal-wt/tasks-mode/artifacts/tasks-mode; CSP REPORTS tasks: 0 across 1 pages.

Production E2E findings and fixes for #430: - The keyboard status test issued its indexed GET immediately after `selectOption('todo')`; it read the previous `doing` value while the UI's async write was still in flight. The test now polls the authoritative API for the exact expected status. It does not relax the assertion. - Editing a saved `.base` file in place failed with `EACCES` because Notes files use immutable content-addressed inodes. The E2E now models an editor save with a sibling temporary file and atomic rename, which also preserves the shared blob. - The tablet/desktop screenshot flow queried `#app-sidebar`, which is only mounted by the phone drawer. It now targets `.desktop-sidebar` at 820/1440 px and moves the pointer off screenshot targets to avoid tooltip overlays. The final production E2E passed: composer creation, Add task row, Board drag and status persistence, a disk-edited Bases view, and all 24 Board/List/Matrix/sidebar screenshots at 390/820/1440 px in light/dark. Output: `tasks e2e: composer, Add task, Board drag, live Bases file edit, and screenshots passed in /home/kayg/Developer/calternal-wt/tasks-mode/artifacts/tasks-mode`; `CSP REPORTS tasks: 0 across 1 pages`.
Author
Owner

Tasks mode report (#430)

Built

  • Added a Notes-backed Task projection and Markdown Task Note writer. The parser preserves hand-edited frontmatter, supports the six Task statuses and priorities, reads imported start: as When only when scheduled: is absent, and reads/writes readable repeat: values with RRULE conversion.
  • Added lossless Obsidian Bases .base parsing and writing, bounded literal filter evaluation, stable view IDs, file-wide and per-view filters, sort/group handling, and Notes API routes for saved views. External Notes and Bases file events refresh the Task projection.
  • Added the Tasks mode Board, List, and Matrix; built-in and tag views in the sidebar; task/view deep links and Copy link actions; composer and per-view Add task flows; server-backed status changes; saved-view create/edit; and the default mode and optional-plugin settings behavior.
  • Added production E2E coverage for composer, Add task, Board drag and status persistence, a disk-edited Bases view, and screenshots. The 24 PNGs are attached to the E2E finding comment.

Files

  • Task model and serialization: crates/calternal-notes-core/src/tasks/ and crates/calternal-notes-core/src/nlp/{mod.rs,tasks_recurrence_md.rs}.
  • Notes API and CalDAV adapter: crates/plugins/notes/src/{lib.rs,task_views.rs,tasks_dav.rs}; contract/client: contracts/openapi.json, packages/api-client/src/generated.ts.
  • Tasks UI: apps/web/src/lib/tasks/, apps/web/src/routes/tasks/, apps/web/src/lib/{navigation.ts,navigation.test.ts,notes/noteIndex.svelte.ts,stores/settings-store.ts,stores/settings-store.test.ts}, apps/web/src/lib/components/{SidebarLinks.svelte,app-sidebar.svelte}, and apps/web/src/routes/settings/plugins/PluginsSection.svelte.
  • E2E/adversarial coverage: apps/web/e2e/tasks.mjs, apps/web/package.json, tests/adversarial/{attack2.py,xuser_matrix.py}.
  • Design/deep-link docs: docs/DESIGN.md, docs/deep-links.md.

Head and commits

  • Branch: job/tasks-mode
  • HEAD: 7ab6818b896ed14b06a6c295706a667b04c1d4f5
  • No push, deploy, or merge into dev was made. The required local origin/dev merge is commit 332498328.

Gates (output verbatim)

cargo fmt --check exited 0 with no stdout.

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

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 38m 19s

cargo test -p calternal-server:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 30m 28s

     Running unittests src/main.rs (/mnt/hdd/targets/jobs/tasks-mode/debug/deps/calternal_server-6bb5ac9c937be6dc)

running 87 tests

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

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

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

cargo test -p calternal-plugin-notes:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 5m 51s

    test result: ok. 130 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 195.80s

     Running tests/apple_replay.rs (/mnt/hdd/targets/jobs/tasks-mode/debug/deps/apple_replay-88163a6d50435d3a)

running 1 test
test completing_reminder_without_description_preserves_notes ... ok

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

   Doc-tests calternal_plugin_notes

running 0 tests

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

bun run check:

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

bun run test --maxWorkers=1:

 FAIL  |component| src/lib/components/ThemePicker.svelte.test.ts > ThemePicker variants > opens dark variants as a keyboard submenu and checks the selected variant
Error: Test timed out in 5000ms.

 Test Files  1 failed | 138 passed (139)
      Tests  1 failed | 893 passed (894)
   Duration  1484.54s (transform 39%, import 23%, environment 21%, tests 12%, setup 5%)

The same ThemePicker test timed out at 5919ms in its isolated rerun; its assertions were not changed.

bun run build:

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

node --check apps/web/e2e/tasks.mjs exited 0 with no stdout. Production E2E:

tasks e2e: composer, Add task, Board drag, live Bases file edit, and screenshots passed in /home/kayg/Developer/calternal-wt/tasks-mode/artifacts/tasks-mode
CSP REPORTS tasks: 0 across 1 pages

One time-boxed Tasks-view adversarial round:

Cross-User classification gate: 312 operations classified
---------- task_views ----------
server alive at end: True

==== ROUND 2 FINDINGS 0

==== ROUND 2 SLOW 0

Cleanup:

     Removed 17694 files, 10.6GiB total

Known gaps

  • Completing a recurring Task does not yet create its next occurrence or write the completion to the Journal.
  • Checkbox metadata promotion, bidirectional linked-checkbox status mirroring, Undo, and on-demand Obsidian Tasks conversion are incomplete.
  • Task-specific remind: auto-fill, lead-time Settings, and complete VALARM mapping are incomplete.
  • CLI, MCP, and WebMCP parity is incomplete. The Board's 2,000-Task under-100ms target was not measured.
  • The full web test gate has the unrelated ThemePicker 5-second timeout recorded above.

Decisions not explicit in DESIGN

  • The merged DESIGN §34 describes optional modes in the shell order, while issue #430 specifies six defaults and adds Mail/Money from Settings. I kept the six issue defaults (Calendar, Tasks, Notes, Files, Photos, Analytics); a User can enable optional modes in Settings, and enabled modes use the shared shell order.
  • The Bases E2E simulates an editor save by atomically replacing the file. The Notes writer stores read-only content-addressed inodes, so an in-place write would fail with EACCES or risk mutating a shared blob.
## Tasks mode report (#430) ### Built - Added a Notes-backed Task projection and Markdown Task Note writer. The parser preserves hand-edited frontmatter, supports the six Task statuses and priorities, reads imported `start:` as When only when `scheduled:` is absent, and reads/writes readable `repeat:` values with RRULE conversion. - Added lossless Obsidian Bases `.base` parsing and writing, bounded literal filter evaluation, stable view IDs, file-wide and per-view filters, sort/group handling, and Notes API routes for saved views. External Notes and Bases file events refresh the Task projection. - Added the Tasks mode Board, List, and Matrix; built-in and tag views in the sidebar; task/view deep links and Copy link actions; composer and per-view Add task flows; server-backed status changes; saved-view create/edit; and the default mode and optional-plugin settings behavior. - Added production E2E coverage for composer, Add task, Board drag and status persistence, a disk-edited Bases view, and screenshots. The 24 PNGs are attached to [the E2E finding comment](https://git.kayg.org/kayg/calternal/issues/430#issuecomment-14427). ### Files - Task model and serialization: `crates/calternal-notes-core/src/tasks/` and `crates/calternal-notes-core/src/nlp/{mod.rs,tasks_recurrence_md.rs}`. - Notes API and CalDAV adapter: `crates/plugins/notes/src/{lib.rs,task_views.rs,tasks_dav.rs}`; contract/client: `contracts/openapi.json`, `packages/api-client/src/generated.ts`. - Tasks UI: `apps/web/src/lib/tasks/`, `apps/web/src/routes/tasks/`, `apps/web/src/lib/{navigation.ts,navigation.test.ts,notes/noteIndex.svelte.ts,stores/settings-store.ts,stores/settings-store.test.ts}`, `apps/web/src/lib/components/{SidebarLinks.svelte,app-sidebar.svelte}`, and `apps/web/src/routes/settings/plugins/PluginsSection.svelte`. - E2E/adversarial coverage: `apps/web/e2e/tasks.mjs`, `apps/web/package.json`, `tests/adversarial/{attack2.py,xuser_matrix.py}`. - Design/deep-link docs: `docs/DESIGN.md`, `docs/deep-links.md`. ### Head and commits - Branch: `job/tasks-mode` - HEAD: `7ab6818b896ed14b06a6c295706a667b04c1d4f5` - No push, deploy, or merge into `dev` was made. The required local `origin/dev` merge is commit `332498328`. ### Gates (output verbatim) `cargo fmt --check` exited 0 with no stdout. `cargo clippy -p calternal-server --all-targets -- -D warnings`: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 38m 19s ``` `cargo test -p calternal-server`: ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 30m 28s Running unittests src/main.rs (/mnt/hdd/targets/jobs/tasks-mode/debug/deps/calternal_server-6bb5ac9c937be6dc) running 87 tests test result: ok. 85 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 24.83s ``` `cargo clippy -p calternal-plugin-notes --all-targets -- -D warnings`: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 3m 30s ``` `cargo test -p calternal-plugin-notes`: ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 5m 51s test result: ok. 130 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 195.80s Running tests/apple_replay.rs (/mnt/hdd/targets/jobs/tasks-mode/debug/deps/apple_replay-88163a6d50435d3a) running 1 test test completing_reminder_without_description_preserves_notes ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.78s Doc-tests calternal_plugin_notes running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` `bun run check`: ```text Text sizes and UI shape values use shared role tokens. svelte-check found 0 errors and 0 warnings ``` `bun run test --maxWorkers=1`: ```text FAIL |component| src/lib/components/ThemePicker.svelte.test.ts > ThemePicker variants > opens dark variants as a keyboard submenu and checks the selected variant Error: Test timed out in 5000ms. Test Files 1 failed | 138 passed (139) Tests 1 failed | 893 passed (894) Duration 1484.54s (transform 39%, import 23%, environment 21%, tests 12%, setup 5%) ``` The same ThemePicker test timed out at 5919ms in its isolated rerun; its assertions were not changed. `bun run build`: ```text ✓ built in 1m 15s > Using @sveltejs/adapter-static Wrote site to "build" ✔ done ``` `node --check apps/web/e2e/tasks.mjs` exited 0 with no stdout. Production E2E: ```text tasks e2e: composer, Add task, Board drag, live Bases file edit, and screenshots passed in /home/kayg/Developer/calternal-wt/tasks-mode/artifacts/tasks-mode CSP REPORTS tasks: 0 across 1 pages ``` One time-boxed Tasks-view adversarial round: ```text Cross-User classification gate: 312 operations classified ---------- task_views ---------- server alive at end: True ==== ROUND 2 FINDINGS 0 ==== ROUND 2 SLOW 0 ``` Cleanup: ```text Removed 17694 files, 10.6GiB total ``` ### Known gaps - Completing a recurring Task does not yet create its next occurrence or write the completion to the Journal. - Checkbox metadata promotion, bidirectional linked-checkbox status mirroring, Undo, and on-demand Obsidian Tasks conversion are incomplete. - Task-specific `remind:` auto-fill, lead-time Settings, and complete VALARM mapping are incomplete. - CLI, MCP, and WebMCP parity is incomplete. The Board's 2,000-Task under-100ms target was not measured. - The full web test gate has the unrelated ThemePicker 5-second timeout recorded above. ### Decisions not explicit in DESIGN - The merged DESIGN §34 describes optional modes in the shell order, while issue #430 specifies six defaults and adds Mail/Money from Settings. I kept the six issue defaults (Calendar, Tasks, Notes, Files, Photos, Analytics); a User can enable optional modes in Settings, and enabled modes use the shared shell order. - The Bases E2E simulates an editor save by atomically replacing the file. The Notes writer stores read-only content-addressed inodes, so an in-place write would fail with `EACCES` or risk mutating a shared blob.
Author
Owner

Integration note: the shared origin/dev tracking ref advanced while the long Rust gates were running. Final git status reads ahead 18, behind 27 for job/tasks-mode; the required origin/dev merge was already made at 332498328. I did not fetch or merge again because the job rule requires one such merge before final gates.

Integration note: the shared `origin/dev` tracking ref advanced while the long Rust gates were running. Final `git status` reads `ahead 18, behind 27` for `job/tasks-mode`; the required `origin/dev` merge was already made at `332498328`. I did not fetch or merge again because the job rule requires one such merge before final gates.
Author
Owner

Started the UI round for #430 on branch job/tasks-mode. Base SHA: 5474493b170f5d12b3d0fc9ccf5c3880e3d24bae. Current HEAD: 7ab6818b896ed14b06a6c295706a667b04c1d4f5. I am inspecting the existing Tasks components and shared UI primitives before changing the screen.

Started the UI round for #430 on branch `job/tasks-mode`. Base SHA: `5474493b170f5d12b3d0fc9ccf5c3880e3d24bae`. Current HEAD: `7ab6818b896ed14b06a6c295706a667b04c1d4f5`. I am inspecting the existing Tasks components and shared UI primitives before changing the screen.
Author
Owner

#430 UI inspection finding: the current TasksWorkspace.svelte renders Layout as a native <select> and Save as view as <details>; TaskBoard.svelte renders Group by as a native select and visible helper row; TaskCard.svelte and TaskList.svelte use native status selects, direct checkboxes, and inline CopyLink controls; TasksSidebar.svelte exposes saved-view CopyLink icons. This matches the reported control and chrome defects. The shared primitives are present in packages/ui; I am composing them into the existing Tasks views and will capture viewport-sized screenshots from the production build.

#430 UI inspection finding: the current `TasksWorkspace.svelte` renders Layout as a native `<select>` and Save as view as `<details>`; `TaskBoard.svelte` renders Group by as a native select and visible helper row; `TaskCard.svelte` and `TaskList.svelte` use native status selects, direct checkboxes, and inline CopyLink controls; `TasksSidebar.svelte` exposes saved-view CopyLink icons. This matches the reported control and chrome defects. The shared primitives are present in `packages/ui`; I am composing them into the existing Tasks views and will capture viewport-sized screenshots from the production build.
Author
Owner

Finding: the first Tasks profile invocation stopped before server startup because the E2E harness looked under target/debug/calternal-server, while this job uses the preset CARGO_TARGET_DIR at /mnt/hdd/targets/jobs/tasks-mode. The profile runner now passes the configured debug binary. A local 10,000-Task seed advanced at about 60 Tasks/minute on the shared host, so I stopped it and started a 1,000-Task local profile. The profile still supports the 10,000-Task maximum for a faster perf host.

Finding: the first Tasks profile invocation stopped before server startup because the E2E harness looked under `target/debug/calternal-server`, while this job uses the preset `CARGO_TARGET_DIR` at `/mnt/hdd/targets/jobs/tasks-mode`. The profile runner now passes the configured debug binary. A local 10,000-Task seed advanced at about 60 Tasks/minute on the shared host, so I stopped it and started a 1,000-Task local profile. The profile still supports the 10,000-Task maximum for a faster perf host.
Author
Owner

Performance finding: the local 1,000-Task profile seed reached 516 Tasks after 17 minutes on the shared host. I stopped it before route measurements so it would not hold the host for the remaining seed. No tasks-ui.json result was produced, so there are no p50/p95 or CPU/RSS numbers to compare with docs/perf/baseline.json. The profile supports the 10,000-Task stress size and 24-client burst; its full local run remains unmeasured.

Performance finding: the local 1,000-Task profile seed reached 516 Tasks after 17 minutes on the shared host. I stopped it before route measurements so it would not hold the host for the remaining seed. No `tasks-ui.json` result was produced, so there are no p50/p95 or CPU/RSS numbers to compare with `docs/perf/baseline.json`. The profile supports the 10,000-Task stress size and 24-client burst; its full local run remains unmeasured.
Author
Owner

Finding: the post-merge E2E reached the real Notes API, then its screenshot fixture assertion expected review while the Task index returned the canonical task/review namespace for #review. The assertion now follows that existing tag vocabulary; no API or production UI code changed for this finding.

Finding: the post-merge E2E reached the real Notes API, then its screenshot fixture assertion expected `review` while the Task index returned the canonical `task/review` namespace for `#review`. The assertion now follows that existing tag vocabulary; no API or production UI code changed for this finding.
Author
Owner

Finding: the local E2E fixture created with POST /api/v1/notes/tasks returned the requested When date but due: null for the 📅 2026-10-04 suffix. The UI fixture now sets due, scheduled, priority and tag through the existing PATCH /api/v1/notes/tasks/properties writer, so the screen evidence uses persisted API data. I left the Task text parser unchanged because this UI round owns presentation only.

Finding: the local E2E fixture created with `POST /api/v1/notes/tasks` returned the requested When date but `due: null` for the `📅 2026-10-04` suffix. The UI fixture now sets due, scheduled, priority and tag through the existing `PATCH /api/v1/notes/tasks/properties` writer, so the screen evidence uses persisted API data. I left the Task text parser unchanged because this UI round owns presentation only.
Author
Owner

Finding: the E2E waited for a scheduled Task on Inbox, and timed out because the built-in Inbox view correctly excludes Tasks with When or Deadline values. I separated the plain Task used by the drag proof from the metadata Task used by screenshots, and capture the latter in Next 7 days. The screenshot flow now asserts the card chips and relative List dates before saving each viewport image.

Finding: the E2E waited for a scheduled Task on Inbox, and timed out because the built-in Inbox view correctly excludes Tasks with When or Deadline values. I separated the plain Task used by the drag proof from the metadata Task used by screenshots, and capture the latter in Next 7 days. The screenshot flow now asserts the card chips and relative List dates before saving each viewport image.
Author
Owner

Finding: after a successful Board drag, Playwright's click on the Change status · Doing menu item retried until that item detached during its entrance transition. The E2E now waits for the shared menu row animation to finish before synthetic clicks on top-level items and radio submenu choices.

Finding: after a successful Board drag, Playwright's click on the `Change status · Doing` menu item retried until that item detached during its entrance transition. The E2E now waits for the shared menu row animation to finish before synthetic clicks on top-level items and radio submenu choices.
Author
Owner

Finding: the real-browser drag proof reached the Board but the authoritative Tasks API still reported todo after the 5-second write window; no status assertion passed. I am tracing the native drag event path before changing the Board behavior.

Finding: the real-browser drag proof reached the Board but the authoritative Tasks API still reported `todo` after the 5-second write window; no status assertion passed. I am tracing the native drag event path before changing the Board behavior.
Author
Owner

Production E2E finding: after a Task status PATCH, the Notes change subscription started a full TaskIndex.refresh(). The loading state replaced the rendered board, detaching its card action menu while the write was settling. refresh() now preserves the ready projection during the background read, so the open view stays mounted; the production Tasks E2E passed through drag, keyboard status change, saved view edit, and all 24 viewport captures afterward.

Production E2E finding: after a Task status PATCH, the Notes change subscription started a full `TaskIndex.refresh()`. The `loading` state replaced the rendered board, detaching its card action menu while the write was settling. `refresh()` now preserves the ready projection during the background read, so the open view stays mounted; the production Tasks E2E passed through drag, keyboard status change, saved view edit, and all 24 viewport captures afterward.
Author
Owner

Production E2E finding: after a direct edit to a saved Bases file, the Notes API and Tasks content showed the new view name but the browser document title stayed at the route fallback (“Task view”). The app shell now derives the document title from the active page-owned header title, so a saved-view rename updates without navigation. The production Tasks E2E now passes through composer creation, Add task, Board drag, status menu, stable Copy link, external file edit, and all 24 required viewport captures.

The full web test run reported one 5-second timeout in the unrelated MailSection provider-details test (138 files passed; 905/906 tests passed). The required isolated rerun passed: 1 file, 4 tests.

Production E2E finding: after a direct edit to a saved Bases file, the Notes API and Tasks content showed the new view name but the browser document title stayed at the route fallback (“Task view”). The app shell now derives the document title from the active page-owned header title, so a saved-view rename updates without navigation. The production Tasks E2E now passes through composer creation, Add task, Board drag, status menu, stable Copy link, external file edit, and all 24 required viewport captures. The full web test run reported one 5-second timeout in the unrelated MailSection provider-details test (138 files passed; 905/906 tests passed). The required isolated rerun passed: 1 file, 4 tests.
Author
Owner

Finished — Forgejo #430 UI round

Branch: job/tasks-mode
Head SHA: a6125829ed3ac0328e3dfac8fdb4a53990db5bbe

Built

  • Reused the shared segmented control, Checkbox, StatusPill, TagPill, glass Card, Menu and OverlaySurface for Tasks controls and actions. Copy link is in item menus and the header action.
  • Kept Board lanes in an inner horizontal snap scroller, bounded each lane, and preserved the mounted view during background refresh. An in-flight Notes event triggers a follow-up read.
  • Kept When and Deadline visible as relative dates in compact List rows. Desktop keeps right-aligned date columns.
  • Made the browser title follow the active page title so a saved-view rename updates without navigation.
  • Added a production Tasks flow and performance profile. The E2E covers Task creation, drag/status writes, stable Copy link, a live Bases-file edit, and 24 viewport screenshots.

Files

apps/web/src/lib/components/ItemActionMenu.svelte, apps/web/src/lib/components/SidebarLinks.svelte, apps/web/src/lib/tasks/{TaskBoard,TaskCard,TaskColumn,TaskList,TasksSidebar,TasksWorkspace,task-status,index.svelte}.ts, apps/web/src/routes/+layout.svelte, apps/web/e2e/{tasks,tasks-perf}.mjs, bench/tasks-ui/{README.md,run.sh}.

The final commit changes apps/web/e2e/tasks.mjs, apps/web/src/lib/tasks/TaskList.svelte, apps/web/src/lib/tasks/index.svelte.ts, and apps/web/src/routes/+layout.svelte.

Gates and verification

bun run check output:

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

svelte-check found 0 errors and 0 warnings

bun run build completed successfully:

✓ built in 1m 29s
Wrote site to "build"
✔ done

CALTERNAL_SERVER_BIN="$CARGO_TARGET_DIR/debug/calternal-server" bun run test:e2e:tasks output:

tasks e2e: composer, Add task, Board drag, live Bases file edit, and screenshots passed in /home/kayg/Developer/calternal-wt/tasks-mode/artifacts/tasks-mode
CSP REPORTS tasks: 0 across 1 pages

The 24 generated PNGs are 390, 820 or 1440 × 900 and cover paper and tokyo-night themes, Board, List, Matrix and sidebar. bun run test had one unrelated MailSection timeout; its isolated rerun passed. Relevant output:

 FAIL  |component| src/routes/settings/mail/MailSection.svelte.test.ts > Settings → Mail account form > keeps provider connection details behind Advanced
Error: Test timed out in 5000ms.
 Test Files  1 failed | 138 passed (139)
      Tests  1 failed | 905 passed (906)
   Duration  170.69s (transform 45%, environment 23%, import 14%, tests 13%, setup 5%)
error: script "test" exited with code 1
$ vitest run src/routes/settings/mail/MailSection.svelte.test.ts
 Test Files  1 passed (1)
      Tests  4 passed (4)
   Duration  14.78s (transform 61%, tests 24%, environment 9%, import 4%, setup 2%)

git diff --check passed with no output. No Rust files changed, so no Rust gates were run. Cleanup output:

Removed 7087 files, 4.8GiB total

Decisions and gaps

  • DESIGN does not set a narrow Tasks List breakpoint. At a 640 px container width, When and Deadline move under the task title as relative labels; Priority hides while Tags, Status and actions remain. The browser title follows the page-owned header title for live saved-view names.
  • The Tasks performance profile is checked in, but local data seeding did not finish at the 1k/10k profile sizes, so there are no complete latency/CPU/RSS numbers to report. No baseline was added without a completed run.
  • Screenshots remain in artifacts/tasks-mode/ and are not committed. The scripts/fj issue CLI exposes no attachment/upload command, so I could not attach the PNGs to this issue; they remain in the worktree for review.

Cargo and web build output were cleaned after verification. The worktree is clean. No push, deploy, merge or issue close was performed.

## Finished — Forgejo #430 UI round Branch: `job/tasks-mode` Head SHA: `a6125829ed3ac0328e3dfac8fdb4a53990db5bbe` ### Built - Reused the shared segmented control, Checkbox, StatusPill, TagPill, glass Card, Menu and OverlaySurface for Tasks controls and actions. Copy link is in item menus and the header action. - Kept Board lanes in an inner horizontal snap scroller, bounded each lane, and preserved the mounted view during background refresh. An in-flight Notes event triggers a follow-up read. - Kept When and Deadline visible as relative dates in compact List rows. Desktop keeps right-aligned date columns. - Made the browser title follow the active page title so a saved-view rename updates without navigation. - Added a production Tasks flow and performance profile. The E2E covers Task creation, drag/status writes, stable Copy link, a live Bases-file edit, and 24 viewport screenshots. ### Files `apps/web/src/lib/components/ItemActionMenu.svelte`, `apps/web/src/lib/components/SidebarLinks.svelte`, `apps/web/src/lib/tasks/{TaskBoard,TaskCard,TaskColumn,TaskList,TasksSidebar,TasksWorkspace,task-status,index.svelte}.ts`, `apps/web/src/routes/+layout.svelte`, `apps/web/e2e/{tasks,tasks-perf}.mjs`, `bench/tasks-ui/{README.md,run.sh}`. The final commit changes `apps/web/e2e/tasks.mjs`, `apps/web/src/lib/tasks/TaskList.svelte`, `apps/web/src/lib/tasks/index.svelte.ts`, and `apps/web/src/routes/+layout.svelte`. ### Gates and verification `bun run check` output: ```text $ node scripts/check-type-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json Text sizes and UI shape values use shared role tokens. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/tasks-mode/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `bun run build` completed successfully: ```text ✓ built in 1m 29s Wrote site to "build" ✔ done ``` `CALTERNAL_SERVER_BIN="$CARGO_TARGET_DIR/debug/calternal-server" bun run test:e2e:tasks` output: ```text tasks e2e: composer, Add task, Board drag, live Bases file edit, and screenshots passed in /home/kayg/Developer/calternal-wt/tasks-mode/artifacts/tasks-mode CSP REPORTS tasks: 0 across 1 pages ``` The 24 generated PNGs are 390, 820 or 1440 × 900 and cover paper and tokyo-night themes, Board, List, Matrix and sidebar. `bun run test` had one unrelated MailSection timeout; its isolated rerun passed. Relevant output: ```text FAIL |component| src/routes/settings/mail/MailSection.svelte.test.ts > Settings → Mail account form > keeps provider connection details behind Advanced Error: Test timed out in 5000ms. Test Files 1 failed | 138 passed (139) Tests 1 failed | 905 passed (906) Duration 170.69s (transform 45%, environment 23%, import 14%, tests 13%, setup 5%) error: script "test" exited with code 1 ``` ```text $ vitest run src/routes/settings/mail/MailSection.svelte.test.ts Test Files 1 passed (1) Tests 4 passed (4) Duration 14.78s (transform 61%, tests 24%, environment 9%, import 4%, setup 2%) ``` `git diff --check` passed with no output. No Rust files changed, so no Rust gates were run. Cleanup output: ```text Removed 7087 files, 4.8GiB total ``` ### Decisions and gaps - DESIGN does not set a narrow Tasks List breakpoint. At a 640 px container width, When and Deadline move under the task title as relative labels; Priority hides while Tags, Status and actions remain. The browser title follows the page-owned header title for live saved-view names. - The Tasks performance profile is checked in, but local data seeding did not finish at the 1k/10k profile sizes, so there are no complete latency/CPU/RSS numbers to report. No baseline was added without a completed run. - Screenshots remain in `artifacts/tasks-mode/` and are not committed. The `scripts/fj issue` CLI exposes no attachment/upload command, so I could not attach the PNGs to this issue; they remain in the worktree for review. Cargo and web build output were cleaned after verification. The worktree is clean. No push, deploy, merge or issue close was performed.
Author
Owner

Superseding final report — Forgejo #430 UI round

The final screenshot review found that the List still displayed future dates as localized calendar dates. The earlier report called those relative labels; this follow-up corrects that gap. Tasks cards and rows now show relative day labels within the next or past seven days, then use the shared short-date format. A focused component regression test failed first with 10/1/26 and 10/3/26, then passed after the change. The production E2E asserts tomorrow and in 3 days for both Board and List.

Branch: job/tasks-mode
Head SHA: 5f00df7ec61d8850fac41509610211d7ce9b0f28
Commits: a6125829e (refresh, narrow List, live title) and 5f00df7ec (relative Task dates).

Delivered

  • Reused the shared segmented control, Checkbox, StatusPill, TagPill, glass Card, Menu and OverlaySurface for Tasks layouts and actions. Copy link lives in item menus and one header action.
  • Put Board lanes in an inner horizontal snap scroller and bounded lane height. Background reads keep the ready view mounted; a Notes event during a read causes one follow-up read.
  • Added a compact register layout with visible When/Deadline labels on narrow rows, plus relative dates in Cards and the full List.
  • Kept the browser title in sync with the page-owned title when a saved view changes without navigation.
  • Added production E2E coverage and a Tasks performance profile.

Files touched by this job include apps/web/src/lib/components/ItemActionMenu.svelte, apps/web/src/lib/components/SidebarLinks.svelte, apps/web/src/lib/tasks/{TaskBoard,TaskCard,TaskColumn,TaskList,TaskList.svelte.test,TasksSidebar,TasksWorkspace,index.svelte,task-date,task-status}.svelte, apps/web/src/routes/+layout.svelte, apps/web/e2e/{tasks,tasks-perf}.mjs, and bench/tasks-ui/{README.md,run.sh}.

Gates and verification

bun run check:

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

svelte-check found 0 errors and 0 warnings

bun run build completed:

✓ built in 50.81s
Run npm run preview to preview your production build locally.
> Using @sveltejs/adapter-static
Wrote site to "build"
✔ done

CALTERNAL_SERVER_BIN="$CARGO_TARGET_DIR/debug/calternal-server" bun run test:e2e:tasks:

tasks e2e: composer, Add task, Board drag, live Bases file edit, and screenshots passed in /home/kayg/Developer/calternal-wt/tasks-mode/artifacts/tasks-mode
CSP REPORTS tasks: 0 across 1 pages

The E2E produced 24 PNGs at 390×900, 820×900 and 1440×900 for paper and tokyo-night, covering Board, List, Matrix and sidebar. The full unit run had two 5-second timeouts in existing shared-menu and Mail settings tests; 138 files and 905 tests passed. The required isolated rerun passed both files:

 FAIL  |component| src/lib/menu-open-focus.svelte.test.ts > shared menu opening focus > keeps the focused first row visually inactive when the pointer opens the menu
Error: Test timed out in 5000ms.
 FAIL  |component| src/routes/settings/mail/MailSection.svelte.test.ts > Settings → Mail account form > keeps provider connection details behind Advanced
Error: Test timed out in 5000ms.
 Test Files  2 failed | 138 passed (140)
      Tests  2 failed | 905 passed (907)
   Duration  293.02s (transform 57%, environment 18%, import 10%, tests 10%, setup 4%)
error: script "test" exited with code 1
$ vitest run src/routes/settings/mail/MailSection.svelte.test.ts src/lib/menu-open-focus.svelte.test.ts
 Test Files  2 passed (2)
      Tests  6 passed (6)
   Start at  18:28:30
   Duration  24.34s (transform 70%, environment 17%, tests 5%, import 4%, setup 3%)

cargo build -p calternal-server was run only to restore the E2E server after cleanup; no Rust source changed and no Rust gates were needed. git diff --check passed with no output. Final cleanup output:

Removed 7068 files, 4.4GiB total

Decisions and known gaps

  • DESIGN does not set the Tasks relative-date window. The implementation uses relative day labels through ±7 calendar days, then the shared short-date format.
  • DESIGN does not specify the narrow List layout. At 640 px container width, When and Deadline move under the task title and Priority hides; Tags, Status and actions remain.
  • The app shell now uses the page-owned title for the browser title, so saved-view renames update without navigation. Background refresh also keeps the loaded projection mounted to preserve open menus.
  • The checked-in performance profile did not finish seeding its 1k/10k local data sets, so there are no complete latency/CPU/RSS metrics and no Tasks baseline was added.
  • Screenshots remain under artifacts/tasks-mode/ and are not committed. scripts/fj issue has no attachment/upload command, so I could not attach the PNGs to this issue; they remain in the worktree for review.

The worktree is clean. No push, deploy, merge or issue close was performed.

## Superseding final report — Forgejo #430 UI round The final screenshot review found that the List still displayed future dates as localized calendar dates. The earlier report called those relative labels; this follow-up corrects that gap. Tasks cards and rows now show relative day labels within the next or past seven days, then use the shared short-date format. A focused component regression test failed first with `10/1/26` and `10/3/26`, then passed after the change. The production E2E asserts `tomorrow` and `in 3 days` for both Board and List. Branch: `job/tasks-mode` Head SHA: `5f00df7ec61d8850fac41509610211d7ce9b0f28` Commits: `a6125829e` (refresh, narrow List, live title) and `5f00df7ec` (relative Task dates). ### Delivered - Reused the shared segmented control, Checkbox, StatusPill, TagPill, glass Card, Menu and OverlaySurface for Tasks layouts and actions. Copy link lives in item menus and one header action. - Put Board lanes in an inner horizontal snap scroller and bounded lane height. Background reads keep the ready view mounted; a Notes event during a read causes one follow-up read. - Added a compact register layout with visible When/Deadline labels on narrow rows, plus relative dates in Cards and the full List. - Kept the browser title in sync with the page-owned title when a saved view changes without navigation. - Added production E2E coverage and a Tasks performance profile. Files touched by this job include `apps/web/src/lib/components/ItemActionMenu.svelte`, `apps/web/src/lib/components/SidebarLinks.svelte`, `apps/web/src/lib/tasks/{TaskBoard,TaskCard,TaskColumn,TaskList,TaskList.svelte.test,TasksSidebar,TasksWorkspace,index.svelte,task-date,task-status}.svelte`, `apps/web/src/routes/+layout.svelte`, `apps/web/e2e/{tasks,tasks-perf}.mjs`, and `bench/tasks-ui/{README.md,run.sh}`. ### Gates and verification `bun run check`: ```text $ node scripts/check-type-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json Text sizes and UI shape values use shared role tokens. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/tasks-mode/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `bun run build` completed: ```text ✓ built in 50.81s Run npm run preview to preview your production build locally. > Using @sveltejs/adapter-static Wrote site to "build" ✔ done ``` `CALTERNAL_SERVER_BIN="$CARGO_TARGET_DIR/debug/calternal-server" bun run test:e2e:tasks`: ```text tasks e2e: composer, Add task, Board drag, live Bases file edit, and screenshots passed in /home/kayg/Developer/calternal-wt/tasks-mode/artifacts/tasks-mode CSP REPORTS tasks: 0 across 1 pages ``` The E2E produced 24 PNGs at 390×900, 820×900 and 1440×900 for paper and tokyo-night, covering Board, List, Matrix and sidebar. The full unit run had two 5-second timeouts in existing shared-menu and Mail settings tests; 138 files and 905 tests passed. The required isolated rerun passed both files: ```text FAIL |component| src/lib/menu-open-focus.svelte.test.ts > shared menu opening focus > keeps the focused first row visually inactive when the pointer opens the menu Error: Test timed out in 5000ms. FAIL |component| src/routes/settings/mail/MailSection.svelte.test.ts > Settings → Mail account form > keeps provider connection details behind Advanced Error: Test timed out in 5000ms. Test Files 2 failed | 138 passed (140) Tests 2 failed | 905 passed (907) Duration 293.02s (transform 57%, environment 18%, import 10%, tests 10%, setup 4%) error: script "test" exited with code 1 ``` ```text $ vitest run src/routes/settings/mail/MailSection.svelte.test.ts src/lib/menu-open-focus.svelte.test.ts Test Files 2 passed (2) Tests 6 passed (6) Start at 18:28:30 Duration 24.34s (transform 70%, environment 17%, tests 5%, import 4%, setup 3%) ``` `cargo build -p calternal-server` was run only to restore the E2E server after cleanup; no Rust source changed and no Rust gates were needed. `git diff --check` passed with no output. Final cleanup output: ```text Removed 7068 files, 4.4GiB total ``` ### Decisions and known gaps - DESIGN does not set the Tasks relative-date window. The implementation uses relative day labels through ±7 calendar days, then the shared short-date format. - DESIGN does not specify the narrow List layout. At 640 px container width, When and Deadline move under the task title and Priority hides; Tags, Status and actions remain. - The app shell now uses the page-owned title for the browser title, so saved-view renames update without navigation. Background refresh also keeps the loaded projection mounted to preserve open menus. - The checked-in performance profile did not finish seeding its 1k/10k local data sets, so there are no complete latency/CPU/RSS metrics and no Tasks baseline was added. - Screenshots remain under `artifacts/tasks-mode/` and are not committed. `scripts/fj issue` has no attachment/upload command, so I could not attach the PNGs to this issue; they remain in the worktree for review. The worktree is clean. No push, deploy, merge or issue close was performed.
Author
Owner

Correction to the file and integration lines in my previous report:

Exact Task UI files include apps/web/src/lib/tasks/TaskBoard.svelte, TaskCard.svelte, TaskColumn.svelte, TaskList.svelte, TaskList.svelte.test.ts, TasksSidebar.svelte, TasksWorkspace.svelte, index.svelte.ts, task-date.ts, and task-status.ts, plus apps/web/src/lib/components/ItemActionMenu.svelte, SidebarLinks.svelte, apps/web/src/routes/+layout.svelte, apps/web/e2e/tasks.mjs, tasks-perf.mjs, and bench/tasks-ui/README.md, run.sh.

The required origin/dev merge was already present before final gates. No merge into dev, push or deploy was performed.

Correction to the file and integration lines in my previous report: Exact Task UI files include `apps/web/src/lib/tasks/TaskBoard.svelte`, `TaskCard.svelte`, `TaskColumn.svelte`, `TaskList.svelte`, `TaskList.svelte.test.ts`, `TasksSidebar.svelte`, `TasksWorkspace.svelte`, `index.svelte.ts`, `task-date.ts`, and `task-status.ts`, plus `apps/web/src/lib/components/ItemActionMenu.svelte`, `SidebarLinks.svelte`, `apps/web/src/routes/+layout.svelte`, `apps/web/e2e/tasks.mjs`, `tasks-perf.mjs`, and `bench/tasks-ui/README.md`, `run.sh`. The required `origin/dev` merge was already present before final gates. No merge into `dev`, push or deploy was performed.
Author
Owner

Starting finishing round on job/tasks-mode. Original base: cd3cea7575. Fetch and merge of origin/dev started; it reported conflicts in navigation.ts, settings-store.ts, and tests/adversarial/attack2.py, which I am resolving with both sides preserved before the UI fixes.

Starting finishing round on job/tasks-mode. Original base: cd3cea757508d9f581d00fb7d5d7973fbc0a75fd. Fetch and merge of origin/dev started; it reported conflicts in navigation.ts, settings-store.ts, and tests/adversarial/attack2.py, which I am resolving with both sides preserved before the UI fixes.
Author
Owner

Confirmed both findings in the current render code. TasksSidebar uses SidebarLinks and ItemActionMenu; its row CSS keeps the action trigger visible, while ItemActionMenu already attaches context-menu and touch long-press actions to the row. TaskColumn renders TaskCard with the same status pill used in Matrix. I’m collapsing the hidden sidebar action width and making the pill optional for Board cards; List remains separate and keeps its Status column.

Confirmed both findings in the current render code. TasksSidebar uses SidebarLinks and ItemActionMenu; its row CSS keeps the action trigger visible, while ItemActionMenu already attaches context-menu and touch long-press actions to the row. TaskColumn renders TaskCard with the same status pill used in Matrix. I’m collapsing the hidden sidebar action width and making the pill optional for Board cards; List remains separate and keeps its Status column.
Author
Owner

Performance profile finding: bench/tasks-ui/run.sh was started on root@10.69.69.63 with the shared release server under /root/perf.lock. The load average at lock acquisition was 0.02 0.02 0.00. The profile was still seeding its 10,000-task dataset after 14:02; at that point the temporary user-data tree had 1,488 files. I stopped the run at 15:56. It did not reach route sampling, so it produced no route p50/p95 or burst metrics. docs/perf/baseline.json has no Tasks UI route baseline. This is a setup-throughput observation, not a route regression measurement. The temporary server and staging files were removed.

Performance profile finding: `bench/tasks-ui/run.sh` was started on `root@10.69.69.63` with the shared release server under `/root/perf.lock`. The load average at lock acquisition was `0.02 0.02 0.00`. The profile was still seeding its 10,000-task dataset after 14:02; at that point the temporary user-data tree had 1,488 files. I stopped the run at 15:56. It did not reach route sampling, so it produced no route p50/p95 or burst metrics. `docs/perf/baseline.json` has no Tasks UI route baseline. This is a setup-throughput observation, not a route regression measurement. The temporary server and staging files were removed.
Author
Owner

Finished — Tasks mode (#430)

Built

  • Task sidebar row actions now have zero width and stay hidden until row hover or keyboard focus. Touch users still get the existing row context menu and long-press actions.
  • Task Board cards omit the Status chip because the column heading supplies that status. List retains its status column; Matrix retains its chip.
  • Added E2E checks for hidden/revealed sidebar actions, touch Copy link, and Board versus List status display.

Files

  • apps/web/src/lib/components/SidebarLinks.svelte
  • apps/web/src/lib/tasks/TasksSidebar.svelte
  • apps/web/src/lib/tasks/TaskCard.svelte
  • apps/web/src/lib/tasks/TaskColumn.svelte
  • apps/web/e2e/tasks.mjs

Commits

  • 3633fbef4 — merge origin/dev while preserving Tasks defaults and probes
  • 2b2a3ff4b — hide Tasks sidebar actions until interaction
  • 242d5aaa3 — remove duplicate Status chips from Task Board
  • 820452a32 — verify Tasks touch sidebar menu actions

Head: 820452a32a019e495bae37b28d12bbe26c97f434.

Gates

bun run check exited 0. Verbatim output:

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

svelte-check found 0 errors and 0 warnings

bun run test exited 0. Verbatim result lines:

 RUN  v5.0.1 /home/kayg/Developer/calternal-wt/tasks-mode/apps/web

 Test Files  143 passed (143)
      Tests  922 passed (922)
   Start at  19:53:58
   Duration  194.07s (transform 54%, environment 16%, import 16%, tests 10%, setup 3%)

Vitest also printed its existing jsdom warnings: Not implemented: Window's scrollTo() method and Could not parse CSS stylesheet; the command still exited 0.

The production web build succeeded. The real API-backed E2E run passed:

tasks e2e: composer, Add task, Board drag, live Bases file edit, and screenshots passed in /home/kayg/Developer/calternal-wt/tasks-mode/artifacts/tasks-mode-final
CSP REPORTS tasks: 0 across 1 pages

cargo clean completed:

Removed 7169 files, 4.5GiB total

No Rust source changed, so Rust clippy and test gates were not run.

Screenshots attached

390px: Paper Board · Paper sidebar · Tokyo Night Board · Tokyo Night sidebar
820px: Paper Board · Paper sidebar · Tokyo Night Board · Tokyo Night sidebar
1440px: Paper Board · Paper sidebar · Tokyo Night Board · Tokyo Night sidebar

The captures cover Board and sidebar at 390px, 820px, and 1440px in Paper and Tokyo Night. They use the production build and real local API. The Browser plugin was unavailable, so Playwright in the repository E2E harness captured them.

Performance profile

The existing bench/tasks-ui/run.sh profile was started on root@10.69.69.63 with the shared release server under /root/perf.lock; the load average at lock acquisition was 0.02 0.02 0.00. It was still seeding 10,000 Tasks after 14:02 and had 1,488 files in its temporary user-data tree. I stopped it at 15:56. It did not reach route sampling, so it produced no route p50/p95 or burst metrics. docs/perf/baseline.json has no Tasks UI route baseline. This is a setup-throughput observation, not a route regression measurement; I posted it as a separate finding comment.

Known integration gap

After the required one-time merge, origin/dev advanced by 7324257e2 and 15e17aeaf. The current tracking ref is two commits ahead of this branch and its diff removes the Tasks UI files, including the files changed here. I did not repeat the merge after gates, in line with the one-merge instruction. The orchestrator should account for this before integrating the branch.

Decisions

No new product decision was needed. The issue specifies hover/focus visibility and says Board columns own Status; the implementation reuses the existing ItemActionMenu for touch and keeps status chips in Matrix and List.

## Finished — Tasks mode (#430) ### Built - Task sidebar row actions now have zero width and stay hidden until row hover or keyboard focus. Touch users still get the existing row context menu and long-press actions. - Task Board cards omit the Status chip because the column heading supplies that status. List retains its status column; Matrix retains its chip. - Added E2E checks for hidden/revealed sidebar actions, touch Copy link, and Board versus List status display. ### Files - `apps/web/src/lib/components/SidebarLinks.svelte` - `apps/web/src/lib/tasks/TasksSidebar.svelte` - `apps/web/src/lib/tasks/TaskCard.svelte` - `apps/web/src/lib/tasks/TaskColumn.svelte` - `apps/web/e2e/tasks.mjs` ### Commits - `3633fbef4` — merge `origin/dev` while preserving Tasks defaults and probes - `2b2a3ff4b` — hide Tasks sidebar actions until interaction - `242d5aaa3` — remove duplicate Status chips from Task Board - `820452a32` — verify Tasks touch sidebar menu actions Head: `820452a32a019e495bae37b28d12bbe26c97f434`. ### Gates `bun run check` exited 0. Verbatim output: ```text $ node scripts/check-type-tokens.mjs && node scripts/check-motion-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json Text sizes and UI shape values use shared role tokens. UI transitions and animation options use shared motion tokens or documented exceptions. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/tasks-mode/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `bun run test` exited 0. Verbatim result lines: ```text RUN v5.0.1 /home/kayg/Developer/calternal-wt/tasks-mode/apps/web Test Files 143 passed (143) Tests 922 passed (922) Start at 19:53:58 Duration 194.07s (transform 54%, environment 16%, import 16%, tests 10%, setup 3%) ``` Vitest also printed its existing jsdom warnings: `Not implemented: Window's scrollTo() method` and `Could not parse CSS stylesheet`; the command still exited 0. The production web build succeeded. The real API-backed E2E run passed: ```text tasks e2e: composer, Add task, Board drag, live Bases file edit, and screenshots passed in /home/kayg/Developer/calternal-wt/tasks-mode/artifacts/tasks-mode-final CSP REPORTS tasks: 0 across 1 pages ``` `cargo clean` completed: ```text Removed 7169 files, 4.5GiB total ``` No Rust source changed, so Rust clippy and test gates were not run. ### Screenshots attached **390px:** [Paper Board](https://git.kayg.org/attachments/5dd65eb0-1c87-4fcf-8234-8c2d149a4b1c) · [Paper sidebar](https://git.kayg.org/attachments/0dd7d4af-2aca-4a75-9f9b-840ee2e2a36d) · [Tokyo Night Board](https://git.kayg.org/attachments/98b23b79-5ec3-4c95-ac49-06d572b4d5f9) · [Tokyo Night sidebar](https://git.kayg.org/attachments/e3296e5a-4fce-4040-9045-e5d0861cc67f) **820px:** [Paper Board](https://git.kayg.org/attachments/ef1dc636-f8ee-4d0b-9fb5-fea9a8546024) · [Paper sidebar](https://git.kayg.org/attachments/c509813f-37c5-41e8-b5d3-ebe89cbe362a) · [Tokyo Night Board](https://git.kayg.org/attachments/af8515f9-e13f-415b-b26b-1102621637c5) · [Tokyo Night sidebar](https://git.kayg.org/attachments/b6d9e580-02b8-4b4e-bed3-bb78a809cd57) **1440px:** [Paper Board](https://git.kayg.org/attachments/1b3343e1-d302-48c1-8c2e-e5764867a4e7) · [Paper sidebar](https://git.kayg.org/attachments/0fc994e1-d94e-4d10-8243-393cf18cd60c) · [Tokyo Night Board](https://git.kayg.org/attachments/74b34860-7416-41eb-8cba-76b6337c757c) · [Tokyo Night sidebar](https://git.kayg.org/attachments/bceb86c9-aece-4cc8-8753-e6f3940be06c) The captures cover Board and sidebar at 390px, 820px, and 1440px in Paper and Tokyo Night. They use the production build and real local API. The Browser plugin was unavailable, so Playwright in the repository E2E harness captured them. ### Performance profile The existing `bench/tasks-ui/run.sh` profile was started on `root@10.69.69.63` with the shared release server under `/root/perf.lock`; the load average at lock acquisition was `0.02 0.02 0.00`. It was still seeding 10,000 Tasks after 14:02 and had 1,488 files in its temporary user-data tree. I stopped it at 15:56. It did not reach route sampling, so it produced no route p50/p95 or burst metrics. `docs/perf/baseline.json` has no Tasks UI route baseline. This is a setup-throughput observation, not a route regression measurement; I posted it as a separate finding comment. ### Known integration gap After the required one-time merge, `origin/dev` advanced by `7324257e2` and `15e17aeaf`. The current tracking ref is two commits ahead of this branch and its diff removes the Tasks UI files, including the files changed here. I did not repeat the merge after gates, in line with the one-merge instruction. The orchestrator should account for this before integrating the branch. ### Decisions No new product decision was needed. The issue specifies hover/focus visibility and says Board columns own Status; the implementation reuses the existing `ItemActionMenu` for touch and keeps status chips in Matrix and List.
Author
Owner

Starting the #430 polish round on branch job/tasks-mode.
HEAD: 820452a32a019e495bae37b28d12bbe26c97f434
origin/dev: cc25c441b7a974185622a1dee853cf38686d2b67
Merge base: aa372eef6c9312403f59a65d5b90cb3648ff52ed

Starting the #430 polish round on branch `job/tasks-mode`. HEAD: `820452a32a019e495bae37b28d12bbe26c97f434` origin/dev: `cc25c441b7a974185622a1dee853cf38686d2b67` Merge base: `aa372eef6c9312403f59a65d5b90cb3648ff52ed`
Author
Owner

Finding from artifacts/tasks-mode-final/1440-paper-board.png and 390-paper-board.png: the Board scroller shows a full-width scrollbar track below the lanes and clips Blocked at the right edge. The card metadata starts at a different left edge from the title text, the #review pill starts farther left, and the ⋯ action is in a separate bottom row. At 390 px the header title is visibly ellipsized to Next 7… while the layout switcher and two action icons occupy the same row.

Finding from `artifacts/tasks-mode-final/1440-paper-board.png` and `390-paper-board.png`: the Board scroller shows a full-width scrollbar track below the lanes and clips Blocked at the right edge. The card metadata starts at a different left edge from the title text, the `#review` pill starts farther left, and the ⋯ action is in a separate bottom row. At 390 px the header title is visibly ellipsized to `Next 7…` while the layout switcher and two action icons occupy the same row.
Author
Owner

Implementation finding: a column Add task must write its selected Status during the create action to follow DESIGN §41. The existing POST /api/v1/notes/tasks request did not accept an initial Status. I am adding an optional TaskStatus field to that route and writing the Status, Done completion date and root Checkbox in the same Notes writer; requests without the field keep their existing default.

Implementation finding: a column Add task must write its selected Status during the create action to follow DESIGN §41. The existing `POST /api/v1/notes/tasks` request did not accept an initial Status. I am adding an optional TaskStatus field to that route and writing the Status, Done completion date and root Checkbox in the same Notes writer; requests without the field keep their existing default.
Author
Owner

Tasks E2E on merged head f3e211f3e found that the card title row intercepted clicks on the ⋯ action. Playwright timed out after 30 seconds and reported .task-title-row as the pointer-event target. I raised the action layer above the row; I will rerun the E2E against the production build.

Tasks E2E on merged head `f3e211f3e` found that the card title row intercepted clicks on the ⋯ action. Playwright timed out after 30 seconds and reported `.task-title-row` as the pointer-event target. I raised the action layer above the row; I will rerun the E2E against the production build.
Author
Owner

The next E2E run showed that z-index and sibling placement alone still let .task-title-row intercept the action click. The ⋯ control now occupies its own third grid column in the title row, which keeps its hit target beside the title without overlap. I am validating this layout before continuing the screenshot run.

The next E2E run showed that z-index and sibling placement alone still let `.task-title-row` intercept the action click. The ⋯ control now occupies its own third grid column in the title row, which keeps its hit target beside the title without overlap. I am validating this layout before continuing the screenshot run.
Author
Owner

Final report — Tasks mode polish round (#430)

Built

  • Made the Board scroller transparent and applied the shared inline edge fade. Board lanes now own their “Add task” row; empty lanes say “No tasks”.
  • Aligned Task card text, metadata, group labels, and empty copy to the title text start. The card action stays at the top trailing corner and appears on hover, focus, and touch. Board cards omit the repeated Status chip.
  • Moved the phone layout selector into the More actions → Layout menu. List and Matrix keep the existing view-wide “Add task” row below their content.
  • Added an optional initial status to the existing Notes Task-create route. A Board lane create writes Status, completion date, and the root Checkbox together.
  • Updated Tasks E2E and the adversarial Task-create probe.

Decisions

  • The design did not specify how a Board lane supplies initial Status. I used the existing Task-create route with an optional status field, preserving the one-action/one-route rule in DESIGN §41.
  • The phone layout choices live in the “More actions” menu because the prompt allowed the menu or sidebar sub-views and the chrome rules require one bar.
  • List and Matrix retain a view-wide Add row below their content; Board uses a per-lane row.
  • The performance profile used a 1,000-Task target after the 10,000-Task setup exceeded the job timebox on the shared local host. The 1,000-Task seed did not finish before the four-hour cutoff, so it produced no route or burst metrics.

Files changed in this round

  • Tasks UI and composer: apps/web/e2e/tasks.mjs, apps/web/src/lib/composer/Composer.svelte, apps/web/src/lib/composer/commit.ts, apps/web/src/lib/composer/controller.svelte.ts, apps/web/src/lib/tasks/TaskBoard.svelte, apps/web/src/lib/tasks/TaskCard.svelte, apps/web/src/lib/tasks/TaskColumn.svelte, apps/web/src/lib/tasks/TasksWorkspace.svelte
  • API and shared UI: contracts/openapi.json, crates/plugins/notes/src/lib.rs, crates/plugins/notes/src/tasks_api.rs, packages/api-client/src/generated.ts, packages/ui/src/tokens.css
  • Adversarial probe: tests/adversarial/attack.py
  • Local origin/dev merge conflict resolution: apps/web/src/routes/+layout.svelte, tests/adversarial/xuser_matrix.py

Gates

cargo fmt --check
(no output; exit status 0)

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

cargo test -p calternal-notes-core
test result: ok. 528 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.16s
test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 14.42s
test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.10s
test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.52s
test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

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

cargo test -p calternal-plugin-notes
test result: ok. 136 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 85.33s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.61s
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
Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 31s

cargo test -p calternal-server
test result: ok. 93 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 30.43s

bun run check
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  143 passed (143)
      Tests  938 passed (938)
   Duration  112.29s (transform 53%, environment 18%, import 15%, tests 11%, setup 4%)

tasks e2e: composer, per-layout and per-lane Add task, Board drag, phone layout menu, touch actions, live Bases file edit, and screenshots passed in /home/kayg/Developer/calternal-wt/tasks-mode/artifacts/tasks-mode-430-f3e211f3e
CSP REPORTS tasks: 0 across 2 pages

cargo clean
Removed 16406 files, 9.8GiB total

Screenshots attached

The 30 new captures are attached to this issue. Each width has Paper and Tokyo Night Board, List, Matrix, sidebar, and 3× card crop captures.

390 px

Gaps at the four-hour cutoff

  • The 10,000-Task profile setup reached 188 tasks in about 10 minutes and was stopped. The bounded 1,000-Task run reached 774/1,000 after about 1h46 and was stopped at the owner’s four-hour job limit, before route and burst sampling. docs/perf/baseline.json has no comparable Tasks UI entry.
  • The required one-round adversarial probe was not run after the merge because the four-hour limit had passed. The existing Task Status probe checks invalid status (400) and valid blocked status (201) when run.
  • Notes and server Clippy/test passed after behavior changes and before the final Rustdoc-only comment commit; cargo fmt --check passed after that Rust comment. The final adversarial module change was documentation only.

Commits

  • abb05d977 — Board layout and lane creation
  • f3e211f3e — local merge of origin/dev before final gates
  • 5b2855676 — keep Task card actions clear of title clicks
  • 2ec2b31fb — document initial Task Status invariant
  • fec3352b1 — document Task Status adversarial probe

Head SHA: fec3352b173671cf225ca311b748b19f2eebf648. No push, deploy, or merge to dev was made. cargo clean removed the job target, and the web build output was deleted.

## Final report — Tasks mode polish round (#430) ### Built - Made the Board scroller transparent and applied the shared inline edge fade. Board lanes now own their “Add task” row; empty lanes say “No tasks”. - Aligned Task card text, metadata, group labels, and empty copy to the title text start. The card action stays at the top trailing corner and appears on hover, focus, and touch. Board cards omit the repeated Status chip. - Moved the phone layout selector into the More actions → Layout menu. List and Matrix keep the existing view-wide “Add task” row below their content. - Added an optional initial `status` to the existing Notes Task-create route. A Board lane create writes Status, completion date, and the root Checkbox together. - Updated Tasks E2E and the adversarial Task-create probe. ### Decisions - The design did not specify how a Board lane supplies initial Status. I used the existing Task-create route with an optional `status` field, preserving the one-action/one-route rule in DESIGN §41. - The phone layout choices live in the “More actions” menu because the prompt allowed the menu or sidebar sub-views and the chrome rules require one bar. - List and Matrix retain a view-wide Add row below their content; Board uses a per-lane row. - The performance profile used a 1,000-Task target after the 10,000-Task setup exceeded the job timebox on the shared local host. The 1,000-Task seed did not finish before the four-hour cutoff, so it produced no route or burst metrics. ### Files changed in this round - Tasks UI and composer: `apps/web/e2e/tasks.mjs`, `apps/web/src/lib/composer/Composer.svelte`, `apps/web/src/lib/composer/commit.ts`, `apps/web/src/lib/composer/controller.svelte.ts`, `apps/web/src/lib/tasks/TaskBoard.svelte`, `apps/web/src/lib/tasks/TaskCard.svelte`, `apps/web/src/lib/tasks/TaskColumn.svelte`, `apps/web/src/lib/tasks/TasksWorkspace.svelte` - API and shared UI: `contracts/openapi.json`, `crates/plugins/notes/src/lib.rs`, `crates/plugins/notes/src/tasks_api.rs`, `packages/api-client/src/generated.ts`, `packages/ui/src/tokens.css` - Adversarial probe: `tests/adversarial/attack.py` - Local `origin/dev` merge conflict resolution: `apps/web/src/routes/+layout.svelte`, `tests/adversarial/xuser_matrix.py` ### Gates ```text cargo fmt --check (no output; exit status 0) cargo clippy -p calternal-notes-core --all-targets -- -D warnings Finished `dev` profile [unoptimized + debuginfo] target(s) in 46.77s cargo test -p calternal-notes-core test result: ok. 528 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.16s test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 14.42s test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.10s test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.52s test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s cargo clippy -p calternal-plugin-notes --all-targets -- -D warnings Finished `dev` profile [unoptimized + debuginfo] target(s) in 31.21s cargo test -p calternal-plugin-notes test result: ok. 136 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 85.33s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.61s 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 Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 31s cargo test -p calternal-server test result: ok. 93 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 30.43s bun run check 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 143 passed (143) Tests 938 passed (938) Duration 112.29s (transform 53%, environment 18%, import 15%, tests 11%, setup 4%) tasks e2e: composer, per-layout and per-lane Add task, Board drag, phone layout menu, touch actions, live Bases file edit, and screenshots passed in /home/kayg/Developer/calternal-wt/tasks-mode/artifacts/tasks-mode-430-f3e211f3e CSP REPORTS tasks: 0 across 2 pages cargo clean Removed 16406 files, 9.8GiB total ``` ### Screenshots attached The 30 new captures are attached to this issue. Each width has Paper and Tokyo Night Board, List, Matrix, sidebar, and 3× card crop captures. **390 px** - Paper: [390-paper-board.png](https://git.kayg.org/attachments/a8515287-d784-4226-bcb6-540e0b7c83f0) · [390-paper-list.png](https://git.kayg.org/attachments/7596f4f9-ce79-4504-b610-449f8351ba7f) · [390-paper-matrix.png](https://git.kayg.org/attachments/a3f21cde-ace4-4fd5-9a74-b3cc75ccf4a9) · [390-paper-sidebar.png](https://git.kayg.org/attachments/a55753a1-f3de-4acf-9e53-ef35aa985669) · [390-paper-card-3x.png](https://git.kayg.org/attachments/37ae1309-8422-446b-8163-289477b4e476) - Tokyo Night: [390-tokyo-night-board.png](https://git.kayg.org/attachments/1d7ec1b7-2f11-4961-99ba-62fa87226186) · [390-tokyo-night-list.png](https://git.kayg.org/attachments/a4e7e8a7-b4a5-44a5-8730-2bcddff592bb) · [390-tokyo-night-matrix.png](https://git.kayg.org/attachments/7e541641-38b0-46d2-a25b-6ccb5043169a) · [390-tokyo-night-sidebar.png](https://git.kayg.org/attachments/5aaa6261-3255-4c73-8c48-22c9e64e3be4) · [390-tokyo-night-card-3x.png](https://git.kayg.org/attachments/1ded890b-4fae-4e73-97e5-35a9e8f5b7fb) **820 px** - Paper: [820-paper-board.png](https://git.kayg.org/attachments/a140cdc0-5f61-45d6-ad18-a1670a216d92) · [820-paper-list.png](https://git.kayg.org/attachments/637a819f-e9fd-4623-930f-38ffb2b752d1) · [820-paper-matrix.png](https://git.kayg.org/attachments/ebb88310-3134-478e-8937-56a1ca5d2a8a) · [820-paper-sidebar.png](https://git.kayg.org/attachments/89c4d35d-dd7a-4048-9296-a9722abfa020) · [820-paper-card-3x.png](https://git.kayg.org/attachments/8dd7c9a9-1f7c-491d-a8c9-4fcb9bd9992b) - Tokyo Night: [820-tokyo-night-board.png](https://git.kayg.org/attachments/32b5b46a-05f9-4ed2-8c1a-b333e1e446c2) · [820-tokyo-night-list.png](https://git.kayg.org/attachments/73fc1cad-42e2-4aec-a8e9-9157dc233cf4) · [820-tokyo-night-matrix.png](https://git.kayg.org/attachments/409a66cb-8eeb-4c95-867d-ed8e14fbcb69) · [820-tokyo-night-sidebar.png](https://git.kayg.org/attachments/3dc843d0-7883-4395-95da-4962503b75dd) · [820-tokyo-night-card-3x.png](https://git.kayg.org/attachments/190749a4-2003-4820-ad96-b4580cae0dfd) **1440 px** - Paper: [1440-paper-board.png](https://git.kayg.org/attachments/be9893cc-479c-421d-bdfd-de4d996dca7c) · [1440-paper-list.png](https://git.kayg.org/attachments/8965890a-7a3a-4cd2-8568-c1330c229758) · [1440-paper-matrix.png](https://git.kayg.org/attachments/7df00695-fede-4f55-9a08-c8846d7055a9) · [1440-paper-sidebar.png](https://git.kayg.org/attachments/39329274-6122-4a15-bfd5-21c6e08459e8) · [1440-paper-card-3x.png](https://git.kayg.org/attachments/b2d52b07-0719-4c2b-800d-d2e54991ba6f) - Tokyo Night: [1440-tokyo-night-board.png](https://git.kayg.org/attachments/4d84d866-1934-4b9e-80a8-e52163a77ec1) · [1440-tokyo-night-list.png](https://git.kayg.org/attachments/28a85e8d-6e67-4439-880c-fd208317f42d) · [1440-tokyo-night-matrix.png](https://git.kayg.org/attachments/e4a06e0b-6f4c-4cae-b0c2-86d4a7bd2b38) · [1440-tokyo-night-sidebar.png](https://git.kayg.org/attachments/e76ae5ed-497c-4a78-8028-fe7748ed3572) · [1440-tokyo-night-card-3x.png](https://git.kayg.org/attachments/3ecf4a92-c6fd-4489-b5f5-4e02cdf2776f) ### Gaps at the four-hour cutoff - The 10,000-Task profile setup reached 188 tasks in about 10 minutes and was stopped. The bounded 1,000-Task run reached 774/1,000 after about 1h46 and was stopped at the owner’s four-hour job limit, before route and burst sampling. `docs/perf/baseline.json` has no comparable Tasks UI entry. - The required one-round adversarial probe was not run after the merge because the four-hour limit had passed. The existing Task Status probe checks invalid status (400) and valid `blocked` status (201) when run. - Notes and server Clippy/test passed after behavior changes and before the final Rustdoc-only comment commit; `cargo fmt --check` passed after that Rust comment. The final adversarial module change was documentation only. ### Commits - `abb05d977` — Board layout and lane creation - `f3e211f3e` — local merge of `origin/dev` before final gates - `5b2855676` — keep Task card actions clear of title clicks - `2ec2b31fb` — document initial Task Status invariant - `fec3352b1` — document Task Status adversarial probe Head SHA: `fec3352b173671cf225ca311b748b19f2eebf648`. No push, deploy, or merge to `dev` was made. `cargo clean` removed the job target, and the web build output was deleted.
Author
Owner

Owner update (2026-09-30): the default Tab list in this issue (Calendar, Tasks, Notes, Files, Photos, Analytics) is superseded. Owner: "didn't we decide that it should be Calendar, Tasks, Notes, Files, Photos, Mail, Contacts, Money?" and "i simply forgot to add it. please add it."

DESIGN §34 now has: Calendar, Tasks, Notes, Files, Photos, Mail, Contacts, Money, Analytics, then Ask; only enabled Tabs show, and Money is off until onboarding (#475). The order and the Tab Bar width are tracked in #590 and #591 (branch job/tray-order, not merged yet). The Tasks mode work keeps using that shared order and does not hard-code its own list.

**Owner update (2026-09-30):** the default Tab list in this issue (Calendar, Tasks, Notes, Files, Photos, Analytics) is superseded. Owner: "didn't we decide that it should be Calendar, Tasks, Notes, Files, Photos, Mail, Contacts, Money?" and "i simply forgot to add it. please add it." DESIGN §34 now has: Calendar, Tasks, Notes, Files, Photos, Mail, Contacts, Money, Analytics, then Ask; only enabled Tabs show, and Money is off until onboarding (#475). The order and the Tab Bar width are tracked in #590 and #591 (branch `job/tray-order`, not merged yet). The Tasks mode work keeps using that shared order and does not hard-code its own list.
Author
Owner

Starting Round 3 in job/tasks-mode, based on merge-base cc25c441b7a974185622a1dee853cf38686d2b67; current branch HEAD is fec3352b173671cf225ca311b748b19f2eebf648. I am addressing the three remaining alignment items from review artifacts tasks-mode-430-f3e211f3e and will attach fresh screenshots and gate output when finished.

Starting Round 3 in `job/tasks-mode`, based on merge-base `cc25c441b7a974185622a1dee853cf38686d2b67`; current branch HEAD is `fec3352b173671cf225ca311b748b19f2eebf648`. I am addressing the three remaining alignment items from review artifacts `tasks-mode-430-f3e211f3e` and will attach fresh screenshots and gate output when finished.
Author
Owner

Round 3 report

Branch: job/tasks-mode
Merged base: origin/dev at 3f258302a0f2d6418ff60c9ce22cbb33e008ca99
Head: f620390c724ee08540d38b0ba69c3d12225fc1e4 (Align task board metadata and lanes)
Merge commit: cc0db120d409e2e5df0ecac2d5c0697040ac37b6

Built

  • Task date and priority metadata now use secondary text without pill backgrounds or inset. TagPills stay visible and start at the Task title text edge.
  • “No tasks” and “+ Add task” now start at the lane title text edge.
  • The Board keeps the shared inline-end fade and adds its shared fade width as end padding so the last lane has clear space at maximum scroll.
  • The Tasks E2E checks the metadata styling/alignment, TagPill edge, lane text alignment and shared fade inset.

Files changed:

  • apps/web/src/lib/tasks/TaskCard.svelte
  • apps/web/src/lib/tasks/TaskColumn.svelte
  • apps/web/src/lib/tasks/TaskBoard.svelte
  • apps/web/e2e/tasks.mjs

Review images

The fresh local folder is artifacts/tasks-mode-430-r3-review/. Ten images are attached to this issue with round3- names:

Gates

cargo fmt --check exited 0 with no output.

Verbatim Rust gate summary lines:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 13.08s
    Finished `test` profile [unoptimized + debuginfo] target(s) in 14.98s
test result: ok. 532 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.24s
test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.17s
test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s
test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.39s
test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 01s
    Finished `test` profile [unoptimized + debuginfo] target(s) in 3m 05s
test result: ok. 167 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 88.34s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.42s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 12s
    Finished `test` profile [unoptimized + debuginfo] target(s) in 11m 25s
test result: ok. 107 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 10.61s

bun run check verbatim summary:

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.
Getting Svelte diagnostics...
svelte-check found 0 errors and 0 warnings

bun run test verbatim summary lines (the runner also printed existing CSS parse and jsdom scrollTo() notices):

 Test Files  151 passed (151)
      Tests  1019 passed (1019)
   Start at  15:49:56
   Duration  48.50s (transform 46%, environment 20%, import 18%, tests 12%, setup 4%)

Tasks E2E (run with Node directly after this host’s Bun/Sharp wrapper could not load libstdc++.so.6):

tasks e2e: composer, per-layout and per-lane Add task, Board drag, phone layout menu, touch actions, live Bases file edit, and screenshots passed in /home/kayg/Developer/calternal-wt/tasks-mode/artifacts/tasks-mode-430-r3-review
CSP REPORTS tasks: 0 across 2 pages

The first direct browser run reported one state_unsafe_mutation; it did not recur on the successful run with stack diagnostics enabled.

Adversarial and performance notes

The one-time ADVERSARIAL_API_ONLY=1 campaign finished with FINDINGS 29; SLOW-only results were load. The server was alive at the end, the search storm had zero failures, the mkdir storm created 200 items with zero errors, and the rename race had one success and zero errors. No Task storm request timed out. The non-SLOW tag/DAV findings are recorded in #568, and the MCP probe setup failure is recorded in #564. The existing expectations were not changed.

The existing bench/tasks-ui profile was attempted locally against the production web build. Its 10,000-Task seed stopped making progress at Task 3,288 for nearly six minutes while the debug server continued heavy writes. I stopped the run before route measurements; no timing file was produced. docs/perf/baseline.json has no matching Tasks UI workload, so there is no comparable baseline yet. This remains a performance follow-up, not a merge gate.

Cleanup: cargo clean reported Removed 16483 files, 9.0GiB total; apps/web/build and apps/web/.svelte-kit were deleted. Screenshots remain uncommitted.

Known gaps

  • The local Tasks UI profile did not reach route or burst measurements.
  • The API adversarial round found existing non-SLOW tag/DAV mismatches; see #568. MCP fixture setup failed before the probe; see #564.
  • The standard Bun Tasks E2E wrapper could not load its native sharp dependency on this host; direct Node execution passed.

Decisions

No new decision outside the Round 3 instructions. Date/priority metadata uses the secondary text role; TagPills remain visible in their own aligned row; Board end space uses the shared --scroll-fade token.

## Round 3 report **Branch:** `job/tasks-mode` **Merged base:** `origin/dev` at `3f258302a0f2d6418ff60c9ce22cbb33e008ca99` **Head:** `f620390c724ee08540d38b0ba69c3d12225fc1e4` (`Align task board metadata and lanes`) **Merge commit:** `cc0db120d409e2e5df0ecac2d5c0697040ac37b6` ### Built - Task date and priority metadata now use secondary text without pill backgrounds or inset. TagPills stay visible and start at the Task title text edge. - “No tasks” and “+ Add task” now start at the lane title text edge. - The Board keeps the shared inline-end fade and adds its shared fade width as end padding so the last lane has clear space at maximum scroll. - The Tasks E2E checks the metadata styling/alignment, TagPill edge, lane text alignment and shared fade inset. Files changed: - `apps/web/src/lib/tasks/TaskCard.svelte` - `apps/web/src/lib/tasks/TaskColumn.svelte` - `apps/web/src/lib/tasks/TaskBoard.svelte` - `apps/web/e2e/tasks.mjs` ### Review images The fresh local folder is `artifacts/tasks-mode-430-r3-review/`. Ten images are attached to this issue with `round3-` names: - 390 px Board: [paper](https://git.kayg.org/attachments/79a5253f-00e4-41b9-9c83-aac3f1b1a7be), [Tokyo Night](https://git.kayg.org/attachments/ee9fcd4f-458f-4714-89f8-1b763fe4cb2d) - 820 px Board: [paper](https://git.kayg.org/attachments/0b56708c-c1ee-4eff-96f6-6d06d6a3e9da), [Tokyo Night](https://git.kayg.org/attachments/b3a7192e-8dbe-4d06-b812-d482bd77faaa) - 1440 px Board: [paper](https://git.kayg.org/attachments/7a9ea15c-4fc8-404e-b55e-966e5e811541), [Tokyo Night](https://git.kayg.org/attachments/41602056-4f05-4d0e-9b2e-147cae55353e) - 3× Task card crops at 390 px: [paper](https://git.kayg.org/attachments/ae0ec231-9d25-406b-939d-3854d1e90e80), [Tokyo Night](https://git.kayg.org/attachments/19ee3c82-4bab-4cdd-8d5d-4cb76fb06374) - 3× Task card crops at 1440 px: [paper](https://git.kayg.org/attachments/ce3d2713-3fb8-41cd-966b-eccdb01df5ae), [Tokyo Night](https://git.kayg.org/attachments/5a2b0023-7662-44ab-9a25-c44edbe71403) ### Gates `cargo fmt --check` exited 0 with no output. Verbatim Rust gate summary lines: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 13.08s Finished `test` profile [unoptimized + debuginfo] target(s) in 14.98s test result: ok. 532 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.24s test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.17s test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.39s test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 01s Finished `test` profile [unoptimized + debuginfo] target(s) in 3m 05s test result: ok. 167 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 88.34s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.42s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 12s Finished `test` profile [unoptimized + debuginfo] target(s) in 11m 25s test result: ok. 107 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 10.61s ``` `bun run check` verbatim summary: ```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. Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `bun run test` verbatim summary lines (the runner also printed existing CSS parse and jsdom `scrollTo()` notices): ```text Test Files 151 passed (151) Tests 1019 passed (1019) Start at 15:49:56 Duration 48.50s (transform 46%, environment 20%, import 18%, tests 12%, setup 4%) ``` Tasks E2E (run with Node directly after this host’s Bun/Sharp wrapper could not load `libstdc++.so.6`): ```text tasks e2e: composer, per-layout and per-lane Add task, Board drag, phone layout menu, touch actions, live Bases file edit, and screenshots passed in /home/kayg/Developer/calternal-wt/tasks-mode/artifacts/tasks-mode-430-r3-review CSP REPORTS tasks: 0 across 2 pages ``` The first direct browser run reported one `state_unsafe_mutation`; it did not recur on the successful run with stack diagnostics enabled. ### Adversarial and performance notes The one-time `ADVERSARIAL_API_ONLY=1` campaign finished with `FINDINGS 29`; SLOW-only results were load. The server was alive at the end, the search storm had zero failures, the mkdir storm created 200 items with zero errors, and the rename race had one success and zero errors. No Task storm request timed out. The non-SLOW tag/DAV findings are recorded in #568, and the MCP probe setup failure is recorded in #564. The existing expectations were not changed. The existing `bench/tasks-ui` profile was attempted locally against the production web build. Its 10,000-Task seed stopped making progress at Task 3,288 for nearly six minutes while the debug server continued heavy writes. I stopped the run before route measurements; no timing file was produced. `docs/perf/baseline.json` has no matching Tasks UI workload, so there is no comparable baseline yet. This remains a performance follow-up, not a merge gate. Cleanup: `cargo clean` reported `Removed 16483 files, 9.0GiB total`; `apps/web/build` and `apps/web/.svelte-kit` were deleted. Screenshots remain uncommitted. ### Known gaps - The local Tasks UI profile did not reach route or burst measurements. - The API adversarial round found existing non-SLOW tag/DAV mismatches; see #568. MCP fixture setup failed before the probe; see #564. - The standard Bun Tasks E2E wrapper could not load its native `sharp` dependency on this host; direct Node execution passed. ### Decisions No new decision outside the Round 3 instructions. Date/priority metadata uses the secondary text role; TagPills remain visible in their own aligned row; Board end space uses the shared `--scroll-fade` token.
Author
Owner

Static audit evidence for DESIGN §35 default Tab order:

apps/web/src/lib/navigation.ts:49-52 reserves a Tasks slot in DEFAULT_MODE_ORDER, but PLUGIN_NAVIGATION has no Tasks item; modeItemsForCatalog at :166-174 emits only registered items. The route inventory also has no /tasks page (Tasks resolve through /t/[id] and Calendar).

Expected: implement the Tasks Tab and its sidebar entries before enabling its slot. Regression idea: with Tasks enabled, verify its default order, navigation entry and stable task deep link.

Static audit evidence for DESIGN §35 default Tab order: apps/web/src/lib/navigation.ts:49-52 reserves a Tasks slot in DEFAULT_MODE_ORDER, but PLUGIN_NAVIGATION has no Tasks item; modeItemsForCatalog at :166-174 emits only registered items. The route inventory also has no /tasks page (Tasks resolve through /t/[id] and Calendar). Expected: implement the Tasks Tab and its sidebar entries before enabling its slot. Regression idea: with Tasks enabled, verify its default order, navigation entry and stable task deep link.
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#430
No description provided.