# SLICE 4 — gtd-gantt data layer > **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). Pure data layer landed; 140/140 tests pass; `tsc --noEmit` clean. No rendering/index wiring yet — that is SLICE5. Resolved open question (2026-07-15): dateless/invalid-date gantt items are **excluded with a warning** (the recorded default) — no Unscheduled strip. If a strip is wanted later it's an additive change to collectGantt + the payload. ## Goal Pure data layer for the gantt: item opt-in parsing, project grouping, collection, config parsing. No rendering yet. ## Design (agreed with user 2026-07-13) - Items opt in with their own ```gtd-gantt fenced block (separate from ```gtd): - **Notes** (bars): `project: bluesky`, `begin-date: yyyy-mm-dd`, `end-date: yyyy-mm-dd` (accept same date formats as resolveDate.ts). - **To-dos** (milestones): `project: bluesky`; the milestone date is the to-do's native **due date**. begin/end on a to-do → warning, treated as milestone anyway. - Rows/swimlanes are grouped by `project:`. - **Chart block vs item block disambiguation** (same fence name!): a `gtd-gantt` block containing a `project:` key is an ITEM declaration; without `project:` it is the CHART config block. The markdown-it renderer must apply the same rule (SLICE5). Item blocks render as a small inline badge ("gantt: bluesky"), not a chart. - Chart config keys: `title`, `notebook`, `scope`, `filter-project` (optional; limit to one project), `sort` / `sort-type` (row order within project), `card-detail` semantics for hover text. Defaults follow the existing parsers' conventions; invalid values warn + fall back. - Semantics: completed to-do milestones render checked/struck (consistent with calendar). Items with unparseable/missing dates → warning + excluded (a gantt has no Unscheduled section — confirm with user if one is wanted; see open questions). - Reuse styling keys? Item gtd-gantt block also accepts `bg-colour`, `fg-colour`, `title`, `text` mirroring the gtd block. ## Open questions for user (non-blocking, defaults chosen) - Dateless gantt items: currently planned as warn+exclude. Alternative: an "Unscheduled" strip like the calendar. DEFAULT: exclude with warning. ## Tasks - [x] `src/Gtd/ganttBlock.ts` — `extractGanttBlock` mirrors gtdBlock.ts (fence regex for `gtd-gantt`, same YAML/empty/malformed handling). Parses project / begin-date / end-date + styling keys (bg-colour/fg-colour/title/ text). Classification is the caller's job via `block.project` (non-null ⇒ item, null ⇒ chart). - [x] `src/Gtd/parseGanttConfig.ts` — chart config: title, scope (+ scope: all + notebook conflict warning), notebook, filter-project, sort, sort-type (`begin-date`|`title`|`modified-date`), card-detail. Invalid → warn + default. - [x] `src/Gtd/collectGantt.ts` — scope (scopeAll-aware) → fetch (always with body) → item filter (project present, ≠ chart) → filter-project → bar vs milestone → group by project → sort → compute range. Returns typed `GanttChart { projects, rangeStart, rangeEnd, warnings, scannedFolders, scannedNotes, itemCount }`. Rules: notes → bars (begin+end required & valid, end≥begin else warn+exclude); to-dos → milestones on their due date (begin/end on a to-do → warning; no due date → warn+exclude); completed/recurring flags on milestones; projects merged case-insensitively, output alphabetical. - [x] Types in `src/Gtd/types.ts` — GanttSortType, GanttItemBlock, GanttBlockResult, GanttConfig, GanttBar, GanttMilestone, GanttProject, GanttChart. - [x] Thorough unit tests — `src/tests/Gtd/gantt.test.ts` (20 cases): block extraction (chart vs item, styling, Date coercion, malformed), config (defaults/full/conflict/invalid), collector (grouping+range, ignore chart/plain/host, bar bad/reversed dates, milestone due-date + begin/end warning, milestone no-due-date, completed+recurring, filter-project, begin-date sort + direction, case-insensitive project merge). - [x] Full test run: **140 passed, 140 total** (12 suites) on 2026-07-15. `tsc --noEmit` clean for src/. ## Resume notes SLICE4 complete — pure data layer only. New files: - `src/Gtd/ganttBlock.ts`, `parseGanttConfig.ts`, `collectGantt.ts` - gantt types appended to `src/Gtd/types.ts` - `src/tests/Gtd/gantt.test.ts` NOT done here (belongs to SLICE5): the markdown-it renderer's chart-vs-item disambiguation, the `getGantt` message handler in `src/index.ts`, and any webview rendering. `collectGantt`'s signature mirrors the other collectors (`adapter, hostNoteId, hostFolderId, config`) so index wiring will look like handleGetKanban. Item blocks must render as a small inline badge (not a chart) — that's a SLICE5 renderer concern. Next: SLICE5.