savepoint 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/.claude/settings.local.json +5 -1
  2. package/.savepoint/Design.md +8 -4
  3. package/.savepoint/audit/E06-atari-noir-layout/proposals.md +130 -0
  4. package/.savepoint/audit/E06-atari-noir-layout/snapshot.md +84 -0
  5. package/.savepoint/config.yml +3 -3
  6. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/Design.md +24 -6
  7. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T007-detail-card-fixes.md +7 -7
  8. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T008-checkbox-states.md +10 -8
  9. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T009-router-priority-marker.md +16 -9
  10. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T010-auto-refresh-watcher.md +25 -22
  11. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/Design.md +10 -4
  12. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T001-border-resize-fix.md +2 -1
  13. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T002-rename-epic-design-files.md +38 -0
  14. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T003-rename-release-prd.md +28 -0
  15. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T004-update-instruction-files.md +50 -0
  16. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T005-update-cross-references.md +44 -0
  17. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T006-column-and-detail-scrolling.md +58 -0
  18. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T007-next-activity-header.md +55 -0
  19. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/Design.md +40 -0
  20. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T001-fix-makefile.md +34 -0
  21. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T002-linux-build-target.md +33 -0
  22. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T003-macos-build-target.md +32 -0
  23. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T004-smoke-tests-and-artifacts.md +38 -0
  24. package/.savepoint/router.md +1 -1
  25. package/.savepoint/visual-identity.md +4 -3
  26. package/AGENTS.md +3 -3
  27. package/README.md +1 -1
  28. package/go.mod +4 -1
  29. package/go.sum +2 -0
  30. package/internal/board/board.go +42 -6
  31. package/internal/board/board_test.go +53 -0
  32. package/internal/board/card.go +9 -3
  33. package/internal/board/card_test.go +28 -14
  34. package/internal/board/column.go +2 -2
  35. package/internal/board/column_test.go +17 -9
  36. package/internal/board/detail.go +21 -11
  37. package/internal/board/detail_test.go +30 -14
  38. package/internal/board/model.go +7 -1
  39. package/internal/board/update.go +24 -1
  40. package/internal/board/view.go +13 -3
  41. package/internal/board/view_test.go +2 -2
  42. package/internal/board/watch.go +82 -0
  43. package/internal/data/parser.go +31 -1
  44. package/internal/data/parser_test.go +8 -2
  45. package/internal/data/task.go +12 -2
  46. package/internal/styles/palette.go +6 -4
  47. package/internal/styles/styles.go +5 -15
  48. package/package.json +5 -4
  49. package/savepoint +0 -0
@@ -14,7 +14,11 @@
14
14
  "Bash(node --require ./scripts/vitest-preload.cjs ./node_modules/vitest/vitest.mjs run --configLoader runner --config vitest.config.js)",
15
15
  "Bash(go test *)",
16
16
  "Bash(go build *)",
17
- "Bash(go vet *)"
17
+ "Bash(go vet *)",
18
+ "Bash(make build *)",
19
+ "Bash(make test *)",
20
+ "Bash(go get *)",
21
+ "Bash(go doc *)"
18
22
  ]
19
23
  }
20
24
  }
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  type: project-design
3
3
  status: active
4
- last_audited: E02-data-readers (2026-05-01)
4
+ last_audited: E06-atari-noir-layout (2026-05-02)
5
5
  ---
6
6
 
7
7
  # Savepoint — System Architecture
@@ -23,7 +23,7 @@ last_audited: E02-data-readers (2026-05-01)
23
23
  - **Go data-reader boundary:** established in epic `E02-data-readers` (2026-05-01). `internal/data` owns Savepoint file parsing and discovery for the Go implementation: task frontmatter models, markdown YAML extraction, router state parsing, config theme defaults, release/epic/task directory listing, and boundary error sentinels.
24
24
  - **Template assets** live under `templates/` with helpers in `src/templates/` (epic E04).
25
25
  - **Init command** (`savepoint init`) validates, scaffolds, prints prompt, clipboard, optional install (epic E05).
26
- - **Board command** (`savepoint board`) reads project, non-TTY fallback, Ink TUI, transition gates, mtime writes, audit signaling (epic E06).
26
+ - **Board command** (`savepoint board`) reads project state, renders the Atari-Noir TUI board, supports release/epic filtering, detail overlays, task status transitions with mtime-guarded writes, router priority markers, and fsnotify-based task auto-refresh (epic E06).
27
27
  - **Audit pipeline** (`savepoint audit`) resolves epic, skips, quality gates, snapshots, router transition, proposal review (epic E07).
28
28
 
29
29
  ## 2. Directory layout
@@ -131,9 +131,13 @@ Acknowledged terminal limits: fonts, scanlines, glows, letter-spacing, mouse-dri
131
131
 
132
132
  **Render fallbacks:** 256-color → 16-color hard-coded → `NO_COLOR=1` monochrome with glyphs → non-TTY plain table.
133
133
 
