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,96 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Subprocess script for running the name picker.
|
|
4
|
+
* This isolates @inquirer/prompts from the main process to prevent
|
|
5
|
+
* stdin corruption that affects subsequent node-pty usage.
|
|
6
|
+
*
|
|
7
|
+
* Usage: node name-picker-subprocess.js <json-encoded-names-array> <output-file>
|
|
8
|
+
* Output: Selected name written to output file
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { select, input } from '@inquirer/prompts';
|
|
12
|
+
import * as fs from 'node:fs';
|
|
13
|
+
|
|
14
|
+
const OTHER_OPTION_VALUE = '__OTHER__';
|
|
15
|
+
|
|
16
|
+
async function main(): Promise<void> {
|
|
17
|
+
// Get names from command line argument
|
|
18
|
+
const namesJson = process.argv[2];
|
|
19
|
+
const outputFile = process.argv[3];
|
|
20
|
+
|
|
21
|
+
if (!namesJson || !outputFile) {
|
|
22
|
+
console.error('Usage: name-picker-subprocess <json-encoded-names-array> <output-file>');
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let names: string[];
|
|
27
|
+
try {
|
|
28
|
+
names = JSON.parse(namesJson);
|
|
29
|
+
} catch {
|
|
30
|
+
console.error('Invalid JSON input');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const result = await pickProjectName(names);
|
|
35
|
+
|
|
36
|
+
// Write result to output file
|
|
37
|
+
fs.writeFileSync(outputFile, result, 'utf-8');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function pickProjectName(names: string[]): Promise<string> {
|
|
41
|
+
if (names.length === 0) {
|
|
42
|
+
return promptForCustomName();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const choices = [
|
|
46
|
+
...names.map((name) => ({
|
|
47
|
+
name: name,
|
|
48
|
+
value: name,
|
|
49
|
+
})),
|
|
50
|
+
{
|
|
51
|
+
name: 'Other (enter custom name)',
|
|
52
|
+
value: OTHER_OPTION_VALUE,
|
|
53
|
+
},
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
const selected = await select({
|
|
57
|
+
message: 'Select a project name:',
|
|
58
|
+
choices,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (selected === OTHER_OPTION_VALUE) {
|
|
62
|
+
return promptForCustomName();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return selected;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function promptForCustomName(): Promise<string> {
|
|
69
|
+
const customName = await input({
|
|
70
|
+
message: 'Enter project name:',
|
|
71
|
+
validate: (value) => {
|
|
72
|
+
const trimmed = value.trim();
|
|
73
|
+
if (!trimmed) {
|
|
74
|
+
return 'Project name cannot be empty';
|
|
75
|
+
}
|
|
76
|
+
if (trimmed.length > 50) {
|
|
77
|
+
return 'Project name must be 50 characters or less';
|
|
78
|
+
}
|
|
79
|
+
if (!/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/.test(trimmed)) {
|
|
80
|
+
return 'Project name can only contain letters, numbers, hyphens, and underscores';
|
|
81
|
+
}
|
|
82
|
+
return true;
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return customName.trim().toLowerCase();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
main().catch((error) => {
|
|
90
|
+
// Check if user cancelled with Ctrl+C
|
|
91
|
+
if (error.message?.includes('User force closed') || error.name === 'ExitPromptError') {
|
|
92
|
+
process.exit(130); // Standard SIGINT exit code
|
|
93
|
+
}
|
|
94
|
+
console.error('Error:', error.message);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
});
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import * as fs from 'node:fs';
|
|
4
|
+
import * as os from 'node:os';
|
|
5
|
+
import * as pty from 'node-pty';
|
|
6
|
+
|
|
7
|
+
// For testing: allow direct import of @inquirer/prompts functions
|
|
8
|
+
let directSelect: typeof import('@inquirer/prompts').select | null = null;
|
|
9
|
+
let directInput: typeof import('@inquirer/prompts').input | null = null;
|
|
10
|
+
|
|
11
|
+
const OTHER_OPTION_VALUE = '__OTHER__';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Enable direct mode for testing (bypasses subprocess).
|
|
15
|
+
* This should only be called in test setup.
|
|
16
|
+
*/
|
|
17
|
+
export async function enableDirectMode(): Promise<void> {
|
|
18
|
+
const inquirer = await import('@inquirer/prompts');
|
|
19
|
+
directSelect = inquirer.select;
|
|
20
|
+
directInput = inquirer.input;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Disable direct mode (use subprocess).
|
|
25
|
+
*/
|
|
26
|
+
export function disableDirectMode(): void {
|
|
27
|
+
directSelect = null;
|
|
28
|
+
directInput = null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Display an interactive name picker with arrow-key navigation.
|
|
33
|
+
* Runs in a PTY subprocess to completely isolate @inquirer/prompts
|
|
34
|
+
* stdin manipulation from the main process.
|
|
35
|
+
*
|
|
36
|
+
* @param names - Array of generated name suggestions (3-5 names)
|
|
37
|
+
* @returns The selected or custom project name
|
|
38
|
+
*/
|
|
39
|
+
export async function pickProjectName(names: string[]): Promise<string> {
|
|
40
|
+
// Use direct mode if enabled (for testing)
|
|
41
|
+
if (directSelect) {
|
|
42
|
+
return pickProjectNameDirect(names);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Get path to the subprocess script
|
|
46
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
47
|
+
const currentDir = path.dirname(currentFile);
|
|
48
|
+
|
|
49
|
+
// Use the compiled js file
|
|
50
|
+
const subprocessScript = path.join(currentDir, 'name-picker-subprocess.js');
|
|
51
|
+
|
|
52
|
+
// Create temp file for result
|
|
53
|
+
const tempFile = path.join(os.tmpdir(), `raf-name-picker-${process.pid}.txt`);
|
|
54
|
+
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
// Spawn subprocess in its own PTY (completely isolates stdin)
|
|
57
|
+
const ptyProcess = pty.spawn('node', [subprocessScript, JSON.stringify(names), tempFile], {
|
|
58
|
+
name: 'xterm-256color',
|
|
59
|
+
cols: process.stdout.columns ?? 80,
|
|
60
|
+
rows: process.stdout.rows ?? 24,
|
|
61
|
+
cwd: process.cwd(),
|
|
62
|
+
env: process.env as Record<string, string>,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Set raw mode on our stdin to pass through keypresses
|
|
66
|
+
if (process.stdin.isTTY) {
|
|
67
|
+
process.stdin.setRawMode(true);
|
|
68
|
+
}
|
|
69
|
+
process.stdin.resume();
|
|
70
|
+
|
|
71
|
+
// Forward input from our stdin to the PTY
|
|
72
|
+
const onData = (data: Buffer): void => {
|
|
73
|
+
ptyProcess.write(data.toString());
|
|
74
|
+
};
|
|
75
|
+
process.stdin.on('data', onData);
|
|
76
|
+
|
|
77
|
+
// Forward output from PTY to our stdout
|
|
78
|
+
ptyProcess.onData((data) => {
|
|
79
|
+
process.stdout.write(data);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
ptyProcess.onExit(({ exitCode }) => {
|
|
83
|
+
// Cleanup stdin
|
|
84
|
+
process.stdin.off('data', onData);
|
|
85
|
+
if (process.stdin.isTTY) {
|
|
86
|
+
process.stdin.setRawMode(false);
|
|
87
|
+
}
|
|
88
|
+
process.stdin.pause();
|
|
89
|
+
|
|
90
|
+
if (exitCode === 130) {
|
|
91
|
+
// SIGINT - user cancelled
|
|
92
|
+
process.exit(130);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (exitCode !== 0) {
|
|
96
|
+
// Clean up temp file
|
|
97
|
+
try {
|
|
98
|
+
if (fs.existsSync(tempFile)) {
|
|
99
|
+
fs.unlinkSync(tempFile);
|
|
100
|
+
}
|
|
101
|
+
} catch {
|
|
102
|
+
// Ignore
|
|
103
|
+
}
|
|
104
|
+
reject(new Error(`Name picker subprocess failed with code ${exitCode}`));
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Read the result from temp file
|
|
109
|
+
try {
|
|
110
|
+
if (!fs.existsSync(tempFile)) {
|
|
111
|
+
reject(new Error('Name picker did not write a selection'));
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const selectedName = fs.readFileSync(tempFile, 'utf-8').trim();
|
|
116
|
+
|
|
117
|
+
// Clean up temp file
|
|
118
|
+
try {
|
|
119
|
+
fs.unlinkSync(tempFile);
|
|
120
|
+
} catch {
|
|
121
|
+
// Ignore
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (!selectedName) {
|
|
125
|
+
reject(new Error('Name picker returned empty selection'));
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
resolve(selectedName);
|
|
130
|
+
} catch (error) {
|
|
131
|
+
reject(error);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Direct implementation for testing (uses @inquirer/prompts in-process).
|
|
139
|
+
*/
|
|
140
|
+
async function pickProjectNameDirect(names: string[]): Promise<string> {
|
|
141
|
+
if (!directSelect || !directInput) {
|
|
142
|
+
throw new Error('Direct mode not enabled');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (names.length === 0) {
|
|
146
|
+
return promptForCustomNameDirect();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const choices = [
|
|
150
|
+
...names.map((name) => ({
|
|
151
|
+
name: name,
|
|
152
|
+
value: name,
|
|
153
|
+
})),
|
|
154
|
+
{
|
|
155
|
+
name: 'Other (enter custom name)',
|
|
156
|
+
value: OTHER_OPTION_VALUE,
|
|
157
|
+
},
|
|
158
|
+
];
|
|
159
|
+
|
|
160
|
+
const selected = await directSelect({
|
|
161
|
+
message: 'Select a project name:',
|
|
162
|
+
choices,
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
if (selected === OTHER_OPTION_VALUE) {
|
|
166
|
+
return promptForCustomNameDirect();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return selected;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Prompt user to enter a custom project name (direct mode).
|
|
174
|
+
*/
|
|
175
|
+
async function promptForCustomNameDirect(): Promise<string> {
|
|
176
|
+
if (!directInput) {
|
|
177
|
+
throw new Error('Direct mode not enabled');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const customName = await directInput({
|
|
181
|
+
message: 'Enter project name:',
|
|
182
|
+
validate: (value) => {
|
|
183
|
+
const trimmed = value.trim();
|
|
184
|
+
if (!trimmed) {
|
|
185
|
+
return 'Project name cannot be empty';
|
|
186
|
+
}
|
|
187
|
+
if (trimmed.length > 50) {
|
|
188
|
+
return 'Project name must be 50 characters or less';
|
|
189
|
+
}
|
|
190
|
+
if (!/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/.test(trimmed)) {
|
|
191
|
+
return 'Project name can only contain letters, numbers, hyphens, and underscores';
|
|
192
|
+
}
|
|
193
|
+
return true;
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
return customName.trim().toLowerCase();
|
|
198
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { select } from '@inquirer/prompts';
|
|
2
|
+
import { discoverProjects, deriveProjectState, getDerivedStats } from '../core/state-derivation.js';
|
|
3
|
+
import { extractProjectNumber, formatProjectNumber } from '../utils/paths.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Information about a pending project for display in the picker.
|
|
7
|
+
*/
|
|
8
|
+
export interface PendingProjectInfo {
|
|
9
|
+
folder: string;
|
|
10
|
+
number: number;
|
|
11
|
+
name: string;
|
|
12
|
+
path: string;
|
|
13
|
+
completedTasks: number;
|
|
14
|
+
totalTasks: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get all projects that have pending tasks (not fully completed).
|
|
19
|
+
* Returns projects sorted by number (oldest first).
|
|
20
|
+
*/
|
|
21
|
+
export function getPendingProjects(rafDir: string): PendingProjectInfo[] {
|
|
22
|
+
const allProjects = discoverProjects(rafDir);
|
|
23
|
+
const pendingProjects: PendingProjectInfo[] = [];
|
|
24
|
+
|
|
25
|
+
for (const project of allProjects) {
|
|
26
|
+
const state = deriveProjectState(project.path);
|
|
27
|
+
const stats = getDerivedStats(state);
|
|
28
|
+
|
|
29
|
+
// Include projects that are not fully completed (have pending or failed tasks)
|
|
30
|
+
if (stats.pending > 0 || stats.failed > 0) {
|
|
31
|
+
const projectNumber = extractProjectNumber(project.path);
|
|
32
|
+
const formattedNumber = projectNumber ?? formatProjectNumber(project.number);
|
|
33
|
+
|
|
34
|
+
pendingProjects.push({
|
|
35
|
+
folder: `${formattedNumber}-${project.name}`,
|
|
36
|
+
number: project.number,
|
|
37
|
+
name: project.name,
|
|
38
|
+
path: project.path,
|
|
39
|
+
completedTasks: stats.completed,
|
|
40
|
+
totalTasks: stats.total,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Sort by number (already sorted by discoverProjects, but ensure it)
|
|
46
|
+
return pendingProjects.sort((a, b) => a.number - b.number);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Format a project for display in the picker.
|
|
51
|
+
* Example: "001 fix-auth-bug (2/5 tasks)"
|
|
52
|
+
*/
|
|
53
|
+
export function formatProjectChoice(project: PendingProjectInfo): string {
|
|
54
|
+
const projectNumber = extractProjectNumber(project.path) ?? formatProjectNumber(project.number);
|
|
55
|
+
return `${projectNumber} ${project.name} (${project.completedTasks}/${project.totalTasks} tasks)`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Display an interactive project picker for pending projects.
|
|
60
|
+
* Returns the selected project folder name or null if no projects or cancelled.
|
|
61
|
+
*/
|
|
62
|
+
export async function pickPendingProject(rafDir: string): Promise<string | null> {
|
|
63
|
+
const pendingProjects = getPendingProjects(rafDir);
|
|
64
|
+
|
|
65
|
+
if (pendingProjects.length === 0) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const choices = pendingProjects.map((project) => ({
|
|
70
|
+
name: formatProjectChoice(project),
|
|
71
|
+
value: project.folder,
|
|
72
|
+
}));
|
|
73
|
+
|
|
74
|
+
const selected = await select({
|
|
75
|
+
message: 'Select a project to execute:',
|
|
76
|
+
choices,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return selected;
|
|
80
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import * as os from 'node:os';
|
|
4
|
+
import { RafConfig, DEFAULT_RAF_CONFIG } from '../types/config.js';
|
|
5
|
+
|
|
6
|
+
const CONFIG_FILENAME = 'raf.config.json';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get the path to Claude CLI settings file.
|
|
10
|
+
*/
|
|
11
|
+
export function getClaudeSettingsPath(): string {
|
|
12
|
+
return path.join(os.homedir(), '.claude', 'settings.json');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function loadConfig(rafDir: string): RafConfig {
|
|
16
|
+
const configPath = path.join(rafDir, CONFIG_FILENAME);
|
|
17
|
+
|
|
18
|
+
if (!fs.existsSync(configPath)) {
|
|
19
|
+
return { ...DEFAULT_RAF_CONFIG };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
24
|
+
const userConfig = JSON.parse(content) as Partial<RafConfig>;
|
|
25
|
+
return { ...DEFAULT_RAF_CONFIG, ...userConfig };
|
|
26
|
+
} catch {
|
|
27
|
+
return { ...DEFAULT_RAF_CONFIG };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function saveConfig(rafDir: string, config: RafConfig): void {
|
|
32
|
+
const configPath = path.join(rafDir, CONFIG_FILENAME);
|
|
33
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function getEditor(): string {
|
|
37
|
+
return process.env['EDITOR'] ?? process.env['VISUAL'] ?? 'vi';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get the Claude model name from Claude CLI settings.
|
|
42
|
+
* Returns the model name or null if not found.
|
|
43
|
+
* @param settingsPath Optional path to settings file (for testing)
|
|
44
|
+
*/
|
|
45
|
+
export function getClaudeModel(settingsPath?: string): string | null {
|
|
46
|
+
const filePath = settingsPath ?? getClaudeSettingsPath();
|
|
47
|
+
try {
|
|
48
|
+
if (!fs.existsSync(filePath)) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
52
|
+
const settings = JSON.parse(content) as { model?: string };
|
|
53
|
+
return settings.model ?? null;
|
|
54
|
+
} catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Get runtime configuration for task execution.
|
|
61
|
+
* Returns default values which can be overridden by command line options.
|
|
62
|
+
*/
|
|
63
|
+
export function getConfig(): { timeout: number; maxRetries: number; autoCommit: boolean } {
|
|
64
|
+
return {
|
|
65
|
+
timeout: DEFAULT_RAF_CONFIG.defaultTimeout,
|
|
66
|
+
maxRetries: DEFAULT_RAF_CONFIG.defaultMaxRetries,
|
|
67
|
+
autoCommit: DEFAULT_RAF_CONFIG.autoCommit,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
2
|
+
|
|
3
|
+
interface LoggerOptions {
|
|
4
|
+
verbose?: boolean;
|
|
5
|
+
debug?: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
class Logger {
|
|
9
|
+
private verbose = false;
|
|
10
|
+
private debugMode = false;
|
|
11
|
+
|
|
12
|
+
configure(options: LoggerOptions): void {
|
|
13
|
+
this.verbose = options.verbose ?? false;
|
|
14
|
+
this.debugMode = options.debug ?? false;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated No longer used - kept for backwards compatibility
|
|
19
|
+
*/
|
|
20
|
+
setContext(_prefix: string): void {
|
|
21
|
+
// No-op: context prefix feature removed in favor of minimal output style
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @deprecated No longer used - kept for backwards compatibility
|
|
26
|
+
*/
|
|
27
|
+
clearContext(): void {
|
|
28
|
+
// No-op: context prefix feature removed in favor of minimal output style
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private formatMessage(message: string): string {
|
|
32
|
+
return message;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
debug(message: string, ...args: unknown[]): void {
|
|
36
|
+
if (this.debugMode) {
|
|
37
|
+
console.log(`[DEBUG] ${message}`, ...args);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
info(message: string, ...args: unknown[]): void {
|
|
42
|
+
console.log(this.formatMessage(message), ...args);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
verbose_log(message: string, ...args: unknown[]): void {
|
|
46
|
+
if (this.verbose || this.debugMode) {
|
|
47
|
+
console.log(this.formatMessage(message), ...args);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
warn(message: string, ...args: unknown[]): void {
|
|
52
|
+
console.warn(`⚠️ ${this.formatMessage(message)}`, ...args);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
error(message: string, ...args: unknown[]): void {
|
|
56
|
+
console.error(`✗ ${this.formatMessage(message)}`, ...args);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
print(message: string, ...args: unknown[]): void {
|
|
60
|
+
console.log(message, ...args);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
success(message: string, ...args: unknown[]): void {
|
|
64
|
+
console.log(`✓ ${this.formatMessage(message)}`, ...args);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
task(status: string, name: string): void {
|
|
68
|
+
console.log(`${status} ${name}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
newline(): void {
|
|
72
|
+
console.log();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
dim(message: string, ...args: unknown[]): void {
|
|
76
|
+
// ANSI escape code for dim text
|
|
77
|
+
console.log(`\x1b[2m${this.formatMessage(message)}\x1b[0m`, ...args);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export const logger = new Logger();
|