87 lines
5.0 KiB
Markdown

# 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.