savepoint 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/.github/workflows/ci.yml +20 -0
  2. package/.savepoint/Design.md +4 -3
  3. package/.savepoint/releases/v1.1/epics/E15-hardening/E15-Audit.md +272 -0
  4. package/.savepoint/releases/v1.1/epics/E15-hardening/E15-Detail.md +25 -8
  5. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T001-benchmarks.md +11 -11
  6. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T002-fuzz-targets.md +15 -9
  7. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T003-debug-flag.md +11 -11
  8. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T004-dist-checksums.md +9 -9
  9. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T005-windows-targets.md +11 -11
  10. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T006-abbreviation-splitting.md +9 -9
  11. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T007-root-test-allowlist.md +15 -10
  12. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T008-ci-and-release-automation.md +46 -0
  13. package/.savepoint/router.md +4 -4
  14. package/AGENTS.md +2 -2
  15. package/Makefile +3 -1
  16. package/agent_skills_test.go +1 -1
  17. package/internal/board/board.go +4 -0
  18. package/internal/board/card_test.go +33 -0
  19. package/internal/board/column.go +43 -14
  20. package/internal/board/column_test.go +71 -0
  21. package/internal/board/debug.go +26 -0
  22. package/internal/board/debug_test.go +108 -0
  23. package/internal/board/detail.go +33 -0
  24. package/internal/board/detail_test.go +48 -0
  25. package/internal/board/epic_panel.go +2 -0
  26. package/internal/board/update.go +19 -0
  27. package/internal/board/update_test.go +27 -0
  28. package/internal/board/view_test.go +62 -0
  29. package/internal/board/watch.go +6 -0
  30. package/internal/buildtool/main.go +44 -6
  31. package/internal/buildtool/main_test.go +178 -0
  32. package/internal/data/fuzz_test.go +75 -0
  33. package/internal/data/parser.go +3 -2
  34. package/internal/data/testdata/fuzz/FuzzSplitFrontmatterBody/68eb66b0fe91e7e3 +2 -0
  35. package/internal/data/write.go +9 -6
  36. package/main.go +24 -5
  37. package/package.json +1 -1
  38. package/savepoint +0 -0
  39. /package/project-audit/{audit_report_opus_4.6 → audit_report_opus_4.6.md} +0 -0
@@ -0,0 +1,20 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ branches: [master]
8
+
9
+ jobs:
10
+ ci:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - uses: actions/setup-go@v5
16
+ with:
17
+ go-version: '1.26'
18
+ check-latest: true
19
+
20
+ - run: make ci
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  type: project-design
3
3
  status: active
4
- last_audited: v1.1/E14-structural-improvements
4
+ last_audited: v1.1/E15-hardening
5
5
  ---
6
6
 
7
7
  # Savepoint — System Architecture
@@ -27,6 +27,7 @@ last_audited: v1.1/E14-structural-improvements
27
27
  - **Doctor command** (`savepoint doctor`, `savepoint doctor --epic E##`) runs read-only integrity diagnostics for config, router state, release/epic/task structure, frontmatter validity, acceptance criteria presence, dependencies, duplicate task IDs, stale audit files, orphaned task IDs, and configured quality gates. It prints a human-readable report with repair suggestions and exits 0 when clean, 1 when problems are diagnosed, and 2 for internal or invocation failures.
28
28
  - **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.
29
29
  - **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.
30
+ - **Hardening baseline** (v1.1 E15) adds board render/layout benchmarks, data frontmatter fuzz targets, debug logging via CLI `--debug` or `SAVEPOINT_DEBUG`, abbreviation-aware task checklist sentence splitting, root test package isolation, documented audit-tab hidden-section allowlisting, repo-local CI, `make ci`, distribution SHA256 checksums, and Windows amd64/arm64 build outputs.
30
31
  - **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.
31
32
 
32
33
  ## 2. Directory layout