134
- **Layout:** single screen with a 5-column Kanban board and detail pane. Non-TTY output uses `src/tui/render/plain-table.ts`.
134
+ **Layout:** single screen with a 3-column task board (`planned`, `in_progress`, `done`), optional epic sidebar on wide terminals, centered overlays for release/epic/help/task detail, static Atari-Noir header/footer, full-width dividers, uniform black TUI backgrounds, and navigation hints. Non-TTY output remains a plain table fallback.
135
135
 
136
- **Implementation modules:** see AGENTS.md Codebase Map (E06 and E07 epic rows).
136
+ **Visual guardrail:** the terminal board intentionally uses one black background for Background, Surface, and Surface 2. Do not restore subtly different dark panel fills; depth should come from spacing, dividers, glyphs, and focused Atari Orange borders.
137
+
138
+ **Board persistence and refresh:** task status transitions write canonical task frontmatter through `internal/data.WriteTaskStatus` with mtime conflict checks. The board watches `.savepoint/releases/` recursively with fsnotify and reloads task data after debounced file changes.
139
+
140
+ **Implementation modules:** see AGENTS.md Codebase Map.
137
141
 
138
142
  **Keybindings:** arrow/vim navigation, enter advances, backspace retreats, r/R refreshes, a/A exits toward audit review when proposals exist, q quits.
139
143
 
