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,330 +0,0 @@
1
- # Ink.js Gotchas & Common Problems
2
-
3
- ## Table of Contents
4
-
5
- 1. [Icon / Emoji Width Problems](#1-icon--emoji-width-problems)
6
- 2. [Ctrl+C Handling](#2-ctrlc-handling)
7
- 3. [useInput Conflicts](#3-useinput-conflicts)
8
- 4. [Enter Double-Fire](#4-enter-double-fire)
9
- 5. [CJK / Multi-Width Cursor](#5-cjk--multi-width-cursor)
10
- 6. [Layout Breaks](#6-layout-breaks)
11
- 7. [console.log Interference](#7-consolelog-interference)
12
- 8. [Ink Color Type Errors](#8-ink-color-type-errors)
13
-
14
- ---
15
-
16
- ## 1. Icon / Emoji Width Problems
17
-
18
- ### Problem
19
-
20
- `string-width` v8+ changed how Variation Selectors (VS15/VS16) are handled,
21
- causing emoji width calculations to be off. Terminals may render an emoji as
22
- 2 cells wide, but `stringWidth()` sometimes returns 1.
23
-
24
- ### Solution: WIDTH_OVERRIDES Pattern
25
-
26
- ```typescript
27
- import stringWidth from "string-width";
28
-
29
- const iconWidthOverrides: Record<string, number> = {
30
- "⚡": 1,
31
- "✨": 1,
32
- "🐛": 1,
33
- "🔥": 1,
34
- "🚀": 1,
35
- "📌": 1,
36
- "🟢": 1,
37
- "🟠": 1,
38
- "👉": 1,
39
- "💾": 1,
40
- "📤": 1,
41
- "🔃": 1,
42
- "✅": 1,
43
- "⚠️": 1,
44
- "🔗": 1,
45
- "💻": 1,
46
- "☁️": 1,
47
- };
48
-
49
- const getIconWidth = (icon: string): number => {
50
- const baseWidth = stringWidth(icon);
51
- const override = iconWidthOverrides[icon];
52
- return override !== undefined ? Math.max(baseWidth, override) : baseWidth;
53
- };
54
-
55
- // Fixed-width column padding
56
- const COLUMN_WIDTH = 2;
57
- const padIcon = (icon: string): string => {
58
- const width = getIconWidth(icon);
59
- const padding = Math.max(0, COLUMN_WIDTH - width);
60
- return icon + " ".repeat(padding);
61
- };
62
- ```
63
-
64
- ### Affected Areas
65
-
66
- - Status icon columns in board view
67
- - Progress indicators
68
- - Any fixed-width layout with inline symbols
69
-
70
- ---
71
-
72
- ## 2. Ctrl+C Handling
73
-
74
- ### Problem
75
-
76
- Ink handles `Ctrl+C` by default to exit the app. This can fire twice or
77
- conflict with custom cleanup logic.
78
-
79
- ### Solution: `exitOnCtrlC: false` + `useInput` + SIGINT
80
-
81
- ```typescript
82
- import { render, useApp, useInput } from "ink";
83
- import process from "node:process";
84
-
85
- function App({ onExit }: { onExit: () => void }) {
86
- const { exit } = useApp();
87
-
88
- useInput((input, key) => {
89
- if (key.ctrl && input === "c") {
90
- onExit();
91
- exit();
92
- }
93
- });
94
-
95
- // Also handle SIGINT directly
96
- useEffect(() => {
97
- const handler = () => {
98
- onExit();
99
- exit();
100
- };
101
- process.on("SIGINT", handler);
102
- return () => process.off("SIGINT", handler);
103
- }, [exit, onExit]);
104
-
105
- return <Box>...</Box>;
106
- }
107
-
108
- // Disable Ink's default Ctrl+C handler
109
- render(<App onExit={cleanup} />, { exitOnCtrlC: false });
110
- ```
111
-
112
- ---
113
-
114
- ## 3. useInput Conflicts
115
-
116
- ### Problem
117
-
118
- When multiple `useInput` hooks exist, **all handlers fire** for every keypress.
119
- A parent and child component may both process the same key.
120
-
121
- ### Solutions
122
-
123
- **Pattern 1: `disabled` prop**
124
-
125
- ```typescript
126
- useInput((input, key) => {
127
- if (disabled) return; // Ignore input when inactive
128
- // Handle key...
129
- });
130
- ```
131
-
132
- **Pattern 2: Mode flag**
133
-
134
- ```typescript
135
- const [filterMode, setFilterMode] = useState(false);
136
-
137
- useInput((input, key) => {
138
- if (filterMode) return; // Global shortcuts disabled while filtering
139
- if (input === "c") onCleanupCommand?.();
140
- });
141
- ```
142
-
143
- **Pattern 3: `blockKeys` prop on Input component**
144
-
145
- ```typescript
146
- // Inside an Input component
147
- useInput((input) => {
148
- if (blockKeys && blockKeys.includes(input)) {
149
- return; // Consume the key; do not propagate to parent
150
- }
151
- });
152
-
153
- // Usage
154
- <Input blockKeys={["c", "r", "f"]} ... />
155
- ```
156
-
157
- ---
158
-
159
- ## 4. Enter Double-Fire
160
-
161
- ### Problem
162
-
163
- After selecting an item in a Select component, the Enter key event propagates
164
- to the next screen and triggers an unwanted action there.
165
-
166
- ### Solution: Ready-state buffering
167
-
168
- ```typescript
169
- const [ready, setReady] = useState(false);
170
-
171
- useEffect(() => {
172
- // Defer input handling until after the first render cycle
173
- const timer = setTimeout(() => setReady(true), 50);
174
- return () => clearTimeout(timer);
175
- }, []);
176
-
177
- useInput((input, key) => {
178
- if (!ready) return; // Drop events during initialization
179
- if (key.return) {
180
- onSelect(selectedItem);
181
- }
182
- });
183
- ```
184
-
185
- ---
186
-
187
- ## 5. CJK / Multi-Width Cursor
188
-
189
- ### Problem
190
-
191
- CJK characters and some symbols display as 2 cells wide but count as 1
192
- character. Calculating cursor position by character count causes drift during
193
- CJK input.
194
-
195
- ### Solution: Display-width based position calculation
196
-
197
- ```typescript
198
- function getCharWidth(char: string): number {
199
- const code = char.codePointAt(0);
200
- if (!code) return 1;
201
-
202
- // CJK, Hangul, emoji ranges render as 2 cells wide
203
- if (
204
- (code >= 0x1100 && code <= 0x115f) || // Hangul Jamo
205
- (code >= 0x2e80 && code <= 0x9fff) || // CJK
206
- (code >= 0xac00 && code <= 0xd7af) || // Hangul Syllables
207
- (code >= 0xf900 && code <= 0xfaff) || // CJK Compatibility
208
- (code >= 0xfe10 && code <= 0xfe1f) || // Vertical forms
209
- (code >= 0x1f300 && code <= 0x1f9ff) // Emojis
210
- ) {
211
- return 2;
212
- }
213
- return 1;
214
- }
215
-
216
- function getDisplayWidth(str: string): number {
217
- return [...str].reduce((width, char) => width + getCharWidth(char), 0);
218
- }
219
-
220
- function toDisplayColumn(text: string, charPosition: number): number {
221
- return getDisplayWidth(text.slice(0, charPosition));
222
- }
223
- ```
224
-
225
- ---
226
-
227
- ## 6. Layout Breaks
228
-
229
- ### Problem
230
-
231
- - Long lines wrap past terminal width
232
- - Timestamps or labels get pushed to the next line
233
- - Column positions drift
234
-
235
- ### Solutions
236
-
237
- **Safe margin**
238
-
239
- ```typescript
240
- const { stdout } = useStdout();
241
- const columns = Math.max(20, (stdout?.columns ?? 80) - 1); // 1-cell margin
242
-
243
- // Or use 90% width (Gemini CLI pattern)
244
- const safeColumns = Math.floor(columns * 0.9);
245
- ```
246
-
247
- **Fixed-width columns**
248
-
249
- ```typescript
250
- const COLUMN_WIDTH = 2;
251
- const padToWidth = (content: string, width: number): string => {
252
- const actualWidth = stringWidth(content);
253
- const padding = Math.max(0, width - actualWidth);
254
- return content + " ".repeat(padding);
255
- };
256
- ```
257
-
258
- **Truncate to width**
259
-
260
- ```typescript
261
- function truncateToWidth(text: string, maxWidth: number): string {
262
- let width = 0;
263
- let result = "";
264
- for (const char of text) {
265
- const charWidth = getCharWidth(char);
266
- if (width + charWidth > maxWidth) {
267
- return result + "…";
268
- }
269
- width += charWidth;
270
- result += char;
271
- }
272
- return result;
273
- }
274
- ```
275
-
276
- ---
277
-
278
- ## 7. console.log Interference
279
-
280
- ### Problem
281
-
282
- `console.log` output competes with Ink's rendering. Ink redraws the screen
283
- periodically, so log lines get overwritten or corrupt the UI.
284
-
285
- ### Solutions
286
-
287
- **Structured logs to stderr**
288
-
289
- ```typescript
290
- import pino from "pino";
291
-
292
- const logger = pino({
293
- transport: {
294
- target: "pino-pretty",
295
- options: { destination: 2 }, // stderr
296
- },
297
- });
298
- ```
299
-
300
- **Conditional debug logging**
301
-
302
- ```typescript
303
- if (process.env.DEBUG) {
304
- console.error("Debug:", data); // stderr, not stdout
305
- }
306
- ```
307
-
308
- ---
309
-
310
- ## 8. Ink Color Type Errors
311
-
312
- ### Problem
313
-
314
- Using `<Text color="cyan">` in TypeScript can trigger strict type errors
315
- because Ink's color types are narrow.
316
-
317
- ### Solutions
318
-
319
- ```typescript
320
- // Use a const assertion
321
- <Text color={"cyan" as const}>...</Text>
322
-
323
- // Or define as a variable
324
- const selectedColor = "cyan" as const;
325
- <Text color={selectedColor}>...</Text>
326
-
327
- // Or use chalk inside the Text node
328
- import chalk from "chalk";
329
- <Text>{chalk.cyan("Selected")}</Text>
330
- ```
@@ -1,384 +0,0 @@
1
- # Testing Patterns & Best Practices
2
-
3
- ## Table of Contents
4
-
5
- 1. [Test Environment Setup](#test-environment-setup)
6
- 2. [Component Tests](#component-tests)
7
- 3. [Mock Patterns](#mock-patterns)
8
- 4. [Integration Tests](#integration-tests)
9
- 5. [Edge Cases](#edge-cases)
10
- 6. [Performance Tests](#performance-tests)
11
- 7. [Test Utilities](#test-utilities)
12
-
13
- ---
14
-
15
- ## Test Environment Setup
16
-
17
- ### Vitest + happy-dom
18
-
19
- ```typescript
20
- /**
21
- * @vitest-environment happy-dom
22
- */
23
- import { describe, it, expect, beforeEach, vi } from "vitest";
24
- import { render } from "@testing-library/react";
25
- import { Window } from "happy-dom";
26
-
27
- describe("Component", () => {
28
- beforeEach(() => {
29
- const window = new Window();
30
- // @ts-expect-error - happy-dom type mismatch
31
- globalThis.window = window;
32
- // @ts-expect-error - happy-dom type mismatch
33
- globalThis.document = window.document;
34
- });
35
- });
36
- ```
37
-
38
- ### ink-testing-library
39
-
40
- ```typescript
41
- import { render } from "ink-testing-library";
42
-
43
- describe("Select", () => {
44
- it("should render items", () => {
45
- const items = [
46
- { label: "Item 1", value: "1" },
47
- { label: "Item 2", value: "2" },
48
- ];
49
-
50
- const { lastFrame } = render(
51
- <Select items={items} onSelect={vi.fn()} />,
52
- );
53
-
54
- expect(lastFrame()).toContain("Item 1");
55
- expect(lastFrame()).toContain("Item 2");
56
- });
57
- });
58
- ```
59
-
60
- ---
61
-
62
- ## Component Tests
63
-
64
- ### Basic Pattern
65
-
66
- ```typescript
67
- import { render } from "ink-testing-library";
68
- import { describe, it, expect, vi } from "vitest";
69
-
70
- describe("Header", () => {
71
- it("should render title", () => {
72
- const { lastFrame } = render(<Header title="Test" />);
73
- expect(lastFrame()).toContain("Test");
74
- });
75
-
76
- it("should render version when provided", () => {
77
- const { lastFrame } = render(
78
- <Header title="Test" version="1.0.0" />,
79
- );
80
- expect(lastFrame()).toContain("1.0.0");
81
- });
82
- });
83
- ```
84
-
85
- ### Key Input Tests
86
-
87
- ```typescript
88
- import { render } from "ink-testing-library";
89
-
90
- describe("Select", () => {
91
- it("should move selection down on j key", async () => {
92
- const items = [
93
- { label: "Item 1", value: "1" },
94
- { label: "Item 2", value: "2" },
95
- ];
96
-
97
- const { stdin, lastFrame } = render(
98
- <Select items={items} onSelect={vi.fn()} />,
99
- );
100
-
101
- // Initial state
102
- expect(lastFrame()).toContain("› Item 1");
103
-
104
- // Press j to move down
105
- stdin.write("j");
106
-
107
- // Selection moved
108
- expect(lastFrame()).toContain("› Item 2");
109
- });
110
-
111
- it("should call onSelect on Enter", () => {
112
- const onSelect = vi.fn();
113
- const items = [{ label: "Item 1", value: "1" }];
114
-
115
- const { stdin } = render(
116
- <Select items={items} onSelect={onSelect} />,
117
- );
118
-
119
- stdin.write("\r"); // Enter key
120
-
121
- expect(onSelect).toHaveBeenCalledWith(items[0]);
122
- });
123
- });
124
- ```
125
-
126
- ### Async Tests
127
-
128
- ```typescript
129
- import { render } from "ink-testing-library";
130
- import { vi } from "vitest";
131
-
132
- describe("LoadingIndicator", () => {
133
- beforeEach(() => {
134
- vi.useFakeTimers();
135
- });
136
-
137
- afterEach(() => {
138
- vi.useRealTimers();
139
- });
140
-
141
- it("should show after delay", async () => {
142
- const { lastFrame } = render(
143
- <LoadingIndicator isLoading={true} delay={300} />,
144
- );
145
-
146
- // Not shown initially
147
- expect(lastFrame()).toBe("");
148
-
149
- // Shown after 300ms
150
- vi.advanceTimersByTime(300);
151
- expect(lastFrame()).toContain("Loading");
152
- });
153
- });
154
- ```
155
-
156
- ---
157
-
158
- ## Mock Patterns
159
-
160
- ### External Dependency Mock
161
-
162
- ```typescript
163
- vi.mock("../../../fs/project.js", () => ({
164
- findProjectRoot: vi.fn().mockResolvedValue("/repo"),
165
- readConfig: vi.fn().mockResolvedValue({ defaultRelease: "v1" }),
166
- getSavepointPath: vi.fn().mockReturnValue("/repo/.savepoint"),
167
- }));
168
- ```
169
-
170
- ### Screen Component Mock
171
-
172
- Mock sibling screens to isolate the component under test:
173
-
174
- ```typescript
175
- const capturedProps: BoardScreenProps[] = [];
176
-
177
- vi.mock("../../components/screens/BoardScreen.js", () => ({
178
- BoardScreen: (props: BoardScreenProps) => {
179
- capturedProps.push(props);
180
- return <div>Mocked BoardScreen</div>;
181
- },
182
- }));
183
-
184
- describe("App", () => {
185
- beforeEach(() => {
186
- capturedProps.length = 0; // Reset
187
- });
188
-
189
- it("should pass tasks to BoardScreen", async () => {
190
- render(<App />);
191
-
192
- await waitFor(() => {
193
- expect(capturedProps.length).toBeGreaterThan(0);
194
- });
195
-
196
- expect(capturedProps[0].tasks).toHaveLength(2);
197
- });
198
- });
199
- ```
200
-
201
- ### Hook Mock
202
-
203
- ```typescript
204
- vi.mock("../../hooks/useAsyncData.js", () => ({
205
- useAsyncData: () => ({
206
- data: [
207
- { id: "T001", title: "Setup project" },
208
- { id: "T002", title: "Add tests" },
209
- ],
210
- loading: false,
211
- error: null,
212
- refresh: vi.fn(),
213
- }),
214
- }));
215
- ```
216
-
217
- ### Conditional Mock Responses
218
-
219
- ```typescript
220
- const mockFetchTasks = vi.fn();
221
-
222
- vi.mock("../../../domain/tasks.js", () => ({
223
- fetchTasks: mockFetchTasks,
224
- }));
225
-
226
- describe("useAsyncData", () => {
227
- it("should handle error", async () => {
228
- mockFetchTasks.mockRejectedValueOnce(new Error("Read error"));
229
- // Assert error state is set
230
- });
231
-
232
- it("should return tasks", async () => {
233
- mockFetchTasks.mockResolvedValueOnce([{ id: "T001" }]);
234
- // Assert data is returned
235
- });
236
- });
237
- ```
238
-
239
- ---
240
-
241
- ## Integration Tests
242
-
243
- ### Navigation Flow
244
-
245
- ```typescript
246
- describe("Navigation", () => {
247
- it("should navigate from board to detail on Enter", async () => {
248
- const { stdin, lastFrame } = render(<App />);
249
-
250
- // Wait for board
251
- await waitFor(() => {
252
- expect(lastFrame()).toContain("Board");
253
- });
254
-
255
- // Press Enter
256
- stdin.write("\r");
257
-
258
- // Detail screen appears
259
- await waitFor(() => {
260
- expect(lastFrame()).toContain("Detail");
261
- });
262
- });
263
-
264
- it("should go back on Escape", async () => {
265
- const { stdin, lastFrame } = render(<App />);
266
-
267
- // Navigate to detail
268
- stdin.write("\r");
269
- await waitFor(() => {
270
- expect(lastFrame()).toContain("Detail");
271
- });
272
-
273
- // Press Escape
274
- stdin.write("\x1B"); // Escape key
275
-
276
- await waitFor(() => {
277
- expect(lastFrame()).toContain("Board");
278
- });
279
- });
280
- });
281
- ```
282
-
283
- ---
284
-
285
- ## Edge Cases
286
-
287
- ```typescript
288
- describe("Edge Cases", () => {
289
- it("should handle empty list", () => {
290
- const { lastFrame } = render(
291
- <Select items={[]} onSelect={vi.fn()} />,
292
- );
293
-
294
- expect(lastFrame()).not.toContain("undefined");
295
- });
296
-
297
- it("should handle very long labels", () => {
298
- const items = [{
299
- label: "A".repeat(200),
300
- value: "1",
301
- }];
302
-
303
- const { lastFrame } = render(
304
- <Select items={items} onSelect={vi.fn()} />,
305
- );
306
-
307
- // Assert output is defined (not crashed)
308
- expect(lastFrame()).toBeDefined();
309
- });
310
- });
311
- ```
312
-
313
- ---
314
-
315
- ## Performance Tests
316
-
317
- ```typescript
318
- describe("Performance", () => {
319
- it("should handle 1000 items without significant lag", async () => {
320
- const items = Array.from({ length: 1000 }, (_, i) => ({
321
- label: `Item ${i}`,
322
- value: String(i),
323
- }));
324
-
325
- const start = performance.now();
326
-
327
- const { stdin } = render(
328
- <Select items={items} onSelect={vi.fn()} limit={20} />,
329
- );
330
-
331
- // 100 navigation keypresses
332
- for (let i = 0; i < 100; i++) {
333
- stdin.write("j");
334
- }
335
-
336
- const duration = performance.now() - start;
337
-
338
- // Must complete within 1 second
339
- expect(duration).toBeLessThan(1000);
340
- });
341
- });
342
- ```
343
-
344
- ---
345
-
346
- ## Test Utilities
347
-
348
- ### waitFor Helper
349
-
350
- ```typescript
351
- async function waitFor(
352
- condition: () => boolean | void,
353
- timeout = 1000,
354
- ): Promise<void> {
355
- const start = Date.now();
356
-
357
- while (Date.now() - start < timeout) {
358
- try {
359
- if (condition()) return;
360
- } catch {
361
- // Condition not yet met
362
- }
363
- await new Promise((r) => setTimeout(r, 10));
364
- }
365
-
366
- throw new Error("waitFor timed out");
367
- }
368
- ```
369
-
370
- ### Key Constants
371
-
372
- ```typescript
373
- const KEYS = {
374
- ENTER: "\r",
375
- ESCAPE: "\x1B",
376
- UP: "\x1B[A",
377
- DOWN: "\x1B[B",
378
- LEFT: "\x1B[D",
379
- RIGHT: "\x1B[C",
380
- TAB: "\t",
381
- BACKSPACE: "\x7F",
382
- CTRL_C: "\x03",
383
- };
384
- ```