@@ -178,8 +179,8 @@ All failure modes are diagnosed by `savepoint doctor`. Doctor diagnoses and prop
178
179
  - **License:** MIT.
179
180
  - **Runtime:** Go CLI binary. Source builds with `go build`; tests run with `go test ./...`.
180
181
  - **Local build:** `make build` delegates to `internal/buildtool`, builds `savepoint` or `savepoint.exe`, and injects `main.version` from `VERSION` or the latest git tag.
181
- - **Cross-platform builds:** `make build-all` cross-compiles linux-amd64, linux-arm64, darwin-amd64, and darwin-arm64 raw binaries into `dist/{platform}-{arch}/savepoint`.
182
- - **Artifacts:** `make dist` creates versioned `.tar.gz` archives in `dist/` for the Linux and Darwin targets using Go archive APIs, not shell `tar`.
182
+ - **Cross-platform builds:** `make build-all` cross-compiles linux-amd64, linux-arm64, darwin-amd64, darwin-arm64, windows-amd64, and windows-arm64 raw binaries into `dist/{platform}-{arch}/savepoint` or `savepoint.exe` for Windows. `make ci` runs the repo-local verification sequence used by CI.
183
+ - **Artifacts:** `make dist` creates versioned `.tar.gz` archives in `dist/` for Linux, Darwin, and Windows targets using Go archive APIs, not shell `tar`, and writes SHA256 hashes to `dist/checksums.txt`.
183
184
  - **Smoke validation:** `make smoke-test` builds the local binary and runs `--version` as a headless exit-0 check.
184
185
  - **No telemetry.** Ever.
185
186
 
