Commit Graph
749 Commits
Author SHA1 Message Date
Lucas Berger 9fb1e0da84 docs(04-02): complete scoped fan-out primitives plan
SUMMARY.md for 04-02: listEmitter + listAccess TDD plan.
RED/GREEN gate confirmed. D-04 isolation proven. ioredis not introduced.
2026-06-09 12:24:50 -04:00
Lucas Berger 9e17853d89 fix(04-02): use fileParallelism:false to prevent DB test race conditions
Replaced singleFork:true + sequence config with the simpler fileParallelism:false
which correctly serializes test file execution. The previous singleFork approach
ran tests from multiple files concurrently within one process, allowing the global
afterEach cleanup (test/setup.ts: truncates lists/listShares) to delete rows mid-test
in another file, causing intermittent FK violations (ER_DUP_ENTRY, ER_NO_REFERENCED_ROW).

fileParallelism:false runs one test file at a time so afterEach cleanup for file A
never races with insertions from file B.
2026-06-09 12:23:13 -04:00
Lucas Berger 792efeb3df feat(04-02): implement listEmitter + listAccess; all 9 tests GREEN
listEmitter.ts:
- Module-level EventEmitter singleton; setMaxListeners(200) (T-04-04)
- publishListEvent(listId, event): emits on list:${listId} channel
- subscribeListEvents(listId, handler): registers listener, returns unsub closure
- ListEvent type union: item:added/updated/deleted, list:updated/deleted
- D-04 isolation guaranteed by per-list channel keying

listAccess.ts:
- getAccessibleListIds(userId): two SELECT queries (owned + shared), Set dedupe
- Satisfies T-04-02/T-04-03: over-returning proven impossible by Test 7

listAccess.test.ts fix:
- Use randomUUID() suffix in seedUser to avoid oidc_sub unique-key collisions
  across test re-runs (users table not truncated by global afterEach)

vitest.config.ts:
- pool: 'forks' + singleFork: true to prevent FK violations from concurrent
  DB workers racing against the shared-state global afterEach cleanup
- sequence.concurrent: false as belt-and-suspenders

ioredis NOT introduced (D-18 abstraction boundary satisfied)
2026-06-09 12:20:38 -04:00
Lucas Berger 2d250afce2 test(04-02): add failing listEmitter + listAccess tests (RED gate)
- listEmitter.test.ts: 5 real assertions replacing it.todo stubs
  (Tests 1-4: scoped delivery, D-04 negative cross-list isolation, unsub, multi-handler, D-18 scale)
- listAccess.test.ts: 4 DB-backed assertions (Tests 5-8)
  (owned lists, shared via list_shares, D-04 negative private exclusion, dedupe)
