rafcode 1.0.0
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/.claude/settings.local.json +32 -0
- package/CLAUDE.md +187 -0
- package/LICENSE +21 -0
- package/RAF/001-raf-task-improvements/input.md +9 -0
- package/RAF/001-raf-task-improvements/outcomes/001-add-decisions-folder.md +21 -0
- package/RAF/001-raf-task-improvements/outcomes/002-fix-write-error-on-shutdown.md +22 -0
- package/RAF/001-raf-task-improvements/outcomes/003-stash-changes-on-failure.md +34 -0
- package/RAF/001-raf-task-improvements/outcomes/004-add-project-name-to-commits.md +28 -0
- package/RAF/001-raf-task-improvements/outcomes/005-add-running-time-display.md +36 -0
- package/RAF/001-raf-task-improvements/outcomes/006-add-task-name-to-logs.md +22 -0
- package/RAF/001-raf-task-improvements/outcomes/007-show-model-at-task-start.md +52 -0
- package/RAF/001-raf-task-improvements/outcomes/009-remove-editor-placeholder-text.md +20 -0
- package/RAF/001-raf-task-improvements/outcomes/SUMMARY.md +83 -0
- package/RAF/001-raf-task-improvements/plans/001-add-decisions-folder.md +38 -0
- package/RAF/001-raf-task-improvements/plans/002-fix-write-error-on-shutdown.md +33 -0
- package/RAF/001-raf-task-improvements/plans/003-stash-changes-on-failure.md +37 -0
- package/RAF/001-raf-task-improvements/plans/004-add-project-name-to-commits.md +34 -0
- package/RAF/001-raf-task-improvements/plans/005-add-running-time-display.md +39 -0
- package/RAF/001-raf-task-improvements/plans/006-add-task-name-to-logs.md +37 -0
- package/RAF/001-raf-task-improvements/plans/009-remove-editor-placeholder-text.md +34 -0
- package/RAF/002-raf-task-improvements-execution/decisions/DECISIONS.md +13 -0
- package/RAF/002-raf-task-improvements-execution/input.md +3 -0
- package/RAF/002-raf-task-improvements-execution/outcomes/001-commit-show-model-at-task-start.md +17 -0
- package/RAF/002-raf-task-improvements-execution/outcomes/002-delete-skipped-plan.md +23 -0
- package/RAF/002-raf-task-improvements-execution/outcomes/SUMMARY.md +32 -0
- package/RAF/002-raf-task-improvements-execution/plans/001-commit-show-model-at-task-start.md +37 -0
- package/RAF/002-raf-task-improvements-execution/plans/002-delete-skipped-plan.md +23 -0
- package/RAF/003-multi-project-execution/decisions/DECISIONS.md +68 -0
- package/RAF/003-multi-project-execution/input.md +6 -0
- package/RAF/003-multi-project-execution/outcomes/001-remove-state-json.md +52 -0
- package/RAF/003-multi-project-execution/outcomes/002-update-raf-status.md +50 -0
- package/RAF/003-multi-project-execution/outcomes/003-simplify-git-logic.md +35 -0
- package/RAF/003-multi-project-execution/outcomes/004-auto-commit-planning.md +43 -0
- package/RAF/003-multi-project-execution/outcomes/005-rerun-failed-tasks.md +43 -0
- package/RAF/003-multi-project-execution/outcomes/006-multi-project-execution.md +42 -0
- package/RAF/003-multi-project-execution/outcomes/007-verify-timeout.md +54 -0
- package/RAF/003-multi-project-execution/outcomes/008-move-decisions-file.md +38 -0
- package/RAF/003-multi-project-execution/outcomes/SUMMARY.md +79 -0
- package/RAF/003-multi-project-execution/plans/001-remove-state-json.md +71 -0
- package/RAF/003-multi-project-execution/plans/002-update-raf-status.md +65 -0
- package/RAF/003-multi-project-execution/plans/003-simplify-git-logic.md +74 -0
- package/RAF/003-multi-project-execution/plans/004-auto-commit-planning.md +57 -0
- package/RAF/003-multi-project-execution/plans/005-rerun-failed-tasks.md +69 -0
- package/RAF/003-multi-project-execution/plans/006-multi-project-execution.md +81 -0
- package/RAF/003-multi-project-execution/plans/007-verify-timeout.md +63 -0
- package/RAF/003-multi-project-execution/plans/008-move-decisions-file.md +78 -0
- package/RAF/004-task-naming-optimization/decisions.md +22 -0
- package/RAF/004-task-naming-optimization/input.md +6 -0
- package/RAF/004-task-naming-optimization/outcomes/001-remove-summary-file.md +17 -0
- package/RAF/004-task-naming-optimization/outcomes/002-base36-project-numbering.md +32 -0
- package/RAF/004-task-naming-optimization/outcomes/003-improve-haiku-prompt.md +20 -0
- package/RAF/004-task-naming-optimization/outcomes/SUMMARY.md +28 -0
- package/RAF/004-task-naming-optimization/plans/001-remove-summary-file.md +34 -0
- package/RAF/004-task-naming-optimization/plans/002-base36-project-numbering.md +56 -0
- package/RAF/004-task-naming-optimization/plans/003-improve-haiku-prompt.md +50 -0
- package/RAF/005-task-naming-improvements/decisions.md +60 -0
- package/RAF/005-task-naming-improvements/input.md +2 -0
- package/RAF/005-task-naming-improvements/outcomes/001-enhance-identifier-resolution.md +42 -0
- package/RAF/005-task-naming-improvements/outcomes/002-add-identifier-support-to-status.md +38 -0
- package/RAF/005-task-naming-improvements/outcomes/003-update-do-for-full-folder-names.md +44 -0
- package/RAF/005-task-naming-improvements/outcomes/004-implement-amend-flag-for-plan.md +55 -0
- package/RAF/005-task-naming-improvements/outcomes/005-commit-outcomes-on-complete.md +47 -0
- package/RAF/005-task-naming-improvements/outcomes/006-update-execution-prompt-commit-schema.md +40 -0
- package/RAF/005-task-naming-improvements/outcomes/007-allow-pending-task-amendments.md +38 -0
- package/RAF/005-task-naming-improvements/outcomes/008-fix-timeout-label.md +24 -0
- package/RAF/005-task-naming-improvements/plans/001-enhance-identifier-resolution.md +46 -0
- package/RAF/005-task-naming-improvements/plans/002-add-identifier-support-to-status.md +36 -0
- package/RAF/005-task-naming-improvements/plans/003-update-do-for-full-folder-names.md +38 -0
- package/RAF/005-task-naming-improvements/plans/004-implement-amend-flag-for-plan.md +67 -0
- package/RAF/005-task-naming-improvements/plans/005-commit-outcomes-on-complete.md +86 -0
- package/RAF/005-task-naming-improvements/plans/006-update-execution-prompt-commit-schema.md +60 -0
- package/RAF/005-task-naming-improvements/plans/007-allow-pending-task-amendments.md +60 -0
- package/RAF/005-task-naming-improvements/plans/008-fix-timeout-label.md +31 -0
- package/RAF/006-fix-double-summary-headers/decisions.md +28 -0
- package/RAF/006-fix-double-summary-headers/input.md +3 -0
- package/RAF/006-fix-double-summary-headers/outcomes/001-fix-double-summary-headers.md +29 -0
- package/RAF/006-fix-double-summary-headers/outcomes/002-update-readme-for-npm.md +31 -0
- package/RAF/006-fix-double-summary-headers/outcomes/003-npm-publish-instructions.md +30 -0
- package/RAF/006-fix-double-summary-headers/outcomes/004-flexible-project-lookup.md +47 -0
- package/RAF/006-fix-double-summary-headers/plans/001-fix-double-summary-headers.md +42 -0
- package/RAF/006-fix-double-summary-headers/plans/002-update-readme-for-npm.md +44 -0
- package/RAF/006-fix-double-summary-headers/plans/003-npm-publish-instructions.md +45 -0
- package/RAF/006-fix-double-summary-headers/plans/004-flexible-project-lookup.md +40 -0
- package/RAF/007-improve-outcome-format/decisions.md +28 -0
- package/RAF/007-improve-outcome-format/input.md +2 -0
- package/RAF/007-improve-outcome-format/outcomes/001-update-execution-prompt.md +10 -0
- package/RAF/007-improve-outcome-format/outcomes/002-update-state-derivation.md +17 -0
- package/RAF/007-improve-outcome-format/outcomes/003-update-do-command-outcome-handling.md +16 -0
- package/RAF/007-improve-outcome-format/outcomes/004-implement-failure-analysis.md +16 -0
- package/RAF/007-improve-outcome-format/outcomes/005-update-documentation.md +15 -0
- package/RAF/007-improve-outcome-format/plans/001-update-execution-prompt.md +36 -0
- package/RAF/007-improve-outcome-format/plans/002-update-state-derivation.md +35 -0
- package/RAF/007-improve-outcome-format/plans/003-update-do-command-outcome-handling.md +37 -0
- package/RAF/007-improve-outcome-format/plans/004-implement-failure-analysis.md +44 -0
- package/RAF/007-improve-outcome-format/plans/005-update-documentation.md +33 -0
- package/RAF/008-beautiful-do/decisions.md +31 -0
- package/RAF/008-beautiful-do/input.md +1 -0
- package/RAF/008-beautiful-do/outcomes/001-terminal-symbols.md +55 -0
- package/RAF/008-beautiful-do/outcomes/002-refactor-do-output.md +95 -0
- package/RAF/008-beautiful-do/outcomes/003-refactor-status-output.md +71 -0
- package/RAF/008-beautiful-do/outcomes/004-simplify-logger.md +53 -0
- package/RAF/008-beautiful-do/outcomes/005-add-tests.md +41 -0
- package/RAF/008-beautiful-do/plans/001-terminal-symbols.md +41 -0
- package/RAF/008-beautiful-do/plans/002-refactor-do-output.md +44 -0
- package/RAF/008-beautiful-do/plans/003-refactor-status-output.md +37 -0
- package/RAF/008-beautiful-do/plans/004-simplify-logger.md +32 -0
- package/RAF/008-beautiful-do/plans/005-add-tests.md +40 -0
- package/RAF/009-system-promt-ammend/decisions.md +13 -0
- package/RAF/009-system-promt-ammend/input.md +9 -0
- package/RAF/009-system-promt-ammend/outcomes/001-model-override.md +79 -0
- package/RAF/009-system-promt-ammend/outcomes/002-system-prompt-append.md +51 -0
- package/RAF/009-system-promt-ammend/outcomes/003-retry-context.md +60 -0
- package/RAF/009-system-promt-ammend/plans/001-model-override.md +61 -0
- package/RAF/009-system-promt-ammend/plans/002-system-prompt-append.md +56 -0
- package/RAF/009-system-promt-ammend/plans/003-retry-context.md +76 -0
- package/RAF/010-outcome-marker-fallback/decisions.md +19 -0
- package/RAF/010-outcome-marker-fallback/input.md +1 -0
- package/RAF/010-outcome-marker-fallback/outcomes/001-outcome-file-marker-fallback.md +35 -0
- package/RAF/010-outcome-marker-fallback/outcomes/002-creative-project-naming.md +47 -0
- package/RAF/010-outcome-marker-fallback/plans/001-outcome-file-marker-fallback.md +58 -0
- package/RAF/010-outcome-marker-fallback/plans/002-creative-project-naming.md +68 -0
- package/RAF/011-do-task-in-commit/decisions.md +22 -0
- package/RAF/011-do-task-in-commit/input.md +1 -0
- package/RAF/011-do-task-in-commit/outcomes/001-update-execution-prompt.md +54 -0
- package/RAF/011-do-task-in-commit/outcomes/002-update-tests.md +61 -0
- package/RAF/011-do-task-in-commit/outcomes/003-update-documentation.md +51 -0
- package/RAF/011-do-task-in-commit/plans/001-update-execution-prompt.md +46 -0
- package/RAF/011-do-task-in-commit/plans/002-update-tests.md +51 -0
- package/RAF/011-do-task-in-commit/plans/003-update-documentation.md +45 -0
- package/RAF/012-name-picker-buffet/decisions.md +40 -0
- package/RAF/012-name-picker-buffet/input.md +6 -0
- package/RAF/012-name-picker-buffet/outcomes/001-name-picker-for-raf-plan.md +49 -0
- package/RAF/012-name-picker-buffet/outcomes/002-interactive-project-picker-for-raf-do.md +49 -0
- package/RAF/012-name-picker-buffet/outcomes/003-raf-status-truncation.md +55 -0
- package/RAF/012-name-picker-buffet/outcomes/004-failure-reason-details.md +65 -0
- package/RAF/012-name-picker-buffet/outcomes/005-remove-raf-commits.md +57 -0
- package/RAF/012-name-picker-buffet/outcomes/006-update-execution-prompt-for-commits.md +47 -0
- package/RAF/012-name-picker-buffet/outcomes/007-fix-plan-mode-user-prompt.md +83 -0
- package/RAF/012-name-picker-buffet/outcomes/008-add-auto-flag-for-plan-mode.md +77 -0
- package/RAF/012-name-picker-buffet/plans/001-name-picker-for-raf-plan.md +47 -0
- package/RAF/012-name-picker-buffet/plans/002-interactive-project-picker-for-raf-do.md +43 -0
- package/RAF/012-name-picker-buffet/plans/003-raf-status-truncation.md +36 -0
- package/RAF/012-name-picker-buffet/plans/004-failure-reason-details.md +46 -0
- package/RAF/012-name-picker-buffet/plans/005-remove-raf-commits.md +42 -0
- package/RAF/012-name-picker-buffet/plans/006-update-execution-prompt-for-commits.md +47 -0
- package/RAF/012-name-picker-buffet/plans/007-fix-plan-mode-user-prompt.md +55 -0
- package/RAF/012-name-picker-buffet/plans/008-add-auto-flag-for-plan-mode.md +49 -0
- package/RAF/013-dependencies-watchdog/decisions.md +37 -0
- package/RAF/013-dependencies-watchdog/input.md +1 -0
- package/RAF/013-dependencies-watchdog/outcomes/001-define-dependency-syntax.md +56 -0
- package/RAF/013-dependencies-watchdog/outcomes/002-update-planning-prompts.md +60 -0
- package/RAF/013-dependencies-watchdog/outcomes/003-parse-dependencies-update-state.md +81 -0
- package/RAF/013-dependencies-watchdog/outcomes/004-implement-dependency-checking-in-do.md +116 -0
- package/RAF/013-dependencies-watchdog/outcomes/005-update-execution-prompts.md +75 -0
- package/RAF/013-dependencies-watchdog/outcomes/006-add-tests.md +100 -0
- package/RAF/013-dependencies-watchdog/outcomes/007-add-act-alias.md +46 -0
- package/RAF/013-dependencies-watchdog/outcomes/008-add-exit-message.md +52 -0
- package/RAF/013-dependencies-watchdog/plans/001-define-dependency-syntax.md +32 -0
- package/RAF/013-dependencies-watchdog/plans/002-update-planning-prompts.md +38 -0
- package/RAF/013-dependencies-watchdog/plans/003-parse-dependencies-update-state.md +46 -0
- package/RAF/013-dependencies-watchdog/plans/004-implement-dependency-checking-in-do.md +48 -0
- package/RAF/013-dependencies-watchdog/plans/005-update-execution-prompts.md +44 -0
- package/RAF/013-dependencies-watchdog/plans/006-add-tests.md +54 -0
- package/RAF/013-dependencies-watchdog/plans/007-add-act-alias.md +26 -0
- package/RAF/013-dependencies-watchdog/plans/008-add-exit-message.md +31 -0
- package/RAF/014-watchdog/decisions.md +16 -0
- package/RAF/014-watchdog/input.md +2 -0
- package/RAF/014-watchdog/outcomes/001-amend-flag-position.md +50 -0
- package/RAF/014-watchdog/outcomes/002-details-only-on-failure.md +58 -0
- package/RAF/014-watchdog/plans/001-amend-flag-position.md +34 -0
- package/RAF/014-watchdog/plans/002-details-only-on-failure.md +46 -0
- package/RAF/015-name-lottery/decisions.md +14 -0
- package/RAF/015-name-lottery/input.md +3 -0
- package/RAF/015-name-lottery/outcomes/001-auto-pick-project-name.md +31 -0
- package/RAF/015-name-lottery/outcomes/002-mention-plan-files-in-commit.md +23 -0
- package/RAF/015-name-lottery/outcomes/003-fix-input-md-in-amend-flow.md +44 -0
- package/RAF/015-name-lottery/plans/001-auto-pick-project-name.md +38 -0
- package/RAF/015-name-lottery/plans/002-mention-plan-files-in-commit.md +32 -0
- package/RAF/015-name-lottery/plans/003-fix-input-md-in-amend-flow.md +44 -0
- package/README.md +116 -0
- package/dist/commands/do.d.ts +12 -0
- package/dist/commands/do.d.ts.map +1 -0
- package/dist/commands/do.js +684 -0
- package/dist/commands/do.js.map +1 -0
- package/dist/commands/plan.d.ts +3 -0
- package/dist/commands/plan.d.ts.map +1 -0
- package/dist/commands/plan.js +345 -0
- package/dist/commands/plan.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +117 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/core/claude-runner.d.ts +78 -0
- package/dist/core/claude-runner.d.ts.map +1 -0
- package/dist/core/claude-runner.js +297 -0
- package/dist/core/claude-runner.js.map +1 -0
- package/dist/core/editor.d.ts +10 -0
- package/dist/core/editor.d.ts.map +1 -0
- package/dist/core/editor.js +77 -0
- package/dist/core/editor.js.map +1 -0
- package/dist/core/failure-analyzer.d.ts +28 -0
- package/dist/core/failure-analyzer.d.ts.map +1 -0
- package/dist/core/failure-analyzer.js +305 -0
- package/dist/core/failure-analyzer.js.map +1 -0
- package/dist/core/git.d.ts +42 -0
- package/dist/core/git.d.ts.map +1 -0
- package/dist/core/git.js +148 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/project-manager.d.ts +72 -0
- package/dist/core/project-manager.d.ts.map +1 -0
- package/dist/core/project-manager.js +193 -0
- package/dist/core/project-manager.js.map +1 -0
- package/dist/core/retry-handler.d.ts +19 -0
- package/dist/core/retry-handler.d.ts.map +1 -0
- package/dist/core/retry-handler.js +51 -0
- package/dist/core/retry-handler.js.map +1 -0
- package/dist/core/shutdown-handler.d.ts +30 -0
- package/dist/core/shutdown-handler.d.ts.map +1 -0
- package/dist/core/shutdown-handler.js +79 -0
- package/dist/core/shutdown-handler.js.map +1 -0
- package/dist/core/state-derivation.d.ts +82 -0
- package/dist/core/state-derivation.d.ts.map +1 -0
- package/dist/core/state-derivation.js +271 -0
- package/dist/core/state-derivation.js.map +1 -0
- package/dist/core/state-manager.d.ts +54 -0
- package/dist/core/state-manager.d.ts.map +1 -0
- package/dist/core/state-manager.js +198 -0
- package/dist/core/state-manager.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/output-parser.d.ts +19 -0
- package/dist/parsers/output-parser.d.ts.map +1 -0
- package/dist/parsers/output-parser.js +137 -0
- package/dist/parsers/output-parser.js.map +1 -0
- package/dist/prompts/amend.d.ts +20 -0
- package/dist/prompts/amend.d.ts.map +1 -0
- package/dist/prompts/amend.js +166 -0
- package/dist/prompts/amend.js.map +1 -0
- package/dist/prompts/execution.d.ts +30 -0
- package/dist/prompts/execution.d.ts.map +1 -0
- package/dist/prompts/execution.js +179 -0
- package/dist/prompts/execution.js.map +1 -0
- package/dist/prompts/planning.d.ts +15 -0
- package/dist/prompts/planning.d.ts.map +1 -0
- package/dist/prompts/planning.js +163 -0
- package/dist/prompts/planning.js.map +1 -0
- package/dist/types/config.d.ts +26 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +7 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/state.d.ts +33 -0
- package/dist/types/state.d.ts.map +1 -0
- package/dist/types/state.js +28 -0
- package/dist/types/state.js.map +1 -0
- package/dist/ui/name-picker-subprocess.d.ts +11 -0
- package/dist/ui/name-picker-subprocess.d.ts.map +1 -0
- package/dist/ui/name-picker-subprocess.js +83 -0
- package/dist/ui/name-picker-subprocess.js.map +1 -0
- package/dist/ui/name-picker.d.ts +19 -0
- package/dist/ui/name-picker.d.ts.map +1 -0
- package/dist/ui/name-picker.js +173 -0
- package/dist/ui/name-picker.js.map +1 -0
- package/dist/ui/project-picker.d.ts +27 -0
- package/dist/ui/project-picker.d.ts.map +1 -0
- package/dist/ui/project-picker.js +58 -0
- package/dist/ui/project-picker.js.map +1 -0
- package/dist/utils/config.d.ts +24 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +63 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/logger.d.ts +32 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +60 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/name-generator.d.ts +20 -0
- package/dist/utils/name-generator.d.ts.map +1 -0
- package/dist/utils/name-generator.js +183 -0
- package/dist/utils/name-generator.js.map +1 -0
- package/dist/utils/paths.d.ts +132 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +412 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/status-line.d.ts +14 -0
- package/dist/utils/status-line.d.ts.map +1 -0
- package/dist/utils/status-line.js +36 -0
- package/dist/utils/status-line.js.map +1 -0
- package/dist/utils/terminal-symbols.d.ts +50 -0
- package/dist/utils/terminal-symbols.d.ts.map +1 -0
- package/dist/utils/terminal-symbols.js +97 -0
- package/dist/utils/terminal-symbols.js.map +1 -0
- package/dist/utils/timer.d.ts +17 -0
- package/dist/utils/timer.d.ts.map +1 -0
- package/dist/utils/timer.js +56 -0
- package/dist/utils/timer.js.map +1 -0
- package/dist/utils/validation.d.ts +17 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +106 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/utils/version.d.ts +2 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +12 -0
- package/dist/utils/version.js.map +1 -0
- package/jest.config.ts +30 -0
- package/package.json +55 -0
- package/src/commands/do.ts +829 -0
- package/src/commands/plan.ts +422 -0
- package/src/commands/status.ts +146 -0
- package/src/core/claude-runner.ts +374 -0
- package/src/core/editor.ts +85 -0
- package/src/core/failure-analyzer.ts +372 -0
- package/src/core/git.ts +166 -0
- package/src/core/project-manager.ts +243 -0
- package/src/core/retry-handler.ts +72 -0
- package/src/core/shutdown-handler.ts +93 -0
- package/src/core/state-derivation.ts +343 -0
- package/src/index.ts +20 -0
- package/src/parsers/output-parser.ts +164 -0
- package/src/prompts/amend.ts +194 -0
- package/src/prompts/execution.ts +223 -0
- package/src/prompts/planning.ts +175 -0
- package/src/types/config.ts +35 -0
- package/src/ui/name-picker-subprocess.ts +96 -0
- package/src/ui/name-picker.ts +198 -0
- package/src/ui/project-picker.ts +80 -0
- package/src/utils/config.ts +69 -0
- package/src/utils/logger.ts +81 -0
- package/src/utils/name-generator.ts +211 -0
- package/src/utils/paths.ts +497 -0
- package/src/utils/status-line.ts +45 -0
- package/src/utils/terminal-symbols.ts +124 -0
- package/src/utils/timer.ts +64 -0
- package/src/utils/validation.ts +132 -0
- package/src/utils/version.ts +12 -0
- package/tests/unit/claude-runner-interactive.test.ts +343 -0
- package/tests/unit/claude-runner.test.ts +629 -0
- package/tests/unit/command-output.test.ts +295 -0
- package/tests/unit/config.test.ts +72 -0
- package/tests/unit/dependency-integration.test.ts +559 -0
- package/tests/unit/do-blocked-tasks.test.ts +323 -0
- package/tests/unit/do-command.test.ts +198 -0
- package/tests/unit/do-multiproject.test.ts +270 -0
- package/tests/unit/do-rerun.test.ts +270 -0
- package/tests/unit/execution-prompt.test.ts +406 -0
- package/tests/unit/failure-analyzer.test.ts +276 -0
- package/tests/unit/failure-history.test.ts +143 -0
- package/tests/unit/git-stash.test.ts +138 -0
- package/tests/unit/git.test.ts +80 -0
- package/tests/unit/logger.test.ts +132 -0
- package/tests/unit/name-generator.test.ts +283 -0
- package/tests/unit/name-picker.test.ts +179 -0
- package/tests/unit/outcome-content.test.ts +166 -0
- package/tests/unit/output-parser.test.ts +178 -0
- package/tests/unit/paths.test.ts +741 -0
- package/tests/unit/plan-command-amend-flag.test.ts +115 -0
- package/tests/unit/plan-command-amend-input.test.ts +156 -0
- package/tests/unit/plan-command-auto-flag.test.ts +112 -0
- package/tests/unit/plan-command.test.ts +580 -0
- package/tests/unit/planning-prompt.test.ts +137 -0
- package/tests/unit/project-manager.test.ts +265 -0
- package/tests/unit/project-picker.test.ts +338 -0
- package/tests/unit/retry-handler.test.ts +89 -0
- package/tests/unit/state-derivation.test.ts +714 -0
- package/tests/unit/status-command.test.ts +271 -0
- package/tests/unit/status-line.test.ts +92 -0
- package/tests/unit/terminal-symbols.test.ts +214 -0
- package/tests/unit/timer.test.ts +102 -0
- package/tests/unit/validation.test.ts +118 -0
- package/tsconfig.json +26 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status line utility for displaying in-place updates during task execution.
|
|
3
|
+
* Uses carriage return to update the line without scrolling.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface StatusLine {
|
|
7
|
+
update: (text: string) => void;
|
|
8
|
+
clear: () => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Creates a status line that can be updated in-place.
|
|
13
|
+
* The status line is cleared before any new content is written.
|
|
14
|
+
*/
|
|
15
|
+
export function createStatusLine(): StatusLine {
|
|
16
|
+
let lastLength = 0;
|
|
17
|
+
let isActive = false;
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
update(text: string): void {
|
|
21
|
+
// Only write to TTY
|
|
22
|
+
if (!process.stdout.isTTY) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
isActive = true;
|
|
27
|
+
// Clear the previous line content and write new content
|
|
28
|
+
const clearStr = ' '.repeat(lastLength);
|
|
29
|
+
process.stdout.write(`\r${clearStr}\r${text}`);
|
|
30
|
+
lastLength = text.length;
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
clear(): void {
|
|
34
|
+
if (!process.stdout.isTTY || !isActive) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Clear the line and reset cursor
|
|
39
|
+
const clearStr = ' '.repeat(lastLength);
|
|
40
|
+
process.stdout.write(`\r${clearStr}\r`);
|
|
41
|
+
lastLength = 0;
|
|
42
|
+
isActive = false;
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal symbols and formatting helpers for beautiful terminal output.
|
|
3
|
+
* All functions are pure and testable - no side effects.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { formatElapsedTime } from './timer.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Visual symbols for terminal output using dots/symbols style.
|
|
10
|
+
*/
|
|
11
|
+
export const SYMBOLS = {
|
|
12
|
+
running: '●',
|
|
13
|
+
completed: '✓',
|
|
14
|
+
failed: '✗',
|
|
15
|
+
pending: '○',
|
|
16
|
+
blocked: '⊘',
|
|
17
|
+
project: '▶',
|
|
18
|
+
} as const;
|
|
19
|
+
|
|
20
|
+
export type TaskStatus = 'running' | 'completed' | 'failed' | 'pending' | 'blocked';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Truncates a string to the specified length, adding ellipsis if needed.
|
|
24
|
+
*/
|
|
25
|
+
function truncate(str: string, maxLength: number): string {
|
|
26
|
+
if (str.length <= maxLength) {
|
|
27
|
+
return str;
|
|
28
|
+
}
|
|
29
|
+
return str.slice(0, maxLength - 1) + '…';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Formats a single task progress line.
|
|
34
|
+
* @param current - Current task number (1-indexed)
|
|
35
|
+
* @param total - Total number of tasks
|
|
36
|
+
* @param status - Task status
|
|
37
|
+
* @param name - Task name
|
|
38
|
+
* @param elapsedMs - Optional elapsed time in milliseconds
|
|
39
|
+
* @returns Formatted string like "● auth-login 1:23" or "✓ auth-login 1/5"
|
|
40
|
+
*/
|
|
41
|
+
export function formatTaskProgress(
|
|
42
|
+
current: number,
|
|
43
|
+
total: number,
|
|
44
|
+
status: TaskStatus,
|
|
45
|
+
name: string,
|
|
46
|
+
elapsedMs?: number
|
|
47
|
+
): string {
|
|
48
|
+
const symbol = SYMBOLS[status];
|
|
49
|
+
const displayName = truncate(name || 'task', 40);
|
|
50
|
+
|
|
51
|
+
// Show elapsed time for running tasks, completed tasks, and failed tasks
|
|
52
|
+
if (elapsedMs !== undefined) {
|
|
53
|
+
const timeStr = formatElapsedTime(elapsedMs);
|
|
54
|
+
return `${symbol} ${displayName} ${timeStr}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return `${symbol} ${displayName} ${current}/${total}`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Formats a project header line.
|
|
62
|
+
* @param name - Project name
|
|
63
|
+
* @param taskCount - Number of tasks in the project
|
|
64
|
+
* @returns Formatted string like "▶ my-project (5 tasks)"
|
|
65
|
+
*/
|
|
66
|
+
export function formatProjectHeader(name: string, taskCount: number): string {
|
|
67
|
+
const displayName = truncate(name || 'project', 50);
|
|
68
|
+
const taskWord = taskCount === 1 ? 'task' : 'tasks';
|
|
69
|
+
return `${SYMBOLS.project} ${displayName} (${taskCount} ${taskWord})`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Formats a summary line showing completion status.
|
|
74
|
+
* @param completed - Number of completed tasks
|
|
75
|
+
* @param failed - Number of failed tasks
|
|
76
|
+
* @param pending - Number of pending tasks
|
|
77
|
+
* @param elapsedMs - Optional total elapsed time in milliseconds
|
|
78
|
+
* @param blocked - Number of blocked tasks (default 0)
|
|
79
|
+
* @returns Formatted string like "✓ 5/5 completed in 12:34" or "✗ 3/5 (2 failed, 1 blocked)"
|
|
80
|
+
*/
|
|
81
|
+
export function formatSummary(
|
|
82
|
+
completed: number,
|
|
83
|
+
failed: number,
|
|
84
|
+
pending: number,
|
|
85
|
+
elapsedMs?: number,
|
|
86
|
+
blocked: number = 0
|
|
87
|
+
): string {
|
|
88
|
+
const total = completed + failed + pending + blocked;
|
|
89
|
+
|
|
90
|
+
if (total === 0) {
|
|
91
|
+
return `${SYMBOLS.pending} no tasks`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const hasFailures = failed > 0;
|
|
95
|
+
const hasBlocked = blocked > 0;
|
|
96
|
+
const symbol = hasFailures || hasBlocked ? SYMBOLS.failed : SYMBOLS.completed;
|
|
97
|
+
|
|
98
|
+
if (hasFailures || hasBlocked) {
|
|
99
|
+
const parts: string[] = [];
|
|
100
|
+
if (hasFailures) {
|
|
101
|
+
parts.push(failed === 1 ? '1 failed' : `${failed} failed`);
|
|
102
|
+
}
|
|
103
|
+
if (hasBlocked) {
|
|
104
|
+
parts.push(blocked === 1 ? '1 blocked' : `${blocked} blocked`);
|
|
105
|
+
}
|
|
106
|
+
return `${symbol} ${completed}/${total} (${parts.join(', ')})`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const timeStr = elapsedMs !== undefined ? ` in ${formatElapsedTime(elapsedMs)}` : '';
|
|
110
|
+
return `${symbol} ${completed}/${total} completed${timeStr}`;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Formats a compact progress bar showing task status as a sequence of symbols.
|
|
115
|
+
* @param tasks - Array of task statuses
|
|
116
|
+
* @returns Formatted string like "✓✓●○○"
|
|
117
|
+
*/
|
|
118
|
+
export function formatProgressBar(tasks: TaskStatus[]): string {
|
|
119
|
+
if (tasks.length === 0) {
|
|
120
|
+
return '';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return tasks.map((status) => SYMBOLS[status]).join('');
|
|
124
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format elapsed time in human-readable format.
|
|
3
|
+
* - Under 1 minute: "Xs"
|
|
4
|
+
* - Under 1 hour: "Xm Ys"
|
|
5
|
+
* - 1 hour or more: "Xh Ym"
|
|
6
|
+
*/
|
|
7
|
+
export function formatElapsedTime(ms: number): string {
|
|
8
|
+
const totalSeconds = Math.floor(ms / 1000);
|
|
9
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
10
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
11
|
+
const seconds = totalSeconds % 60;
|
|
12
|
+
|
|
13
|
+
if (hours > 0) {
|
|
14
|
+
return `${hours}h ${minutes}m`;
|
|
15
|
+
} else if (minutes > 0) {
|
|
16
|
+
return `${minutes}m ${seconds}s`;
|
|
17
|
+
} else {
|
|
18
|
+
return `${seconds}s`;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface TaskTimer {
|
|
23
|
+
start: () => void;
|
|
24
|
+
stop: () => number;
|
|
25
|
+
getElapsed: () => number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Creates a task timer that tracks elapsed time and can display a status line.
|
|
30
|
+
*/
|
|
31
|
+
export function createTaskTimer(onTick?: (elapsed: number) => void): TaskTimer {
|
|
32
|
+
let startTime: number | null = null;
|
|
33
|
+
let intervalId: ReturnType<typeof setInterval> | null = null;
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
start(): void {
|
|
37
|
+
startTime = Date.now();
|
|
38
|
+
if (onTick) {
|
|
39
|
+
// Immediately show initial state
|
|
40
|
+
onTick(0);
|
|
41
|
+
// Then update every second
|
|
42
|
+
intervalId = setInterval(() => {
|
|
43
|
+
if (startTime !== null) {
|
|
44
|
+
onTick(Date.now() - startTime);
|
|
45
|
+
}
|
|
46
|
+
}, 1000);
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
stop(): number {
|
|
51
|
+
if (intervalId !== null) {
|
|
52
|
+
clearInterval(intervalId);
|
|
53
|
+
intervalId = null;
|
|
54
|
+
}
|
|
55
|
+
const elapsed = startTime !== null ? Date.now() - startTime : 0;
|
|
56
|
+
startTime = null;
|
|
57
|
+
return elapsed;
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
getElapsed(): number {
|
|
61
|
+
return startTime !== null ? Date.now() - startTime : 0;
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { execSync } from 'node:child_process';
|
|
4
|
+
import { logger } from './logger.js';
|
|
5
|
+
|
|
6
|
+
export interface ValidationResult {
|
|
7
|
+
valid: boolean;
|
|
8
|
+
warnings: string[];
|
|
9
|
+
errors: string[];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function validateEnvironment(): ValidationResult {
|
|
13
|
+
const result: ValidationResult = {
|
|
14
|
+
valid: true,
|
|
15
|
+
warnings: [],
|
|
16
|
+
errors: [],
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Check Claude CLI is installed
|
|
20
|
+
try {
|
|
21
|
+
execSync('which claude', { encoding: 'utf-8', stdio: 'pipe' });
|
|
22
|
+
} catch {
|
|
23
|
+
result.valid = false;
|
|
24
|
+
result.errors.push('Claude CLI not found. Please install it first.');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Check for git repo (warning only)
|
|
28
|
+
try {
|
|
29
|
+
execSync('git rev-parse --is-inside-work-tree', { encoding: 'utf-8', stdio: 'pipe' });
|
|
30
|
+
} catch {
|
|
31
|
+
result.warnings.push('Not in a git repository. Auto-commit will be disabled.');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Check for CLAUDE.md (warning only)
|
|
35
|
+
if (!fs.existsSync('CLAUDE.md')) {
|
|
36
|
+
result.warnings.push('No CLAUDE.md found in current directory.');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function validateProjectName(name: string): boolean {
|
|
43
|
+
// Allow alphanumeric, hyphens, underscores
|
|
44
|
+
const validPattern = /^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;
|
|
45
|
+
return validPattern.test(name) && name.length <= 50;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function sanitizeProjectName(name: string): string {
|
|
49
|
+
return name
|
|
50
|
+
.toLowerCase()
|
|
51
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
52
|
+
.replace(/^-+|-+$/g, '')
|
|
53
|
+
.substring(0, 50);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function validateProjectExists(rafDir: string, projectName: string): string | null {
|
|
57
|
+
const entries = fs.readdirSync(rafDir, { withFileTypes: true });
|
|
58
|
+
|
|
59
|
+
for (const entry of entries) {
|
|
60
|
+
if (entry.isDirectory()) {
|
|
61
|
+
// Match numeric pattern like "001-project-name" (or legacy 01-project-name)
|
|
62
|
+
const numericMatch = entry.name.match(/^\d{2,3}-(.+)$/);
|
|
63
|
+
if (numericMatch && numericMatch[1] === projectName) {
|
|
64
|
+
return path.join(rafDir, entry.name);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Match base36 pattern like "a00-project-name"
|
|
68
|
+
const base36Match = entry.name.match(/^[a-z][0-9a-z]{2}-(.+)$/i);
|
|
69
|
+
if (base36Match && base36Match[1] === projectName) {
|
|
70
|
+
return path.join(rafDir, entry.name);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function validatePlansExist(projectPath: string): boolean {
|
|
79
|
+
const plansDir = path.join(projectPath, 'plans');
|
|
80
|
+
if (!fs.existsSync(plansDir)) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const plans = fs.readdirSync(plansDir).filter(f => f.endsWith('.md'));
|
|
85
|
+
return plans.length > 0;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function reportValidation(result: ValidationResult): void {
|
|
89
|
+
for (const warning of result.warnings) {
|
|
90
|
+
logger.warn(warning);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
for (const error of result.errors) {
|
|
94
|
+
logger.error(error);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const VALID_MODELS = ['sonnet', 'haiku', 'opus'] as const;
|
|
99
|
+
|
|
100
|
+
export type ValidModelName = (typeof VALID_MODELS)[number];
|
|
101
|
+
|
|
102
|
+
export function validateModelName(model: string): ValidModelName | null {
|
|
103
|
+
const normalized = model.toLowerCase();
|
|
104
|
+
if (VALID_MODELS.includes(normalized as ValidModelName)) {
|
|
105
|
+
return normalized as ValidModelName;
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function resolveModelOption(model?: string, sonnet?: boolean): ValidModelName {
|
|
111
|
+
// Check for conflicting flags
|
|
112
|
+
if (model && sonnet) {
|
|
113
|
+
throw new Error('Cannot specify both --model and --sonnet flags');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// --sonnet shorthand
|
|
117
|
+
if (sonnet) {
|
|
118
|
+
return 'sonnet';
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// --model flag
|
|
122
|
+
if (model) {
|
|
123
|
+
const validated = validateModelName(model);
|
|
124
|
+
if (!validated) {
|
|
125
|
+
throw new Error(`Invalid model name: "${model}". Valid options: ${VALID_MODELS.join(', ')}`);
|
|
126
|
+
}
|
|
127
|
+
return validated;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Default to opus
|
|
131
|
+
return 'opus';
|
|
132
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { dirname, join } from 'path';
|
|
4
|
+
|
|
5
|
+
export function getVersion(): string {
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
// From dist/utils/version.js to package.json is ../../package.json
|
|
9
|
+
const packagePath = join(__dirname, '..', '..', 'package.json');
|
|
10
|
+
const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));
|
|
11
|
+
return packageJson.version;
|
|
12
|
+
}
|