@@ -0,0 +1,130 @@
1
+ # E06 Atari-Noir Layout Audit Proposals
2
+
3
+ ## Target File
4
+
5
+ `.savepoint/Design.md`
6
+
7
+ ## Replace
8
+
9
+ ```md
10
+ - **Board command** (`savepoint board`) reads project, non-TTY fallback, Ink TUI, transition gates, mtime writes, audit signaling (epic E06).
11
+ ```
12
+
13
+ ## With
14
+
15
+ ```md
16
+ - **Board command** (`savepoint board`) reads project state, renders the Atari-Noir TUI board, supports release/epic filtering, detail overlays, task status transitions with mtime-guarded writes, router priority markers, and fsnotify-based task auto-refresh (epic E06).
17
+ ```
18
+
19
+ ## Target File
20
+
21
+ `.savepoint/Design.md`
22
+
23
+ ## Replace
24
+
25
+ ```md
26
+ **Layout:** single screen with a 5-column Kanban board and detail pane. Non-TTY output uses `src/tui/render/plain-table.ts`.
27
+
28
+ **Implementation modules:** see AGENTS.md Codebase Map (E06 and E07 epic rows).
29
+ ```
30
+
31
+ ## With
32
+
33
+ ```md
34
+ **Layout:** single screen with a 3-column task board (`planned`, `in_progress`, `done`), optional epic sidebar on wide terminals, centered overlays for release/epic/help/task detail, static Atari-Noir header/footer, and navigation hints. Non-TTY output remains a plain table fallback.
35
+
36
+ **Board persistence and refresh:** task status transitions write canonical task frontmatter through `internal/data.WriteTaskStatus` with mtime conflict checks. The board watches `.savepoint/releases/` recursively with fsnotify and reloads task data after debounced file changes.
37
+
38
+ **Implementation modules:** see AGENTS.md Codebase Map.
39
+ ```
40
+
41
+ ## Target File
42
+
43
+ `AGENTS.md`
44
+
45
+ ## Replace
46
+
47
+ ```md
48
+ | `internal/board/` | TUI board components, models, layouts, transitions, and rendering logic |
49
+ | `internal/data/` | Task data models, frontmatter parsing, project configuration, routing, and generic file readers |
50
+ | `internal/styles/` | Shared visual design system, TUI styling, and palettes |
51
+ ```
52
+
53
+ ## With
54
+
55
+ ```md
56
+ | `internal/board/` | TUI board models, layout, rendering, overlays, task transitions, router priority markers, and fsnotify refresh |
57
+ | `internal/data/` | Task/router/config models, frontmatter parsing, checklist state parsing, mtime-guarded writes, discovery, and generic file readers |
58
+ | `internal/styles/` | Atari-Noir palette constants, terminal color fallbacks, shared TUI styles, semantic glyph/tag styles, and footer/header styling |
59
+ ```
60
+
61
+ ## Target File
62
+
63
+ `.savepoint/releases/v1/epics/E06-atari-noir-layout/Design.md`
64
+
65
+ ## Replace
66
+
67
+ ```md
68
+ # Epic E07: Atari-Noir Layout Uplift
69
+ ```
70
+
71
+ ## With
72
+
73
+ ```md
74
+ # Epic E06: Atari-Noir Layout Uplift
75
+ ```
76
+
77
+ ## Target File
78
+
79
+ `.savepoint/releases/v1/epics/E06-atari-noir-layout/Design.md`
80
+
81
+ ## Insert After
82
+
83
+ ```md
84
+ | `internal/board/epic_panel.go` | Refine epic panel layout |
85
+ ```
86
+
87
+ ## With
88
+
89
+ ```md
90
+
91
+ ## Implemented As
92
+
93
+ - `internal/styles/palette.go` defines the Atari-Noir hex palette plus ANSI256/ANSI16 fallbacks.
94
+ - `internal/styles/styles.go` centralizes header, divider, footer, column, card, detail, glyph, and semantic tag styles.
95
+ - `internal/board/view.go` renders the static SavePoint header, the static `PLAN │ BUILD │ AUDIT` footer, subdued navigation hints, and overlay composition.
96
+ - `internal/board/card.go` wraps long task titles instead of truncating them and uses a green `▣` marker for the router-priority task.
97
+ - `internal/board/detail.go` adds spacing below Acceptance Criteria and Implementation Plan headings, renders checklist state with `☑`/`□`, and labels the router-priority task.
98
+ - `internal/data/task.go` and `internal/data/parser.go` represent Implementation Plan items as `CheckItem{Text, Done}` and parse `- [x]`, `- [ ]`, and legacy `- ` items.
99
+ - `internal/data/write.go` persists task status and phase changes with mtime conflict protection.
100
+ - `internal/board/watch.go` adds fsnotify-based recursive release directory watching, 100ms debounce, and reload messages used by `internal/board/update.go`.
101
+
102
+ ## Implementation Deltas
103
+
104
+ - The original visual-only scope expanded to include board usability fixes requested during E06: footer navigation hints, detail overlay spacing, card title word-wrap, checklist state rendering, router priority markers, and auto-refresh on task file changes.
105
+ - The current implementation still uses rounded frames/borders on header, board, columns, cards, and epic panel. That differs from the design language of "unnecessary borders removed" and should be reconciled before closing the visual uplift.
106
+ - `styles.Divider` exists but the main view does not render explicit full-width top/bottom divider lines; divider-like output currently comes from framed containers and component separators.
107
+ ```
108
+
109
+ ## Quality Review
110
+
111
+ ## Must Fix Before Close
112
+
113
+ - None remaining after approval closeout.
114
+
115
+ ## Carry Forward
116
+
117
+ - `internal/board/watch.go:17`: watcher errors are consumed silently. This is acceptable for v1 audit as non-blocking resilience, but a future task should surface watcher failures in `StatusMessage` or diagnostics.
118
+ - `internal/board/update.go:68` and `internal/board/update.go:84`: `ErrMtimeConflict` is intentionally non-destructive, but the user receives no visible conflict message because that error is ignored. Consider showing a manual-refresh message so conflicts are understandable.
119
+ - `go.mod`: `github.com/fsnotify/fsnotify` is currently listed as indirect even though project code imports it directly. `go mod tidy` may fix this metadata.
120
+ - Root instruction drift: `AGENTS.md` references `agent-skills/audit/SKILL.md`, but the repository contains `agent-skills/savepoint-audit/SKILL.md`.
121
+
122
+ ## Already Fixed
123
+
124
+ - `go build ./...`: PASS during audit.
125
+ - `go test ./...`: PASS during audit.
126
+ - Approval closeout added explicit full-width divider lines rendered through `styles.Divider`.
127
+ - Approval closeout removed unnecessary borders from unfocused header, board, column, card, and epic panel surfaces while preserving focused Atari Orange borders.
128
+ - T008 checklist parsing preserves checked/unchecked state in `data.CheckItem` and renders checked items distinctly.
129
+ - T009 router priority marker is wired through model, card, column, and detail rendering.
130
+ - T010 auto-refresh watcher is isolated in `internal/board/watch.go` and cleanly disabled in tests when `Model.Watcher` is nil.
@@ -0,0 +1,84 @@
1
+ ---
2
+ type: audit-snapshot
3
+ release: v1
4
+ epic: E06-atari-noir-layout
5
+ created: 2026-05-02
6
+ mode: manual
7
+ reason: "Audit CLI snapshot was unavailable; router authorized one manual snapshot from known epic scope."
8
+ ---
9
+
10
+ # E06 Atari-Noir Layout Snapshot
11
+
12
+ ## Router State
13
+
14
+ - `state`: `audit-pending`
15
+ - `release`: `v1`
16
+ - `epic`: `E06-atari-noir-layout`
17
+ - `task`: `E06-atari-noir-layout/T010-auto-refresh-watcher`
18
+ - `next_action`: All E06 tasks done. Start new agent session for epic audit.
19
+
20
+ ## Epic Scope
21
+
22
+ E06 implemented the Atari-Noir TUI layout uplift and related board usability fixes:
23
+
24
+ - Atari-Noir palette/style usage in `internal/styles/`.
25
+ - Header/footer rendering, navigation hints, and board layout adjustments in `internal/board/view.go`.
26
+ - Card title wrapping and detail overlay spacing/checklist rendering in `internal/board/card.go` and `internal/board/detail.go`.
27
+ - Router priority marker support across board model/card/detail rendering.
28
+ - Task checklist state parsing in `internal/data/parser.go` and `internal/data/task.go`.
29
+ - File watcher auto-refresh and task status disk persistence in `internal/board/watch.go`, `internal/board/board.go`, `internal/board/model.go`, and `internal/board/update.go`.
30
+
31
+ ## Task Files Reviewed
32
+
33
+ - `.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T001-color-system.md`
34
+ - `.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T002-header-and-dividers.md`
35
+ - `.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T003-footer-status-bar.md`
36
+ - `.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T004-component-refinement.md`
37
+ - `.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T005-restore-nav-hints.md`
38
+ - `.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T007-detail-card-fixes.md`
39
+ - `.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T008-checkbox-states.md`
40
+ - `.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T009-router-priority-marker.md`
41
+ - `.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T010-auto-refresh-watcher.md`
42
+
43
+ ## Changed Files In Epic Scope
44
+
45
+ - `go.mod`
46
+ - `go.sum`
47
+ - `internal/board/board.go`
48
+ - `internal/board/card.go`
49
+ - `internal/board/card_test.go`
50
+ - `internal/board/column.go`
51
+ - `internal/board/column_test.go`
52
+ - `internal/board/detail.go`
53
+ - `internal/board/detail_test.go`
54
+ - `internal/board/epic_panel.go`
55
+ - `internal/board/layout.go`
56
+ - `internal/board/model.go`
57
+ - `internal/board/update.go`
58
+ - `internal/board/view.go`
59
+ - `internal/board/view_test.go`
60
+ - `internal/board/watch.go`
61
+ - `internal/data/parser.go`
62
+ - `internal/data/parser_test.go`
63
+ - `internal/data/task.go`
64
+ - `internal/data/write.go`
65
+ - `internal/styles/palette.go`
66
+ - `internal/styles/styles.go`
67
+
68
+ ## Drift Notes Found
69
+
70
+ - `T002-header-and-dividers.md`: `internal/styles/palette.go` and `internal/styles/styles.go` were not yet reflected with sufficient specificity in the Codebase Map.
71
+
72
+ ## Verification
73
+
74
+ - `go build ./...`: PASS
75
+ - `go test ./...`: PASS
76
+ - Approval closeout rerun: `go build ./...` PASS, `go test ./...` PASS.
77
+ - `make build` and `make test`: not run; `make` is not installed on PATH in this environment.
78
+
79
+ ## Audit Observations
80
+
81
+ - `agent-skills/audit/SKILL.md` is referenced by the root instructions but does not exist; `agent-skills/savepoint-audit/SKILL.md` was used as the equivalent audit skill.
82
+ - The epic Design title says `Epic E07`; the folder, router, and task IDs identify this epic as `E06-atari-noir-layout`.
83
+ - The implementation added scoped behavior beyond the original visual uplift: footer navigation hints, detail overlay spacing, card word-wrap, checklist state parsing/rendering, router priority markers, and fsnotify auto-refresh.
84
+ - Visual ACs around explicit full-width dividers and border reduction are not fully represented in `internal/board/view.go` and `internal/styles/styles.go`; see proposals quality review.
@@ -13,9 +13,9 @@ audit:
13
13
  divergence_threshold: 0.5 # warn if a proposal changes >50% of a live file