- Both files fail: listEmitter.ts and listAccess.ts do not exist yet
2026-06-09 12:15:19 -04:00
Lucas Berger 60745b3281 refactor(04-01): move API list test stubs into tests/ mirror dir to match convention
The two Wave-0 RED stubs (lists.test.ts, listEmitter.test.ts) were co-located in
src/ but all existing API tests live in apps/api/tests/. Move them to tests/routes/
and tests/lib/, add explicit vitest imports to match the tests/ convention, and
update path references in downstream plans 04-02..04-06. PWA tests keep co-location
(that IS the PWA convention).
2026-06-09 12:10:31 -04:00
Lucas Berger 0fd4d66ee7 docs(04-01): complete lists foundation plan 2026-06-09 12:06:53 -04:00
Lucas Berger c0088edf44 feat(04-01): wire BrowserRouter + BottomTabBar + empty Lists surface
- App.tsx: BrowserRouter with /calendar, /lists, /lists/:listId routes; / redirects to /calendar
- BottomTabBar.tsx: fixed-bottom 56px tab bar with Calendar + Lists NavLinks, active accent
- AppNav.tsx: add Calendar/Lists NavLinks to desktop sidebar (≥768px)
- ListsIndex.tsx: full-height surface with isLoading/isError/empty state branches; "+ New List" FAB placeholder
- ListDetail.tsx: placeholder stub for /lists/:listId (Plan 04-04 fills in)
- listsStore.ts: Zustand UI-only store (activeTab, createListSheetOpen)
- listsClient.ts: fetchLists + List/ListItem types (initial; Plans 04-02/03 expand)
- Fix Wave-0 RED stubs: add vitest imports so stubs execute (todo) not error on import
- Fix CalendarShell.test.tsx: wrap renderWithClient in MemoryRouter (AppNav uses NavLink)
2026-06-09 12:03:52 -04:00
Lucas Berger 2f25b15949 feat(04-01): add list tables to schema and apply via generate+migrate [BLOCKING]
- Append lists, list_shares, list_items tables to Drizzle schema (schema.ts)
- lists: owner_id FK, is_shared bool default true (D-01), idx_lists_owner_id
- list_shares: list_id + user_id FKs, uniq_list_share, idx_list_shares_user_id (D-02)
- list_items: rank varchar for fractional-indexing (D-13), checked bool, composite indexes
- Generate 0000_easy_slipstream.sql (full schema baseline) + 0001_lists_schema.sql (new tables)
- Mark 0000 as applied in __drizzle_migrations (prior tables existed from manual DDL)
- Apply 0001_lists_schema.sql via db:migrate — lists/list_shares/list_items now in MariaDB
- Add vitest/globals + node to tsconfig types for test file compatibility
- NEVER used db:push (hard project constraint — drizzle-mariadb-push-unsafe)
- typecheck passes
2026-06-09 11:55:46 -04:00
Lucas Berger 39d4ec84c0 feat(04-01): install new deps + scaffold API test harness with Wave-0 RED stubs
- Add react-router@7, @dnd-kit/core, @dnd-kit/sortable, fractional-indexing to PWA
- Add fractional-indexing to API (rank generation server-side)
- ioredis NOT added (in-memory EventEmitter per RESEARCH Plan 02 justification)
- Create apps/api/test/setup.ts with afterEach DB cleanup for list tables
- Wire test.setupFiles in apps/api/vitest.config.ts
- Add 4 Wave-0 RED stub test files (LIST-01/02/03/04, D-04, D-11, D-07)
- All stubs run as todo, not import-error
2026-06-09 11:49:10 -04:00
Lucas Berger 95b13e6633 chore(04): commit pattern map + session config; ignore intel/graph diff baselines 2026-06-09 11:40:19 -04:00
Lucas Berger eb8ae15862 docs(03): add security threat verification (25/25 closed) 2026-06-09 11:38:53 -04:00
Lucas Berger 2a093468a4 chore: build intel index (.planning/intel/) 2026-06-09 11:33:33 -04:00
Lucas Berger a9da31cc35 test(03): complete UAT - 10 passed, 0 issues 2026-06-09 11:31:12 -04:00
Lucas Berger 01f7456b81 chore: add knowledge graph + ignore graphify-out build cache 2026-06-09 11:25:46 -04:00
Lucas Berger 00cbbb41a6 docs: map existing codebase 2026-06-09 11:20:11 -04:00
Lucas Berger 7c687ea413 docs(03): add code review fix report (--auto, 2 fix passes)
Auto-fix loop converged after 2 fix iterations + a final verifying re-review:
- Pass 1: 13/14 findings fixed (3 Critical, 6 Warning, 4 Info).
- Re-review surfaced 1 new Critical (move-path RRULE data loss) + 4 lower.
- Pass 2: 8/8 fixed, including the move-path RRULE forwarding.
- Final re-review: 0 Critical. Remaining 2 Warning / 2 Info are documented
  v1 scope cuts (recurrence-editing deferred), not defects.

Test suites green throughout: api 108, pwa 145; both tsc --noEmit clean.
Per-iteration REVIEW/REVIEW-FIX snapshots retained as audit trail.
2026-06-09 11:12:09 -04:00
Lucas Berger b8c186491b fix(03): IN-03 re-validate outbox payload before VEVENT build, hard-fail invalid rows 2026-06-09 11:05:50 -04:00
Lucas Berger f95760e6c6 fix(03): IN-01 document RRULE_PRESETS lossy round-trip v1 limitation 2026-06-09 11:05:50 -04:00
Lucas Berger fd13852eb9 fix(03): WR-04 rank failed/dead outbox row above done in sync-status 2026-06-09 11:04:00 -04:00
Lucas Berger 5b720ffdb8 fix(03): WR-03 log unconditional PUT/DELETE when If-Match etag is missing 2026-06-09 11:04:00 -04:00
Lucas Berger eed178fb39 fix(03): WR-01/WR-02/IN-02 recurrence-edit helper text, all-day toggle clamp, edit-mode parse-failure guard 2026-06-09 11:02:09 -04:00
Lucas Berger 5168920eb1 fix(03): CR-01 preserve RRULE on edit-as-move (forward source rule to create row) 2026-06-09 10:59:19 -04:00
Lucas Berger 7a48659cae fix(03): update event lookup test mocks for CR-01/CR-02 query-chain changes
The CR-01 fix appended .orderBy().limit(1) to the edit/delete event lookups
and CR-02 added .innerJoin(calendars).limit(1) to the freshest-etag re-read.
The existing test doubles terminated the mock chain at .where(), so the new
chain calls hit undefined methods → handlers caught the throw and returned 503
(events.test.ts) and the worker skipped the PUT (outboxWorker.test.ts).

