savepoint 1.0.3 → 1.0.6

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 (418) hide show
  1. package/package.json +10 -3
  2. package/{savepoint → savepoint.exe} +0 -0
  3. package/.claude/settings.local.json +0 -38
  4. package/.golangci.yml +0 -11
  5. package/.prettierignore +0 -4
  6. package/.savepoint/Design.md +0 -206
  7. package/.savepoint/PRD.md +0 -58
  8. package/.savepoint/config.yml +0 -27
  9. package/.savepoint/releases/v1/epics/E01-go-setup/E01-Detail.md +0 -39
  10. package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T001-init-module.md +0 -42
  11. package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T002-entrypoint.md +0 -23
  12. package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T003-directory-structure.md +0 -24
  13. package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T004-makefile.md +0 -23
  14. package/.savepoint/releases/v1/epics/E02-data-readers/E02-Detail.md +0 -61
  15. package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T001-task-struct.md +0 -29
  16. package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T002-frontmatter-parser.md +0 -30
  17. package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T003-router-reader.md +0 -29
  18. package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T004-config-reader.md +0 -29
  19. package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T005-discovery.md +0 -30
  20. package/.savepoint/releases/v1/epics/E03-board-tui-core/E03-Detail.md +0 -38
  21. package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T001-model.md +0 -29
  22. package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T002-update-loop.md +0 -30
  23. package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T003-view.md +0 -34
  24. package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T004-styles.md +0 -29
  25. package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T005-layout.md +0 -42
  26. package/.savepoint/releases/v1/epics/E04-board-components/E04-Detail.md +0 -44
  27. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T001-column.md +0 -34
  28. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T002-card.md +0 -33
  29. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T003-epic-panel.md +0 -49
  30. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T004-detail-overlay.md +0 -40
  31. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T005-release-dropdown.md +0 -33
  32. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T006-help-overlay.md +0 -34
  33. package/.savepoint/releases/v1/epics/E05-phase-transitions/E05-Detail.md +0 -38
  34. package/.savepoint/releases/v1/epics/E05-phase-transitions/tasks/T001-phase-stepping.md +0 -29
  35. package/.savepoint/releases/v1/epics/E05-phase-transitions/tasks/T002-gates.md +0 -31
  36. package/.savepoint/releases/v1/epics/E05-phase-transitions/tasks/T003-write-task.md +0 -31
  37. package/.savepoint/releases/v1/epics/E05-phase-transitions/tasks/T004-write-router.md +0 -31
  38. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/E06-Detail.md +0 -62
  39. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T001-color-system.md +0 -39
  40. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T002-header-and-dividers.md +0 -52
  41. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T003-footer-status-bar.md +0 -52
  42. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T004-component-refinement.md +0 -53
  43. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T005-restore-nav-hints.md +0 -39
  44. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T007-detail-card-fixes.md +0 -36
  45. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T008-checkbox-states.md +0 -40
  46. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T009-router-priority-marker.md +0 -48
  47. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T010-auto-refresh-watcher.md +0 -66
  48. package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/Design.md +0 -39
  49. package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/tasks/T001-archive-epics.md +0 -20
  50. package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/tasks/T002-rewrite-prd.md +0 -22
  51. package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/tasks/T003-create-epic-stubs.md +0 -24
  52. package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/tasks/T004-update-router.md +0 -22
  53. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/Design.md +0 -118
  54. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/handoff.md +0 -9
  55. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T001-package-baseline.md +0 -45
  56. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T002-typescript-build.md +0 -48
  57. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T003-vitest-smoke.md +0 -43
  58. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T004-lint-format-gates.md +0 -45
  59. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T005-scaffold-verification.md +0 -40
  60. package/.savepoint/releases/v1/epics/_archived/E02-data-model/Design.md +0 -142
  61. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T001-domain-ids-status.md +0 -27
  62. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T002-markdown-frontmatter-boundary.md +0 -28
  63. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T003-task-documents.md +0 -29
  64. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T004-release-epic-router-config-readers.md +0 -30
  65. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T005-dependency-validation.md +0 -29
  66. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T006-epic-task-set-reader.md +0 -29
  67. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T007-quality-gates.md +0 -31
  68. package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/Design.md +0 -40
  69. package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/tasks/T001-phase-types.md +0 -27
  70. package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/tasks/T002-phase-frontmatter.md +0 -25
  71. package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/tasks/T003-simplify-config.md +0 -26
  72. package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/tasks/T004-simplify-router-domain.md +0 -24
  73. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/Design.md +0 -122
  74. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T001-argument-parser-contract.md +0 -28
  75. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T002-help-text-generation.md +0 -28
  76. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T003-terminal-environment-detection.md +0 -27
  77. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T004-command-stub-modules.md +0 -29
  78. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T005-cli-runner-dispatch.md +0 -34
  79. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T006-entrypoint-quality-gates.md +0 -32
  80. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/Design.md +0 -43
  81. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T001-strip-args.md +0 -26
  82. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T002-strip-help.md +0 -23
  83. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T003-strip-run.md +0 -23
  84. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T004-delete-commands.md +0 -24
  85. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T005-update-cli-tests.md +0 -22
  86. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/Design.md +0 -48
  87. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T001-board-data-phases.md +0 -26
  88. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T002-phase-rendering.md +0 -28
  89. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T003-detail-pane-phases.md +0 -27
  90. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T004-phase-transitions.md +0 -42
  91. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T005-phase-gates.md +0 -24
  92. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T006-phase-write-back.md +0 -24
  93. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T007-remove-audit-flow.md +0 -27
  94. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T008-board-tests.md +0 -25
  95. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/Design.md +0 -85
  96. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T001-project-template-assets.md +0 -17
  97. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T002-release-and-prompt-assets.md +0 -20
  98. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T003-template-registry-renderer.md +0 -22
  99. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T004-template-integrity-tests.md +0 -17
  100. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T005-template-closeout-quality-gates.md +0 -16
  101. package/.savepoint/releases/v1/epics/_archived/E05-init-command/Design.md +0 -88
  102. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T001-init-cli-contract.md +0 -22
  103. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T002-target-validation.md +0 -23
  104. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T003-scaffold-writer.md +0 -24
  105. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T004-magic-prompt-and-clipboard.md +0 -23
  106. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T005-dev-deps-install-option.md +0 -24
  107. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T006-init-command-integration.md +0 -28
  108. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/Design.md +0 -53
  109. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T001-delete-dead-src.md +0 -23
  110. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T002-delete-dead-tests.md +0 -26
  111. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T003-delete-assets.md +0 -25
  112. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T004-clean-savepoint.md +0 -28
  113. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T005-rewrite-agents-md.md +0 -28
  114. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T006-clean-package-json.md +0 -23
  115. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T007-verify.md +0 -25
  116. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/Design.md +0 -104
  117. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T001-board-command-data.md +0 -23
  118. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T002-board-view-state.md +0 -24
  119. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T003-transition-gates-and-writes.md +0 -25
  120. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T004-terminal-theme.md +0 -23
  121. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T005-ink-board-ui.md +0 -26
  122. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T006-board-integration-audit-entry.md +0 -24
  123. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/Design.md +0 -88
  124. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T001-audit-cli-contract.md +0 -23
  125. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T002-quality-gate-runner.md +0 -23
  126. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T003-snapshot-and-prompt.md +0 -23
  127. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T004-audit-orchestration-router.md +0 -27
  128. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T005-proposal-validation-apply.md +0 -25
  129. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T006-audit-review-state.md +0 -24
  130. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T007-audit-review-ui.md +0 -26
  131. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T008-audit-pipeline-integration.md +0 -24
  132. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/Design.md +0 -103
  133. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T001-acceptance-criteria-model.md +0 -30
  134. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T002-release-task-set-reader.md +0 -33
  135. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T003-board-data-and-plain-output.md +0 -34
  136. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T004-board-selection-state.md +0 -33
  137. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T005-ink-board-layout-cleanup.md +0 -37
  138. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T006-task-detail-popup.md +0 -36
  139. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T007-templates-acceptance-criteria.md +0 -34
  140. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T008-board-workflow-integration.md +0 -41
  141. package/.savepoint/releases/v1/epics/_archived/E09-doctor-command/Design.md +0 -70
  142. package/.savepoint/releases/v1/epics/_archived/E10-docs-and-packaging/Design.md +0 -68
  143. package/.savepoint/releases/v1/epics/_archived/E11-release-validation/Design.md +0 -68
  144. package/.savepoint/releases/v1/v1-PRD.md +0 -66
  145. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/E01-Detail.md +0 -40
  146. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T001-next-activity-header.md +0 -56
  147. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T002-rename-epic-design-files.md +0 -38
  148. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T003-rename-release-prd.md +0 -28
  149. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T004-update-instruction-files.md +0 -51
  150. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T005-update-cross-references.md +0 -45
  151. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T006-column-and-detail-scrolling.md +0 -68
  152. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T007-column-focus-border-stability.md +0 -57
  153. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/E02-Audit.md +0 -124
  154. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/E02-Detail.md +0 -49
  155. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T001-fix-makefile.md +0 -37
  156. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T002-linux-build-target.md +0 -38
  157. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T003-macos-build-target.md +0 -36
  158. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T004-smoke-tests-and-artifacts.md +0 -59
  159. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/E03-Audit.md +0 -195
  160. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/E03-Detail.md +0 -45
  161. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T001-border-resize-fix.md +0 -40
  162. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T002-next-activity-below-header.md +0 -64
  163. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T003-checkbox-rendering-fix.md +0 -56
  164. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T005-unify-status-glyphs.md +0 -65
  165. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T006-forced-256-color-profile.md +0 -36
  166. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/E04-Audit.md +0 -167
  167. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/E04-Detail.md +0 -51
  168. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T001-sidebar-focusable-navigation.md +0 -65
  169. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T002-epic-detail-overlay.md +0 -73
  170. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T003-epic-status-glyphs.md +0 -73
  171. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/E05-Audit.md +0 -237
  172. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/E05-Detail.md +0 -54
  173. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T001-update-agents-md.md +0 -45
  174. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T002-update-router-md.md +0 -40
  175. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T003-update-design-md.md +0 -47
  176. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T004-implement-m-hotkey.md +0 -98
  177. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T005-update-help-overlay.md +0 -33
  178. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T006-tests-and-quality-gates.md +0 -62
  179. package/.savepoint/releases/v1.1/epics/E06-audit-command/E06-Audit.md +0 -56
  180. package/.savepoint/releases/v1.1/epics/E06-audit-command/E06-Detail.md +0 -63
  181. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T005-proposals.md +0 -44
  182. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T007-apply-close.md +0 -35
  183. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T009-integration.md +0 -40
  184. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T010-audit-file-migration.md +0 -45
  185. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T011-model-tab-state.md +0 -26
  186. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T012-epic-audit-render.md +0 -33
  187. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T013-handle-tab-keys.md +0 -34
  188. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T014-tab-indicator.md +0 -33
  189. package/.savepoint/releases/v1.1/epics/E07-init-command/E07-Audit.md +0 -336
  190. package/.savepoint/releases/v1.1/epics/E07-init-command/E07-Detail.md +0 -61
  191. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T001-cli-entrypoint.md +0 -37
  192. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T002-target-validation.md +0 -28
  193. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T003-scaffold-writer.md +0 -46
  194. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T004-atomic-writes.md +0 -27
  195. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T005-magic-prompt.md +0 -25
  196. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T006-clipboard.md +0 -26
  197. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T007-integration-test.md +0 -26
  198. package/.savepoint/releases/v1.1/epics/E08-board-command/E08-Audit.md +0 -333
  199. package/.savepoint/releases/v1.1/epics/E08-board-command/E08-Detail.md +0 -68
  200. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T001-cli-entrypoint.md +0 -26
  201. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T002-non-tty-fallback.md +0 -27
  202. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T003-tui-app-shell.md +0 -28
  203. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T004-board-model.md +0 -29
  204. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T005-detail-pane.md +0 -27
  205. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T006-status-transitions.md +0 -29
  206. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T007-theme-fallbacks.md +0 -29
  207. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T008-integration-test.md +0 -27
  208. package/.savepoint/releases/v1.1/epics/E09-doctor-command/E09-Audit.md +0 -207
  209. package/.savepoint/releases/v1.1/epics/E09-doctor-command/E09-Detail.md +0 -65
  210. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T001-cli-entrypoint.md +0 -24
  211. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T002-config-router-validation.md +0 -28
  212. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T003-structure-checks.md +0 -29
  213. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T004-dependency-checks.md +0 -27
  214. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T005-audit-orphan-checks.md +0 -28
  215. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T006-quality-gates-report.md +0 -31
  216. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/E11-Detail.md +0 -36
  217. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T001-debug-logging.md +0 -25
  218. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T002-increase-debounce.md +0 -21
  219. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T003-error-handling.md +0 -22
  220. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T004-test-verify.md +0 -29
  221. package/.savepoint/releases/v1.1/epics/E12-validation-fix/E12-Audit.md +0 -444
  222. package/.savepoint/releases/v1.1/epics/E12-validation-fix/E12-Detail.md +0 -45
  223. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T001-default-phase.md +0 -35
  224. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T002-default-status.md +0 -19
  225. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T003-better-errors.md +0 -29
  226. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T004-validate-on-write.md +0 -25
  227. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T005-tests.md +0 -37
  228. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/E13-Audit.md +0 -118
  229. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/E13-Detail.md +0 -73
  230. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T001-safe-cleanup.md +0 -66
  231. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T002-bug-fixes.md +0 -35
  232. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T003-centralize-duplication.md +0 -60
  233. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T004-infrastructure.md +0 -33
  234. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T005-decompose-update.md +0 -37
  235. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T006-async-io.md +0 -40
  236. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T007-test-coverage.md +0 -37
  237. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/E14-Audit.md +0 -267
  238. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/E14-Detail.md +0 -54
  239. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T001-group-model.md +0 -39
  240. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T002-data-interfaces.md +0 -42
  241. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T003-discover-orphans.md +0 -33
  242. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T004-epic-panel-headings.md +0 -35
  243. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T005-shell-tokenization.md +0 -27
  244. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T006-unify-enums.md +0 -29
  245. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T007-testutil-package.md +0 -28
  246. package/.savepoint/releases/v1.1/epics/E15-hardening/E15-Detail.md +0 -43
  247. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T001-benchmarks.md +0 -31
  248. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T002-fuzz-targets.md +0 -28
  249. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T003-debug-flag.md +0 -30
  250. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T004-dist-checksums.md +0 -27
  251. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T005-windows-targets.md +0 -28
  252. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T006-abbreviation-splitting.md +0 -26
  253. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T007-root-test-allowlist.md +0 -28
  254. package/.savepoint/releases/v1.1/epics/_archived/T001-cli-entrypoint.md +0 -25
  255. package/.savepoint/releases/v1.1/epics/_archived/T002-quality-gates.md +0 -27
  256. package/.savepoint/releases/v1.1/epics/_archived/T003-snapshot.md +0 -27
  257. package/.savepoint/releases/v1.1/epics/_archived/T004-ai-reconcile.md +0 -29
  258. package/.savepoint/releases/v1.1/epics/_archived/T006-tui-review.md +0 -31
  259. package/.savepoint/releases/v1.1/epics/_archived/T008-skip-handling.md +0 -34
  260. package/.savepoint/releases/v1.1/v1.1-PRD.md +0 -139
  261. package/.savepoint/router.md +0 -57
  262. package/.savepoint/visual-identity.md +0 -125
  263. package/AGENTS.md +0 -99
  264. package/CLAUDE.md +0 -1
  265. package/GEMINI.md +0 -1
  266. package/Makefile +0 -29
  267. package/agent-skills/ink-tui-design/SKILL.md +0 -309
  268. package/agent-skills/ink-tui-design/references/component-patterns.md +0 -371
  269. package/agent-skills/ink-tui-design/references/hooks-guide.md +0 -436
  270. package/agent-skills/ink-tui-design/references/ink-gotchas.md +0 -330
  271. package/agent-skills/ink-tui-design/references/testing-patterns.md +0 -384
  272. package/agent-skills/savepoint-audit/SKILL.md +0 -87
  273. package/agent-skills/savepoint-build-task/SKILL.md +0 -44
  274. package/agent-skills/savepoint-create-plan/SKILL.md +0 -33
  275. package/agent-skills/savepoint-create-task/SKILL.md +0 -44
  276. package/agent-skills/savepoint-draft-prd/SKILL.md +0 -37
  277. package/agent-skills/savepoint-system-design/SKILL.md +0 -38
  278. package/agent-skills/superpowers/brainstorming/SKILL.md +0 -165
  279. package/agent-skills/superpowers/brainstorming/visual-companion.md +0 -304
  280. package/agent-skills/superpowers/dispatching-parallel-agents/SKILL.md +0 -193
  281. package/agent-skills/superpowers/executing-plans/SKILL.md +0 -77
  282. package/agent-skills/superpowers/finishing-a-development-branch/SKILL.md +0 -213
  283. package/agent-skills/superpowers/receiving-code-review/SKILL.md +0 -226
  284. package/agent-skills/superpowers/requesting-code-review/SKILL.md +0 -115
  285. package/agent-skills/superpowers/requesting-code-review/code-reviewer.md +0 -160
  286. package/agent-skills/superpowers/subagent-driven-development/SKILL.md +0 -292
  287. package/agent-skills/superpowers/subagent-driven-development/code-quality-reviewer-prompt.md +0 -27
  288. package/agent-skills/superpowers/subagent-driven-development/implementer-prompt.md +0 -113
  289. package/agent-skills/superpowers/subagent-driven-development/spec-reviewer-prompt.md +0 -61
  290. package/agent-skills/superpowers/systematic-debugging/SKILL.md +0 -305
  291. package/agent-skills/superpowers/systematic-debugging/condition-based-waiting.md +0 -122
  292. package/agent-skills/superpowers/systematic-debugging/defense-in-depth.md +0 -130
  293. package/agent-skills/superpowers/systematic-debugging/root-cause-tracing.md +0 -183
  294. package/agent-skills/superpowers/test-driven-development/SKILL.md +0 -389
  295. package/agent-skills/superpowers/test-driven-development/testing-anti-patterns.md +0 -317
  296. package/agent-skills/superpowers/verification-before-completion/SKILL.md +0 -147
  297. package/agent-skills/superpowers/writing-plans/SKILL.md +0 -159
  298. package/agent-skills/superpowers/writing-plans/plan-document-reviewer-prompt.md +0 -49
  299. package/agent_skills_test.go +0 -91
  300. package/assets/banner.png +0 -0
  301. package/assets/logo.png +0 -0
  302. package/assets/strawman.png +0 -0
  303. package/cmd/board.go +0 -59
  304. package/cmd/board_test.go +0 -137
  305. package/cmd/doctor.go +0 -53
  306. package/cmd/doctor_test.go +0 -146
  307. package/cmd/init.go +0 -63
  308. package/cmd/init_test.go +0 -104
  309. package/go.mod +0 -36
  310. package/go.sum +0 -75
  311. package/internal/board/board.go +0 -177
  312. package/internal/board/board_test.go +0 -168
  313. package/internal/board/card.go +0 -129
  314. package/internal/board/card_test.go +0 -254
  315. package/internal/board/column.go +0 -127
  316. package/internal/board/column_test.go +0 -139
  317. package/internal/board/detail.go +0 -185
  318. package/internal/board/detail_test.go +0 -340
  319. package/internal/board/epic_panel.go +0 -262
  320. package/internal/board/epic_panel_test.go +0 -869
  321. package/internal/board/help.go +0 -41
  322. package/internal/board/help_test.go +0 -86
  323. package/internal/board/integration_test.go +0 -266
  324. package/internal/board/interfaces.go +0 -65
  325. package/internal/board/interfaces_test.go +0 -114
  326. package/internal/board/io.go +0 -93
  327. package/internal/board/layout.go +0 -68
  328. package/internal/board/layout_test.go +0 -106
  329. package/internal/board/model.go +0 -235
  330. package/internal/board/model_test.go +0 -67
  331. package/internal/board/plain.go +0 -88
  332. package/internal/board/plain_test.go +0 -117
  333. package/internal/board/release.go +0 -34
  334. package/internal/board/release_test.go +0 -177
  335. package/internal/board/render_policy_test.go +0 -77
  336. package/internal/board/status.go +0 -23
  337. package/internal/board/theme.go +0 -24
  338. package/internal/board/theme_test.go +0 -31
  339. package/internal/board/transitions.go +0 -113
  340. package/internal/board/transitions_test.go +0 -164
  341. package/internal/board/tui.go +0 -32
  342. package/internal/board/update.go +0 -556
  343. package/internal/board/update_test.go +0 -575
  344. package/internal/board/util.go +0 -76
  345. package/internal/board/view.go +0 -317
  346. package/internal/board/view_test.go +0 -315
  347. package/internal/board/watch.go +0 -130
  348. package/internal/buildtool/main.go +0 -211
  349. package/internal/buildtool/main_test.go +0 -46
  350. package/internal/data/config.go +0 -101
  351. package/internal/data/config_test.go +0 -122
  352. package/internal/data/discover.go +0 -178
  353. package/internal/data/discover_test.go +0 -130
  354. package/internal/data/errors.go +0 -13
  355. package/internal/data/lifecycle.go +0 -44
  356. package/internal/data/lifecycle_test.go +0 -41
  357. package/internal/data/parser.go +0 -242
  358. package/internal/data/parser_test.go +0 -281
  359. package/internal/data/router.go +0 -52
  360. package/internal/data/router_test.go +0 -35
  361. package/internal/data/task.go +0 -57
  362. package/internal/data/task_test.go +0 -51
  363. package/internal/data/write.go +0 -218
  364. package/internal/data/write_test.go +0 -623
  365. package/internal/doctor/checks.go +0 -567
  366. package/internal/doctor/checks_test.go +0 -716
  367. package/internal/doctor/gates.go +0 -193
  368. package/internal/doctor/gates_test.go +0 -166
  369. package/internal/doctor/interfaces.go +0 -64
  370. package/internal/doctor/interfaces_test.go +0 -104
  371. package/internal/doctor/repairs.go +0 -80
  372. package/internal/doctor/repairs_test.go +0 -81
  373. package/internal/doctor/report.go +0 -157
  374. package/internal/doctor/report_test.go +0 -89
  375. package/internal/init/clipboard.go +0 -146
  376. package/internal/init/clipboard_test.go +0 -74
  377. package/internal/init/install.go +0 -16
  378. package/internal/init/integration_test.go +0 -197
  379. package/internal/init/prompt.go +0 -14
  380. package/internal/init/prompt_test.go +0 -77
  381. package/internal/init/scaffold.go +0 -59
  382. package/internal/init/scaffold_test.go +0 -179
  383. package/internal/init/template_freshness_test.go +0 -56
  384. package/internal/init/validate.go +0 -85
  385. package/internal/init/validate_test.go +0 -141
  386. package/internal/init/write.go +0 -73
  387. package/internal/init/write_test.go +0 -91
  388. package/internal/styles/palette.go +0 -49
  389. package/internal/styles/styles.go +0 -139
  390. package/internal/styles/styles_test.go +0 -133
  391. package/internal/testutil/fixture.go +0 -113
  392. package/internal/testutil/fs.go +0 -26
  393. package/main.go +0 -117
  394. package/project-audit/audit_report_glm_5.1.md +0 -411
  395. package/project-audit/audit_report_opus_4.6 +0 -406
  396. package/project-audit/consolidated-audit-report.md +0 -456
  397. package/scripts/vitest-preload.cjs +0 -95
  398. package/templates/project/.savepoint/Design.md +0 -47
  399. package/templates/project/.savepoint/PRD.md +0 -34
  400. package/templates/project/.savepoint/config.yml +0 -27
  401. package/templates/project/.savepoint/router.md +0 -153
  402. package/templates/project/.savepoint/visual-identity.md +0 -122
  403. package/templates/project/AGENTS.md +0 -88
  404. package/templates/project/agent-skills/savepoint-audit/SKILL.md +0 -87
  405. package/templates/project/agent-skills/savepoint-build-task/SKILL.md +0 -44
  406. package/templates/project/agent-skills/savepoint-create-plan/SKILL.md +0 -33
  407. package/templates/project/agent-skills/savepoint-create-task/SKILL.md +0 -44
  408. package/templates/project/agent-skills/savepoint-draft-prd/SKILL.md +0 -37
  409. package/templates/project/agent-skills/savepoint-system-design/SKILL.md +0 -38
  410. package/templates/prompts/audit-reconciliation.prompt.md +0 -72
  411. package/templates/prompts/design.prompt.md +0 -45
  412. package/templates/prompts/epic-design.prompt.md +0 -43
  413. package/templates/prompts/magic-prompt.prompt.md +0 -7
  414. package/templates/prompts/prd.prompt.md +0 -42
  415. package/templates/prompts/task-breakdown.prompt.md +0 -54
  416. package/templates/prompts/task-building.prompt.md +0 -38
  417. package/templates/prompts/task-planning.prompt.md +0 -53
  418. package/templates/release/v1/PRD.md +0 -37