14
14
 
15
15
  theme:
16
- bg: "#121212"
17
- surface: "#0D0D0D"
18
- surface_2: "#0F0F0F"
16
+ bg: "#000000"
17
+ surface: "#000000"
18
+ surface_2: "#000000"
19
19
  border: "#1A1A1A"
20
20
  text: "#F0E6DA"
21
21
  accents:
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  type: epic-design
3
- status: planned
4
- ---
5
-
6
- # Epic E07: Atari-Noir Layout Uplift
3
+ status: audited
4
+ ---
5
+
6
+ # Epic E06: Atari-Noir Layout Uplift
7
7
 
8
8
  ## Purpose
9
9
 
@@ -38,5 +38,23 @@ Update the existing TUI to align with the **Atari-Noir SavePoint design system**
38
38
  | `internal/board/view.go` | Implement header, footer, dividers |
39
39
  | `internal/board/layout.go` | Adjust layout height calculations |
40
40
  | `internal/board/column.go` | Refine column styling and spacing |
41
- | `internal/board/card.go` | Refine card surface and focus state |
42
- | `internal/board/epic_panel.go` | Refine epic panel layout |
41
+ | `internal/board/card.go` | Refine card surface and focus state |
42
+ | `internal/board/epic_panel.go` | Refine epic panel layout |
43
+
44
+ ## Implemented As
45
+
46
+ - `internal/styles/palette.go` defines the Atari-Noir hex palette plus ANSI256/ANSI16 fallbacks.
47
+ - `internal/styles/styles.go` centralizes header, divider, footer, column, card, detail, glyph, and semantic tag styles.
48
+ - `internal/board/view.go` renders the static SavePoint header, explicit full-width top/bottom dividers, the static `PLAN │ BUILD │ AUDIT` footer, subdued navigation hints, and overlay composition.
49
+ - `internal/board/card.go` wraps long task titles instead of truncating them and uses a green `▣` marker for the router-priority task.
50
+ - `internal/board/detail.go` adds spacing below Acceptance Criteria and Implementation Plan headings, renders checklist state with `☑`/`□`, and labels the router-priority task.
51
+ - `internal/data/task.go` and `internal/data/parser.go` represent Implementation Plan items as `CheckItem{Text, Done}` and parse `- [x]`, `- [ ]`, and legacy `- ` items.
52
+ - `internal/data/write.go` persists task status and phase changes with mtime conflict protection.
53
+ - `internal/board/watch.go` adds fsnotify-based recursive release directory watching, 100ms debounce, and reload messages used by `internal/board/update.go`.
54
+
55
+ ## Implementation Deltas
56
+
57
+ - The original visual-only scope expanded to include board usability fixes requested during E06: footer navigation hints, detail overlay spacing, card title word-wrap, checklist state rendering, router priority markers, and auto-refresh on task file changes.
58
+ - Audit closeout removed unnecessary borders from unfocused header, board, column, card, and epic-panel surfaces while preserving Atari Orange borders for focused cards/columns and detail overlays.
59
+ - User-approved visual guardrail: Background, Surface, and Surface 2 are intentionally the same black value in the terminal TUI. Do not reintroduce subtly different background fills for panels/cards.
60
+ - The main view now renders explicit full-width divider lines with `styles.Divider` rather than relying on component frames as separators.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: E06-atari-noir-layout/T007-detail-card-fixes
3
- status: planned
3
+ status: done
4
4
  objective: "Add line breaks under Acceptance Criteria and Implementation Plan headings in task detail, and word-wrap card titles instead of truncating"