Extend the mocks to match the corrected production chains. Behaviour-preserving:
mockWhereCalEvents stays the awaited terminal so etag override assertions still drive.

8 failing tests now green; full suite: api 103, pwa 141.
2026-06-09 10:51:10 -04:00
Lucas Berger 6d2fd79209 fix(03): IN-04 type resolveUserId param as Hono Context instead of any 2026-06-09 10:44:15 -04:00
Lucas Berger 7e4ea710d0 fix(03): IN-03 guard localStorage access in InstallPrompt 2026-06-09 10:43:37 -04:00
Lucas Berger e29d6c1714 fix(03): IN-02 treat unmapped 4xx as hard fail (no full-backoff retry) 2026-06-09 10:43:14 -04:00
Lucas Berger 95f9d8c097 fix(03): IN-01 cache decrypted client per userId within a drain cycle 2026-06-09 10:42:41 -04:00
Lucas Berger 1c71f8c980 fix(03): WR-06 surface move-failed distinctly with re-save guidance 2026-06-09 10:41:55 -04:00
Lucas Berger 7bc129f0f3 fix(03): WR-04 start background workers only when run as entrypoint 2026-06-09 10:40:54 -04:00
Lucas Berger 22d1bc27d6 fix(03): WR-05 use resolved realpath for direct-run guard 2026-06-09 10:40:26 -04:00
Lucas Berger d34edece96 fix(03): WR-03 use cleaned string for all-day check in parseDateTime 2026-06-09 10:39:54 -04:00
Lucas Berger 5499f83782 fix(03): WR-02 make default-calendar selection deterministic (orderBy id, limit 1) 2026-06-09 10:39:28 -04:00
Lucas Berger 02aa407764 fix(03): WR-01 preserve existing RRULE on edit instead of resetting to none 2026-06-09 10:39:06 -04:00
Lucas Berger f645644853 fix(03): CR-03 convert exclusive all-day end to inclusive on edit pre-fill 2026-06-09 10:37:13 -04:00
Lucas Berger a596f520b4 fix(03): CR-02 scope freshest-etag re-read to the writing member's calendar 2026-06-09 10:36:18 -04:00
Lucas Berger 54addb1515 fix(03): CR-01 scope event edit/delete lookup to acting member's writable set 2026-06-09 10:35:51 -04:00
Lucas Berger 8b519460d9 docs(03): add code review report 2026-06-09 10:32:20 -04:00
Lucas Berger 197e138e3b docs(04): finalize phase plan (coverage gates + roadmap annotations) 2026-06-09 10:25:22 -04:00
Lucas BergerandClaude Opus 4.8 38fa6f448b docs(04): create phase plan — 6 plans across 5 waves for shared lists + live sync
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 10:21:53 -04:00
Lucas Berger d89eb47483 docs(03): add code review report 2026-06-09 10:19:01 -04:00
Lucas Berger a348bdd815 docs(04): add validation strategy 2026-06-09 10:03:12 -04:00
Lucas Berger bc45bddac9 docs(04): research phase — lists schema, SSE fan-out, fractional-indexing, dnd-kit, react-router 2026-06-09 10:01:47 -04:00
Lucas BergerandClaude Sonnet 4.6 492b85e9dc docs(04): UI design contract for shared lists + live sync
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 09:43:32 -04:00
Lucas Berger f695cc014d wip: Phase 4 paused — discuss complete, entry gate cleared, ready to plan 2026-06-07 21:53:23 -04:00
Lucas Berger 9ee59065f1 docs(quick-260607-u8o): record SSE-over-Pangolin smoke test PASS 2026-06-07 21:51:38 -04:00
Lucas Berger 1329e19803 chore: merge executor worktree (worktree-agent-a0352288acbf5055f) 2026-06-07 21:50:53 -04:00
Lucas Berger 26655cf859 docs(260607-u8o): mark Gate 2 Part C SSE row + summary PASS
- Part C row C1: PENDING -> PASS (2026-06-08) with verbatim evidence
- Summary Part-C row: DEFERRED -> PASS (Phase 4 entry gate D-14 cleared)
2026-06-07 21:49:55 -04:00
Lucas Berger dea6cb65a1 docs(260607-u8o): mark Phase 1 UAT item 4 (SSE smoke) PASS
- Record SSE-over-Pangolin smoke PASS (2026-06-08) with verbatim evidence
- Update Summary: passed 0->1, pending 4->3
2026-06-07 21:49:30 -04:00
Lucas Berger 92585d78db docs(260607-u8o): pre-dispatch plan for record SSE smoke PASS 2026-06-07 21:48:25 -04:00
Lucas Berger ecdb2317c8 docs(state): record phase 4 context session 2026-06-07 21:32:10 -04:00