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,108 +0,0 @@
1
- package board
2
-
3
- import (
4
- "bytes"
5
- "fmt"
6
- "io"
7
- "os"
8
- "strings"
9
- "testing"
10
- )
11
-
12
- func TestSetDebugToggle(t *testing.T) {
13
- t.Cleanup(func() { SetDebug(false) })
14
-
15
- if DebugEnabled() {
16
- t.Fatal("debug should be off by default")
17
- }
18
-
19
- SetDebug(true)
20
- if !DebugEnabled() {
21
- t.Fatal("debug should be on after SetDebug(true)")
22
- }
23
-
24
- SetDebug(false)
25
- if DebugEnabled() {
26
- t.Fatal("debug should be off after SetDebug(false)")
27
- }
28
- }
29
-
30
- func TestDebugfWritesToStderr(t *testing.T) {
31
- t.Cleanup(func() { SetDebug(false) })
32
-
33
- r, w, err := os.Pipe()
34
- if err != nil {
35
- t.Fatal(err)
36
- }
37
- orig := os.Stderr
38
- os.Stderr = w
39
-
40
- SetDebug(true)
41
- debugf("test message %d", 42)
42
-
43
- os.Stderr = orig
44
- w.Close()
45
-
46
- var buf bytes.Buffer
47
- io.Copy(&buf, r)
48
- r.Close()
49
-
50
- out := buf.String()
51
- if !strings.Contains(out, "test message 42") {
52
- t.Fatalf("expected debug output, got: %q", out)
53
- }
54
- if !strings.Contains(out, "[savepoint debug]") {
55
- t.Fatalf("expected debug prefix, got: %q", out)
56
- }
57
- }
58
-
59
- func TestDebugfSilentWhenDisabled(t *testing.T) {
60
- t.Cleanup(func() { SetDebug(false) })
61
-
62
- r, w, err := os.Pipe()
63
- if err != nil {
64
- t.Fatal(err)
65
- }
66
- orig := os.Stderr
67
- os.Stderr = w
68
-
69
- SetDebug(false)
70
- debugf("should not appear")
71
-
72
- os.Stderr = orig
73
- w.Close()
74
-
75
- var buf bytes.Buffer
76
- io.Copy(&buf, r)
77
- r.Close()
78
-
79
- if buf.Len() != 0 {
80
- t.Fatalf("expected no debug output when disabled, got: %q", buf.String())
81
- }
82
- }
83
-
84
- func TestDebugfFormat(t *testing.T) {
85
- t.Cleanup(func() { SetDebug(false) })
86
-
87
- r, w, err := os.Pipe()
88
- if err != nil {
89
- t.Fatal(err)
90
- }
91
- orig := os.Stderr
92
- os.Stderr = w
93
-
94
- SetDebug(true)
95
- debugf("key=%q value=%d", "hello", 7)
96
-
97
- os.Stderr = orig
98
- w.Close()
99
-
100
- var buf bytes.Buffer
101
- io.Copy(&buf, r)
102
- r.Close()
103
-
104
- want := fmt.Sprintf("[savepoint debug] key=%q value=%d\n", "hello", 7)
105
- if buf.String() != want {
106
- t.Fatalf("expected %q, got %q", want, buf.String())
107
- }
108
- }
@@ -1,218 +0,0 @@
1
- package board
2
-
3
- import (
4
- "strings"
5
-
6
- "github.com/charmbracelet/lipgloss"
7
- "github.com/opencode/savepoint/internal/data"
8
- "github.com/opencode/savepoint/internal/styles"
9
- )
10
-
11
- const detailBorderPad = 4 // rounded border (2) + padding (2×1)
12
- const detailVerticalOverhead = 4 // overlay border (2) + fixed title/header rows (2)
13
-
14
- // RenderDetail renders a task detail overlay panel at the given display width.
15
- // When router state matches t's release/epic/task, a "(router priority)" label is shown.
16
- func RenderDetail(t data.Task, overlayW int, routerState *data.RouterState, maxHeight, offset int) string {
17
- inner := overlayW - detailBorderPad
18
- if inner < 4 {
19
- inner = 4
20
- }
21
-
22
- lines := []string{
23
- styles.ColumnTitleFocused.Render("TASK DETAIL"),
24
- strings.Repeat("─", inner),
25
- }
26
- body := []string{
27
- detailRow("ID", t.ID, inner),
28
- detailRow("Title", t.Title, inner),
29
- detailRow("Epic", t.Epic, inner),
30
- detailRow("Release", t.Release, inner),
31
- detailRow("Status", string(t.Column), inner),
32
- detailRow("Phase", phaseLabel(t.Stage), inner),
33
- }
34
-
35
- if t.Description != "" {
36
- body = append(body,
37
- "",
38
- styles.ColumnTitle.Render("Description:"),
39
- )
40
- for _, line := range WrapText(t.Description, inner) {
41
- body = append(body, styles.CardMeta.Render(line))
42
- }
43
- }
44
-
45
- if len(t.Checklist) > 0 {
46
- body = append(body, "", styles.ColumnTitle.Render("Implementation Plan:"), "")
47
- for _, item := range t.Checklist {
48
- glyph := "[ ] "
49
- style := styles.CardMeta
50
- if item.Done {
51
- glyph = "[x] "
52
- style = styles.TagDone
53
- }
54
- body = append(body, renderChecklistSentences(item.Text, glyph, inner, style)...)
55
- }
56
- }
57
-
58
- if t.Column != data.ColumnDone && isRouterPriority(t, routerState) {
59
- body = append(body, "", styles.TagDone.Render("(router priority)"))
60
- }
61
- body = append(body, "", styles.CardMeta.Render("esc:close"))
62
- lines = append(lines, visibleDetailLines(body, maxHeight-detailVerticalOverhead, offset)...)
63
-
64
- return styles.DetailOverlay.Width(overlayW).Render(strings.Join(lines, "\n"))
65
- }
66
-
67
- func renderChecklistSentences(text, glyph string, width int, style lipgloss.Style) []string {
68
- textWidth := width - len(glyph)
69
- if textWidth < 4 {
70
- textWidth = 4
71
- }
72
-
73
- lines := []string{}
74
- continuationIndent := strings.Repeat(" ", len(glyph))
75
- for _, sentence := range splitChecklistSentences(text) {
76
- wrapped := WrapText(sentence, textWidth)
77
- for i, line := range wrapped {
78
- if i == 0 {
79
- lines = append(lines, style.Render(glyph+line))
80
- continue
81
- }
82
- lines = append(lines, style.Render(continuationIndent+line))
83
- }
84
- }
85
- return lines
86
- }
87
-
88
- // knownAbbreviations is the set of dot-terminated tokens that must not trigger
89
- // sentence splits. Add entries (lowercase, trailing dot) to extend the list.
90
- var knownAbbreviations = map[string]bool{
91
- "e.g.": true,
92
- "i.e.": true,
93
- "vs.": true,
94
- "etc.": true,
95
- "fig.": true,
96
- "no.": true,
97
- "mr.": true,
98
- "mrs.": true,
99
- "dr.": true,
100
- "st.": true,
101
- "jr.": true,
102
- "sr.": true,
103
- "prof.": true,
104
- "approx.": true,
105
- "est.": true,
106
- }
107
-
108
- // isKnownAbbreviation reports whether the period at dotPos in s is the trailing
109
- // dot of a known abbreviation (e.g. "e.g.", "Dr.").
110
- func isKnownAbbreviation(s string, dotPos int) bool {
111
- start := dotPos
112
- for start > 0 && s[start-1] != ' ' {
113
- start--
114
- }
115
- return knownAbbreviations[strings.ToLower(s[start:dotPos+1])]
116
- }
117
-
118
- func splitChecklistSentences(text string) []string {
119
- fields := strings.Fields(text)
120
- if len(fields) == 0 {
121
- return nil
122
- }
123
- normalized := strings.Join(fields, " ")
124
-
125
- sentences := []string{}
126
- start := 0
127
- for i, r := range normalized {
128
- if r != '.' && r != '!' && r != '?' {
129
- continue
130
- }
131
- if r == '.' && isKnownAbbreviation(normalized, i) {
132
- continue
133
- }
134
- end := i + len(string(r))
135
- if end < len(normalized) && normalized[end] != ' ' {
136
- continue
137
- }
138
- sentence := strings.TrimSpace(normalized[start:end])
139
- if sentence != "" {
140
- sentences = append(sentences, sentence)
141
- }
142
- start = end
143
- }
144
- if tail := strings.TrimSpace(normalized[start:]); tail != "" {
145
- sentences = append(sentences, tail)
146
- }
147
- return sentences
148
- }
149
-
150
- func visibleDetailLines(lines []string, maxBodyHeight, offset int) []string {
151
- total := len(lines)
152
- if maxBodyHeight <= 0 || total <= maxBodyHeight {
153
- return lines
154
- }
155
- offset = clampDetailOffset(offset, total)
156
- available := maxBodyHeight
157
- if offset > 0 {
158
- available--
159
- }
160
- if available < 1 {
161
- available = 1
162
- }
163
- end := min(offset+available, total)
164
- if end < total && available > 1 {
165
- available--
166
- end = min(offset+available, total)
167
- }
168
-
169
- visible := make([]string, 0, available+2)
170
- if offset > 0 {
171
- visible = append(visible, renderScrollIndicator("↑", offset, "above"))
172
- }
173
- visible = append(visible, lines[offset:end]...)
174
- if end < total {
175
- visible = append(visible, renderScrollIndicator("↓", total-end, "more"))
176
- }
177
- return visible
178
- }
179
-
180
- func clampDetailOffset(offset, total int) int {
181
- if offset < 0 || total <= 0 {
182
- return 0
183
- }
184
- if offset >= total {
185
- return total - 1
186
- }
187
- return offset
188
- }
189
-
190
- func detailRow(label, value string, width int) string {
191
- prefix := label + ": "
192
- wrapped := WrapText(value, width-len(prefix))
193
- if len(wrapped) == 0 {
194
- wrapped = []string{""}
195
- }
196
- lines := make([]string, 0, len(wrapped))
197
- for i, line := range wrapped {
198
- if i == 0 {
199
- lines = append(lines, styles.ColumnTitle.Render(prefix)+styles.CardMeta.Render(line))
200
- continue
201
- }
202
- lines = append(lines, strings.Repeat(" ", len(prefix))+styles.CardMeta.Render(line))
203
- }
204
- return strings.Join(lines, "\n")
205
- }
206
-
207
- func phaseLabel(s data.ProgressStage) string {
208
- switch s {
209
- case data.StageTest:
210
- return "test"
211
- case data.StageAudit:
212
- return "audit"
213
- default:
214
- return "build"
215
- }
216
- }
217
-
218
-
@@ -1,388 +0,0 @@
1
- package board
2
-
3
- import (
4
- "regexp"
5
- "strings"
6
- "testing"
7
-
8
- tea "github.com/charmbracelet/bubbletea"
9
- "github.com/opencode/savepoint/internal/data"
10
- )
11
-
12
- var ansiPattern = regexp.MustCompile(`\x1b\[[0-9;?]*[ -/]*[@-~]`)
13
-
14
- func plainTerminal(s string) string {
15
- return ansiPattern.ReplaceAllString(s, "")
16
- }
17
-
18
- func sampleTask() data.Task {
19
- return data.Task{
20
- ID: "E04/T001",
21
- Title: "My Task",
22
- Epic: "E04-board-components",
23
- Release: "v1",
24
- Column: data.ColumnInProgress,
25
- Stage: data.StageBuild,
26
- }
27
- }
28
-
29
- func TestRenderDetail_containsID(t *testing.T) {
30
- got := RenderDetail(sampleTask(), 60, nil, 0, 0)
31
- if !strings.Contains(got, "E04/T001") {
32
- t.Error("RenderDetail missing task ID")
33
- }
34
- }
35
-
36
- func TestRenderDetail_containsTitle(t *testing.T) {
37
- got := RenderDetail(sampleTask(), 60, nil, 0, 0)
38
- if !strings.Contains(got, "My Task") {
39
- t.Error("RenderDetail missing task title")
40
- }
41
- }
42
-
43
- func TestRenderDetail_containsEpic(t *testing.T) {
44
- got := RenderDetail(sampleTask(), 60, nil, 0, 0)
45
- if !strings.Contains(got, "E04-board-components") {
46
- t.Error("RenderDetail missing epic")
47
- }
48
- }
49
-
50
- func TestRenderDetail_containsRelease(t *testing.T) {
51
- got := RenderDetail(sampleTask(), 60, nil, 0, 0)
52
- if !strings.Contains(got, "v1") {
53
- t.Error("RenderDetail missing release")
54
- }
55
- }
56
-
57
- func TestRenderDetail_containsStatus(t *testing.T) {
58
- got := RenderDetail(sampleTask(), 60, nil, 0, 0)
59
- if !strings.Contains(got, "in_progress") {
60
- t.Error("RenderDetail missing status")
61
- }
62
- }
63
-
64
- func TestRenderDetail_containsPhase(t *testing.T) {
65
- got := RenderDetail(sampleTask(), 60, nil, 0, 0)
66
- if !strings.Contains(got, "build") {
67
- t.Error("RenderDetail missing phase")
68
- }
69
- }
70
-
71
- func TestRenderDetail_containsEscHint(t *testing.T) {
72
- got := RenderDetail(sampleTask(), 60, nil, 0, 0)
73
- if !strings.Contains(got, "esc") {
74
- t.Error("RenderDetail missing esc:close hint")
75
- }
76
- }
77
-
78
- func TestRenderDetail_containsDescription(t *testing.T) {
79
- tk := sampleTask()
80
- tk.Description = "some description text"
81
- got := RenderDetail(tk, 60, nil, 0, 0)
82
- if !strings.Contains(got, "some description text") {
83
- t.Error("RenderDetail missing description text")
84
- }
85
- }
86
-
87
- func TestRenderDetail_noDescriptionSectionWhenEmpty(t *testing.T) {
88
- got := RenderDetail(sampleTask(), 60, nil, 0, 0)
89
- if strings.Contains(got, "Description:") {
90
- t.Error("RenderDetail should not show Description section when empty")
91
- }
92
- }
93
-
94
- func TestRenderDetail_containsChecklist(t *testing.T) {
95
- tk := sampleTask()
96
- tk.Checklist = []data.CheckItem{{Text: "first implementation item"}, {Text: "second implementation item", Done: true}}
97
- got := RenderDetail(tk, 60, nil, 0, 0)
98
- if !strings.Contains(got, "Implementation Plan:") {
99
- t.Error("RenderDetail missing implementation plan heading")
100
- }
101
- if !strings.Contains(got, "first implementation item") {
102
- t.Error("RenderDetail missing first checklist item")
103
- }
104
- if !strings.Contains(got, "second implementation item") {
105
- t.Error("RenderDetail missing second checklist item")
106
- }
107
- }
108
-
109
- func TestRenderDetail_checklistSingleSentenceGetsOneCheckbox(t *testing.T) {
110
- tk := sampleTask()
111
- tk.Checklist = []data.CheckItem{{Text: "single sentence task"}}
112
-
113
- got := plainTerminal(RenderDetail(tk, 60, nil, 0, 0))
114
-
115
- if count := strings.Count(got, "[ ]"); count != 1 {
116
- t.Fatalf("RenderDetail checkbox count = %d, want 1\n%s", count, got)
117
- }
118
- if strings.Contains(got, "[x]") {
119
- t.Fatal("RenderDetail should not render checked marker for unchecked item")
120
- }
121
- }
122
-
123
- func TestRenderDetail_checklistMultiSentenceGetsOneCheckboxPerSentence(t *testing.T) {
124
- tk := sampleTask()
125
- tk.Checklist = []data.CheckItem{{Text: "First sentence. Second sentence! Third sentence?"}}
126
-
127
- got := plainTerminal(RenderDetail(tk, 60, nil, 0, 0))
128
-
129
- if count := strings.Count(got, "[ ]"); count != 3 {
130
- t.Fatalf("RenderDetail checkbox count = %d, want 3\n%s", count, got)
131
- }
132
- for _, want := range []string{"[ ] First sentence.", "[ ] Second sentence!", "[ ] Third sentence?"} {
133
- if !strings.Contains(got, want) {
134
- t.Fatalf("RenderDetail missing sentence checkbox line %q\n%s", want, got)
135
- }
136
- }
137
- }
138
-
139
- func TestRenderDetail_checklistHardWrappedSentenceDoesNotDuplicateCheckbox(t *testing.T) {
140
- tk := sampleTask()
141
- tk.Checklist = []data.CheckItem{{
142
- Text: "This sentence is intentionally long enough to wrap inside a narrow detail overlay while remaining one semantic sentence.",
143
- }}
144
-
145
- got := plainTerminal(RenderDetail(tk, 34, nil, 0, 0))
146
-
147
- if count := strings.Count(got, "[ ]"); count != 1 {
148
- t.Fatalf("RenderDetail checkbox count = %d, want 1\n%s", count, got)
149
- }
150
- if !strings.Contains(got, " intentionally long enough") {
151
- t.Fatalf("RenderDetail continuation line should align under checkbox text\n%s", got)
152
- }
153
- }
154
-
155
- func TestRenderDetail_checklistCheckedSentenceUsesCheckedMarker(t *testing.T) {
156
- tk := sampleTask()
157
- tk.Checklist = []data.CheckItem{{Text: "already done. still done.", Done: true}}
158
-
159
- got := plainTerminal(RenderDetail(tk, 60, nil, 0, 0))
160
-
161
- if count := strings.Count(got, "[x]"); count != 2 {
162
- t.Fatalf("RenderDetail checked checkbox count = %d, want 2\n%s", count, got)
163
- }
164
- if strings.Contains(got, "[ ]") {
165
- t.Fatal("RenderDetail should not render unchecked marker for checked item")
166
- }
167
- }
168
-
169
- func TestRenderDetail_wrapsLongDescription(t *testing.T) {
170
- tk := sampleTask()
171
- tk.Description = "alpha beta gamma delta epsilon zeta eta theta iota kappa lambda"
172
- got := RenderDetail(tk, 30, nil, 0, 0)
173
- if strings.Contains(got, tk.Description) {
174
- t.Error("RenderDetail should wrap long description text")
175
- }
176
- if !strings.Contains(got, "alpha beta") || !strings.Contains(got, "lambda") {
177
- t.Error("RenderDetail should preserve wrapped description words")
178
- }
179
- }
180
-
181
- func TestRenderDetail_noAcceptanceSectionWhenEmpty(t *testing.T) {
182
- got := RenderDetail(sampleTask(), 60, nil, 0, 0)
183
- if strings.Contains(got, "Acceptance Criteria:") {
184
- t.Error("RenderDetail should not show Acceptance section when empty")
185
- }
186
- }
187
-
188
- func TestPhaseLabel_build(t *testing.T) {
189
- if got := phaseLabel(data.StageBuild); got != "build" {
190
- t.Errorf("phaseLabel(StageBuild) = %q, want %q", got, "build")
191
- }
192
- }
193
-
194
- func TestPhaseLabel_test(t *testing.T) {
195
- if got := phaseLabel(data.StageTest); got != "test" {
196
- t.Errorf("phaseLabel(StageTest) = %q, want %q", got, "test")
197
- }
198
- }
199
-
200
- func TestPhaseLabel_audit(t *testing.T) {
201
- if got := phaseLabel(data.StageAudit); got != "audit" {
202
- t.Errorf("phaseLabel(StageAudit) = %q, want %q", got, "audit")
203
- }
204
- }
205
-
206
- func TestPhaseLabel_default(t *testing.T) {
207
- if got := phaseLabel(""); got != "build" {
208
- t.Errorf("phaseLabel(%q) = %q, want %q", "", got, "build")
209
- }
210
- }
211
-
212
- func TestUpdate_enterOpensDetailOverlay(t *testing.T) {
213
- tasks := []data.Task{sampleTask()}
214
- m := NewModel(tasks, "v1", "E04-board-components")
215
- m.FocusedColumn = data.ColumnInProgress
216
- m.FocusedTask = 0
217
- got, _ := m.Update(tea.KeyMsg{Type: tea.KeyEnter})
218
- updated := requireModel(t, got)
219
- if updated.Overlay != OverlayDetail {
220
- t.Errorf("Overlay = %q, want %q", updated.Overlay, OverlayDetail)
221
- }
222
- }
223
-
224
- func TestUpdate_enterNoOpWhenNoTasks(t *testing.T) {
225
- m := NewModel(nil, "v1", "E04-board-components")
226
- m.FocusedColumn = data.ColumnPlanned
227
- got, _ := m.Update(tea.KeyMsg{Type: tea.KeyEnter})
228
- updated := requireModel(t, got)
229
- if updated.Overlay != OverlayNone {
230
- t.Errorf("Overlay = %q, want none when column has no tasks", updated.Overlay)
231
- }
232
- }
233
-
234
- func TestUpdate_detailOverlayEscCloses(t *testing.T) {
235
- m := NewModel(nil, "v1", "E04-board-components")
236
- m.Overlay = OverlayDetail
237
- got, _ := m.Update(tea.KeyMsg{Type: tea.KeyEsc})
238
- updated := requireModel(t, got)
239
- if updated.Overlay != OverlayNone {
240
- t.Errorf("Overlay = %q after esc, want none", updated.Overlay)
241
- }
242
- }
243
-
244
- func TestUpdate_detailOverlayBlocksColumnNav(t *testing.T) {
245
- m := NewModel(nil, "v1", "E04-board-components")
246
- m.Overlay = OverlayDetail
247
- m.FocusedColumn = data.ColumnPlanned
248
- got, _ := m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("l")})
249
- updated := requireModel(t, got)
250
- if updated.FocusedColumn != data.ColumnPlanned {
251
- t.Error("column nav should be blocked when detail overlay is open")
252
- }
253
- }
254
-
255
- func TestView_detailOverlayRendered(t *testing.T) {
256
- tasks := []data.Task{sampleTask()}
257
- m := NewModel(tasks, "v1", "E04-board-components")
258
- m.Width = 100
259
- m.Height = 30
260
- m.FocusedColumn = data.ColumnInProgress
261
- m.FocusedTask = 0
262
- m.Overlay = OverlayDetail
263
- got := m.View()
264
- if !strings.Contains(got, "TASK DETAIL") {
265
- t.Error("View() with OverlayDetail missing TASK DETAIL header")
266
- }
267
- if !strings.Contains(got, "E04/T001") {
268
- t.Error("View() with OverlayDetail missing task ID")
269
- }
270
- }
271
-
272
- func TestRenderDetail_routerPriorityLabel(t *testing.T) {
273
- task := sampleTask()
274
- router := &data.RouterState{Release: task.Release, Epic: task.Epic, Task: task.ID}
275
- got := RenderDetail(task, 60, router, 0, 0)
276
- if !strings.Contains(got, "(router priority)") {
277
- t.Error("RenderDetail missing router priority label for matching task")
278
- }
279
- }
280
-
281
- func TestRenderDetail_noRouterPriorityLabelWhenNoMatch(t *testing.T) {
282
- task := sampleTask()
283
- router := &data.RouterState{Release: task.Release, Epic: task.Epic, Task: "other-id"}
284
- got := RenderDetail(task, 60, router, 0, 0)
285
- if strings.Contains(got, "(router priority)") {
286
- t.Error("RenderDetail should not show router priority label for non-matching task")
287
- }
288
- }
289
-
290
- func TestRenderDetail_viewportShowsScrollIndicators(t *testing.T) {
291
- task := sampleTask()
292
- task.Description = "alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu nu xi omicron"
293
-
294
- got := RenderDetail(task, 32, nil, 8, 2)
295
-
296
- if !strings.Contains(got, "↑ 2 above") {
297
- t.Error("RenderDetail missing above indicator")
298
- }
299
- if !strings.Contains(got, "↓") || !strings.Contains(got, "more") {
300
- t.Error("RenderDetail missing more indicator")
301
- }
302
- if strings.Contains(got, "ID:") {
303
- t.Error("RenderDetail should not render body lines above viewport")
304
- }
305
- }
306
-
307
- func TestUpdate_detailOverlayScrollsWithJK(t *testing.T) {
308
- m := NewModel([]data.Task{sampleTask()}, "v1", "E04-board-components")
309
- m.Overlay = OverlayDetail
310
-
311
- got, _ := m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("j")})
312
- updated := requireModel(t, got)
313
- if updated.DetailOffset != 1 {
314
- t.Errorf("DetailOffset after j = %d, want 1", updated.DetailOffset)
315
- }
316
-
317
- got, _ = updated.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("k")})
318
- updated = requireModel(t, got)
319
- if updated.DetailOffset != 0 {
320
- t.Errorf("DetailOffset after k = %d, want 0", updated.DetailOffset)
321
- }
322
- }
323
-
324
- func TestSplitChecklistSentences_abbreviationEg(t *testing.T) {
325
- got := splitChecklistSentences("Use e.g. a widget. Done.")
326
- if len(got) != 2 {
327
- t.Fatalf("splitChecklistSentences with e.g. = %d sentences, want 2: %v", len(got), got)
328
- }
329
- if got[0] != "Use e.g. a widget." {
330
- t.Errorf("sentence[0] = %q, want %q", got[0], "Use e.g. a widget.")
331
- }
332
- }
333
-
334
- func TestSplitChecklistSentences_abbreviationIe(t *testing.T) {
335
- got := splitChecklistSentences("Call i.e. the function. Done.")
336
- if len(got) != 2 {
337
- t.Fatalf("splitChecklistSentences with i.e. = %d sentences, want 2: %v", len(got), got)
338
- }
339
- }
340
-
341
- func TestSplitChecklistSentences_abbreviationDr(t *testing.T) {
342
- got := splitChecklistSentences("Dr. Smith approved it. Done.")
343
- if len(got) != 2 {
344
- t.Fatalf("splitChecklistSentences with Dr. = %d sentences, want 2: %v", len(got), got)
345
- }
346
- if got[0] != "Dr. Smith approved it." {
347
- t.Errorf("sentence[0] = %q, want %q", got[0], "Dr. Smith approved it.")
348
- }
349
- }
350
-
351
- func TestSplitChecklistSentences_abbreviationEtc(t *testing.T) {
352
- got := splitChecklistSentences("Add widgets, buttons, etc. to the panel. Done.")
353
- if len(got) != 2 {
354
- t.Fatalf("splitChecklistSentences with etc. = %d sentences, want 2: %v", len(got), got)
355
- }
356
- }
357
-
358
- func TestSplitChecklistSentences_abbreviationCaseInsensitive(t *testing.T) {
359
- got := splitChecklistSentences("See Fig. 3 for details. Done.")
360
- if len(got) != 2 {
361
- t.Fatalf("splitChecklistSentences with Fig. = %d sentences, want 2: %v", len(got), got)
362
- }
363
- }
364
-
365
- func TestSplitChecklistSentences_normalSplitUnaffected(t *testing.T) {
366
- got := splitChecklistSentences("First sentence. Second sentence.")
367
- if len(got) != 2 {
368
- t.Fatalf("splitChecklistSentences normal split = %d sentences, want 2: %v", len(got), got)
369
- }
370
- }
371
-
372
- func TestOverlayWidth_clampMax(t *testing.T) {
373
- if got := overlayWidth(120); got != 80 {
374
- t.Errorf("overlayWidth(120) = %d, want 80", got)
375
- }
376
- }
377
-
378
- func TestOverlayWidth_termMinus4(t *testing.T) {
379
- if got := overlayWidth(60); got != 56 {
380
- t.Errorf("overlayWidth(60) = %d, want 56", got)
381
- }
382
- }
383
-
384
- func TestOverlayWidth_clampMin(t *testing.T) {
385
- if got := overlayWidth(10); got != 20 {
386
- t.Errorf("overlayWidth(10) = %d, want 20", got)
387
- }
388
- }