5.0 KiB

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

  • src/Gtd/ganttBlock.tsextractGanttBlock 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).
  • 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.
  • 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.
  • Types in src/Gtd/types.ts — GanttSortType, GanttItemBlock, GanttBlockResult, GanttConfig, GanttBar, GanttMilestone, GanttProject, GanttChart.
  • 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).
  • 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.