savepoint 1.0.1 → 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.
Files changed (278) hide show
  1. package/.claude/settings.local.json +15 -1
  2. package/.golangci.yml +11 -0
  3. package/.savepoint/Design.md +52 -46
  4. package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T001-init-module.md +1 -1
  5. package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T005-layout.md +1 -1
  6. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T002-card.md +1 -1
  7. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T006-help-overlay.md +1 -1
  8. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/{Design.md → E06-Detail.md} +5 -3
  9. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T002-header-and-dividers.md +1 -1
  10. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T003-footer-status-bar.md +1 -1
  11. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T004-component-refinement.md +1 -1
  12. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T010-auto-refresh-watcher.md +2 -0
  13. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/{Design.md → E01-Detail.md} +9 -1
  14. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/{T007-next-activity-header.md → T001-next-activity-header.md} +13 -12
  15. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T002-rename-epic-design-files.md +9 -9
  16. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T003-rename-release-prd.md +2 -2
  17. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T004-update-instruction-files.md +13 -12
  18. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T005-update-cross-references.md +14 -13
  19. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T006-column-and-detail-scrolling.md +25 -15
  20. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T007-column-focus-border-stability.md +57 -0
  21. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/E02-Audit.md +124 -0
  22. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/{Design.md → E02-Detail.md} +12 -3
  23. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T001-fix-makefile.md +11 -8
  24. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T002-linux-build-target.md +12 -7
  25. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T003-macos-build-target.md +9 -5
  26. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T004-smoke-tests-and-artifacts.md +30 -9
  27. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/E03-Audit.md +195 -0
  28. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/E03-Detail.md +45 -0
  29. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T001-border-resize-fix.md +40 -0
  30. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T002-next-activity-below-header.md +64 -0
  31. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T003-checkbox-rendering-fix.md +56 -0
  32. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T005-unify-status-glyphs.md +65 -0
  33. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T006-forced-256-color-profile.md +36 -0
  34. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/E04-Audit.md +167 -0
  35. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/E04-Detail.md +51 -0
  36. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T001-sidebar-focusable-navigation.md +65 -0
  37. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T002-epic-detail-overlay.md +73 -0
  38. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T003-epic-status-glyphs.md +73 -0
  39. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/E05-Audit.md +237 -0
  40. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/E05-Detail.md +54 -0
  41. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T001-update-agents-md.md +45 -0
  42. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T002-update-router-md.md +40 -0
  43. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T003-update-design-md.md +47 -0
  44. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T004-implement-m-hotkey.md +98 -0
  45. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T005-update-help-overlay.md +33 -0
  46. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T006-tests-and-quality-gates.md +62 -0
  47. package/.savepoint/releases/v1.1/epics/E06-audit-command/E06-Audit.md +56 -0
  48. package/.savepoint/releases/v1.1/epics/E06-audit-command/E06-Detail.md +63 -0
  49. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T005-proposals.md +44 -0
  50. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T007-apply-close.md +35 -0
  51. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T009-integration.md +40 -0
  52. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T010-audit-file-migration.md +45 -0
  53. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T011-model-tab-state.md +26 -0
  54. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T012-epic-audit-render.md +33 -0
  55. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T013-handle-tab-keys.md +34 -0
  56. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T014-tab-indicator.md +33 -0
  57. package/.savepoint/releases/v1.1/epics/E07-init-command/E07-Audit.md +336 -0
  58. package/.savepoint/releases/v1.1/epics/E07-init-command/E07-Detail.md +61 -0
  59. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T001-cli-entrypoint.md +37 -0
  60. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T002-target-validation.md +28 -0
  61. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T003-scaffold-writer.md +46 -0
  62. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T004-atomic-writes.md +27 -0
  63. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T005-magic-prompt.md +25 -0
  64. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T006-clipboard.md +26 -0
  65. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T007-integration-test.md +26 -0
  66. package/.savepoint/releases/v1.1/epics/E08-board-command/E08-Audit.md +333 -0
  67. package/.savepoint/releases/v1.1/epics/E08-board-command/E08-Detail.md +68 -0
  68. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T001-cli-entrypoint.md +26 -0
  69. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T002-non-tty-fallback.md +27 -0
  70. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T003-tui-app-shell.md +28 -0
  71. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T004-board-model.md +29 -0
  72. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T005-detail-pane.md +27 -0
  73. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T006-status-transitions.md +29 -0
  74. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T007-theme-fallbacks.md +29 -0
  75. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T008-integration-test.md +27 -0
  76. package/.savepoint/releases/v1.1/epics/E09-doctor-command/E09-Audit.md +207 -0
  77. package/.savepoint/releases/v1.1/epics/E09-doctor-command/E09-Detail.md +65 -0
  78. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T001-cli-entrypoint.md +24 -0
  79. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T002-config-router-validation.md +28 -0
  80. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T003-structure-checks.md +29 -0
  81. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T004-dependency-checks.md +27 -0
  82. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T005-audit-orphan-checks.md +28 -0
  83. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T006-quality-gates-report.md +31 -0
  84. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/E11-Detail.md +36 -0
  85. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T001-debug-logging.md +25 -0
  86. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T002-increase-debounce.md +21 -0
  87. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T003-error-handling.md +22 -0
  88. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T004-test-verify.md +29 -0
  89. package/.savepoint/releases/v1.1/epics/E12-validation-fix/E12-Audit.md +444 -0
  90. package/.savepoint/releases/v1.1/epics/E12-validation-fix/E12-Detail.md +45 -0
  91. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T001-default-phase.md +35 -0
  92. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T002-default-status.md +19 -0
  93. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T003-better-errors.md +29 -0
  94. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T004-validate-on-write.md +25 -0
  95. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T005-tests.md +37 -0
  96. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/E13-Audit.md +118 -0
  97. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/E13-Detail.md +73 -0
  98. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T001-safe-cleanup.md +66 -0
  99. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T002-bug-fixes.md +35 -0
  100. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T003-centralize-duplication.md +60 -0
  101. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T004-infrastructure.md +33 -0
  102. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T005-decompose-update.md +37 -0
  103. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T006-async-io.md +40 -0
  104. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T007-test-coverage.md +37 -0
  105. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/E14-Audit.md +267 -0
  106. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/E14-Detail.md +54 -0
  107. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T001-group-model.md +39 -0
  108. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T002-data-interfaces.md +42 -0
  109. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T003-discover-orphans.md +33 -0
  110. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T004-epic-panel-headings.md +35 -0
  111. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T005-shell-tokenization.md +27 -0
  112. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T006-unify-enums.md +29 -0
  113. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T007-testutil-package.md +28 -0
  114. package/.savepoint/releases/v1.1/epics/E15-hardening/E15-Detail.md +43 -0
  115. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T001-benchmarks.md +31 -0
  116. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T002-fuzz-targets.md +28 -0
  117. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T003-debug-flag.md +30 -0
  118. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T004-dist-checksums.md +27 -0
  119. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T005-windows-targets.md +28 -0
  120. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T006-abbreviation-splitting.md +26 -0
  121. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T007-root-test-allowlist.md +28 -0
  122. package/.savepoint/releases/v1.1/epics/_archived/T001-cli-entrypoint.md +25 -0
  123. package/.savepoint/releases/v1.1/epics/_archived/T002-quality-gates.md +27 -0
  124. package/.savepoint/releases/v1.1/epics/_archived/T003-snapshot.md +27 -0
  125. package/.savepoint/releases/v1.1/epics/_archived/T004-ai-reconcile.md +29 -0
  126. package/.savepoint/releases/v1.1/epics/_archived/T006-tui-review.md +31 -0
  127. package/.savepoint/releases/v1.1/epics/_archived/T008-skip-handling.md +34 -0
  128. package/.savepoint/releases/v1.1/v1.1-PRD.md +139 -0
  129. package/.savepoint/router.md +29 -108
  130. package/AGENTS.md +69 -111
  131. package/Makefile +19 -3
  132. package/README.md +6 -6
  133. package/agent-skills/savepoint-audit/SKILL.md +87 -35
  134. package/agent-skills/savepoint-build-task/SKILL.md +9 -4
  135. package/agent-skills/savepoint-create-plan/SKILL.md +10 -5
  136. package/agent-skills/savepoint-create-task/SKILL.md +44 -31
  137. package/agent-skills/savepoint-draft-prd/SKILL.md +8 -3
  138. package/agent-skills/savepoint-system-design/SKILL.md +8 -3
  139. package/agent_skills_test.go +91 -0
  140. package/cmd/board.go +59 -0
  141. package/cmd/board_test.go +137 -0
  142. package/cmd/doctor.go +53 -0
  143. package/cmd/doctor_test.go +146 -0
  144. package/cmd/init.go +63 -0
  145. package/cmd/init_test.go +104 -0
  146. package/internal/board/board.go +69 -49
  147. package/internal/board/board_test.go +83 -67
  148. package/internal/board/card.go +71 -20
  149. package/internal/board/card_test.go +141 -12
  150. package/internal/board/column.go +77 -11
  151. package/internal/board/column_test.go +63 -13
  152. package/internal/board/detail.go +107 -72
  153. package/internal/board/detail_test.go +117 -26
  154. package/internal/board/epic_panel.go +211 -18
  155. package/internal/board/epic_panel_test.go +637 -14
  156. package/internal/board/help.go +1 -0
  157. package/internal/board/help_test.go +1 -0
  158. package/internal/board/integration_test.go +266 -0
  159. package/internal/board/interfaces.go +65 -0
  160. package/internal/board/interfaces_test.go +114 -0
  161. package/internal/board/io.go +93 -0
  162. package/internal/board/layout.go +12 -2
  163. package/internal/board/layout_test.go +17 -0
  164. package/internal/board/model.go +130 -52
  165. package/internal/board/plain.go +88 -0
  166. package/internal/board/plain_test.go +117 -0
  167. package/internal/board/release.go +1 -9
  168. package/internal/board/release_test.go +6 -6
  169. package/internal/board/render_policy_test.go +77 -0
  170. package/internal/board/status.go +23 -0
  171. package/internal/board/theme.go +24 -0
  172. package/internal/board/theme_test.go +31 -0
  173. package/internal/board/transitions.go +113 -88
  174. package/internal/board/transitions_test.go +164 -141
  175. package/internal/board/tui.go +32 -0
  176. package/internal/board/update.go +472 -94
  177. package/internal/board/update_test.go +447 -0
  178. package/internal/board/util.go +76 -0
  179. package/internal/board/view.go +139 -22
  180. package/internal/board/view_test.go +171 -3
  181. package/internal/board/watch.go +57 -9
  182. package/internal/buildtool/main.go +211 -0
  183. package/internal/buildtool/main_test.go +46 -0
  184. package/internal/data/config.go +17 -3
  185. package/internal/data/config_test.go +49 -0
  186. package/internal/data/discover.go +26 -0
  187. package/internal/data/discover_test.go +34 -10
  188. package/internal/data/errors.go +4 -0
  189. package/internal/data/lifecycle.go +13 -6
  190. package/internal/data/lifecycle_test.go +14 -11
  191. package/internal/data/parser.go +29 -6
  192. package/internal/data/parser_test.go +66 -7
  193. package/internal/data/task.go +1 -0
  194. package/internal/data/write.go +85 -11
  195. package/internal/data/write_test.go +167 -0
  196. package/internal/doctor/checks.go +567 -0
  197. package/internal/doctor/checks_test.go +716 -0
  198. package/internal/doctor/gates.go +193 -0
  199. package/internal/doctor/gates_test.go +166 -0
  200. package/internal/doctor/interfaces.go +64 -0
  201. package/internal/doctor/interfaces_test.go +104 -0
  202. package/internal/doctor/repairs.go +80 -0
  203. package/internal/doctor/repairs_test.go +81 -0
  204. package/internal/doctor/report.go +157 -0
  205. package/internal/doctor/report_test.go +89 -0
  206. package/internal/init/clipboard.go +146 -0
  207. package/internal/init/clipboard_test.go +74 -0
  208. package/internal/init/install.go +16 -0
  209. package/internal/init/integration_test.go +197 -0
  210. package/internal/init/prompt.go +14 -0
  211. package/internal/init/prompt_test.go +77 -0
  212. package/internal/init/scaffold.go +59 -0
  213. package/internal/init/scaffold_test.go +179 -0
  214. package/internal/init/template_freshness_test.go +56 -0
  215. package/internal/init/validate.go +85 -0
  216. package/internal/init/validate_test.go +141 -0
  217. package/internal/init/write.go +73 -0
  218. package/internal/init/write_test.go +91 -0
  219. package/internal/styles/palette.go +3 -3
  220. package/internal/styles/styles.go +39 -12
  221. package/internal/styles/styles_test.go +133 -0
  222. package/internal/testutil/fixture.go +113 -0
  223. package/internal/testutil/fs.go +26 -0
  224. package/main.go +107 -1
  225. package/package.json +2 -2
  226. package/project-audit/audit_report_glm_5.1.md +411 -0
  227. package/project-audit/audit_report_opus_4.6 +406 -0
  228. package/project-audit/consolidated-audit-report.md +456 -0
  229. package/savepoint +0 -0
  230. package/templates/project/.savepoint/Design.md +2 -2
  231. package/templates/project/.savepoint/router.md +15 -14
  232. package/templates/project/AGENTS.md +56 -98
  233. package/templates/project/agent-skills/savepoint-audit/SKILL.md +87 -0
  234. package/templates/project/agent-skills/savepoint-build-task/SKILL.md +44 -0
  235. package/templates/project/agent-skills/savepoint-create-plan/SKILL.md +33 -0
  236. package/templates/project/agent-skills/savepoint-create-task/SKILL.md +44 -0
  237. package/templates/project/agent-skills/savepoint-draft-prd/SKILL.md +37 -0
  238. package/templates/project/agent-skills/savepoint-system-design/SKILL.md +38 -0
  239. package/templates/prompts/audit-reconciliation.prompt.md +35 -30
  240. package/templates/prompts/design.prompt.md +3 -1
  241. package/templates/prompts/epic-design.prompt.md +3 -3
  242. package/templates/prompts/task-breakdown.prompt.md +1 -1
  243. package/templates/prompts/task-building.prompt.md +1 -1
  244. package/templates/prompts/task-planning.prompt.md +1 -1
  245. package/.savepoint/audit/E01-go-setup/proposals.md +0 -166
  246. package/.savepoint/audit/E01-go-setup/snapshot.md +0 -71
  247. package/.savepoint/audit/E01-scaffolding/proposals/AGENTS.md +0 -66
  248. package/.savepoint/audit/E01-scaffolding/proposals/Design.md +0 -210
  249. package/.savepoint/audit/E01-scaffolding/proposals/epic-Design.md +0 -117
  250. package/.savepoint/audit/E01-scaffolding/proposals/quality-review.md +0 -101
  251. package/.savepoint/audit/E01-scaffolding/snapshot.md +0 -54
  252. package/.savepoint/audit/E02-data-model/snapshot.md +0 -128
  253. package/.savepoint/audit/E02-data-readers/proposals.md +0 -123
  254. package/.savepoint/audit/E02-data-readers/snapshot.md +0 -54
  255. package/.savepoint/audit/E03-board-tui-core/proposals.md +0 -146
  256. package/.savepoint/audit/E03-board-tui-core/snapshot.md +0 -57
  257. package/.savepoint/audit/E03-cli-foundation/snapshot.md +0 -106
  258. package/.savepoint/audit/E04-board-components/proposals.md +0 -118
  259. package/.savepoint/audit/E04-board-components/snapshot.md +0 -77
  260. package/.savepoint/audit/E04-templates-and-prompts/snapshot.md +0 -115
  261. package/.savepoint/audit/E05-init-command/snapshot.md +0 -125
  262. package/.savepoint/audit/E05-phase-transitions/proposals.md +0 -83
  263. package/.savepoint/audit/E05-phase-transitions/snapshot.md +0 -36
  264. package/.savepoint/audit/E06-atari-noir-layout/proposals.md +0 -130
  265. package/.savepoint/audit/E06-atari-noir-layout/snapshot.md +0 -84
  266. package/.savepoint/audit/E06-tui-board/snapshot.md +0 -64
  267. package/.savepoint/audit/E07-audit-pipeline/snapshot.md +0 -165
  268. package/.savepoint/audit/E08-board-workflow-cleanup/snapshot.md +0 -65
  269. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T001-border-resize-fix.md +0 -36
  270. package/ink-cli-ui-design.zip +0 -0
  271. package/main.exe +0 -0
  272. package/savepoint.exe +0 -0
  273. /package/.savepoint/releases/v1/epics/E01-go-setup/{Design.md → E01-Detail.md} +0 -0
  274. /package/.savepoint/releases/v1/epics/E02-data-readers/{Design.md → E02-Detail.md} +0 -0
  275. /package/.savepoint/releases/v1/epics/E03-board-tui-core/{Design.md → E03-Detail.md} +0 -0
  276. /package/.savepoint/releases/v1/epics/E04-board-components/{Design.md → E04-Detail.md} +0 -0
  277. /package/.savepoint/releases/v1/epics/E05-phase-transitions/{Design.md → E05-Detail.md} +0 -0
  278. /package/.savepoint/releases/v1/{PRD.md → v1-PRD.md} +0 -0