5
5
  depends_on: []
6
6
  ---
@@ -18,11 +18,11 @@ depends_on: []
18
18
 
19
19
  ## Implementation Plan
20
20
 
21
- - [ ] Edit `internal/board/detail.go` — add `""` entry after the `Acceptance Criteria:` heading line and after the `Implementation Plan:` heading line.
22
- - [ ] Edit `internal/board/detail.go` — make `wrapText` and `splitLongWord` exported (capitalize) so they can be reused from `card.go`.
23
- - [ ] Edit `internal/board/card.go` — replace `truncate(t.Title, inner)` with a multi-line approach that word-wraps the title across available width.
24
- - [ ] Edit `internal/board/card.go` — combine wrapped title lines with newlines in the card content (joining with `\n`).
25
- - [ ] Run `make build && make test` to verify no regressions.
21
+ - [x] Edit `internal/board/detail.go` — add `""` entry after the `Acceptance Criteria:` heading line and after the `Implementation Plan:` heading line.
22
+ - [x] Edit `internal/board/detail.go` — make `wrapText` and `splitLongWord` exported (capitalize) so they can be reused from `card.go`.
23
+ - [x] Edit `internal/board/card.go` — replace `truncate(t.Title, inner)` with a multi-line approach that word-wraps the title across available width.
24
+ - [x] Edit `internal/board/card.go` — combine wrapped title lines with newlines in the card content (joining with `\n`).
25
+ - [x] Run `make build && make test` to verify no regressions.
26
26
 
27
27
  ## Context Log
28
28
 
@@ -33,4 +33,4 @@ Files read:
33
33
 
34
34
  Estimated input tokens: 600
35
35
 
36
- Notes:
36
+ Notes: Exported WrapText/SplitLongWord from detail.go; updated card_test.go TestRenderCard_titleTruncated → TestRenderCard_titleWraps. Build and tests pass.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: E06-atari-noir-layout/T008-checkbox-states
3
- status: planned
3
+ status: done
4
4
  objective: "Parse and render checked/unchecked state for Implementation Plan checklist items"
5
5
  depends_on: []
6
6
  ---
@@ -19,11 +19,11 @@ depends_on: []
19
19
 
20
20
  ## Implementation Plan
21
21
 
22
- - [ ] Edit `internal/data/task.go` — add `CheckItem` struct with `Text string` and `Done bool` fields; change `Checklist []string` to `Checklist []CheckItem`.
23
- - [ ] Edit `internal/data/parser.go` — update `extractChecklistSection()` to detect `- [x] ` vs `- [ ] ` vs `- ` prefixes and set `Done` accordingly; strip prefix from `Text`.
24
- - [ ] Update all usages of `Checklist` across the codebase (likely only `board/detail.go` and tests).
25
- - [ ] Edit `internal/board/detail.go` — in the Implementation Plan section, render done items with `☑ ` + green `TagDone` styling and undone items with `□ ` + dim `CardMeta` styling.
26
- - [ ] Run `make build && make test` to verify no regressions.
22
+ - [x] Edit `internal/data/task.go` — add `CheckItem` struct with `Text string` and `Done bool` fields; change `Checklist []string` to `Checklist []CheckItem`.
23
+ - [x] Edit `internal/data/parser.go` — update `extractChecklistSection()` to detect `- [x] ` vs `- [ ] ` vs `- ` prefixes and set `Done` accordingly; strip prefix from `Text`.
24
+ - [x] Update all usages of `Checklist` across the codebase (likely only `board/detail.go` and tests).
25
+ - [x] Edit `internal/board/detail.go` — in the Implementation Plan section, render done items with `☑ ` + green `TagDone` styling and undone items with `□ ` + dim `CardMeta` styling.
26
+ - [x] Run `make build && make test` to verify no regressions.
27
27
 
