savepoint 1.0.4 → 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 (425) hide show
  1. package/package.json +10 -3
  2. package/savepoint.exe +0 -0
  3. package/.claude/settings.local.json +0 -38
  4. package/.github/workflows/ci.yml +0 -20
  5. package/.golangci.yml +0 -11
  6. package/.prettierignore +0 -4
  7. package/.savepoint/Design.md +0 -207
  8. package/.savepoint/PRD.md +0 -58
  9. package/.savepoint/config.yml +0 -27
  10. package/.savepoint/releases/v1/epics/E01-go-setup/E01-Detail.md +0 -39
  11. package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T001-init-module.md +0 -42
  12. package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T002-entrypoint.md +0 -23
  13. package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T003-directory-structure.md +0 -24
  14. package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T004-makefile.md +0 -23
  15. package/.savepoint/releases/v1/epics/E02-data-readers/E02-Detail.md +0 -61
  16. package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T001-task-struct.md +0 -29
  17. package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T002-frontmatter-parser.md +0 -30
  18. package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T003-router-reader.md +0 -29
  19. package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T004-config-reader.md +0 -29
  20. package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T005-discovery.md +0 -30
  21. package/.savepoint/releases/v1/epics/E03-board-tui-core/E03-Detail.md +0 -38
  22. package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T001-model.md +0 -29
  23. package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T002-update-loop.md +0 -30
  24. package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T003-view.md +0 -34
  25. package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T004-styles.md +0 -29
  26. package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T005-layout.md +0 -42
  27. package/.savepoint/releases/v1/epics/E04-board-components/E04-Detail.md +0 -44
  28. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T001-column.md +0 -34
  29. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T002-card.md +0 -33
  30. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T003-epic-panel.md +0 -49
  31. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T004-detail-overlay.md +0 -40
  32. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T005-release-dropdown.md +0 -33
  33. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T006-help-overlay.md +0 -34
  34. package/.savepoint/releases/v1/epics/E05-phase-transitions/E05-Detail.md +0 -38
  35. package/.savepoint/releases/v1/epics/E05-phase-transitions/tasks/T001-phase-stepping.md +0 -29
  36. package/.savepoint/releases/v1/epics/E05-phase-transitions/tasks/T002-gates.md +0 -31
  37. package/.savepoint/releases/v1/epics/E05-phase-transitions/tasks/T003-write-task.md +0 -31
  38. package/.savepoint/releases/v1/epics/E05-phase-transitions/tasks/T004-write-router.md +0 -31
  39. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/E06-Detail.md +0 -62
  40. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T001-color-system.md +0 -39
  41. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T002-header-and-dividers.md +0 -52
  42. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T003-footer-status-bar.md +0 -52
  43. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T004-component-refinement.md +0 -53
  44. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T005-restore-nav-hints.md +0 -39
  45. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T007-detail-card-fixes.md +0 -36
  46. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T008-checkbox-states.md +0 -40
  47. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T009-router-priority-marker.md +0 -48
  48. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T010-auto-refresh-watcher.md +0 -66
  49. package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/Design.md +0 -39
  50. package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/tasks/T001-archive-epics.md +0 -20
  51. package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/tasks/T002-rewrite-prd.md +0 -22
  52. package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/tasks/T003-create-epic-stubs.md +0 -24
  53. package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/tasks/T004-update-router.md +0 -22
  54. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/Design.md +0 -118
  55. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/handoff.md +0 -9
  56. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T001-package-baseline.md +0 -45
  57. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T002-typescript-build.md +0 -48
  58. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T003-vitest-smoke.md +0 -43
  59. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T004-lint-format-gates.md +0 -45
  60. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T005-scaffold-verification.md +0 -40
  61. package/.savepoint/releases/v1/epics/_archived/E02-data-model/Design.md +0 -142
  62. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T001-domain-ids-status.md +0 -27
  63. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T002-markdown-frontmatter-boundary.md +0 -28
  64. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T003-task-documents.md +0 -29
  65. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T004-release-epic-router-config-readers.md +0 -30
  66. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T005-dependency-validation.md +0 -29
  67. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T006-epic-task-set-reader.md +0 -29
  68. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T007-quality-gates.md +0 -31
  69. package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/Design.md +0 -40
  70. package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/tasks/T001-phase-types.md +0 -27
  71. package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/tasks/T002-phase-frontmatter.md +0 -25
  72. package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/tasks/T003-simplify-config.md +0 -26
  73. package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/tasks/T004-simplify-router-domain.md +0 -24
  74. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/Design.md +0 -122
  75. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T001-argument-parser-contract.md +0 -28
  76. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T002-help-text-generation.md +0 -28
  77. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T003-terminal-environment-detection.md +0 -27
  78. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T004-command-stub-modules.md +0 -29
  79. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T005-cli-runner-dispatch.md +0 -34
  80. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T006-entrypoint-quality-gates.md +0 -32
  81. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/Design.md +0 -43
  82. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T001-strip-args.md +0 -26
  83. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T002-strip-help.md +0 -23
  84. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T003-strip-run.md +0 -23
  85. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T004-delete-commands.md +0 -24
  86. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T005-update-cli-tests.md +0 -22
  87. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/Design.md +0 -48
  88. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T001-board-data-phases.md +0 -26
  89. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T002-phase-rendering.md +0 -28
  90. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T003-detail-pane-phases.md +0 -27
  91. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T004-phase-transitions.md +0 -42
  92. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T005-phase-gates.md +0 -24
  93. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T006-phase-write-back.md +0 -24
  94. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T007-remove-audit-flow.md +0 -27
  95. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T008-board-tests.md +0 -25
  96. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/Design.md +0 -85
  97. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T001-project-template-assets.md +0 -17
  98. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T002-release-and-prompt-assets.md +0 -20
  99. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T003-template-registry-renderer.md +0 -22
  100. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T004-template-integrity-tests.md +0 -17
  101. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T005-template-closeout-quality-gates.md +0 -16
  102. package/.savepoint/releases/v1/epics/_archived/E05-init-command/Design.md +0 -88
  103. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T001-init-cli-contract.md +0 -22
  104. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T002-target-validation.md +0 -23
  105. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T003-scaffold-writer.md +0 -24
  106. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T004-magic-prompt-and-clipboard.md +0 -23
  107. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T005-dev-deps-install-option.md +0 -24
  108. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T006-init-command-integration.md +0 -28
  109. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/Design.md +0 -53
  110. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T001-delete-dead-src.md +0 -23
  111. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T002-delete-dead-tests.md +0 -26
  112. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T003-delete-assets.md +0 -25
  113. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T004-clean-savepoint.md +0 -28
  114. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T005-rewrite-agents-md.md +0 -28
  115. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T006-clean-package-json.md +0 -23
  116. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T007-verify.md +0 -25
  117. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/Design.md +0 -104
  118. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T001-board-command-data.md +0 -23
  119. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T002-board-view-state.md +0 -24
  120. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T003-transition-gates-and-writes.md +0 -25
  121. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T004-terminal-theme.md +0 -23
  122. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T005-ink-board-ui.md +0 -26
  123. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T006-board-integration-audit-entry.md +0 -24
  124. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/Design.md +0 -88
  125. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T001-audit-cli-contract.md +0 -23
  126. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T002-quality-gate-runner.md +0 -23
  127. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T003-snapshot-and-prompt.md +0 -23
  128. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T004-audit-orchestration-router.md +0 -27
  129. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T005-proposal-validation-apply.md +0 -25
  130. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T006-audit-review-state.md +0 -24
  131. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T007-audit-review-ui.md +0 -26
  132. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T008-audit-pipeline-integration.md +0 -24
  133. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/Design.md +0 -103
  134. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T001-acceptance-criteria-model.md +0 -30
  135. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T002-release-task-set-reader.md +0 -33
  136. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T003-board-data-and-plain-output.md +0 -34
  137. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T004-board-selection-state.md +0 -33
  138. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T005-ink-board-layout-cleanup.md +0 -37
  139. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T006-task-detail-popup.md +0 -36
  140. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T007-templates-acceptance-criteria.md +0 -34
  141. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T008-board-workflow-integration.md +0 -41
  142. package/.savepoint/releases/v1/epics/_archived/E09-doctor-command/Design.md +0 -70
  143. package/.savepoint/releases/v1/epics/_archived/E10-docs-and-packaging/Design.md +0 -68
  144. package/.savepoint/releases/v1/epics/_archived/E11-release-validation/Design.md +0 -68
  145. package/.savepoint/releases/v1/v1-PRD.md +0 -66
  146. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/E01-Detail.md +0 -40
  147. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T001-next-activity-header.md +0 -56
  148. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T002-rename-epic-design-files.md +0 -38
  149. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T003-rename-release-prd.md +0 -28
  150. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T004-update-instruction-files.md +0 -51
  151. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T005-update-cross-references.md +0 -45
  152. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T006-column-and-detail-scrolling.md +0 -68
  153. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T007-column-focus-border-stability.md +0 -57
  154. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/E02-Audit.md +0 -124
  155. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/E02-Detail.md +0 -49
  156. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T001-fix-makefile.md +0 -37
  157. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T002-linux-build-target.md +0 -38
  158. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T003-macos-build-target.md +0 -36
  159. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T004-smoke-tests-and-artifacts.md +0 -59
  160. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/E03-Audit.md +0 -195
  161. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/E03-Detail.md +0 -45
  162. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T001-border-resize-fix.md +0 -40
  163. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T002-next-activity-below-header.md +0 -64
  164. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T003-checkbox-rendering-fix.md +0 -56
  165. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T005-unify-status-glyphs.md +0 -65
  166. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T006-forced-256-color-profile.md +0 -36
  167. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/E04-Audit.md +0 -167
  168. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/E04-Detail.md +0 -51
  169. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T001-sidebar-focusable-navigation.md +0 -65
  170. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T002-epic-detail-overlay.md +0 -73
  171. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T003-epic-status-glyphs.md +0 -73
  172. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/E05-Audit.md +0 -237
  173. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/E05-Detail.md +0 -54
  174. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T001-update-agents-md.md +0 -45
  175. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T002-update-router-md.md +0 -40
  176. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T003-update-design-md.md +0 -47
  177. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T004-implement-m-hotkey.md +0 -98
  178. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T005-update-help-overlay.md +0 -33
  179. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T006-tests-and-quality-gates.md +0 -62
  180. package/.savepoint/releases/v1.1/epics/E06-audit-command/E06-Audit.md +0 -56
  181. package/.savepoint/releases/v1.1/epics/E06-audit-command/E06-Detail.md +0 -63
  182. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T005-proposals.md +0 -44
  183. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T007-apply-close.md +0 -35
  184. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T009-integration.md +0 -40
  185. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T010-audit-file-migration.md +0 -45
  186. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T011-model-tab-state.md +0 -26
  187. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T012-epic-audit-render.md +0 -33
  188. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T013-handle-tab-keys.md +0 -34
  189. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T014-tab-indicator.md +0 -33
  190. package/.savepoint/releases/v1.1/epics/E07-init-command/E07-Audit.md +0 -336
  191. package/.savepoint/releases/v1.1/epics/E07-init-command/E07-Detail.md +0 -61
  192. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T001-cli-entrypoint.md +0 -37
  193. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T002-target-validation.md +0 -28
  194. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T003-scaffold-writer.md +0 -46
  195. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T004-atomic-writes.md +0 -27
  196. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T005-magic-prompt.md +0 -25
  197. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T006-clipboard.md +0 -26
  198. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T007-integration-test.md +0 -26
  199. package/.savepoint/releases/v1.1/epics/E08-board-command/E08-Audit.md +0 -333
  200. package/.savepoint/releases/v1.1/epics/E08-board-command/E08-Detail.md +0 -68
  201. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T001-cli-entrypoint.md +0 -26
  202. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T002-non-tty-fallback.md +0 -27
  203. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T003-tui-app-shell.md +0 -28
  204. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T004-board-model.md +0 -29
  205. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T005-detail-pane.md +0 -27
  206. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T006-status-transitions.md +0 -29
  207. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T007-theme-fallbacks.md +0 -29
  208. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T008-integration-test.md +0 -27
  209. package/.savepoint/releases/v1.1/epics/E09-doctor-command/E09-Audit.md +0 -207
  210. package/.savepoint/releases/v1.1/epics/E09-doctor-command/E09-Detail.md +0 -65
  211. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T001-cli-entrypoint.md +0 -24
  212. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T002-config-router-validation.md +0 -28
  213. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T003-structure-checks.md +0 -29
  214. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T004-dependency-checks.md +0 -27
  215. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T005-audit-orphan-checks.md +0 -28
  216. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T006-quality-gates-report.md +0 -31
  217. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/E11-Detail.md +0 -36
  218. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T001-debug-logging.md +0 -25
  219. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T002-increase-debounce.md +0 -21
  220. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T003-error-handling.md +0 -22
  221. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T004-test-verify.md +0 -29
  222. package/.savepoint/releases/v1.1/epics/E12-validation-fix/E12-Audit.md +0 -444
  223. package/.savepoint/releases/v1.1/epics/E12-validation-fix/E12-Detail.md +0 -45
  224. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T001-default-phase.md +0 -35
  225. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T002-default-status.md +0 -19
  226. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T003-better-errors.md +0 -29
  227. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T004-validate-on-write.md +0 -25
  228. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T005-tests.md +0 -37
  229. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/E13-Audit.md +0 -118
  230. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/E13-Detail.md +0 -73
  231. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T001-safe-cleanup.md +0 -66
  232. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T002-bug-fixes.md +0 -35
  233. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T003-centralize-duplication.md +0 -60
  234. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T004-infrastructure.md +0 -33
  235. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T005-decompose-update.md +0 -37
  236. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T006-async-io.md +0 -40
  237. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T007-test-coverage.md +0 -37
  238. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/E14-Audit.md +0 -267
  239. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/E14-Detail.md +0 -54
  240. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T001-group-model.md +0 -39
  241. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T002-data-interfaces.md +0 -42
  242. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T003-discover-orphans.md +0 -33
  243. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T004-epic-panel-headings.md +0 -35
  244. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T005-shell-tokenization.md +0 -27
  245. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T006-unify-enums.md +0 -29
  246. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T007-testutil-package.md +0 -28
  247. package/.savepoint/releases/v1.1/epics/E15-hardening/E15-Audit.md +0 -272
  248. package/.savepoint/releases/v1.1/epics/E15-hardening/E15-Detail.md +0 -60
  249. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T001-benchmarks.md +0 -31
  250. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T002-fuzz-targets.md +0 -34
  251. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T003-debug-flag.md +0 -30
  252. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T004-dist-checksums.md +0 -27
  253. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T005-windows-targets.md +0 -28
  254. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T006-abbreviation-splitting.md +0 -26
  255. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T007-root-test-allowlist.md +0 -33
  256. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T008-ci-and-release-automation.md +0 -46
  257. package/.savepoint/releases/v1.1/epics/_archived/T001-cli-entrypoint.md +0 -25
  258. package/.savepoint/releases/v1.1/epics/_archived/T002-quality-gates.md +0 -27
  259. package/.savepoint/releases/v1.1/epics/_archived/T003-snapshot.md +0 -27
  260. package/.savepoint/releases/v1.1/epics/_archived/T004-ai-reconcile.md +0 -29
  261. package/.savepoint/releases/v1.1/epics/_archived/T006-tui-review.md +0 -31
  262. package/.savepoint/releases/v1.1/epics/_archived/T008-skip-handling.md +0 -34
  263. package/.savepoint/releases/v1.1/v1.1-PRD.md +0 -139
  264. package/.savepoint/router.md +0 -57
  265. package/.savepoint/visual-identity.md +0 -125
  266. package/AGENTS.md +0 -99
  267. package/CLAUDE.md +0 -1
  268. package/GEMINI.md +0 -1
  269. package/Makefile +0 -31
  270. package/agent-skills/ink-tui-design/SKILL.md +0 -309
  271. package/agent-skills/ink-tui-design/references/component-patterns.md +0 -371
  272. package/agent-skills/ink-tui-design/references/hooks-guide.md +0 -436
  273. package/agent-skills/ink-tui-design/references/ink-gotchas.md +0 -330
  274. package/agent-skills/ink-tui-design/references/testing-patterns.md +0 -384
  275. package/agent-skills/savepoint-audit/SKILL.md +0 -87
  276. package/agent-skills/savepoint-build-task/SKILL.md +0 -44
  277. package/agent-skills/savepoint-create-plan/SKILL.md +0 -33
  278. package/agent-skills/savepoint-create-task/SKILL.md +0 -44
  279. package/agent-skills/savepoint-draft-prd/SKILL.md +0 -37
  280. package/agent-skills/savepoint-system-design/SKILL.md +0 -38
  281. package/agent-skills/superpowers/brainstorming/SKILL.md +0 -165
  282. package/agent-skills/superpowers/brainstorming/visual-companion.md +0 -304
  283. package/agent-skills/superpowers/dispatching-parallel-agents/SKILL.md +0 -193
  284. package/agent-skills/superpowers/executing-plans/SKILL.md +0 -77
  285. package/agent-skills/superpowers/finishing-a-development-branch/SKILL.md +0 -213
  286. package/agent-skills/superpowers/receiving-code-review/SKILL.md +0 -226
  287. package/agent-skills/superpowers/requesting-code-review/SKILL.md +0 -115
  288. package/agent-skills/superpowers/requesting-code-review/code-reviewer.md +0 -160
  289. package/agent-skills/superpowers/subagent-driven-development/SKILL.md +0 -292
  290. package/agent-skills/superpowers/subagent-driven-development/code-quality-reviewer-prompt.md +0 -27
  291. package/agent-skills/superpowers/subagent-driven-development/implementer-prompt.md +0 -113
  292. package/agent-skills/superpowers/subagent-driven-development/spec-reviewer-prompt.md +0 -61
  293. package/agent-skills/superpowers/systematic-debugging/SKILL.md +0 -305
  294. package/agent-skills/superpowers/systematic-debugging/condition-based-waiting.md +0 -122
  295. package/agent-skills/superpowers/systematic-debugging/defense-in-depth.md +0 -130
  296. package/agent-skills/superpowers/systematic-debugging/root-cause-tracing.md +0 -183
  297. package/agent-skills/superpowers/test-driven-development/SKILL.md +0 -389
  298. package/agent-skills/superpowers/test-driven-development/testing-anti-patterns.md +0 -317
  299. package/agent-skills/superpowers/verification-before-completion/SKILL.md +0 -147
  300. package/agent-skills/superpowers/writing-plans/SKILL.md +0 -159
  301. package/agent-skills/superpowers/writing-plans/plan-document-reviewer-prompt.md +0 -49
  302. package/agent_skills_test.go +0 -91
  303. package/assets/banner.png +0 -0
  304. package/assets/logo.png +0 -0
  305. package/assets/strawman.png +0 -0
  306. package/cmd/board.go +0 -59
  307. package/cmd/board_test.go +0 -137
  308. package/cmd/doctor.go +0 -53
  309. package/cmd/doctor_test.go +0 -146
  310. package/cmd/init.go +0 -63
  311. package/cmd/init_test.go +0 -104
  312. package/go.mod +0 -36
  313. package/go.sum +0 -75
  314. package/internal/board/board.go +0 -181
  315. package/internal/board/board_test.go +0 -168
  316. package/internal/board/card.go +0 -129
  317. package/internal/board/card_test.go +0 -287
  318. package/internal/board/column.go +0 -156
  319. package/internal/board/column_test.go +0 -210
  320. package/internal/board/debug.go +0 -26
  321. package/internal/board/debug_test.go +0 -108
  322. package/internal/board/detail.go +0 -218
  323. package/internal/board/detail_test.go +0 -388
  324. package/internal/board/epic_panel.go +0 -264
  325. package/internal/board/epic_panel_test.go +0 -869
  326. package/internal/board/help.go +0 -41
  327. package/internal/board/help_test.go +0 -86
  328. package/internal/board/integration_test.go +0 -266
  329. package/internal/board/interfaces.go +0 -65
  330. package/internal/board/interfaces_test.go +0 -114
  331. package/internal/board/io.go +0 -93
  332. package/internal/board/layout.go +0 -68
  333. package/internal/board/layout_test.go +0 -106
  334. package/internal/board/model.go +0 -235
  335. package/internal/board/model_test.go +0 -67
  336. package/internal/board/plain.go +0 -88
  337. package/internal/board/plain_test.go +0 -117
  338. package/internal/board/release.go +0 -34
  339. package/internal/board/release_test.go +0 -177
  340. package/internal/board/render_policy_test.go +0 -77
  341. package/internal/board/status.go +0 -23
  342. package/internal/board/theme.go +0 -24
  343. package/internal/board/theme_test.go +0 -31
  344. package/internal/board/transitions.go +0 -113
  345. package/internal/board/transitions_test.go +0 -164
  346. package/internal/board/tui.go +0 -32
  347. package/internal/board/update.go +0 -575
  348. package/internal/board/update_test.go +0 -602
  349. package/internal/board/util.go +0 -76
  350. package/internal/board/view.go +0 -317
  351. package/internal/board/view_test.go +0 -377
  352. package/internal/board/watch.go +0 -136
  353. package/internal/buildtool/main.go +0 -249
  354. package/internal/buildtool/main_test.go +0 -224
  355. package/internal/data/config.go +0 -101
  356. package/internal/data/config_test.go +0 -122
  357. package/internal/data/discover.go +0 -178
  358. package/internal/data/discover_test.go +0 -130
  359. package/internal/data/errors.go +0 -13
  360. package/internal/data/fuzz_test.go +0 -75
  361. package/internal/data/lifecycle.go +0 -44
  362. package/internal/data/lifecycle_test.go +0 -41
  363. package/internal/data/parser.go +0 -243
  364. package/internal/data/parser_test.go +0 -281
  365. package/internal/data/router.go +0 -52
  366. package/internal/data/router_test.go +0 -35
  367. package/internal/data/task.go +0 -57
  368. package/internal/data/task_test.go +0 -51
  369. package/internal/data/testdata/fuzz/FuzzSplitFrontmatterBody/68eb66b0fe91e7e3 +0 -2
  370. package/internal/data/write.go +0 -221
  371. package/internal/data/write_test.go +0 -623
  372. package/internal/doctor/checks.go +0 -567
  373. package/internal/doctor/checks_test.go +0 -716
  374. package/internal/doctor/gates.go +0 -193
  375. package/internal/doctor/gates_test.go +0 -166
  376. package/internal/doctor/interfaces.go +0 -64
  377. package/internal/doctor/interfaces_test.go +0 -104
  378. package/internal/doctor/repairs.go +0 -80
  379. package/internal/doctor/repairs_test.go +0 -81
  380. package/internal/doctor/report.go +0 -157
  381. package/internal/doctor/report_test.go +0 -89
  382. package/internal/init/clipboard.go +0 -146
  383. package/internal/init/clipboard_test.go +0 -74
  384. package/internal/init/install.go +0 -16
  385. package/internal/init/integration_test.go +0 -197
  386. package/internal/init/prompt.go +0 -14
  387. package/internal/init/prompt_test.go +0 -77
  388. package/internal/init/scaffold.go +0 -59
  389. package/internal/init/scaffold_test.go +0 -179
  390. package/internal/init/template_freshness_test.go +0 -56
  391. package/internal/init/validate.go +0 -85
  392. package/internal/init/validate_test.go +0 -141
  393. package/internal/init/write.go +0 -73
  394. package/internal/init/write_test.go +0 -91
  395. package/internal/styles/palette.go +0 -49
  396. package/internal/styles/styles.go +0 -139
  397. package/internal/styles/styles_test.go +0 -133
  398. package/internal/testutil/fixture.go +0 -113
  399. package/internal/testutil/fs.go +0 -26
  400. package/main.go +0 -136
  401. package/project-audit/audit_report_glm_5.1.md +0 -411
  402. package/project-audit/audit_report_opus_4.6.md +0 -406
  403. package/project-audit/consolidated-audit-report.md +0 -456
  404. package/scripts/vitest-preload.cjs +0 -95
  405. package/templates/project/.savepoint/Design.md +0 -47
  406. package/templates/project/.savepoint/PRD.md +0 -34
  407. package/templates/project/.savepoint/config.yml +0 -27
  408. package/templates/project/.savepoint/router.md +0 -153
  409. package/templates/project/.savepoint/visual-identity.md +0 -122
  410. package/templates/project/AGENTS.md +0 -88
  411. package/templates/project/agent-skills/savepoint-audit/SKILL.md +0 -87
  412. package/templates/project/agent-skills/savepoint-build-task/SKILL.md +0 -44
  413. package/templates/project/agent-skills/savepoint-create-plan/SKILL.md +0 -33
  414. package/templates/project/agent-skills/savepoint-create-task/SKILL.md +0 -44
  415. package/templates/project/agent-skills/savepoint-draft-prd/SKILL.md +0 -37
  416. package/templates/project/agent-skills/savepoint-system-design/SKILL.md +0 -38
  417. package/templates/prompts/audit-reconciliation.prompt.md +0 -72
  418. package/templates/prompts/design.prompt.md +0 -45
  419. package/templates/prompts/epic-design.prompt.md +0 -43
  420. package/templates/prompts/magic-prompt.prompt.md +0 -7
  421. package/templates/prompts/prd.prompt.md +0 -42
  422. package/templates/prompts/task-breakdown.prompt.md +0 -54
  423. package/templates/prompts/task-building.prompt.md +0 -38
  424. package/templates/prompts/task-planning.prompt.md +0 -53
  425. 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
- }