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,143 @@
|
|
|
1
|
+
import { formatRetryHistoryForConsole } from '../../src/commands/do.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tests for retry history formatting.
|
|
5
|
+
*
|
|
6
|
+
* NOTE: Retry history is now shown in console output instead of being written
|
|
7
|
+
* to outcome files. This test suite verifies the console output formatting.
|
|
8
|
+
*/
|
|
9
|
+
describe('Retry History Formatting', () => {
|
|
10
|
+
describe('formatRetryHistoryForConsole', () => {
|
|
11
|
+
it('should return empty string when no failures occurred', () => {
|
|
12
|
+
const result = formatRetryHistoryForConsole('001', 'my-task', [], 1, true);
|
|
13
|
+
expect(result).toBe('');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('should format single failure followed by success', () => {
|
|
17
|
+
const failureHistory = [{ attempt: 1, reason: 'Task timed out' }];
|
|
18
|
+
const result = formatRetryHistoryForConsole('001', 'my-task', failureHistory, 2, true);
|
|
19
|
+
|
|
20
|
+
expect(result).toContain('Task 001 (my-task):');
|
|
21
|
+
expect(result).toContain('Attempt 1: Failed - Task timed out');
|
|
22
|
+
expect(result).toContain('Attempt 2: Succeeded');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should format multiple failures followed by success', () => {
|
|
26
|
+
const failureHistory = [
|
|
27
|
+
{ attempt: 1, reason: 'Context overflow - task too large' },
|
|
28
|
+
{ attempt: 2, reason: 'API rate limit exceeded' },
|
|
29
|
+
];
|
|
30
|
+
const result = formatRetryHistoryForConsole('001', 'my-task', failureHistory, 3, true);
|
|
31
|
+
|
|
32
|
+
expect(result).toContain('Task 001 (my-task):');
|
|
33
|
+
expect(result).toContain('Attempt 1: Failed - Context overflow - task too large');
|
|
34
|
+
expect(result).toContain('Attempt 2: Failed - API rate limit exceeded');
|
|
35
|
+
expect(result).toContain('Attempt 3: Succeeded');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should format failures without success when task ultimately failed', () => {
|
|
39
|
+
const failureHistory = [
|
|
40
|
+
{ attempt: 1, reason: 'Task timed out' },
|
|
41
|
+
{ attempt: 2, reason: 'Task timed out' },
|
|
42
|
+
{ attempt: 3, reason: 'Context overflow' },
|
|
43
|
+
];
|
|
44
|
+
const result = formatRetryHistoryForConsole('001', 'my-task', failureHistory, 3, false);
|
|
45
|
+
|
|
46
|
+
expect(result).toContain('Task 001 (my-task):');
|
|
47
|
+
expect(result).toContain('Attempt 1: Failed - Task timed out');
|
|
48
|
+
expect(result).toContain('Attempt 2: Failed - Task timed out');
|
|
49
|
+
expect(result).toContain('Attempt 3: Failed - Context overflow');
|
|
50
|
+
expect(result).not.toContain('Succeeded');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should preserve failure reasons exactly as provided', () => {
|
|
54
|
+
const failureHistory = [
|
|
55
|
+
{ attempt: 1, reason: 'No completion marker found in output or outcome file' },
|
|
56
|
+
];
|
|
57
|
+
const result = formatRetryHistoryForConsole('001', 'my-task', failureHistory, 2, true);
|
|
58
|
+
|
|
59
|
+
expect(result).toContain('Attempt 1: Failed - No completion marker found in output or outcome file');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should handle task name same as task id', () => {
|
|
63
|
+
const failureHistory = [{ attempt: 1, reason: 'Test failure' }];
|
|
64
|
+
const result = formatRetryHistoryForConsole('001', '001', failureHistory, 2, true);
|
|
65
|
+
|
|
66
|
+
// When taskName equals taskId, should just show taskId without parentheses
|
|
67
|
+
expect(result).toContain('Task 001:');
|
|
68
|
+
expect(result).not.toContain('Task 001 (001):');
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('should have proper indentation structure', () => {
|
|
72
|
+
const failureHistory = [
|
|
73
|
+
{ attempt: 1, reason: 'First failure' },
|
|
74
|
+
{ attempt: 2, reason: 'Second failure' },
|
|
75
|
+
];
|
|
76
|
+
const result = formatRetryHistoryForConsole('001', 'my-task', failureHistory, 3, true);
|
|
77
|
+
const lines = result.split('\n');
|
|
78
|
+
|
|
79
|
+
// First line should be task header with minimal indentation
|
|
80
|
+
expect(lines[0]).toMatch(/^\s{2}Task/);
|
|
81
|
+
// Following lines should have more indentation for attempts
|
|
82
|
+
expect(lines[1]).toMatch(/^\s{4}Attempt 1/);
|
|
83
|
+
expect(lines[2]).toMatch(/^\s{4}Attempt 2/);
|
|
84
|
+
expect(lines[3]).toMatch(/^\s{4}Attempt 3/);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should handle single failure with immediate success on retry', () => {
|
|
88
|
+
const failureHistory = [{ attempt: 1, reason: 'Rate limit exceeded' }];
|
|
89
|
+
const result = formatRetryHistoryForConsole('001', 'my-task', failureHistory, 2, true);
|
|
90
|
+
|
|
91
|
+
const lines = result.split('\n');
|
|
92
|
+
expect(lines).toHaveLength(3);
|
|
93
|
+
expect(lines[0]).toContain('Task 001 (my-task):');
|
|
94
|
+
expect(lines[1]).toContain('Attempt 1: Failed - Rate limit exceeded');
|
|
95
|
+
expect(lines[2]).toContain('Attempt 2: Succeeded');
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should handle maximum retries (3 failures)', () => {
|
|
99
|
+
const failureHistory = [
|
|
100
|
+
{ attempt: 1, reason: 'API error' },
|
|
101
|
+
{ attempt: 2, reason: 'API error' },
|
|
102
|
+
{ attempt: 3, reason: 'API error' },
|
|
103
|
+
];
|
|
104
|
+
const result = formatRetryHistoryForConsole('001', 'my-task', failureHistory, 3, false);
|
|
105
|
+
|
|
106
|
+
const lines = result.split('\n');
|
|
107
|
+
expect(lines).toHaveLength(4);
|
|
108
|
+
expect(lines[0]).toContain('Task 001 (my-task):');
|
|
109
|
+
expect(lines[1]).toContain('Attempt 1: Failed - API error');
|
|
110
|
+
expect(lines[2]).toContain('Attempt 2: Failed - API error');
|
|
111
|
+
expect(lines[3]).toContain('Attempt 3: Failed - API error');
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('integration scenarios', () => {
|
|
116
|
+
it('should work for clean success (no failures)', () => {
|
|
117
|
+
// On first attempt success, no retry history
|
|
118
|
+
const result = formatRetryHistoryForConsole('001', 'my-task', [], 1, true);
|
|
119
|
+
expect(result).toBe('');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should work for retry after timeout then success', () => {
|
|
123
|
+
const failureHistory = [{ attempt: 1, reason: 'Task timed out' }];
|
|
124
|
+
const result = formatRetryHistoryForConsole('001', 'my-task', failureHistory, 2, true);
|
|
125
|
+
|
|
126
|
+
expect(result).toContain('Attempt 1');
|
|
127
|
+
expect(result).toContain('Task timed out');
|
|
128
|
+
expect(result).toContain('Attempt 2');
|
|
129
|
+
expect(result).toContain('Succeeded');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('should work for ultimate failure after all retries', () => {
|
|
133
|
+
const failureHistory = [
|
|
134
|
+
{ attempt: 1, reason: 'Context overflow - task too large' },
|
|
135
|
+
];
|
|
136
|
+
const result = formatRetryHistoryForConsole('001', 'my-task', failureHistory, 1, false);
|
|
137
|
+
|
|
138
|
+
expect(result).toContain('Attempt 1');
|
|
139
|
+
expect(result).toContain('Context overflow');
|
|
140
|
+
expect(result).not.toContain('Succeeded');
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
});
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
|
|
3
|
+
// Mock execSync before importing the module
|
|
4
|
+
const mockExecSync = jest.fn();
|
|
5
|
+
jest.unstable_mockModule('node:child_process', () => ({
|
|
6
|
+
execSync: mockExecSync,
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
// Mock logger to prevent console output
|
|
10
|
+
jest.unstable_mockModule('../../src/utils/logger.js', () => ({
|
|
11
|
+
logger: {
|
|
12
|
+
debug: jest.fn(),
|
|
13
|
+
warn: jest.fn(),
|
|
14
|
+
error: jest.fn(),
|
|
15
|
+
},
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
// Import after mocking
|
|
19
|
+
const { stashChanges, isGitRepo, hasUncommittedChanges } = await import('../../src/core/git.js');
|
|
20
|
+
|
|
21
|
+
describe('stashChanges', () => {
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
jest.clearAllMocks();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should return false when not in a git repository', () => {
|
|
27
|
+
mockExecSync.mockImplementation(() => {
|
|
28
|
+
throw new Error('not a git repository');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const result = stashChanges('test-stash');
|
|
32
|
+
expect(result).toBe(false);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should return false when there are no uncommitted changes', () => {
|
|
36
|
+
mockExecSync.mockImplementation((cmd: unknown) => {
|
|
37
|
+
const cmdStr = cmd as string;
|
|
38
|
+
if (cmdStr.includes('rev-parse')) {
|
|
39
|
+
return 'true\n';
|
|
40
|
+
}
|
|
41
|
+
if (cmdStr.includes('status --porcelain')) {
|
|
42
|
+
return ''; // No changes
|
|
43
|
+
}
|
|
44
|
+
return '';
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const result = stashChanges('test-stash');
|
|
48
|
+
expect(result).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should stash changes with descriptive name', () => {
|
|
52
|
+
mockExecSync.mockImplementation((cmd: unknown) => {
|
|
53
|
+
const cmdStr = cmd as string;
|
|
54
|
+
if (cmdStr.includes('rev-parse')) {
|
|
55
|
+
return 'true\n';
|
|
56
|
+
}
|
|
57
|
+
if (cmdStr.includes('status --porcelain')) {
|
|
58
|
+
return 'M src/file.ts\n';
|
|
59
|
+
}
|
|
60
|
+
if (cmdStr.includes('stash push')) {
|
|
61
|
+
return '';
|
|
62
|
+
}
|
|
63
|
+
return '';
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const result = stashChanges('raf-001-task-3-failed');
|
|
67
|
+
expect(result).toBe(true);
|
|
68
|
+
expect(mockExecSync).toHaveBeenCalledWith(
|
|
69
|
+
'git stash push -m "raf-001-task-3-failed"',
|
|
70
|
+
expect.any(Object)
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should escape quotes in stash name', () => {
|
|
75
|
+
mockExecSync.mockImplementation((cmd: unknown) => {
|
|
76
|
+
const cmdStr = cmd as string;
|
|
77
|
+
if (cmdStr.includes('rev-parse')) {
|
|
78
|
+
return 'true\n';
|
|
79
|
+
}
|
|
80
|
+
if (cmdStr.includes('status --porcelain')) {
|
|
81
|
+
return 'M src/file.ts\n';
|
|
82
|
+
}
|
|
83
|
+
if (cmdStr.includes('stash push')) {
|
|
84
|
+
return '';
|
|
85
|
+
}
|
|
86
|
+
return '';
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const result = stashChanges('test "with" quotes');
|
|
90
|
+
expect(result).toBe(true);
|
|
91
|
+
expect(mockExecSync).toHaveBeenCalledWith(
|
|
92
|
+
'git stash push -m "test \\"with\\" quotes"',
|
|
93
|
+
expect.any(Object)
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should return false if stash command fails', () => {
|
|
98
|
+
mockExecSync.mockImplementation((cmd: unknown) => {
|
|
99
|
+
const cmdStr = cmd as string;
|
|
100
|
+
if (cmdStr.includes('rev-parse')) {
|
|
101
|
+
return 'true\n';
|
|
102
|
+
}
|
|
103
|
+
if (cmdStr.includes('status --porcelain')) {
|
|
104
|
+
return 'M src/file.ts\n';
|
|
105
|
+
}
|
|
106
|
+
if (cmdStr.includes('stash push')) {
|
|
107
|
+
throw new Error('stash failed');
|
|
108
|
+
}
|
|
109
|
+
return '';
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const result = stashChanges('test-stash');
|
|
113
|
+
expect(result).toBe(false);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('should use correct stash name format for RAF failures', () => {
|
|
117
|
+
mockExecSync.mockImplementation((cmd: unknown) => {
|
|
118
|
+
const cmdStr = cmd as string;
|
|
119
|
+
if (cmdStr.includes('rev-parse')) {
|
|
120
|
+
return 'true\n';
|
|
121
|
+
}
|
|
122
|
+
if (cmdStr.includes('status --porcelain')) {
|
|
123
|
+
return 'M src/file.ts\nA src/new.ts\n';
|
|
124
|
+
}
|
|
125
|
+
if (cmdStr.includes('stash push')) {
|
|
126
|
+
return '';
|
|
127
|
+
}
|
|
128
|
+
return '';
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const result = stashChanges('raf-002-task-5-failed');
|
|
132
|
+
expect(result).toBe(true);
|
|
133
|
+
expect(mockExecSync).toHaveBeenCalledWith(
|
|
134
|
+
'git stash push -m "raf-002-task-5-failed"',
|
|
135
|
+
expect.any(Object)
|
|
136
|
+
);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { parseGitStatus } from '../../src/core/git.js';
|
|
2
|
+
|
|
3
|
+
describe('git utilities', () => {
|
|
4
|
+
describe('parseGitStatus', () => {
|
|
5
|
+
it('should return empty array for empty output', () => {
|
|
6
|
+
expect(parseGitStatus('')).toEqual([]);
|
|
7
|
+
expect(parseGitStatus(' ')).toEqual([]);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('should parse modified files (staged)', () => {
|
|
11
|
+
const output = 'M src/file.ts';
|
|
12
|
+
expect(parseGitStatus(output)).toEqual(['src/file.ts']);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should parse modified files (unstaged)', () => {
|
|
16
|
+
// Git porcelain format: XY PATH (X=index, Y=worktree, space, then path)
|
|
17
|
+
// For unstaged modification: ' M filename' (space, M, space, filename)
|
|
18
|
+
const output = ' M src/file.ts';
|
|
19
|
+
expect(parseGitStatus(output)).toEqual(['src/file.ts']);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should parse modified files (both staged and unstaged)', () => {
|
|
23
|
+
const output = 'MM src/file.ts';
|
|
24
|
+
expect(parseGitStatus(output)).toEqual(['src/file.ts']);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should parse added files', () => {
|
|
28
|
+
const output = 'A src/new-file.ts';
|
|
29
|
+
expect(parseGitStatus(output)).toEqual(['src/new-file.ts']);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should parse deleted files', () => {
|
|
33
|
+
const output = 'D src/old-file.ts';
|
|
34
|
+
expect(parseGitStatus(output)).toEqual(['src/old-file.ts']);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should parse untracked files', () => {
|
|
38
|
+
const output = '?? src/untracked.ts';
|
|
39
|
+
expect(parseGitStatus(output)).toEqual(['src/untracked.ts']);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should parse renamed files (extracting new name)', () => {
|
|
43
|
+
const output = 'R old-name.ts -> new-name.ts';
|
|
44
|
+
expect(parseGitStatus(output)).toEqual(['new-name.ts']);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should parse copied files (extracting new name)', () => {
|
|
48
|
+
const output = 'C original.ts -> copy.ts';
|
|
49
|
+
expect(parseGitStatus(output)).toEqual(['copy.ts']);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should parse multiple files', () => {
|
|
53
|
+
const output = `M src/modified.ts
|
|
54
|
+
A src/added.ts
|
|
55
|
+
D src/deleted.ts
|
|
56
|
+
?? src/untracked.ts`;
|
|
57
|
+
expect(parseGitStatus(output)).toEqual([
|
|
58
|
+
'src/modified.ts',
|
|
59
|
+
'src/added.ts',
|
|
60
|
+
'src/deleted.ts',
|
|
61
|
+
'src/untracked.ts',
|
|
62
|
+
]);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should handle quoted paths with special characters', () => {
|
|
66
|
+
const output = '"src/file with spaces.ts"';
|
|
67
|
+
// This is incomplete input but tests quote handling
|
|
68
|
+
// Real git status has format: XY "path"
|
|
69
|
+
const output2 = 'M "src/file with spaces.ts"';
|
|
70
|
+
expect(parseGitStatus(output2)).toEqual(['src/file with spaces.ts']);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should skip malformed lines', () => {
|
|
74
|
+
const output = `M valid.ts
|
|
75
|
+
ab
|
|
76
|
+
M another.ts`;
|
|
77
|
+
expect(parseGitStatus(output)).toEqual(['valid.ts', 'another.ts']);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
import { logger } from '../../src/utils/logger.js';
|
|
3
|
+
|
|
4
|
+
describe('Logger', () => {
|
|
5
|
+
let consoleLogSpy: ReturnType<typeof jest.spyOn>;
|
|
6
|
+
let consoleWarnSpy: ReturnType<typeof jest.spyOn>;
|
|
7
|
+
let consoleErrorSpy: ReturnType<typeof jest.spyOn>;
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
|
|
11
|
+
consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|
12
|
+
consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
13
|
+
logger.clearContext();
|
|
14
|
+
logger.configure({ verbose: false, debug: false });
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
consoleLogSpy.mockRestore();
|
|
19
|
+
consoleWarnSpy.mockRestore();
|
|
20
|
+
consoleErrorSpy.mockRestore();
|
|
21
|
+
logger.clearContext();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('print', () => {
|
|
25
|
+
it('should output text exactly as passed', () => {
|
|
26
|
+
logger.print('Hello World');
|
|
27
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('Hello World');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should pass additional arguments through', () => {
|
|
31
|
+
logger.print('Value: %d', 42);
|
|
32
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('Value: %d', 42);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should not add any prefix', () => {
|
|
36
|
+
logger.print('raw text');
|
|
37
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('raw text');
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('info', () => {
|
|
42
|
+
it('should output message without prefix', () => {
|
|
43
|
+
logger.info('Starting task');
|
|
44
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('Starting task');
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe('success', () => {
|
|
49
|
+
it('should output with ✓ prefix', () => {
|
|
50
|
+
logger.success('Task completed');
|
|
51
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('✓ Task completed');
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe('warn', () => {
|
|
56
|
+
it('should output with ⚠️ prefix', () => {
|
|
57
|
+
logger.warn('Something needs attention');
|
|
58
|
+
expect(consoleWarnSpy).toHaveBeenCalledWith('⚠️ Something needs attention');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe('error', () => {
|
|
63
|
+
it('should output with ✗ prefix', () => {
|
|
64
|
+
logger.error('Something went wrong');
|
|
65
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('✗ Something went wrong');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('context methods (deprecated)', () => {
|
|
70
|
+
it('setContext should be a no-op', () => {
|
|
71
|
+
logger.setContext('[Task 2/5: fix-login]');
|
|
72
|
+
logger.info('Starting task');
|
|
73
|
+
// Context should NOT be applied - it's a no-op
|
|
74
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('Starting task');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('clearContext should be a no-op', () => {
|
|
78
|
+
logger.setContext('[Task 1/1: test]');
|
|
79
|
+
logger.clearContext();
|
|
80
|
+
logger.info('No prefix here');
|
|
81
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('No prefix here');
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe('verbose_log', () => {
|
|
86
|
+
it('should log when verbose mode is enabled', () => {
|
|
87
|
+
logger.configure({ verbose: true });
|
|
88
|
+
logger.verbose_log('Verbose message');
|
|
89
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('Verbose message');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should not log when verbose mode is disabled', () => {
|
|
93
|
+
logger.configure({ verbose: false });
|
|
94
|
+
logger.verbose_log('Verbose message');
|
|
95
|
+
expect(consoleLogSpy).not.toHaveBeenCalled();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should log when debug mode is enabled', () => {
|
|
99
|
+
logger.configure({ debug: true });
|
|
100
|
+
logger.verbose_log('Verbose message');
|
|
101
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('Verbose message');
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe('debug', () => {
|
|
106
|
+
it('should log with [DEBUG] prefix when debug mode is enabled', () => {
|
|
107
|
+
logger.configure({ debug: true });
|
|
108
|
+
logger.debug('Debug message');
|
|
109
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG] Debug message');
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('should not log when debug mode is disabled', () => {
|
|
113
|
+
logger.configure({ debug: false });
|
|
114
|
+
logger.debug('Debug message');
|
|
115
|
+
expect(consoleLogSpy).not.toHaveBeenCalled();
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
describe('task', () => {
|
|
120
|
+
it('should output status and name', () => {
|
|
121
|
+
logger.task('●', 'running-task');
|
|
122
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('● running-task');
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
describe('newline', () => {
|
|
127
|
+
it('should output an empty line', () => {
|
|
128
|
+
logger.newline();
|
|
129
|
+
expect(consoleLogSpy).toHaveBeenCalledWith();
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|