28
28
  ## Context Log
29
29
 
@@ -32,7 +32,9 @@ Files read:
32
32
  - `internal/data/parser.go`
33
33
  - `internal/board/detail.go`
34
34
  - `internal/styles/styles.go`
35
+ - `internal/data/parser_test.go`
36
+ - `internal/board/detail_test.go`
35
37
 
36
- Estimated input tokens: 800
38
+ Estimated input tokens: 1200
37
39
 
38
- Notes:
40
+ Notes: Added `extractChecklistItems` alongside existing `extractChecklistSection` (kept for `[]string` Acceptance path). Build and all tests pass.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: E06-atari-noir-layout/T009-router-priority-marker
3
- status: planned
3
+ status: done
4
4
  objective: "Highlight the router priority task with a green marker on the card and optional text highlight"
5
5
  depends_on: []
6
6
  ---
@@ -12,18 +12,19 @@ depends_on: []
12
12
  - The model reads `RouterState.Task` (the `task:` field from `router.md`) and stores it as `Model.RouterTask`
13
13
  - In the board view, the task card whose ID matches `RouterTask` shows a green `▣` glyph (using `TagDone`/green style) instead of the normal phase-colored glyph
14
14
  - Non-priority tasks keep their existing phase-colored glyphs unchanged
15
+ - Board always default view to current state release and epic
15
16
  - The task detail overlay shows a `"(router priority)"` label or marker when the displayed task matches `RouterTask`
16
17
  - All existing keyboard interactions, column rendering, and card behavior remain intact
17
18
 
18
19
  ## Implementation Plan
19
20
 
20
- - [ ] Edit `internal/board/model.go` — add `RouterTask string` field to `Model`.
21
- - [ ] Edit `internal/board/board.go` — in `newProjectModel()`, read `routerState.Task` into `model.RouterTask`.
22
- - [ ] Edit `internal/board/card.go` — update `RenderCard` to accept a `routerTaskID string` parameter; when `t.ID == routerTaskID`, replace the phase glyph with a green `▣` using `TagDone` style.
23
- - [ ] Edit `internal/board/card.go` — update `RenderCard` signature and callsites (`column.go`, `view.go`).
24
- - [ ] Edit `internal/board/detail.go` — update `RenderDetail` to accept a `routerTaskID string`; when matching, append a `"(router priority)"` green label line.
25
- - [ ] Update all callsites of `RenderCard` and `RenderDetail` to pass `m.RouterTask`.
26
- - [ ] Run `make build && make test` to verify no regressions.
21
+ - [x] Edit `internal/board/model.go` — add `RouterTask string` field to `Model`.
22
+ - [x] Edit `internal/board/board.go` — in `newProjectModel()`, read `routerState.Task` into `model.RouterTask`.
23
+ - [x] Edit `internal/board/card.go` — update `RenderCard` to accept a `routerTaskID string` parameter; when `t.ID == routerTaskID`, replace the phase glyph with a green `▣` using `TagDone` style.
24
+ - [x] Edit `internal/board/card.go` — update `RenderCard` signature and callsites (`column.go`, `view.go`).
25
+ - [x] Edit `internal/board/detail.go` — update `RenderDetail` to accept a `routerTaskID string`; when matching, append a `"(router priority)"` green label line.
26
+ - [x] Update all callsites of `RenderCard` and `RenderDetail` to pass `m.RouterTask`.
27
+ - [x] Run `make build && make test` to verify no regressions.
27
28
 
28
29
  ## Context Log
29
30
 
@@ -35,7 +36,13 @@ Files read:
35
36
  - `internal/board/detail.go`
36
37
  - `internal/data/router.go`
37
38
  - `internal/board/view.go`
39
+ - `internal/board/card_test.go`
40
+ - `internal/board/detail_test.go`
41
+ - `internal/board/column_test.go`
38
42
 
39
- Estimated input tokens: 1000
43
+ Estimated input tokens: 1800
40
44
 
41
45
  Notes:
46
+ - `go build && go test ./...` — PASS (all board tests green)
47
+ - `RenderColumn` signature extended with `routerTaskID string`; all 7 test callsites updated
48
+ - New tests: `TestRenderCard_routerPriorityUsesGreenGlyph`, `TestRenderDetail_routerPriorityLabel`, `TestRenderDetail_noRouterPriorityLabelWhenNoMatch`
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: E06-atari-noir-layout/T010-auto-refresh-watcher
3
- status: planned
3
+ status: done
4
4
  objective: "Auto-refresh the board when task files change on disk via fsnotify file watcher"
5
5
  depends_on: []
6
6
  ---
@@ -19,26 +19,26 @@ depends_on: []
19
19
 
20
20
  ## Implementation Plan
21
21
 
22
- - [ ] Add `github.com/fsnotify/fsnotify` to `go.mod`
23
- - [ ] Create `internal/board/watch.go`:
22
+ - [x] Add `github.com/fsnotify/fsnotify` to `go.mod`
23
+ - [x] Create `internal/board/watch.go`:
24
24
  - Define `fileChangeMsg struct{}` and `reloadMsg struct{ tasks []data.Task }`
