2026-07-28 12:11:09 -04:00

277 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# SLICE 12 — Filter project notes independently from task to-dos
> **State-saving rule:** update this file after every completed task and whenever
> work pauses. Keep implementation, automated validation, production packaging,
> and manual Joplin acceptance as separate status boundaries.
## Status
**COMPLETE.** Phases 17 are implemented and validated. Focused and full
automation passed, the production JPL was built, and the user confirmed manual
Joplin acceptance on 2026-07-28.
## Goal
Allow `gtd-kanban` and `gtd-matrix` blocks to include or exclude opted-in
ordinary notes independently from native Joplin to-dos. The user treats
ordinary `gtd` notes as projects and native to-dos as tasks, and needs focused
project-only, task-only, and combined views.
```yaml
# Projects only
notes: all
todos: none
```
```yaml
# Tasks only
notes: none
todos: all
```
```yaml
# Projects and tasks
notes: all
todos: all
```
## Confirmed configuration contract
- The option is named `notes`, plural, matching the existing `todos` option and
the calendar configuration vocabulary.
- `notes` is valid only in `gtd-kanban` and `gtd-matrix` blocks in this slice.
- Accepted values are `all` and `none`.
- The default is `all`, preserving current behavior for existing blocks.
- `notes: all` means all **eligible ordinary notes containing a found `gtd`
block**. It never means every plain note in scope.
- `notes: none` excludes every ordinary note, including notes tagged
`in-progress`, `done`, `urgent`, or `important`.
- A tag alone never opts an ordinary note into a view.
- The existing `todos` contract remains unchanged: `gtd-only | all | none`,
defaulting to `gtd-only`.
- `notes` and `todos` are independent. Every valid combination is supported.
- Invalid or empty `notes` values warn and fall back to `all`.
- The singular key `note` remains unknown and produces the normal unknown-option
warning; no alias is introduced.
## Inclusion table
| Item | `gtd` block | `notes` | `todos` | Result |
|---|---:|---|---|---|
| Ordinary note | yes | `all` | any | Included, then normal view rules apply |
| Ordinary note | yes | `none` | any | Excluded |
| Ordinary note | no | `all` | any | Excluded |
| Ordinary note | no | `none` | any | Excluded |
| Native to-do | yes | any | `gtd-only` or `all` | Included, subject to completion rules |
| Native to-do | no | any | `all` | Included, subject to completion rules |
| Native to-do | no | any | `gtd-only` or `none` | Excluded |
The host dashboard note remains excluded regardless of its type, block, or
configuration.
## Interaction with existing behavior
### Kanban
- `notes: all` preserves SLICE9 and SLICE11 note behavior.
- An admitted unfinished note uses `in-progress-tag` to select In Progress or
Backlog.
- An admitted note carrying `done-tag` enters Done, even if it also carries
`in-progress-tag`.
- Completed ordinary notes remain exempt from the native to-do `done-window`.
- `notes: none` excludes ordinary notes before tag lookup, card construction,
completion checks, sorting, grouping, statistics, and pagination.
- Native to-do behavior is unaffected by `notes`.
### Matrix
- `notes: all` preserves both Skeleton and Eisenhower note behavior.
- Admitted notes carrying `done-tag` remain excluded before quadrant bucketing.
- Other admitted notes use the existing date and tag axes for the selected mode.
- `notes: none` excludes ordinary notes before tag lookup, completion checks,
quadrant bucketing, sorting, grouping, statistics, and pagination.
- Native completed to-dos remain excluded, and incomplete to-do behavior is
unaffected by `notes`.
### Notebook grouping and statistics
- SLICE10 exact-owner grouping remains unchanged.
- A filtered note must not create a notebook group, warning, card count, or
pagination state.
- A group containing only filtered notes is omitted.
- Non-empty descendant groups remain visible even when their ancestors become
empty after filtering.
- `scannedFolders` and `scannedNotes` continue to describe scan work, not admitted
cards; `cardCount`, bucket totals, headings, and pagination use admitted cards.
- Malformed-block warnings are emitted only for items admitted by their type
filter. A malformed ordinary note under `notes: none` produces no warning.
### Rendering and payload
- No new rendering branch is required. Collectors return the same card and
grouped-layout payloads with filtered arrays and totals.
- SLICE8 independent `page-size` expansion state remains per rendered bucket.
- Empty project-only or task-only results use the existing empty-state behavior.
- Card glyphs, styling, drilldown, recurrence, and read-only behavior do not
change.
## Data-access and performance rules
Filtering should occur as early as correctness permits:
```text
scan note metadata/body
|
+-- host note -> exclude
+-- ordinary note + notes:none -> exclude
+-- to-do rejected by todos -> exclude
|
v
parse/admit gtd block -> warnings -> tag lookup -> card -> bucket
```
- Do not request tags for an item rejected by `notes` or `todos`.
- Ordinary notes require bodies to prove explicit `gtd` opt-in when
`notes: all`.
- `todos: gtd-only` requires bodies to determine to-do admission.
- `todos: all` still needs bodies because an optional `gtd` block can override
the to-do card date, title, colours, icon, and text. Do not optimize this away.
- Retain current body fetching whenever either admitted type can use a `gtd`
block. Any no-body optimization must be proven not to alter card overrides,
warnings, scan counts, or host-note handling.
## Architecture
Add a note-specific inclusion type rather than reusing `InclusionMode`, because
`gtd-only` would be redundant: all ordinary notes are already explicitly
`gtd`-only.
```ts
type NoteInclusionMode = "all" | "none";
interface KanbanConfig {
notes: NoteInclusionMode;
// existing fields
}
interface MatrixConfig {
notes: NoteInclusionMode;
// existing fields
}
```
Both collectors should apply the type filter before malformed-block warnings,
tag requests, and card construction. Keep parsing and filtering behavior shared
in intent, but avoid an abstraction that obscures the different kanban and
matrix completion paths.
## Implementation plan
### Phase 1 — Configuration and types
- [x] Add `NoteInclusionMode = "all" | "none"`.
- [x] Add `notes` to `KanbanConfig` and `MatrixConfig`.
- [x] Recognize `notes` in both parsers.
- [x] Parse case-insensitive `all | none`, defaulting to `all`.
- [x] Warn on invalid, empty, null, array, or object values and use `all`.
- [x] Preserve the unknown-option warning for singular `note`.
- [x] Add parser tests for defaults, valid values, normalization, invalid values,
and coexistence with every `todos` mode.
### Phase 2 — Kanban filtering
- [x] Exclude ordinary notes immediately when `config.notes === "none"`.
- [x] Preserve explicit `gtd` opt-in when `config.notes === "all"`.
- [x] Ensure rejected notes trigger no malformed-block warning or tag request.
- [x] Preserve Backlog, In Progress, Done, done-tag precedence, done-window,
sorting, and native to-do behavior.
- [x] Cover project-only, task-only, combined, and fully empty configurations.
- [x] Cover empty, valid, and malformed `gtd` blocks.
### Phase 3 — Matrix filtering
- [x] Exclude ordinary notes immediately when `config.notes === "none"`.
- [x] Preserve explicit `gtd` opt-in when `config.notes === "all"`.
- [x] Ensure rejected notes trigger no malformed-block warning or tag request.
- [x] Preserve done-note exclusion and native completed-to-do exclusion.
- [x] Cover project-only, task-only, combined, and fully empty configurations in
both Skeleton and Eisenhower modes.
- [x] Cover empty, valid, and malformed `gtd` blocks.
### Phase 4 — Grouping, totals, and performance
- [x] Verify single-layout `cardCount` and all bucket totals after filtering.
- [x] Verify exact-owner notebook groups omit groups emptied by filtering.
- [x] Verify non-empty descendants survive filtered empty ancestors.
- [x] Verify filtered notes do not generate group-local warnings.
- [x] Verify each surviving bucket retains independent SLICE8 pagination.
- [x] Assert no tag request occurs for filtered notes.
- [x] Audit `getNotesInFolder` body-field hints without removing to-do `gtd`
overrides or malformed-block warnings.
### Phase 5 — Documentation
- [x] Add `notes: all | none` to README kanban and matrix option tables.
- [x] Document that `all` means all opted-in ordinary `gtd` notes.
- [x] Add project-only, task-only, and combined examples.
- [x] Document independence from `todos`, note completion behavior, grouped-view
effects, and the default-preserving migration story.
- [x] Update SPEC.md configuration, inclusion matrix, collector flow, statistics,
and performance notes.
- [x] Add an unreleased CHANGELOG entry.
### Phase 6 — Automated validation and packaging
- [x] Run focused parser, kanban, matrix, grouping, and field-hint tests
(117 passed).
- [x] Run the complete Jest suite (251 tests across 16 suites).
- [x] Run TypeScript validation and webview JavaScript syntax checking.
- [x] Run whitespace and prohibited-reference audits.
- [x] Build the production JPL.
- [x] Inspect archive contents; SHA-256:
final v1.0.0 artifact
`0b28fb0f5ffcb60d92e017fb0972ecaa456fcc3c24b144891dce7d72dc7d98ef`.
### Phase 7 — Manual Joplin acceptance
- [x] Existing blocks without `notes` still show opted-in project notes.
- [x] Kanban `notes: all` plus `todos: none` shows projects only across Backlog,
In Progress, and Done.
- [x] Kanban `notes: none` plus `todos: all` shows tasks only.
- [x] Kanban `notes: all` plus `todos: all` shows both without duplication.
- [x] Matrix project-only and task-only configurations work in Skeleton mode.
- [x] Matrix project-only and task-only configurations work in Eisenhower mode.
- [x] A plain note without `gtd` remains excluded under `notes: all`.
- [x] A `done` project appears in Kanban Done and remains excluded from matrices.
- [x] Invalid `notes` warns and falls back to `all`; singular `note` warns as
unknown.
- [x] Filtered malformed notes do not produce warnings.
- [x] Single and grouped views have correct headings, totals, empty states,
sorting, pagination, and navigation.
- [x] Record explicit user sign-off separately from automated checks.
## Out of scope
- Allowing ordinary notes without a `gtd` block into kanban or matrix views.
- Adding `gtd-only` as a distinct `notes` value.
- Renaming or changing the existing `todos` option.
- Inferring project/task identity from tags, titles, notebooks, or note content.
- Mutating note types, tags, or completion state from a rendered view.
- Changing calendar inclusion semantics.
- Changing Gantt item admission.
- Persisting filters or pagination state outside the fenced block.
## Acceptance criteria
- Existing kanban and matrix blocks behave identically when `notes` is omitted.
- `notes: all` includes only ordinary notes containing a `gtd` block.
- `notes: none` excludes ordinary notes without affecting native to-dos.
- All `notes` and `todos` combinations behave independently and predictably.
- Filtering happens before tag access, warning creation, bucketing, grouping,
totals, sorting, and pagination.
- SLICE8 batching, SLICE10 grouping, and SLICE11 completion semantics do not
regress.
- Documentation clearly supports project-only, task-only, and combined views.
- Automated validation, production packaging, and explicit manual acceptance
are completed and recorded separately.