@@ -0,0 +1,456 @@
1
+ # Consolidated Audit Report — Savepoint
2
+
3
+ This report merges findings from two independent audits (Opus 4.6 and GLM 5.1) of the Savepoint codebase. Where both audits identified the same issue, the finding is merged with combined evidence. Where only one audit identified an issue, it is included with attribution. Severity disagreements are resolved in favour of the higher rating, per the principle that the more cautious assessment should prevail.
4
+
5
+ ---
6
+
7
+ ## 1. Executive Summary
8
+
9
+ **Savepoint** is a Go CLI/TUI tool (~5,600 lines of production code, ~5,600 lines of tests, 264 tests across 39 test files) that implements a file-based project state machine with a kanban-style terminal board. It uses the Charmbracelet stack (Bubble Tea, Lip Gloss) for TUI rendering, fsnotify for file watching, and YAML-frontmatter markdown files as its data layer.
10
+
11
+ ### What is working well
12
+
13
+ - **File-per-responsibility** is followed diligently. Nearly every `.go` file does one job. The `board/` package splits cleanly into `model.go`, `view.go`, `update.go`, `card.go`, `column.go`, etc.
14
+ - **Test coverage is strong.** 264 tests across 39 files — roughly 1.6× the production code. All packages except `buildtool` and `styles` have tests, and integration tests exist for `board` and `init`.
15
+ - **Clean dependency tree.** Only 2 direct dependencies (`bubbletea`, `fsnotify`) plus the Charmbracelet ecosystem for rendering. No framework bloat.
16
+ - **All tests pass.** `go test ./...` reports zero failures.
17
+ - **Data model is honest.** The `data` package cleanly separates parsing, lifecycle validation, writing, and discovery.
18
+ - **Dependency injection in `cmd/`** via function types (`InitRunner`, `BoardRunner`, `DoctorRunner`) makes commands trivially testable.
19
+ - **Atomic file writes** in `data/write.go` and `init/write.go` prevent corruption.
20
+ - **Policy tests** (`render_policy_test.go`) enforce cross-cutting visual constraints.
21
+ - **Responsive TUI layout** with clean breakpoint-based column rendering.
22
+
23
+ ### Biggest risks
24
+
25
+ 1. **Synchronous file I/O inside the Bubble Tea `Update()` loop** freezes the TUI on slow disks. This is the highest-impact architectural issue.
26
+ 2. **`update.go` is a 521-line monolith** with a deeply nested key-dispatch switch. Hard to extend or test in isolation.
27
+ 3. **Duplicated YAML frontmatter read/write/parse logic** appears in `write.go`, `parser.go`, `board.go`, `checks.go`, and `epic_panel.go`.
28
+ 4. **Cycle detection in `checks.go` produces inaccurate paths** — a correctness bug.
29
+ 5. **No interfaces used for I/O boundaries** — all data-access types are concrete structs, making them impossible to mock without disk fixtures.
30
+
31
+ ### Extensibility
32
+
33
+ The project is easy to extend for new checks, overlays, and commands. It is harder to extend for new data sources or rendering backends because I/O is baked into concrete functions. The main risk to extensibility is the `update.go` monolith.
34
+
35
+ ### Architecture fit
36
+
37
+ The architecture (flat `internal/` packages, Elm-like TUI model, embedded templates) is well-suited for a small-to-medium CLI tool. No over-engineering is evident. The main architectural debts are the I/O-in-update anti-pattern and the `update.go` size.
38
+
39
+ ---
40
+
41
+ ## 2. Severity-Ranked Recommendations
42
+
43
+ ### Critical
44
+
45
+ #### C1. Synchronous file I/O in the TUI update loop
46
+
47
+ - **Finding:** `update.go` performs filesystem reads and writes directly inside `Update()`: `writeTaskStatus()`, `writeRouterTask()`, `writeRouterReleaseEpic()`, `readEpicDetailFile()`, `selectEpicPanelEpic()`. These block the TUI event loop.
48
+ - **Why it matters:** Any disk latency (network drives, slow SSDs, virus scanners) freezes the entire TUI. Bubble Tea's design intent is for `Update()` to be pure — I/O should happen in `tea.Cmd` functions that return messages.
49
+ - **Evidence:** `internal/board/update.go` (writeRouterTask, writeRouterReleaseEpic, readEpicDetailFile), `internal/board/model.go:235-280` (writeRouterReleaseEpic, writeRouterTask)
50
+ - **Recommended fix:** Extract I/O operations into `tea.Cmd` functions. E.g., `writeTaskStatusCmd(task, path, mtime) tea.Cmd` returns a `tea.Msg` on completion. `Update()` dispatches the command and handles the result message. This is the standard Bubble Tea pattern.
51
+ - **Estimated effort:** Medium
52
+
53
+ #### C2. Cycle detection produces inaccurate paths
54
+
55
+ - **Finding:** `detectCycles` in `checks.go` uses a `parent` map that gets overwritten when a node is visited from multiple paths. When a cycle is found, the path reconstructed via `parent` may not represent the actual cycle.
56
+ - **Why it matters:** Users could be shown a cycle path that doesn't actually exist, causing confusion or incorrect doctor reports.
57
+ - **Evidence:** `internal/doctor/checks.go` — the DFS `parent` map is a simple `map[string]string` that gets overwritten per-visit
58
+ - **Recommended fix:** Use a stack-based cycle reconstruction (track the current DFS path as a slice) or validate the reconstructed path actually forms a cycle before reporting it.
59
+ - **Estimated effort:** Small
60
+
61
+ ---
62
+
63
+ ### High
64
+
65
+ #### H1. Committed binaries in the repository
66
+
67
+ - **Finding:** `savepoint` (5.5 MB), `savepoint.exe` (6.0 MB), `dist/`, and `ink-cli-ui-design.zip` are tracked in Git.
68
+ - **Why it matters:** Bloats clone size (12+ MB), causes merge noise, and risks accidentally shipping stale binaries.
69
+ - **Evidence:** `.gitignore` does not exclude root binaries. `dist/` is also checked in.
70
+ - **Recommended fix:** Add `savepoint`, `savepoint.exe`, `dist/`, and `*.zip` to `.gitignore`. Run `git rm --cached` on tracked binaries. Build in CI only.
71
+ - **Estimated effort:** Small
72
+
73
+ #### H2. `update.go` complexity: God-method `Update()`
74
+
75
+ - **Finding:** `update.go` is 521 lines. The `Update()` method alone spans ~190 lines with 4+ levels of nesting inside `case tea.KeyMsg`. Overlay handling mixes 5 overlay types in one `updateOverlay()` function.
76
+ - **Why it matters:** Adding a new keybinding or overlay requires editing a deeply nested switch. Bug surface area grows with each addition. The space-bar and backspace handlers have nearly identical structure — find-task-by-ID, mutate, write, refresh.
77
+ - **Evidence:** `internal/board/update.go` — lines 19–192 for `Update()`, lines 132–158 and 159–181 for near-duplicate handler structure
78
+ - **Recommended fix:** Extract key handlers into named methods: `handleAdvanceTask()`, `handleRetreatTask()`, `handleSetPriority()`. Extract `updateBoardKeys()` and `updateOverlayKeys()` from the top-level switch. Split the overlay update into per-type handlers.
79
+ - **Estimated effort:** Medium
80
+
81
+ #### H3. Duplicated frontmatter body-extraction logic
82
+
83
+ - **Finding:** The pattern "extract frontmatter → unmarshal YAML → compute body start offset → reconstruct file" appears in:
84
+ - `write.go:updateFrontmatterField` (lines 40–83)
85
+ - `write.go:WriteTaskStatus` (lines 85–150)
86
+ - `board.go` (router reading)
87
+ - `checks.go` (task validation)
88
+ - `epic_panel.go:epicDetailBody` and `epicAuditBody` (frontmatter stripping, lines 50–60 and 125–134)
89
+ - The magic `delimLen := 4; bodyStart := delimLen + len(raw) + delimLen` appears in two places
90
+ - **Why it matters:** A change to frontmatter format must be patched in 4+ places. The body-offset calculation is fragile.
91
+ - **Evidence:** `internal/data/write.go:74-79` and `internal/data/write.go:140-145` are identical; `internal/board/epic_panel.go:51-59` and `internal/board/epic_panel.go:126-133` are identical
92
+ - **Recommended fix:** Extract `SplitFrontmatterBody(content string) (yaml string, body string, err error)` in the `data` package. Extract `stripFrontmatter(content string) string` for `epic_panel.go`.
93
+ - **Estimated effort:** Small
94
+
95
+ #### H4. No interfaces for data-access types
96
+
97
+ - **Finding:** `Discover`, `Parser`, `ConfigReader`, `RouterReader` are all concrete structs. Every consumer calls `data.NewDiscover()`, `data.NewParser()`, etc. directly.
98
+ - **Why it matters:** Test helpers in `board` and `doctor` must create real filesystem fixtures to test business logic. This is expensive and brittle.
99
+ - **Evidence:** `internal/board/board.go` lines 37, 85, 130 all call `data.NewDiscover()` with no injection point. `internal/doctor/checks.go` lines 116, 293, 454, 525 do the same.
100
+ - **Recommended fix:** Define interfaces at the consumer side (e.g., `type taskDiscoverer interface { ListReleases(root string) ([]data.ReleaseInfo, error) ... }`). Keep the existing structs as production implementations. Accept the interface in board/doctor constructors.
101
+ - **Estimated effort:** Medium
102
+
103
+ #### H5. Stdlib reimplementation in `repairs.go` and `buildtool/main.go`
104
+
105
+ - **Finding:** `contains()` and `indexOf()` in `repairs.go` reimplement `strings.Contains` and `strings.Index`. `trimSpace()` in `buildtool/main.go` reimplements `bytes.TrimSpace`.
106
+ - **Why it matters:** Makes code harder to read for Go developers expecting standard library calls. The custom implementations may have subtle differences from the stdlib versions (e.g., Unicode whitespace handling).
107
+ - **Evidence:** `internal/doctor/repairs.go:50-61`, `internal/buildtool/main.go:211-219`
108
+ - **Recommended fix:** Replace with `strings.Contains`, `strings.Index`, and `strings.TrimSpace` respectively.
109
+ - **Estimated effort:** Small
110
+
111
+ #### H6. Fragile repair suggestion matching via substring search on error messages
112
+
113
+ - **Finding:** `SuggestRepair()` pattern-matches against error message substrings to suggest fixes. If error messages change format, repairs silently break.
114
+ - **Evidence:** `internal/doctor/repairs.go:8-66` — hard-coded substring matching against messages like `"not found"`, `"invalid"`, `"missing"`
115
+ - **Recommended fix:** Define typed error codes or sentinel errors in `data/` and `doctor/`, and match on error type rather than substring.
116
+ - **Estimated effort:** Medium
117
+
118
+ #### H7. Quality gate command execution has no timeout
119
+
120
+ - **Finding:** `RunQualityGates` executes commands from `config.yml` with no timeout. A hung command blocks the doctor indefinitely.
121
+ - **Evidence:** `internal/doctor/gates.go:32-55` — `exec.Command` with `Run()` and no `Context` timeout
122
+ - **Recommended fix:** Use `exec.CommandContext(ctx, ...)` with a configurable timeout (default: 60s). Add a `gate_timeout` config option.
123
+ - **Estimated effort:** Small
124
+
125
+ #### H8. `\r\n` normalization is scattered across files
126
+
127
+ - **Finding:** `strings.ReplaceAll(content, "\r\n", "\n")` appears in `parser.go`, `write.go` (3 times), `epic_panel.go`, and likely elsewhere.
128
+ - **Why it matters:** If the normalization logic changes (e.g., also handling `\r` alone), every call site must be found and updated. Missing a call site causes subtle cross-platform bugs.
129
+ - **Evidence:** `internal/data/parser.go:92`, `internal/data/write.go:22,46,104`, `internal/board/epic_panel.go`
130
+ - **Recommended fix:** Create a `normalizeLineEndings(s string) string` function in `internal/data/` and use it everywhere.
131
+ - **Estimated effort:** Small
132
+
133
+ ---
134
+
135
+ ### Medium
136
+
137
+ #### M1. `Discover`, `Parser`, `ConfigReader` are stateless singletons instantiated repeatedly
138
+
139
+ - **Finding:** `data.NewDiscover()`, `data.NewParser()`, `data.NewConfigReader()`, `data.NewRouterReader()` all return pointers to zero-value structs. `Discover` is re-created 7 times across `board.go`, `checks.go`, and `main.go`.
140
+ - **Recommended fix:** Either convert to package-level functions (since there's no state) or introduce consumer-side interfaces per H4.
141
+ - **Estimated effort:** Small
142
+
143
+ #### M2. `newProgramModel()` contains hardcoded epic slug
144
+
145
+ - **Finding:** `board.go:33` — `NewModel(nil, "v1", "E03-board-tui-core")` is a development leftover.
146
+ - **Recommended fix:** Delete `newProgramModel()` or replace hardcoded values with empty strings.
147
+ - **Estimated effort:** Small
148
+
149
+ #### M3. Hardcoded state constants in `checks.go` duplicate `data/` definitions
150
+
151
+ - **Finding:** `validStates` map in `checks.go` duplicates state names defined in `data/lifecycle.go`.
152
+ - **Recommended fix:** Remove `validStates` and use `data.IsCanonicalColumn()` / `data.IsCanonicalStage()`.
153
+ - **Estimated effort:** Small
154
+
155
+ #### M4. Inconsistent directory abstraction: `CheckOrphans` bypasses `data.Discover`
156
+
157
+ - **Finding:** Most of `checks.go` uses `data.Discover` for filesystem traversal, but `CheckOrphans` uses `os.ReadDir` directly.
158
+ - **Recommended fix:** Add a `ListRootDirs()` method to `data.Discover` and use it in `CheckOrphans`.
159
+ - **Estimated effort:** Small
160
+
161
+ #### M5. Layout constants split between `layout.go` and `column.go`
162
+
163
+ - **Finding:** `colOverhead` is defined in `column.go` (value 4) and used in both `column.go` and `layout.go`.
164
+ - **Recommended fix:** Move all layout constants to `layout.go`.
165
+ - **Estimated effort:** Small
166
+
167
+ #### M6. `AtomicWrite` cross-device rename fallback is broken
168
+
169
+ - **Finding:** `replaceFile()` tries `os.Rename` first, then falls back to creating a backup and renaming, but `os.Rename` will still fail on cross-device moves in the fallback path.
170
+ - **Evidence:** `internal/init/write.go:52-63`
171
+ - **Recommended fix:** Use `os.Open` + `io.Copy` + `os.Remove` for cross-filesystem fallback.
172
+ - **Estimated effort:** Small
173
+
174
+ #### M7. Ad-hoc Markdown parsing in `epic_panel.go` is fragile
175
+
176
+ - **Finding:** `epicDetailBody()` and `epicAuditBody()` skip headings containing "component" or "files" via substring matching. Any heading with those substrings will be silently hidden.
177
+ - **Recommended fix:** Use exact heading matches with a configurable allowlist/blocklist rather than substring matching.
178
+ - **Estimated effort:** Small (exact match) / Medium (markdown parser)
179
+
180
+ #### M8. `Config.Theme` defaults not filling individual accent colors
181
+
182
+ - **Finding:** `fillThemeDefaults()` fills base theme colors when empty, but for accents it's all-or-nothing: `len(theme.Accents) == 0` triggers the default.
183
+ - **Recommended fix:** Fill missing accent keys individually from `defaultTheme.Accents`.
184
+ - **Estimated effort:** Small
185
+
186
+ #### M9. `splitCommand` in `gates.go` is a naïve shell tokenizer
187
+
188
+ - **Finding:** Only handles double-quote grouping — no escaping, no single quotes, no backslash-escapes.
189
+ - **Recommended fix:** Document the limitation or use `shellwords` parsing.
190
+ - **Estimated effort:** Small
191
+
192
+ #### M10. No Windows build target in `buildtool`
193
+
194
+ - **Finding:** `targets` list only includes Linux and Darwin. No Windows target despite a `localExecutable()` Windows branch.
195
+ - **Recommended fix:** Add Windows amd64 and arm64 targets. Add `.exe` suffix handling.
196
+ - **Estimated effort:** Small
197
+
198
+ #### M11. `buildtool` has no tests
199
+
200
+ - **Finding:** Only production package with `[no test files]`.
201
+ - **Recommended fix:** Add tests for `run()`, `version()`, and `writeTarGz()`.
202
+
203
+ ---
204
+
205
+ ### Low
206
+
207
+ #### L1. `ColumnType` and `TaskStatus` are parallel enumerations for the same concept
208
+
209
+ - **Recommended fix:** Consider unifying into a single status type. Low priority.
210
+ - **Estimated effort:** Medium
211
+
212
+ #### L2. `package.json` test script is misleading
213
+
214
+ - **Finding:** `"test": "savepoint init"` — `npm test` scaffolds a project instead of running tests.
215
+ - **Recommended fix:** Change to `"test": "echo \"Run 'make test' for Go tests\""`.
216
+
217
+ #### L3. Dead code: `taskLabel()`, `loadAllTasks()`, `newProgramModel()`, `CheckResult`
218
+
219
+ - **Recommended fix:** Delete all four.
220
+
221
+ #### L4. `shortID` and `shortRouterID` are near-duplicates
222
+
223
+ - **Recommended fix:** Consolidate into one `ShortID(full string) string` function.
224
+
225
+ #### L5. `epicIndex` and `releaseIndex` are identical functions
226
+
227
+ - **Recommended fix:** Extract `sliceIndex(items []string, target string) int`.
228
+
229
+ #### L6. No linter configured
230
+
231
+ - **Recommended fix:** Add `.golangci.yml` with `unused`, `errcheck`, `staticcheck`, `govet`, `ineffassign`.
232
+
233
+ #### L7. No distribution checksums
234
+
235
+ - **Finding:** `dist()` creates tar.gz archives but no SHA256 checksums file.
236
+ - **Recommended fix:** Generate `checksums.txt` during `dist`.
237
+
238
+ #### L8. `agent_skills_test.go` hardcodes expected skill count of 6
239
+
240
+ - **Recommended fix:** Remove count assertion or derive from directory listing.
241
+
242
+ #### L9. Test helper duplication across packages
243
+
244
+ - **Recommended fix:** Create `internal/testutil` package with shared fixtures.
245
+
246
+ #### L10. `splitChecklistSentences` doesn't handle abbreviations
247
+
248
+ - **Recommended fix:** Skip periods preceded by known abbreviations (e.g., "e.g.", "i.e.").
249
+
250
+ #### L11. `package main` test file at root level
251
+
252
+ - **Recommended fix:** Move to a dedicated test package.
253
+
254
+ #### L12. Audit section allowlist should be configurable
255
+
256
+ - **Recommended fix:** Extract `allowedSections` to a named constant with documentation.
257
+
258
+ #### L13. `reloadTasks` silently swallows errors
259
+
260
+ - **Finding:** `watch.go` returns `nil` on error, causing the board to silently stop refreshing.
261
+ - **Recommended fix:** Return an `errorMsg` so the TUI can surface it.
262
+
263
+ ---
264
+
265
+ ## 3. Complexity & Modularity Review
266
+
267
+ ### Overly large files
268
+
269
+ | File | Lines | Concern |
270
+ |------|-------|---------|
271
+ | `internal/board/update.go` | 521 | `Update()` is 190 lines; `updateOverlay()` is 100 lines |
272
+ | `internal/doctor/checks.go` | 585 | Single-file check aggregator; could be split by check type |
273
+ | `internal/data/write.go` | 216 | Two large functions with duplicated body-offset arithmetic |
274
+ | `internal/board/epic_panel.go` | 256 | Sidebar, detail, audit, and dropdown rendering mixed |
275
+
276
+ ### Tight coupling
277
+
278
+ - **Board → data:** Appropriate for project size. Clean boundary.
279
+ - **Board → os:** `model.go` and `update.go` call `os.ReadFile`, `os.Stat`, `os.WriteFile` directly. Couples UI logic to filesystem.
280
+
281
+ ### Repeated logic
282
+
283
+ 1. Frontmatter stripping (3+ places)
284
+ 2. `\r\n` normalization (4+ call sites across 2 packages)
285
+ 3. `shortID` extraction (2 near-duplicate implementations)
286
+ 4. `indexOf`/`epicIndex`/`releaseIndex` pattern (3 implementations)
287
+ 5. Space-bar and Backspace handlers in `update.go` (nearly identical structure)
288
+ 6. `Discover` instantiation (7 separate `NewDiscover()` calls)
289
+
290
+ ### Unclear data flow
291
+
292
+ - **`Task.Status` vs `Task.Column`:** Two representations of the same state. `syncTaskStatus` manually keeps them in sync.
293
+ - **`watch.go` silent error swallowing:** `reloadTasks` returns `nil` on error.
294
+
295
+ ### Excessive abstraction
296
+
297
+ - `Discover`, `Parser`, `ConfigReader`, `RouterReader` are empty structs used as method namespaces. Should be package-level functions or interfaces.
298
+
299
+ ---
300
+
301
+ ## 4. Architecture Review
302
+
303
+ ### Folder organisation ✅
304
+
305
+ ```
306
+ savepoint/
307
+ ├── cmd/ # CLI arg parsing — clean separation from execution
308
+ ├── internal/
309
+ │ ├── board/ # TUI model/view/update — Elm architecture
310
+ │ ├── buildtool/ # Standalone Go binary for build automation
311
+ │ ├── data/ # Models, parsing, writing, discovery
312
+ │ ├── doctor/ # Read-only diagnostics
313
+ │ ├── init/ # Scaffolding
314
+ │ └── styles/ # Centralised palette + styles
315
+ ├── templates/ # Embedded scaffold templates
316
+ └── agent-skills/ # Prompt documents for AI agents
317
+ ```
318
+
319
+ ### Domain boundaries ✅
320
+
321
+ - **Data layer** (`internal/data/`): Task lifecycle, parsing, discovery, config, writing. Correct boundary.
322
+ - **Board/TUI** (`internal/board/`): Rendering, interaction, file watching. Largest package.
323
+ - **Doctor** (`internal/doctor/`): Checks, gates, repairs, report. Each file has one job. Clean.
324
+ - **Init** (`internal/init/`): Scaffold, validate, write, clipboard, prompt. Clean.
325
+
326
+ ### State management
327
+
328
+ Bubble Tea `Model` with 27 fields. Upper bound of manageable. Consider grouping related fields into sub-structs if TUI grows. I/O-in-Update is the main concern (C1).
329
+
330
+ ### Configuration approach ✅
331
+
332
+ `config.yml` with defaults baked into Go code. Three-tier color support. `QualityGates` for project-specific commands. Clean.
333
+
334
+ ### Error handling
335
+
336
+ Generally good — errors wrapped with `fmt.Errorf("context: %w", err)`. Key exceptions:
337
+ - `reloadTasks` silently swallows errors (L13)
338
+ - `SuggestRepair` relies on substring matching (H6)
339
+ - Quality gates have no timeout (H7)
340
+
341
+ ---
342
+
343
+ ## 5. Best-Practice Review
344
+
345
+ ### Framework conventions ⚠️
346
+
347
+ Bubble Tea conventions generally followed. I/O in `Update()` violates the framework's core principle — see C1.
348
+
349
+ ### Type security ✅
350
+
351
+ Custom types (`ColumnType`, `ProgressStage`, `OverlayType`) used appropriately. `ColumnType`/`TaskStatus` duality is a minor concern (L1).
352
+
353
+ ### Linting/formatting ⚠️
354
+
355
+ No linter configured. Add `.golangci.yml` with `unused`, `errcheck`, `staticcheck`, `govet`, `ineffassign`.
356
+
357
+ ### Testing ✅
358
+
359
+ Strong coverage (264 tests, ~1.6:1 test-to-code ratio). Missing: `buildtool`, `styles`, benchmarks, fuzz tests.
360
+
361
+ ### Dependency management ✅
362
+
363
+ `go.mod` is clean. 2 direct dependencies. All indirect deps from Charmbracelet ecosystem.
364
+
365
+ ### Build/deployment ⚠️
366
+
367
+ - No CI configuration visible
368
+ - Binaries committed to repo (H1)
369
+ - No Windows build target (M10)
370
+ - No distribution checksums (L7)
371
+
372
+ ### Logging/debugging ⚠️
373
+
374
+ No logging. TUI uses `StatusMessage` for user feedback. No `--debug` flag. Recommend adding `SAVEPOINT_DEBUG` env var.
375
+
376
+ ---
377
+
378
+ ## 6. Refactor Roadmap
379
+
380
+ ### Phase 1 — Safe cleanup
381
+
382
+ **Objective:** Remove dead code, fix obvious duplication, improve hygiene.
383
+
384
+ | Task | Risk |
385
+ |------|------|
386
+ | Add binaries to `.gitignore` and remove from Git tracking | None |
387
+ | Delete `taskLabel()`, `loadAllTasks()`, `newProgramModel()`, `CheckResult` | None |
388
+ | Remove unused `exitCode` param from `GateSuggestion` | None |
389
+ | Replace `contains()`/`indexOf()` with `strings.Contains`/`strings.Index` | None |
390
+ | Replace `trimSpace()` with `strings.TrimSpace` | None |
391
+ | Replace `validStates` map with `data.IsCanonicalColumn()`/`data.IsCanonicalStage()` | Low |
392
+ | Fix `package.json` test script | None |
393
+ | Add `.golangci.yml` with basic linters | None |
394
+ | Co-locate layout constants (`colOverhead`) into `layout.go` | Low |
395
+ | Consolidate `shortID`/`shortRouterID` and `epicIndex`/`releaseIndex` | Low |
396
+
397
+ **Expected benefit:** Cleaner codebase, smaller repo, automated lint catches.
398
+ **Risk level:** Very low.
399
+
400
+ ### Phase 2 — Structural improvements
401
+
402
+ **Objective:** Reduce duplication, improve modularity, make key files easier to extend.
403
+
404
+ | Task | Risk |
405
+ |------|------|
406
+ | Extract `SplitFrontmatterBody()` in `data` package | Low — well-tested |
407
+ | Extract `stripFrontmatter()` for `epic_panel.go` | Low |
408
+ | Add `normalizeLineEndings()` to `data` package; use everywhere | Low |
409
+ | Split `Update()` into `handleBoardKey()`, `handleOverlayKey()`, named methods | Medium |
410
+ | Group `Model` fields into sub-structs | Medium |
411
+ | Convert stateless data types to package-level functions or consumer-defined interfaces | Medium |
412
+ | Fix `AtomicWrite` cross-device fallback | Low |
413
+ | Make `Config.Theme.Accents` fill missing keys individually | Low |
414
+
415
+ **Expected benefit:** Easier to add features, reduced duplication, more testable.
416
+ **Risk level:** Medium.
417
+
418
+ ### Phase 3 — Hardening
419
+
420
+ **Objective:** Fix the I/O-in-update anti-pattern, add missing tests, improve error handling.
421
+
422
+ | Task | Risk |
423
+ |------|------|
424
+ | Extract all filesystem I/O from `update.go` into `tea.Cmd` functions | Medium-High |
425
+ | Add `tea.Cmd`-based router writing for priority key and epic selection | Medium |
426
+ | Handle `reloadTasks` errors by emitting `errorMsg` | Low |
427
+ | Add timeout to quality gate execution | Low |
428
+ | Convert `SuggestRepair` to typed error matching | Medium |
429
+ | Add tests for `buildtool/` | Low |
430
+ | Add tests for `styles/` | Low |
431
+ | Add benchmark tests for render functions | Low |
432
+ | Add fuzz targets for YAML frontmatter parsing | Low |
433
+ | Add `--debug`/`SAVEPOINT_DEBUG` flag | Low |
434
+ | Fix cycle detection path reconstruction | Low |
435
+
436
+ **Expected benefit:** TUI responsiveness, correct error propagation, test coverage completeness.
437
+ **Risk level:** Low–Medium.
438
+
439
+ ---
440
+
441
+ ## 7. Top 10 Action List
442
+
443
+ - [ ] **1. Extract I/O from `update.go` into `tea.Cmd` functions** — Critical — `internal/board/update.go`, `internal/board/model.go` — Prevents TUI freezes on slow disk; follows Bubble Tea conventions; highest architectural impact
444
+ - [ ] **2. Remove committed binaries from the repository** — High — `.gitignore`, `savepoint`, `savepoint.exe`, `dist/`, `ink-cli-ui-design.zip` — Repo shrinks by 12 MB+, eliminates merge noise
445
+ - [ ] **3. Fix cycle detection path reconstruction in `checks.go`** — High (bug) — `internal/doctor/checks.go` — Produces inaccurate error messages today
446
+ - [ ] **4. Extract `SplitFrontmatterBody()` to deduplicate write logic** — High — `internal/data/write.go`, `internal/board/epic_panel.go` — Single source of truth for frontmatter reconstruction
447
+ - [ ] **5. Split `Update()` into named key-handler methods** — High — `internal/board/update.go` — 190-line method becomes 5–6 focused methods; easier to extend
448
+ - [ ] **6. Replace stdlib reimplementations (`contains`, `indexOf`, `trimSpace`)** — High — `internal/doctor/repairs.go`, `internal/buildtool/main.go` — Eliminates confusing custom code
449
+ - [ ] **7. Add timeout to quality gate execution** — High — `internal/doctor/gates.go` — Prevents indefinite blocking
450
+ - [ ] **8. Centralize `\r\n` normalization and frontmatter stripping** — Medium — `internal/data/parser.go`, `internal/data/write.go`, `internal/board/epic_panel.go` — Single source of truth for cross-platform line endings and body extraction
451
+ - [ ] **9. Consolidate layout constants, shared utilities, and duplicate functions** — Medium — `internal/board/column.go`, `internal/board/layout.go`, `internal/board/card.go`, `internal/board/view.go`, `internal/board/detail.go`, `internal/board/epic_panel.go`, `internal/board/release.go` — Reduces scatter and makes logic findable
452
+ - [ ] **10. Fix `AtomicWrite` cross-device rename fallback** — Medium — `internal/init/write.go` — Prevents silent data loss on cross-filesystem moves
453
+
454
+ ---
455
+
456
+ *Consolidated from audits by Opus 4.6 and GLM 5.1 on 2026-05-03.*
package/savepoint CHANGED
Binary file
@@ -34,9 +34,9 @@ last_audited: never
34
34
 
35
35
  <!-- Commands and flags if applicable. -->
36
36
 
37
- ## 7. Audit pipeline
37
+ ## 7. Agent audit workflow
38
38
 
39
- <!-- Steps the audit follows. -->
39
+ <!-- Savepoint audit is agent-led and skill-driven, not a CLI pipeline. At epic close, a fresh audit agent writes one epic-local `E##-Audit.md` with exactly these user-facing sections: `## Main Findings` and `## Code Style Review`. File-specific `### Target File` / `### Replace` / `### With` blocks belong under a separate `## Proposed Changes` admin section so the TUI Audit tab can omit them. -->
40
40
 
41
41
  ## 8. Testing strategy
42
42
 
@@ -9,7 +9,7 @@ This file routes the agent based on the project's current state. Read this whene
9
9
  3. The active epic Design
10
10
  4. The active task file, when a task is selected
11
11
 
12
- Read `.savepoint/PRD.md` only for project vision changes. Read `.savepoint/Design.md` only for architecture changes or audit closeout. Read `.savepoint/releases/v{{RELEASE_NUMBER}}/PRD.md` only for release planning or epic-order questions.
12
+ Read `.savepoint/PRD.md` only for project vision changes. Read `.savepoint/Design.md` only for architecture changes or audit closeout. Read `.savepoint/releases/{release}/{release}-PRD.md` only for release planning or epic-order questions.
13
13
 
14
14
  **Conditional read (token discipline):** if your active task touches **Ink/TUI implementation**, also read `agent-skills/ink-tui-design/SKILL.md` after Design.md as the execution guide. If it touches **TUI rendering, theme, or visual design**, also read `.savepoint/visual-identity.md` as the visual guardrails. Otherwise skip the extra files — they are tokens you do not need.
15
15
 
@@ -27,11 +27,12 @@ next_action: "The project has its PRD and Design locked but no epics defined yet
27
27
 
28
28
  If the user explicitly asks you to audit an epic, perform the audit for that epic even if the router has not reached `state: audit-pending` yet.
29
29
 
30
- Persist the audit artifacts before replying:
30
+ Persist the audit artifact before replying:
31
31
 
32
- - Ensure `.savepoint/audit/{E##-epic}/snapshot.md` exists. Create a manual snapshot once if needed.
33
- - Write the proposal bundle to `.savepoint/audit/{E##-epic}/proposals.md`.
34
- - Do not stop at chat-only findings. The filesystem artifact is part of the task output.
32
+ - Write exactly one `.savepoint/releases/{release}/epics/{E##-epic}/E##-Audit.md`.
33
+ - Include `## Main Findings`, `## Code Style Review`, and `## Proposed Changes`.
34
+ - Keep file-specific `### Target File` / `### Replace` / `### With` blocks under `## Proposed Changes`.
35
+ - Do not apply proposals or mark the epic audited until the user says `apply audit`.
35
36
 
36
37
  ## State → next action
37
38
 
@@ -43,9 +44,9 @@ The project has its PRD and Design locked but no epics defined yet.
43
44
 
44
45
  **Next action:**
45
46
 
46
- 1. Read `.savepoint/releases/v{{RELEASE_NUMBER}}/PRD.md` — the v{{RELEASE_NUMBER}} release scope (epic list lives there).
47
+ 1. Read `.savepoint/releases/{release}/{release}-PRD.md` — the release scope (epic list lives there).
47
48
  2. Help the user define the epics list and confirm priority.
48
- 3. For each epic in order, create the directory `.savepoint/releases/v{{RELEASE_NUMBER}}/epics/E##-{epic-name}/` with a `Design.md` stub.
49
+ 3. For each epic in order, create the directory `.savepoint/releases/{release}/epics/E##-{epic-name}/` with a `Design.md` stub.
49
50
  4. When epic E01 (scaffolding) is created, transition to `state: epic-design` for that epic.
50
51
 
51
52
  **Do not** start writing code. We are still in planning.
@@ -70,7 +71,7 @@ Epic Design exists but tasks are missing or not fully planned.
70
71
 
71
72
  1. Re-read the epic Design.
72
73
  2. Create or update the full epic task list — each task **independently buildable**, **objective-led**, with declared `depends_on`.
73
- 3. Each task file lives at `.savepoint/releases/v{{RELEASE_NUMBER}}/epics/{E##-epic}/tasks/TNNN-slug.md` with frontmatter:
74
+ 3. Each task file lives at `.savepoint/releases/{release}/epics/{E##-epic}/tasks/TNNN-slug.md` with frontmatter:
74
75
  ```yaml
75
76
  ---
76
77
  id: {E##-epic}/TNNN-slug
@@ -102,12 +103,11 @@ The last task in an epic is `done`. Audit must run before the next epic starts.
102
103
 
103
104
  **Context gate:** If you just built this epic in the current session, you **must not** audit it. Close this session. The user should start a new session for the audit.
104
105
 
105
- **Next action (fresh session only):** Confirm `.savepoint/audit/{E##-epic}/snapshot.md` exists. If it is missing while the audit CLI is still unavailable, create one manual snapshot from the known epic scope once; do not search broadly for replacement inputs. Then read the snapshot, read the epic's `Design.md`, and read only the files listed as changed. Write one patch-shaped proposal bundle to `.savepoint/audit/{E##-epic}/proposals.md`:
106
+ **Next action (fresh session only):** Read the epic's `E##-Detail.md`, task files, drift notes, `.savepoint/Design.md`, `AGENTS.md`, and scoped changed files. Write one epic-local audit file to `.savepoint/releases/{release}/epics/{E##-epic}/E##-Audit.md`:
106
107
 
107
- - `Design.md` section merge only the epic delta into project architecture.
108
- - `AGENTS.md` section refresh Codebase Map entries from changed-module metadata; preserve existing rows.
109
- - `epic-Design.md` section add "Implemented as:" notes and deltas from the original plan.
110
- - `Quality Review` section — semantic-review findings against the 10 Code Style rules.
108
+ - `## Main Findings` — user-facing AC verification, important drift, and notable risks.
109
+ - `## Code Style Review` checklist against the 10 AGENTS.md code style rules.
110
+ - `## Proposed Changes` — admin/apply metadata using `### Target File`, `### Replace`, and `### With`.
111
111
 
112
112
  Prefer delta-only edits (`Insert After`, `Replace`, `Delete`) anchored to exact text. Do not quote and replace entire large sections unless the whole section genuinely changed.
113
113
 
@@ -139,7 +139,7 @@ Quality review section format:
139
139
  ## Already Fixed
140
140
  ```
141
141
 
142
- After proposals are approved, apply approved proposals to live files, mark the epic `Design.md` as `status: audited`, update project `Design.md` `last_audited`, refresh `AGENTS.md` Codebase Map, and advance this router to the next epic state.
142
+ After proposals are approved, apply approved proposals to live files, mark the epic `E##-Detail.md` as `status: audited`, update project `Design.md` `last_audited`, refresh `AGENTS.md` Codebase Map if needed, and advance this router to the next epic state.
143
143
 
144
144
  Stop. The user reviews proposals in the TUI before commit actions.
145
145
 
@@ -150,3 +150,4 @@ If you are not Claude Opus / Gemini 2.5 Pro / GPT-5.5 / equivalent, surface a wa
150
150
  > _"Heads up — I'm running on a lighter model. Savepoint's planning steps work best with top-tier models because the embedded prompts are detailed. I'll do my best, but consider switching the model for PRD/Design/Task-breakdown steps."_
151
151
 
152
152
  Then proceed.
153
+ proceed.