savepoint 1.0.2 → 1.0.3
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 +12 -1
- package/.golangci.yml +11 -0
- package/.savepoint/Design.md +37 -36
- package/.savepoint/{audit/v1.1/E02-cross-platform-compatibility/proposals.md → releases/v1.1/epics/E02-cross-platform-compatibility/E02-Audit.md} +48 -38
- package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/E03-Audit.md +195 -0
- package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/E03-Detail.md +14 -1
- package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T006-forced-256-color-profile.md +3 -3
- package/.savepoint/{audit/v1.1/E04-epic-navigation/proposals.md → releases/v1.1/epics/E04-epic-navigation/E04-Audit.md} +65 -54
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/E05-Audit.md +237 -0
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/E05-Detail.md +25 -16
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T001-update-agents-md.md +17 -6
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T002-update-router-md.md +15 -5
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T003-update-design-md.md +19 -5
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T004-implement-m-hotkey.md +11 -1
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T005-update-help-overlay.md +9 -6
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T006-tests-and-quality-gates.md +29 -13
- package/.savepoint/releases/v1.1/epics/E06-audit-command/E06-Audit.md +56 -0
- package/.savepoint/releases/v1.1/epics/E06-audit-command/E06-Detail.md +63 -0
- package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T005-proposals.md +44 -0
- package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T007-apply-close.md +35 -0
- package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T009-integration.md +40 -0
- package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T010-audit-file-migration.md +45 -0
- package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T011-model-tab-state.md +26 -0
- package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T012-epic-audit-render.md +33 -0
- package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T013-handle-tab-keys.md +34 -0
- package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T014-tab-indicator.md +33 -0
- package/.savepoint/releases/v1.1/epics/E07-init-command/E07-Audit.md +336 -0
- package/.savepoint/releases/v1.1/epics/E07-init-command/E07-Detail.md +61 -0
- package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T001-cli-entrypoint.md +37 -0
- package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T002-target-validation.md +28 -0
- package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T003-scaffold-writer.md +46 -0
- package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T004-atomic-writes.md +27 -0
- package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T005-magic-prompt.md +25 -0
- package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T006-clipboard.md +26 -0
- package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T007-integration-test.md +26 -0
- package/.savepoint/releases/v1.1/epics/E08-board-command/E08-Audit.md +333 -0
- package/.savepoint/releases/v1.1/epics/E08-board-command/E08-Detail.md +68 -0
- package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T001-cli-entrypoint.md +26 -0
- package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T002-non-tty-fallback.md +27 -0
- package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T003-tui-app-shell.md +28 -0
- package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T004-board-model.md +29 -0
- package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T005-detail-pane.md +27 -0
- package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T006-status-transitions.md +29 -0
- package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T007-theme-fallbacks.md +29 -0
- package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T008-integration-test.md +27 -0
- package/.savepoint/releases/v1.1/epics/E09-doctor-command/E09-Audit.md +207 -0
- package/.savepoint/releases/v1.1/epics/E09-doctor-command/E09-Detail.md +65 -0
- package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T001-cli-entrypoint.md +24 -0
- package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T002-config-router-validation.md +28 -0
- package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T003-structure-checks.md +29 -0
- package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T004-dependency-checks.md +27 -0
- package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T005-audit-orphan-checks.md +28 -0
- package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T006-quality-gates-report.md +31 -0
- package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/E11-Detail.md +36 -0
- package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T001-debug-logging.md +25 -0
- package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T002-increase-debounce.md +21 -0
- package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T003-error-handling.md +22 -0
- package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T004-test-verify.md +29 -0
- package/.savepoint/releases/v1.1/epics/E12-validation-fix/E12-Audit.md +444 -0
- package/.savepoint/releases/v1.1/epics/E12-validation-fix/E12-Detail.md +45 -0
- package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T001-default-phase.md +35 -0
- package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T002-default-status.md +19 -0
- package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T003-better-errors.md +29 -0
- package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T004-validate-on-write.md +25 -0
- package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T005-tests.md +37 -0
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/E13-Audit.md +118 -0
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/E13-Detail.md +73 -0
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T001-safe-cleanup.md +66 -0
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T002-bug-fixes.md +35 -0
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T003-centralize-duplication.md +60 -0
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T004-infrastructure.md +33 -0
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T005-decompose-update.md +37 -0
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T006-async-io.md +40 -0
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T007-test-coverage.md +37 -0
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/E14-Audit.md +267 -0
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/E14-Detail.md +54 -0
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T001-group-model.md +39 -0
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T002-data-interfaces.md +42 -0
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T003-discover-orphans.md +33 -0
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T004-epic-panel-headings.md +35 -0
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T005-shell-tokenization.md +27 -0
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T006-unify-enums.md +29 -0
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T007-testutil-package.md +28 -0
- package/.savepoint/releases/v1.1/epics/E15-hardening/E15-Detail.md +43 -0
- package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T001-benchmarks.md +31 -0
- package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T002-fuzz-targets.md +28 -0
- package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T003-debug-flag.md +30 -0
- package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T004-dist-checksums.md +27 -0
- package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T005-windows-targets.md +28 -0
- package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T006-abbreviation-splitting.md +26 -0
- package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T007-root-test-allowlist.md +28 -0
- package/.savepoint/releases/v1.1/epics/_archived/T001-cli-entrypoint.md +25 -0
- package/.savepoint/releases/v1.1/epics/_archived/T002-quality-gates.md +27 -0
- package/.savepoint/releases/v1.1/epics/_archived/T003-snapshot.md +27 -0
- package/.savepoint/releases/v1.1/epics/_archived/T004-ai-reconcile.md +29 -0
- package/.savepoint/releases/v1.1/epics/_archived/T006-tui-review.md +31 -0
- package/.savepoint/releases/v1.1/epics/_archived/T008-skip-handling.md +34 -0
- package/.savepoint/releases/v1.1/v1.1-PRD.md +67 -7
- package/.savepoint/router.md +9 -16
- package/AGENTS.md +38 -23
- package/README.md +0 -1
- package/agent-skills/savepoint-audit/SKILL.md +86 -34
- package/agent-skills/savepoint-build-task/SKILL.md +7 -2
- package/agent-skills/savepoint-create-plan/SKILL.md +7 -2
- package/agent-skills/savepoint-create-task/SKILL.md +44 -31
- package/agent-skills/savepoint-draft-prd/SKILL.md +7 -2
- package/agent-skills/savepoint-system-design/SKILL.md +7 -2
- package/agent_skills_test.go +91 -0
- package/cmd/board.go +59 -0
- package/cmd/board_test.go +137 -0
- package/cmd/doctor.go +53 -0
- package/cmd/doctor_test.go +146 -0
- package/cmd/init.go +63 -0
- package/cmd/init_test.go +104 -0
- package/internal/board/board.go +40 -36
- package/internal/board/board_test.go +27 -82
- package/internal/board/card.go +43 -23
- package/internal/board/card_test.go +41 -5
- package/internal/board/column.go +44 -13
- package/internal/board/column_test.go +5 -2
- package/internal/board/detail.go +0 -47
- package/internal/board/epic_panel.go +118 -22
- package/internal/board/epic_panel_test.go +302 -17
- package/internal/board/help.go +1 -0
- package/internal/board/help_test.go +1 -0
- package/internal/board/integration_test.go +266 -0
- package/internal/board/interfaces.go +65 -0
- package/internal/board/interfaces_test.go +114 -0
- package/internal/board/io.go +93 -0
- package/internal/board/model.go +79 -118
- package/internal/board/plain.go +88 -0
- package/internal/board/plain_test.go +117 -0
- package/internal/board/release.go +1 -9
- package/internal/board/release_test.go +6 -6
- package/internal/board/status.go +4 -4
- package/internal/board/theme.go +24 -0
- package/internal/board/theme_test.go +31 -0
- package/internal/board/transitions.go +113 -88
- package/internal/board/transitions_test.go +164 -141
- package/internal/board/tui.go +32 -0
- package/internal/board/update.go +325 -215
- package/internal/board/update_test.go +299 -18
- package/internal/board/util.go +76 -0
- package/internal/board/view.go +31 -28
- package/internal/board/view_test.go +12 -2
- package/internal/board/watch.go +35 -5
- package/internal/buildtool/main.go +2 -10
- package/internal/buildtool/main_test.go +46 -0
- package/internal/data/config.go +17 -3
- package/internal/data/config_test.go +49 -0
- package/internal/data/discover.go +26 -0
- package/internal/data/discover_test.go +34 -10
- package/internal/data/errors.go +4 -0
- package/internal/data/lifecycle.go +13 -6
- package/internal/data/lifecycle_test.go +14 -11
- package/internal/data/parser.go +21 -6
- package/internal/data/parser_test.go +31 -7
- package/internal/data/task.go +0 -9
- package/internal/data/write.go +85 -11
- package/internal/data/write_test.go +167 -0
- package/internal/doctor/checks.go +567 -0
- package/internal/doctor/checks_test.go +716 -0
- package/internal/doctor/gates.go +193 -0
- package/internal/doctor/gates_test.go +166 -0
- package/internal/doctor/interfaces.go +64 -0
- package/internal/doctor/interfaces_test.go +104 -0
- package/internal/doctor/repairs.go +80 -0
- package/internal/doctor/repairs_test.go +81 -0
- package/internal/doctor/report.go +157 -0
- package/internal/doctor/report_test.go +89 -0
- package/internal/init/clipboard.go +146 -0
- package/internal/init/clipboard_test.go +74 -0
- package/internal/init/install.go +16 -0
- package/internal/init/integration_test.go +197 -0
- package/internal/init/prompt.go +14 -0
- package/internal/init/prompt_test.go +77 -0
- package/internal/init/scaffold.go +59 -0
- package/internal/init/scaffold_test.go +179 -0
- package/internal/init/template_freshness_test.go +56 -0
- package/internal/init/validate.go +85 -0
- package/internal/init/validate_test.go +141 -0
- package/internal/init/write.go +73 -0
- package/internal/init/write_test.go +91 -0
- package/internal/styles/styles_test.go +133 -0
- package/internal/testutil/fixture.go +113 -0
- package/internal/testutil/fs.go +26 -0
- package/main.go +101 -4
- package/package.json +2 -2
- package/project-audit/audit_report_glm_5.1.md +411 -0
- package/project-audit/audit_report_opus_4.6 +406 -0
- package/project-audit/consolidated-audit-report.md +456 -0
- package/savepoint +0 -0
- package/templates/project/.savepoint/Design.md +2 -2
- package/templates/project/.savepoint/router.md +10 -10
- package/templates/project/AGENTS.md +33 -21
- package/templates/project/agent-skills/savepoint-audit/SKILL.md +87 -0
- package/templates/project/agent-skills/savepoint-build-task/SKILL.md +44 -0
- package/templates/project/agent-skills/savepoint-create-plan/SKILL.md +33 -0
- package/templates/project/agent-skills/savepoint-create-task/SKILL.md +44 -0
- package/templates/project/agent-skills/savepoint-draft-prd/SKILL.md +37 -0
- package/templates/project/agent-skills/savepoint-system-design/SKILL.md +38 -0
- package/templates/prompts/audit-reconciliation.prompt.md +33 -28
- package/templates/prompts/design.prompt.md +3 -1
- package/.savepoint/audit/v1/E01/proposals.md +0 -168
- package/.savepoint/audit/v1/E01/snapshot.md +0 -78
- package/.savepoint/audit/v1/E01-go-setup/proposals.md +0 -166
- package/.savepoint/audit/v1/E01-go-setup/snapshot.md +0 -71
- package/.savepoint/audit/v1/E01-scaffolding/proposals/AGENTS.md +0 -66
- package/.savepoint/audit/v1/E01-scaffolding/proposals/Design.md +0 -210
- package/.savepoint/audit/v1/E01-scaffolding/proposals/epic-Design.md +0 -117
- package/.savepoint/audit/v1/E01-scaffolding/proposals/quality-review.md +0 -101
- package/.savepoint/audit/v1/E01-scaffolding/snapshot.md +0 -54
- package/.savepoint/audit/v1/E02-data-model/snapshot.md +0 -128
- package/.savepoint/audit/v1/E02-data-readers/proposals.md +0 -123
- package/.savepoint/audit/v1/E02-data-readers/snapshot.md +0 -54
- package/.savepoint/audit/v1/E03-board-tui-core/proposals.md +0 -146
- package/.savepoint/audit/v1/E03-board-tui-core/snapshot.md +0 -57
- package/.savepoint/audit/v1/E03-cli-foundation/snapshot.md +0 -106
- package/.savepoint/audit/v1/E04-board-components/proposals.md +0 -118
- package/.savepoint/audit/v1/E04-board-components/snapshot.md +0 -77
- package/.savepoint/audit/v1/E04-templates-and-prompts/snapshot.md +0 -115
- package/.savepoint/audit/v1/E05-init-command/snapshot.md +0 -125
- package/.savepoint/audit/v1/E05-phase-transitions/proposals.md +0 -83
- package/.savepoint/audit/v1/E05-phase-transitions/snapshot.md +0 -36
- package/.savepoint/audit/v1/E06-atari-noir-layout/proposals.md +0 -130
- package/.savepoint/audit/v1/E06-atari-noir-layout/snapshot.md +0 -84
- package/.savepoint/audit/v1/E06-tui-board/snapshot.md +0 -64
- package/.savepoint/audit/v1/E07-audit-pipeline/snapshot.md +0 -165
- package/.savepoint/audit/v1/E08-board-workflow-cleanup/snapshot.md +0 -65
- package/.savepoint/audit/v1.1/E02-cross-platform-compatibility/snapshot.md +0 -41
- package/.savepoint/audit/v1.1/E04-epic-navigation/snapshot.md +0 -48
- package/ink-cli-ui-design.zip +0 -0
- package/savepoint.exe +0 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: audit-findings
|
|
3
|
+
audited: 2026-05-05
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Audit Findings: E14 Structural Improvements
|
|
7
|
+
|
|
8
|
+
## Main Findings
|
|
9
|
+
|
|
10
|
+
Audit proposals were applied and E14 is closed as audited. The board model is grouped into focused embedded state structs, dead board helpers were removed, board and doctor now use consumer-side data-access interfaces, doctor orphan traversal goes through `Discover.ListRootDirs`, audit tab hidden-section filtering uses exact heading matches, `TaskStatus` has been removed in favor of the canonical column/status values, and shared Go test fixtures now live in `internal/testutil`.
|
|
11
|
+
|
|
12
|
+
The shell tokenizer follow-up was applied: empty quoted arguments such as `-run ""` are preserved, trailing backslashes are retained, and the branch tests were added. Router state was advanced to `epic-design` for `E15-hardening`, `E14-Detail.md` now has `status: audited`, and `.savepoint/Design.md` has `last_audited: v1.1/E14-structural-improvements`.
|
|
13
|
+
|
|
14
|
+
All seven task files include `## Context Files`; no `## Drift Notes` sections were found. The remaining review note is that `package.json` contains a version bump outside the explicit E14 task scope; it was left untouched as apparent release housekeeping.
|
|
15
|
+
|
|
16
|
+
## Code Style Review
|
|
17
|
+
|
|
18
|
+
- [x] One job per file - E14 keeps production responsibilities in board/data/doctor and moves shared test fixtures to `internal/testutil`.
|
|
19
|
+
- [x] One job per function - the touched functions remain small and named around a single behavior.
|
|
20
|
+
- [x] Test branches - `splitCommand` now covers empty quoted arguments and trailing escapes.
|
|
21
|
+
- [x] Types are documentation - consumer-side interfaces and `ColumnType` document the intended contracts.
|
|
22
|
+
- [x] Build, don't speculate - the implementation maps to the listed audit findings.
|
|
23
|
+
- [x] Errors at boundaries - data discovery and quality-gate execution continue returning boundary errors.
|
|
24
|
+
- [x] One source of truth - task status constants are consolidated under `ColumnType`.
|
|
25
|
+
- [x] Comments explain WHY - new comments describe contracts or compatibility, not line-by-line mechanics.
|
|
26
|
+
- [x] Content in data files - no new product copy is embedded in logic.
|
|
27
|
+
- [ ] Small diffs - residual note: the `package.json` version bump remains outside the E14 task scope and was left untouched.
|
|
28
|
+
|
|
29
|
+
## Proposed Changes
|
|
30
|
+
|
|
31
|
+
### Target File
|
|
32
|
+
internal/doctor/gates.go
|
|
33
|
+
|
|
34
|
+
### Replace
|
|
35
|
+
```go
|
|
36
|
+
func splitCommand(command string) []string {
|
|
37
|
+
var parts []string
|
|
38
|
+
current := strings.Builder{}
|
|
39
|
+
inDoubleQuote := false
|
|
40
|
+
inSingleQuote := false
|
|
41
|
+
|
|
42
|
+
for i := 0; i < len(command); i++ {
|
|
43
|
+
c := command[i]
|
|
44
|
+
|
|
45
|
+
if inSingleQuote {
|
|
46
|
+
if c == '\'' {
|
|
47
|
+
inSingleQuote = false
|
|
48
|
+
} else {
|
|
49
|
+
current.WriteByte(c)
|
|
50
|
+
}
|
|
51
|
+
continue
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if inDoubleQuote {
|
|
55
|
+
if c == '\\' && i+1 < len(command) {
|
|
56
|
+
next := command[i+1]
|
|
57
|
+
if next == '"' || next == '\\' || next == '$' || next == '`' {
|
|
58
|
+
i++
|
|
59
|
+
current.WriteByte(command[i])
|
|
60
|
+
continue
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if c == '"' {
|
|
64
|
+
inDoubleQuote = false
|
|
65
|
+
continue
|
|
66
|
+
}
|
|
67
|
+
current.WriteByte(c)
|
|
68
|
+
continue
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if c == '\\' && i+1 < len(command) {
|
|
72
|
+
i++
|
|
73
|
+
current.WriteByte(command[i])
|
|
74
|
+
continue
|
|
75
|
+
}
|
|
76
|
+
if c == '"' {
|
|
77
|
+
inDoubleQuote = true
|
|
78
|
+
continue
|
|
79
|
+
}
|
|
80
|
+
if c == '\'' {
|
|
81
|
+
inSingleQuote = true
|
|
82
|
+
continue
|
|
83
|
+
}
|
|
84
|
+
if c == ' ' {
|
|
85
|
+
if current.Len() > 0 {
|
|
86
|
+
parts = append(parts, current.String())
|
|
87
|
+
current.Reset()
|
|
88
|
+
}
|
|
89
|
+
continue
|
|
90
|
+
}
|
|
91
|
+
current.WriteByte(c)
|
|
92
|
+
}
|
|
93
|
+
if current.Len() > 0 {
|
|
94
|
+
parts = append(parts, current.String())
|
|
95
|
+
}
|
|
96
|
+
return parts
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### With
|
|
101
|
+
```go
|
|
102
|
+
func splitCommand(command string) []string {
|
|
103
|
+
var parts []string
|
|
104
|
+
current := strings.Builder{}
|
|
105
|
+
inDoubleQuote := false
|
|
106
|
+
inSingleQuote := false
|
|
107
|
+
tokenStarted := false
|
|
108
|
+
|
|
109
|
+
flush := func() {
|
|
110
|
+
if tokenStarted || current.Len() > 0 {
|
|
111
|
+
parts = append(parts, current.String())
|
|
112
|
+
current.Reset()
|
|
113
|
+
tokenStarted = false
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
for i := 0; i < len(command); i++ {
|
|
118
|
+
c := command[i]
|
|
119
|
+
|
|
120
|
+
if inSingleQuote {
|
|
121
|
+
tokenStarted = true
|
|
122
|
+
if c == '\'' {
|
|
123
|
+
inSingleQuote = false
|
|
124
|
+
} else {
|
|
125
|
+
current.WriteByte(c)
|
|
126
|
+
}
|
|
127
|
+
continue
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if inDoubleQuote {
|
|
131
|
+
tokenStarted = true
|
|
132
|
+
if c == '\\' && i+1 < len(command) {
|
|
133
|
+
next := command[i+1]
|
|
134
|
+
if next == '"' || next == '\\' || next == '$' || next == '`' {
|
|
135
|
+
i++
|
|
136
|
+
current.WriteByte(command[i])
|
|
137
|
+
continue
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if c == '"' {
|
|
141
|
+
inDoubleQuote = false
|
|
142
|
+
continue
|
|
143
|
+
}
|
|
144
|
+
current.WriteByte(c)
|
|
145
|
+
continue
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
switch c {
|
|
149
|
+
case '\\':
|
|
150
|
+
tokenStarted = true
|
|
151
|
+
if i+1 < len(command) {
|
|
152
|
+
i++
|
|
153
|
+
current.WriteByte(command[i])
|
|
154
|
+
} else {
|
|
155
|
+
current.WriteByte(c)
|
|
156
|
+
}
|
|
157
|
+
case '"':
|
|
158
|
+
tokenStarted = true
|
|
159
|
+
inDoubleQuote = true
|
|
160
|
+
case '\'':
|
|
161
|
+
tokenStarted = true
|
|
162
|
+
inSingleQuote = true
|
|
163
|
+
case ' ', '\t', '\n', '\r':
|
|
164
|
+
flush()
|
|
165
|
+
default:
|
|
166
|
+
tokenStarted = true
|
|
167
|
+
current.WriteByte(c)
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
flush()
|
|
171
|
+
return parts
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Target File
|
|
176
|
+
internal/doctor/gates_test.go
|
|
177
|
+
|
|
178
|
+
### Replace
|
|
179
|
+
```go
|
|
180
|
+
{"echo 'hello world'", []string{"echo", "hello world"}},
|
|
181
|
+
{"echo \"hello \\\"world\\\"\"", []string{"echo", "hello \"world\""}},
|
|
182
|
+
{"echo hello\\ world", []string{"echo", "hello world"}},
|
|
183
|
+
{"echo 'it''s'", []string{"echo", "its"}},
|
|
184
|
+
{"", nil},
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### With
|
|
188
|
+
```go
|
|
189
|
+
{"echo 'hello world'", []string{"echo", "hello world"}},
|
|
190
|
+
{"echo \"hello \\\"world\\\"\"", []string{"echo", "hello \"world\""}},
|
|
191
|
+
{"echo hello\\ world", []string{"echo", "hello world"}},
|
|
192
|
+
{"echo 'it''s'", []string{"echo", "its"}},
|
|
193
|
+
{"go test -run \"\" ./...", []string{"go", "test", "-run", "", "./..."}},
|
|
194
|
+
{"printf ''", []string{"printf", ""}},
|
|
195
|
+
{"echo trailing\\", []string{"echo", "trailing\\"}},
|
|
196
|
+
{"", nil},
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Target File
|
|
200
|
+
.savepoint/router.md
|
|
201
|
+
|
|
202
|
+
### Replace
|
|
203
|
+
```yaml
|
|
204
|
+
epic: E14
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### With
|
|
208
|
+
```yaml
|
|
209
|
+
epic: E14-structural-improvements
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Target File
|
|
213
|
+
.savepoint/Design.md
|
|
214
|
+
|
|
215
|
+
### Replace
|
|
216
|
+
```md
|
|
217
|
+
- **Audit remediation baseline** (v1.1 E13) centralizes frontmatter/body splitting and line-ending normalization in `internal/data`, uses typed sentinel errors for doctor repair suggestions, applies a configurable `quality_gates.gate_timeout`, removes tracked build artifacts from source control, adds `.golangci.yml`, and moves board filesystem reads/writes behind Bubble Tea command messages while preserving direct file I/O inside command helpers.
|
|
218
|
+
- **Agent audit workflow** is skill-driven, not a CLI pipeline. At `audit-pending`, a fresh audit agent writes one epic-local `E##-Audit.md`; the user reviews its Audit tab, then asks an agent to apply the admin proposal blocks, update the visible audit findings to reflect the applied outcome, and close the epic.
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### With
|
|
222
|
+
```md
|
|
223
|
+
- **Audit remediation baseline** (v1.1 E13) centralizes frontmatter/body splitting and line-ending normalization in `internal/data`, uses typed sentinel errors for doctor repair suggestions, applies a configurable `quality_gates.gate_timeout`, removes tracked build artifacts from source control, adds `.golangci.yml`, and moves board filesystem reads/writes behind Bubble Tea command messages while preserving direct file I/O inside command helpers.
|
|
224
|
+
- **Structural improvement baseline** (v1.1 E14) groups board `Model` fields into focused embedded state structs, defines consumer-side board/doctor data-access interfaces, routes doctor orphan discovery through `Discover.ListRootDirs`, renders audit-tab hidden sections via exact heading matches, improves quality-gate shell tokenization for quoted and escaped arguments, removes the separate `TaskStatus` enum in favor of `ColumnType`, and adds `internal/testutil` for shared Go test fixtures.
|
|
225
|
+
- **Agent audit workflow** is skill-driven, not a CLI pipeline. At `audit-pending`, a fresh audit agent writes one epic-local `E##-Audit.md`; the user reviews its Audit tab, then asks an agent to apply the admin proposal blocks, update the visible audit findings to reflect the applied outcome, and close the epic.
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Target File
|
|
229
|
+
AGENTS.md
|
|
230
|
+
|
|
231
|
+
### Replace
|
|
232
|
+
```md
|
|
233
|
+
| `internal/data/` | Task/router models, frontmatter parsing/splitting, lifecycle validation/defaulting, discovery, canonical write helpers |
|
|
234
|
+
| `internal/styles/` | Atari-Noir palette, TUI styles |
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### With
|
|
238
|
+
```md
|
|
239
|
+
| `internal/data/` | Task/router models, frontmatter parsing/splitting, lifecycle validation/defaulting, discovery including root-dir traversal, unified task status constants, canonical write helpers |
|
|
240
|
+
| `internal/testutil/` | Shared Go test fixtures and filesystem helpers for internal package tests |
|
|
241
|
+
| `internal/styles/` | Atari-Noir palette, TUI styles |
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Target File
|
|
245
|
+
.savepoint/releases/v1.1/epics/E14-structural-improvements/E14-Detail.md
|
|
246
|
+
|
|
247
|
+
### Replace
|
|
248
|
+
```md
|
|
249
|
+
**Out of scope:**
|
|
250
|
+
- New UI features or commands
|
|
251
|
+
- Audit Phase 3 hardening items (separate epic E15)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### With
|
|
255
|
+
```md
|
|
256
|
+
**Out of scope:**
|
|
257
|
+
- New UI features or commands
|
|
258
|
+
- Audit Phase 3 hardening items (separate epic E15)
|
|
259
|
+
|
|
260
|
+
## Implemented As
|
|
261
|
+
|
|
262
|
+
- `Model` grouping landed as embedded state structs in `internal/board/model.go`, preserving existing call sites while separating view, data, navigation, epic, release, and data-access state.
|
|
263
|
+
- Consumer-side interfaces landed in `internal/board/interfaces.go` and `internal/doctor/interfaces.go`; concrete `internal/data` types satisfy them without data-layer changes.
|
|
264
|
+
- `TaskStatus` was removed. `ColumnType` is the canonical task lifecycle type, while `data.Task.Status` remains a string mirror for parsed frontmatter and board glyph compatibility.
|
|
265
|
+
- `internal/testutil` was added for shared test filesystem and fixture helpers across board, doctor, data, and init tests.
|
|
266
|
+
- Audit follow-up before close: preserve empty quoted shell arguments in `splitCommand` and normalize router epic from `E14` to `E14-structural-improvements`.
|
|
267
|
+
```
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: epic-design
|
|
3
|
+
status: audited
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# E14: Phase 2 — Structural Improvements
|
|
7
|
+
|
|
8
|
+
## Purpose
|
|
9
|
+
|
|
10
|
+
Address the remaining Phase 2 findings from the consolidated codebase audit (Opus 4.6 + GLM 5.1) that were not covered by E13: model decomposition, consumer-side interfaces, and structural Medium/Low items flagged by both audits.
|
|
11
|
+
|
|
12
|
+
## What this epic adds
|
|
13
|
+
|
|
14
|
+
- Model fields grouped into focused sub-structs for maintainability
|
|
15
|
+
- Consumer-side interfaces for data-access types enabling test mocking
|
|
16
|
+
- Discover-based traversal in CheckOrphans replacing raw os.ReadDir
|
|
17
|
+
- Exact heading matching in epic_panel replacing fragile substrings
|
|
18
|
+
- Improved shell tokenization with quote/escape support
|
|
19
|
+
- Consolidated ColumnType/TaskStatus enumeration removing syncTaskStatus
|
|
20
|
+
- Shared testutil package reducing fixture duplication
|
|
21
|
+
|
|
22
|
+
## Components
|
|
23
|
+
|
|
24
|
+
| Module | Purpose |
|
|
25
|
+
|--------|---------|
|
|
26
|
+
| `internal/board/model.go` | Group Model fields into sub-structs |
|
|
27
|
+
| `internal/board/board.go` | Remove newProgramModel and loadAllTasks dead code |
|
|
28
|
+
| `internal/board/` + `internal/doctor/` | Introduce consumer-side interfaces |
|
|
29
|
+
| `internal/data/discover.go` | Add ListRootDirs method |
|
|
30
|
+
| `internal/data/task.go` | Unify ColumnType/TaskStatus |
|
|
31
|
+
| `internal/board/transitions.go` | Remove syncTaskStatus |
|
|
32
|
+
| `internal/board/epic_panel.go` | Replace substring heading matching |
|
|
33
|
+
| `internal/doctor/gates.go` | Improve splitCommand tokenizer |
|
|
34
|
+
| `internal/doctor/checks.go` | Route CheckOrphans through Discover |
|
|
35
|
+
| `internal/testutil/` | New package for shared test fixtures |
|
|
36
|
+
|
|
37
|
+
## Boundaries
|
|
38
|
+
|
|
39
|
+
**In scope:**
|
|
40
|
+
- All Phase 2 audit findings not covered by E13 (Model grouping, interfaces)
|
|
41
|
+
- Medium/Low audit findings that fit the structural theme (M4, M7, M9, L1, L9)
|
|
42
|
+
- Dead code removal (M2, L3)
|
|
43
|
+
|
|
44
|
+
**Out of scope:**
|
|
45
|
+
- New UI features or commands
|
|
46
|
+
- Audit Phase 3 hardening items (separate epic E15)
|
|
47
|
+
|
|
48
|
+
## Implemented As
|
|
49
|
+
|
|
50
|
+
- `Model` grouping landed as embedded state structs in `internal/board/model.go`, preserving existing call sites while separating view, data, navigation, epic, release, and data-access state.
|
|
51
|
+
- Consumer-side interfaces landed in `internal/board/interfaces.go` and `internal/doctor/interfaces.go`; concrete `internal/data` types satisfy them without data-layer changes.
|
|
52
|
+
- `TaskStatus` was removed. `ColumnType` is the canonical task lifecycle type, while `data.Task.Status` remains a string mirror for parsed frontmatter and board glyph compatibility.
|
|
53
|
+
- `internal/testutil` was added for shared test filesystem and fixture helpers across board, doctor, data, and init tests.
|
|
54
|
+
- Audit closeout preserved empty quoted shell arguments in `splitCommand` and advanced the router to `E15-hardening`.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E14-structural-improvements/T001-group-model
|
|
3
|
+
status: done
|
|
4
|
+
objective: Group the 27-field Model struct into focused sub-structs; delete newProgramModel and loadAllTasks
|
|
5
|
+
depends_on: []
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# T001: Group Model Fields Into Sub-structs and Remove Dead Code
|
|
9
|
+
|
|
10
|
+
## Context Files
|
|
11
|
+
|
|
12
|
+
- `internal/board/model.go` — Model struct with 27 flat fields
|
|
13
|
+
- `internal/board/board.go:32-34` — newProgramModel with hardcoded slug
|
|
14
|
+
- `internal/board/board.go:125-128` — loadAllTasks dead wrapper
|
|
15
|
+
- `internal/board/board_test.go:13` — references newProgramModel
|
|
16
|
+
|
|
17
|
+
## Acceptance Criteria
|
|
18
|
+
|
|
19
|
+
- [x] Model fields grouped into sub-structs (e.g. ViewConfig, NavigationState, DataState)
|
|
20
|
+
- [x] newProgramModel() removed from board.go
|
|
21
|
+
- [x] loadAllTasks() removed from board.go
|
|
22
|
+
- [x] board_test.go updated to not reference removed functions
|
|
23
|
+
- [x] `go test ./...` passes with no regressions
|
|
24
|
+
|
|
25
|
+
## Implementation Plan
|
|
26
|
+
|
|
27
|
+
- [x] Identify logical field groups in Model struct
|
|
28
|
+
- [x] Extract sub-struct type definitions
|
|
29
|
+
- [x] Update all field references across the board package
|
|
30
|
+
- [x] Delete newProgramModel() and loadAllTasks()
|
|
31
|
+
- [x] Update board_test.go to construct Model directly
|
|
32
|
+
- [x] Run `make build && make test`
|
|
33
|
+
|
|
34
|
+
## Context Log
|
|
35
|
+
|
|
36
|
+
- Files read: `.savepoint/router.md`, `.savepoint/releases/v1.1/epics/E14-structural-improvements/E14-Detail.md`, `.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T001-group-model.md`, `agent-skills/savepoint-build-task/SKILL.md`, `internal/board/model.go`, `internal/board/board.go`, `internal/board/board_test.go`
|
|
37
|
+
- Files edited: `.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T001-group-model.md`, `internal/board/model.go`, `internal/board/board.go`, `internal/board/board_test.go`
|
|
38
|
+
- Tokens used: approximately 16k
|
|
39
|
+
- Quality gates: `make build` passed; `make test` passed. Initial sandboxed runs hit Go build-cache access errors, then passed with approved escalation.
|
package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T002-data-interfaces.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E14-structural-improvements/T002-data-interfaces
|
|
3
|
+
status: done
|
|
4
|
+
objective: Define consumer-side interfaces for stateless data types and accept them in board/doctor constructors
|
|
5
|
+
depends_on: []
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# T002: Extract Consumer-Side Interfaces for Data-Access Types
|
|
9
|
+
|
|
10
|
+
## Context Files
|
|
11
|
+
|
|
12
|
+
- `internal/data/discover.go` — NewDiscover() returns *Discover
|
|
13
|
+
- `internal/data/parser.go` — NewParser() returns *Parser
|
|
14
|
+
- `internal/data/config.go` — NewConfigReader() returns *ConfigReader
|
|
15
|
+
- `internal/data/router.go` — NewRouterReader() returns *RouterReader
|
|
16
|
+
- `internal/board/board.go` — calls data.NewDiscover() directly
|
|
17
|
+
- `internal/doctor/checks.go` — calls data.NewDiscover() directly
|
|
18
|
+
- `internal/board/model.go` — NewModel() signature
|
|
19
|
+
|
|
20
|
+
## Acceptance Criteria
|
|
21
|
+
|
|
22
|
+
- [x] Consumer-side interfaces defined for taskDiscoverer, taskParser, configReader, routerReader
|
|
23
|
+
- [x] board.NewModel() accepts interfaces instead of calling constructors directly
|
|
24
|
+
- [x] doctor.CheckXxx functions accept interfaces instead of calling constructors directly
|
|
25
|
+
- [x] Existing concrete types satisfy the interfaces with no changes to internal/data
|
|
26
|
+
- [x] Tests can inject mock implementations
|
|
27
|
+
- [x] `go test ./...` passes with no regressions
|
|
28
|
+
|
|
29
|
+
## Implementation Plan
|
|
30
|
+
|
|
31
|
+
- [x] Define interfaces in board/types.go or at each consumer site
|
|
32
|
+
- [x] Update NewModel signature to accept interfaces with zero-value defaults
|
|
33
|
+
- [x] Update CheckOrphans, CheckDependencies, CheckRouter signatures
|
|
34
|
+
- [x] Add doc comments documenting the interface contracts
|
|
35
|
+
- [x] Run `make build && make test`
|
|
36
|
+
|
|
37
|
+
## Context Log
|
|
38
|
+
|
|
39
|
+
- Files read: `internal/data/discover.go`, `internal/data/parser.go`, `internal/data/config.go`, `internal/data/router.go`, `internal/board/board.go`, `internal/doctor/checks.go`, `internal/board/model.go`, related board/doctor tests.
|
|
40
|
+
- Files edited: `internal/board/interfaces.go`, `internal/board/model.go`, `internal/board/board.go`, `internal/board/tui.go`, `internal/board/io.go`, `internal/board/update.go`, `internal/board/watch.go`, `internal/board/interfaces_test.go`, `internal/doctor/interfaces.go`, `internal/doctor/checks.go`, `internal/doctor/gates.go`, `internal/doctor/interfaces_test.go`.
|
|
41
|
+
- Token estimate: ~18k.
|
|
42
|
+
- Quality gates: `go test ./internal/board ./internal/doctor` passed; `make build && make test` passed (`go test ./...` all packages).
|
package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T003-discover-orphans.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E14-structural-improvements/T003-discover-orphans
|
|
3
|
+
status: done
|
|
4
|
+
objective: Add ListRootDirs to Discover and use it in CheckOrphans instead of direct os.ReadDir
|
|
5
|
+
depends_on: []
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# T003: Route CheckOrphans Through Discover
|
|
9
|
+
|
|
10
|
+
## Context Files
|
|
11
|
+
|
|
12
|
+
- `internal/doctor/checks.go:488-514` — CheckOrphans uses os.ReadDir directly
|
|
13
|
+
- `internal/data/discover.go` — existing ListReleases, ListEpics, ListTasks methods
|
|
14
|
+
|
|
15
|
+
## Acceptance Criteria
|
|
16
|
+
|
|
17
|
+
- [x] ListRootDirs(releasesPath string) ([]string, error) added to Discover
|
|
18
|
+
- [x] CheckOrphans uses data.Discover for filesystem traversal
|
|
19
|
+
- [x] `go test ./...` passes with no regressions
|
|
20
|
+
|
|
21
|
+
## Implementation Plan
|
|
22
|
+
|
|
23
|
+
- [x] Add ListRootDirs method to Discover in discover.go
|
|
24
|
+
- [x] Add tests for ListRootDirs in discover_test.go
|
|
25
|
+
- [x] Refactor CheckOrphans to use Discover instead of os.ReadDir
|
|
26
|
+
- [x] Run `make build && make test`
|
|
27
|
+
|
|
28
|
+
## Context Log
|
|
29
|
+
|
|
30
|
+
- Files read: `internal/doctor/checks.go`, `internal/data/discover.go`, `internal/data/discover_test.go`, `internal/doctor/interfaces.go`.
|
|
31
|
+
- Files edited: `internal/data/discover.go`, `internal/data/discover_test.go`, `internal/doctor/interfaces.go`, `internal/doctor/interfaces_test.go`, `internal/doctor/checks.go`.
|
|
32
|
+
- Token estimate: ~8k.
|
|
33
|
+
- Quality gates: `go test ./internal/data ./internal/doctor` passed; `make build && make test` passed (`go test ./...` all packages).
|
package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T004-epic-panel-headings.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E14-structural-improvements/T004-epic-panel-headings
|
|
3
|
+
status: done
|
|
4
|
+
objective: Replace substring heading matching in epic_panel with exact heading match and configurable blocklist
|
|
5
|
+
depends_on: []
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# T004: Replace Ad-hoc Heading Matching in epic_panel
|
|
9
|
+
|
|
10
|
+
## Context Files
|
|
11
|
+
|
|
12
|
+
- `internal/board/epic_panel.go:131-136` — substring heading detection in epicAuditBody
|
|
13
|
+
|
|
14
|
+
## Acceptance Criteria
|
|
15
|
+
|
|
16
|
+
- [x] Heading filtering uses exact match against a blocklist (not substring)
|
|
17
|
+
- [x] Blocklist is configurable via a named variable
|
|
18
|
+
- [x] Existing behavior preserved for all known audit headings
|
|
19
|
+
- [x] `go test ./...` passes with no regressions
|
|
20
|
+
|
|
21
|
+
## Implementation Plan
|
|
22
|
+
|
|
23
|
+
- [x] Identify current substring logic and blocklist
|
|
24
|
+
- [x] Replace with exact heading matching
|
|
25
|
+
- [x] Rename/restructure the blocklist variable
|
|
26
|
+
- [x] Update tests if applicable
|
|
27
|
+
- [x] Run `make build && make test`
|
|
28
|
+
|
|
29
|
+
## Context Log
|
|
30
|
+
|
|
31
|
+
- Files read: `internal/board/epic_panel.go`, `internal/board/epic_panel_test.go`.
|
|
32
|
+
- Files edited: `internal/board/epic_panel.go`, `internal/board/epic_panel_test.go`.
|
|
33
|
+
- Token estimate: ~6k.
|
|
34
|
+
- Quality gates: `go test ./internal/board` passed; `make build && make test` passed (`go test ./...` all packages).
|
|
35
|
+
- TUI note: could not press `p` from the agent environment; router already points at this task as current priority.
|
package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T005-shell-tokenization.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E14-structural-improvements/T005-shell-tokenization
|
|
3
|
+
status: done
|
|
4
|
+
objective: Improve splitCommand to handle single quotes and backslash-escapes, or document limitations
|
|
5
|
+
depends_on: []
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# T005: Improve Shell Tokenization in Gates
|
|
9
|
+
|
|
10
|
+
## Context Files
|
|
11
|
+
|
|
12
|
+
- `internal/doctor/gates.go:125` — splitCommand function (naïve shell tokenizer)
|
|
13
|
+
|
|
14
|
+
## Acceptance Criteria
|
|
15
|
+
|
|
16
|
+
- [x] splitCommand handles single-quote grouping or limitation is documented
|
|
17
|
+
- [x] splitCommand handles backslash-escaped characters or limitation is documented
|
|
18
|
+
- [x] Existing double-quote handling preserved
|
|
19
|
+
- [x] `go test ./...` passes with no regressions
|
|
20
|
+
|
|
21
|
+
## Implementation Plan
|
|
22
|
+
|
|
23
|
+
- [x] Review current splitCommand implementation
|
|
24
|
+
- [x] Add single-quote parsing
|
|
25
|
+
- [x] Add backslash-escape handling
|
|
26
|
+
- [x] Update existing tests and add new test cases
|
|
27
|
+
- [x] Run `make build && make test`
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E14-structural-improvements/T006-unify-enums
|
|
3
|
+
status: done
|
|
4
|
+
objective: Consolidate ColumnType and TaskStatus into a single status type and remove syncTaskStatus
|
|
5
|
+
depends_on: []
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# T006: Unify ColumnType and TaskStatus Enumerations
|
|
9
|
+
|
|
10
|
+
## Context Files
|
|
11
|
+
|
|
12
|
+
- `internal/data/task.go:13-36` — ColumnType and TaskStatus parallel definitions
|
|
13
|
+
- `internal/board/transitions.go:57-59` — syncTaskStatus manually syncs both enums
|
|
14
|
+
- Multiple consumer files reference Task.Status or Task.Column
|
|
15
|
+
|
|
16
|
+
## Acceptance Criteria
|
|
17
|
+
|
|
18
|
+
- [x] ColumnType and TaskStatus consolidated into a single type
|
|
19
|
+
- [x] syncTaskStatus removed from transitions.go
|
|
20
|
+
- [x] All consumer references updated
|
|
21
|
+
- [x] `go test ./...` passes with no regressions
|
|
22
|
+
|
|
23
|
+
## Implementation Plan
|
|
24
|
+
|
|
25
|
+
- [x] Choose the surviving type (ColumnType has wider usage)
|
|
26
|
+
- [x] Merge TaskStatus constants into ColumnType
|
|
27
|
+
- [x] Remove syncTaskStatus and inline any callers
|
|
28
|
+
- [x] Update all references across the codebase
|
|
29
|
+
- [x] Run `make build && make test`
|
package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T007-testutil-package.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E14-structural-improvements/T007-testutil-package
|
|
3
|
+
status: done
|
|
4
|
+
objective: Create internal/testutil with shared fixtures to reduce duplication across board/doctor/data/init tests
|
|
5
|
+
depends_on: []
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# T007: Consolidate Test Helpers Into Testutil Package
|
|
9
|
+
|
|
10
|
+
## Context Files
|
|
11
|
+
|
|
12
|
+
- All test files across internal/board, internal/doctor, internal/data, internal/init
|
|
13
|
+
- Common fixture patterns: temp directory creation, task file writing, config scaffolding
|
|
14
|
+
|
|
15
|
+
## Acceptance Criteria
|
|
16
|
+
|
|
17
|
+
- [x] internal/testutil package created
|
|
18
|
+
- [x] Common fixture helpers extracted and shared
|
|
19
|
+
- [x] All existing tests still pass after refactoring to use shared helpers
|
|
20
|
+
- [x] No unnecessary exports in the public API
|
|
21
|
+
- [x] `go test ./...` passes with no regressions
|
|
22
|
+
|
|
23
|
+
## Implementation Plan
|
|
24
|
+
|
|
25
|
+
- [x] Survey existing test helpers for duplication patterns
|
|
26
|
+
- [x] Create internal/testutil with shared fixture functions
|
|
27
|
+
- [x] Refactor each test package to use shared helpers
|
|
28
|
+
- [x] Run `make build && make test`
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: epic-design
|
|
3
|
+
status: planned
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# E15: Phase 3 — Hardening
|
|
7
|
+
|
|
8
|
+
## Purpose
|
|
9
|
+
|
|
10
|
+
Address the remaining Phase 3 findings from the consolidated codebase audit (Opus 4.6 + GLM 5.1) that were not covered by E13: benchmarks, fuzzing, debug instrumentation, and hardening Medium/Low items.
|
|
11
|
+
|
|
12
|
+
## What this epic adds
|
|
13
|
+
|
|
14
|
+
- Benchmark tests for render functions
|
|
15
|
+
- Fuzz targets for YAML frontmatter parsing
|
|
16
|
+
- --debug flag and SAVEPOINT_DEBUG environment variable
|
|
17
|
+
- Distribution checksums in buildtool
|
|
18
|
+
- Windows build targets in buildtool
|
|
19
|
+
- Abbreviation-aware checklist sentence splitting
|
|
20
|
+
- Root-level test relocation and audit allowlist consolidation
|
|
21
|
+
|
|
22
|
+
## Components
|
|
23
|
+
|
|
24
|
+
| Module | Purpose |
|
|
25
|
+
|--------|---------|
|
|
26
|
+
| `internal/board/view_test.go` | Add render benchmarks |
|
|
27
|
+
| `internal/data/parser_test.go` | Add fuzz targets |
|
|
28
|
+
| `cmd/main.go` | Add --debug / SAVEPOINT_DEBUG |
|
|
29
|
+
| `internal/buildtool/main.go` | Add checksums, Windows targets |
|
|
30
|
+
| `internal/board/detail.go` | Fix abbreviation handling |
|
|
31
|
+
| `internal/board/epic_panel.go` | Extract allowlist constant |
|
|
32
|
+
| `agent_skills_test.go` | Move to cmd_test package |
|
|
33
|
+
|
|
34
|
+
## Boundaries
|
|
35
|
+
|
|
36
|
+
**In scope:**
|
|
37
|
+
- All Phase 3 audit findings not covered by E13 (benchmarks, fuzz, debug flag)
|
|
38
|
+
- Medium/Low hardening items (M10, L7, L10, L11, L12)
|
|
39
|
+
|
|
40
|
+
**Out of scope:**
|
|
41
|
+
- CI/CD configuration — separate concern
|
|
42
|
+
- New UI features or commands
|
|
43
|
+
- Structural improvements (separate epic E14)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E15-hardening/T001-benchmarks
|
|
3
|
+
status: planned
|
|
4
|
+
objective: Add benchmark tests for board render functions
|
|
5
|
+
depends_on: []
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# T001: Add Benchmark Tests for Render Functions
|
|
9
|
+
|
|
10
|
+
## Context Files
|
|
11
|
+
|
|
12
|
+
- `internal/board/view.go` — renderColumn, renderColumnHeaders
|
|
13
|
+
- `internal/board/card.go` — RenderCard
|
|
14
|
+
- `internal/board/column.go` — RenderColumn
|
|
15
|
+
- `internal/board/layout.go` — layout calculations
|
|
16
|
+
|
|
17
|
+
## Acceptance Criteria
|
|
18
|
+
|
|
19
|
+
- [ ] Benchmark added for RenderCard with varied content widths
|
|
20
|
+
- [ ] Benchmark added for renderColumn with multiple tasks
|
|
21
|
+
- [ ] Benchmark added for layout calculations at different widths
|
|
22
|
+
- [ ] Benchmarks are repeatable with consistent results
|
|
23
|
+
- [ ] Benchmarks don't modify package state
|
|
24
|
+
- [ ] `go test -bench=. ./internal/board/` runs without errors
|
|
25
|
+
|
|
26
|
+
## Implementation Plan
|
|
27
|
+
|
|
28
|
+
- [ ] Add benchmark functions in view_test.go, card_test.go, column_test.go
|
|
29
|
+
- [ ] Create test data with representative task mixtures
|
|
30
|
+
- [ ] Run benchmarks and document baseline
|
|
31
|
+
- [ ] Run `make build && make test`
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: E15-hardening/T002-fuzz-targets
|
|
3
|
+
status: planned
|
|
4
|
+
objective: Add fuzz targets for YAML frontmatter parsing round-trip
|
|
5
|
+
depends_on: []
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# T002: Add Fuzz Targets for YAML Frontmatter Parsing
|
|
9
|
+
|
|
10
|
+
## Context Files
|
|
11
|
+
|
|
12
|
+
- `internal/data/parser.go` — extractFrontmatter
|
|
13
|
+
- `internal/data/write.go` — WriteTaskStatus, SplitFrontmatterBody
|
|
14
|
+
- `internal/data/parser_test.go` — existing tests
|
|
15
|
+
|
|
16
|
+
## Acceptance Criteria
|
|
17
|
+
|
|
18
|
+
- [ ] Fuzz target added for extractFrontmatter round-trip
|
|
19
|
+
- [ ] Fuzz target added for WriteTaskStatus round-trip (write then re-parse)
|
|
20
|
+
- [ ] Fuzz targets exercise edge cases (empty content, malformed YAML, unicode)
|
|
21
|
+
- [ ] `go test -fuzz=. ./internal/data/` runs without errors
|
|
22
|
+
|
|
23
|
+
## Implementation Plan
|
|
24
|
+
|
|
25
|
+
- [ ] Create fuzz_test.go in internal/data with fuzz targets
|
|
26
|
+
- [ ] Define corpus seed inputs from known edge cases
|
|
27
|
+
- [ ] Run fuzz targets for short duration to verify stability
|
|
28
|
+
- [ ] Run `make build && make test`
|