# 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: ` 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: 1. A raw 32-char hex folder id. 2. A `Parent/Child/...` title path (case-insensitive match on titles). 3. 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 include `title` (currently id/parent_id only). ## Tasks - [x] Extend `RawFolder` + `joplinAdapter.getFolders()` with `title`. Done: `RawFolder.title` is 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"]`. - [x] 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 exports `parseNotebookOption` (shared trim/null normaliser used by all three config parsers). - [x] Add `notebook` key to parseCalendarConfig / parseKanbanConfig / parseMatrixConfig (`string | null`, default null; "notebook" added to each knownKeys list). - [x] Wire in `src/index.ts`: `resolveScanFolder()` helper resolves the notebook (or returns host folder) and pushes any warning onto `config.warnings`; all three handlers pass the resolved id to their collector. - [x] 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. - [x] Docs: README option tables (all three views) + SPEC.md §2.1/§2.3/§2.4 (row + example lines). Workspace planning files remain git-excluded. - [x] Full test run: **112 passed, 112 total** (10 suites) on 2026-07-15. `npx tsc --noEmit` clean for `src/` (only pre-existing api/ + node_modules lib noise). ## Resume notes SLICE2 complete. Files touched: - `src/Gtd/types.ts` (`RawFolder.title?`, `notebook` on 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`).