savepoint 1.0.3 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (418) hide show
  1. package/package.json +10 -3
  2. package/{savepoint → savepoint.exe} +0 -0
  3. package/.claude/settings.local.json +0 -38
  4. package/.golangci.yml +0 -11
  5. package/.prettierignore +0 -4
  6. package/.savepoint/Design.md +0 -206
  7. package/.savepoint/PRD.md +0 -58
  8. package/.savepoint/config.yml +0 -27
  9. package/.savepoint/releases/v1/epics/E01-go-setup/E01-Detail.md +0 -39
  10. package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T001-init-module.md +0 -42
  11. package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T002-entrypoint.md +0 -23
  12. package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T003-directory-structure.md +0 -24
  13. package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T004-makefile.md +0 -23
  14. package/.savepoint/releases/v1/epics/E02-data-readers/E02-Detail.md +0 -61
  15. package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T001-task-struct.md +0 -29
  16. package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T002-frontmatter-parser.md +0 -30
  17. package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T003-router-reader.md +0 -29
  18. package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T004-config-reader.md +0 -29
  19. package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T005-discovery.md +0 -30
  20. package/.savepoint/releases/v1/epics/E03-board-tui-core/E03-Detail.md +0 -38
  21. package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T001-model.md +0 -29
  22. package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T002-update-loop.md +0 -30
  23. package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T003-view.md +0 -34
  24. package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T004-styles.md +0 -29
  25. package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T005-layout.md +0 -42
  26. package/.savepoint/releases/v1/epics/E04-board-components/E04-Detail.md +0 -44
  27. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T001-column.md +0 -34
  28. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T002-card.md +0 -33
  29. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T003-epic-panel.md +0 -49
  30. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T004-detail-overlay.md +0 -40
  31. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T005-release-dropdown.md +0 -33
  32. package/.savepoint/releases/v1/epics/E04-board-components/tasks/T006-help-overlay.md +0 -34
  33. package/.savepoint/releases/v1/epics/E05-phase-transitions/E05-Detail.md +0 -38
  34. package/.savepoint/releases/v1/epics/E05-phase-transitions/tasks/T001-phase-stepping.md +0 -29
  35. package/.savepoint/releases/v1/epics/E05-phase-transitions/tasks/T002-gates.md +0 -31
  36. package/.savepoint/releases/v1/epics/E05-phase-transitions/tasks/T003-write-task.md +0 -31
  37. package/.savepoint/releases/v1/epics/E05-phase-transitions/tasks/T004-write-router.md +0 -31
  38. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/E06-Detail.md +0 -62
  39. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T001-color-system.md +0 -39
  40. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T002-header-and-dividers.md +0 -52
  41. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T003-footer-status-bar.md +0 -52
  42. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T004-component-refinement.md +0 -53
  43. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T005-restore-nav-hints.md +0 -39
  44. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T007-detail-card-fixes.md +0 -36
  45. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T008-checkbox-states.md +0 -40
  46. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T009-router-priority-marker.md +0 -48
  47. package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T010-auto-refresh-watcher.md +0 -66
  48. package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/Design.md +0 -39
  49. package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/tasks/T001-archive-epics.md +0 -20
  50. package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/tasks/T002-rewrite-prd.md +0 -22
  51. package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/tasks/T003-create-epic-stubs.md +0 -24
  52. package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/tasks/T004-update-router.md +0 -22
  53. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/Design.md +0 -118
  54. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/handoff.md +0 -9
  55. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T001-package-baseline.md +0 -45
  56. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T002-typescript-build.md +0 -48
  57. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T003-vitest-smoke.md +0 -43
  58. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T004-lint-format-gates.md +0 -45
  59. package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T005-scaffold-verification.md +0 -40
  60. package/.savepoint/releases/v1/epics/_archived/E02-data-model/Design.md +0 -142
  61. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T001-domain-ids-status.md +0 -27
  62. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T002-markdown-frontmatter-boundary.md +0 -28
  63. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T003-task-documents.md +0 -29
  64. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T004-release-epic-router-config-readers.md +0 -30
  65. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T005-dependency-validation.md +0 -29
  66. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T006-epic-task-set-reader.md +0 -29
  67. package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T007-quality-gates.md +0 -31
  68. package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/Design.md +0 -40
  69. package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/tasks/T001-phase-types.md +0 -27
  70. package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/tasks/T002-phase-frontmatter.md +0 -25
  71. package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/tasks/T003-simplify-config.md +0 -26
  72. package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/tasks/T004-simplify-router-domain.md +0 -24
  73. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/Design.md +0 -122
  74. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T001-argument-parser-contract.md +0 -28
  75. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T002-help-text-generation.md +0 -28
  76. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T003-terminal-environment-detection.md +0 -27
  77. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T004-command-stub-modules.md +0 -29
  78. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T005-cli-runner-dispatch.md +0 -34
  79. package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T006-entrypoint-quality-gates.md +0 -32
  80. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/Design.md +0 -43
  81. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T001-strip-args.md +0 -26
  82. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T002-strip-help.md +0 -23
  83. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T003-strip-run.md +0 -23
  84. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T004-delete-commands.md +0 -24
  85. package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T005-update-cli-tests.md +0 -22
  86. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/Design.md +0 -48
  87. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T001-board-data-phases.md +0 -26
  88. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T002-phase-rendering.md +0 -28
  89. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T003-detail-pane-phases.md +0 -27
  90. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T004-phase-transitions.md +0 -42
  91. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T005-phase-gates.md +0 -24
  92. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T006-phase-write-back.md +0 -24
  93. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T007-remove-audit-flow.md +0 -27
  94. package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T008-board-tests.md +0 -25
  95. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/Design.md +0 -85
  96. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T001-project-template-assets.md +0 -17
  97. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T002-release-and-prompt-assets.md +0 -20
  98. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T003-template-registry-renderer.md +0 -22
  99. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T004-template-integrity-tests.md +0 -17
  100. package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T005-template-closeout-quality-gates.md +0 -16
  101. package/.savepoint/releases/v1/epics/_archived/E05-init-command/Design.md +0 -88
  102. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T001-init-cli-contract.md +0 -22
  103. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T002-target-validation.md +0 -23
  104. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T003-scaffold-writer.md +0 -24
  105. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T004-magic-prompt-and-clipboard.md +0 -23
  106. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T005-dev-deps-install-option.md +0 -24
  107. package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T006-init-command-integration.md +0 -28
  108. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/Design.md +0 -53
  109. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T001-delete-dead-src.md +0 -23
  110. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T002-delete-dead-tests.md +0 -26
  111. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T003-delete-assets.md +0 -25
  112. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T004-clean-savepoint.md +0 -28
  113. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T005-rewrite-agents-md.md +0 -28
  114. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T006-clean-package-json.md +0 -23
  115. package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T007-verify.md +0 -25
  116. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/Design.md +0 -104
  117. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T001-board-command-data.md +0 -23
  118. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T002-board-view-state.md +0 -24
  119. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T003-transition-gates-and-writes.md +0 -25
  120. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T004-terminal-theme.md +0 -23
  121. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T005-ink-board-ui.md +0 -26
  122. package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T006-board-integration-audit-entry.md +0 -24
  123. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/Design.md +0 -88
  124. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T001-audit-cli-contract.md +0 -23
  125. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T002-quality-gate-runner.md +0 -23
  126. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T003-snapshot-and-prompt.md +0 -23
  127. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T004-audit-orchestration-router.md +0 -27
  128. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T005-proposal-validation-apply.md +0 -25
  129. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T006-audit-review-state.md +0 -24
  130. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T007-audit-review-ui.md +0 -26
  131. package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T008-audit-pipeline-integration.md +0 -24
  132. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/Design.md +0 -103
  133. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T001-acceptance-criteria-model.md +0 -30
  134. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T002-release-task-set-reader.md +0 -33
  135. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T003-board-data-and-plain-output.md +0 -34
  136. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T004-board-selection-state.md +0 -33
  137. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T005-ink-board-layout-cleanup.md +0 -37
  138. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T006-task-detail-popup.md +0 -36
  139. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T007-templates-acceptance-criteria.md +0 -34
  140. package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T008-board-workflow-integration.md +0 -41
  141. package/.savepoint/releases/v1/epics/_archived/E09-doctor-command/Design.md +0 -70
  142. package/.savepoint/releases/v1/epics/_archived/E10-docs-and-packaging/Design.md +0 -68
  143. package/.savepoint/releases/v1/epics/_archived/E11-release-validation/Design.md +0 -68
  144. package/.savepoint/releases/v1/v1-PRD.md +0 -66
  145. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/E01-Detail.md +0 -40
  146. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T001-next-activity-header.md +0 -56
  147. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T002-rename-epic-design-files.md +0 -38
  148. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T003-rename-release-prd.md +0 -28
  149. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T004-update-instruction-files.md +0 -51
  150. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T005-update-cross-references.md +0 -45
  151. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T006-column-and-detail-scrolling.md +0 -68
  152. package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T007-column-focus-border-stability.md +0 -57
  153. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/E02-Audit.md +0 -124
  154. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/E02-Detail.md +0 -49
  155. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T001-fix-makefile.md +0 -37
  156. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T002-linux-build-target.md +0 -38
  157. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T003-macos-build-target.md +0 -36
  158. package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T004-smoke-tests-and-artifacts.md +0 -59
  159. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/E03-Audit.md +0 -195
  160. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/E03-Detail.md +0 -45
  161. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T001-border-resize-fix.md +0 -40
  162. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T002-next-activity-below-header.md +0 -64
  163. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T003-checkbox-rendering-fix.md +0 -56
  164. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T005-unify-status-glyphs.md +0 -65
  165. package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T006-forced-256-color-profile.md +0 -36
  166. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/E04-Audit.md +0 -167
  167. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/E04-Detail.md +0 -51
  168. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T001-sidebar-focusable-navigation.md +0 -65
  169. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T002-epic-detail-overlay.md +0 -73
  170. package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T003-epic-status-glyphs.md +0 -73
  171. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/E05-Audit.md +0 -237
  172. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/E05-Detail.md +0 -54
  173. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T001-update-agents-md.md +0 -45
  174. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T002-update-router-md.md +0 -40
  175. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T003-update-design-md.md +0 -47
  176. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T004-implement-m-hotkey.md +0 -98
  177. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T005-update-help-overlay.md +0 -33
  178. package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T006-tests-and-quality-gates.md +0 -62
  179. package/.savepoint/releases/v1.1/epics/E06-audit-command/E06-Audit.md +0 -56
  180. package/.savepoint/releases/v1.1/epics/E06-audit-command/E06-Detail.md +0 -63
  181. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T005-proposals.md +0 -44
  182. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T007-apply-close.md +0 -35
  183. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T009-integration.md +0 -40
  184. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T010-audit-file-migration.md +0 -45
  185. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T011-model-tab-state.md +0 -26
  186. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T012-epic-audit-render.md +0 -33
  187. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T013-handle-tab-keys.md +0 -34
  188. package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T014-tab-indicator.md +0 -33
  189. package/.savepoint/releases/v1.1/epics/E07-init-command/E07-Audit.md +0 -336
  190. package/.savepoint/releases/v1.1/epics/E07-init-command/E07-Detail.md +0 -61
  191. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T001-cli-entrypoint.md +0 -37
  192. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T002-target-validation.md +0 -28
  193. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T003-scaffold-writer.md +0 -46
  194. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T004-atomic-writes.md +0 -27
  195. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T005-magic-prompt.md +0 -25
  196. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T006-clipboard.md +0 -26
  197. package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T007-integration-test.md +0 -26
  198. package/.savepoint/releases/v1.1/epics/E08-board-command/E08-Audit.md +0 -333
  199. package/.savepoint/releases/v1.1/epics/E08-board-command/E08-Detail.md +0 -68
  200. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T001-cli-entrypoint.md +0 -26
  201. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T002-non-tty-fallback.md +0 -27
  202. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T003-tui-app-shell.md +0 -28
  203. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T004-board-model.md +0 -29
  204. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T005-detail-pane.md +0 -27
  205. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T006-status-transitions.md +0 -29
  206. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T007-theme-fallbacks.md +0 -29
  207. package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T008-integration-test.md +0 -27
  208. package/.savepoint/releases/v1.1/epics/E09-doctor-command/E09-Audit.md +0 -207
  209. package/.savepoint/releases/v1.1/epics/E09-doctor-command/E09-Detail.md +0 -65
  210. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T001-cli-entrypoint.md +0 -24
  211. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T002-config-router-validation.md +0 -28
  212. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T003-structure-checks.md +0 -29
  213. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T004-dependency-checks.md +0 -27
  214. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T005-audit-orphan-checks.md +0 -28
  215. package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T006-quality-gates-report.md +0 -31
  216. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/E11-Detail.md +0 -36
  217. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T001-debug-logging.md +0 -25
  218. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T002-increase-debounce.md +0 -21
  219. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T003-error-handling.md +0 -22
  220. package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T004-test-verify.md +0 -29
  221. package/.savepoint/releases/v1.1/epics/E12-validation-fix/E12-Audit.md +0 -444
  222. package/.savepoint/releases/v1.1/epics/E12-validation-fix/E12-Detail.md +0 -45
  223. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T001-default-phase.md +0 -35
  224. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T002-default-status.md +0 -19
  225. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T003-better-errors.md +0 -29
  226. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T004-validate-on-write.md +0 -25
  227. package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T005-tests.md +0 -37
  228. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/E13-Audit.md +0 -118
  229. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/E13-Detail.md +0 -73
  230. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T001-safe-cleanup.md +0 -66
  231. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T002-bug-fixes.md +0 -35
  232. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T003-centralize-duplication.md +0 -60
  233. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T004-infrastructure.md +0 -33
  234. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T005-decompose-update.md +0 -37
  235. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T006-async-io.md +0 -40
  236. package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T007-test-coverage.md +0 -37
  237. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/E14-Audit.md +0 -267
  238. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/E14-Detail.md +0 -54
  239. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T001-group-model.md +0 -39
  240. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T002-data-interfaces.md +0 -42
  241. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T003-discover-orphans.md +0 -33
  242. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T004-epic-panel-headings.md +0 -35
  243. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T005-shell-tokenization.md +0 -27
  244. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T006-unify-enums.md +0 -29
  245. package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T007-testutil-package.md +0 -28
  246. package/.savepoint/releases/v1.1/epics/E15-hardening/E15-Detail.md +0 -43
  247. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T001-benchmarks.md +0 -31
  248. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T002-fuzz-targets.md +0 -28
  249. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T003-debug-flag.md +0 -30
  250. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T004-dist-checksums.md +0 -27
  251. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T005-windows-targets.md +0 -28
  252. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T006-abbreviation-splitting.md +0 -26
  253. package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T007-root-test-allowlist.md +0 -28
  254. package/.savepoint/releases/v1.1/epics/_archived/T001-cli-entrypoint.md +0 -25
  255. package/.savepoint/releases/v1.1/epics/_archived/T002-quality-gates.md +0 -27
  256. package/.savepoint/releases/v1.1/epics/_archived/T003-snapshot.md +0 -27
  257. package/.savepoint/releases/v1.1/epics/_archived/T004-ai-reconcile.md +0 -29
  258. package/.savepoint/releases/v1.1/epics/_archived/T006-tui-review.md +0 -31
  259. package/.savepoint/releases/v1.1/epics/_archived/T008-skip-handling.md +0 -34
  260. package/.savepoint/releases/v1.1/v1.1-PRD.md +0 -139
  261. package/.savepoint/router.md +0 -57
  262. package/.savepoint/visual-identity.md +0 -125
  263. package/AGENTS.md +0 -99
  264. package/CLAUDE.md +0 -1
  265. package/GEMINI.md +0 -1
  266. package/Makefile +0 -29
  267. package/agent-skills/ink-tui-design/SKILL.md +0 -309
  268. package/agent-skills/ink-tui-design/references/component-patterns.md +0 -371
  269. package/agent-skills/ink-tui-design/references/hooks-guide.md +0 -436
  270. package/agent-skills/ink-tui-design/references/ink-gotchas.md +0 -330
  271. package/agent-skills/ink-tui-design/references/testing-patterns.md +0 -384
  272. package/agent-skills/savepoint-audit/SKILL.md +0 -87
  273. package/agent-skills/savepoint-build-task/SKILL.md +0 -44
  274. package/agent-skills/savepoint-create-plan/SKILL.md +0 -33
  275. package/agent-skills/savepoint-create-task/SKILL.md +0 -44
  276. package/agent-skills/savepoint-draft-prd/SKILL.md +0 -37
  277. package/agent-skills/savepoint-system-design/SKILL.md +0 -38
  278. package/agent-skills/superpowers/brainstorming/SKILL.md +0 -165
  279. package/agent-skills/superpowers/brainstorming/visual-companion.md +0 -304
  280. package/agent-skills/superpowers/dispatching-parallel-agents/SKILL.md +0 -193
  281. package/agent-skills/superpowers/executing-plans/SKILL.md +0 -77
  282. package/agent-skills/superpowers/finishing-a-development-branch/SKILL.md +0 -213
  283. package/agent-skills/superpowers/receiving-code-review/SKILL.md +0 -226
  284. package/agent-skills/superpowers/requesting-code-review/SKILL.md +0 -115
  285. package/agent-skills/superpowers/requesting-code-review/code-reviewer.md +0 -160
  286. package/agent-skills/superpowers/subagent-driven-development/SKILL.md +0 -292
  287. package/agent-skills/superpowers/subagent-driven-development/code-quality-reviewer-prompt.md +0 -27
  288. package/agent-skills/superpowers/subagent-driven-development/implementer-prompt.md +0 -113
  289. package/agent-skills/superpowers/subagent-driven-development/spec-reviewer-prompt.md +0 -61
  290. package/agent-skills/superpowers/systematic-debugging/SKILL.md +0 -305
  291. package/agent-skills/superpowers/systematic-debugging/condition-based-waiting.md +0 -122
  292. package/agent-skills/superpowers/systematic-debugging/defense-in-depth.md +0 -130
  293. package/agent-skills/superpowers/systematic-debugging/root-cause-tracing.md +0 -183
  294. package/agent-skills/superpowers/test-driven-development/SKILL.md +0 -389
  295. package/agent-skills/superpowers/test-driven-development/testing-anti-patterns.md +0 -317
  296. package/agent-skills/superpowers/verification-before-completion/SKILL.md +0 -147
  297. package/agent-skills/superpowers/writing-plans/SKILL.md +0 -159
  298. package/agent-skills/superpowers/writing-plans/plan-document-reviewer-prompt.md +0 -49
  299. package/agent_skills_test.go +0 -91
  300. package/assets/banner.png +0 -0
  301. package/assets/logo.png +0 -0
  302. package/assets/strawman.png +0 -0
  303. package/cmd/board.go +0 -59
  304. package/cmd/board_test.go +0 -137
  305. package/cmd/doctor.go +0 -53
  306. package/cmd/doctor_test.go +0 -146
  307. package/cmd/init.go +0 -63
  308. package/cmd/init_test.go +0 -104
  309. package/go.mod +0 -36
  310. package/go.sum +0 -75
  311. package/internal/board/board.go +0 -177
  312. package/internal/board/board_test.go +0 -168
  313. package/internal/board/card.go +0 -129
  314. package/internal/board/card_test.go +0 -254
  315. package/internal/board/column.go +0 -127
  316. package/internal/board/column_test.go +0 -139
  317. package/internal/board/detail.go +0 -185
  318. package/internal/board/detail_test.go +0 -340
  319. package/internal/board/epic_panel.go +0 -262
  320. package/internal/board/epic_panel_test.go +0 -869
  321. package/internal/board/help.go +0 -41
  322. package/internal/board/help_test.go +0 -86
  323. package/internal/board/integration_test.go +0 -266
  324. package/internal/board/interfaces.go +0 -65
  325. package/internal/board/interfaces_test.go +0 -114
  326. package/internal/board/io.go +0 -93
  327. package/internal/board/layout.go +0 -68
  328. package/internal/board/layout_test.go +0 -106
  329. package/internal/board/model.go +0 -235
  330. package/internal/board/model_test.go +0 -67
  331. package/internal/board/plain.go +0 -88
  332. package/internal/board/plain_test.go +0 -117
  333. package/internal/board/release.go +0 -34
  334. package/internal/board/release_test.go +0 -177
  335. package/internal/board/render_policy_test.go +0 -77
  336. package/internal/board/status.go +0 -23
  337. package/internal/board/theme.go +0 -24
  338. package/internal/board/theme_test.go +0 -31
  339. package/internal/board/transitions.go +0 -113
  340. package/internal/board/transitions_test.go +0 -164
  341. package/internal/board/tui.go +0 -32
  342. package/internal/board/update.go +0 -556
  343. package/internal/board/update_test.go +0 -575
  344. package/internal/board/util.go +0 -76
  345. package/internal/board/view.go +0 -317
  346. package/internal/board/view_test.go +0 -315
  347. package/internal/board/watch.go +0 -130
  348. package/internal/buildtool/main.go +0 -211
  349. package/internal/buildtool/main_test.go +0 -46
  350. package/internal/data/config.go +0 -101
  351. package/internal/data/config_test.go +0 -122
  352. package/internal/data/discover.go +0 -178
  353. package/internal/data/discover_test.go +0 -130
  354. package/internal/data/errors.go +0 -13
  355. package/internal/data/lifecycle.go +0 -44
  356. package/internal/data/lifecycle_test.go +0 -41
  357. package/internal/data/parser.go +0 -242
  358. package/internal/data/parser_test.go +0 -281
  359. package/internal/data/router.go +0 -52
  360. package/internal/data/router_test.go +0 -35
  361. package/internal/data/task.go +0 -57
  362. package/internal/data/task_test.go +0 -51
  363. package/internal/data/write.go +0 -218
  364. package/internal/data/write_test.go +0 -623
  365. package/internal/doctor/checks.go +0 -567
  366. package/internal/doctor/checks_test.go +0 -716
  367. package/internal/doctor/gates.go +0 -193
  368. package/internal/doctor/gates_test.go +0 -166
  369. package/internal/doctor/interfaces.go +0 -64
  370. package/internal/doctor/interfaces_test.go +0 -104
  371. package/internal/doctor/repairs.go +0 -80
  372. package/internal/doctor/repairs_test.go +0 -81
  373. package/internal/doctor/report.go +0 -157
  374. package/internal/doctor/report_test.go +0 -89
  375. package/internal/init/clipboard.go +0 -146
  376. package/internal/init/clipboard_test.go +0 -74
  377. package/internal/init/install.go +0 -16
  378. package/internal/init/integration_test.go +0 -197
  379. package/internal/init/prompt.go +0 -14
  380. package/internal/init/prompt_test.go +0 -77
  381. package/internal/init/scaffold.go +0 -59
  382. package/internal/init/scaffold_test.go +0 -179
  383. package/internal/init/template_freshness_test.go +0 -56
  384. package/internal/init/validate.go +0 -85
  385. package/internal/init/validate_test.go +0 -141
  386. package/internal/init/write.go +0 -73
  387. package/internal/init/write_test.go +0 -91
  388. package/internal/styles/palette.go +0 -49
  389. package/internal/styles/styles.go +0 -139
  390. package/internal/styles/styles_test.go +0 -133
  391. package/internal/testutil/fixture.go +0 -113
  392. package/internal/testutil/fs.go +0 -26
  393. package/main.go +0 -117
  394. package/project-audit/audit_report_glm_5.1.md +0 -411
  395. package/project-audit/audit_report_opus_4.6 +0 -406
  396. package/project-audit/consolidated-audit-report.md +0 -456
  397. package/scripts/vitest-preload.cjs +0 -95
  398. package/templates/project/.savepoint/Design.md +0 -47
  399. package/templates/project/.savepoint/PRD.md +0 -34
  400. package/templates/project/.savepoint/config.yml +0 -27
  401. package/templates/project/.savepoint/router.md +0 -153
  402. package/templates/project/.savepoint/visual-identity.md +0 -122
  403. package/templates/project/AGENTS.md +0 -88
  404. package/templates/project/agent-skills/savepoint-audit/SKILL.md +0 -87
  405. package/templates/project/agent-skills/savepoint-build-task/SKILL.md +0 -44
  406. package/templates/project/agent-skills/savepoint-create-plan/SKILL.md +0 -33
  407. package/templates/project/agent-skills/savepoint-create-task/SKILL.md +0 -44
  408. package/templates/project/agent-skills/savepoint-draft-prd/SKILL.md +0 -37
  409. package/templates/project/agent-skills/savepoint-system-design/SKILL.md +0 -38
  410. package/templates/prompts/audit-reconciliation.prompt.md +0 -72
  411. package/templates/prompts/design.prompt.md +0 -45
  412. package/templates/prompts/epic-design.prompt.md +0 -43
  413. package/templates/prompts/magic-prompt.prompt.md +0 -7
  414. package/templates/prompts/prd.prompt.md +0 -42
  415. package/templates/prompts/task-breakdown.prompt.md +0 -54
  416. package/templates/prompts/task-building.prompt.md +0 -38
  417. package/templates/prompts/task-planning.prompt.md +0 -53
  418. package/templates/release/v1/PRD.md +0 -37