@@ -0,0 +1,272 @@
1
+ ---
2
+ type: audit-findings
3
+ audited: 2026-05-06
4
+ ---
5
+ # Audit Findings: E15 Phase 3 - Hardening
6
+
7
+ ## Main Findings
8
+
9
+ Applied the E15 audit proposals and closed the epic as audited.
10
+
11
+ - Fixed the Windows archive packaging issue: Windows tarballs now preserve `savepoint.exe` as the archive member name instead of extracting as `savepoint`.
12
+ - Added a regression test covering the Windows archive member name.
13
+ - Reconciled E15 documentation drift in `Design.md`, `AGENTS.md`, and `E15-Detail.md`.
14
+ - Marked `E15-Detail.md` as `status: audited`.
15
+ - Updated `Design.md` `last_audited` to `v1.1/E15-hardening`.
16
+ - Advanced router state to `epic-design` with no active epic because there are no later unarchived epics in v1.1.
17
+
18
+ Verification after applying proposals:
19
+
20
+ - `go test ./internal/buildtool`
21
+ - `make build`
22
+ - `make test`
23
+ - `make ci`
24
+
25
+ No remaining audit blockers are known. The `## Proposed Changes` section remains below as the apply trace.
26
+
27
+ ## Code Style Review
28
+
29
+ - [x] One job per file - E15 changes stayed within board rendering/debug, data parsing/fuzzing, buildtool packaging, CI, and task metadata.
30
+ - [x] One job per function - new helpers such as `executableName`, `writeChecksums`, `stripDebugFlag`, `debugf`, and abbreviation checks are narrowly scoped.
31
+ - [x] Test branches - Windows build output and Windows archive member naming are now covered.
32
+ - [x] Types document intent - existing Go types and small helper APIs remain explicit enough for this scope.
33
+ - [x] Build only what is needed - no speculative runtime features were added beyond E15 scope.
34
+ - [x] Handle errors at boundaries - buildtool, filesystem, checksum, fuzz, and parser errors are propagated with context.
35
+ - [x] One source of truth - target lists and executable naming are centralized in buildtool; the proposed archive fix reuses that source.
36
+ - [x] Comments explain why - new comments document abbreviation suppression and audit-tab hidden sections rather than restating obvious code.
37
+ - [x] Content lives in data - workflow and architecture copy remain in markdown; no new product copy was embedded in logic.
38
+ - [x] Small diffs - most changes are localized, test-backed additions.
39
+
40
+ ## Proposed Changes
41
+
42
+ ### Target File
43
+ internal/buildtool/main.go
44
+
45
+ ### Replace
46
+ ```go
47
+ if err := writeTarGz(archive, source, "savepoint"); err != nil {
48
+ ```
49
+
50
+ ### With
51
+ ```go
52
+ if err := writeTarGz(archive, source, executableName(target.os)); err != nil {
53
+ ```
54
+
55
+ ### Target File
56
+ internal/buildtool/main_test.go
57
+
58
+ ### Replace
59
+ ```go
60
+ import (
61
+ "crypto/sha256"
62
+ "encoding/hex"
63
+ "os"
64
+ "path/filepath"
65
+ "runtime"
66
+ "strings"
67
+ "testing"
68
+ )
69
+ ```
70
+
71
+ ### With
72
+ ```go
73
+ import (
74
+ "archive/tar"
75
+ "compress/gzip"
76
+ "crypto/sha256"
77
+ "encoding/hex"
78
+ "io"
79
+ "os"
80
+ "path/filepath"
81
+ "runtime"
82
+ "strings"
83
+ "testing"
84
+ )
85
+ ```
86
+
87
+ ### Target File
88
+ internal/buildtool/main_test.go
89
+
90
+ ### Replace
91
+ ```go
92
+ func TestExecutableName(t *testing.T) {
93
+ if got := executableName("windows"); got != "savepoint.exe" {
94
+ t.Errorf("executableName(windows) = %q, want savepoint.exe", got)
95
+ }
96
+ if got := executableName("linux"); got != "savepoint" {
97
+ t.Errorf("executableName(linux) = %q, want savepoint", got)
98
+ }
99
+ if got := executableName("darwin"); got != "savepoint" {
100
+ t.Errorf("executableName(darwin) = %q, want savepoint", got)
101
+ }
102
+ }
103
+ ```
104
+
105
+ ### With
106
+ ```go
107
+ func TestExecutableName(t *testing.T) {
108
+ if got := executableName("windows"); got != "savepoint.exe" {
109
+ t.Errorf("executableName(windows) = %q, want savepoint.exe", got)
110
+ }
111
+ if got := executableName("linux"); got != "savepoint" {
112
+ t.Errorf("executableName(linux) = %q, want savepoint", got)
113
+ }
114
+ if got := executableName("darwin"); got != "savepoint" {
115
+ t.Errorf("executableName(darwin) = %q, want savepoint", got)
116
+ }
117
+ }
118
+
119
+ func TestWriteTarGzPreservesWindowsExecutableName(t *testing.T) {
120
+ dir := t.TempDir()
121
+ source := filepath.Join(dir, "savepoint.exe")
122
+ if err := os.WriteFile(source, []byte("binary"), 0o755); err != nil {
123
+ t.Fatal(err)
124
+ }
125
+
126
+ archive := filepath.Join(dir, "savepoint-windows-amd64.tar.gz")
127
+ if err := writeTarGz(archive, source, executableName("windows")); err != nil {
128
+ t.Fatalf("writeTarGz: %v", err)
129
+ }
130
+
131
+ f, err := os.Open(archive)
132
+ if err != nil {
133
+ t.Fatal(err)
134
+ }
135
+ defer f.Close()
136
+
137
+ gz, err := gzip.NewReader(f)
138
+ if err != nil {
139
+ t.Fatal(err)
140
+ }
141
+ defer gz.Close()
142
+
143
+ tr := tar.NewReader(gz)
144
+ header, err := tr.Next()
145
+ if err != nil {
146
+ t.Fatal(err)
147
+ }
148
+ if header.Name != "savepoint.exe" {
149
+ t.Fatalf("archive member = %q, want savepoint.exe", header.Name)
150
+ }
151
+
152
+ content, err := io.ReadAll(tr)
153
+ if err != nil {
154
+ t.Fatal(err)
155
+ }
156
+ if string(content) != "binary" {
157
+ t.Fatalf("archive content = %q, want binary", content)
158
+ }
159
+ }
160
+ ```
161
+
162
+ ### Target File
163
+ .savepoint/Design.md
164
+
165
+ ### Replace
166
+ ```md
167
+ - **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.
168
+ - **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.
169
+ ```
170
+
171
+ ### With
172
+ ```md
173
+ - **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.
174
+ - **Hardening baseline** (v1.1 E15) adds board render/layout benchmarks, data frontmatter fuzz targets, debug logging via CLI `--debug` or `SAVEPOINT_DEBUG`, abbreviation-aware task checklist sentence splitting, root test package isolation, documented audit-tab hidden-section allowlisting, repo-local CI, `make ci`, distribution SHA256 checksums, and Windows amd64/arm64 build outputs.
175
+ - **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.
176
+ ```
177
+
178
+ ### Target File
179
+ .savepoint/Design.md
180
+
181
+ ### Replace
182
+ ```md
183
+ - **Cross-platform builds:** `make build-all` cross-compiles linux-amd64, linux-arm64, darwin-amd64, and darwin-arm64 raw binaries into `dist/{platform}-{arch}/savepoint`.
184
+ - **Artifacts:** `make dist` creates versioned `.tar.gz` archives in `dist/` for the Linux and Darwin targets using Go archive APIs, not shell `tar`.
185
+ ```
186
+
187
+ ### With
188
+ ```md
189
+ - **Cross-platform builds:** `make build-all` cross-compiles linux-amd64, linux-arm64, darwin-amd64, darwin-arm64, windows-amd64, and windows-arm64 raw binaries into `dist/{platform}-{arch}/savepoint` or `savepoint.exe` for Windows. `make ci` runs the repo-local verification sequence used by CI.
190
+ - **Artifacts:** `make dist` creates versioned `.tar.gz` archives in `dist/` for Linux, Darwin, and Windows targets using Go archive APIs, not shell `tar`, and writes SHA256 hashes to `dist/checksums.txt`.
191
+ ```
192
+
193
+ ### Target File
194
+ AGENTS.md
195
+
196
+ ### Replace
197
+ ```md
198
+ | `internal/board/` | TUI board, overlays, epic sidebar, Next Activity line, router priority key, detail checklist rendering, status glyphs, forced color profile, async update I/O commands, shared board utilities |
199
+ ```
200
+
201
+ ### With
202
+ ```md
203
+ | `internal/board/` | TUI board, overlays, epic sidebar, Next Activity line, router priority key, detail checklist rendering, status glyphs, forced color profile, debug logging hooks, async update I/O commands, shared board utilities |
204
+ ```
205
+
206
+ ### Target File
207
+ AGENTS.md
208
+
209
+ ### Replace
210
+ ```md
211
+ | `internal/buildtool/` | Makefile helper, cross-compile, archives |
212
+ ```
213
+
214
+ ### With
215
+ ```md
216
+ | `internal/buildtool/` | Makefile helper, cross-compile including Windows targets, archives, distribution checksums |
217
+ ```
218
+
219
+ ### Target File
220
+ .savepoint/releases/v1.1/epics/E15-hardening/E15-Detail.md
221
+
222
+ ### Replace
223
+ ```md
224
+ ## Components
225
+
226
+ | Module | Purpose |
227
+ |--------|---------|
228
+ | `internal/board/view_test.go` | Add render benchmarks |
229
+ | `internal/data/parser_test.go` | Add fuzz targets |
230
+ | `cmd/main.go` | Add --debug / SAVEPOINT_DEBUG |
231
+ | `internal/buildtool/main.go` | Add checksums, Windows targets |
232
+ | `internal/board/detail.go` | Fix abbreviation handling |
233
+ | `internal/board/epic_panel.go` | Extract allowlist constant |
234
+ | `agent_skills_test.go` | Move to cmd_test package |
235
+ | `Makefile` | Add `ci` target for local verification |
236
+ | `.github/workflows/ci.yml` | Add repo CI workflow |
237
+
238
+ ## Boundaries
239
+ ```
240
+
241
+ ### With
242
+ ```md
243
+ ## Components
244
+
245
+ | Module | Purpose |
246
+ |--------|---------|
247
+ | `internal/board/view_test.go` | Add render and layout benchmarks |
248
+ | `internal/board/card_test.go` | Add card render benchmarks |
249
+ | `internal/board/column_test.go` | Add column render benchmarks |
250
+ | `internal/data/fuzz_test.go` | Add frontmatter and split-body fuzz targets |
251
+ | `main.go` | Add global --debug parsing and SAVEPOINT_DEBUG activation |
252
+ | `internal/board/debug.go` | Add board debug logging helper |
253
+ | `internal/board/board.go` | Log board initialization under debug mode |
254
+ | `internal/board/watch.go` | Log watcher and reload activity under debug mode |
255
+ | `internal/board/update.go` | Log update dispatch and preserve focused-card visibility |
256
+ | `internal/buildtool/main.go` | Add checksums and Windows targets |
257
+ | `internal/board/detail.go` | Fix abbreviation handling |
258
+ | `internal/board/epic_panel.go` | Document audit hidden-section allowlist |
259
+ | `agent_skills_test.go` | Move to external root test package |
260
+ | `Makefile` | Add `ci` target for local verification |
261
+ | `.github/workflows/ci.yml` | Add repo CI workflow |
262
+
263
+ ## Implemented As
264
+
265
+ - Debug activation is in root `main.go` because global flags are parsed before dispatching into `cmd/`.
266
+ - Fuzz targets live in `internal/data/fuzz_test.go` rather than `internal/data/parser_test.go`.
267
+ - Fuzzing found and fixed `SplitFrontmatterBody` delimiter-offset handling and CR line-ending normalization.
268
+ - Root `agent_skills_test.go` remains at the repository root but now uses external package `main_test`, which removes the root package coupling without moving fixture-relative paths.
269
+ - CI was included as repo-local guardrail scope for E15 via `T008-ci-and-release-automation`.
270
+
271
+ ## Boundaries
272
+ ```
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  type: epic-design
3
- status: planned
3
+ status: audited
4
4
  ---