25
25
  - `watchFiles(w *fsnotify.Watcher) tea.Cmd` — blocks on watcher.Events, drains channel for 100ms, emits single `fileChangeMsg`
26
26
  - `reloadTasks(root string) tea.Cmd` — calls `loadAllTasks(root)` and emits `reloadMsg{tasks}`
27
27
  - `loadAllTasks(root string) ([]data.Task, error)` — extracted from `board.go`, reuses `Discover` + `Parser`
28
- - [ ] Edit `internal/board/model.go`:
29
- - Add `watcher *fsnotify.Watcher` field to `Model`
30
- - `Init()` — create watcher, `watcher.AddRecursive(root)` on `.savepoint/releases/`, return `watchFiles(watcher)`
31
- - Close watcher in `Init()` if root is empty (test mode)
32
- - [ ] Edit `internal/board/board.go`:
28
+ - [x] Edit `internal/board/model.go`:
29
+ - Add `Watcher *fsnotify.Watcher` field to `Model`
30
+ - `Init()` — returns `watchFiles(m.Watcher)` if watcher non-nil, else nil
31
+ - [x] Edit `internal/board/board.go`:
33
32
  - Extract task-discovery loop from `newProjectModel` into `loadAllTasks(root string) ([]data.Task, error)`
34
- - `newProjectModel` calls `loadAllTasks` instead of inline logic
35
- - [ ] Edit `internal/board/update.go`:
33
+ - `newProjectModel` calls `loadAllTasks` + `newWatcher`, sets `model.Watcher`
34
+ - `loadEpicTasks` now sets `task.Path` and `task.Mtime` from stat
35
+ - [x] Edit `internal/board/update.go`:
36
36
  - Handle `fileChangeMsg` → return `reloadTasks(m.Root)` cmd
37
- - Handle `reloadMsg` → swap `m.AllTasks = msg.tasks`, call `m.refreshTasks()`, return `watchFiles(m.watcher)` to re-subscribe
38
- - On quit (`q`/`ctrl+c`), close `m.watcher` before `tea.Quit`
39
- - [ ] Edit `internal/board/transitions.go`:
40
- - In `Advance` / `Retreat`, call `data.WriteTaskStatus(taskPath, task, expectedMtime)` to persist to disk so the watcher picks it up
41
- - [ ] Run `go build ./...` and `go test ./...` to verify no regressions
37
+ - Handle `reloadMsg` → swap `m.AllTasks = msg.tasks`, call `m.refreshTasks()`, return `watchFiles(m.Watcher)` to re-subscribe
38
+ - On quit (`q`/`ctrl+c`), close `m.Watcher` before `tea.Quit`
39
+ - `space`/`backspace` now call `data.WriteTaskStatus` to persist to disk
40
+ - [x] `internal/data/task.go`: added `Path string` and `Mtime time.Time` (yaml:"-") to Task
41
+ - [x] Run `go build ./...` and `go test ./...` to verify no regressions
42
42
 
43
43
  ## Context Log
44
44
 
@@ -47,15 +47,18 @@ Files read:
47
47
  - `internal/board/board.go`
48
48
  - `internal/board/update.go`
49
49
  - `internal/board/transitions.go`
50
- - `internal/board/watch.go` (does not exist yet)
50
+ - `internal/board/watch.go` (created)
51
51
  - `internal/data/write.go`
52
+ - `internal/data/task.go`
53
+ - `internal/data/parser.go`
52
54
  - `.savepoint/AGENTS.md`
53
- - `.savepoint/releases/v1/epics/E06-atari-noir-layout/Design.md`
54
- - `.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T009-router-priority-marker.md`
55
55
 
56
- Estimated input tokens: 1800
56
+ Estimated input tokens: 2200
57
+
58
+ Quality gates: `go build ./...` PASS, `go test ./...` PASS (board: 0.317s, data: 0.343s)
57
59
 
58
60
  Notes:
59
- - The watcher watches `.savepoint/releases/` recursively. `fsnotify` v1.7+ supports `AddWith(path, fsnotify.Recursive)` on macOS/Windows; on Linux, fall back to walking and adding each subdirectory.
60
- - The 100ms debounce in `watchFiles` collapses rapid write sequences (e.g. editor save + lsp format) into a single reload.
61
- - `WriteTaskStatus` needs the task file path. Task struct may need a `Path` field populated at load time to make persistence possible.
61
+ - fsnotify v1.10.0 has no recursive AddWith option; used `filepath.WalkDir` + `w.Add` per subdir instead.
62
+ - `data.Task` gained `Path` and `Mtime` (yaml:"-") fields populated in `loadEpicTasks`.
63
+ - Advance/Retreat disk writes live in `update.go`, not `transitions.go` (keeps transitions pure).
64
+ - Watcher created in `newProjectModel`; Init() subscribes if non-nil; nil watcher = test-safe.
@@ -14,13 +14,19 @@ Performance, layout robustness, and structural improvements for the board TUI. F
14
14
  - Right-border clipping is eliminated at all terminal widths ≥ 40