@@ -1,41 +0,0 @@
1
- package board
2
-
3
- import (
4
- "strings"
5
-
6
- "github.com/opencode/savepoint/internal/styles"
7
- )
8
-
9
- const helpBorderPad = 4 // rounded border (2) + padding (2x1)
10
-
11
- // RenderHelp renders the keyboard shortcut reference overlay.
12
- func RenderHelp(width int) string {
13
- inner := width - helpBorderPad
14
- if inner < 4 {
15
- inner = 4
16
- }
17
-
18
- lines := []string{
19
- styles.ColumnTitleFocused.Render("KEYBOARD SHORTCUTS"),
20
- strings.Repeat("─", inner),
21
- helpRow("h / left", "previous column"),
22
- helpRow("l / right", "next column"),
23
- helpRow("enter", "open task detail / select item"),
24
- helpRow("e", "open epic selector on narrow screens"),
25
- helpRow("r", "open release selector"),
26
- helpRow("p", "mark focused task as priority"),
27
- helpRow("up / k", "move selector up"),
28
- helpRow("down / j", "move selector down"),
29
- helpRow("?", "open help"),
30
- helpRow("esc / q", "close overlay"),
31
- helpRow("q / ctrl+c", "quit from board"),
32
- "",
33
- styles.CardMeta.Render("esc/q:close"),
34
- }
35
-
36
- return styles.DetailOverlay.Width(width).Render(strings.Join(lines, "\n"))
37
- }
38
-
39
- func helpRow(key, action string) string {
40
- return styles.ColumnTitle.Render(key+": ") + styles.CardMeta.Render(action)
41
- }
@@ -1,86 +0,0 @@
1
- package board
2
-
3
- import (
4
- "strings"
5
- "testing"
6
-
7
- tea "github.com/charmbracelet/bubbletea"
8
- )
9
-
10
- func TestRenderHelp_containsTitle(t *testing.T) {
11
- got := RenderHelp(60)
12
- if !strings.Contains(got, "KEYBOARD SHORTCUTS") {
13
- t.Error("RenderHelp missing title")
14
- }
15
- }
16
-
17
- func TestRenderHelp_containsShortcuts(t *testing.T) {
18
- got := RenderHelp(60)
19
- for _, shortcut := range []string{
20
- "h / left",
21
- "l / right",
22
- "enter",
23
- "e",
24
- "r",
25
- "p",
26
- "up / k",
27
- "down / j",
28
- "?",
29
- "esc / q",
30
- "q / ctrl+c",
31
- } {
32
- if !strings.Contains(got, shortcut) {
33
- t.Errorf("RenderHelp missing shortcut %q", shortcut)
34
- }
35
- }
36
- }
37
-
38
- func TestRenderHelp_containsCloseHint(t *testing.T) {
39
- got := RenderHelp(60)
40
- if !strings.Contains(got, "esc/q:close") {
41
- t.Error("RenderHelp missing close hint")
42
- }
43
- }
44
-
45
- func TestUpdate_questionMarkOpensHelpOverlay(t *testing.T) {
46
- m := NewModel(nil, "v1", "E04")
47
- got, _ := m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("?")})
48
- updated := requireModel(t, got)
49
- if updated.Overlay != OverlayHelp {
50
- t.Errorf("Overlay = %q, want %q", updated.Overlay, OverlayHelp)
51
- }
52
- }
53
-
54
- func TestUpdate_helpOverlayEscCloses(t *testing.T) {
55
- m := NewModel(nil, "v1", "E04")
56
- m.Overlay = OverlayHelp
57
- got, _ := m.Update(tea.KeyMsg{Type: tea.KeyEsc})
58
- updated := requireModel(t, got)
59
- if updated.Overlay != OverlayNone {
60
- t.Errorf("Overlay = %q after esc, want none", updated.Overlay)
61
- }
62
- }
63
-
64
- func TestUpdate_helpOverlayQCloses(t *testing.T) {
65
- m := NewModel(nil, "v1", "E04")
66
- m.Overlay = OverlayHelp
67
- got, _ := m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("q")})
68
- updated := requireModel(t, got)
69
- if updated.Overlay != OverlayNone {
70
- t.Errorf("Overlay = %q after q, want none", updated.Overlay)
71
- }
72
- }
73
-
74
- func TestView_helpOverlayRendered(t *testing.T) {
75
- m := NewModel(nil, "v1", "E04")
76
- m.Width = 100
77
- m.Height = 30
78
- m.Overlay = OverlayHelp
79
- got := m.View()
80
- if !strings.Contains(got, "KEYBOARD SHORTCUTS") {
81
- t.Error("View() with OverlayHelp missing help header")
82
- }
83
- if !strings.Contains(got, "q / ctrl+c") {
84
- t.Error("View() with OverlayHelp missing quit shortcut")
85
- }
86
- }
@@ -1,266 +0,0 @@
1
- package board
2
-
3
- import (
4
- "os"
5
- "path/filepath"
6
- "strings"
7
- "testing"
8
- "time"
9
-
10
- tea "github.com/charmbracelet/bubbletea"
11
- "github.com/opencode/savepoint/internal/data"
12
- "github.com/opencode/savepoint/internal/testutil"
13
- )
14
-
15
- // writeTaskWithBody creates a task file with a body section to verify content preservation.
16
- func writeTaskWithBody(t *testing.T, root, release, epic, taskSlug string, column data.ColumnType, body string) string {
17
- t.Helper()
18
- tf := testutil.TaskFixture{
19
- Slug: taskSlug,
20
- Release: release,
21
- Status: string(column),
22
- Objective: "Test task",
23
- Body: body,
24
- }
25
- if column == data.ColumnInProgress {
26
- tf.Phase = "build"
27
- }
28
- testutil.WriteTask(t, root, release, epic, tf)
29
- return filepath.Join(root, "releases", release, "epics", epic, "tasks", taskSlug+".md")
30
- }
31
-
32
- // TestBoardPipeline_endToEnd loads a real project from disk and renders the full board view.
33
- func TestBoardPipeline_endToEnd(t *testing.T) {
34
- projectRoot := t.TempDir()
35
- savepointRoot := filepath.Join(projectRoot, ".savepoint")
36
- testutil.WriteRouter(t, savepointRoot, "task-building", "v1", "E01-init", "", "test")
37
- writeTask(t, savepointRoot, "v1", "E01-init", "T001-scaffold", data.ColumnPlanned)
38
- writeTask(t, savepointRoot, "v1", "E01-init", "T002-validate", data.ColumnInProgress)
39
- writeTask(t, savepointRoot, "v1", "E01-init", "T003-done-task", data.ColumnDone)
40
-
41
- model, err := newProjectModel(projectRoot, "", "")
42
- if err != nil {
43
- t.Fatalf("newProjectModel: %v", err)
44
- }
45
- if model.Watcher != nil {
46
- t.Cleanup(func() { model.Watcher.Close() })
47
- }
48
-
49
- model.Width = 120
50
- model.Height = 40
51
- view := model.View()
52
-
53
- for _, want := range []string{"PLANNED", "IN PROGRESS", "DONE", "T001", "T002", "T003"} {
54
- if !strings.Contains(view, want) {
55
- t.Errorf("board view missing %q", want)
56
- }
57
- }
58
- }
59
-
60
- // TestRunPlainOutput_endToEnd calls runPlainOutput against a real temp project root.
61
- func TestRunPlainOutput_endToEnd(t *testing.T) {
62
- projectRoot := t.TempDir()
63
- savepointRoot := filepath.Join(projectRoot, ".savepoint")
64
- testutil.WriteRouter(t, savepointRoot, "task-building", "v1", "E01-init", "", "test")
65
- writeTask(t, savepointRoot, "v1", "E01-init", "T001-scaffold", data.ColumnPlanned)
66
- writeTask(t, savepointRoot, "v1", "E01-init", "T002-validate", data.ColumnDone)
67
-
68
- model, err := newProjectModel(projectRoot, "", "")
69
- if err != nil {
70
- t.Fatalf("newProjectModel: %v", err)
71
- }
72
- if model.Watcher != nil {
73
- t.Cleanup(func() { model.Watcher.Close() })
74
- }
75
-
76
- out := RenderPlainTable(model)
77
-
78
- if !strings.Contains(out, plainNonTTYWarning) {
79
- t.Error("plain output missing non-TTY warning")
80
- }
81
- for _, want := range []string{"PLANNED", "DONE", "T001-scaffold", "T002-validate"} {
82
- if !strings.Contains(out, want) {
83
- t.Errorf("plain output missing %q", want)
84
- }
85
- }
86
- }
87
-
88
- // TestStatusWrite_preservesTaskBody advances a task via space key and verifies the body text is unchanged.
89
- func TestStatusWrite_preservesTaskBody(t *testing.T) {
90
- root := t.TempDir()
91
- body := "## Acceptance Criteria\n\n- [ ] thing one\n- [ ] thing two\n"
92
- path := writeTaskWithBody(t, root, "v1", "E01-init", "T001-scaffold", data.ColumnPlanned, body)
93
-
94
- fi, err := os.Stat(path)
95
- if err != nil {
96
- t.Fatal(err)
97
- }
98
- task := data.Task{
99
- ID: "E01-init/T001-scaffold",
100
- Column: data.ColumnPlanned,
101
- Path: path,
102
- Mtime: fi.ModTime(),
103
- }
104
-
105
- m := NewModel([]data.Task{task}, "v1", "E01-init")
106
- m.FocusedColumn = data.ColumnPlanned
107
-
108
- got, cmd := m.Update(tea.KeyMsg{Type: tea.KeySpace})
109
- msg := cmd()
110
- got2, _ := got.Update(msg)
111
- updated := requireModel(t, got2)
112
-
113
- if updated.AllTasks[0].Column != data.ColumnInProgress {
114
- t.Errorf("Column = %q, want in_progress", updated.AllTasks[0].Column)
115
- }
116
-
117
- raw, err := os.ReadFile(path)
118
- if err != nil {
119
- t.Fatal(err)
120
- }
121
- if !strings.Contains(string(raw), body) {
122
- t.Errorf("task body was altered after status write; got:\n%s", raw)
123
- }
124
- }
125
-
126
- // TestMtimeConflict_directDetection verifies WriteTaskStatus returns ErrMtimeConflict on mtime mismatch.
127
- func TestMtimeConflict_directDetection(t *testing.T) {
128
- dir := t.TempDir()
129
- path := filepath.Join(dir, "T001.md")
130
- content := "---\nid: E01/T001\nstatus: planned\nphase: build\n---\n\n# Task\n"
131
- if err := os.WriteFile(path, []byte(content), 0644); err != nil {
132
- t.Fatal(err)
133
- }
134
-
135
- task := &data.Task{
136
- ID: "E01/T001",
137
- Column: data.ColumnInProgress,
138
- Stage: data.StageBuild,
139
- }
140
- staleTime := time.Now().Add(-time.Hour)
141
- err := data.WriteTaskStatus(path, task, staleTime)
142
- if err != data.ErrMtimeConflict {
143
- t.Errorf("WriteTaskStatus with stale mtime = %v, want ErrMtimeConflict", err)
144
- }
145
- }
146
-
147
- // TestMtimeConflict_boardWarns verifies the board surfaces an mtime conflict instead of overwriting external edits.
148
- func TestMtimeConflict_boardWarns(t *testing.T) {
149
- path := filepath.Join(t.TempDir(), "T001.md")
150
- content := "---\nid: E01/T001\nstatus: in_progress\nphase: build\n---\n\n# Task\n"
151
- if err := os.WriteFile(path, []byte(content), 0644); err != nil {
152
- t.Fatal(err)
153
- }
154
- fi, err := os.Stat(path)
155
- if err != nil {
156
- t.Fatal(err)
157
- }
158
-
159
- task := data.Task{
160
- ID: "E01/T001",
161
- Column: data.ColumnInProgress,
162
- Stage: data.StageBuild,
163
- Path: path,
164
- Mtime: fi.ModTime().Add(-time.Minute), // intentionally stale
165
- }
166
- m := NewModel([]data.Task{task}, "v1", "E01")
167
- m.FocusedColumn = data.ColumnInProgress
168
-
169
- got, cmd := m.Update(tea.KeyMsg{Type: tea.KeySpace})
170
- msg := cmd()
171
- got2, _ := got.Update(msg)
172
- updated := requireModel(t, got2)
173
-
174
- if !strings.Contains(updated.StatusMessage, "mtime conflict") {
175
- t.Errorf("StatusMessage = %q, want mtime conflict warning", updated.StatusMessage)
176
- }
177
-
178
- raw, err := os.ReadFile(path)
179
- if err != nil {
180
- t.Fatal(err)
181
- }
182
- if !strings.Contains(string(raw), "phase: build") {
183
- t.Errorf("task file was overwritten despite mtime conflict:\n%s", raw)
184
- }
185
- }
186
-
187
- // TestReleaseFilter_showsOnlyMatchingRelease verifies the --release flag filters tasks.
188
- func TestReleaseFilter_showsOnlyMatchingRelease(t *testing.T) {
189
- projectRoot := t.TempDir()
190
- savepointRoot := filepath.Join(projectRoot, ".savepoint")
191
- testutil.WriteRouter(t, savepointRoot, "task-building", "v1", "E01-init", "", "test")
192
- writeTask(t, savepointRoot, "v1", "E01-init", "T001-v1-task", data.ColumnPlanned)
193
- writeTask(t, savepointRoot, "v2", "E01-init", "T001-v2-task", data.ColumnPlanned)
194
-
195
- model, err := newProjectModel(projectRoot, "v2", "")
196
- if err != nil {
197
- t.Fatalf("newProjectModel: %v", err)
198
- }
199
- if model.Watcher != nil {
200
- t.Cleanup(func() { model.Watcher.Close() })
201
- }
202
-
203
- if model.SelectedRelease != "v2" {
204
- t.Errorf("SelectedRelease = %q, want v2", model.SelectedRelease)
205
- }
206
- planned := model.Tasks[data.ColumnPlanned]
207
- for _, task := range planned {
208
- if task.Release != "v2" {
209
- t.Errorf("task %q has release %q, want v2 only", task.ID, task.Release)
210
- }
211
- }
212
- }
213
-
214
- // TestEpicFilter_showsOnlyMatchingEpic verifies the --epic flag filters tasks.
215
- func TestEpicFilter_showsOnlyMatchingEpic(t *testing.T) {
216
- projectRoot := t.TempDir()
217
- savepointRoot := filepath.Join(projectRoot, ".savepoint")
218
- testutil.WriteRouter(t, savepointRoot, "task-building", "v1", "E01-init", "", "test")
219
- writeTask(t, savepointRoot, "v1", "E01-init", "T001-alpha", data.ColumnPlanned)
220
- writeTask(t, savepointRoot, "v1", "E02-build", "T001-beta", data.ColumnPlanned)
221
-
222
- model, err := newProjectModel(projectRoot, "v1", "E02-build")
223
- if err != nil {
224
- t.Fatalf("newProjectModel: %v", err)
225
- }
226
- if model.Watcher != nil {
227
- t.Cleanup(func() { model.Watcher.Close() })
228
- }
229
-
230
- if model.SelectedEpic != "E02-build" {
231
- t.Errorf("SelectedEpic = %q, want E02-build", model.SelectedEpic)
232
- }
233
- planned := model.Tasks[data.ColumnPlanned]
234
- for _, task := range planned {
235
- if task.Epic != "E02-build" {
236
- t.Errorf("task %q has epic %q, want E02-build only", task.ID, task.Epic)
237
- }
238
- }
239
- }
240
-
241
- // TestDetailPane_opensOnEnter verifies enter key opens the detail overlay.
242
- func TestDetailPane_opensOnEnter(t *testing.T) {
243
- tasks := []data.Task{{ID: "E01/T001", Title: "Scaffold init", Column: data.ColumnPlanned}}
244
- m := NewModel(tasks, "v1", "E01")
245
- m.FocusedColumn = data.ColumnPlanned
246
-
247
- got, _ := m.Update(tea.KeyMsg{Type: tea.KeyEnter})
248
- updated := requireModel(t, got)
249
-
250
- if updated.Overlay != OverlayDetail {
251
- t.Errorf("Overlay = %q, want %q", updated.Overlay, OverlayDetail)
252
- }
253
- }
254
-
255
- // TestDetailPane_escClosesOverlay verifies esc dismisses the detail overlay.
256
- func TestDetailPane_escClosesOverlay(t *testing.T) {
257
- m := NewModel(nil, "v1", "E01")
258
- m.Overlay = OverlayDetail
259
-
260
- got, _ := m.Update(tea.KeyMsg{Type: tea.KeyEsc})
261
- updated := requireModel(t, got)
262
-
263
- if updated.Overlay != OverlayNone {
264
- t.Errorf("Overlay = %q after esc, want none", updated.Overlay)
265
- }
266
- }
@@ -1,65 +0,0 @@
1
- package board
2
-
3
- import "github.com/opencode/savepoint/internal/data"
4
-
5
- // taskDiscoverer provides project traversal for board loading.
6
- type taskDiscoverer interface {
7
- FindSavepointRoot(start string) (string, error)
8
- ListReleases(root string) ([]data.ReleaseInfo, error)
9
- ListEpics(root, release string) ([]data.EpicInfo, error)
10
- ListTasks(root, release, epic string) ([]data.TaskInfo, error)
11
- }
12
-
13
- // taskParser parses Savepoint frontmatter and task files for board loading.
14
- type taskParser interface {
15
- ParseFrontmatter(content string) (map[string]any, error)
16
- ParseTaskFile(path string, content string) (*data.Task, error)
17
- }
18
-
19
- // configReader reads board display configuration.
20
- type configReader interface {
21
- Read(path string) (*data.Config, error)
22
- }
23
-
24
- // routerReader parses router state from router.md content.
25
- type routerReader interface {
26
- ReadState(content string) (*data.RouterState, error)
27
- }
28
-
29
- // ModelDependencies contains board data-access dependencies.
30
- type ModelDependencies struct {
31
- Discoverer taskDiscoverer
32
- Parser taskParser
33
- ConfigReader configReader
34
- RouterReader routerReader
35
- }
36
-
37
- func defaultModelDependencies() ModelDependencies {
38
- return ModelDependencies{
39
- Discoverer: data.NewDiscover(),
40
- Parser: data.NewParser(),
41
- ConfigReader: data.NewConfigReader(),
42
- RouterReader: data.NewRouterReader(),
43
- }
44
- }
45
-
46
- func modelDependencies(overrides []ModelDependencies) ModelDependencies {
47
- deps := defaultModelDependencies()
48
- if len(overrides) == 0 {
49
- return deps
50
- }
51
- override := overrides[0]
52
- if override.Discoverer != nil {
53
- deps.Discoverer = override.Discoverer
54
- }
55
- if override.Parser != nil {
56
- deps.Parser = override.Parser
57
- }
58
- if override.ConfigReader != nil {
59
- deps.ConfigReader = override.ConfigReader
60
- }
61
- if override.RouterReader != nil {
62
- deps.RouterReader = override.RouterReader
63
- }
64
- return deps
65
- }
@@ -1,114 +0,0 @@
1
- package board
2
-
3
- import (
4
- "path/filepath"
5
- "testing"
6
-
7
- "github.com/opencode/savepoint/internal/data"
8
- "github.com/opencode/savepoint/internal/testutil"
9
- )
10
-
11
- type stubBoardDiscoverer struct {
12
- root string
13
- releases []data.ReleaseInfo
14
- epics map[string][]data.EpicInfo
15
- tasks map[string][]data.TaskInfo
16
- findCalls int
17
- }
18
-
19
- func (d *stubBoardDiscoverer) FindSavepointRoot(start string) (string, error) {
20
- d.findCalls++
21
- return d.root, nil
22
- }
23
-
24
- func (d *stubBoardDiscoverer) ListReleases(root string) ([]data.ReleaseInfo, error) {
25
- return d.releases, nil
26
- }
27
-
28
- func (d *stubBoardDiscoverer) ListEpics(root, release string) ([]data.EpicInfo, error) {
29
- return d.epics[release], nil
30
- }
31
-
32
- func (d *stubBoardDiscoverer) ListTasks(root, release, epic string) ([]data.TaskInfo, error) {
33
- return d.tasks[release+"/"+epic], nil
34
- }
35
-
36
- type countingBoardParser struct {
37
- parser *data.Parser
38
- frontmatterCalls int
39
- taskFileCalls int
40
- }
41
-
42
- func (p *countingBoardParser) ParseFrontmatter(content string) (map[string]any, error) {
43
- p.frontmatterCalls++
44
- return p.parser.ParseFrontmatter(content)
45
- }
46
-
47
- func (p *countingBoardParser) ParseTaskFile(path string, content string) (*data.Task, error) {
48
- p.taskFileCalls++
49
- return p.parser.ParseTaskFile(path, content)
50
- }
51
-
52
- type stubBoardRouterReader struct {
53
- state *data.RouterState
54
- calls int
55
- }
56
-
57
- func (r *stubBoardRouterReader) ReadState(content string) (*data.RouterState, error) {
58
- r.calls++
59
- return r.state, nil
60
- }
61
-
62
- func TestNewProjectModelUsesInjectedInterfaces(t *testing.T) {
63
- projectRoot := t.TempDir()
64
- savepointRoot := filepath.Join(projectRoot, ".savepoint")
65
- epicPath := filepath.Join(savepointRoot, "releases", "v9", "epics", "E01-mock")
66
- taskPath := filepath.Join(epicPath, "tasks", "T001-mock.md")
67
-
68
- testutil.WriteFile(t, filepath.Join(savepointRoot, "router.md"), "# router")
69
- testutil.WriteFile(t, filepath.Join(epicPath, "E01-Detail.md"), "---\ntype: epic-design\nstatus: planned\n---\n\n# Epic\n")
70
- testutil.WriteFile(t, taskPath, "---\nid: E01-mock/T001-mock\nstatus: planned\nobjective: Mock task\ndepends_on: []\n---\n\n# Task\n")
71
-
72
- discoverer := &stubBoardDiscoverer{
73
- root: savepointRoot,
74
- releases: []data.ReleaseInfo{{
75
- ID: "v9",
76
- Path: filepath.Join(savepointRoot, "releases", "v9"),
77
- }},
78
- epics: map[string][]data.EpicInfo{
79
- "v9": {{ID: "E01-mock", Path: epicPath}},
80
- },
81
- tasks: map[string][]data.TaskInfo{
82
- "v9/E01-mock": {{ID: "T001-mock", Path: taskPath}},
83
- },
84
- }
85
- parser := &countingBoardParser{parser: data.NewParser()}
86
- router := &stubBoardRouterReader{state: &data.RouterState{
87
- State: "task-building",
88
- Release: "v9",
89
- Epic: "E01-mock",
90
- Task: "E01-mock/T001-mock",
91
- }}
92
-
93
- model, err := newProjectModelWithDependencies(projectRoot, "", "", ModelDependencies{
94
- Discoverer: discoverer,
95
- Parser: parser,
96
- RouterReader: router,
97
- })
98
- if err != nil {
99
- t.Fatalf("newProjectModelWithDependencies() error = %v", err)
100
- }
101
-
102
- if discoverer.findCalls != 1 {
103
- t.Fatalf("FindSavepointRoot calls = %d, want 1", discoverer.findCalls)
104
- }
105
- if router.calls != 1 {
106
- t.Fatalf("ReadState calls = %d, want 1", router.calls)
107
- }
108
- if parser.frontmatterCalls != 1 || parser.taskFileCalls != 1 {
109
- t.Fatalf("parser calls = frontmatter:%d task:%d, want 1 each", parser.frontmatterCalls, parser.taskFileCalls)
110
- }
111
- if got := model.Tasks[data.ColumnPlanned][0].ID; got != "E01-mock/T001-mock" {
112
- t.Fatalf("loaded task = %q, want injected task", got)
113
- }
114
- }
@@ -1,93 +0,0 @@
1
- package board
2
-
3
- import (
4
- "os"
5
- "path/filepath"
6
- "time"
7
-
8
- tea "github.com/charmbracelet/bubbletea"
9
- "github.com/opencode/savepoint/internal/data"
10
- )
11
-
12
- func writeRouterTaskCmd(root string, task data.Task, reader routerReader) tea.Cmd {
13
- return func() tea.Msg {
14
- routerPath := filepath.Join(root, "router.md")
15
- fi, err := os.Stat(routerPath)
16
- if err != nil {
17
- return errorMsg{message: err.Error()}
18
- }
19
- content, err := os.ReadFile(routerPath)
20
- if err != nil {
21
- return errorMsg{message: err.Error()}
22
- }
23
- state, err := reader.ReadState(string(content))
24
- if err != nil {
25
- return errorMsg{message: err.Error()}
26
- }
27
- state.Release = task.Release
28
- state.Epic = task.Epic
29
- state.State = "task-building"
30
- state.Task = task.ID
31
- state.NextAction = "Build " + task.ID + "."
32
- if err := data.WriteRouterState(root, state, fi.ModTime()); err != nil {
33
- return errorMsg{message: err.Error()}
34
- }
35
- message := "Router set to " + task.Release + " " + task.Epic + "/" + shortID(task.ID)
36
- return routerWriteMsg{message: message, state: state, taskID: task.ID}
37
- }
38
- }
39
-
40
- func writeRouterReleaseEpicCmd(root, selectedEpic, selectedRelease string, reader routerReader) tea.Cmd {
41
- return func() tea.Msg {
42
- routerPath := filepath.Join(root, "router.md")
43
- fi, err := os.Stat(routerPath)
44
- if err != nil {
45
- return errorMsg{message: err.Error()}
46
- }
47
- content, err := os.ReadFile(routerPath)
48
- if err != nil {
49
- return errorMsg{message: err.Error()}
50
- }
51
- state, err := reader.ReadState(string(content))
52
- if err != nil {
53
- return errorMsg{message: err.Error()}
54
- }
55
- state.Epic = shortID(selectedEpic)
56
- state.Release = selectedRelease
57
- if err := data.WriteRouterState(root, state, fi.ModTime()); err != nil {
58
- return errorMsg{message: err.Error()}
59
- }
60
- return routerWriteMsg{state: state}
61
- }
62
- }
63
-
64
- func writeTaskStatusCmd(orig, next data.Task, expectedMtime time.Time, prefix string) tea.Cmd {
65
- return func() tea.Msg {
66
- if err := data.WriteTaskStatus(next.Path, &next, expectedMtime); err != nil {
67
- return errorMsg{message: taskWriteErrorMessage(err)}
68
- }
69
- fi, err := os.Stat(next.Path)
70
- if err != nil {
71
- return errorMsg{message: err.Error()}
72
- }
73
- next.Mtime = fi.ModTime()
74
- return taskWriteMsg{prefix: prefix, next: next}
75
- }
76
- }
77
-
78
- func readEpicDetailCmd(epicDir, shortIDStr string) tea.Cmd {
79
- return func() tea.Msg {
80
- content := readEpicDetailFile(epicDir, shortIDStr)
81
- return epicDetailMsg{content: content}
82
- }
83
- }
84
-
85
- func readEpicAuditCmd(epicDir, shortIDStr string) tea.Cmd {
86
- return func() tea.Msg {
87
- raw, err := os.ReadFile(filepath.Join(epicDir, shortIDStr+"-Audit.md"))
88
- if err != nil {
89
- return auditContentMsg{content: "(no audit available)"}
90
- }
91
- return auditContentMsg{content: string(raw)}
92
- }
93
- }