savepoint 1.0.1 → 1.0.2
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.
- package/.claude/settings.local.json +4 -1
- package/.savepoint/Design.md +22 -17
- package/.savepoint/audit/v1/E01/proposals.md +168 -0
- package/.savepoint/audit/v1/E01/snapshot.md +78 -0
- package/.savepoint/audit/{E01-go-setup → v1/E01-go-setup}/proposals.md +7 -7
- package/.savepoint/audit/{E01-go-setup → v1/E01-go-setup}/snapshot.md +2 -2
- package/.savepoint/audit/{E01-scaffolding → v1/E01-scaffolding}/proposals/AGENTS.md +5 -5
- package/.savepoint/audit/{E02-data-readers → v1/E02-data-readers}/proposals.md +20 -20
- package/.savepoint/audit/{E02-data-readers → v1/E02-data-readers}/snapshot.md +1 -1
- package/.savepoint/audit/{E03-board-tui-core → v1/E03-board-tui-core}/proposals.md +11 -11
- package/.savepoint/audit/{E03-board-tui-core → v1/E03-board-tui-core}/snapshot.md +1 -1
- package/.savepoint/audit/{E04-board-components → v1/E04-board-components}/proposals.md +14 -14
- package/.savepoint/audit/{E04-board-components → v1/E04-board-components}/snapshot.md +1 -1
- package/.savepoint/audit/{E05-init-command → v1/E05-init-command}/snapshot.md +1 -1
- package/.savepoint/audit/{E05-phase-transitions → v1/E05-phase-transitions}/proposals.md +4 -4
- package/.savepoint/audit/{E05-phase-transitions → v1/E05-phase-transitions}/snapshot.md +1 -1
- package/.savepoint/audit/{E06-atari-noir-layout → v1/E06-atari-noir-layout}/proposals.md +2 -2
- package/.savepoint/audit/{E07-audit-pipeline → v1/E07-audit-pipeline}/snapshot.md +6 -6
- package/.savepoint/audit/v1.1/E02-cross-platform-compatibility/proposals.md +114 -0
- package/.savepoint/audit/v1.1/E02-cross-platform-compatibility/snapshot.md +41 -0
- package/.savepoint/audit/v1.1/E04-epic-navigation/proposals.md +156 -0
- package/.savepoint/audit/v1.1/E04-epic-navigation/snapshot.md +48 -0
- package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T001-init-module.md +1 -1
- package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T005-layout.md +1 -1
- package/.savepoint/releases/v1/epics/E04-board-components/tasks/T002-card.md +1 -1
- package/.savepoint/releases/v1/epics/E04-board-components/tasks/T006-help-overlay.md +1 -1
- package/.savepoint/releases/v1/epics/E06-atari-noir-layout/{Design.md → E06-Detail.md} +5 -3
- package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T002-header-and-dividers.md +1 -1
- package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T003-footer-status-bar.md +1 -1
- package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T004-component-refinement.md +1 -1
- package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T010-auto-refresh-watcher.md +2 -0
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/{Design.md → E01-Detail.md} +9 -1
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/{T007-next-activity-header.md → T001-next-activity-header.md} +13 -12
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T002-rename-epic-design-files.md +9 -9
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T003-rename-release-prd.md +2 -2
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T004-update-instruction-files.md +13 -12
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T005-update-cross-references.md +14 -13
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T006-column-and-detail-scrolling.md +25 -15
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T007-column-focus-border-stability.md +57 -0
- package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/{Design.md → E02-Detail.md} +12 -3
- package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T001-fix-makefile.md +11 -8
- package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T002-linux-build-target.md +12 -7
- package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T003-macos-build-target.md +9 -5
- package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T004-smoke-tests-and-artifacts.md +30 -9
- package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/E03-Detail.md +32 -0
- package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T001-border-resize-fix.md +40 -0
- package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T002-next-activity-below-header.md +64 -0
- package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T003-checkbox-rendering-fix.md +56 -0
- package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T005-unify-status-glyphs.md +65 -0
- package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T006-forced-256-color-profile.md +36 -0
- package/.savepoint/releases/v1.1/epics/E04-epic-navigation/E04-Detail.md +51 -0
- package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T001-sidebar-focusable-navigation.md +65 -0
- package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T002-epic-detail-overlay.md +73 -0
- package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T003-epic-status-glyphs.md +73 -0
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/E05-Detail.md +45 -0
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T001-update-agents-md.md +34 -0
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T002-update-router-md.md +30 -0
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T003-update-design-md.md +33 -0
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T004-implement-m-hotkey.md +88 -0
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T005-update-help-overlay.md +30 -0
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T006-tests-and-quality-gates.md +46 -0
- package/.savepoint/releases/v1.1/v1.1-PRD.md +79 -0
- package/.savepoint/router.md +33 -105
- package/AGENTS.md +56 -113
- package/Makefile +19 -3
- package/README.md +6 -5
- package/agent-skills/savepoint-audit/SKILL.md +6 -6
- package/agent-skills/savepoint-build-task/SKILL.md +2 -2
- package/agent-skills/savepoint-create-plan/SKILL.md +3 -3
- package/agent-skills/savepoint-create-task/SKILL.md +2 -2
- package/agent-skills/savepoint-draft-prd/SKILL.md +1 -1
- package/agent-skills/savepoint-system-design/SKILL.md +1 -1
- package/internal/board/board.go +43 -27
- package/internal/board/board_test.go +71 -0
- package/internal/board/card.go +34 -3
- package/internal/board/card_test.go +105 -12
- package/internal/board/column.go +40 -5
- package/internal/board/column_test.go +60 -13
- package/internal/board/detail.go +107 -25
- package/internal/board/detail_test.go +117 -26
- package/internal/board/epic_panel.go +105 -8
- package/internal/board/epic_panel_test.go +343 -5
- package/internal/board/layout.go +12 -2
- package/internal/board/layout_test.go +17 -0
- package/internal/board/model.go +141 -24
- package/internal/board/render_policy_test.go +77 -0
- package/internal/board/status.go +23 -0
- package/internal/board/update.go +276 -8
- package/internal/board/update_test.go +166 -0
- package/internal/board/view.go +131 -17
- package/internal/board/view_test.go +159 -1
- package/internal/board/watch.go +24 -6
- package/internal/buildtool/main.go +219 -0
- package/internal/data/parser.go +8 -0
- package/internal/data/parser_test.go +35 -0
- package/internal/data/task.go +10 -0
- package/internal/styles/palette.go +3 -3
- package/internal/styles/styles.go +39 -12
- package/main.go +9 -0
- package/package.json +1 -1
- package/savepoint +0 -0
- package/savepoint.exe +0 -0
- package/templates/project/.savepoint/router.md +6 -5
- package/templates/project/AGENTS.md +47 -101
- package/templates/prompts/audit-reconciliation.prompt.md +6 -6
- package/templates/prompts/epic-design.prompt.md +3 -3
- package/templates/prompts/task-breakdown.prompt.md +1 -1
- package/templates/prompts/task-building.prompt.md +1 -1
- package/templates/prompts/task-planning.prompt.md +1 -1
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T001-border-resize-fix.md +0 -36
- package/main.exe +0 -0
- /package/.savepoint/audit/{E01-scaffolding → v1/E01-scaffolding}/proposals/Design.md +0 -0
- /package/.savepoint/audit/{E01-scaffolding → v1/E01-scaffolding}/proposals/epic-Design.md +0 -0
- /package/.savepoint/audit/{E01-scaffolding → v1/E01-scaffolding}/proposals/quality-review.md +0 -0
- /package/.savepoint/audit/{E01-scaffolding → v1/E01-scaffolding}/snapshot.md +0 -0
- /package/.savepoint/audit/{E02-data-model → v1/E02-data-model}/snapshot.md +0 -0
- /package/.savepoint/audit/{E03-cli-foundation → v1/E03-cli-foundation}/snapshot.md +0 -0
- /package/.savepoint/audit/{E04-templates-and-prompts → v1/E04-templates-and-prompts}/snapshot.md +0 -0
- /package/.savepoint/audit/{E06-atari-noir-layout → v1/E06-atari-noir-layout}/snapshot.md +0 -0
- /package/.savepoint/audit/{E06-tui-board → v1/E06-tui-board}/snapshot.md +0 -0
- /package/.savepoint/audit/{E08-board-workflow-cleanup → v1/E08-board-workflow-cleanup}/snapshot.md +0 -0
- /package/.savepoint/releases/v1/epics/E01-go-setup/{Design.md → E01-Detail.md} +0 -0
- /package/.savepoint/releases/v1/epics/E02-data-readers/{Design.md → E02-Detail.md} +0 -0
- /package/.savepoint/releases/v1/epics/E03-board-tui-core/{Design.md → E03-Detail.md} +0 -0
- /package/.savepoint/releases/v1/epics/E04-board-components/{Design.md → E04-Detail.md} +0 -0
- /package/.savepoint/releases/v1/epics/E05-phase-transitions/{Design.md → E05-Detail.md} +0 -0
- /package/.savepoint/releases/v1/{PRD.md → v1-PRD.md} +0 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E03-ui-visual-refinement/T002-next-activity-below-header
|
|
3
|
+
status: done
|
|
4
|
+
objective: "Reposition Next Activity below header as a dedicated line with phase-aligned styling"
|
|
5
|
+
depends_on:
|
|
6
|
+
- E03-ui-visual-refinement/T001-border-resize-fix
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# T002: Reposition Next Activity Below Header with Phase-Aligned Styling
|
|
10
|
+
|
|
11
|
+
## Acceptance Criteria
|
|
12
|
+
|
|
13
|
+
- Next Activity renders as a dedicated full-width line immediately below the header bar
|
|
14
|
+
- The line is hidden (not rendered) when no activity is active or router state is idle
|
|
15
|
+
- The line uses `phase:` prefix mapped to existing footer phase styles:
|
|
16
|
+
- `task-building` → FooterPhaseBuild (orange + bold)
|
|
17
|
+
- `audit-pending` → FooterPhaseAudit (green + bold)
|
|
18
|
+
- `pre-implementation` / `epic-design` / `epic-task-breakdown` → FooterPhasePlan (purple + bold)
|
|
19
|
+
- Format: `"PLAN: Build T010 (E06) v1"` — phase prefix in styled tag, activity text follows
|
|
20
|
+
- Activity text is the `next_action` value from router state (already populated)
|
|
21
|
+
- At narrow widths (< 60 chars), the line truncates gracefully: `"PLAN: Build T0…"`
|
|
22
|
+
- Existing header layout is preserved — nothing shifts or wraps incorrectly
|
|
23
|
+
|
|
24
|
+
## Implementation Plan
|
|
25
|
+
|
|
26
|
+
- [x] Read `internal/board/view.go` — locate current header rendering and any existing Next Activity right-aligned logic
|
|
27
|
+
- [x] Read `internal/styles/styles.go` — verify FooterPhaseBuild/FooterPhaseAudit/FooterPhasePlan are available for reuse, or add them if missing
|
|
28
|
+
- [x] Read `internal/data/router.go` — confirm RouterState model exposes `state` and `next_action` fields
|
|
29
|
+
- [x] Edit `internal/board/view.go` — add `renderNextActivityLine(state)` that returns a styled string using phase-mapped style
|
|
30
|
+
- [x] Edit `internal/board/view.go` — insert the rendered line immediately after header output in the `View()` function
|
|
31
|
+
- [x] Edit `internal/board/layout.go` — adjust vertical layout height calculation to account for the new line
|
|
32
|
+
- [x] Add tests in `internal/board/view_test.go` — verify phase mapping, truncation, and hidden state
|
|
33
|
+
- [x] Run `make build && make test` to verify no regressions
|
|
34
|
+
|
|
35
|
+
## Context Log
|
|
36
|
+
|
|
37
|
+
Files read:
|
|
38
|
+
- `.savepoint/router.md`
|
|
39
|
+
- `agent-skills/savepoint-build-task/SKILL.md`
|
|
40
|
+
- `.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/E03-Design.md`
|
|
41
|
+
- `.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T002-next-activity-below-header.md`
|
|
42
|
+
- `.savepoint/visual-identity.md`
|
|
43
|
+
- `agent-skills/ink-tui-design/SKILL.md`
|
|
44
|
+
- `internal/board/view.go`
|
|
45
|
+
- `internal/board/layout.go`
|
|
46
|
+
- `internal/styles/styles.go`
|
|
47
|
+
- `internal/data/router.go`
|
|
48
|
+
- `internal/board/view_test.go`
|
|
49
|
+
- `internal/board/layout_test.go`
|
|
50
|
+
|
|
51
|
+
Files edited:
|
|
52
|
+
- `internal/board/view.go`
|
|
53
|
+
- `internal/board/layout.go`
|
|
54
|
+
- `internal/board/view_test.go`
|
|
55
|
+
- `internal/board/layout_test.go`
|
|
56
|
+
- `.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T002-next-activity-below-header.md`
|
|
57
|
+
- `.savepoint/router.md`
|
|
58
|
+
|
|
59
|
+
Estimated input tokens: 9800
|
|
60
|
+
|
|
61
|
+
Notes:
|
|
62
|
+
- Key design decision from user: placement below header as dedicated line (not right-aligned in header); reuse existing FooterPhase* styles
|
|
63
|
+
- Acceptance criteria verified by `go test ./internal/board` covering dedicated line ordering, hidden nil/idle/empty states, phase tag mapping, `next_action` text, narrow truncation, and header preservation.
|
|
64
|
+
- Quality gates: `make build` could not run because `make` is not installed in this Windows shell. Equivalent `go run ./internal/buildtool build` passed. Equivalent `go test ./...` passed.
|
package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T003-checkbox-rendering-fix.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E03-ui-visual-refinement/T003-checkbox-rendering-fix
|
|
3
|
+
status: done
|
|
4
|
+
objective: "Fix checkbox rendering to place checkboxes at sentence start, not at line break positions"
|
|
5
|
+
depends_on:
|
|
6
|
+
- E03-ui-visual-refinement/T001-border-resize-fix
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# T003: Fix Checkbox Rendering — Place at Sentence Start
|
|
10
|
+
|
|
11
|
+
## Acceptance Criteria
|
|
12
|
+
|
|
13
|
+
- Checkboxes (`[ ]` / `[x]`) render at the beginning of each task description sentence, not at arbitrary line-break positions
|
|
14
|
+
- If a task description is hard-wrapped in markdown at column 80, the checkbox appears only once per sentence
|
|
15
|
+
- Multi-sentence tasks show one checkbox per sentence, visually aligned at column 0 of each sentence
|
|
16
|
+
- Already-checked tasks show `[x]` at sentence start consistently
|
|
17
|
+
- No duplicate checkboxes for the same sentence
|
|
18
|
+
- Single-sentence tasks (most common case) render exactly one checkbox at the start, unchanged from current behavior
|
|
19
|
+
|
|
20
|
+
## Implementation Plan
|
|
21
|
+
|
|
22
|
+
- [x] Read `internal/data/task.go` — locate the markdown parsing / TUI rendering path for task descriptions
|
|
23
|
+
- [x] Read `internal/board/view.go` — locate where task items are rendered in the board columns
|
|
24
|
+
- [x] Identify the parsing layer — this is likely where markdown task body text is split into the displayed description string before being passed to rendering
|
|
25
|
+
- [x] Edit the identified file(s) — change the sentence-splitting logic to split on sentence boundaries (`. `, `!\n`, `?\n`) rather than on hard line breaks
|
|
26
|
+
- [x] In the rendering layer, emit one checkbox per sentence start, aligned to column 0 of each sentence block
|
|
27
|
+
- [x] Add tests in the relevant test file for sentence-boundary detection, single-sentence, multi-sentence, and hard-wrapped cases
|
|
28
|
+
- [x] Run `make build && make test` to verify no regressions
|
|
29
|
+
|
|
30
|
+
## Context Log
|
|
31
|
+
|
|
32
|
+
Files read:
|
|
33
|
+
- `internal/data/task.go`
|
|
34
|
+
- `internal/data/parser.go`
|
|
35
|
+
- `internal/data/parser_test.go`
|
|
36
|
+
- `internal/board/view.go`
|
|
37
|
+
- `internal/board/detail.go`
|
|
38
|
+
- `internal/board/detail_test.go`
|
|
39
|
+
- `agent-skills/savepoint-build-task/SKILL.md`
|
|
40
|
+
- `agent-skills/ink-tui-design/SKILL.md`
|
|
41
|
+
- `.savepoint/visual-identity.md`
|
|
42
|
+
|
|
43
|
+
Files edited:
|
|
44
|
+
- `internal/data/parser.go`
|
|
45
|
+
- `internal/data/parser_test.go`
|
|
46
|
+
- `internal/board/detail.go`
|
|
47
|
+
- `internal/board/detail_test.go`
|
|
48
|
+
|
|
49
|
+
Estimated input tokens: 8,500
|
|
50
|
+
|
|
51
|
+
Notes:
|
|
52
|
+
- Parser now joins hard-wrapped continuation lines into the current checklist item.
|
|
53
|
+
- Detail rendering now splits checklist item text into semantic sentences and emits `[ ]` / `[x]` only at sentence starts; wrapped continuation lines are indented under the sentence text.
|
|
54
|
+
- Focused tests: `go test ./internal/data ./internal/board` passed.
|
|
55
|
+
- Required literal quality gate: `make build` could not run because `make` is not installed in this PowerShell environment.
|
|
56
|
+
- Equivalent gates: `go run ./internal/buildtool build` passed; `go test ./...` passed.
|
package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T005-unify-status-glyphs.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E03-ui-visual-refinement/T005-unify-status-glyphs
|
|
3
|
+
status: done
|
|
4
|
+
objective: "Unify icon/glyph determination across task cards and epic sidebar via a shared statusGlyph helper with backward compatibility"
|
|
5
|
+
depends_on: []
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# T005: Unify Task Status Glyph Determination
|
|
9
|
+
|
|
10
|
+
## Acceptance Criteria
|
|
11
|
+
|
|
12
|
+
- A new `status` field is added to the `data.Task` struct (one of: `planned`, `in_progress`, `done`, `audited`)
|
|
13
|
+
- A shared `statusGlyph(status string) (styled string)` helper exists in `internal/board/status.go` that maps status strings to the same glyph+style used by the epic sidebar
|
|
14
|
+
- `RenderCard` in `card.go` uses the unified helper when `Task.Status` is set, otherwise falls back to the existing Column+Stage logic with identical behavior
|
|
15
|
+
- The epic sidebar's `epicSidebarGlyph` function is refactored to call the shared `statusGlyph` helper instead of its own switch
|
|
16
|
+
- All existing tests pass without modification
|
|
17
|
+
- New tests cover the explicit `Status` path for each status value
|
|
18
|
+
- No changes to existing task files are required
|
|
19
|
+
- `make build && make test` pass
|
|
20
|
+
|
|
21
|
+
## Implementation Plan
|
|
22
|
+
|
|
23
|
+
- [x] Read `internal/data/task.go` — study Task struct and existing columns/stage types
|
|
24
|
+
- [x] Read `internal/board/card.go` — study current RenderCard glyph determination path
|
|
25
|
+
- [x] Read `internal/board/epic_panel.go` — study epicSidebarGlyph for extraction opportunity
|
|
26
|
+
- [x] Edit `internal/data/task.go` — add `Status string` field to Task struct and Status constants
|
|
27
|
+
- [x] Create `internal/board/status.go` — shared `statusGlyph(status string) string` function with the unified glyph mapping
|
|
28
|
+
- [x] Edit `internal/board/epic_panel.go` — refactor `epicSidebarGlyph` to call the shared `statusGlyph`
|
|
29
|
+
- [x] Edit `internal/board/card.go` — update `RenderCard` to use `statusGlyph` when Status is set, else existing backward-compat path
|
|
30
|
+
- [x] Edit `internal/board/card_test.go` — add tests for explicit Status path (planned/in_progress/done/audited)
|
|
31
|
+
- [x] Run `make build && make test` to verify no regressions
|
|
32
|
+
|
|
33
|
+
## Context Log
|
|
34
|
+
|
|
35
|
+
Files read:
|
|
36
|
+
- `.savepoint/router.md`
|
|
37
|
+
- `.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/E03-Detail.md`
|
|
38
|
+
- `.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T005-unify-status-glyphs.md`
|
|
39
|
+
- `agent-skills/savepoint-build-task/SKILL.md`
|
|
40
|
+
- `agent-skills/ink-tui-design/SKILL.md`
|
|
41
|
+
- `.savepoint/visual-identity.md`
|
|
42
|
+
- `internal/data/task.go`
|
|
43
|
+
- `internal/data/parser.go`
|
|
44
|
+
- `internal/data/write.go`
|
|
45
|
+
- `internal/data/task_test.go`
|
|
46
|
+
- `internal/board/card.go`
|
|
47
|
+
- `internal/board/epic_panel.go`
|
|
48
|
+
- `internal/styles/styles.go`
|
|
49
|
+
- `internal/board/card_test.go`
|
|
50
|
+
- `internal/board/epic_panel_test.go`
|
|
51
|
+
- `.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T003-epic-status-glyphs.md`
|
|
52
|
+
|
|
53
|
+
Estimated input tokens: 11000
|
|
54
|
+
|
|
55
|
+
Notes:
|
|
56
|
+
- Option A approach: backward compatible when `Status` is unset
|
|
57
|
+
- The unified glyph mapping matches epic sidebar: planned→○, in_progress→▶, done→◉, audited→✓
|
|
58
|
+
- Old `Column`+`Stage` path reproduces exact current behavior (▣/◇/◆ with column-level overrides)
|
|
59
|
+
- `go test ./internal/board ./internal/data` initially hit a sandbox AppData build-cache permission error; rerun outside the sandbox passed.
|
|
60
|
+
- Literal `make build && make test` could not run because `make` is not installed in this Windows shell.
|
|
61
|
+
- Equivalent quality gates passed: `go run ./internal/buildtool build`; `go test ./...`.
|
|
62
|
+
|
|
63
|
+
## Drift Notes
|
|
64
|
+
|
|
65
|
+
- Drift: `internal/board/status.go` added, not yet in Codebase Map.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E03-ui-visual-refinement/T006-forced-256-color-profile
|
|
3
|
+
status: done
|
|
4
|
+
objective: "Force 256-color terminal profile at init to ensure consistent background rendering across all terminals"
|
|
5
|
+
depends_on: []
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# T006: Forced 256-Color Profile for Terminal Consistency
|
|
9
|
+
|
|
10
|
+
## Acceptance Criteria
|
|
11
|
+
|
|
12
|
+
- On startup, `lipgloss` is configured to use `Force256Color` profile instead of relying on terminal detection
|
|
13
|
+
- The board's background renders as uniform black (`"#000000"` / ANSI256 `"232"`) on every color-capable terminal including PowerShell, CMD, Windows Terminal, VS Code terminal, and all Unix terminals
|
|
14
|
+
- No color artifacts or background mismatches are visible when running on PowerShell
|
|
15
|
+
- Existing style definitions using TrueColor hex values still resolve correctly via Lipgloss's 256-color fallback
|
|
16
|
+
- `make build && make test` pass with no regressions
|
|
17
|
+
|
|
18
|
+
## Implementation Plan
|
|
19
|
+
|
|
20
|
+
- [ ] Read `main.go` — understand startup flow and identify where to inject profile forcing
|
|
21
|
+
- [ ] Edit `main.go` — add `lipgloss.SetColorProfile(lipgloss.Force256Color)` call before `board.Run()`
|
|
22
|
+
- [ ] Run `make build && make test` to verify no regressions
|
|
23
|
+
|
|
24
|
+
## Context Log
|
|
25
|
+
|
|
26
|
+
Files read:
|
|
27
|
+
- `main.go`
|
|
28
|
+
- `internal/styles/palette.go`
|
|
29
|
+
- `internal/styles/styles.go`
|
|
30
|
+
|
|
31
|
+
Estimated input tokens: 400
|
|
32
|
+
|
|
33
|
+
Notes:
|
|
34
|
+
- `lipgloss.Force256Color` is supported on all Go platforms and all color-capable terminals
|
|
35
|
+
- This is a single-line change — no new dependencies or imports beyond the existing `github.com/charmbracelet/lipgloss` package
|
|
36
|
+
- TrueColor hex values (`"#000000"`) are mapped to nearest 256-color values (`"232"`) via palette.go's `color()` helper; these are already configured
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: epic-design
|
|
3
|
+
status: audited
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Epic E04: Epic Navigation
|
|
7
|
+
|
|
8
|
+
## Purpose
|
|
9
|
+
|
|
10
|
+
Make the epic sidebar an active, focusable UI component. The sidebar currently lists epics as static text — the only way to switch epics is through the `E` key dropdown popup. This epic gives the sidebar parity with task columns: ↑/↓ navigation, focus highlighting, and an Enter-triggered "Epic Detail" overlay.
|
|
11
|
+
|
|
12
|
+
## Definition of Done
|
|
13
|
+
|
|
14
|
+
- Epic sidebar is focusable — left arrow from `Planned` column moves focus to sidebar
|
|
15
|
+
- In sidebar focus: ↑/↓ navigates through epics, right arrow returns to column view
|
|
16
|
+
- Focused epic filters tasks in all three columns (same filtering as current `SelectedEpic`)
|
|
17
|
+
- A focused epic entry in the sidebar is visually distinct from unfocused ones
|
|
18
|
+
- Enter on a focused epic opens an "Epic Detail" overlay showing the epic's `E##-Detail.md` content
|
|
19
|
+
- Overlay supports scrolling (↑/↓, PgUp/PgDown) identical to task detail overlay
|
|
20
|
+
- `E` key dropdown behavior is preserved unchanged
|
|
21
|
+
- All above works only when epic panel is visible (≥120 terminal width)
|
|
22
|
+
|
|
23
|
+
## Components and files
|
|
24
|
+
|
|
25
|
+
| Path | Purpose |
|
|
26
|
+
|------|---------|
|
|
27
|
+
| `internal/board/model.go` | Add `EpicPanelFocus`, `EpicPanelCursor`, `EpicDetailOffset`, `EpicDetailContent` state |
|
|
28
|
+
| `internal/board/update.go` | Handle left arrow to enter panel, ↑/↓ within, Enter to open detail, right arrow to exit |
|
|
29
|
+
| `internal/board/view.go` | Pass focus/cursor to `RenderEpicSidebar`, render epic detail overlay |
|
|
30
|
+
| `internal/board/epic_panel.go` | Update `RenderEpicSidebar` for focus/cursor, add `RenderEpicDetail` |
|
|
31
|
+
| `internal/board/detail.go` | Reuse `visibleDetailLines`, `WrapText`, scroll helpers for epic detail |
|
|
32
|
+
| `internal/board/board.go` | Load epic status from detail files in `loadBoardData` |
|
|
33
|
+
| `internal/board/watch.go` | Carry `epicStatuses` in `reloadMsg` for dynamic reloads |
|
|
34
|
+
| `internal/data/parser.go` | Reuse `ParseFrontmatter` to extract status YAML field |
|
|
35
|
+
|
|
36
|
+
## Architectural notes
|
|
37
|
+
|
|
38
|
+
- `EpicPanelFocus bool` is a lightweight flag replacing the need for a new column type
|
|
39
|
+
- The epic detail overlay content is read from `E##-Detail.md` on the filesystem when Enter is pressed (not pre-loaded)
|
|
40
|
+
- Detail file path is deterministic: `{root}/releases/{release}/epics/{epic-slug}/{shortID}-Detail.md`
|
|
41
|
+
- If the detail file is missing, the overlay shows a "(no detail available)" message
|
|
42
|
+
- Column selection, task selection, and existing overlay behavior are completely unchanged
|
|
43
|
+
|
|
44
|
+
## Implemented as
|
|
45
|
+
|
|
46
|
+
- `internal/board/model.go` adds `EpicPanelFocus`, `EpicPanelCursor`, `EpicDetailOffset`, `EpicDetailContent`, and `EpicStatus` model state.
|
|
47
|
+
- `internal/board/update.go` handles global keys before epic-panel routing, focuses the panel from the Planned column on wide layouts, changes the selected epic during panel cursor movement, writes router release/epic state, and opens the epic detail overlay on Enter.
|
|
48
|
+
- `internal/board/epic_panel.go` renders the purple-accented epic sidebar focus state, purple epic detail overlay, markdown detail body, and side-panel-only status glyph prefixes.
|
|
49
|
+
- `internal/board/board.go` loads epic status frontmatter during board-data loading; `internal/board/watch.go` carries that status map through reloads.
|
|
50
|
+
- Epic navigation deliberately uses `VibePurple` (`#B1A1DF`) for focused epic panel borders, focused epic labels, epic detail overlays, and epic/audit accents, while task-column focus remains Atari Orange.
|
|
51
|
+
- Implementation deviation: T001 originally said Enter in epic-panel focus selected the focused epic. The final behavior from T002 is that up/down selects and filters immediately, while Enter opens the epic detail overlay.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E04-epic-navigation/T001-sidebar-focusable-navigation
|
|
3
|
+
status: done
|
|
4
|
+
objective: "Make the epic sidebar focusable with up/down navigation to select epics"
|
|
5
|
+
depends_on: []
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# T001: Sidebar Focusable Navigation
|
|
9
|
+
|
|
10
|
+
## Acceptance Criteria
|
|
11
|
+
|
|
12
|
+
- Left arrow (`←`/`h`) from the `Planned` column moves keyboard focus to the epic panel (when panel is visible at ≥120 width)
|
|
13
|
+
- In epic panel focus mode, `↑`/`k` moves the cursor up through the epic list (clamped to bounds)
|
|
14
|
+
- In epic panel focus mode, `↓`/`j` moves the cursor down through the epic list (clamped to bounds)
|
|
15
|
+
- The focused epic entry in the sidebar is highlighted with the same focused style used in task columns
|
|
16
|
+
- `Enter` in epic panel focus mode selects the focused epic: tasks are filtered to that epic, and focus remains in the panel
|
|
17
|
+
- Right arrow (`→`/`l`) from epic panel focus exits back to the `Planned` column with `FocusedTask=0`
|
|
18
|
+
- The existing `E` key dropdown overlay still works unchanged
|
|
19
|
+
- When no epics exist in the current release, the panel shows no navigable cursor
|
|
20
|
+
- All navigation is blocked when any overlay is open (existing behavior)
|
|
21
|
+
|
|
22
|
+
## Implementation Plan
|
|
23
|
+
|
|
24
|
+
- [x] Add `EpicPanelFocus bool` and `EpicPanelCursor int` to `Model` in `model.go`
|
|
25
|
+
- [x] Add `EpicPanelFocus` tracking to `refreshEpicsForRelease()` — clamp cursor and clear focus if epics list becomes empty
|
|
26
|
+
- [x] In `update.go` — before the `switch msg.String()` block, check `m.Overlay == OverlayNone && m.EpicPanelFocus` and route to a new `updateEpicPanel` method
|
|
27
|
+
- [x] In `updateEpicPanel` — handle `up`/`k` (decrement cursor), `down`/`j` (increment cursor), `enter` (call `m.selectEpicPanelEpic()`), `right`/`l` (exit to Planned column), `left`/`h` (no-op or wrap)
|
|
28
|
+
- [x] In `update.go` main switch — handle `left`/`h` when `FocusedColumn == Planned` by setting `EpicPanelFocus = true` (only when epic panel is visible, i.e. `CalculateLayout(m.Width, m.Height).EpicPanelVisible`)
|
|
29
|
+
|
|
30
|
+
- [x] Add `m.selectEpicPanelEpic()` method: set `m.SelectedEpic = m.Epics[m.EpicPanelCursor]`, reset `m.FocusedTask = 0`, `m.DetailOffset = 0`, call `m.refreshTasks()`, call `m.ensureFocusedTaskVisible()`, write router state
|
|
31
|
+
- [x] Update `epic_panel.go` — update `RenderEpicSidebar` signature to accept `focus bool, cursor int` params; when focused, render the item at cursor with `styles.TaskItemFocused` and `epicActiveMarker`; when not focused, keep current rendering with `SelectedEpic` marker
|
|
32
|
+
- [x] Update `view.go` — pass `m.EpicPanelFocus` and `m.EpicPanelCursor` to `RenderEpicSidebar` in `renderEpicPanel`
|
|
33
|
+
- [x] Add `m.epicPanelPageSize()` helper returning `m.Height / 2` (or similar) for eventual PgUp/PgDown support
|
|
34
|
+
- [x] Run `make build && make test` to verify no regressions
|
|
35
|
+
|
|
36
|
+
## Context Log
|
|
37
|
+
|
|
38
|
+
Files read:
|
|
39
|
+
- `.savepoint/router.md`
|
|
40
|
+
- `agent-skills/savepoint-build-task/SKILL.md`
|
|
41
|
+
- `agent-skills/ink-tui-design/SKILL.md`
|
|
42
|
+
- `.savepoint/visual-identity.md`
|
|
43
|
+
- `.savepoint/releases/v1.1/epics/E04-epic-navigation/E04-Detail.md`
|
|
44
|
+
- `.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T001-sidebar-focusable-navigation.md`
|
|
45
|
+
- `internal/board/model.go`
|
|
46
|
+
- `internal/board/update.go`
|
|
47
|
+
- `internal/board/view.go`
|
|
48
|
+
- `internal/board/epic_panel.go`
|
|
49
|
+
- `internal/board/layout.go`
|
|
50
|
+
- `internal/board/board.go`
|
|
51
|
+
- `internal/board/epic_panel_test.go`
|
|
52
|
+
- `internal/board/update_test.go`
|
|
53
|
+
- `internal/board/model_test.go`
|
|
54
|
+
- `internal/board/view_test.go`
|
|
55
|
+
|
|
56
|
+
Estimated input tokens: 12000
|
|
57
|
+
|
|
58
|
+
Notes:
|
|
59
|
+
- Model's `EpicCursor` field (used in dropdown) is distinct from new `EpicPanelCursor`
|
|
60
|
+
- The epic panel visibility is determined by `layout.EpicPanelVisible` in `CalculateLayout`
|
|
61
|
+
- Focused board tests: `go test ./internal/board` passed.
|
|
62
|
+
- Required quality gate `make build && make test`: failed to start because `make` is not installed in this shell.
|
|
63
|
+
- Equivalent quality gates: `go build -o savepoint main.go` passed; `go test ./...` passed.
|
|
64
|
+
- Follow-up fix after manual review: epic panel focus now renders with the focused panel border and focused title so entering the sidebar is visually apparent even when the cursor starts on the already selected epic. Re-ran `go test ./internal/board`, `go build -o savepoint main.go`, and `go test ./...`; all passed.
|
|
65
|
+
- Follow-up input-routing fix: global `q`, `e`, `r`, and `?` keys now run before epic-panel-specific key handling, so quit and dropdown overlays still work when the epic panel is focused. Added regression tests for `q`, `e`, and `r` from epic panel focus. Re-ran `go test ./internal/board`, `go build -o savepoint main.go`, and `go test ./...`; all passed.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E04-epic-navigation/T002-epic-detail-overlay
|
|
3
|
+
status: done
|
|
4
|
+
objective: "Add Epic Detail overlay showing E##-Detail.md content, triggered by Enter on a focused epic"
|
|
5
|
+
depends_on:
|
|
6
|
+
- E04-epic-navigation/T001-sidebar-focusable-navigation
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# T002: Epic Detail Overlay
|
|
10
|
+
|
|
11
|
+
## Acceptance Criteria
|
|
12
|
+
|
|
13
|
+
- Pressing `Enter` on a focused epic in the sidebar opens a centered overlay titled "EPIC DETAIL"
|
|
14
|
+
- The overlay content is read from the epic's `E##-Detail.md` file on disk
|
|
15
|
+
- If the file exists, it shows: epic title, purpose, definition of done, and the components table (rendered as text)
|
|
16
|
+
- If the file does not exist, the overlay shows an informative "(no detail available)" message
|
|
17
|
+
- The overlay is height-capped at ~70% of terminal height with scroll indicators (↑/↓) for overflow
|
|
18
|
+
- `↑`/`k` and `↓`/`j` scroll the detail content (reuses existing scroll indicator pattern from `detail.go`)
|
|
19
|
+
- `PgUp`/`PgDown` scroll in page increments
|
|
20
|
+
- `Esc` or `q` closes the overlay and returns to epic panel focus
|
|
21
|
+
- The overlay uses `styles.DetailOverlay` for consistent visual styling with task detail
|
|
22
|
+
|
|
23
|
+
## Implementation Plan
|
|
24
|
+
|
|
25
|
+
- [x] Add `OverlayEpicDetail OverlayType = "detail-epic"` to `model.go`
|
|
26
|
+
- [x] Add `EpicDetailOffset int` to `Model` in `model.go`
|
|
27
|
+
- [x] Add `EpicDetailContent string` to `Model` in `model.go` (cached content of the detail file)
|
|
28
|
+
|
|
29
|
+
- [x] In `epic_panel.go` — add `RenderEpicDetail(epicID, content string, overlayW, maxHeight, offset int) string`:
|
|
30
|
+
- Parse frontmatter lines from the markdown content (lines between `---` markers) for metadata display
|
|
31
|
+
- Render header: epic ID and title from markdown heading
|
|
32
|
+
- Render body: the rest of the markdown content as plain text (no markdown rendering)
|
|
33
|
+
- Use `visibleDetailLines` from `detail.go` for height-capped scrolling
|
|
34
|
+
- Reuse `styles.DetailOverlay`, `styles.ColumnTitleFocused`, `styles.CardMeta`, `styles.ColumnTitle`
|
|
35
|
+
|
|
36
|
+
- [x] In `update.go` — when `m.EpicPanelFocus && enter`:
|
|
37
|
+
- Derive detail file path: `{m.Root}/releases/{m.SelectedRelease}/epics/{epicSlug}/{shortID(epicSlug)}-Detail.md`
|
|
38
|
+
- Read the file content with `os.ReadFile`
|
|
39
|
+
- If error (file missing, etc.), set `m.EpicDetailContent = "(no detail available)"`
|
|
40
|
+
- Set `m.Overlay = OverlayEpicDetail`, `m.EpicDetailOffset = 0`
|
|
41
|
+
- Cache the content in `m.EpicDetailContent`
|
|
42
|
+
|
|
43
|
+
- [x] In `updateOverlay` in `update.go` — match `OverlayEpicDetail` and handle:
|
|
44
|
+
- `esc`/`q` → `OverlayNone` (exit back to epic panel focus)
|
|
45
|
+
- `up`/`k` → decrement `EpicDetailOffset` if > 0
|
|
46
|
+
- `down`/`j` → increment `EpicDetailOffset`
|
|
47
|
+
- `pgup`/`pgdown` → page scroll using existing `detailPageSize()`
|
|
48
|
+
|
|
49
|
+
- [x] In `view.go` — match `OverlayEpicDetail` and call `RenderEpicDetail(...)` with the cached content
|
|
50
|
+
- [x] Reuse `visibleDetailLines`, `clampDetailOffset`, `detailRow`, `WrapText` from `detail.go` — no need to copy
|
|
51
|
+
- [x] Run `make build && make test` to verify no regressions
|
|
52
|
+
|
|
53
|
+
## Context Log
|
|
54
|
+
|
|
55
|
+
Files read:
|
|
56
|
+
- `internal/board/model.go`
|
|
57
|
+
- `internal/board/update.go`
|
|
58
|
+
- `internal/board/view.go`
|
|
59
|
+
- `internal/board/epic_panel.go`
|
|
60
|
+
- `internal/board/detail.go`
|
|
61
|
+
- `internal/board/card.go` — `shortID` helper
|
|
62
|
+
- `.savepoint/releases/v1.1/epics/E01-tui-optimisation/E01-Detail.md` — example detail file
|
|
63
|
+
|
|
64
|
+
Estimated input tokens: ~2800
|
|
65
|
+
|
|
66
|
+
Quality gate: `go build` ✓, `go test ./...` ✓ (all 3 packages pass)
|
|
67
|
+
|
|
68
|
+
Notes:
|
|
69
|
+
- `detail.go` functions `visibleDetailLines`, `clampDetailOffset`, `WrapText` are unexported — `epic_panel.go` is in the same `board` package so they're accessible
|
|
70
|
+
- Content loading is synchronous (simple file read) — no async command needed
|
|
71
|
+
- `shortID` extracts "E04" from "E04-epic-navigation" via first `-` split
|
|
72
|
+
- Updated `TestUpdate_epicPanelEnterSelectsFocusedEpic` → `TestUpdate_epicPanelEnterOpensDetailOverlay` to reflect T002 behavior change
|
|
73
|
+
- Added 7 new tests covering overlay open, scroll, pgup/pgdown, esc close, view rendering, no-content fallback
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E04-epic-navigation/T003-epic-status-glyphs
|
|
3
|
+
status: done
|
|
4
|
+
objective: "Add status glyphs to the epic sidebar showing each epic's lifecycle state"
|
|
5
|
+
depends_on:
|
|
6
|
+
- E04-epic-navigation/T001-sidebar-focusable-navigation
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# T003: Epic Status Glyphs in Side Panel
|
|
10
|
+
|
|
11
|
+
## Acceptance Criteria
|
|
12
|
+
|
|
13
|
+
- Each epic in the sidebar shows a status glyph prefix: `○` for `planned`, `▶` for `in_progress`, `◉` for `done`, `✓` for `audited`, space for unknown
|
|
14
|
+
- The glyph is styled: `○` in dim, `▶` in orange, `◉` in green, `✓` in green — matching the status colour convention
|
|
15
|
+
- The status is read from the `status:` field in each epic's `E##-Detail.md` frontmatter at load time
|
|
16
|
+
- Only the **side panel** is affected — the `E` key dropdown overlay is unchanged
|
|
17
|
+
- The status map is loaded once during `loadBoardData` and cached in the Model (no per-frame file I/O)
|
|
18
|
+
- If an epic's detail file is missing or has no `status` frontmatter, the glyph defaults to a space (no indicator)
|
|
19
|
+
- All existing epic sidebar rendering (focus highlighting, cursor, active marker, selected marker) works unchanged
|
|
20
|
+
- `make build && make test` pass
|
|
21
|
+
|
|
22
|
+
## Implementation Plan
|
|
23
|
+
|
|
24
|
+
- [x] Add `EpicStatus map[string]string` to `Model` in `model.go` — keyed by epic ID, values like `"planned"`, `"in_progress"`, `"done"`, `"audited"`
|
|
25
|
+
- [x] In `board.go` — update `loadBoardData` to load epic statuses:
|
|
26
|
+
- After listing epics for a release, iterate each epic's directory
|
|
27
|
+
- Build detail file path: `filepath.Join(epic.Path, shortID(epic.ID)+"-Detail.md")`
|
|
28
|
+
- Read the file with `os.ReadFile`
|
|
29
|
+
- Parse frontmatter with `data.NewParser().ParseFrontmatter(string(content))`
|
|
30
|
+
- Extract `"status"` from the returned map; if missing, skip
|
|
31
|
+
- Store in `epicStatuses[epic.ID]` — collect all epics across releases into the map
|
|
32
|
+
- [x] Pass `epicStatuses map[string]string` through the `reloadMsg` pipeline so dynamic reloads preserve glyphs
|
|
33
|
+
- [x] In `epic_panel.go` — update `RenderEpicSidebar` signature to accept `status map[string]string`
|
|
34
|
+
- [x] Add a helper function `epicSidebarGlyph(status map[string]string, epicID string) string`:
|
|
35
|
+
- `"planned"` → styles.CardMeta.Render("○")
|
|
36
|
+
- `"in_progress"` → styles.GlyphBuild.Render("▶")
|
|
37
|
+
- `"done"` → styles.TagDone.Render("◉")
|
|
38
|
+
- `"audited"` → styles.TagDone.Render("✓")
|
|
39
|
+
- default → " " (single space)
|
|
40
|
+
- [x] In `RenderEpicSidebar` — prepend the glyph to each epic label: `"▶ E01-tui-optimisation"`
|
|
41
|
+
- [x] In `view.go` — pass `m.EpicStatus` to `RenderEpicSidebar`
|
|
42
|
+
- [x] Handle `EpicStatus` in `reloadMsg` handler in `update.go` — store the map when tasks reload
|
|
43
|
+
- [x] Update `reloadMsg` struct in `watch.go` to carry `epicStatuses map[string]string`
|
|
44
|
+
- [x] Run `make build && make test` to verify no regressions
|
|
45
|
+
|
|
46
|
+
## Context Log
|
|
47
|
+
|
|
48
|
+
Files read:
|
|
49
|
+
- `internal/board/model.go`
|
|
50
|
+
- `internal/board/epic_panel.go`
|
|
51
|
+
- `internal/board/view.go`
|
|
52
|
+
- `internal/board/board.go`
|
|
53
|
+
- `internal/board/watch.go`
|
|
54
|
+
- `internal/board/update.go`
|
|
55
|
+
- `internal/board/card.go` — glyph pattern reference
|
|
56
|
+
- `internal/styles/styles.go` — existing style constants
|
|
57
|
+
- `internal/data/parser.go` — `ParseFrontmatter` for YAML extraction
|
|
58
|
+
- `.savepoint/releases/v1.1/epics/E01-tui-optimisation/E01-Detail.md` — example frontmatter with status field
|
|
59
|
+
- `.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T001-sidebar-focusable-navigation.md` — dependency status check
|
|
60
|
+
- `internal/board/epic_panel_test.go` — updated RenderEpicSidebar test calls
|
|
61
|
+
|
|
62
|
+
Estimated input tokens: 1800
|
|
63
|
+
|
|
64
|
+
Notes:
|
|
65
|
+
- Reuses `data.NewParser().ParseFrontmatter()` which already handles YAML frontmatter extraction
|
|
66
|
+
- Reuses `shortID()` from `card.go` (same package) to derive the detail file name
|
|
67
|
+
- The `E` key dropdown in `epic_panel.go` (`RenderEpicDropdown`) is intentionally NOT updated — side panel only per user preference
|
|
68
|
+
- Function named `epicSidebarGlyph` (not `epicStatusGlyph`) — takes `(map[string]string, string)` for nil-safe lookup
|
|
69
|
+
- `go build` + `go test ./...` pass
|
|
70
|
+
|
|
71
|
+
## Drift Notes
|
|
72
|
+
|
|
73
|
+
No drift — all changes are within existing files and follow established patterns.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: epic-design
|
|
3
|
+
status: planned
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Epic E05: Tasking Permissions & Router Updates
|
|
7
|
+
|
|
8
|
+
## Purpose
|
|
9
|
+
|
|
10
|
+
Restrict agent task status mutation to `in_progress` only (no `done`, no retreat). Add an explicit TUI hotkey (`m`) to update the router to the current task, decoupling router updates from navigation. The user retains full control over `done` transitions and retreats via the board.
|
|
11
|
+
|
|
12
|
+
## Definition of Done
|
|
13
|
+
|
|
14
|
+
- AGENTS.md updated: agents set `status: in_progress` when starting implementation; only user can set `done` or retreat
|
|
15
|
+
- Router.md updated: document that agent sets router task when starting work via explicit `m` action
|
|
16
|
+
- Design.md Section 4 updated: status model distinguishes agent vs user capabilities
|
|
17
|
+
- TUI `m` hotkey implemented: sets router's `task` field to the currently focused task; detects if it's the last uncompleted task in the epic → sets `audit-pending` state
|
|
18
|
+
- Help overlay shows `m` key binding
|
|
19
|
+
- `make build && make test` passes
|
|
20
|
+
|
|
21
|
+
## Components and files
|
|
22
|
+
|
|
23
|
+
| Path | Purpose |
|
|
24
|
+
|------|---------|
|
|
25
|
+
| `AGENTS.md` | Remove "set status: done" from Task Completion Protocol; add `in_progress` guidance |
|
|
26
|
+
| `.savepoint/router.md` | Add agent router-update guidance in task-building state |
|
|
27
|
+
| `.savepoint/Design.md` | Revise Section 4 status model: agent `in_progress` only, user `done`/retreat only |
|
|
28
|
+
| `.savepoint/releases/v1.1/v1.1-PRD.md` | Add E05 to epic breakdown |
|
|
29
|
+
| `.savepoint/router.md` | Update current state for E05/T001 |
|
|
30
|
+
| `internal/board/update.go` | Add `m` key handler for explicit router update |
|
|
31
|
+
| `internal/board/model.go` | Add `writeRouterTask()` method to update router's `task` field and derive state |
|
|
32
|
+
| `internal/board/help.go` | Add `m` key to keyboard shortcuts |
|
|
33
|
+
| `internal/data/router.go` | No changes needed (WriteRouterState already supports all fields) |
|
|
34
|
+
| `internal/data/write.go` | No changes needed |
|
|
35
|
+
|
|
36
|
+
## Architectural notes
|
|
37
|
+
|
|
38
|
+
- The `m` hotkey reads the currently focused task, not the epic panel cursor
|
|
39
|
+
- Router state derivation from task:
|
|
40
|
+
- Task is the last uncompleted task in its epic → `state: audit-pending`, `task: <empty>`
|
|
41
|
+
- Otherwise → `state: task-building`, `task: <full-task-id>`
|
|
42
|
+
- `release` and `epic` are always set from the focused task
|
|
43
|
+
- The `m` key does nothing when no task is focused, or when focused on a `done` task
|
|
44
|
+
- The `m` key is independent of navigation — user can browse freely without router drift
|
|
45
|
+
- No code enforcement against agents writing `done`. This is a documentation-only trust boundary. AGENTS.md is the contract.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E05-tasking-permissions/T001-update-agents-md
|
|
3
|
+
status: planned
|
|
4
|
+
objective: "Update AGENTS.md to remove agent 'set status: done' permission and add 'set status: in_progress' guidance with router update instruction"
|
|
5
|
+
depends_on: []
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# T001: Update AGENTS.md
|
|
9
|
+
|
|
10
|
+
## Acceptance Criteria
|
|
11
|
+
|
|
12
|
+
- Task Completion Protocol no longer says "Set the task frontmatter to `status: done`"
|
|
13
|
+
- Protocol says "When starting implementation, set `status: in_progress`"
|
|
14
|
+
- Protocol says "After setting `in_progress`, press `m` in the TUI to update the router"
|
|
15
|
+
- The words "Set the task frontmatter to `status: done`" are removed or replaced
|
|
16
|
+
- Audit Handoff Rule still says the agent updates router.md to `state: audit-pending` when all tasks are done (this is router state, not task state)
|
|
17
|
+
|
|
18
|
+
## Implementation Plan
|
|
19
|
+
|
|
20
|
+
- [ ] In AGENTS.md `## Task Completion Protocol`: replace "Set the task frontmatter to `status: done`" with appropriate guidance
|
|
21
|
+
- [ ] In AGENTS.md `## Task Completion Protocol` step 7: keep router update for `audit-pending` (that's router state, not task status)
|
|
22
|
+
- [ ] In AGENTS.md add note under `## Task Status Canon` about agent vs user capabilities
|
|
23
|
+
- [ ] Run `make build && make test` to verify
|
|
24
|
+
|
|
25
|
+
## Context Log
|
|
26
|
+
|
|
27
|
+
Files read:
|
|
28
|
+
- AGENTS.md
|
|
29
|
+
- .savepoint/router.md
|
|
30
|
+
- .savepoint/releases/v1.1/epics/E05-tasking-permissions/E05-Detail.md
|
|
31
|
+
|
|
32
|
+
Estimated input tokens: 3000
|
|
33
|
+
|
|
34
|
+
Notes:
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E05-tasking-permissions/T002-update-router-md
|
|
3
|
+
status: planned
|
|
4
|
+
objective: "Add agent router-update guidance to router.md task-building state and update current state for E05"
|
|
5
|
+
depends_on: ["E05-tasking-permissions/T001-update-agents-md"]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# T002: Update Router.md
|
|
9
|
+
|
|
10
|
+
## Acceptance Criteria
|
|
11
|
+
|
|
12
|
+
- Router.md `task-building` state section includes guidance: "When starting work, set task `status: in_progress` and press `m` in TUI to update router task"
|
|
13
|
+
- Current state in router.md updated to point to E05/T001
|
|
14
|
+
- Router.md continues to describe `audit-pending` transition correctly (user confirms, router updates)
|
|
15
|
+
|
|
16
|
+
## Implementation Plan
|
|
17
|
+
|
|
18
|
+
- [ ] Edit `.savepoint/router.md` `task-building` state block to add agent router-update instruction
|
|
19
|
+
- [ ] Update router.md `## Current state` yaml block to point to E05 tasking-permissions epic
|
|
20
|
+
- [ ] Run `make build && make test` to verify
|
|
21
|
+
|
|
22
|
+
## Context Log
|
|
23
|
+
|
|
24
|
+
Files read:
|
|
25
|
+
- .savepoint/router.md
|
|
26
|
+
- .savepoint/releases/v1.1/epics/E05-tasking-permissions/E05-Detail.md
|
|
27
|
+
|
|
28
|
+
Estimated input tokens: 2500
|
|
29
|
+
|
|
30
|
+
Notes:
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E05-tasking-permissions/T003-update-design-md
|
|
3
|
+
status: planned
|
|
4
|
+
objective: "Revise Design.md Section 4 to document agent vs user task status capabilities"
|
|
5
|
+
depends_on: ["E05-tasking-permissions/T001-update-agents-md"]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# T003: Update Design.md
|
|
9
|
+
|
|
10
|
+
## Acceptance Criteria
|
|
11
|
+
|
|
12
|
+
- Design.md Section 4 (`## 4. Status model & gates`) documents:
|
|
13
|
+
- Agent can only set `status: in_progress`
|
|
14
|
+
- Only user can set `status: done` or retreat
|
|
15
|
+
- Router update is explicit via TUI `m` key, not automatic on navigation
|
|
16
|
+
- `last_audited` field updated (or not — this is documenting current design, not auditing)
|
|
17
|
+
- No other sections modified
|
|
18
|
+
|
|
19
|
+
## Implementation Plan
|
|
20
|
+
|
|
21
|
+
- [ ] Edit `.savepoint/Design.md` Section 4 to add new permission row or note
|
|
22
|
+
- [ ] Update `last_audited` in frontmatter
|
|
23
|
+
- [ ] Run `make build && make test` to verify
|
|
24
|
+
|
|
25
|
+
## Context Log
|
|
26
|
+
|
|
27
|
+
Files read:
|
|
28
|
+
- .savepoint/Design.md
|
|
29
|
+
- .savepoint/releases/v1.1/epics/E05-tasking-permissions/E05-Detail.md
|
|
30
|
+
|
|
31
|
+
Estimated input tokens: 2500
|
|
32
|
+
|
|
33
|
+
Notes:
|