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,412 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
export const RAF_DIR = 'RAF';
|
|
4
|
+
// Base36 constants
|
|
5
|
+
const BASE36_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz';
|
|
6
|
+
const BASE36_START = 1000; // First base36 project number
|
|
7
|
+
const MAX_NUMERIC = 999; // Last numeric project number
|
|
8
|
+
/**
|
|
9
|
+
* Encode a project number >= 1000 to a 3-character base36 string.
|
|
10
|
+
* The encoding offsets by 1000, so:
|
|
11
|
+
* - 1000 -> 'a00'
|
|
12
|
+
* - 1001 -> 'a01'
|
|
13
|
+
* - 1035 -> 'a0z'
|
|
14
|
+
* - 1036 -> 'a10'
|
|
15
|
+
* - etc.
|
|
16
|
+
*
|
|
17
|
+
* First character uses a-z (10-35 in base36, letters only).
|
|
18
|
+
* Second and third characters use 0-9a-z (0-35 in base36).
|
|
19
|
+
*/
|
|
20
|
+
export function encodeBase36(num) {
|
|
21
|
+
if (num < BASE36_START) {
|
|
22
|
+
throw new Error(`encodeBase36 only accepts numbers >= ${BASE36_START}, got ${num}`);
|
|
23
|
+
}
|
|
24
|
+
// Offset to get the base36 representation starting at 'a00' for 1000
|
|
25
|
+
const offset = num - BASE36_START;
|
|
26
|
+
// First character: 'a' + (offset / 36^2), uses only letters a-z
|
|
27
|
+
// This gives us 26 possible first characters (a-z)
|
|
28
|
+
const firstCharIndex = Math.floor(offset / (36 * 36));
|
|
29
|
+
if (firstCharIndex >= 26) {
|
|
30
|
+
throw new Error(`Project number ${num} exceeds maximum base36 capacity (max: ${BASE36_START + 26 * 36 * 36 - 1})`);
|
|
31
|
+
}
|
|
32
|
+
const firstChar = BASE36_CHARS[10 + firstCharIndex]; // Start from 'a' (index 10)
|
|
33
|
+
// Second and third characters: remaining value in base36
|
|
34
|
+
const remainder = offset % (36 * 36);
|
|
35
|
+
const secondCharIndex = Math.floor(remainder / 36);
|
|
36
|
+
const thirdCharIndex = remainder % 36;
|
|
37
|
+
const secondChar = BASE36_CHARS[secondCharIndex];
|
|
38
|
+
const thirdChar = BASE36_CHARS[thirdCharIndex];
|
|
39
|
+
return `${firstChar}${secondChar}${thirdChar}`;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Decode a 3-character base36 string to a project number.
|
|
43
|
+
* Returns the decoded number >= 1000, or null if invalid format.
|
|
44
|
+
*/
|
|
45
|
+
export function decodeBase36(str) {
|
|
46
|
+
if (str.length !== 3) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const lower = str.toLowerCase();
|
|
50
|
+
const firstChar = lower.charAt(0);
|
|
51
|
+
const secondChar = lower.charAt(1);
|
|
52
|
+
const thirdChar = lower.charAt(2);
|
|
53
|
+
// First character must be a letter (a-z)
|
|
54
|
+
const firstIndex = BASE36_CHARS.indexOf(firstChar);
|
|
55
|
+
if (firstIndex < 10 || firstIndex > 35) {
|
|
56
|
+
return null; // Not a letter
|
|
57
|
+
}
|
|
58
|
+
// Second and third characters can be 0-9 or a-z
|
|
59
|
+
const secondIndex = BASE36_CHARS.indexOf(secondChar);
|
|
60
|
+
const thirdIndex = BASE36_CHARS.indexOf(thirdChar);
|
|
61
|
+
if (secondIndex === -1 || thirdIndex === -1) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
// Calculate the offset from 1000
|
|
65
|
+
const letterOffset = firstIndex - 10; // 'a' = 0, 'b' = 1, etc.
|
|
66
|
+
const offset = letterOffset * 36 * 36 + secondIndex * 36 + thirdIndex;
|
|
67
|
+
return BASE36_START + offset;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Check if a string is a valid base36 project prefix.
|
|
71
|
+
* Valid format: starts with a-z, followed by two base36 chars (0-9, a-z).
|
|
72
|
+
*/
|
|
73
|
+
export function isBase36Prefix(str) {
|
|
74
|
+
if (str.length !== 3) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
return /^[a-z][0-9a-z]{2}$/.test(str.toLowerCase());
|
|
78
|
+
}
|
|
79
|
+
export function getRafDir() {
|
|
80
|
+
return path.resolve(process.cwd(), RAF_DIR);
|
|
81
|
+
}
|
|
82
|
+
export function ensureRafDir() {
|
|
83
|
+
const rafDir = getRafDir();
|
|
84
|
+
if (!fs.existsSync(rafDir)) {
|
|
85
|
+
fs.mkdirSync(rafDir, { recursive: true });
|
|
86
|
+
}
|
|
87
|
+
return rafDir;
|
|
88
|
+
}
|
|
89
|
+
export function getNextProjectNumber(rafDir) {
|
|
90
|
+
if (!fs.existsSync(rafDir)) {
|
|
91
|
+
return 1;
|
|
92
|
+
}
|
|
93
|
+
const entries = fs.readdirSync(rafDir, { withFileTypes: true });
|
|
94
|
+
const numbers = [];
|
|
95
|
+
for (const entry of entries) {
|
|
96
|
+
if (entry.isDirectory()) {
|
|
97
|
+
// Try numeric format first (2-3 digits)
|
|
98
|
+
const numericMatch = entry.name.match(/^(\d{2,3})-/);
|
|
99
|
+
if (numericMatch && numericMatch[1]) {
|
|
100
|
+
numbers.push(parseInt(numericMatch[1], 10));
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
// Try base36 format
|
|
104
|
+
const base36Match = entry.name.match(/^([a-z][0-9a-z]{2})-/i);
|
|
105
|
+
if (base36Match && base36Match[1]) {
|
|
106
|
+
const decoded = decodeBase36(base36Match[1].toLowerCase());
|
|
107
|
+
if (decoded !== null) {
|
|
108
|
+
numbers.push(decoded);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (numbers.length === 0) {
|
|
114
|
+
return 1;
|
|
115
|
+
}
|
|
116
|
+
return Math.max(...numbers) + 1;
|
|
117
|
+
}
|
|
118
|
+
export function formatProjectNumber(num) {
|
|
119
|
+
if (num <= MAX_NUMERIC) {
|
|
120
|
+
return num.toString().padStart(3, '0');
|
|
121
|
+
}
|
|
122
|
+
return encodeBase36(num);
|
|
123
|
+
}
|
|
124
|
+
export function getProjectDir(rafDir, projectName) {
|
|
125
|
+
if (!fs.existsSync(rafDir)) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
const entries = fs.readdirSync(rafDir, { withFileTypes: true });
|
|
129
|
+
for (const entry of entries) {
|
|
130
|
+
if (entry.isDirectory()) {
|
|
131
|
+
// Try numeric format first
|
|
132
|
+
const numericMatch = entry.name.match(/^\d{2,3}-(.+)$/);
|
|
133
|
+
if (numericMatch && numericMatch[1] === projectName) {
|
|
134
|
+
return path.join(rafDir, entry.name);
|
|
135
|
+
}
|
|
136
|
+
// Try base36 format
|
|
137
|
+
const base36Match = entry.name.match(/^[a-z][0-9a-z]{2}-(.+)$/i);
|
|
138
|
+
if (base36Match && base36Match[1] === projectName) {
|
|
139
|
+
return path.join(rafDir, entry.name);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Extract project number prefix from a project path.
|
|
147
|
+
* Supports both numeric (001-999) and base36 (a00-zzz) formats.
|
|
148
|
+
* E.g., "/Users/foo/RAF/001-my-project" -> "001"
|
|
149
|
+
* E.g., "/Users/foo/RAF/a00-my-project" -> "a00"
|
|
150
|
+
* Returns the prefix string (e.g., "001" or "a00") or null if not found.
|
|
151
|
+
*/
|
|
152
|
+
export function extractProjectNumber(projectPath) {
|
|
153
|
+
const folderName = path.basename(projectPath);
|
|
154
|
+
// Try numeric format first (2-3 digits)
|
|
155
|
+
const numericMatch = folderName.match(/^(\d{2,3})-/);
|
|
156
|
+
if (numericMatch && numericMatch[1]) {
|
|
157
|
+
return numericMatch[1];
|
|
158
|
+
}
|
|
159
|
+
// Try base36 format (letter followed by two alphanumeric chars)
|
|
160
|
+
const base36Match = folderName.match(/^([a-z][0-9a-z]{2})-/i);
|
|
161
|
+
if (base36Match && base36Match[1]) {
|
|
162
|
+
return base36Match[1].toLowerCase();
|
|
163
|
+
}
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Parse a project prefix string to its numeric value.
|
|
168
|
+
* Handles both numeric (001-999) and base36 (a00-zzz) formats.
|
|
169
|
+
* Returns the numeric project number or null if invalid.
|
|
170
|
+
*/
|
|
171
|
+
export function parseProjectPrefix(prefix) {
|
|
172
|
+
// Try numeric first
|
|
173
|
+
if (/^\d{2,3}$/.test(prefix)) {
|
|
174
|
+
return parseInt(prefix, 10);
|
|
175
|
+
}
|
|
176
|
+
// Try base36
|
|
177
|
+
if (isBase36Prefix(prefix)) {
|
|
178
|
+
return decodeBase36(prefix);
|
|
179
|
+
}
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Extract project name from a project path (without number prefix).
|
|
184
|
+
* Supports both numeric (001-999) and base36 (a00-zzz) formats.
|
|
185
|
+
* E.g., "/Users/foo/RAF/001-my-project" -> "my-project"
|
|
186
|
+
* E.g., "/Users/foo/RAF/a00-my-project" -> "my-project"
|
|
187
|
+
* Returns the project name or null if not found.
|
|
188
|
+
*/
|
|
189
|
+
export function extractProjectName(projectPath) {
|
|
190
|
+
const folderName = path.basename(projectPath);
|
|
191
|
+
// Try numeric format first
|
|
192
|
+
const numericMatch = folderName.match(/^\d{2,3}-(.+)$/);
|
|
193
|
+
if (numericMatch && numericMatch[1]) {
|
|
194
|
+
return numericMatch[1];
|
|
195
|
+
}
|
|
196
|
+
// Try base36 format
|
|
197
|
+
const base36Match = folderName.match(/^[a-z][0-9a-z]{2}-(.+)$/i);
|
|
198
|
+
if (base36Match && base36Match[1]) {
|
|
199
|
+
return base36Match[1];
|
|
200
|
+
}
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Extract task name from a plan filename (without number prefix and extension).
|
|
205
|
+
* E.g., "002-fix-login-bug.md" -> "fix-login-bug"
|
|
206
|
+
* Returns the task name or null if not found.
|
|
207
|
+
*/
|
|
208
|
+
export function extractTaskNameFromPlanFile(planFilename) {
|
|
209
|
+
const basename = path.basename(planFilename, '.md');
|
|
210
|
+
const match = basename.match(/^\d{2,3}-(.+)$/);
|
|
211
|
+
return match && match[1] ? match[1] : null;
|
|
212
|
+
}
|
|
213
|
+
export function listProjects(rafDir) {
|
|
214
|
+
if (!fs.existsSync(rafDir)) {
|
|
215
|
+
return [];
|
|
216
|
+
}
|
|
217
|
+
const entries = fs.readdirSync(rafDir, { withFileTypes: true });
|
|
218
|
+
const projects = [];
|
|
219
|
+
for (const entry of entries) {
|
|
220
|
+
if (entry.isDirectory()) {
|
|
221
|
+
// Try numeric format first
|
|
222
|
+
const numericMatch = entry.name.match(/^(\d{2,3})-(.+)$/);
|
|
223
|
+
if (numericMatch && numericMatch[1] && numericMatch[2]) {
|
|
224
|
+
projects.push({
|
|
225
|
+
number: parseInt(numericMatch[1], 10),
|
|
226
|
+
name: numericMatch[2],
|
|
227
|
+
path: path.join(rafDir, entry.name),
|
|
228
|
+
});
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
// Try base36 format
|
|
232
|
+
const base36Match = entry.name.match(/^([a-z][0-9a-z]{2})-(.+)$/i);
|
|
233
|
+
if (base36Match && base36Match[1] && base36Match[2]) {
|
|
234
|
+
const decoded = decodeBase36(base36Match[1].toLowerCase());
|
|
235
|
+
if (decoded !== null) {
|
|
236
|
+
projects.push({
|
|
237
|
+
number: decoded,
|
|
238
|
+
name: base36Match[2],
|
|
239
|
+
path: path.join(rafDir, entry.name),
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return projects.sort((a, b) => a.number - b.number);
|
|
246
|
+
}
|
|
247
|
+
export function getPlansDir(projectPath) {
|
|
248
|
+
return path.join(projectPath, 'plans');
|
|
249
|
+
}
|
|
250
|
+
export function getOutcomesDir(projectPath) {
|
|
251
|
+
return path.join(projectPath, 'outcomes');
|
|
252
|
+
}
|
|
253
|
+
export function getOutcomeFilePath(projectPath, taskId, taskName) {
|
|
254
|
+
return path.join(projectPath, 'outcomes', `${taskId}-${taskName}.md`);
|
|
255
|
+
}
|
|
256
|
+
export function getDecisionsPath(projectPath) {
|
|
257
|
+
return path.join(projectPath, 'decisions.md');
|
|
258
|
+
}
|
|
259
|
+
export function getLogsDir(projectPath) {
|
|
260
|
+
return path.join(projectPath, 'logs');
|
|
261
|
+
}
|
|
262
|
+
export function getInputPath(projectPath) {
|
|
263
|
+
return path.join(projectPath, 'input.md');
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Parse project information from a folder name.
|
|
267
|
+
* Returns null if the folder name doesn't match expected project format.
|
|
268
|
+
*/
|
|
269
|
+
function parseProjectFolder(rafDir, folderName) {
|
|
270
|
+
// Try numeric format first
|
|
271
|
+
const numericMatch = folderName.match(/^(\d{2,3})-(.+)$/);
|
|
272
|
+
if (numericMatch && numericMatch[1] && numericMatch[2]) {
|
|
273
|
+
return {
|
|
274
|
+
number: parseInt(numericMatch[1], 10),
|
|
275
|
+
name: numericMatch[2],
|
|
276
|
+
path: path.join(rafDir, folderName),
|
|
277
|
+
folder: folderName,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
// Try base36 format
|
|
281
|
+
const base36Match = folderName.match(/^([a-z][0-9a-z]{2})-(.+)$/i);
|
|
282
|
+
if (base36Match && base36Match[1] && base36Match[2]) {
|
|
283
|
+
const decoded = decodeBase36(base36Match[1].toLowerCase());
|
|
284
|
+
if (decoded !== null) {
|
|
285
|
+
return {
|
|
286
|
+
number: decoded,
|
|
287
|
+
name: base36Match[2],
|
|
288
|
+
path: path.join(rafDir, folderName),
|
|
289
|
+
folder: folderName,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Resolve a project identifier with detailed result including ambiguity detection.
|
|
297
|
+
*
|
|
298
|
+
* Supported identifier formats (checked in this order):
|
|
299
|
+
* 1. Full folder name (e.g., "001-fix-stuff", "a01-important-project")
|
|
300
|
+
* - Must be an exact match to an existing folder
|
|
301
|
+
* - Pattern: numeric prefix (2-3 digits) or base36 prefix, followed by hyphen and name
|
|
302
|
+
* 2. Numeric ID (e.g., "003", "3", "1000")
|
|
303
|
+
* - Looks up by project number
|
|
304
|
+
* 3. Base36 prefix (e.g., "a00", "a01")
|
|
305
|
+
* - Looks up by base36 project number (for projects >= 1000)
|
|
306
|
+
* 4. Project name (e.g., "my-project", "fix-stuff")
|
|
307
|
+
* - Looks up by the name portion of the folder (after the prefix)
|
|
308
|
+
* - Case-insensitive matching
|
|
309
|
+
* - Returns error if multiple projects have the same name
|
|
310
|
+
*
|
|
311
|
+
* @param rafDir - The RAF directory containing project folders
|
|
312
|
+
* @param identifier - The identifier to resolve
|
|
313
|
+
* @returns Resolution result with path, error type, and matches for ambiguous cases
|
|
314
|
+
*/
|
|
315
|
+
export function resolveProjectIdentifierWithDetails(rafDir, identifier) {
|
|
316
|
+
if (!fs.existsSync(rafDir)) {
|
|
317
|
+
return { path: null, error: 'not_found' };
|
|
318
|
+
}
|
|
319
|
+
// Pattern to match full folder names: NNN-name or XXX-name (base36)
|
|
320
|
+
// Supports 2-3 digit numeric prefixes or 3-char base36 prefixes
|
|
321
|
+
const fullFolderPattern = /^(\d{2,3}|[a-z][0-9a-z]{2})-(.+)$/i;
|
|
322
|
+
const fullFolderMatch = identifier.match(fullFolderPattern);
|
|
323
|
+
// Check if identifier is a full folder name (exact match required)
|
|
324
|
+
if (fullFolderMatch) {
|
|
325
|
+
// Check for exact case-insensitive match by listing directory
|
|
326
|
+
const entries = fs.readdirSync(rafDir, { withFileTypes: true });
|
|
327
|
+
for (const entry of entries) {
|
|
328
|
+
if (entry.isDirectory() && entry.name.toLowerCase() === identifier.toLowerCase()) {
|
|
329
|
+
return { path: path.join(rafDir, entry.name) };
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
// Full folder name format but doesn't exist as a folder.
|
|
333
|
+
// Fall through to name-based matching - the entire identifier might be a project name
|
|
334
|
+
// (e.g., "fix-double-summary-headers" looks like "fix-xxx" but is actually a name).
|
|
335
|
+
}
|
|
336
|
+
// Check if it's a numeric identifier (e.g., "003", "3", "1000")
|
|
337
|
+
const isNumeric = /^\d+$/.test(identifier);
|
|
338
|
+
// Check if it's a base36 identifier (e.g., "a00", "a01")
|
|
339
|
+
const isBase36 = isBase36Prefix(identifier);
|
|
340
|
+
// Convert base36 to numeric for matching
|
|
341
|
+
let targetNumber = null;
|
|
342
|
+
if (isNumeric) {
|
|
343
|
+
targetNumber = parseInt(identifier, 10);
|
|
344
|
+
}
|
|
345
|
+
else if (isBase36) {
|
|
346
|
+
targetNumber = decodeBase36(identifier);
|
|
347
|
+
}
|
|
348
|
+
const entries = fs.readdirSync(rafDir, { withFileTypes: true });
|
|
349
|
+
const nameMatches = [];
|
|
350
|
+
for (const entry of entries) {
|
|
351
|
+
if (entry.isDirectory()) {
|
|
352
|
+
const project = parseProjectFolder(rafDir, entry.name);
|
|
353
|
+
if (project) {
|
|
354
|
+
if (targetNumber !== null) {
|
|
355
|
+
// Match by number (either numeric or base36 identifier)
|
|
356
|
+
if (project.number === targetNumber) {
|
|
357
|
+
return { path: project.path };
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
// Match by name (case-insensitive)
|
|
362
|
+
if (project.name.toLowerCase() === identifier.toLowerCase()) {
|
|
363
|
+
nameMatches.push(project);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
// Handle name matches
|
|
370
|
+
if (nameMatches.length === 1) {
|
|
371
|
+
return { path: nameMatches[0].path };
|
|
372
|
+
}
|
|
373
|
+
else if (nameMatches.length > 1) {
|
|
374
|
+
// Multiple projects with the same name - ambiguous
|
|
375
|
+
return {
|
|
376
|
+
path: null,
|
|
377
|
+
error: 'ambiguous',
|
|
378
|
+
matches: nameMatches.sort((a, b) => a.number - b.number),
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
return { path: null, error: 'not_found' };
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Resolve a project identifier to a full project path.
|
|
385
|
+
*
|
|
386
|
+
* Supported identifier formats (checked in this order):
|
|
387
|
+
* 1. Full folder name (e.g., "001-fix-stuff", "a01-important-project")
|
|
388
|
+
* - Must be an exact match to an existing folder
|
|
389
|
+
* - Pattern: numeric prefix (2-3 digits) or base36 prefix, followed by hyphen and name
|
|
390
|
+
* 2. Numeric ID (e.g., "003", "3", "1000")
|
|
391
|
+
* - Looks up by project number
|
|
392
|
+
* 3. Base36 prefix (e.g., "a00", "a01")
|
|
393
|
+
* - Looks up by base36 project number (for projects >= 1000)
|
|
394
|
+
* 4. Project name (e.g., "my-project", "fix-stuff")
|
|
395
|
+
* - Looks up by the name portion of the folder (after the prefix)
|
|
396
|
+
* - Case-insensitive matching
|
|
397
|
+
*
|
|
398
|
+
* Note: For ambiguity detection (multiple projects with same name), use
|
|
399
|
+
* resolveProjectIdentifierWithDetails instead.
|
|
400
|
+
*
|
|
401
|
+
* This function is designed to be extensible for future task-level references
|
|
402
|
+
* like "001-project/002-task".
|
|
403
|
+
*
|
|
404
|
+
* @param rafDir - The RAF directory containing project folders
|
|
405
|
+
* @param identifier - The identifier to resolve
|
|
406
|
+
* @returns The full project path or null if not found (or ambiguous)
|
|
407
|
+
*/
|
|
408
|
+
export function resolveProjectIdentifier(rafDir, identifier) {
|
|
409
|
+
const result = resolveProjectIdentifierWithDetails(rafDir, identifier);
|
|
410
|
+
return result.path;
|
|
411
|
+
}
|
|
412
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
export interface StatusLine {
|
|
6
|
+
update: (text: string) => void;
|
|
7
|
+
clear: () => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Creates a status line that can be updated in-place.
|
|
11
|
+
* The status line is cleared before any new content is written.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createStatusLine(): StatusLine;
|
|
14
|
+
//# sourceMappingURL=status-line.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-line.d.ts","sourceRoot":"","sources":["../../src/utils/status-line.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,UAAU,CA8B7C"}
|
|
@@ -0,0 +1,36 @@
|
|
|
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
|
+
* Creates a status line that can be updated in-place.
|
|
7
|
+
* The status line is cleared before any new content is written.
|
|
8
|
+
*/
|
|
9
|
+
export function createStatusLine() {
|
|
10
|
+
let lastLength = 0;
|
|
11
|
+
let isActive = false;
|
|
12
|
+
return {
|
|
13
|
+
update(text) {
|
|
14
|
+
// Only write to TTY
|
|
15
|
+
if (!process.stdout.isTTY) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
isActive = true;
|
|
19
|
+
// Clear the previous line content and write new content
|
|
20
|
+
const clearStr = ' '.repeat(lastLength);
|
|
21
|
+
process.stdout.write(`\r${clearStr}\r${text}`);
|
|
22
|
+
lastLength = text.length;
|
|
23
|
+
},
|
|
24
|
+
clear() {
|
|
25
|
+
if (!process.stdout.isTTY || !isActive) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
// Clear the line and reset cursor
|
|
29
|
+
const clearStr = ' '.repeat(lastLength);
|
|
30
|
+
process.stdout.write(`\r${clearStr}\r`);
|
|
31
|
+
lastLength = 0;
|
|
32
|
+
isActive = false;
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=status-line.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-line.js","sourceRoot":"","sources":["../../src/utils/status-line.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,OAAO;QACL,MAAM,CAAC,IAAY;YACjB,oBAAoB;YACpB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;gBAC1B,OAAO;YACT,CAAC;YAED,QAAQ,GAAG,IAAI,CAAC;YAChB,wDAAwD;YACxD,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,QAAQ,KAAK,IAAI,EAAE,CAAC,CAAC;YAC/C,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,CAAC;QAED,KAAK;YACH,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACvC,OAAO;YACT,CAAC;YAED,kCAAkC;YAClC,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC;YACxC,UAAU,GAAG,CAAC,CAAC;YACf,QAAQ,GAAG,KAAK,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal symbols and formatting helpers for beautiful terminal output.
|
|
3
|
+
* All functions are pure and testable - no side effects.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Visual symbols for terminal output using dots/symbols style.
|
|
7
|
+
*/
|
|
8
|
+
export declare const SYMBOLS: {
|
|
9
|
+
readonly running: "●";
|
|
10
|
+
readonly completed: "✓";
|
|
11
|
+
readonly failed: "✗";
|
|
12
|
+
readonly pending: "○";
|
|
13
|
+
readonly blocked: "⊘";
|
|
14
|
+
readonly project: "▶";
|
|
15
|
+
};
|
|
16
|
+
export type TaskStatus = 'running' | 'completed' | 'failed' | 'pending' | 'blocked';
|
|
17
|
+
/**
|
|
18
|
+
* Formats a single task progress line.
|
|
19
|
+
* @param current - Current task number (1-indexed)
|
|
20
|
+
* @param total - Total number of tasks
|
|
21
|
+
* @param status - Task status
|
|
22
|
+
* @param name - Task name
|
|
23
|
+
* @param elapsedMs - Optional elapsed time in milliseconds
|
|
24
|
+
* @returns Formatted string like "● auth-login 1:23" or "✓ auth-login 1/5"
|
|
25
|
+
*/
|
|
26
|
+
export declare function formatTaskProgress(current: number, total: number, status: TaskStatus, name: string, elapsedMs?: number): string;
|
|
27
|
+
/**
|
|
28
|
+
* Formats a project header line.
|
|
29
|
+
* @param name - Project name
|
|
30
|
+
* @param taskCount - Number of tasks in the project
|
|
31
|
+
* @returns Formatted string like "▶ my-project (5 tasks)"
|
|
32
|
+
*/
|
|
33
|
+
export declare function formatProjectHeader(name: string, taskCount: number): string;
|
|
34
|
+
/**
|
|
35
|
+
* Formats a summary line showing completion status.
|
|
36
|
+
* @param completed - Number of completed tasks
|
|
37
|
+
* @param failed - Number of failed tasks
|
|
38
|
+
* @param pending - Number of pending tasks
|
|
39
|
+
* @param elapsedMs - Optional total elapsed time in milliseconds
|
|
40
|
+
* @param blocked - Number of blocked tasks (default 0)
|
|
41
|
+
* @returns Formatted string like "✓ 5/5 completed in 12:34" or "✗ 3/5 (2 failed, 1 blocked)"
|
|
42
|
+
*/
|
|
43
|
+
export declare function formatSummary(completed: number, failed: number, pending: number, elapsedMs?: number, blocked?: number): string;
|
|
44
|
+
/**
|
|
45
|
+
* Formats a compact progress bar showing task status as a sequence of symbols.
|
|
46
|
+
* @param tasks - Array of task statuses
|
|
47
|
+
* @returns Formatted string like "✓✓●○○"
|
|
48
|
+
*/
|
|
49
|
+
export declare function formatProgressBar(tasks: TaskStatus[]): string;
|
|
50
|
+
//# sourceMappingURL=terminal-symbols.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-symbols.d.ts","sourceRoot":"","sources":["../../src/utils/terminal-symbols.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;GAEG;AACH,eAAO,MAAM,OAAO;;;;;;;CAOV,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAYpF;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAWR;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAI3E;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,GAAE,MAAU,GAClB,MAAM,CAwBR;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,CAM7D"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal symbols and formatting helpers for beautiful terminal output.
|
|
3
|
+
* All functions are pure and testable - no side effects.
|
|
4
|
+
*/
|
|
5
|
+
import { formatElapsedTime } from './timer.js';
|
|
6
|
+
/**
|
|
7
|
+
* Visual symbols for terminal output using dots/symbols style.
|
|
8
|
+
*/
|
|
9
|
+
export const SYMBOLS = {
|
|
10
|
+
running: '●',
|
|
11
|
+
completed: '✓',
|
|
12
|
+
failed: '✗',
|
|
13
|
+
pending: '○',
|
|
14
|
+
blocked: '⊘',
|
|
15
|
+
project: '▶',
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Truncates a string to the specified length, adding ellipsis if needed.
|
|
19
|
+
*/
|
|
20
|
+
function truncate(str, maxLength) {
|
|
21
|
+
if (str.length <= maxLength) {
|
|
22
|
+
return str;
|
|
23
|
+
}
|
|
24
|
+
return str.slice(0, maxLength - 1) + '…';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Formats a single task progress line.
|
|
28
|
+
* @param current - Current task number (1-indexed)
|
|
29
|
+
* @param total - Total number of tasks
|
|
30
|
+
* @param status - Task status
|
|
31
|
+
* @param name - Task name
|
|
32
|
+
* @param elapsedMs - Optional elapsed time in milliseconds
|
|
33
|
+
* @returns Formatted string like "● auth-login 1:23" or "✓ auth-login 1/5"
|
|
34
|
+
*/
|
|
35
|
+
export function formatTaskProgress(current, total, status, name, elapsedMs) {
|
|
36
|
+
const symbol = SYMBOLS[status];
|
|
37
|
+
const displayName = truncate(name || 'task', 40);
|
|
38
|
+
// Show elapsed time for running tasks, completed tasks, and failed tasks
|
|
39
|
+
if (elapsedMs !== undefined) {
|
|
40
|
+
const timeStr = formatElapsedTime(elapsedMs);
|
|
41
|
+
return `${symbol} ${displayName} ${timeStr}`;
|
|
42
|
+
}
|
|
43
|
+
return `${symbol} ${displayName} ${current}/${total}`;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Formats a project header line.
|
|
47
|
+
* @param name - Project name
|
|
48
|
+
* @param taskCount - Number of tasks in the project
|
|
49
|
+
* @returns Formatted string like "▶ my-project (5 tasks)"
|
|
50
|
+
*/
|
|
51
|
+
export function formatProjectHeader(name, taskCount) {
|
|
52
|
+
const displayName = truncate(name || 'project', 50);
|
|
53
|
+
const taskWord = taskCount === 1 ? 'task' : 'tasks';
|
|
54
|
+
return `${SYMBOLS.project} ${displayName} (${taskCount} ${taskWord})`;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Formats a summary line showing completion status.
|
|
58
|
+
* @param completed - Number of completed tasks
|
|
59
|
+
* @param failed - Number of failed tasks
|
|
60
|
+
* @param pending - Number of pending tasks
|
|
61
|
+
* @param elapsedMs - Optional total elapsed time in milliseconds
|
|
62
|
+
* @param blocked - Number of blocked tasks (default 0)
|
|
63
|
+
* @returns Formatted string like "✓ 5/5 completed in 12:34" or "✗ 3/5 (2 failed, 1 blocked)"
|
|
64
|
+
*/
|
|
65
|
+
export function formatSummary(completed, failed, pending, elapsedMs, blocked = 0) {
|
|
66
|
+
const total = completed + failed + pending + blocked;
|
|
67
|
+
if (total === 0) {
|
|
68
|
+
return `${SYMBOLS.pending} no tasks`;
|
|
69
|
+
}
|
|
70
|
+
const hasFailures = failed > 0;
|
|
71
|
+
const hasBlocked = blocked > 0;
|
|
72
|
+
const symbol = hasFailures || hasBlocked ? SYMBOLS.failed : SYMBOLS.completed;
|
|
73
|
+
if (hasFailures || hasBlocked) {
|
|
74
|
+
const parts = [];
|
|
75
|
+
if (hasFailures) {
|
|
76
|
+
parts.push(failed === 1 ? '1 failed' : `${failed} failed`);
|
|
77
|
+
}
|
|
78
|
+
if (hasBlocked) {
|
|
79
|
+
parts.push(blocked === 1 ? '1 blocked' : `${blocked} blocked`);
|
|
80
|
+
}
|
|
81
|
+
return `${symbol} ${completed}/${total} (${parts.join(', ')})`;
|
|
82
|
+
}
|
|
83
|
+
const timeStr = elapsedMs !== undefined ? ` in ${formatElapsedTime(elapsedMs)}` : '';
|
|
84
|
+
return `${symbol} ${completed}/${total} completed${timeStr}`;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Formats a compact progress bar showing task status as a sequence of symbols.
|
|
88
|
+
* @param tasks - Array of task statuses
|
|
89
|
+
* @returns Formatted string like "✓✓●○○"
|
|
90
|
+
*/
|
|
91
|
+
export function formatProgressBar(tasks) {
|
|
92
|
+
if (tasks.length === 0) {
|
|
93
|
+
return '';
|
|
94
|
+
}
|
|
95
|
+
return tasks.map((status) => SYMBOLS[status]).join('');
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=terminal-symbols.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-symbols.js","sourceRoot":"","sources":["../../src/utils/terminal-symbols.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
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 declare function formatElapsedTime(ms: number): string;
|
|
8
|
+
export interface TaskTimer {
|
|
9
|
+
start: () => void;
|
|
10
|
+
stop: () => number;
|
|
11
|
+
getElapsed: () => number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Creates a task timer that tracks elapsed time and can display a status line.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createTaskTimer(onTick?: (elapsed: number) => void): TaskTimer;
|
|
17
|
+
//# sourceMappingURL=timer.d.ts.map
|