15
15
  - Resize handling is robust — no corruption, no artifacts when growing/shrinking
16
16
  - The board auto-refreshes when task files change on disk via fsnotify
17
+ - Board columns use virtual viewport scrolling — 4-5 cards visible with `↑/↓` indicators
18
+ - Detail overlay is height-capped (~70%) with scroll indicators for overflow content
19
+ - All scroll indicators use dim/subtle styling consistent with Atari Noir aesthetic
17
20
 
18
21
  ## Components and files
19
22
 
20
23
  | Path | Purpose |
21
24
  |------|---------|
22
- | `internal/board/layout.go` | Layout arithmetic and resize guards |
23
- | `internal/board/view.go` | Minimum width clamping |
25
+ | `internal/board/layout.go` | Layout arithmetic and resize guards, height-aware ContentHeight |
26
+ | `internal/board/view.go` | Minimum width clamping, height passthrough to renderers |
24
27
  | `internal/board/watch.go` | File watcher and reload commands |
25
- | `internal/board/model.go` | Watcher lifecycle |
26
- | `internal/board/update.go` | Reload message handling |
28
+ | `internal/board/model.go` | Watcher lifecycle, ColumnOffsets, DetailOffset state |
29
+ | `internal/board/update.go` | Reload message handling, auto-scroll offsets, PageUp/PageDown |
30
+ | `internal/board/column.go` | Virtual viewport slicing, scroll indicator rendering |
31
+ | `internal/board/detail.go` | Height-capped overlay, detail scroll indicators |
32
+ | `internal/styles/styles.go` | ScrollIndicator style (dim/subtle) |
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  id: E01-tui-optimisation/T001-border-resize-fix
3
- status: planned
3
+ status: in_progress
4
+ phase: build
4
5
  objective: "Fix right-border clipping and ensure clean rendering on terminal resize"
5
6
  depends_on: []
6
7
  ---
@@ -0,0 +1,38 @@
1
+ ---
2
+ id: E01-tui-optimisation/T002-rename-epic-design-files
3
+ status: planned
4
+ objective: "Rename all epic Design.md files to E##-Detail.md convention"
5
+ depends_on: []
6
+ ---
7
+
8
+ # T002: Rename Epic Design Files
9
+
10
+ ## Acceptance Criteria
11
+
12
+ - All 8 active epic `Design.md` files renamed to `E##-Detail.md` pattern
13
+ - Archived epics under `_archived/` left unchanged
14
+ - Root `.savepoint/Design.md` left unchanged
15
+ - No content changes in renamed files
16
+ - All renamed files remain valid markdown with intact frontmatter
17
+
18
+ ## Implementation Plan
19
+
20
+ - [ ] Rename `.savepoint/releases/v1/epics/E01-scaffolding/Design.md` → `E01-Detail.md`
21
+ - [ ] Rename `.savepoint/releases/v1/epics/E02-architecture/Design.md` → `E02-Detail.md`
22
+ - [ ] Rename `.savepoint/releases/v1/epics/E03-board-tui-core/Design.md` → `E03-Detail.md`
23
+ - [ ] Rename `.savepoint/releases/v1/epics/E04-board-components/Design.md` → `E04-Detail.md`
24
+ - [ ] Rename `.savepoint/releases/v1/epics/E05-phase-transitions/Design.md` → `E05-Detail.md`
25
+ - [ ] Rename `.savepoint/releases/v1/epics/E06-atari-noir-layout/Design.md` → `E06-Detail.md`
26
+ - [ ] Rename `.savepoint/releases/v1.1/epics/E01-tui-optimisation/Design.md` → `E01-Detail.md`
27
+ - [ ] Rename `.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/Design.md` → `E02-Detail.md`
28
+
29
+ ## Context Log
30
+
31
+ Files read:
32
+ - None (file renames only)
33
+
34
+ Estimated input tokens: 300
35
+
36
+ Notes:
37
+ - Content is not modified, only file paths change
38
+ - Archived epics explicitly excluded per user request
@@ -0,0 +1,28 @@
1
+ ---
2
+ id: E01-tui-optimisation/T003-rename-release-prd
3
+ status: planned
4
+ objective: "Rename release PRD.md to version-anchored convention"
5
+ depends_on: []
6
+ ---
7
+
8
+ # T003: Rename Release PRD
9
+
10
+ ## Acceptance Criteria
11
+
12
+ - `.savepoint/releases/v1/PRD.md` renamed to `.savepoint/releases/v1/v1-PRD.md`
13
+ - No content changes
14
+ - Root `.savepoint/PRD.md` left unchanged
15
+
16
+ ## Implementation Plan
17
+
18
+ - [ ] Rename `.savepoint/releases/v1/PRD.md` → `v1-PRD.md`
19
+
20
+ ## Context Log
21
+
22
+ Files read:
23
+ - None (file rename only)
24
+
25
+ Estimated input tokens: 100
26
+
27
+ Notes:
28
+ - Single file rename