@@ -1,340 +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 TestOverlayWidth_clampMax(t *testing.T) {
325
- if got := overlayWidth(120); got != 80 {
326
- t.Errorf("overlayWidth(120) = %d, want 80", got)
327
- }
328
- }
329
-
330
- func TestOverlayWidth_termMinus4(t *testing.T) {
331
- if got := overlayWidth(60); got != 56 {
332
- t.Errorf("overlayWidth(60) = %d, want 56", got)
333
- }
334
- }
335
-
336
- func TestOverlayWidth_clampMin(t *testing.T) {
337
- if got := overlayWidth(10); got != 20 {
338
- t.Errorf("overlayWidth(10) = %d, want 20", got)
339
- }
340
- }
@@ -1,262 +0,0 @@
1
- package board
2
-
3
- import (
4
- "strings"
5
-
6
- "github.com/charmbracelet/lipgloss"
7
- "github.com/opencode/savepoint/internal/styles"
8
- )
9
-
10
- // RenderEpicDetail renders an overlay showing the content of an E##-Detail.md file.
11
- func RenderEpicDetail(epicSlug, content string, overlayW, maxHeight, offset int, tab int) string {
12
- inner := overlayW - detailBorderPad
13
- if inner < 4 {
14
- inner = 4
15
- }
16
-
17
- tabIndicator := renderTabIndicator(tab, inner)
18
- lines := []string{
19
- styles.EpicTitleFocused.Render("EPIC DETAIL"),
20
- tabIndicator,
21
- }
22
-
23
- body := epicDetailBody(content, inner)
24
- body = append(body, "", styles.CardMeta.Render("1:Detail 2:Audit esc:close"))
25
- lines = append(lines, visibleDetailLines(body, maxHeight-detailVerticalOverhead-1, offset)...)
26
-
27
- return styles.EpicDetailOverlay.Width(overlayW).Render(strings.Join(lines, "\n"))
28
- }
29
-
30
- func renderTabIndicator(tab int, width int) string {
31
- var detail, audit string
32
- if tab == 0 {
33
- detail = styles.EpicItemFocused.Render("DETAIL [1]")
34
- audit = styles.CardMeta.Render("AUDIT [2]")
35
- } else {
36
- detail = styles.CardMeta.Render("DETAIL [1]")
37
- audit = styles.EpicItemFocused.Render("AUDIT [2]")
38
- }
39
- return detail + styles.CardMeta.Render(" │ ") + audit
40
- }
41
-
42
- // stripFrontmatter removes YAML frontmatter (between leading --- markers) from content.
43
- func stripFrontmatter(content string) []string {
44
- lines := strings.Split(content, "\n")
45
- start := 0
46
- if len(lines) > 0 && strings.TrimSpace(lines[0]) == "---" {
47
- for i := 1; i < len(lines); i++ {
48
- if strings.TrimSpace(lines[i]) == "---" {
49
- start = i + 1
50
- break
51
- }
52
- }
53
- }
54
- return lines[start:]
55
- }
56
-
57
- // epicDetailBody parses markdown content into display lines, stripping frontmatter.
58
- func epicDetailBody(content string, width int) []string {
59
- if strings.TrimSpace(content) == "" || content == "(no detail available)" {
60
- return []string{styles.CardMeta.Render("(no detail available)")}
61
- }
62
-
63
- lines := stripFrontmatter(content)
64
-
65
- var body []string
66
- skip := false
67
- for _, line := range lines {
68
- trimmed := strings.TrimRight(line, " \t")
69
- if strings.HasPrefix(trimmed, "## ") {
70
- heading := strings.ToLower(strings.TrimPrefix(trimmed, "## "))
71
- skip = strings.Contains(heading, "component") || strings.Contains(heading, "files")
72
- }
73
- if skip {
74
- continue
75
- }
76
- switch {
77
- case strings.HasPrefix(trimmed, "# "):
78
- body = append(body, styles.EpicTitleFocused.Render(strings.TrimPrefix(trimmed, "# ")))
79
- case strings.HasPrefix(trimmed, "## "):
80
- body = append(body, "", styles.EpicItemFocused.Render(strings.TrimPrefix(trimmed, "## ")))
81
- case strings.HasPrefix(trimmed, "### "):
82
- body = append(body, styles.EpicItemFocused.Render(strings.TrimPrefix(trimmed, "### ")))
83
- case strings.HasPrefix(trimmed, "|"):
84
- body = append(body, styles.CardMeta.Render(trimmed))
85
- case trimmed == "":
86
- body = append(body, "")
87
- default:
88
- for _, wrapped := range WrapText(trimmed, width) {
89
- body = append(body, styles.CardMeta.Render(wrapped))
90
- }
91
- }
92
- }
93
- return body
94
- }
95
-
96
- // RenderEpicAuditTab renders an overlay showing audit findings from an E##-Audit.md file.
97
- func RenderEpicAuditTab(epicSlug, content string, overlayW, maxHeight, offset int, tab int) string {
98
- inner := overlayW - detailBorderPad
99
- if inner < 4 {
100
- inner = 4
101
- }
102
-
103
- tabIndicator := renderTabIndicator(tab, inner)
104
- lines := []string{
105
- styles.GlyphAudit.Render("EPIC AUDIT"),
106
- tabIndicator,
107
- }
108
-
109
- body := epicAuditBody(content, inner)
110
- body = append(body, "", styles.CardMeta.Render("1:Detail 2:Audit esc:close"))
111
- lines = append(lines, visibleDetailLines(body, maxHeight-detailVerticalOverhead-1, offset)...)
112
-
113
- return styles.EpicDetailOverlay.Width(overlayW).Render(strings.Join(lines, "\n"))
114
- }
115
-
116
- var epicAuditHiddenSectionHeadings = map[string]struct{}{
117
- "12. Distribution & build": {},
118
- "Acceptance Criteria": {},
119
- "Architectural notes": {},
120
- "Boundaries": {},
121
- "Context Files": {},
122
- "Implemented As": {},
123
- "Implemented as": {},
124
- "Implementation Plan": {},
125
- "Manual audit override": {},
126
- "Proposed Changes": {},
127
- "Quality Review": {},
128
- "With": {},
129
- }
130
-
131
- func epicAuditBody(content string, width int) []string {
132
- if strings.TrimSpace(content) == "" || content == "(no audit available)" {
133
- return []string{styles.CardMeta.Render("(no audit available)")}
134
- }
135
-
136
- lines := stripFrontmatter(content)
137
-
138
- var body []string
139
- inHiddenSection := false
140
-
141
- for _, line := range lines {
142
- trimmed := strings.TrimRight(line, " \t\r")
143
- switch {
144
- case strings.HasPrefix(trimmed, "## "):
145
- sectionName := strings.TrimPrefix(trimmed, "## ")
146
- _, inHiddenSection = epicAuditHiddenSectionHeadings[sectionName]
147
- if !inHiddenSection {
148
- body = append(body, "", styles.EpicItemFocused.Render(sectionName))
149
- }
150
- case inHiddenSection:
151
- case strings.HasPrefix(trimmed, "### "):
152
- body = append(body, styles.EpicItemFocused.Render(strings.TrimPrefix(trimmed, "### ")))
153
- case strings.HasPrefix(trimmed, "- [x] ") || strings.HasPrefix(trimmed, "- [X] "):
154
- text := strings.TrimPrefix(strings.TrimPrefix(trimmed, "- [x] "), "- [X] ")
155
- body = append(body, renderChecklistSentences(text, "[x] ", width, styles.TagDone)...)
156
- case strings.HasPrefix(trimmed, "- [ ] "):
157
- text := strings.TrimPrefix(trimmed, "- [ ] ")
158
- body = append(body, renderChecklistSentences(text, "[ ] ", width, styles.CardMeta)...)
159
- case strings.HasPrefix(trimmed, "- "):
160
- body = append(body, styles.CardMeta.Render("• "+strings.TrimPrefix(trimmed, "- ")))
161
- case trimmed == "":
162
- body = append(body, "")
163
- default:
164
- for _, wrapped := range WrapText(trimmed, width) {
165
- body = append(body, styles.CardMeta.Render(wrapped))
166
- }
167
- }
168
- }
169
- return body
170
- }
171
-
172
- const epicActiveMarker = "►"
173
-
174
- // RenderEpicSidebar renders the fixed left sidebar listing epics with active indicator.
175
- // If epics is empty and selected is non-empty, selected is shown as the sole entry.
176
- func RenderEpicSidebar(epics []string, selected string, width int, focus bool, cursor int, status map[string]string, maxHeight int) string {
177
- inner := width - epicPanelOverhead
178
- if inner < 2 {
179
- inner = 2
180
- }
181
- list := epics
182
- if len(list) == 0 && selected != "" {
183
- list = []string{selected}
184
- }
185
-
186
- title := styles.ColumnTitle.Render("EPICS")
187
- if focus {
188
- title = styles.EpicTitleFocused.Render("EPICS")
189
- }
190
- lines := []string{title, strings.Repeat("─", inner)}
191
- for i, e := range list {
192
- g := epicSidebarGlyph(status, e)
193
- gw := lipgloss.Width(g)
194
- if gw < 1 {
195
- gw = 1
196
- }
197
- label := truncate(e, inner-2-gw)
198
- if focus && len(epics) > 0 && i == cursor {
199
- lines = append(lines, styles.EpicItemFocused.Render(epicActiveMarker+" "+g+" "+label))
200
- } else if !focus && e == selected {
201
- lines = append(lines, styles.EpicItemFocused.Render(epicActiveMarker+" "+g+" "+label))
202
- } else {
203
- lines = append(lines, styles.TaskItem.Render(" "+g+" "+label))
204
- }
205
- }
206
- if len(list) == 0 {
207
- lines = append(lines, styles.TaskItem.Render("(none)"))
208
- }
209
- if maxHeight > 0 && len(lines) > maxHeight {
210
- items := lines[2:]
211
- available := maxHeight - 3
212
- if available < 1 {
213
- available = 1
214
- }
215
- clipped := make([]string, 0, maxHeight)
216
- clipped = append(clipped, lines[0], lines[1])
217
- clipped = append(clipped, items[:min(available, len(items))]...)
218
- if len(items) > available {
219
- clipped = append(clipped, renderScrollIndicator("↓", len(items)-available, "more"))
220
- }
221
- lines = clipped
222
- }
223
- style := styles.EpicPanel.Width(width)
224
- if focus && len(epics) > 0 {
225
- style = styles.EpicPanelFocused.Width(width)
226
- }
227
- return style.Render(strings.Join(lines, "\n"))
228
- }
229
-
230
- func epicSidebarGlyph(status map[string]string, epicID string) string {
231
- if status == nil {
232
- return statusGlyphDefault
233
- }
234
- s, ok := status[epicID]
235
- if !ok {
236
- return statusGlyphDefault
237
- }
238
- return statusGlyph(s)
239
- }
240
-
241
- // RenderEpicDropdown renders the epic selection dropdown overlay.
242
- func RenderEpicDropdown(epics []string, cursor int, width int) string {
243
- inner := width - epicPanelOverhead
244
- if inner < 2 {
245
- inner = 2
246
- }
247
-
248
- lines := []string{styles.ColumnTitleFocused.Render("SELECT EPIC"), strings.Repeat("─", inner)}
249
- for i, e := range epics {
250
- label := truncate(e, inner-2)
251
- if i == cursor {
252
- lines = append(lines, styles.TaskItemFocused.Render(epicActiveMarker+" "+label))
253
- } else {
254
- lines = append(lines, styles.TaskItem.Render(" "+label))
255
- }
256
- }
257
- if len(epics) == 0 {
258
- lines = append(lines, styles.TaskItem.Render("(none)"))
259
- }
260
- lines = append(lines, "", styles.CardMeta.Render("↑↓:nav enter:select esc:cancel"))
261
- return styles.EpicPanel.Width(width).Render(strings.Join(lines, "\n"))
262
- }