savepoint 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +10 -3
- package/savepoint.exe +0 -0
- package/.claude/settings.local.json +0 -38
- package/.github/workflows/ci.yml +0 -20
- package/.golangci.yml +0 -11
- package/.prettierignore +0 -4
- package/.savepoint/Design.md +0 -207
- package/.savepoint/PRD.md +0 -58
- package/.savepoint/config.yml +0 -27
- package/.savepoint/releases/v1/epics/E01-go-setup/E01-Detail.md +0 -39
- package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T001-init-module.md +0 -42
- package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T002-entrypoint.md +0 -23
- package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T003-directory-structure.md +0 -24
- package/.savepoint/releases/v1/epics/E01-go-setup/tasks/T004-makefile.md +0 -23
- package/.savepoint/releases/v1/epics/E02-data-readers/E02-Detail.md +0 -61
- package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T001-task-struct.md +0 -29
- package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T002-frontmatter-parser.md +0 -30
- package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T003-router-reader.md +0 -29
- package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T004-config-reader.md +0 -29
- package/.savepoint/releases/v1/epics/E02-data-readers/tasks/T005-discovery.md +0 -30
- package/.savepoint/releases/v1/epics/E03-board-tui-core/E03-Detail.md +0 -38
- package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T001-model.md +0 -29
- package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T002-update-loop.md +0 -30
- package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T003-view.md +0 -34
- package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T004-styles.md +0 -29
- package/.savepoint/releases/v1/epics/E03-board-tui-core/tasks/T005-layout.md +0 -42
- package/.savepoint/releases/v1/epics/E04-board-components/E04-Detail.md +0 -44
- package/.savepoint/releases/v1/epics/E04-board-components/tasks/T001-column.md +0 -34
- package/.savepoint/releases/v1/epics/E04-board-components/tasks/T002-card.md +0 -33
- package/.savepoint/releases/v1/epics/E04-board-components/tasks/T003-epic-panel.md +0 -49
- package/.savepoint/releases/v1/epics/E04-board-components/tasks/T004-detail-overlay.md +0 -40
- package/.savepoint/releases/v1/epics/E04-board-components/tasks/T005-release-dropdown.md +0 -33
- package/.savepoint/releases/v1/epics/E04-board-components/tasks/T006-help-overlay.md +0 -34
- package/.savepoint/releases/v1/epics/E05-phase-transitions/E05-Detail.md +0 -38
- package/.savepoint/releases/v1/epics/E05-phase-transitions/tasks/T001-phase-stepping.md +0 -29
- package/.savepoint/releases/v1/epics/E05-phase-transitions/tasks/T002-gates.md +0 -31
- package/.savepoint/releases/v1/epics/E05-phase-transitions/tasks/T003-write-task.md +0 -31
- package/.savepoint/releases/v1/epics/E05-phase-transitions/tasks/T004-write-router.md +0 -31
- package/.savepoint/releases/v1/epics/E06-atari-noir-layout/E06-Detail.md +0 -62
- package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T001-color-system.md +0 -39
- package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T002-header-and-dividers.md +0 -52
- package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T003-footer-status-bar.md +0 -52
- package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T004-component-refinement.md +0 -53
- package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T005-restore-nav-hints.md +0 -39
- package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T007-detail-card-fixes.md +0 -36
- package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T008-checkbox-states.md +0 -40
- package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T009-router-priority-marker.md +0 -48
- package/.savepoint/releases/v1/epics/E06-atari-noir-layout/tasks/T010-auto-refresh-watcher.md +0 -66
- package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/Design.md +0 -39
- package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/tasks/T001-archive-epics.md +0 -20
- package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/tasks/T002-rewrite-prd.md +0 -22
- package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/tasks/T003-create-epic-stubs.md +0 -24
- package/.savepoint/releases/v1/epics/_archived/E01-archive-and-reset/tasks/T004-update-router.md +0 -22
- package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/Design.md +0 -118
- package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/handoff.md +0 -9
- package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T001-package-baseline.md +0 -45
- package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T002-typescript-build.md +0 -48
- package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T003-vitest-smoke.md +0 -43
- package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T004-lint-format-gates.md +0 -45
- package/.savepoint/releases/v1/epics/_archived/E01-scaffolding/tasks/T005-scaffold-verification.md +0 -40
- package/.savepoint/releases/v1/epics/_archived/E02-data-model/Design.md +0 -142
- package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T001-domain-ids-status.md +0 -27
- package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T002-markdown-frontmatter-boundary.md +0 -28
- package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T003-task-documents.md +0 -29
- package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T004-release-epic-router-config-readers.md +0 -30
- package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T005-dependency-validation.md +0 -29
- package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T006-epic-task-set-reader.md +0 -29
- package/.savepoint/releases/v1/epics/_archived/E02-data-model/tasks/T007-quality-gates.md +0 -31
- package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/Design.md +0 -40
- package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/tasks/T001-phase-types.md +0 -27
- package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/tasks/T002-phase-frontmatter.md +0 -25
- package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/tasks/T003-simplify-config.md +0 -26
- package/.savepoint/releases/v1/epics/_archived/E02-domain-phase-model/tasks/T004-simplify-router-domain.md +0 -24
- package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/Design.md +0 -122
- package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T001-argument-parser-contract.md +0 -28
- package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T002-help-text-generation.md +0 -28
- package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T003-terminal-environment-detection.md +0 -27
- package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T004-command-stub-modules.md +0 -29
- package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T005-cli-runner-dispatch.md +0 -34
- package/.savepoint/releases/v1/epics/_archived/E03-cli-foundation/tasks/T006-entrypoint-quality-gates.md +0 -32
- package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/Design.md +0 -43
- package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T001-strip-args.md +0 -26
- package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T002-strip-help.md +0 -23
- package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T003-strip-run.md +0 -23
- package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T004-delete-commands.md +0 -24
- package/.savepoint/releases/v1/epics/_archived/E03-cli-simplify/tasks/T005-update-cli-tests.md +0 -22
- package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/Design.md +0 -48
- package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T001-board-data-phases.md +0 -26
- package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T002-phase-rendering.md +0 -28
- package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T003-detail-pane-phases.md +0 -27
- package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T004-phase-transitions.md +0 -42
- package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T005-phase-gates.md +0 -24
- package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T006-phase-write-back.md +0 -24
- package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T007-remove-audit-flow.md +0 -27
- package/.savepoint/releases/v1/epics/_archived/E04-board-phase-integration/tasks/T008-board-tests.md +0 -25
- package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/Design.md +0 -85
- package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T001-project-template-assets.md +0 -17
- package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T002-release-and-prompt-assets.md +0 -20
- package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T003-template-registry-renderer.md +0 -22
- package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T004-template-integrity-tests.md +0 -17
- package/.savepoint/releases/v1/epics/_archived/E04-templates-and-prompts/tasks/T005-template-closeout-quality-gates.md +0 -16
- package/.savepoint/releases/v1/epics/_archived/E05-init-command/Design.md +0 -88
- package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T001-init-cli-contract.md +0 -22
- package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T002-target-validation.md +0 -23
- package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T003-scaffold-writer.md +0 -24
- package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T004-magic-prompt-and-clipboard.md +0 -23
- package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T005-dev-deps-install-option.md +0 -24
- package/.savepoint/releases/v1/epics/_archived/E05-init-command/tasks/T006-init-command-integration.md +0 -28
- package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/Design.md +0 -53
- package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T001-delete-dead-src.md +0 -23
- package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T002-delete-dead-tests.md +0 -26
- package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T003-delete-assets.md +0 -25
- package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T004-clean-savepoint.md +0 -28
- package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T005-rewrite-agents-md.md +0 -28
- package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T006-clean-package-json.md +0 -23
- package/.savepoint/releases/v1/epics/_archived/E05-project-cleanup/tasks/T007-verify.md +0 -25
- package/.savepoint/releases/v1/epics/_archived/E06-tui-board/Design.md +0 -104
- package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T001-board-command-data.md +0 -23
- package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T002-board-view-state.md +0 -24
- package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T003-transition-gates-and-writes.md +0 -25
- package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T004-terminal-theme.md +0 -23
- package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T005-ink-board-ui.md +0 -26
- package/.savepoint/releases/v1/epics/_archived/E06-tui-board/tasks/T006-board-integration-audit-entry.md +0 -24
- package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/Design.md +0 -88
- package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T001-audit-cli-contract.md +0 -23
- package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T002-quality-gate-runner.md +0 -23
- package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T003-snapshot-and-prompt.md +0 -23
- package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T004-audit-orchestration-router.md +0 -27
- package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T005-proposal-validation-apply.md +0 -25
- package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T006-audit-review-state.md +0 -24
- package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T007-audit-review-ui.md +0 -26
- package/.savepoint/releases/v1/epics/_archived/E07-audit-pipeline/tasks/T008-audit-pipeline-integration.md +0 -24
- package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/Design.md +0 -103
- package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T001-acceptance-criteria-model.md +0 -30
- package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T002-release-task-set-reader.md +0 -33
- package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T003-board-data-and-plain-output.md +0 -34
- package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T004-board-selection-state.md +0 -33
- package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T005-ink-board-layout-cleanup.md +0 -37
- package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T006-task-detail-popup.md +0 -36
- package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T007-templates-acceptance-criteria.md +0 -34
- package/.savepoint/releases/v1/epics/_archived/E08-board-workflow-cleanup/tasks/T008-board-workflow-integration.md +0 -41
- package/.savepoint/releases/v1/epics/_archived/E09-doctor-command/Design.md +0 -70
- package/.savepoint/releases/v1/epics/_archived/E10-docs-and-packaging/Design.md +0 -68
- package/.savepoint/releases/v1/epics/_archived/E11-release-validation/Design.md +0 -68
- package/.savepoint/releases/v1/v1-PRD.md +0 -66
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/E01-Detail.md +0 -40
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T001-next-activity-header.md +0 -56
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T002-rename-epic-design-files.md +0 -38
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T003-rename-release-prd.md +0 -28
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T004-update-instruction-files.md +0 -51
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T005-update-cross-references.md +0 -45
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T006-column-and-detail-scrolling.md +0 -68
- package/.savepoint/releases/v1.1/epics/E01-tui-optimisation/tasks/T007-column-focus-border-stability.md +0 -57
- package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/E02-Audit.md +0 -124
- package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/E02-Detail.md +0 -49
- package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T001-fix-makefile.md +0 -37
- package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T002-linux-build-target.md +0 -38
- package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T003-macos-build-target.md +0 -36
- package/.savepoint/releases/v1.1/epics/E02-cross-platform-compatibility/tasks/T004-smoke-tests-and-artifacts.md +0 -59
- package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/E03-Audit.md +0 -195
- package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/E03-Detail.md +0 -45
- package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T001-border-resize-fix.md +0 -40
- package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T002-next-activity-below-header.md +0 -64
- package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T003-checkbox-rendering-fix.md +0 -56
- package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T005-unify-status-glyphs.md +0 -65
- package/.savepoint/releases/v1.1/epics/E03-ui-visual-refinement/tasks/T006-forced-256-color-profile.md +0 -36
- package/.savepoint/releases/v1.1/epics/E04-epic-navigation/E04-Audit.md +0 -167
- package/.savepoint/releases/v1.1/epics/E04-epic-navigation/E04-Detail.md +0 -51
- package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T001-sidebar-focusable-navigation.md +0 -65
- package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T002-epic-detail-overlay.md +0 -73
- package/.savepoint/releases/v1.1/epics/E04-epic-navigation/tasks/T003-epic-status-glyphs.md +0 -73
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/E05-Audit.md +0 -237
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/E05-Detail.md +0 -54
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T001-update-agents-md.md +0 -45
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T002-update-router-md.md +0 -40
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T003-update-design-md.md +0 -47
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T004-implement-m-hotkey.md +0 -98
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T005-update-help-overlay.md +0 -33
- package/.savepoint/releases/v1.1/epics/E05-tasking-permissions/tasks/T006-tests-and-quality-gates.md +0 -62
- package/.savepoint/releases/v1.1/epics/E06-audit-command/E06-Audit.md +0 -56
- package/.savepoint/releases/v1.1/epics/E06-audit-command/E06-Detail.md +0 -63
- package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T005-proposals.md +0 -44
- package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T007-apply-close.md +0 -35
- package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T009-integration.md +0 -40
- package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T010-audit-file-migration.md +0 -45
- package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T011-model-tab-state.md +0 -26
- package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T012-epic-audit-render.md +0 -33
- package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T013-handle-tab-keys.md +0 -34
- package/.savepoint/releases/v1.1/epics/E06-audit-command/tasks/T014-tab-indicator.md +0 -33
- package/.savepoint/releases/v1.1/epics/E07-init-command/E07-Audit.md +0 -336
- package/.savepoint/releases/v1.1/epics/E07-init-command/E07-Detail.md +0 -61
- package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T001-cli-entrypoint.md +0 -37
- package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T002-target-validation.md +0 -28
- package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T003-scaffold-writer.md +0 -46
- package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T004-atomic-writes.md +0 -27
- package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T005-magic-prompt.md +0 -25
- package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T006-clipboard.md +0 -26
- package/.savepoint/releases/v1.1/epics/E07-init-command/tasks/T007-integration-test.md +0 -26
- package/.savepoint/releases/v1.1/epics/E08-board-command/E08-Audit.md +0 -333
- package/.savepoint/releases/v1.1/epics/E08-board-command/E08-Detail.md +0 -68
- package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T001-cli-entrypoint.md +0 -26
- package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T002-non-tty-fallback.md +0 -27
- package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T003-tui-app-shell.md +0 -28
- package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T004-board-model.md +0 -29
- package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T005-detail-pane.md +0 -27
- package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T006-status-transitions.md +0 -29
- package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T007-theme-fallbacks.md +0 -29
- package/.savepoint/releases/v1.1/epics/E08-board-command/tasks/T008-integration-test.md +0 -27
- package/.savepoint/releases/v1.1/epics/E09-doctor-command/E09-Audit.md +0 -207
- package/.savepoint/releases/v1.1/epics/E09-doctor-command/E09-Detail.md +0 -65
- package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T001-cli-entrypoint.md +0 -24
- package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T002-config-router-validation.md +0 -28
- package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T003-structure-checks.md +0 -29
- package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T004-dependency-checks.md +0 -27
- package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T005-audit-orphan-checks.md +0 -28
- package/.savepoint/releases/v1.1/epics/E09-doctor-command/tasks/T006-quality-gates-report.md +0 -31
- package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/E11-Detail.md +0 -36
- package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T001-debug-logging.md +0 -25
- package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T002-increase-debounce.md +0 -21
- package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T003-error-handling.md +0 -22
- package/.savepoint/releases/v1.1/epics/E11-board-refresh-fix/tasks/T004-test-verify.md +0 -29
- package/.savepoint/releases/v1.1/epics/E12-validation-fix/E12-Audit.md +0 -444
- package/.savepoint/releases/v1.1/epics/E12-validation-fix/E12-Detail.md +0 -45
- package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T001-default-phase.md +0 -35
- package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T002-default-status.md +0 -19
- package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T003-better-errors.md +0 -29
- package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T004-validate-on-write.md +0 -25
- package/.savepoint/releases/v1.1/epics/E12-validation-fix/tasks/T005-tests.md +0 -37
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/E13-Audit.md +0 -118
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/E13-Detail.md +0 -73
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T001-safe-cleanup.md +0 -66
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T002-bug-fixes.md +0 -35
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T003-centralize-duplication.md +0 -60
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T004-infrastructure.md +0 -33
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T005-decompose-update.md +0 -37
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T006-async-io.md +0 -40
- package/.savepoint/releases/v1.1/epics/E13-audit-remediation/tasks/T007-test-coverage.md +0 -37
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/E14-Audit.md +0 -267
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/E14-Detail.md +0 -54
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T001-group-model.md +0 -39
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T002-data-interfaces.md +0 -42
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T003-discover-orphans.md +0 -33
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T004-epic-panel-headings.md +0 -35
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T005-shell-tokenization.md +0 -27
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T006-unify-enums.md +0 -29
- package/.savepoint/releases/v1.1/epics/E14-structural-improvements/tasks/T007-testutil-package.md +0 -28
- package/.savepoint/releases/v1.1/epics/E15-hardening/E15-Audit.md +0 -272
- package/.savepoint/releases/v1.1/epics/E15-hardening/E15-Detail.md +0 -60
- package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T001-benchmarks.md +0 -31
- package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T002-fuzz-targets.md +0 -34
- package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T003-debug-flag.md +0 -30
- package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T004-dist-checksums.md +0 -27
- package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T005-windows-targets.md +0 -28
- package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T006-abbreviation-splitting.md +0 -26
- package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T007-root-test-allowlist.md +0 -33
- package/.savepoint/releases/v1.1/epics/E15-hardening/tasks/T008-ci-and-release-automation.md +0 -46
- package/.savepoint/releases/v1.1/epics/_archived/T001-cli-entrypoint.md +0 -25
- package/.savepoint/releases/v1.1/epics/_archived/T002-quality-gates.md +0 -27
- package/.savepoint/releases/v1.1/epics/_archived/T003-snapshot.md +0 -27
- package/.savepoint/releases/v1.1/epics/_archived/T004-ai-reconcile.md +0 -29
- package/.savepoint/releases/v1.1/epics/_archived/T006-tui-review.md +0 -31
- package/.savepoint/releases/v1.1/epics/_archived/T008-skip-handling.md +0 -34
- package/.savepoint/releases/v1.1/v1.1-PRD.md +0 -139
- package/.savepoint/router.md +0 -57
- package/.savepoint/visual-identity.md +0 -125
- package/AGENTS.md +0 -99
- package/CLAUDE.md +0 -1
- package/GEMINI.md +0 -1
- package/Makefile +0 -31
- package/agent-skills/ink-tui-design/SKILL.md +0 -309
- package/agent-skills/ink-tui-design/references/component-patterns.md +0 -371
- package/agent-skills/ink-tui-design/references/hooks-guide.md +0 -436
- package/agent-skills/ink-tui-design/references/ink-gotchas.md +0 -330
- package/agent-skills/ink-tui-design/references/testing-patterns.md +0 -384
- package/agent-skills/savepoint-audit/SKILL.md +0 -87
- package/agent-skills/savepoint-build-task/SKILL.md +0 -44
- package/agent-skills/savepoint-create-plan/SKILL.md +0 -33
- package/agent-skills/savepoint-create-task/SKILL.md +0 -44
- package/agent-skills/savepoint-draft-prd/SKILL.md +0 -37
- package/agent-skills/savepoint-system-design/SKILL.md +0 -38
- package/agent-skills/superpowers/brainstorming/SKILL.md +0 -165
- package/agent-skills/superpowers/brainstorming/visual-companion.md +0 -304
- package/agent-skills/superpowers/dispatching-parallel-agents/SKILL.md +0 -193
- package/agent-skills/superpowers/executing-plans/SKILL.md +0 -77
- package/agent-skills/superpowers/finishing-a-development-branch/SKILL.md +0 -213
- package/agent-skills/superpowers/receiving-code-review/SKILL.md +0 -226
- package/agent-skills/superpowers/requesting-code-review/SKILL.md +0 -115
- package/agent-skills/superpowers/requesting-code-review/code-reviewer.md +0 -160
- package/agent-skills/superpowers/subagent-driven-development/SKILL.md +0 -292
- package/agent-skills/superpowers/subagent-driven-development/code-quality-reviewer-prompt.md +0 -27
- package/agent-skills/superpowers/subagent-driven-development/implementer-prompt.md +0 -113
- package/agent-skills/superpowers/subagent-driven-development/spec-reviewer-prompt.md +0 -61
- package/agent-skills/superpowers/systematic-debugging/SKILL.md +0 -305
- package/agent-skills/superpowers/systematic-debugging/condition-based-waiting.md +0 -122
- package/agent-skills/superpowers/systematic-debugging/defense-in-depth.md +0 -130
- package/agent-skills/superpowers/systematic-debugging/root-cause-tracing.md +0 -183
- package/agent-skills/superpowers/test-driven-development/SKILL.md +0 -389
- package/agent-skills/superpowers/test-driven-development/testing-anti-patterns.md +0 -317
- package/agent-skills/superpowers/verification-before-completion/SKILL.md +0 -147
- package/agent-skills/superpowers/writing-plans/SKILL.md +0 -159
- package/agent-skills/superpowers/writing-plans/plan-document-reviewer-prompt.md +0 -49
- package/agent_skills_test.go +0 -91
- package/assets/banner.png +0 -0
- package/assets/logo.png +0 -0
- package/assets/strawman.png +0 -0
- package/cmd/board.go +0 -59
- package/cmd/board_test.go +0 -137
- package/cmd/doctor.go +0 -53
- package/cmd/doctor_test.go +0 -146
- package/cmd/init.go +0 -63
- package/cmd/init_test.go +0 -104
- package/go.mod +0 -36
- package/go.sum +0 -75
- package/internal/board/board.go +0 -181
- package/internal/board/board_test.go +0 -168
- package/internal/board/card.go +0 -129
- package/internal/board/card_test.go +0 -287
- package/internal/board/column.go +0 -156
- package/internal/board/column_test.go +0 -210
- package/internal/board/debug.go +0 -26
- package/internal/board/debug_test.go +0 -108
- package/internal/board/detail.go +0 -218
- package/internal/board/detail_test.go +0 -388
- package/internal/board/epic_panel.go +0 -264
- package/internal/board/epic_panel_test.go +0 -869
- package/internal/board/help.go +0 -41
- package/internal/board/help_test.go +0 -86
- package/internal/board/integration_test.go +0 -266
- package/internal/board/interfaces.go +0 -65
- package/internal/board/interfaces_test.go +0 -114
- package/internal/board/io.go +0 -93
- package/internal/board/layout.go +0 -68
- package/internal/board/layout_test.go +0 -106
- package/internal/board/model.go +0 -235
- package/internal/board/model_test.go +0 -67
- package/internal/board/plain.go +0 -88
- package/internal/board/plain_test.go +0 -117
- package/internal/board/release.go +0 -34
- package/internal/board/release_test.go +0 -177
- package/internal/board/render_policy_test.go +0 -77
- package/internal/board/status.go +0 -23
- package/internal/board/theme.go +0 -24
- package/internal/board/theme_test.go +0 -31
- package/internal/board/transitions.go +0 -113
- package/internal/board/transitions_test.go +0 -164
- package/internal/board/tui.go +0 -32
- package/internal/board/update.go +0 -575
- package/internal/board/update_test.go +0 -602
- package/internal/board/util.go +0 -76
- package/internal/board/view.go +0 -317
- package/internal/board/view_test.go +0 -377
- package/internal/board/watch.go +0 -136
- package/internal/buildtool/main.go +0 -249
- package/internal/buildtool/main_test.go +0 -224
- package/internal/data/config.go +0 -101
- package/internal/data/config_test.go +0 -122
- package/internal/data/discover.go +0 -178
- package/internal/data/discover_test.go +0 -130
- package/internal/data/errors.go +0 -13
- package/internal/data/fuzz_test.go +0 -75
- package/internal/data/lifecycle.go +0 -44
- package/internal/data/lifecycle_test.go +0 -41
- package/internal/data/parser.go +0 -243
- package/internal/data/parser_test.go +0 -281
- package/internal/data/router.go +0 -52
- package/internal/data/router_test.go +0 -35
- package/internal/data/task.go +0 -57
- package/internal/data/task_test.go +0 -51
- package/internal/data/testdata/fuzz/FuzzSplitFrontmatterBody/68eb66b0fe91e7e3 +0 -2
- package/internal/data/write.go +0 -221
- package/internal/data/write_test.go +0 -623
- package/internal/doctor/checks.go +0 -567
- package/internal/doctor/checks_test.go +0 -716
- package/internal/doctor/gates.go +0 -193
- package/internal/doctor/gates_test.go +0 -166
- package/internal/doctor/interfaces.go +0 -64
- package/internal/doctor/interfaces_test.go +0 -104
- package/internal/doctor/repairs.go +0 -80
- package/internal/doctor/repairs_test.go +0 -81
- package/internal/doctor/report.go +0 -157
- package/internal/doctor/report_test.go +0 -89
- package/internal/init/clipboard.go +0 -146
- package/internal/init/clipboard_test.go +0 -74
- package/internal/init/install.go +0 -16
- package/internal/init/integration_test.go +0 -197
- package/internal/init/prompt.go +0 -14
- package/internal/init/prompt_test.go +0 -77
- package/internal/init/scaffold.go +0 -59
- package/internal/init/scaffold_test.go +0 -179
- package/internal/init/template_freshness_test.go +0 -56
- package/internal/init/validate.go +0 -85
- package/internal/init/validate_test.go +0 -141
- package/internal/init/write.go +0 -73
- package/internal/init/write_test.go +0 -91
- package/internal/styles/palette.go +0 -49
- package/internal/styles/styles.go +0 -139
- package/internal/styles/styles_test.go +0 -133
- package/internal/testutil/fixture.go +0 -113
- package/internal/testutil/fs.go +0 -26
- package/main.go +0 -136
- package/project-audit/audit_report_glm_5.1.md +0 -411
- package/project-audit/audit_report_opus_4.6.md +0 -406
- package/project-audit/consolidated-audit-report.md +0 -456
- package/scripts/vitest-preload.cjs +0 -95
- package/templates/project/.savepoint/Design.md +0 -47
- package/templates/project/.savepoint/PRD.md +0 -34
- package/templates/project/.savepoint/config.yml +0 -27
- package/templates/project/.savepoint/router.md +0 -153
- package/templates/project/.savepoint/visual-identity.md +0 -122
- package/templates/project/AGENTS.md +0 -88
- package/templates/project/agent-skills/savepoint-audit/SKILL.md +0 -87
- package/templates/project/agent-skills/savepoint-build-task/SKILL.md +0 -44
- package/templates/project/agent-skills/savepoint-create-plan/SKILL.md +0 -33
- package/templates/project/agent-skills/savepoint-create-task/SKILL.md +0 -44
- package/templates/project/agent-skills/savepoint-draft-prd/SKILL.md +0 -37
- package/templates/project/agent-skills/savepoint-system-design/SKILL.md +0 -38
- package/templates/prompts/audit-reconciliation.prompt.md +0 -72
- package/templates/prompts/design.prompt.md +0 -45
- package/templates/prompts/epic-design.prompt.md +0 -43
- package/templates/prompts/magic-prompt.prompt.md +0 -7
- package/templates/prompts/prd.prompt.md +0 -42
- package/templates/prompts/task-breakdown.prompt.md +0 -54
- package/templates/prompts/task-building.prompt.md +0 -38
- package/templates/prompts/task-planning.prompt.md +0 -53
- package/templates/release/v1/PRD.md +0 -37
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: ink-tui-design
|
|
3
|
-
description: |
|
|
4
|
-
Ink.js TUI design and implementation guide with visual design vocabulary.
|
|
5
|
-
Use when:
|
|
6
|
-
(1) Creating or modifying Ink.js components for the savepoint TUI
|
|
7
|
-
(2) Implementing useInput/useApp hooks
|
|
8
|
-
(3) Solving emoji/icon width issues (string-width)
|
|
9
|
-
(4) Terminal responsive layout and dynamic height calculations
|
|
10
|
-
(5) Keyboard input handling (Enter, Ctrl+C, conflicts)
|
|
11
|
-
(6) Multi-width character (CJK) cursor issues
|
|
12
|
-
(7) CLI UI test design (ink-testing-library)
|
|
13
|
-
(8) Performance optimization (React.memo, custom comparators)
|
|
14
|
-
(9) Visual design decisions for terminal rendering
|
|
15
|
-
(10) Non-TTY fallback rendering
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
# Ink TUI Design
|
|
19
|
-
|
|
20
|
-
A unified guide for building terminal UIs with Ink.js, combining implementation
|
|
21
|
-
mechanics and visual design vocabulary. This skill owns the **how** of TUI
|
|
22
|
-
implementation. The **what** of visual direction (palette, spacing, signature
|
|
23
|
-
patterns) lives in `.savepoint/visual-identity.md` and always wins when the two
|
|
24
|
-
diverge.
|
|
25
|
-
|
|
26
|
-
## Quick Start
|
|
27
|
-
|
|
28
|
-
### New Component
|
|
29
|
-
|
|
30
|
-
1. Determine component type: Screen / Part / Common
|
|
31
|
-
2. Read [component-patterns.md](references/component-patterns.md) for the pattern
|
|
32
|
-
3. Read [ink-gotchas.md](references/ink-gotchas.md) if this component uses
|
|
33
|
-
emoji, `useInput`, or `Ctrl+C` handling
|
|
34
|
-
4. Add types where needed
|
|
35
|
-
5. Implement the component
|
|
36
|
-
6. Write tests (see [testing-patterns.md](references/testing-patterns.md))
|
|
37
|
-
|
|
38
|
-
### Common Problem Solving
|
|
39
|
-
|
|
40
|
-
| Problem | Reference |
|
|
41
|
-
| ------------------------ | ------------------------------------------------------------------- |
|
|
42
|
-
| Emoji width misalignment | [ink-gotchas.md#icon-emoji-width](references/ink-gotchas.md) |
|
|
43
|
-
| Ctrl+C fired twice | [ink-gotchas.md#ctrlc-handling](references/ink-gotchas.md) |
|
|
44
|
-
| useInput conflicts | [ink-gotchas.md#useinput-conflicts](references/ink-gotchas.md) |
|
|
45
|
-
| Enter key propagates | [ink-gotchas.md#enter-double-fire](references/ink-gotchas.md) |
|
|
46
|
-
| CJK cursor drift | [ink-gotchas.md#cjk-cursor](references/ink-gotchas.md) |
|
|
47
|
-
| Layout breaks on resize | [ink-gotchas.md#layout-breaks](references/ink-gotchas.md) |
|
|
48
|
-
| console.log interferes | [ink-gotchas.md#consolelog-interference](references/ink-gotchas.md) |
|
|
49
|
-
| Ink color type errors | [ink-gotchas.md#ink-color-types](references/ink-gotchas.md) |
|
|
50
|
-
|
|
51
|
-
## Directory Conventions
|
|
52
|
-
|
|
53
|
-
Match the project structure under `src/tui/`:
|
|
54
|
-
|
|
55
|
-
```
|
|
56
|
-
src/tui/
|
|
57
|
-
├── App.tsx # Root Ink component — board, detail pane, input routing
|
|
58
|
-
├── Board.tsx # Main kanban-style board view
|
|
59
|
-
├── DetailPane.tsx # Expanded task detail overlay
|
|
60
|
-
├── state/ # Pure reducer and view-state logic
|
|
61
|
-
│ ├── reducer.ts # Board navigation, selection, refresh state
|
|
62
|
-
│ ├── app-reducer.ts # App-level state (screen stack, mode)
|
|
63
|
-
│ └── view-state.ts # Derived view models
|
|
64
|
-
├── io/ # Transition gates and write helpers
|
|
65
|
-
│ ├── gates.ts # Can-transition? rules before writing status
|
|
66
|
-
│ └── write-status.ts # File-backed status updates with mtime checks
|
|
67
|
-
├── theme/ # Color capability detection and palette
|
|
68
|
-
│ ├── index.ts # Theme exports
|
|
69
|
-
│ ├── palette.ts # Color constants (ANSI 256, true color fallbacks)
|
|
70
|
-
│ └── capability.ts # Terminal color support detection
|
|
71
|
-
├── render/ # Non-TTY and plain-text rendering
|
|
72
|
-
│ ├── plain-table.ts # Deterministic table layout for CI/pipes
|
|
73
|
-
│ └── errors.ts # Warning and error message formatting
|
|
74
|
-
└── audit-review/ # Audit mode screens (optional, per epic)
|
|
75
|
-
├── AuditReviewApp.tsx
|
|
76
|
-
├── ProposalList.tsx
|
|
77
|
-
├── OperationDetail.tsx
|
|
78
|
-
├── state.ts
|
|
79
|
-
└── summary.ts
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
Rules:
|
|
83
|
-
|
|
84
|
-
- **One job per file.** A component that both renders and manages data state
|
|
85
|
-
should be split into a Screen wrapper (state) and a Part (rendering).
|
|
86
|
-
- **State is explicit and local.** Keep UI state in the smallest surface that
|
|
87
|
-
needs it. Derive view data from project files, never invent hidden state.
|
|
88
|
-
- **Test branching, navigation, render output, and non-TTY fallbacks.** Every
|
|
89
|
-
component with `if/else/switch` gets a test. Pure rendering without branches
|
|
90
|
-
may skip.
|
|
91
|
-
|
|
92
|
-
## Component Classification
|
|
93
|
-
|
|
94
|
-
### Screen
|
|
95
|
-
|
|
96
|
-
- Represents a complete interactive view
|
|
97
|
-
- Handles keyboard input via `useInput`
|
|
98
|
-
- Uses a 3-layer layout: Header / Content / Footer
|
|
99
|
-
- Owns screen-specific business logic and state
|
|
100
|
-
|
|
101
|
-
### Part
|
|
102
|
-
|
|
103
|
-
- Reusable, stateless rendering unit
|
|
104
|
-
- Optimized with `React.memo`
|
|
105
|
-
- Receives all data through props
|
|
106
|
-
|
|
107
|
-
### Common
|
|
108
|
-
|
|
109
|
-
- Basic input primitives (Select, Confirm, Input)
|
|
110
|
-
- Supports both controlled and uncontrolled modes
|
|
111
|
-
|
|
112
|
-
See [component-patterns.md](references/component-patterns.md) for complete
|
|
113
|
-
examples of each classification.
|
|
114
|
-
|
|
115
|
-
## Visual Design for Terminals
|
|
116
|
-
|
|
117
|
-
> **Override authority:** `.savepoint/visual-identity.md` owns the project's
|
|
118
|
-
> Atari-Noir design system (palette, spacing rhythm, signature patterns). The
|
|
119
|
-
> following is a general vocabulary. When they conflict, always defer to
|
|
120
|
-
> `visual-identity.md`.
|
|
121
|
-
|
|
122
|
-
### Box Drawing & Borders
|
|
123
|
-
|
|
124
|
-
Choose border styles that express intent:
|
|
125
|
-
|
|
126
|
-
| Style | Characters | Mood |
|
|
127
|
-
| ----------- | ---------- | ------------------------------ |
|
|
128
|
-
| Single line | `┌─┐│└┘` | Clean, modern, minimal |
|
|
129
|
-
| Double line | `╔═╗║╚╝` | Bold, formal, retro-mainframe |
|
|
130
|
-
| Rounded | `╭─╮│╰╯` | Soft, friendly |
|
|
131
|
-
| Heavy | `┏━┓┃┗┛` | Strong, industrial |
|
|
132
|
-
| ASCII | `+-+\|` | Retro, universal compatibility |
|
|
133
|
-
|
|
134
|
-
This project's default is **single line** in quiet `#1A1A1A` per
|
|
135
|
-
`visual-identity.md`. Use double line only for modal title bars or audit
|
|
136
|
-
headers. Avoid defaulting to plain ASCII unless targeting very old terminals.
|
|
137
|
-
|
|
138
|
-
### Color Strategies
|
|
139
|
-
|
|
140
|
-
| Strategy | When to use |
|
|
141
|
-
| ------------------- | ----------------------------------------------------------------------- |
|
|
142
|
-
| ANSI 16 | Maximum compatibility; craft combinations beyond default red/green/blue |
|
|
143
|
-
| 256-color | Richer palettes; gradients and subtle background variations |
|
|
144
|
-
| True color (24-bit) | Full spectrum; smooth transitions, background tints |
|
|
145
|
-
| Monochrome | Single color with intensity variations (dim, normal, bold, reverse) |
|
|
146
|
-
|
|
147
|
-
This project prefers **true color with 256/16 fallbacks**. See `theme/capability.ts`
|
|
148
|
-
for detection and `theme/palette.ts` for the Atari-Noir color constants.
|
|
149
|
-
|
|
150
|
-
Create atmosphere with:
|
|
151
|
-
|
|
152
|
-
- Background color blocks for panels (not giant fills — intentional accents)
|
|
153
|
-
- Color-coded semantic meaning (reinforce with text; never rely on color alone)
|
|
154
|
-
- Inverted/reverse video for the active/focused row
|
|
155
|
-
- Dim text for secondary info, bold for primary
|
|
156
|
-
|
|
157
|
-
### Typography & Text Hierarchy
|
|
158
|
-
|
|
159
|
-
The terminal is all typography. Make it count:
|
|
160
|
-
|
|
161
|
-
- **Weight:** Bold for primary actions and headers; dim for metadata
|
|
162
|
-
- **Case:** UPPERCASE for section headers; sentence case for body
|
|
163
|
-
- **Symbols:** Enrich with `→ • ◆ ★ ⚡ λ ∴ ≡` and status glyphs
|
|
164
|
-
- **Custom bullets:** Replace `-` with `▸ ◉ ✓ ⬢ ›` where it adds clarity
|
|
165
|
-
- **Letter spacing:** Simulate with spaces for impact headers where the medium
|
|
166
|
-
allows (fixed-width cells limit this)
|
|
167
|
-
|
|
168
|
-
### Layout Principles
|
|
169
|
-
|
|
170
|
-
- **Panels & Windows:** Distinct regions with quiet borders. Depth from
|
|
171
|
-
contrast/glow, not heavy shadows.
|
|
172
|
-
- **Columns:** Side-by-side using careful spacing. Keep layout compact and
|
|
173
|
-
readable on narrow terminals first.
|
|
174
|
-
- **Whitespace:** Generous padding inside panels; breathing room between
|
|
175
|
-
sections.
|
|
176
|
-
- **Density:** Match to purpose. The board view is information-dense; audit
|
|
177
|
-
review breathes more.
|
|
178
|
-
- **Hierarchy:** Clear visual distinction between primary content, secondary
|
|
179
|
-
info, and chrome.
|
|
180
|
-
|
|
181
|
-
### Data Display
|
|
182
|
-
|
|
183
|
-
| Element | Technique |
|
|
184
|
-
| ----------------- | ---------------------------------------------------------------- |
|
|
185
|
-
| Status indicators | `●` green/live, `○` empty, `◐` partial, `✓` complete, `✗` failed |
|
|
186
|
-
| Sparklines | `▁▂▃▄▅▆▇█` for inline mini-charts |
|
|
187
|
-
| Horizontal bars | Block characters for proportional comparison |
|
|
188
|
-
| Trees | `├── └── │` for hierarchies |
|
|
189
|
-
| Gauges | `[████████░░]` with percentage |
|
|
190
|
-
|
|
191
|
-
### Decorative Elements
|
|
192
|
-
|
|
193
|
-
- **Dividers:** `─────` `═══` `••••••` `░░░░░░` — match tone to section
|
|
194
|
-
- **Section markers:** `▶ SECTION`, `[ SECTION ]`, `─── SECTION ───`, `◆ SECTION`
|
|
195
|
-
- **Icons:** Prefer semantic Unicode or Nerd Font icons. Always apply width
|
|
196
|
-
overrides for emoji (see Pattern 1 below).
|
|
197
|
-
|
|
198
|
-
### Anti-Patterns to Avoid
|
|
199
|
-
|
|
200
|
-
Never ship generic terminal aesthetics:
|
|
201
|
-
|
|
202
|
-
- Plain unformatted text output
|
|
203
|
-
- Default colors without intentional palette
|
|
204
|
-
- `[INFO]`, `[ERROR]` prefixes without styling
|
|
205
|
-
- Simple `----` dividers everywhere
|
|
206
|
-
- Walls of unstructured text
|
|
207
|
-
- Generic progress bars without personality
|
|
208
|
-
- Boring help text formatting
|
|
209
|
-
- Inconsistent spacing and alignment
|
|
210
|
-
- Accidental line wrapping (treat as a bug)
|
|
211
|
-
- Relying on color alone for state changes
|
|
212
|
-
|
|
213
|
-
## Key Patterns
|
|
214
|
-
|
|
215
|
-
### 1. Icon Width Overrides
|
|
216
|
-
|
|
217
|
-
`string-width` v8+ miscalculates some emoji widths. Override explicitly:
|
|
218
|
-
|
|
219
|
-
```typescript
|
|
220
|
-
const iconWidthOverrides: Record<string, number> = {
|
|
221
|
-
"⚡": 1,
|
|
222
|
-
"✨": 1,
|
|
223
|
-
"✅": 1,
|
|
224
|
-
"⚠️": 1,
|
|
225
|
-
"🟢": 1,
|
|
226
|
-
"🟠": 1,
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
const getIconWidth = (icon: string): number => {
|
|
230
|
-
const baseWidth = stringWidth(icon);
|
|
231
|
-
const override = iconWidthOverrides[icon];
|
|
232
|
-
return override !== undefined ? Math.max(baseWidth, override) : baseWidth;
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
const padIcon = (icon: string, columnWidth = 2): string => {
|
|
236
|
-
const width = getIconWidth(icon);
|
|
237
|
-
const padding = Math.max(0, columnWidth - width);
|
|
238
|
-
return icon + " ".repeat(padding);
|
|
239
|
-
};
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
### 2. useInput Conflict Avoidance
|
|
243
|
-
|
|
244
|
-
Multiple `useInput` hooks all receive input. Guard each handler:
|
|
245
|
-
|
|
246
|
-
```typescript
|
|
247
|
-
useInput((input, key) => {
|
|
248
|
-
if (disabled) return; // Do nothing when this component is inactive
|
|
249
|
-
if (key.return) {
|
|
250
|
-
onSelect(selectedItem);
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
### 3. Ctrl+C Handling
|
|
256
|
-
|
|
257
|
-
```typescript
|
|
258
|
-
render(<App />, { exitOnCtrlC: false });
|
|
259
|
-
|
|
260
|
-
// Inside the component
|
|
261
|
-
useInput((input, key) => {
|
|
262
|
-
if (key.ctrl && input === "c") {
|
|
263
|
-
cleanup();
|
|
264
|
-
exit();
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
### 4. Dynamic Height Calculation
|
|
270
|
-
|
|
271
|
-
```typescript
|
|
272
|
-
const { rows } = useTerminalSize();
|
|
273
|
-
const headerLines = 2;
|
|
274
|
-
const footerLines = 1;
|
|
275
|
-
const contentHeight = rows - headerLines - footerLines;
|
|
276
|
-
const listLimit = Math.max(5, contentHeight);
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
### 5. React.memo + Custom Comparison
|
|
280
|
-
|
|
281
|
-
```typescript
|
|
282
|
-
function arePropsEqual<T>(prev: Props<T>, next: Props<T>): boolean {
|
|
283
|
-
if (prev.items.length !== next.items.length) return false;
|
|
284
|
-
for (let i = 0; i < prev.items.length; i++) {
|
|
285
|
-
if (prev.items[i].value !== next.items[i].value) return false;
|
|
286
|
-
}
|
|
287
|
-
return true;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
export const Select = React.memo(SelectComponent, arePropsEqual);
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
## Detailed References
|
|
294
|
-
|
|
295
|
-
- **Ink.js Gotchas & Common Problems**: [references/ink-gotchas.md](references/ink-gotchas.md)
|
|
296
|
-
- **Component Design Patterns**: [references/component-patterns.md](references/component-patterns.md)
|
|
297
|
-
- **Custom Hooks Guide**: [references/hooks-guide.md](references/hooks-guide.md)
|
|
298
|
-
- **Testing Patterns**: [references/testing-patterns.md](references/testing-patterns.md)
|
|
299
|
-
|
|
300
|
-
## Visual Identity Authority
|
|
301
|
-
|
|
302
|
-
All aesthetic decisions — palette, spacing, signature patterns, motion, tone —
|
|
303
|
-
are owned by `.savepoint/visual-identity.md`. When implementing a TUI feature:
|
|
304
|
-
|
|
305
|
-
1. Read `visual-identity.md` first if the task touches rendering, theme, or
|
|
306
|
-
visual design.
|
|
307
|
-
2. Return to this skill for Ink mechanics, component patterns, and testing.
|
|
308
|
-
3. If `visual-identity.md` says "quiet borders" and this skill says "double-line
|
|
309
|
-
headers," `visual-identity.md` wins.
|
|
@@ -1,371 +0,0 @@
|
|
|
1
|
-
# Component Design Patterns
|
|
2
|
-
|
|
3
|
-
## Table of Contents
|
|
4
|
-
|
|
5
|
-
1. [Directory Structure](#directory-structure)
|
|
6
|
-
2. [Component Classification](#component-classification)
|
|
7
|
-
3. [Three-Layer Layout](#three-layer-layout)
|
|
8
|
-
4. [React.memo Optimization](#reactmemo-optimization)
|
|
9
|
-
5. [Controlled / Uncontrolled Modes](#controlled--uncontrolled-modes)
|
|
10
|
-
6. [Loop-Free Navigation](#loop-free-navigation)
|
|
11
|
-
7. [ErrorBoundary Pattern](#errorboundary-pattern)
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## Directory Structure
|
|
16
|
-
|
|
17
|
-
Match the project layout under `src/tui/`:
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
src/tui/
|
|
21
|
-
├── App.tsx # Root component (screen management)
|
|
22
|
-
├── Board.tsx # Main board screen
|
|
23
|
-
├── DetailPane.tsx # Task detail overlay
|
|
24
|
-
├── state/
|
|
25
|
-
│ ├── reducer.ts # Board selection, navigation, refresh
|
|
26
|
-
│ ├── app-reducer.ts # App-level state
|
|
27
|
-
│ └── view-state.ts # Derived view models
|
|
28
|
-
├── io/
|
|
29
|
-
│ ├── gates.ts # Transition gate evaluation
|
|
30
|
-
│ └── write-status.ts # File-backed status writes
|
|
31
|
-
├── theme/
|
|
32
|
-
│ ├── palette.ts # Color constants
|
|
33
|
-
│ ├── capability.ts # Terminal color detection
|
|
34
|
-
│ └── index.ts # Theme exports
|
|
35
|
-
├── render/
|
|
36
|
-
│ ├── plain-table.ts # Non-TTY table rendering
|
|
37
|
-
│ └── errors.ts # Warning / error formatting
|
|
38
|
-
└── audit-review/ # Audit-specific screens
|
|
39
|
-
├── AuditReviewApp.tsx
|
|
40
|
-
├── ProposalList.tsx
|
|
41
|
-
├── OperationDetail.tsx
|
|
42
|
-
├── state.ts
|
|
43
|
-
└── summary.ts
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Component Classification
|
|
47
|
-
|
|
48
|
-
### Screen
|
|
49
|
-
|
|
50
|
-
A complete interactive view.
|
|
51
|
-
|
|
52
|
-
**Responsibilities:**
|
|
53
|
-
|
|
54
|
-
- Handle keyboard input via `useInput`
|
|
55
|
-
- Use Header / Content / Footer three-layer layout
|
|
56
|
-
- Own screen-specific business logic
|
|
57
|
-
|
|
58
|
-
**Naming:** `<Concept>Screen.tsx` (or `App.tsx`, `Board.tsx` for top-level)
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
interface BoardScreenProps {
|
|
62
|
-
tasks: TaskItem[];
|
|
63
|
-
stats: TaskStats;
|
|
64
|
-
onSelect: (task: TaskItem) => void;
|
|
65
|
-
onQuit?: () => void;
|
|
66
|
-
onRefresh?: () => void;
|
|
67
|
-
loading?: boolean;
|
|
68
|
-
error?: Error | null;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export function BoardScreen({
|
|
72
|
-
tasks,
|
|
73
|
-
stats,
|
|
74
|
-
onSelect,
|
|
75
|
-
onQuit,
|
|
76
|
-
onRefresh,
|
|
77
|
-
loading,
|
|
78
|
-
error,
|
|
79
|
-
}: BoardScreenProps) {
|
|
80
|
-
const { rows } = useTerminalSize();
|
|
81
|
-
|
|
82
|
-
useInput((input, key) => {
|
|
83
|
-
if (key.escape || input === "q") {
|
|
84
|
-
onQuit?.();
|
|
85
|
-
}
|
|
86
|
-
if (input === "r") {
|
|
87
|
-
onRefresh?.();
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
return (
|
|
92
|
-
<Box flexDirection="column" height={rows}>
|
|
93
|
-
<Header title="Savepoint Board" />
|
|
94
|
-
<Box flexDirection="column" flexGrow={1}>
|
|
95
|
-
{loading ? (
|
|
96
|
-
<LoadingIndicator />
|
|
97
|
-
) : (
|
|
98
|
-
<Select items={tasks} onSelect={onSelect} />
|
|
99
|
-
)}
|
|
100
|
-
</Box>
|
|
101
|
-
<Footer actions={[{ key: "q", label: "Quit" }]} />
|
|
102
|
-
</Box>
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Part
|
|
108
|
-
|
|
109
|
-
Reusable, stateless rendering units.
|
|
110
|
-
|
|
111
|
-
**Responsibilities:**
|
|
112
|
-
|
|
113
|
-
- Display only
|
|
114
|
-
- Optimized with `React.memo`
|
|
115
|
-
- All data received via props
|
|
116
|
-
|
|
117
|
-
**Naming:** `<Feature>.tsx`
|
|
118
|
-
|
|
119
|
-
```typescript
|
|
120
|
-
interface HeaderProps {
|
|
121
|
-
title: string;
|
|
122
|
-
version?: string;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export const Header = React.memo(function Header({
|
|
126
|
-
title,
|
|
127
|
-
version,
|
|
128
|
-
}: HeaderProps) {
|
|
129
|
-
return (
|
|
130
|
-
<Box borderStyle="single" paddingX={1}>
|
|
131
|
-
<Text bold>{title}</Text>
|
|
132
|
-
{version && <Text dimColor> v{version}</Text>}
|
|
133
|
-
</Box>
|
|
134
|
-
);
|
|
135
|
-
});
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### Common
|
|
139
|
-
|
|
140
|
-
Basic input primitives.
|
|
141
|
-
|
|
142
|
-
**Responsibilities:**
|
|
143
|
-
|
|
144
|
-
- Support both controlled and uncontrolled modes
|
|
145
|
-
- Generic interface reusable across the project
|
|
146
|
-
- May contain their own `useInput` for local keyboard handling
|
|
147
|
-
|
|
148
|
-
**Naming:** `<BaseType>.tsx` (e.g., `Select.tsx`, `Input.tsx`, `Confirm.tsx`)
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
## Three-Layer Layout
|
|
153
|
-
|
|
154
|
-
Standard screen layout pattern.
|
|
155
|
-
|
|
156
|
-
```typescript
|
|
157
|
-
export function StandardScreen({ children }: PropsWithChildren) {
|
|
158
|
-
const { rows } = useTerminalSize();
|
|
159
|
-
|
|
160
|
-
return (
|
|
161
|
-
<Box flexDirection="column" height={rows}>
|
|
162
|
-
{/* Layer 1: Header — fixed height */}
|
|
163
|
-
<Header title="App Title" />
|
|
164
|
-
|
|
165
|
-
{/* Layer 2: Content — flexGrow fills remaining height */}
|
|
166
|
-
<Box flexDirection="column" flexGrow={1}>
|
|
167
|
-
{children}
|
|
168
|
-
</Box>
|
|
169
|
-
|
|
170
|
-
{/* Layer 3: Footer — fixed height */}
|
|
171
|
-
<Footer actions={footerActions} />
|
|
172
|
-
</Box>
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
### Dynamic Height Calculation
|
|
178
|
-
|
|
179
|
-
```typescript
|
|
180
|
-
const { rows } = useTerminalSize();
|
|
181
|
-
|
|
182
|
-
// Fixed section line counts
|
|
183
|
-
const headerLines = 2; // border + title
|
|
184
|
-
const filterLines = 1; // filter input
|
|
185
|
-
const statsLines = 1; // statistics
|
|
186
|
-
const footerLines = 1; // footer
|
|
187
|
-
|
|
188
|
-
const fixedLines = headerLines + filterLines + statsLines + footerLines;
|
|
189
|
-
const contentHeight = rows - fixedLines;
|
|
190
|
-
const listLimit = Math.max(5, contentHeight); // minimum 5 lines
|
|
191
|
-
|
|
192
|
-
return (
|
|
193
|
-
<Select
|
|
194
|
-
items={items}
|
|
195
|
-
limit={listLimit}
|
|
196
|
-
onSelect={handleSelect}
|
|
197
|
-
/>
|
|
198
|
-
);
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
---
|
|
202
|
-
|
|
203
|
-
## React.memo Optimization
|
|
204
|
-
|
|
205
|
-
### Basic Pattern
|
|
206
|
-
|
|
207
|
-
```typescript
|
|
208
|
-
export const Header = React.memo(function Header(props: HeaderProps) {
|
|
209
|
-
return <Box>...</Box>;
|
|
210
|
-
});
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
### Custom Comparison Function
|
|
214
|
-
|
|
215
|
-
> **Important:** When using a custom comparison function, callback props
|
|
216
|
-
> (`onSelect`, etc.) must have stable references. Memoize callbacks in the
|
|
217
|
-
> parent with `useCallback`.
|
|
218
|
-
|
|
219
|
-
Compare by array contents rather than reference:
|
|
220
|
-
|
|
221
|
-
```typescript
|
|
222
|
-
function arePropsEqual<T extends SelectItem>(
|
|
223
|
-
prevProps: SelectProps<T>,
|
|
224
|
-
nextProps: SelectProps<T>,
|
|
225
|
-
): boolean {
|
|
226
|
-
// Simple value comparison
|
|
227
|
-
if (
|
|
228
|
-
prevProps.limit !== nextProps.limit ||
|
|
229
|
-
prevProps.disabled !== nextProps.disabled ||
|
|
230
|
-
prevProps.onSelect !== nextProps.onSelect
|
|
231
|
-
) {
|
|
232
|
-
return false;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// Array length comparison
|
|
236
|
-
if (prevProps.items.length !== nextProps.items.length) {
|
|
237
|
-
return false;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// Array element comparison
|
|
241
|
-
for (let i = 0; i < prevProps.items.length; i++) {
|
|
242
|
-
const prevItem = prevProps.items[i];
|
|
243
|
-
const nextItem = nextProps.items[i];
|
|
244
|
-
if (
|
|
245
|
-
prevItem.value !== nextItem.value ||
|
|
246
|
-
prevItem.label !== nextItem.label
|
|
247
|
-
) {
|
|
248
|
-
return false;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
return true;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
export const Select = React.memo(
|
|
256
|
-
SelectComponent,
|
|
257
|
-
arePropsEqual,
|
|
258
|
-
) as typeof SelectComponent;
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
---
|
|
262
|
-
|
|
263
|
-
## Controlled / Uncontrolled Modes
|
|
264
|
-
|
|
265
|
-
Allow parent components to control state when needed.
|
|
266
|
-
|
|
267
|
-
```typescript
|
|
268
|
-
interface SelectProps<T> {
|
|
269
|
-
items: T[];
|
|
270
|
-
onSelect: (item: T) => void;
|
|
271
|
-
// Uncontrolled mode
|
|
272
|
-
initialIndex?: number;
|
|
273
|
-
// Controlled mode
|
|
274
|
-
selectedIndex?: number;
|
|
275
|
-
onSelectedIndexChange?: (index: number) => void;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
function SelectComponent<T>({
|
|
279
|
-
items,
|
|
280
|
-
onSelect,
|
|
281
|
-
initialIndex = 0,
|
|
282
|
-
selectedIndex: externalSelectedIndex,
|
|
283
|
-
onSelectedIndexChange,
|
|
284
|
-
}: SelectProps<T>) {
|
|
285
|
-
// Internal state (uncontrolled)
|
|
286
|
-
const [internalSelectedIndex, setInternalSelectedIndex] =
|
|
287
|
-
useState(initialIndex);
|
|
288
|
-
|
|
289
|
-
// Determine mode
|
|
290
|
-
const isControlled = externalSelectedIndex !== undefined;
|
|
291
|
-
const selectedIndex = isControlled
|
|
292
|
-
? externalSelectedIndex
|
|
293
|
-
: internalSelectedIndex;
|
|
294
|
-
|
|
295
|
-
// Unified update function
|
|
296
|
-
const updateSelectedIndex = (value: number | ((prev: number) => number)) => {
|
|
297
|
-
const newIndex = typeof value === "function" ? value(selectedIndex) : value;
|
|
298
|
-
|
|
299
|
-
if (!isControlled) {
|
|
300
|
-
setInternalSelectedIndex(newIndex);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
onSelectedIndexChange?.(newIndex);
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
// ...
|
|
307
|
-
}
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
---
|
|
311
|
-
|
|
312
|
-
## Loop-Free Navigation
|
|
313
|
-
|
|
314
|
-
Stop at list boundaries rather than wrapping around.
|
|
315
|
-
|
|
316
|
-
```typescript
|
|
317
|
-
useInput((input, key) => {
|
|
318
|
-
if (key.upArrow || input === "k") {
|
|
319
|
-
// Move up (stop at 0)
|
|
320
|
-
updateSelectedIndex((current) => Math.max(0, current - 1));
|
|
321
|
-
} else if (key.downArrow || input === "j") {
|
|
322
|
-
// Move down (stop at last item)
|
|
323
|
-
updateSelectedIndex((current) => Math.min(items.length - 1, current + 1));
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
---
|
|
329
|
-
|
|
330
|
-
## ErrorBoundary Pattern
|
|
331
|
-
|
|
332
|
-
> **Note:** ErrorBoundary must be a class component due to React constraints.
|
|
333
|
-
> This is the only exception to the "function components + hooks" rule.
|
|
334
|
-
|
|
335
|
-
```typescript
|
|
336
|
-
interface Props {
|
|
337
|
-
children: React.ReactNode;
|
|
338
|
-
fallback?: React.ReactNode;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
interface State {
|
|
342
|
-
hasError: boolean;
|
|
343
|
-
error: Error | null;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
export class ErrorBoundary extends Component<Props, State> {
|
|
347
|
-
constructor(props: Props) {
|
|
348
|
-
super(props);
|
|
349
|
-
this.state = { hasError: false, error: null };
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
static getDerivedStateFromError(error: Error): State {
|
|
353
|
-
return { hasError: true, error };
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
|
357
|
-
console.error("ErrorBoundary caught:", error, errorInfo);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
render() {
|
|
361
|
-
if (this.state.hasError) {
|
|
362
|
-
return this.props.fallback ?? (
|
|
363
|
-
<Box>
|
|
364
|
-
<Text color="red">Error: {this.state.error?.message}</Text>
|
|
365
|
-
</Box>
|
|
366
|
-
);
|
|
367
|
-
}
|
|
368
|
-
return this.props.children;
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
```
|