5
5
 
6
6
  # E15: Phase 3 — Hardening
@@ -18,18 +18,35 @@ Address the remaining Phase 3 findings from the consolidated codebase audit (Opu
18
18
  - Windows build targets in buildtool
19
19
  - Abbreviation-aware checklist sentence splitting
20
20
  - Root-level test relocation and audit allowlist consolidation
21
+ - Repo-local CI workflow and `ci` Makefile target for build/test verification
21
22
 
22
23
  ## Components
23
24
 
24
25
  | Module | Purpose |
25
26
  |--------|---------|
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 |
27
+ | `internal/board/view_test.go` | Add render and layout benchmarks |
28
+ | `internal/board/card_test.go` | Add card render benchmarks |
29
+ | `internal/board/column_test.go` | Add column render benchmarks |
30
+ | `internal/data/fuzz_test.go` | Add frontmatter and split-body fuzz targets |
31
+ | `main.go` | Add global --debug parsing and SAVEPOINT_DEBUG activation |
32
+ | `internal/board/debug.go` | Add board debug logging helper |
33
+ | `internal/board/board.go` | Log board initialization under debug mode |
34
+ | `internal/board/watch.go` | Log watcher and reload activity under debug mode |
35
+ | `internal/board/update.go` | Log update dispatch and preserve focused-card visibility |
36
+ | `internal/buildtool/main.go` | Add checksums and Windows targets |
30
37
  | `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 |
38
+ | `internal/board/epic_panel.go` | Document audit hidden-section allowlist |
39
+ | `agent_skills_test.go` | Move to external root test package |
40
+ | `Makefile` | Add `ci` target for local verification |
41
+ | `.github/workflows/ci.yml` | Add repo CI workflow |
42
+
43
+ ## Implemented As
44
+
45
+ - Debug activation is in root `main.go` because global flags are parsed before dispatching into `cmd/`.
46
+ - Fuzz targets live in `internal/data/fuzz_test.go` rather than `internal/data/parser_test.go`.
47
+ - Fuzzing found and fixed `SplitFrontmatterBody` delimiter-offset handling and CR line-ending normalization.
48
+ - Root `agent_skills_test.go` remains at the repository root but now uses external package `main_test`, which removes the root package coupling without moving fixture-relative paths.
49
+ - CI was included as repo-local guardrail scope for E15 via `T008-ci-and-release-automation`.
33
50
 
34
51
  ## Boundaries
35
52
 
@@ -38,6 +55,6 @@ Address the remaining Phase 3 findings from the consolidated codebase audit (Opu
38
55
  - Medium/Low hardening items (M10, L7, L10, L11, L12)
39
56
 
40
57
  **Out of scope:**
41
- - CI/CD configuration separate concern
58
+ - External deployment hosting beyond repo-local CI/release automation
42
59
  - New UI features or commands
43
60
  - Structural improvements (separate epic E14)
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: E15-hardening/T001-benchmarks
3
- status: planned
3
+ status: done
4
4
  objective: Add benchmark tests for board render functions
5
5
  depends_on: []
6
6
  ---
@@ -16,16 +16,16 @@ depends_on: []
16
16
 
17
17
  ## Acceptance Criteria
18
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
19
+ - [x] Benchmark added for RenderCard with varied content widths
20
+ - [x] Benchmark added for renderColumn with multiple tasks
21
+ - [x] Benchmark added for layout calculations at different widths
22
+ - [x] Benchmarks are repeatable with consistent results
23
+ - [x] Benchmarks don't modify package state
24
+ - [x] `go test -bench=. ./internal/board/` runs without errors
25
25
 
26
26
  ## Implementation Plan
27
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`
28
+ - [x] Add benchmark functions in view_test.go, card_test.go, column_test.go
29
+ - [x] Create test data with representative task mixtures
30
+ - [x] Run benchmarks and document baseline
31
+ - [x] Run `make build && make test`
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: E15-hardening/T002-fuzz-targets
3
- status: planned
3
+ status: done
4
4
  objective: Add fuzz targets for YAML frontmatter parsing round-trip
5
5
  depends_on: []
6
6
  ---
@@ -15,14 +15,20 @@ depends_on: []
15
15
 
16
16
  ## Acceptance Criteria
17
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
18
+ - [x] Fuzz target added for extractFrontmatter round-trip
19
+ - [x] Fuzz target added for WriteTaskStatus round-trip (write then re-parse)
20
+ - [x] Fuzz targets exercise edge cases (empty content, malformed YAML, unicode)
21
+ - [x] `go test -fuzz=. ./internal/data/` runs without errors
22
22
 
23
23
  ## Implementation Plan
24
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`
25
+ - [x] Create fuzz_test.go in internal/data with fuzz targets
26
+ - [x] Define corpus seed inputs from known edge cases
27
+ - [x] Run fuzz targets for short duration to verify stability
28
+ - [x] Run `make build && make test`
29
+
30
+ ## Drift Notes
31
+
32
+ - Fuzzer found bug in `SplitFrontmatterBody`: used `len(TrimSpace(raw))` for bodyStart, causing off-by-N when frontmatter has leading/trailing whitespace. Fixed to compute bodyStart from actual `\n---` offset.
33
+ - Fuzzer found `normalizeLineEndings` not idempotent with `\r\r\n` sequences. Fixed to also replace lone `\r` with `\n` (handles legacy Mac CR line endings).
34
+ - No new files/modules beyond `internal/data/fuzz_test.go` (in-scope per E15-Detail.md).
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: E15-hardening/T003-debug-flag
3
- status: planned
3
+ status: done
4
4
  objective: Add --debug flag and SAVEPOINT_DEBUG env var for structured debug logging
5
5
  depends_on: []
6
6
  ---
@@ -15,16 +15,16 @@ depends_on: []
15
15
 
16
16
  ## Acceptance Criteria
17
17
 
18
- - [ ] --debug flag accepted at CLI level
19
- - [ ] SAVEPOINT_DEBUG env var recognized
20
- - [ ] Debug output includes board init, file watcher events, and command dispatch
21
- - [ ] Debug output is off by default (no performance impact)
22
- - [ ] `go test ./...` passes with no regressions
18
+ - [x] --debug flag accepted at CLI level
19
+ - [x] SAVEPOINT_DEBUG env var recognized
20
+ - [x] Debug output includes board init, file watcher events, and command dispatch
21
+ - [x] Debug output is off by default (no performance impact)
22
+ - [x] `go test ./...` passes with no regressions
23
23
 
24
24
  ## Implementation Plan
25
25
 
26
- - [ ] Define debug logging helper in a shared location
27
- - [ ] Add --debug flag parsing in main.go
28
- - [ ] Instrument key points in board init, file watcher, and update dispatch
29
- - [ ] Add tests for debug flag behavior
30
- - [ ] Run `make build && make test`
26
+ - [x] Define debug logging helper in a shared location
27
+ - [x] Add --debug flag parsing in main.go
28
+ - [x] Instrument key points in board init, file watcher, and update dispatch
29
+ - [x] Add tests for debug flag behavior
30
+ - [x] Run `make build && make test`
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: E15-hardening/T004-dist-checksums
3
- status: planned
3
+ status: done
4
4
  objective: Generate checksums.txt during make dist using Go crypto APIs
5
5
  depends_on: []
6
6
  ---
@@ -14,14 +14,14 @@ depends_on: []
14
14
 
15
15
  ## Acceptance Criteria
16
16
 
17
- - [ ] dist() generates checksums.txt file with SHA256 hashes
18
- - [ ] checksums.txt is included in the dist directory
19
- - [ ] Existing archive creation behavior preserved
20
- - [ ] `go test ./...` passes
17
+ - [x] dist() generates checksums.txt file with SHA256 hashes
18
+ - [x] checksums.txt is included in the dist directory
19
+ - [x] Existing archive creation behavior preserved
20
+ - [x] `go test ./...` passes
21
21
 
22
22
  ## Implementation Plan
23
23
 
24
- - [ ] Add SHA256 checksum computation in dist() using crypto/sha256
25
- - [ ] Write checksums.txt to dist directory
26
- - [ ] Add tests for checksum generation
27
- - [ ] Run `make build && make test`
24
+ - [x] Add SHA256 checksum computation in dist() using crypto/sha256
25
+ - [x] Write checksums.txt to dist directory
26
+ - [x] Add tests for checksum generation
27
+ - [x] Run `make build && make test`
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: E15-hardening/T005-windows-targets
3
- status: planned
3
+ status: done
4
4
  objective: Add Windows amd64 and arm64 build targets to buildtool
5
5
  depends_on: []
6
6
  ---
@@ -13,16 +13,16 @@ depends_on: []
13
13
 
14
14
  ## Acceptance Criteria
15
15
 
16
- - [ ] Windows amd64 target added
17
- - [ ] Windows arm64 target added
18
- - [ ] .exe suffix handled for Windows binaries
19
- - [ ] Existing Linux and Darwin targets preserved
20
- - [ ] `go test ./...` passes
16
+ - [x] Windows amd64 target added
17
+ - [x] Windows arm64 target added
18
+ - [x] .exe suffix handled for Windows binaries
19
+ - [x] Existing Linux and Darwin targets preserved
20
+ - [x] `go test ./...` passes
21
21
 
22
22
  ## Implementation Plan
23
23
 
24
- - [ ] Add windows-amd64 and windows-arm64 to targets list
25
- - [ ] Handle .exe suffix in build output path
26
- - [ ] Update localExecutable to detect Windows
27
- - [ ] Update tests for new targets
28
- - [ ] Run `make build && make test`
24
+ - [x] Add windows-amd64 and windows-arm64 to targets list
25
+ - [x] Handle .exe suffix in build output path via `executableName(goos)`
26
+ - [x] Update localExecutable to detect Windows (already done in prior task)
27
+ - [x] Update tests for new targets
28
+ - [x] Run `make build && make test`
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: E15-hardening/T006-abbreviation-splitting
3
- status: planned
3
+ status: done
4
4
  objective: Fix splitChecklistSentences to skip periods preceded by known abbreviations
5
5
  depends_on: []
6
6
  ---
@@ -13,14 +13,14 @@ depends_on: []
13
13
 
14
14
  ## Acceptance Criteria
15
15
 
16
- - [ ] Known abbreviations (e.g., "e.g.", "i.e.") do not trigger sentence breaks
17
- - [ ] Existing sentence splitting behavior preserved for non-abbreviation periods
18
- - [ ] Abbreviation list is configurable/extensible
19
- - [ ] `go test ./...` passes with no regressions
16
+ - [x] Known abbreviations (e.g., "e.g.", "i.e.") do not trigger sentence breaks
17
+ - [x] Existing sentence splitting behavior preserved for non-abbreviation periods
18
+ - [x] Abbreviation list is configurable/extensible
19
+ - [x] `go test ./...` passes with no regressions
20
20
 
21
21
  ## Implementation Plan
22
22
 
23
- - [ ] Define known abbreviation set
24
- - [ ] Add abbreviation check before period-based sentence split
25
- - [ ] Add test cases for abbreviations in sentences
26
- - [ ] Run `make build && make test`
23
+ - [x] Define known abbreviation set
24
+ - [x] Add abbreviation check before period-based sentence split
25
+ - [x] Add test cases for abbreviations in sentences
26
+ - [x] Run `make build && make test`
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: E15-hardening/T007-root-test-allowlist
3
- status: planned
3
+ status: done
4
4
  objective: Move agent_skills_test.go to a test package and extract audit allowlist to a named constant
5
5
  depends_on: []
6
6
  ---
@@ -14,15 +14,20 @@ depends_on: []
14
14
 
15
15
  ## Acceptance Criteria
16
16
 
17
- - [ ] agent_skills_test.go moved to cmd_test package (or appropriate location)
18
- - [ ] allowedSections extracted to a named constant with documentation
19
- - [ ] All existing tests still pass after refactoring
20
- - [ ] `go test ./...` passes with no regressions
17
+ - [x] agent_skills_test.go moved to cmd_test package (or appropriate location)
18
+ - [x] allowedSections extracted to a named constant with documentation
19
+ - [x] All existing tests still pass after refactoring
20
+ - [x] `go test ./...` passes with no regressions
21
21
 
22
22
  ## Implementation Plan
23
23
 
24
- - [ ] Move agent_skills_test.go to an appropriate internal test package
25
- - [ ] Update imports and paths in moved test
26
- - [ ] Extract allowedSections map to a named constant
27
- - [ ] Update any references in epic_panel.go
28
- - [ ] Run `make build && make test`
24
+ - [x] Move agent_skills_test.go to an appropriate internal test package
25
+ - [x] Update imports and paths in moved test
26
+ - [x] Extract allowedSections map to a named constant
27
+ - [x] Update any references in epic_panel.go
28
+ - [x] Run `make build && make test`
29
+
30
+ ## Notes
31
+
32
+ - `agent_skills_test.go` changed from `package main` → `package main_test` (external test package at root). Paths remain valid since Go test working dir is the package dir.
33
+ - `epicAuditHiddenSectionHeadings` already extracted as package-level var; added doc comment explaining suppression rationale.