3.6 KiB
SLICE 2 — notebook: option for all gtd block types
State-saving rule: update this file immediately after EVERY completed task (tick the checkbox, update Status and Resume notes) and whenever pausing for input — automatically, without being asked. State on disk must always match reality.
Status
COMPLETE (2026-07-15). SLICE1 done; all tasks landed; 112/112 tests pass.
Goal
Every view block (gtd-calendar, gtd-kanban, gtd-matrix, later gtd-gantt)
accepts notebook: <name-or-path-or-id> to root the folder scan at a specific
notebook, possibly outside the host note's tree. scope: then applies relative
to that notebook.
Design (agreed with user 2026-07-13)
- Accept, in order of resolution:
- A raw 32-char hex folder id.
- A
Parent/Child/...title path (case-insensitive match on titles). - A bare title — if unique, use it; if ambiguous, warn and fall back to the host folder (consistent with the plugin's warn-don't-fail convention).
- Unknown notebook → warning + fall back to host folder.
- Folder titles are needed: extend
DataAdapter.getFolders()fields to includetitle(currently id/parent_id only).
Tasks
- Extend
RawFolder+joplinAdapter.getFolders()withtitle. Done:RawFolder.titleis optional (title?: string) — folder scoping uses id/parent_id only, so scope-only test fixtures don't need it; the real adapter always requests["id","parent_id","title"]. - New
src/Gtd/resolveNotebook.ts(pure): folders + spec →{ folderId, warning }. Resolution order id → path → unique bare title; any miss warns and falls back to the host folder. Also exportsparseNotebookOption(shared trim/null normaliser used by all three config parsers). - Add
notebookkey to parseCalendarConfig / parseKanbanConfig / parseMatrixConfig (string | null, default null; "notebook" added to each knownKeys list). - Wire in
src/index.ts:resolveScanFolder()helper resolves the notebook (or returns host folder) and pushes any warning ontoconfig.warnings; all three handlers pass the resolved id to their collector. - Tests:
src/tests/Gtd/resolveNotebook.test.ts— resolver (id, unknown id, unique title, ambiguous title, missing title, path, path-disambiguation, unresolvable path, empty),parseNotebookOption, config parsing for all three views, and a collector-level integration (resolved notebook reroots collectEvents' scan). 15 new cases. - Docs: README option tables (all three views) + SPEC.md §2.1/§2.3/§2.4 (row + example lines). Workspace planning files remain git-excluded.
- Full test run: 112 passed, 112 total (10 suites) on 2026-07-15.
npx tsc --noEmitclean forsrc/(only pre-existing api/ + node_modules lib noise).
Resume notes
SLICE2 complete. Files touched:
src/Gtd/types.ts(RawFolder.title?,notebookon all three configs)src/Gtd/resolveNotebook.ts(new; resolver +parseNotebookOption)src/Gtd/parseCalendarConfig.ts,parseKanbanConfig.ts,parseMatrixConfig.ts(notebook key + knownKeys)src/index.ts(getFolders title field,resolveScanFolder, 3 handler wirings)src/tests/Gtd/resolveNotebook.test.ts(new)README.md(3 tables),SPEC.md(§2.1 row + 3 example lines)
Design note: notebook resolution lives in index.ts (needs the folder tree),
so collectors stay unchanged — they still take a plain folderId. When
notebook: is set, getFolders() is fetched once in the handler and again
inside the collector; acceptable (only on notebook use), could be deduped later
if it matters. Next: SLICE3 (scope: all).