rafcode 1.2.0 → 2.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.md +118 -22
- package/RAF/aaaabt-verbose-chronicle/decisions.md +25 -0
- package/RAF/aaaabt-verbose-chronicle/input.md +3 -0
- package/RAF/aaaabt-verbose-chronicle/outcomes/01-amend-iteration-references.md +25 -0
- package/RAF/aaaabt-verbose-chronicle/outcomes/02-verbose-task-name-display.md +31 -0
- package/RAF/aaaabt-verbose-chronicle/outcomes/03-verbose-streaming-fix.md +48 -0
- package/RAF/aaaabt-verbose-chronicle/outcomes/04-commit-verification-before-halt.md +56 -0
- package/RAF/aaaabt-verbose-chronicle/plans/01-amend-iteration-references.md +35 -0
- package/RAF/aaaabt-verbose-chronicle/plans/02-verbose-task-name-display.md +38 -0
- package/RAF/aaaabt-verbose-chronicle/plans/03-verbose-streaming-fix.md +45 -0
- package/RAF/aaaabt-verbose-chronicle/plans/04-commit-verification-before-halt.md +62 -0
- package/RAF/aaaacu-worktree-weaver/decisions.md +88 -0
- package/RAF/aaaacu-worktree-weaver/input.md +27 -0
- package/RAF/aaaacu-worktree-weaver/outcomes/01-git-worktree-utilities.md +41 -0
- package/RAF/aaaacu-worktree-weaver/outcomes/02-worktree-plan-command.md +44 -0
- package/RAF/aaaacu-worktree-weaver/outcomes/03-worktree-do-command.md +58 -0
- package/RAF/aaaacu-worktree-weaver/outcomes/04-auto-merge-and-cleanup.md +40 -0
- package/RAF/aaaacu-worktree-weaver/outcomes/05-worktree-tests.md +43 -0
- package/RAF/aaaacu-worktree-weaver/outcomes/06-update-documentation.md +33 -0
- package/RAF/aaaacu-worktree-weaver/plans/01-git-worktree-utilities.md +51 -0
- package/RAF/aaaacu-worktree-weaver/plans/02-worktree-plan-command.md +93 -0
- package/RAF/aaaacu-worktree-weaver/plans/03-worktree-do-command.md +81 -0
- package/RAF/aaaacu-worktree-weaver/plans/04-auto-merge-and-cleanup.md +51 -0
- package/RAF/aaaacu-worktree-weaver/plans/05-worktree-tests.md +52 -0
- package/RAF/aaaacu-worktree-weaver/plans/06-update-documentation.md +55 -0
- package/RAF/aaaacv-trim-the-fat/decisions.md +34 -0
- package/RAF/aaaacv-trim-the-fat/input.md +5 -0
- package/RAF/aaaacv-trim-the-fat/outcomes/01-add-worktree-support-to-status.md +43 -0
- package/RAF/aaaacv-trim-the-fat/outcomes/02-remove-multi-project-from-do.md +50 -0
- package/RAF/aaaacv-trim-the-fat/outcomes/03-commit-artifacts-on-amend.md +35 -0
- package/RAF/aaaacv-trim-the-fat/outcomes/04-worktree-aware-exit-messages.md +36 -0
- package/RAF/aaaacv-trim-the-fat/plans/01-add-worktree-support-to-status.md +43 -0
- package/RAF/aaaacv-trim-the-fat/plans/02-remove-multi-project-from-do.md +44 -0
- package/RAF/aaaacv-trim-the-fat/plans/03-commit-artifacts-on-amend.md +38 -0
- package/RAF/aaaacv-trim-the-fat/plans/04-worktree-aware-exit-messages.md +38 -0
- package/RAF/aaaacw-prune-cycle/decisions.md +25 -0
- package/RAF/aaaacw-prune-cycle/input.md +5 -0
- package/RAF/aaaacw-prune-cycle/outcomes/01-create-worktree-from-branch.md +32 -0
- package/RAF/aaaacw-prune-cycle/outcomes/02-cleanup-worktree-on-success.md +33 -0
- package/RAF/aaaacw-prune-cycle/outcomes/03-amend-recreate-worktree.md +40 -0
- package/RAF/aaaacw-prune-cycle/plans/01-create-worktree-from-branch.md +31 -0
- package/RAF/aaaacw-prune-cycle/plans/02-cleanup-worktree-on-success.md +38 -0
- package/RAF/aaaacw-prune-cycle/plans/03-amend-recreate-worktree.md +50 -0
- package/RAF/aaaacx-epoch-shift/decisions.md +25 -0
- package/RAF/aaaacx-epoch-shift/input.md +1 -0
- package/RAF/aaaacx-epoch-shift/outcomes/01-epoch-id-generation.md +34 -0
- package/RAF/aaaacx-epoch-shift/outcomes/02-update-pattern-matching.md +32 -0
- package/RAF/aaaacx-epoch-shift/outcomes/03-update-tests.md +59 -0
- package/RAF/aaaacx-epoch-shift/outcomes/04-update-documentation.md +30 -0
- package/RAF/aaaacx-epoch-shift/plans/01-epoch-id-generation.md +40 -0
- package/RAF/aaaacx-epoch-shift/plans/02-update-pattern-matching.md +60 -0
- package/RAF/aaaacx-epoch-shift/plans/03-update-tests.md +48 -0
- package/RAF/aaaacx-epoch-shift/plans/04-update-documentation.md +44 -0
- package/RAF/ahmpro-merge-guardian/decisions.md +25 -0
- package/RAF/ahmpro-merge-guardian/input.md +4 -0
- package/RAF/ahmpro-merge-guardian/outcomes/001-fix-amend-worktree-commit.md +45 -0
- package/RAF/ahmpro-merge-guardian/outcomes/002-base36-task-ids.md +55 -0
- package/RAF/ahmpro-merge-guardian/outcomes/003-worktree-pr-creation.md +41 -0
- package/RAF/ahmpro-merge-guardian/outcomes/004-post-execution-picker.md +53 -0
- package/RAF/ahmpro-merge-guardian/plans/001-fix-amend-worktree-commit.md +39 -0
- package/RAF/ahmpro-merge-guardian/plans/002-base36-task-ids.md +43 -0
- package/RAF/ahmpro-merge-guardian/plans/003-worktree-pr-creation.md +43 -0
- package/RAF/ahmpro-merge-guardian/plans/004-post-execution-picker.md +51 -0
- package/RAF/ahnbcu-letterjam/decisions.md +13 -0
- package/RAF/ahnbcu-letterjam/input.md +3 -0
- package/RAF/ahnbcu-letterjam/outcomes/01-base26-encoding.md +42 -0
- package/RAF/ahnbcu-letterjam/outcomes/02-update-tests.md +38 -0
- package/RAF/ahnbcu-letterjam/outcomes/03-migrate-command.md +51 -0
- package/RAF/ahnbcu-letterjam/outcomes/04-update-documentation.md +29 -0
- package/RAF/ahnbcu-letterjam/plans/01-base26-encoding.md +36 -0
- package/RAF/ahnbcu-letterjam/plans/02-update-tests.md +37 -0
- package/RAF/ahnbcu-letterjam/plans/03-migrate-command.md +49 -0
- package/RAF/ahnbcu-letterjam/plans/04-update-documentation.md +39 -0
- package/RAF/ahnwrk-worktree-weaver/decisions.md +19 -0
- package/RAF/ahnwrk-worktree-weaver/input.md +4 -0
- package/RAF/ahnwrk-worktree-weaver/outcomes/01-remove-co-authored-by.md +20 -0
- package/RAF/ahnwrk-worktree-weaver/outcomes/02-update-task-status-format.md +21 -0
- package/RAF/ahnwrk-worktree-weaver/outcomes/03-worktree-auto-discovery.md +34 -0
- package/RAF/ahnwrk-worktree-weaver/outcomes/04-fix-pr-description.md +30 -0
- package/RAF/ahnwrk-worktree-weaver/plans/01-remove-co-authored-by.md +26 -0
- package/RAF/ahnwrk-worktree-weaver/plans/02-update-task-status-format.md +27 -0
- package/RAF/ahnwrk-worktree-weaver/plans/03-worktree-auto-discovery.md +37 -0
- package/RAF/ahnwrk-worktree-weaver/plans/04-fix-pr-description.md +50 -0
- package/README.md +56 -10
- package/dist/commands/do.d.ts +15 -0
- package/dist/commands/do.d.ts.map +1 -1
- package/dist/commands/do.js +400 -131
- package/dist/commands/do.js.map +1 -1
- package/dist/commands/migrate.d.ts +14 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +228 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/plan.d.ts.map +1 -1
- package/dist/commands/plan.js +237 -40
- package/dist/commands/plan.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +221 -47
- package/dist/commands/status.js.map +1 -1
- package/dist/core/claude-runner.d.ts +52 -1
- package/dist/core/claude-runner.d.ts.map +1 -1
- package/dist/core/claude-runner.js +195 -17
- package/dist/core/claude-runner.js.map +1 -1
- package/dist/core/git.d.ts +29 -5
- package/dist/core/git.d.ts.map +1 -1
- package/dist/core/git.js +95 -18
- package/dist/core/git.js.map +1 -1
- package/dist/core/project-manager.d.ts.map +1 -1
- package/dist/core/project-manager.js +2 -2
- package/dist/core/project-manager.js.map +1 -1
- package/dist/core/pull-request.d.ts +84 -0
- package/dist/core/pull-request.d.ts.map +1 -0
- package/dist/core/pull-request.js +414 -0
- package/dist/core/pull-request.js.map +1 -0
- package/dist/core/state-derivation.d.ts +3 -3
- package/dist/core/state-derivation.d.ts.map +1 -1
- package/dist/core/state-derivation.js +18 -14
- package/dist/core/state-derivation.js.map +1 -1
- package/dist/core/worktree.d.ts +120 -0
- package/dist/core/worktree.d.ts.map +1 -0
- package/dist/core/worktree.js +322 -0
- package/dist/core/worktree.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/parsers/stream-renderer.d.ts +42 -0
- package/dist/parsers/stream-renderer.d.ts.map +1 -0
- package/dist/parsers/stream-renderer.js +100 -0
- package/dist/parsers/stream-renderer.js.map +1 -0
- package/dist/prompts/amend.d.ts +1 -0
- package/dist/prompts/amend.d.ts.map +1 -1
- package/dist/prompts/amend.js +25 -10
- package/dist/prompts/amend.js.map +1 -1
- package/dist/prompts/execution.js +5 -5
- package/dist/prompts/execution.js.map +1 -1
- package/dist/prompts/planning.d.ts +1 -0
- package/dist/prompts/planning.d.ts.map +1 -1
- package/dist/prompts/planning.js +11 -10
- package/dist/prompts/planning.js.map +1 -1
- package/dist/types/config.d.ts +5 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/ui/project-picker.d.ts +34 -3
- package/dist/ui/project-picker.d.ts.map +1 -1
- package/dist/ui/project-picker.js +78 -10
- package/dist/ui/project-picker.js.map +1 -1
- package/dist/utils/paths.d.ts +38 -43
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +123 -193
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/terminal-symbols.d.ts +2 -2
- package/dist/utils/terminal-symbols.js +3 -3
- package/dist/utils/terminal-symbols.js.map +1 -1
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +2 -8
- package/dist/utils/validation.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/do.ts +471 -142
- package/src/commands/migrate.ts +269 -0
- package/src/commands/plan.ts +264 -40
- package/src/commands/status.ts +252 -45
- package/src/core/claude-runner.ts +270 -17
- package/src/core/git.ts +99 -19
- package/src/core/project-manager.ts +2 -1
- package/src/core/pull-request.ts +480 -0
- package/src/core/state-derivation.ts +18 -14
- package/src/core/worktree.ts +357 -0
- package/src/index.ts +2 -0
- package/src/parsers/stream-renderer.ts +139 -0
- package/src/prompts/amend.ts +27 -9
- package/src/prompts/execution.ts +5 -5
- package/src/prompts/planning.ts +12 -10
- package/src/types/config.ts +6 -0
- package/src/ui/project-picker.ts +110 -10
- package/src/utils/paths.ts +129 -214
- package/src/utils/terminal-symbols.ts +3 -3
- package/src/utils/validation.ts +2 -9
- package/tests/unit/amend-prompt.test.ts +85 -0
- package/tests/unit/claude-runner.test.ts +567 -1
- package/tests/unit/commit-planning-artifacts-worktree.test.ts +327 -0
- package/tests/unit/commit-planning-artifacts.test.ts +303 -35
- package/tests/unit/dependency-integration.test.ts +95 -95
- package/tests/unit/do-blocked-tasks.test.ts +53 -53
- package/tests/unit/do-command.test.ts +39 -132
- package/tests/unit/do-rerun.test.ts +65 -65
- package/tests/unit/do-worktree-cleanup.test.ts +151 -0
- package/tests/unit/execution-prompt.test.ts +71 -60
- package/tests/unit/failure-history.test.ts +19 -19
- package/tests/unit/git-commit-helpers.test.ts +103 -0
- package/tests/unit/git-stash.test.ts +4 -4
- package/tests/unit/migrate-command.test.ts +197 -0
- package/tests/unit/outcome-content.test.ts +20 -20
- package/tests/unit/paths.test.ts +269 -467
- package/tests/unit/plan-amend-worktree-recreate.test.ts +246 -0
- package/tests/unit/plan-command.test.ts +144 -93
- package/tests/unit/planning-prompt.test.ts +41 -4
- package/tests/unit/post-execution-picker.test.ts +251 -0
- package/tests/unit/project-manager.test.ts +20 -8
- package/tests/unit/project-picker.test.ts +425 -42
- package/tests/unit/pull-request.test.ts +852 -0
- package/tests/unit/state-derivation.test.ts +138 -137
- package/tests/unit/status-command.test.ts +344 -76
- package/tests/unit/stream-renderer.test.ts +286 -0
- package/tests/unit/terminal-symbols.test.ts +4 -4
- package/tests/unit/worktree-integration.test.ts +405 -0
- package/tests/unit/worktree.test.ts +523 -0
- package/tests/unit/do-multiproject.test.ts +0 -270
- /package/RAF/{001-raf-task-improvements → aaaaab-raf-task-improvements}/input.md +0 -0
- /package/RAF/{001-raf-task-improvements/outcomes/001-add-decisions-folder.md → aaaaab-raf-task-improvements/outcomes/01-add-decisions-folder.md} +0 -0
- /package/RAF/{001-raf-task-improvements/outcomes/002-fix-write-error-on-shutdown.md → aaaaab-raf-task-improvements/outcomes/02-fix-write-error-on-shutdown.md} +0 -0
- /package/RAF/{001-raf-task-improvements/outcomes/003-stash-changes-on-failure.md → aaaaab-raf-task-improvements/outcomes/03-stash-changes-on-failure.md} +0 -0
- /package/RAF/{001-raf-task-improvements/outcomes/004-add-project-name-to-commits.md → aaaaab-raf-task-improvements/outcomes/04-add-project-name-to-commits.md} +0 -0
- /package/RAF/{001-raf-task-improvements/outcomes/005-add-running-time-display.md → aaaaab-raf-task-improvements/outcomes/05-add-running-time-display.md} +0 -0
- /package/RAF/{001-raf-task-improvements/outcomes/006-add-task-name-to-logs.md → aaaaab-raf-task-improvements/outcomes/06-add-task-name-to-logs.md} +0 -0
- /package/RAF/{001-raf-task-improvements/outcomes/007-show-model-at-task-start.md → aaaaab-raf-task-improvements/outcomes/07-show-model-at-task-start.md} +0 -0
- /package/RAF/{001-raf-task-improvements/outcomes/009-remove-editor-placeholder-text.md → aaaaab-raf-task-improvements/outcomes/09-remove-editor-placeholder-text.md} +0 -0
- /package/RAF/{001-raf-task-improvements → aaaaab-raf-task-improvements}/outcomes/SUMMARY.md +0 -0
- /package/RAF/{001-raf-task-improvements/plans/001-add-decisions-folder.md → aaaaab-raf-task-improvements/plans/01-add-decisions-folder.md} +0 -0
- /package/RAF/{001-raf-task-improvements/plans/002-fix-write-error-on-shutdown.md → aaaaab-raf-task-improvements/plans/02-fix-write-error-on-shutdown.md} +0 -0
- /package/RAF/{001-raf-task-improvements/plans/003-stash-changes-on-failure.md → aaaaab-raf-task-improvements/plans/03-stash-changes-on-failure.md} +0 -0
- /package/RAF/{001-raf-task-improvements/plans/004-add-project-name-to-commits.md → aaaaab-raf-task-improvements/plans/04-add-project-name-to-commits.md} +0 -0
- /package/RAF/{001-raf-task-improvements/plans/005-add-running-time-display.md → aaaaab-raf-task-improvements/plans/05-add-running-time-display.md} +0 -0
- /package/RAF/{001-raf-task-improvements/plans/006-add-task-name-to-logs.md → aaaaab-raf-task-improvements/plans/06-add-task-name-to-logs.md} +0 -0
- /package/RAF/{001-raf-task-improvements/plans/009-remove-editor-placeholder-text.md → aaaaab-raf-task-improvements/plans/09-remove-editor-placeholder-text.md} +0 -0
- /package/RAF/{002-raf-task-improvements-execution → aaaaac-raf-task-improvements-execution}/decisions/DECISIONS.md +0 -0
- /package/RAF/{002-raf-task-improvements-execution → aaaaac-raf-task-improvements-execution}/input.md +0 -0
- /package/RAF/{002-raf-task-improvements-execution/outcomes/001-commit-show-model-at-task-start.md → aaaaac-raf-task-improvements-execution/outcomes/01-commit-show-model-at-task-start.md} +0 -0
- /package/RAF/{002-raf-task-improvements-execution/outcomes/002-delete-skipped-plan.md → aaaaac-raf-task-improvements-execution/outcomes/02-delete-skipped-plan.md} +0 -0
- /package/RAF/{002-raf-task-improvements-execution → aaaaac-raf-task-improvements-execution}/outcomes/SUMMARY.md +0 -0
- /package/RAF/{002-raf-task-improvements-execution/plans/001-commit-show-model-at-task-start.md → aaaaac-raf-task-improvements-execution/plans/01-commit-show-model-at-task-start.md} +0 -0
- /package/RAF/{002-raf-task-improvements-execution/plans/002-delete-skipped-plan.md → aaaaac-raf-task-improvements-execution/plans/02-delete-skipped-plan.md} +0 -0
- /package/RAF/{003-multi-project-execution → aaaaad-multi-project-execution}/decisions/DECISIONS.md +0 -0
- /package/RAF/{003-multi-project-execution → aaaaad-multi-project-execution}/input.md +0 -0
- /package/RAF/{003-multi-project-execution/outcomes/001-remove-state-json.md → aaaaad-multi-project-execution/outcomes/01-remove-state-json.md} +0 -0
- /package/RAF/{003-multi-project-execution/outcomes/002-update-raf-status.md → aaaaad-multi-project-execution/outcomes/02-update-raf-status.md} +0 -0
- /package/RAF/{003-multi-project-execution/outcomes/003-simplify-git-logic.md → aaaaad-multi-project-execution/outcomes/03-simplify-git-logic.md} +0 -0
- /package/RAF/{003-multi-project-execution/outcomes/004-auto-commit-planning.md → aaaaad-multi-project-execution/outcomes/04-auto-commit-planning.md} +0 -0
- /package/RAF/{003-multi-project-execution/outcomes/005-rerun-failed-tasks.md → aaaaad-multi-project-execution/outcomes/05-rerun-failed-tasks.md} +0 -0
- /package/RAF/{003-multi-project-execution/outcomes/006-multi-project-execution.md → aaaaad-multi-project-execution/outcomes/06-multi-project-execution.md} +0 -0
- /package/RAF/{003-multi-project-execution/outcomes/007-verify-timeout.md → aaaaad-multi-project-execution/outcomes/07-verify-timeout.md} +0 -0
- /package/RAF/{003-multi-project-execution/outcomes/008-move-decisions-file.md → aaaaad-multi-project-execution/outcomes/08-move-decisions-file.md} +0 -0
- /package/RAF/{003-multi-project-execution → aaaaad-multi-project-execution}/outcomes/SUMMARY.md +0 -0
- /package/RAF/{003-multi-project-execution/plans/001-remove-state-json.md → aaaaad-multi-project-execution/plans/01-remove-state-json.md} +0 -0
- /package/RAF/{003-multi-project-execution/plans/002-update-raf-status.md → aaaaad-multi-project-execution/plans/02-update-raf-status.md} +0 -0
- /package/RAF/{003-multi-project-execution/plans/003-simplify-git-logic.md → aaaaad-multi-project-execution/plans/03-simplify-git-logic.md} +0 -0
- /package/RAF/{003-multi-project-execution/plans/004-auto-commit-planning.md → aaaaad-multi-project-execution/plans/04-auto-commit-planning.md} +0 -0
- /package/RAF/{003-multi-project-execution/plans/005-rerun-failed-tasks.md → aaaaad-multi-project-execution/plans/05-rerun-failed-tasks.md} +0 -0
- /package/RAF/{003-multi-project-execution/plans/006-multi-project-execution.md → aaaaad-multi-project-execution/plans/06-multi-project-execution.md} +0 -0
- /package/RAF/{003-multi-project-execution/plans/007-verify-timeout.md → aaaaad-multi-project-execution/plans/07-verify-timeout.md} +0 -0
- /package/RAF/{003-multi-project-execution/plans/008-move-decisions-file.md → aaaaad-multi-project-execution/plans/08-move-decisions-file.md} +0 -0
- /package/RAF/{004-task-naming-optimization → aaaaae-task-naming-optimization}/decisions.md +0 -0
- /package/RAF/{004-task-naming-optimization → aaaaae-task-naming-optimization}/input.md +0 -0
- /package/RAF/{004-task-naming-optimization/outcomes/001-remove-summary-file.md → aaaaae-task-naming-optimization/outcomes/01-remove-summary-file.md} +0 -0
- /package/RAF/{004-task-naming-optimization/outcomes/002-base36-project-numbering.md → aaaaae-task-naming-optimization/outcomes/02-base36-project-numbering.md} +0 -0
- /package/RAF/{004-task-naming-optimization/outcomes/003-improve-haiku-prompt.md → aaaaae-task-naming-optimization/outcomes/03-improve-haiku-prompt.md} +0 -0
- /package/RAF/{004-task-naming-optimization → aaaaae-task-naming-optimization}/outcomes/SUMMARY.md +0 -0
- /package/RAF/{004-task-naming-optimization/plans/001-remove-summary-file.md → aaaaae-task-naming-optimization/plans/01-remove-summary-file.md} +0 -0
- /package/RAF/{004-task-naming-optimization/plans/002-base36-project-numbering.md → aaaaae-task-naming-optimization/plans/02-base36-project-numbering.md} +0 -0
- /package/RAF/{004-task-naming-optimization/plans/003-improve-haiku-prompt.md → aaaaae-task-naming-optimization/plans/03-improve-haiku-prompt.md} +0 -0
- /package/RAF/{005-task-naming-improvements → aaaaaf-task-naming-improvements}/decisions.md +0 -0
- /package/RAF/{005-task-naming-improvements → aaaaaf-task-naming-improvements}/input.md +0 -0
- /package/RAF/{005-task-naming-improvements/outcomes/001-enhance-identifier-resolution.md → aaaaaf-task-naming-improvements/outcomes/01-enhance-identifier-resolution.md} +0 -0
- /package/RAF/{005-task-naming-improvements/outcomes/002-add-identifier-support-to-status.md → aaaaaf-task-naming-improvements/outcomes/02-add-identifier-support-to-status.md} +0 -0
- /package/RAF/{005-task-naming-improvements/outcomes/003-update-do-for-full-folder-names.md → aaaaaf-task-naming-improvements/outcomes/03-update-do-for-full-folder-names.md} +0 -0
- /package/RAF/{005-task-naming-improvements/outcomes/004-implement-amend-flag-for-plan.md → aaaaaf-task-naming-improvements/outcomes/04-implement-amend-flag-for-plan.md} +0 -0
- /package/RAF/{005-task-naming-improvements/outcomes/005-commit-outcomes-on-complete.md → aaaaaf-task-naming-improvements/outcomes/05-commit-outcomes-on-complete.md} +0 -0
- /package/RAF/{005-task-naming-improvements/outcomes/006-update-execution-prompt-commit-schema.md → aaaaaf-task-naming-improvements/outcomes/06-update-execution-prompt-commit-schema.md} +0 -0
- /package/RAF/{005-task-naming-improvements/outcomes/007-allow-pending-task-amendments.md → aaaaaf-task-naming-improvements/outcomes/07-allow-pending-task-amendments.md} +0 -0
- /package/RAF/{005-task-naming-improvements/outcomes/008-fix-timeout-label.md → aaaaaf-task-naming-improvements/outcomes/08-fix-timeout-label.md} +0 -0
- /package/RAF/{005-task-naming-improvements/plans/001-enhance-identifier-resolution.md → aaaaaf-task-naming-improvements/plans/01-enhance-identifier-resolution.md} +0 -0
- /package/RAF/{005-task-naming-improvements/plans/002-add-identifier-support-to-status.md → aaaaaf-task-naming-improvements/plans/02-add-identifier-support-to-status.md} +0 -0
- /package/RAF/{005-task-naming-improvements/plans/003-update-do-for-full-folder-names.md → aaaaaf-task-naming-improvements/plans/03-update-do-for-full-folder-names.md} +0 -0
- /package/RAF/{005-task-naming-improvements/plans/004-implement-amend-flag-for-plan.md → aaaaaf-task-naming-improvements/plans/04-implement-amend-flag-for-plan.md} +0 -0
- /package/RAF/{005-task-naming-improvements/plans/005-commit-outcomes-on-complete.md → aaaaaf-task-naming-improvements/plans/05-commit-outcomes-on-complete.md} +0 -0
- /package/RAF/{005-task-naming-improvements/plans/006-update-execution-prompt-commit-schema.md → aaaaaf-task-naming-improvements/plans/06-update-execution-prompt-commit-schema.md} +0 -0
- /package/RAF/{005-task-naming-improvements/plans/007-allow-pending-task-amendments.md → aaaaaf-task-naming-improvements/plans/07-allow-pending-task-amendments.md} +0 -0
- /package/RAF/{005-task-naming-improvements/plans/008-fix-timeout-label.md → aaaaaf-task-naming-improvements/plans/08-fix-timeout-label.md} +0 -0
- /package/RAF/{006-fix-double-summary-headers → aaaaag-fix-double-summary-headers}/decisions.md +0 -0
- /package/RAF/{006-fix-double-summary-headers → aaaaag-fix-double-summary-headers}/input.md +0 -0
- /package/RAF/{006-fix-double-summary-headers/outcomes/001-fix-double-summary-headers.md → aaaaag-fix-double-summary-headers/outcomes/01-fix-double-summary-headers.md} +0 -0
- /package/RAF/{006-fix-double-summary-headers/outcomes/002-update-readme-for-npm.md → aaaaag-fix-double-summary-headers/outcomes/02-update-readme-for-npm.md} +0 -0
- /package/RAF/{006-fix-double-summary-headers/outcomes/003-npm-publish-instructions.md → aaaaag-fix-double-summary-headers/outcomes/03-npm-publish-instructions.md} +0 -0
- /package/RAF/{006-fix-double-summary-headers/outcomes/004-flexible-project-lookup.md → aaaaag-fix-double-summary-headers/outcomes/04-flexible-project-lookup.md} +0 -0
- /package/RAF/{006-fix-double-summary-headers/plans/001-fix-double-summary-headers.md → aaaaag-fix-double-summary-headers/plans/01-fix-double-summary-headers.md} +0 -0
- /package/RAF/{006-fix-double-summary-headers/plans/002-update-readme-for-npm.md → aaaaag-fix-double-summary-headers/plans/02-update-readme-for-npm.md} +0 -0
- /package/RAF/{006-fix-double-summary-headers/plans/003-npm-publish-instructions.md → aaaaag-fix-double-summary-headers/plans/03-npm-publish-instructions.md} +0 -0
- /package/RAF/{006-fix-double-summary-headers/plans/004-flexible-project-lookup.md → aaaaag-fix-double-summary-headers/plans/04-flexible-project-lookup.md} +0 -0
- /package/RAF/{007-improve-outcome-format → aaaaah-improve-outcome-format}/decisions.md +0 -0
- /package/RAF/{007-improve-outcome-format → aaaaah-improve-outcome-format}/input.md +0 -0
- /package/RAF/{007-improve-outcome-format/outcomes/001-update-execution-prompt.md → aaaaah-improve-outcome-format/outcomes/01-update-execution-prompt.md} +0 -0
- /package/RAF/{007-improve-outcome-format/outcomes/002-update-state-derivation.md → aaaaah-improve-outcome-format/outcomes/02-update-state-derivation.md} +0 -0
- /package/RAF/{007-improve-outcome-format/outcomes/003-update-do-command-outcome-handling.md → aaaaah-improve-outcome-format/outcomes/03-update-do-command-outcome-handling.md} +0 -0
- /package/RAF/{007-improve-outcome-format/outcomes/004-implement-failure-analysis.md → aaaaah-improve-outcome-format/outcomes/04-implement-failure-analysis.md} +0 -0
- /package/RAF/{007-improve-outcome-format/outcomes/005-update-documentation.md → aaaaah-improve-outcome-format/outcomes/05-update-documentation.md} +0 -0
- /package/RAF/{007-improve-outcome-format/plans/001-update-execution-prompt.md → aaaaah-improve-outcome-format/plans/01-update-execution-prompt.md} +0 -0
- /package/RAF/{007-improve-outcome-format/plans/002-update-state-derivation.md → aaaaah-improve-outcome-format/plans/02-update-state-derivation.md} +0 -0
- /package/RAF/{007-improve-outcome-format/plans/003-update-do-command-outcome-handling.md → aaaaah-improve-outcome-format/plans/03-update-do-command-outcome-handling.md} +0 -0
- /package/RAF/{007-improve-outcome-format/plans/004-implement-failure-analysis.md → aaaaah-improve-outcome-format/plans/04-implement-failure-analysis.md} +0 -0
- /package/RAF/{007-improve-outcome-format/plans/005-update-documentation.md → aaaaah-improve-outcome-format/plans/05-update-documentation.md} +0 -0
- /package/RAF/{008-beautiful-do → aaaaai-beautiful-do}/decisions.md +0 -0
- /package/RAF/{008-beautiful-do → aaaaai-beautiful-do}/input.md +0 -0
- /package/RAF/{008-beautiful-do/outcomes/001-terminal-symbols.md → aaaaai-beautiful-do/outcomes/01-terminal-symbols.md} +0 -0
- /package/RAF/{008-beautiful-do/outcomes/002-refactor-do-output.md → aaaaai-beautiful-do/outcomes/02-refactor-do-output.md} +0 -0
- /package/RAF/{008-beautiful-do/outcomes/003-refactor-status-output.md → aaaaai-beautiful-do/outcomes/03-refactor-status-output.md} +0 -0
- /package/RAF/{008-beautiful-do/outcomes/004-simplify-logger.md → aaaaai-beautiful-do/outcomes/04-simplify-logger.md} +0 -0
- /package/RAF/{008-beautiful-do/outcomes/005-add-tests.md → aaaaai-beautiful-do/outcomes/05-add-tests.md} +0 -0
- /package/RAF/{008-beautiful-do/plans/001-terminal-symbols.md → aaaaai-beautiful-do/plans/01-terminal-symbols.md} +0 -0
- /package/RAF/{008-beautiful-do/plans/002-refactor-do-output.md → aaaaai-beautiful-do/plans/02-refactor-do-output.md} +0 -0
- /package/RAF/{008-beautiful-do/plans/003-refactor-status-output.md → aaaaai-beautiful-do/plans/03-refactor-status-output.md} +0 -0
- /package/RAF/{008-beautiful-do/plans/004-simplify-logger.md → aaaaai-beautiful-do/plans/04-simplify-logger.md} +0 -0
- /package/RAF/{008-beautiful-do/plans/005-add-tests.md → aaaaai-beautiful-do/plans/05-add-tests.md} +0 -0
- /package/RAF/{009-system-promt-ammend → aaaaaj-system-promt-ammend}/decisions.md +0 -0
- /package/RAF/{009-system-promt-ammend → aaaaaj-system-promt-ammend}/input.md +0 -0
- /package/RAF/{009-system-promt-ammend/outcomes/001-model-override.md → aaaaaj-system-promt-ammend/outcomes/01-model-override.md} +0 -0
- /package/RAF/{009-system-promt-ammend/outcomes/002-system-prompt-append.md → aaaaaj-system-promt-ammend/outcomes/02-system-prompt-append.md} +0 -0
- /package/RAF/{009-system-promt-ammend/outcomes/003-retry-context.md → aaaaaj-system-promt-ammend/outcomes/03-retry-context.md} +0 -0
- /package/RAF/{009-system-promt-ammend/plans/001-model-override.md → aaaaaj-system-promt-ammend/plans/01-model-override.md} +0 -0
- /package/RAF/{009-system-promt-ammend/plans/002-system-prompt-append.md → aaaaaj-system-promt-ammend/plans/02-system-prompt-append.md} +0 -0
- /package/RAF/{009-system-promt-ammend/plans/003-retry-context.md → aaaaaj-system-promt-ammend/plans/03-retry-context.md} +0 -0
- /package/RAF/{010-outcome-marker-fallback → aaaabk-outcome-marker-fallback}/decisions.md +0 -0
- /package/RAF/{010-outcome-marker-fallback → aaaabk-outcome-marker-fallback}/input.md +0 -0
- /package/RAF/{010-outcome-marker-fallback/outcomes/001-outcome-file-marker-fallback.md → aaaabk-outcome-marker-fallback/outcomes/01-outcome-file-marker-fallback.md} +0 -0
- /package/RAF/{010-outcome-marker-fallback/outcomes/002-creative-project-naming.md → aaaabk-outcome-marker-fallback/outcomes/02-creative-project-naming.md} +0 -0
- /package/RAF/{010-outcome-marker-fallback/plans/001-outcome-file-marker-fallback.md → aaaabk-outcome-marker-fallback/plans/01-outcome-file-marker-fallback.md} +0 -0
- /package/RAF/{010-outcome-marker-fallback/plans/002-creative-project-naming.md → aaaabk-outcome-marker-fallback/plans/02-creative-project-naming.md} +0 -0
- /package/RAF/{011-do-task-in-commit → aaaabl-do-task-in-commit}/decisions.md +0 -0
- /package/RAF/{011-do-task-in-commit → aaaabl-do-task-in-commit}/input.md +0 -0
- /package/RAF/{011-do-task-in-commit/outcomes/001-update-execution-prompt.md → aaaabl-do-task-in-commit/outcomes/01-update-execution-prompt.md} +0 -0
- /package/RAF/{011-do-task-in-commit/outcomes/002-update-tests.md → aaaabl-do-task-in-commit/outcomes/02-update-tests.md} +0 -0
- /package/RAF/{011-do-task-in-commit/outcomes/003-update-documentation.md → aaaabl-do-task-in-commit/outcomes/03-update-documentation.md} +0 -0
- /package/RAF/{011-do-task-in-commit/plans/001-update-execution-prompt.md → aaaabl-do-task-in-commit/plans/01-update-execution-prompt.md} +0 -0
- /package/RAF/{011-do-task-in-commit/plans/002-update-tests.md → aaaabl-do-task-in-commit/plans/02-update-tests.md} +0 -0
- /package/RAF/{011-do-task-in-commit/plans/003-update-documentation.md → aaaabl-do-task-in-commit/plans/03-update-documentation.md} +0 -0
- /package/RAF/{012-name-picker-buffet → aaaabm-name-picker-buffet}/decisions.md +0 -0
- /package/RAF/{012-name-picker-buffet → aaaabm-name-picker-buffet}/input.md +0 -0
- /package/RAF/{012-name-picker-buffet/outcomes/001-name-picker-for-raf-plan.md → aaaabm-name-picker-buffet/outcomes/01-name-picker-for-raf-plan.md} +0 -0
- /package/RAF/{012-name-picker-buffet/outcomes/002-interactive-project-picker-for-raf-do.md → aaaabm-name-picker-buffet/outcomes/02-interactive-project-picker-for-raf-do.md} +0 -0
- /package/RAF/{012-name-picker-buffet/outcomes/003-raf-status-truncation.md → aaaabm-name-picker-buffet/outcomes/03-raf-status-truncation.md} +0 -0
- /package/RAF/{012-name-picker-buffet/outcomes/004-failure-reason-details.md → aaaabm-name-picker-buffet/outcomes/04-failure-reason-details.md} +0 -0
- /package/RAF/{012-name-picker-buffet/outcomes/005-remove-raf-commits.md → aaaabm-name-picker-buffet/outcomes/05-remove-raf-commits.md} +0 -0
- /package/RAF/{012-name-picker-buffet/outcomes/006-update-execution-prompt-for-commits.md → aaaabm-name-picker-buffet/outcomes/06-update-execution-prompt-for-commits.md} +0 -0
- /package/RAF/{012-name-picker-buffet/outcomes/007-fix-plan-mode-user-prompt.md → aaaabm-name-picker-buffet/outcomes/07-fix-plan-mode-user-prompt.md} +0 -0
- /package/RAF/{012-name-picker-buffet/outcomes/008-add-auto-flag-for-plan-mode.md → aaaabm-name-picker-buffet/outcomes/08-add-auto-flag-for-plan-mode.md} +0 -0
- /package/RAF/{012-name-picker-buffet/plans/001-name-picker-for-raf-plan.md → aaaabm-name-picker-buffet/plans/01-name-picker-for-raf-plan.md} +0 -0
- /package/RAF/{012-name-picker-buffet/plans/002-interactive-project-picker-for-raf-do.md → aaaabm-name-picker-buffet/plans/02-interactive-project-picker-for-raf-do.md} +0 -0
- /package/RAF/{012-name-picker-buffet/plans/003-raf-status-truncation.md → aaaabm-name-picker-buffet/plans/03-raf-status-truncation.md} +0 -0
- /package/RAF/{012-name-picker-buffet/plans/004-failure-reason-details.md → aaaabm-name-picker-buffet/plans/04-failure-reason-details.md} +0 -0
- /package/RAF/{012-name-picker-buffet/plans/005-remove-raf-commits.md → aaaabm-name-picker-buffet/plans/05-remove-raf-commits.md} +0 -0
- /package/RAF/{012-name-picker-buffet/plans/006-update-execution-prompt-for-commits.md → aaaabm-name-picker-buffet/plans/06-update-execution-prompt-for-commits.md} +0 -0
- /package/RAF/{012-name-picker-buffet/plans/007-fix-plan-mode-user-prompt.md → aaaabm-name-picker-buffet/plans/07-fix-plan-mode-user-prompt.md} +0 -0
- /package/RAF/{012-name-picker-buffet/plans/008-add-auto-flag-for-plan-mode.md → aaaabm-name-picker-buffet/plans/08-add-auto-flag-for-plan-mode.md} +0 -0
- /package/RAF/{013-dependencies-watchdog → aaaabn-dependencies-watchdog}/decisions.md +0 -0
- /package/RAF/{013-dependencies-watchdog → aaaabn-dependencies-watchdog}/input.md +0 -0
- /package/RAF/{013-dependencies-watchdog/outcomes/001-define-dependency-syntax.md → aaaabn-dependencies-watchdog/outcomes/01-define-dependency-syntax.md} +0 -0
- /package/RAF/{013-dependencies-watchdog/outcomes/002-update-planning-prompts.md → aaaabn-dependencies-watchdog/outcomes/02-update-planning-prompts.md} +0 -0
- /package/RAF/{013-dependencies-watchdog/outcomes/003-parse-dependencies-update-state.md → aaaabn-dependencies-watchdog/outcomes/03-parse-dependencies-update-state.md} +0 -0
- /package/RAF/{013-dependencies-watchdog/outcomes/004-implement-dependency-checking-in-do.md → aaaabn-dependencies-watchdog/outcomes/04-implement-dependency-checking-in-do.md} +0 -0
- /package/RAF/{013-dependencies-watchdog/outcomes/005-update-execution-prompts.md → aaaabn-dependencies-watchdog/outcomes/05-update-execution-prompts.md} +0 -0
- /package/RAF/{013-dependencies-watchdog/outcomes/006-add-tests.md → aaaabn-dependencies-watchdog/outcomes/06-add-tests.md} +0 -0
- /package/RAF/{013-dependencies-watchdog/outcomes/007-add-act-alias.md → aaaabn-dependencies-watchdog/outcomes/07-add-act-alias.md} +0 -0
- /package/RAF/{013-dependencies-watchdog/outcomes/008-add-exit-message.md → aaaabn-dependencies-watchdog/outcomes/08-add-exit-message.md} +0 -0
- /package/RAF/{013-dependencies-watchdog/plans/001-define-dependency-syntax.md → aaaabn-dependencies-watchdog/plans/01-define-dependency-syntax.md} +0 -0
- /package/RAF/{013-dependencies-watchdog/plans/002-update-planning-prompts.md → aaaabn-dependencies-watchdog/plans/02-update-planning-prompts.md} +0 -0
- /package/RAF/{013-dependencies-watchdog/plans/003-parse-dependencies-update-state.md → aaaabn-dependencies-watchdog/plans/03-parse-dependencies-update-state.md} +0 -0
- /package/RAF/{013-dependencies-watchdog/plans/004-implement-dependency-checking-in-do.md → aaaabn-dependencies-watchdog/plans/04-implement-dependency-checking-in-do.md} +0 -0
- /package/RAF/{013-dependencies-watchdog/plans/005-update-execution-prompts.md → aaaabn-dependencies-watchdog/plans/05-update-execution-prompts.md} +0 -0
- /package/RAF/{013-dependencies-watchdog/plans/006-add-tests.md → aaaabn-dependencies-watchdog/plans/06-add-tests.md} +0 -0
- /package/RAF/{013-dependencies-watchdog/plans/007-add-act-alias.md → aaaabn-dependencies-watchdog/plans/07-add-act-alias.md} +0 -0
- /package/RAF/{013-dependencies-watchdog/plans/008-add-exit-message.md → aaaabn-dependencies-watchdog/plans/08-add-exit-message.md} +0 -0
- /package/RAF/{014-watchdog → aaaabo-watchdog}/decisions.md +0 -0
- /package/RAF/{014-watchdog → aaaabo-watchdog}/input.md +0 -0
- /package/RAF/{014-watchdog/outcomes/001-amend-flag-position.md → aaaabo-watchdog/outcomes/01-amend-flag-position.md} +0 -0
- /package/RAF/{014-watchdog/outcomes/002-details-only-on-failure.md → aaaabo-watchdog/outcomes/02-details-only-on-failure.md} +0 -0
- /package/RAF/{014-watchdog/plans/001-amend-flag-position.md → aaaabo-watchdog/plans/01-amend-flag-position.md} +0 -0
- /package/RAF/{014-watchdog/plans/002-details-only-on-failure.md → aaaabo-watchdog/plans/02-details-only-on-failure.md} +0 -0
- /package/RAF/{015-name-lottery → aaaabp-name-lottery}/decisions.md +0 -0
- /package/RAF/{015-name-lottery → aaaabp-name-lottery}/input.md +0 -0
- /package/RAF/{015-name-lottery/outcomes/001-auto-pick-project-name.md → aaaabp-name-lottery/outcomes/01-auto-pick-project-name.md} +0 -0
- /package/RAF/{015-name-lottery/outcomes/002-mention-plan-files-in-commit.md → aaaabp-name-lottery/outcomes/02-mention-plan-files-in-commit.md} +0 -0
- /package/RAF/{015-name-lottery/outcomes/003-fix-input-md-in-amend-flow.md → aaaabp-name-lottery/outcomes/03-fix-input-md-in-amend-flow.md} +0 -0
- /package/RAF/{015-name-lottery/plans/001-auto-pick-project-name.md → aaaabp-name-lottery/plans/01-auto-pick-project-name.md} +0 -0
- /package/RAF/{015-name-lottery/plans/002-mention-plan-files-in-commit.md → aaaabp-name-lottery/plans/02-mention-plan-files-in-commit.md} +0 -0
- /package/RAF/{015-name-lottery/plans/003-fix-input-md-in-amend-flow.md → aaaabp-name-lottery/plans/03-fix-input-md-in-amend-flow.md} +0 -0
- /package/RAF/{016-planning-scalpel → aaaabq-planning-scalpel}/decisions.md +0 -0
- /package/RAF/{016-planning-scalpel → aaaabq-planning-scalpel}/input.md +0 -0
- /package/RAF/{016-planning-scalpel/outcomes/001-update-git-commit-instructions.md → aaaabq-planning-scalpel/outcomes/01-update-git-commit-instructions.md} +0 -0
- /package/RAF/{016-planning-scalpel/plans/001-update-git-commit-instructions.md → aaaabq-planning-scalpel/plans/01-update-git-commit-instructions.md} +0 -0
- /package/RAF/{017-decision-vault → aaaabr-decision-vault}/decisions.md +0 -0
- /package/RAF/{017-decision-vault → aaaabr-decision-vault}/input.md +0 -0
- /package/RAF/{017-decision-vault/outcomes/001-create-git-commit-utility.md → aaaabr-decision-vault/outcomes/01-create-git-commit-utility.md} +0 -0
- /package/RAF/{017-decision-vault/outcomes/002-integrate-commit-into-plan.md → aaaabr-decision-vault/outcomes/02-integrate-commit-into-plan.md} +0 -0
- /package/RAF/{017-decision-vault/outcomes/003-add-tests-for-planning-commit.md → aaaabr-decision-vault/outcomes/03-add-tests-for-planning-commit.md} +0 -0
- /package/RAF/{017-decision-vault/plans/001-create-git-commit-utility.md → aaaabr-decision-vault/plans/01-create-git-commit-utility.md} +0 -0
- /package/RAF/{017-decision-vault/plans/002-integrate-commit-into-plan.md → aaaabr-decision-vault/plans/02-integrate-commit-into-plan.md} +0 -0
- /package/RAF/{017-decision-vault/plans/003-add-tests-for-planning-commit.md → aaaabr-decision-vault/plans/03-add-tests-for-planning-commit.md} +0 -0
- /package/RAF/{018-workflow-forge → aaaabs-workflow-forge}/decisions.md +0 -0
- /package/RAF/{018-workflow-forge → aaaabs-workflow-forge}/input.md +0 -0
- /package/RAF/{018-workflow-forge/outcomes/001-add-task-number-progress.md → aaaabs-workflow-forge/outcomes/01-add-task-number-progress.md} +0 -0
- /package/RAF/{018-workflow-forge/outcomes/002-update-plan-do-prompts.md → aaaabs-workflow-forge/outcomes/02-update-plan-do-prompts.md} +0 -0
- /package/RAF/{018-workflow-forge/plans/001-add-task-number-progress.md → aaaabs-workflow-forge/plans/01-add-task-number-progress.md} +0 -0
- /package/RAF/{018-workflow-forge/plans/002-update-plan-do-prompts.md → aaaabs-workflow-forge/plans/02-update-plan-do-prompts.md} +0 -0
package/src/commands/do.ts
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
2
3
|
import { Command } from 'commander';
|
|
4
|
+
import { select } from '@inquirer/prompts';
|
|
3
5
|
import { ProjectManager } from '../core/project-manager.js';
|
|
4
6
|
import { ClaudeRunner } from '../core/claude-runner.js';
|
|
5
7
|
import { shutdownHandler } from '../core/shutdown-handler.js';
|
|
6
|
-
import { stashChanges, hasUncommittedChanges } from '../core/git.js';
|
|
8
|
+
import { stashChanges, hasUncommittedChanges, isGitRepo, getHeadCommitHash } from '../core/git.js';
|
|
7
9
|
import { getExecutionPrompt } from '../prompts/execution.js';
|
|
8
10
|
import { parseOutput, isRetryableFailure } from '../parsers/output-parser.js';
|
|
9
11
|
import { validatePlansExist, resolveModelOption } from '../utils/validation.js';
|
|
10
|
-
import { getRafDir, extractProjectNumber, extractProjectName, extractTaskNameFromPlanFile, resolveProjectIdentifierWithDetails, getOutcomeFilePath } from '../utils/paths.js';
|
|
11
|
-
import { pickPendingProject, getPendingProjects } from '../ui/project-picker.js';
|
|
12
|
+
import { getRafDir, extractProjectNumber, extractProjectName, extractTaskNameFromPlanFile, resolveProjectIdentifierWithDetails, getOutcomeFilePath, parseProjectPrefix } from '../utils/paths.js';
|
|
13
|
+
import { pickPendingProject, getPendingProjects, getPendingWorktreeProjects } from '../ui/project-picker.js';
|
|
14
|
+
import type { PendingProjectInfo } from '../ui/project-picker.js';
|
|
12
15
|
import { logger } from '../utils/logger.js';
|
|
13
16
|
import { getConfig } from '../utils/config.js';
|
|
14
17
|
import { createTaskTimer, formatElapsedTime } from '../utils/timer.js';
|
|
15
18
|
import { createStatusLine } from '../utils/status-line.js';
|
|
16
19
|
import {
|
|
17
|
-
SYMBOLS,
|
|
18
20
|
formatProjectHeader,
|
|
19
21
|
formatSummary,
|
|
20
22
|
formatTaskProgress,
|
|
21
23
|
} from '../utils/terminal-symbols.js';
|
|
22
24
|
import {
|
|
23
25
|
deriveProjectState,
|
|
26
|
+
discoverProjects,
|
|
24
27
|
getNextExecutableTask,
|
|
25
28
|
getDerivedStats,
|
|
26
29
|
getDerivedStatsForTasks,
|
|
@@ -31,8 +34,28 @@ import {
|
|
|
31
34
|
type DerivedProjectState,
|
|
32
35
|
} from '../core/state-derivation.js';
|
|
33
36
|
import { analyzeFailure } from '../core/failure-analyzer.js';
|
|
37
|
+
import {
|
|
38
|
+
getRepoRoot,
|
|
39
|
+
getRepoBasename,
|
|
40
|
+
getCurrentBranch,
|
|
41
|
+
computeWorktreePath,
|
|
42
|
+
computeWorktreeBaseDir,
|
|
43
|
+
validateWorktree,
|
|
44
|
+
listWorktreeProjects,
|
|
45
|
+
mergeWorktreeBranch,
|
|
46
|
+
removeWorktree,
|
|
47
|
+
} from '../core/worktree.js';
|
|
48
|
+
import { createPullRequest, prPreflight } from '../core/pull-request.js';
|
|
34
49
|
import type { DoCommandOptions } from '../types/config.js';
|
|
35
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Post-execution action chosen by the user before task execution begins.
|
|
53
|
+
* - 'merge': merge the worktree branch into the original branch
|
|
54
|
+
* - 'pr': push the branch and create a GitHub PR
|
|
55
|
+
* - 'leave': do nothing, keep the branch as-is
|
|
56
|
+
*/
|
|
57
|
+
export type PostExecutionAction = 'merge' | 'pr' | 'leave';
|
|
58
|
+
|
|
36
59
|
/**
|
|
37
60
|
* Format failure history for console output.
|
|
38
61
|
* Shows attempts that failed before eventual success or final failure.
|
|
@@ -90,25 +113,27 @@ interface ProjectExecutionResult {
|
|
|
90
113
|
|
|
91
114
|
export function createDoCommand(): Command {
|
|
92
115
|
const command = new Command('do')
|
|
93
|
-
.description('Execute planned tasks for
|
|
116
|
+
.description('Execute planned tasks for a project')
|
|
94
117
|
.alias('act')
|
|
95
|
-
.argument('[
|
|
118
|
+
.argument('[project]', 'Project identifier: ID (00j3k1), name (my-project), or folder (00j3k1-my-project)')
|
|
96
119
|
.option('-t, --timeout <minutes>', 'Timeout per task in minutes', '60')
|
|
97
120
|
.option('-v, --verbose', 'Show full Claude output')
|
|
98
121
|
.option('-d, --debug', 'Save all logs and show debug output')
|
|
99
122
|
.option('-f, --force', 'Re-run all tasks regardless of status')
|
|
100
123
|
.option('-m, --model <name>', 'Claude model to use (sonnet, haiku, opus)')
|
|
101
124
|
.option('--sonnet', 'Use Sonnet model (shorthand for --model sonnet)')
|
|
102
|
-
.
|
|
103
|
-
|
|
125
|
+
.option('-w, --worktree', 'Execute tasks in a git worktree')
|
|
126
|
+
.action(async (project: string | undefined, options: DoCommandOptions) => {
|
|
127
|
+
await runDoCommand(project, options);
|
|
104
128
|
});
|
|
105
129
|
|
|
106
130
|
return command;
|
|
107
131
|
}
|
|
108
132
|
|
|
109
|
-
async function runDoCommand(
|
|
133
|
+
async function runDoCommand(projectIdentifierArg: string | undefined, options: DoCommandOptions): Promise<void> {
|
|
110
134
|
const rafDir = getRafDir();
|
|
111
|
-
let
|
|
135
|
+
let projectIdentifier = projectIdentifierArg;
|
|
136
|
+
let worktreeMode = options.worktree ?? false;
|
|
112
137
|
|
|
113
138
|
// Validate and resolve model option
|
|
114
139
|
let model: string;
|
|
@@ -119,28 +144,71 @@ async function runDoCommand(projectIdentifiersArg: string[], options: DoCommandO
|
|
|
119
144
|
process.exit(1);
|
|
120
145
|
}
|
|
121
146
|
|
|
122
|
-
//
|
|
123
|
-
|
|
124
|
-
|
|
147
|
+
// Variables for worktree context (set when --worktree is used)
|
|
148
|
+
let worktreeRoot: string | undefined;
|
|
149
|
+
let originalBranch: string | undefined;
|
|
150
|
+
|
|
151
|
+
if (worktreeMode) {
|
|
152
|
+
// Validate git repo
|
|
153
|
+
const repoRoot = getRepoRoot();
|
|
154
|
+
if (!repoRoot) {
|
|
155
|
+
logger.error('--worktree requires a git repository');
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
const repoBasename = getRepoBasename()!;
|
|
159
|
+
const rafRelativePath = path.relative(repoRoot, rafDir);
|
|
160
|
+
|
|
161
|
+
// Record original branch before any worktree operations
|
|
162
|
+
originalBranch = getCurrentBranch() ?? undefined;
|
|
163
|
+
|
|
164
|
+
if (!projectIdentifier) {
|
|
165
|
+
// Auto-discovery flow
|
|
166
|
+
const selected = await discoverAndPickWorktreeProject(repoBasename, rafDir, rafRelativePath);
|
|
167
|
+
if (!selected) {
|
|
168
|
+
process.exit(0);
|
|
169
|
+
}
|
|
170
|
+
worktreeRoot = selected.worktreeRoot;
|
|
171
|
+
projectIdentifier = selected.projectFolder;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Handle no project identifier (non-worktree mode) - show interactive picker
|
|
176
|
+
if (!projectIdentifier) {
|
|
177
|
+
// Discover worktree projects for the current repo (if in a git repo)
|
|
178
|
+
let worktreeProjects: PendingProjectInfo[] = [];
|
|
179
|
+
const repoRoot = getRepoRoot();
|
|
180
|
+
if (repoRoot) {
|
|
181
|
+
const repoBasename = getRepoBasename()!;
|
|
182
|
+
const rafRelativePath = path.relative(repoRoot, rafDir);
|
|
183
|
+
worktreeProjects = getPendingWorktreeProjects(repoBasename, rafRelativePath);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Check if there are any pending projects (local or worktree)
|
|
125
187
|
const pendingProjects = getPendingProjects(rafDir);
|
|
126
188
|
|
|
127
|
-
if (pendingProjects.length === 0) {
|
|
189
|
+
if (pendingProjects.length === 0 && worktreeProjects.length === 0) {
|
|
128
190
|
logger.info('No pending projects found.');
|
|
129
191
|
logger.info("Run 'raf plan' to create a new project.");
|
|
130
192
|
process.exit(0);
|
|
131
193
|
}
|
|
132
194
|
|
|
133
195
|
try {
|
|
134
|
-
const selectedProject = await pickPendingProject(rafDir);
|
|
196
|
+
const selectedProject = await pickPendingProject(rafDir, worktreeProjects);
|
|
135
197
|
|
|
136
198
|
if (!selectedProject) {
|
|
137
|
-
// This shouldn't happen since we already checked pendingProjects.length
|
|
138
199
|
logger.info('No pending projects found.');
|
|
139
200
|
process.exit(0);
|
|
140
201
|
}
|
|
141
202
|
|
|
142
203
|
// Use the selected project
|
|
143
|
-
|
|
204
|
+
projectIdentifier = selectedProject.folder;
|
|
205
|
+
|
|
206
|
+
// If a worktree project was selected, auto-switch to worktree mode
|
|
207
|
+
if (selectedProject.source === 'worktree' && selectedProject.worktreeRoot) {
|
|
208
|
+
worktreeMode = true;
|
|
209
|
+
worktreeRoot = selectedProject.worktreeRoot;
|
|
210
|
+
originalBranch = getCurrentBranch() ?? undefined;
|
|
211
|
+
}
|
|
144
212
|
} catch (error) {
|
|
145
213
|
// Handle Ctrl+C (user cancellation)
|
|
146
214
|
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
@@ -150,51 +218,109 @@ async function runDoCommand(projectIdentifiersArg: string[], options: DoCommandO
|
|
|
150
218
|
}
|
|
151
219
|
}
|
|
152
220
|
|
|
153
|
-
// Resolve
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
221
|
+
// Resolve project identifier
|
|
222
|
+
let resolvedProject: { identifier: string; path: string; name: string };
|
|
223
|
+
|
|
224
|
+
if (worktreeMode) {
|
|
225
|
+
// Worktree mode: resolve project inside the worktree
|
|
226
|
+
const repoRoot = getRepoRoot()!;
|
|
227
|
+
const repoBasename = getRepoBasename()!;
|
|
228
|
+
const rafRelativePath = path.relative(repoRoot, rafDir);
|
|
229
|
+
|
|
230
|
+
// If worktreeRoot was set by auto-discovery, use it directly
|
|
231
|
+
if (worktreeRoot) {
|
|
232
|
+
const wtRafDir = path.join(worktreeRoot, rafRelativePath);
|
|
233
|
+
const result = resolveProjectIdentifierWithDetails(wtRafDir, projectIdentifier);
|
|
234
|
+
if (!result.path) {
|
|
235
|
+
logger.error(`Project not found in worktree: ${projectIdentifier}`);
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
const projectName = extractProjectName(result.path) ?? projectIdentifier;
|
|
239
|
+
resolvedProject = { identifier: projectIdentifier, path: result.path, name: projectName };
|
|
240
|
+
} else {
|
|
241
|
+
// Explicit identifier: resolve from main repo to get folder name, then validate worktree
|
|
242
|
+
const mainResult = resolveProjectIdentifierWithDetails(rafDir, projectIdentifier);
|
|
157
243
|
|
|
158
|
-
|
|
159
|
-
|
|
244
|
+
let projectFolderName: string;
|
|
245
|
+
if (mainResult.path) {
|
|
246
|
+
// Found in main repo - use its folder name
|
|
247
|
+
projectFolderName = path.basename(mainResult.path);
|
|
248
|
+
} else {
|
|
249
|
+
// Not found in main repo - try to find it in worktrees directly
|
|
250
|
+
// This handles projects that only exist in worktrees
|
|
251
|
+
const worktreeBaseDir = computeWorktreeBaseDir(repoBasename);
|
|
252
|
+
if (!fs.existsSync(worktreeBaseDir)) {
|
|
253
|
+
logger.error(`No worktree found for project "${projectIdentifier}". Did you plan with --worktree?`);
|
|
254
|
+
process.exit(1);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Search worktrees for the project
|
|
258
|
+
const wtProjects = listWorktreeProjects(repoBasename);
|
|
259
|
+
let found = false;
|
|
260
|
+
for (const wtProjectDir of wtProjects) {
|
|
261
|
+
const wtPath = computeWorktreePath(repoBasename, wtProjectDir);
|
|
262
|
+
const wtRafDir = path.join(wtPath, rafRelativePath);
|
|
263
|
+
if (!fs.existsSync(wtRafDir)) continue;
|
|
264
|
+
|
|
265
|
+
const resolution = resolveProjectIdentifierWithDetails(wtRafDir, projectIdentifier);
|
|
266
|
+
if (resolution.path) {
|
|
267
|
+
projectFolderName = path.basename(resolution.path);
|
|
268
|
+
worktreeRoot = wtPath;
|
|
269
|
+
found = true;
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (!found) {
|
|
275
|
+
logger.error(`No worktree found for project "${projectIdentifier}". Did you plan with --worktree?`);
|
|
276
|
+
process.exit(1);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Compute worktree path if not already set
|
|
281
|
+
if (!worktreeRoot) {
|
|
282
|
+
worktreeRoot = computeWorktreePath(repoBasename, projectFolderName!);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Validate the worktree
|
|
286
|
+
const wtProjectRelPath = path.join(rafRelativePath, projectFolderName!);
|
|
287
|
+
const validation = validateWorktree(worktreeRoot, wtProjectRelPath);
|
|
288
|
+
|
|
289
|
+
if (!validation.exists || !validation.isValidWorktree) {
|
|
290
|
+
logger.error(`No worktree found for project "${projectIdentifier}". Did you plan with --worktree?`);
|
|
291
|
+
logger.error(`Expected worktree at: ${worktreeRoot}`);
|
|
292
|
+
process.exit(1);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (!validation.hasProjectFolder || !validation.hasPlans) {
|
|
296
|
+
logger.error(`Worktree exists but project content is missing.`);
|
|
297
|
+
logger.error(`Expected project folder at: ${validation.projectPath ?? path.join(worktreeRoot, wtProjectRelPath)}`);
|
|
298
|
+
process.exit(1);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const projectPath = validation.projectPath!;
|
|
302
|
+
const projectName = extractProjectName(projectPath) ?? projectIdentifier;
|
|
303
|
+
resolvedProject = { identifier: projectIdentifier, path: projectPath, name: projectName };
|
|
304
|
+
}
|
|
305
|
+
} else {
|
|
306
|
+
// Standard mode: resolve from main repo
|
|
307
|
+
const result = resolveProjectIdentifierWithDetails(rafDir, projectIdentifier);
|
|
160
308
|
|
|
161
309
|
if (!result.path) {
|
|
162
310
|
if (result.error === 'ambiguous' && result.matches) {
|
|
163
311
|
const matchList = result.matches
|
|
164
312
|
.map((m) => ` - ${m.folder}`)
|
|
165
313
|
.join('\n');
|
|
166
|
-
|
|
167
|
-
identifier,
|
|
168
|
-
error: `Ambiguous project name. Multiple projects match:\n${matchList}\nPlease specify the project ID or full folder name.`,
|
|
169
|
-
});
|
|
314
|
+
logger.error(`${projectIdentifier}: Ambiguous project name. Multiple projects match:\n${matchList}\nPlease specify the project ID or full folder name.`);
|
|
170
315
|
} else {
|
|
171
|
-
|
|
316
|
+
logger.error(`${projectIdentifier}: Project not found`);
|
|
172
317
|
}
|
|
173
|
-
|
|
318
|
+
logger.info("Run 'raf status' to see available projects.");
|
|
319
|
+
process.exit(1);
|
|
174
320
|
}
|
|
175
321
|
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
// Skip duplicates
|
|
179
|
-
if (seenPaths.has(projectPath)) {
|
|
180
|
-
logger.info(`Skipping duplicate: ${identifier}`);
|
|
181
|
-
continue;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
seenPaths.add(projectPath);
|
|
185
|
-
const projectName = extractProjectName(projectPath) ?? identifier;
|
|
186
|
-
resolvedProjects.push({ identifier, path: projectPath, name: projectName });
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Report resolution errors
|
|
190
|
-
for (const { identifier, error } of errors) {
|
|
191
|
-
logger.error(`${identifier}: ${error}`);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (resolvedProjects.length === 0) {
|
|
195
|
-
logger.error('No valid projects to execute.');
|
|
196
|
-
logger.info("Run 'raf status' to see available projects.");
|
|
197
|
-
process.exit(1);
|
|
322
|
+
const projectName = extractProjectName(result.path) ?? projectIdentifier;
|
|
323
|
+
resolvedProject = { identifier: projectIdentifier, path: result.path, name: projectName };
|
|
198
324
|
}
|
|
199
325
|
|
|
200
326
|
// Get configuration
|
|
@@ -209,66 +335,289 @@ async function runDoCommand(projectIdentifiersArg: string[], options: DoCommandO
|
|
|
209
335
|
// Configure logger
|
|
210
336
|
logger.configure({ verbose, debug });
|
|
211
337
|
|
|
212
|
-
//
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
338
|
+
// Show post-execution picker before task execution (worktree mode only)
|
|
339
|
+
let postAction: PostExecutionAction = 'leave';
|
|
340
|
+
if (worktreeMode && worktreeRoot) {
|
|
341
|
+
try {
|
|
342
|
+
postAction = await pickPostExecutionAction(worktreeRoot);
|
|
343
|
+
} catch (error) {
|
|
344
|
+
// Handle Ctrl+C (user cancellation)
|
|
345
|
+
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
346
|
+
process.exit(0);
|
|
347
|
+
}
|
|
348
|
+
throw error;
|
|
349
|
+
}
|
|
216
350
|
}
|
|
217
351
|
|
|
218
|
-
// Execute
|
|
219
|
-
|
|
220
|
-
const isMultiProject = resolvedProjects.length > 1;
|
|
352
|
+
// Execute project
|
|
353
|
+
let result: ProjectExecutionResult;
|
|
221
354
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
355
|
+
try {
|
|
356
|
+
result = await executeSingleProject(
|
|
357
|
+
resolvedProject.path,
|
|
358
|
+
resolvedProject.name,
|
|
359
|
+
{
|
|
360
|
+
timeout,
|
|
361
|
+
verbose,
|
|
362
|
+
debug,
|
|
363
|
+
force,
|
|
364
|
+
maxRetries,
|
|
365
|
+
autoCommit,
|
|
366
|
+
showModel: true,
|
|
367
|
+
model,
|
|
368
|
+
worktreeCwd: worktreeRoot,
|
|
369
|
+
}
|
|
370
|
+
);
|
|
371
|
+
} catch (error) {
|
|
372
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
373
|
+
logger.error(`Project ${resolvedProject.name} failed: ${errorMessage}`);
|
|
374
|
+
process.exit(1);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Execute post-execution action based on picker choice
|
|
378
|
+
if (worktreeMode && worktreeRoot) {
|
|
379
|
+
const worktreeBranch = path.basename(worktreeRoot);
|
|
380
|
+
|
|
381
|
+
if (result.success) {
|
|
382
|
+
await executePostAction(postAction, worktreeRoot, worktreeBranch, originalBranch, resolvedProject.path);
|
|
383
|
+
} else {
|
|
384
|
+
if (postAction !== 'leave') {
|
|
385
|
+
logger.newline();
|
|
386
|
+
logger.info(`Skipping post-execution action — project has failures. Branch "${worktreeBranch}" is available for inspection.`);
|
|
387
|
+
}
|
|
226
388
|
}
|
|
389
|
+
}
|
|
227
390
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
391
|
+
// Exit with appropriate code
|
|
392
|
+
if (!result.success) {
|
|
393
|
+
process.exit(1);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Show an interactive picker for the post-execution action in worktree mode.
|
|
399
|
+
* Presented before task execution so the user declares intent upfront.
|
|
400
|
+
*
|
|
401
|
+
* If "Create PR" is chosen, runs preflight checks immediately. If preflight fails,
|
|
402
|
+
* warns the user and falls back to re-prompting.
|
|
403
|
+
*/
|
|
404
|
+
export async function pickPostExecutionAction(worktreeRoot: string): Promise<PostExecutionAction> {
|
|
405
|
+
const worktreeBranch = path.basename(worktreeRoot);
|
|
406
|
+
|
|
407
|
+
const chosen = await select<PostExecutionAction>({
|
|
408
|
+
message: `After tasks complete, what should happen with branch "${worktreeBranch}"?`,
|
|
409
|
+
choices: [
|
|
410
|
+
{ name: 'Merge into current branch', value: 'merge' as const },
|
|
411
|
+
{ name: 'Create a GitHub PR', value: 'pr' as const },
|
|
412
|
+
{ name: 'Leave branch as-is', value: 'leave' as const },
|
|
413
|
+
],
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
// Early preflight check for PR option
|
|
417
|
+
if (chosen === 'pr') {
|
|
418
|
+
const preflight = prPreflight(worktreeBranch, worktreeRoot);
|
|
419
|
+
if (!preflight.ready) {
|
|
420
|
+
logger.warn(`PR preflight failed: ${preflight.error}`);
|
|
421
|
+
logger.warn('Falling back to "Leave branch" — you can create a PR manually later.');
|
|
422
|
+
return 'leave';
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return chosen;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Execute the chosen post-execution action.
|
|
431
|
+
* Called after all tasks succeed.
|
|
432
|
+
*/
|
|
433
|
+
async function executePostAction(
|
|
434
|
+
action: PostExecutionAction,
|
|
435
|
+
worktreeRoot: string,
|
|
436
|
+
worktreeBranch: string,
|
|
437
|
+
originalBranch: string | undefined,
|
|
438
|
+
projectPath: string,
|
|
439
|
+
): Promise<void> {
|
|
440
|
+
switch (action) {
|
|
441
|
+
case 'merge': {
|
|
442
|
+
// Clean up worktree before merge (merge uses branch, not directory)
|
|
443
|
+
const cleanupResult = removeWorktree(worktreeRoot);
|
|
444
|
+
if (cleanupResult.success) {
|
|
445
|
+
logger.info(`Cleaned up worktree: ${worktreeRoot}`);
|
|
446
|
+
} else {
|
|
447
|
+
logger.warn(`Could not clean up worktree: ${cleanupResult.error}`);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
if (!originalBranch) {
|
|
451
|
+
logger.warn('Could not determine original branch for merge.');
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
logger.newline();
|
|
456
|
+
logger.info(`Merging branch "${worktreeBranch}" into "${originalBranch}"...`);
|
|
457
|
+
|
|
458
|
+
const mergeResult = mergeWorktreeBranch(worktreeBranch, originalBranch);
|
|
459
|
+
|
|
460
|
+
if (mergeResult.success) {
|
|
461
|
+
const mergeType = mergeResult.fastForward ? 'fast-forward' : 'merge commit';
|
|
462
|
+
logger.success(`Merged "${worktreeBranch}" into "${originalBranch}" (${mergeType})`);
|
|
463
|
+
} else {
|
|
464
|
+
logger.warn(`Could not auto-merge: ${mergeResult.error}`);
|
|
465
|
+
logger.warn(`You can merge manually: git merge ${worktreeBranch}`);
|
|
466
|
+
}
|
|
467
|
+
break;
|
|
255
468
|
}
|
|
256
469
|
|
|
257
|
-
|
|
470
|
+
case 'pr': {
|
|
258
471
|
logger.newline();
|
|
472
|
+
logger.info(`Creating PR for branch "${worktreeBranch}"...`);
|
|
473
|
+
|
|
474
|
+
const prResult = await createPullRequest(worktreeBranch, projectPath, { cwd: worktreeRoot });
|
|
475
|
+
|
|
476
|
+
if (prResult.success) {
|
|
477
|
+
logger.success(`PR created: ${prResult.prUrl}`);
|
|
478
|
+
} else {
|
|
479
|
+
logger.warn(`Could not create PR: ${prResult.error}`);
|
|
480
|
+
logger.warn(`Branch "${worktreeBranch}" has been pushed. You can create a PR manually.`);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// Clean up worktree directory (branch is preserved)
|
|
484
|
+
const prCleanupResult = removeWorktree(worktreeRoot);
|
|
485
|
+
if (prCleanupResult.success) {
|
|
486
|
+
logger.info(`Cleaned up worktree: ${worktreeRoot}`);
|
|
487
|
+
} else {
|
|
488
|
+
logger.warn(`Could not clean up worktree: ${prCleanupResult.error}`);
|
|
489
|
+
}
|
|
490
|
+
break;
|
|
259
491
|
}
|
|
260
|
-
}
|
|
261
492
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
493
|
+
case 'leave': {
|
|
494
|
+
// Clean up worktree directory (branch is preserved)
|
|
495
|
+
const cleanupResult = removeWorktree(worktreeRoot);
|
|
496
|
+
if (cleanupResult.success) {
|
|
497
|
+
logger.info(`Cleaned up worktree: ${worktreeRoot}`);
|
|
498
|
+
} else {
|
|
499
|
+
logger.warn(`Could not clean up worktree: ${cleanupResult.error}`);
|
|
500
|
+
}
|
|
501
|
+
break;
|
|
502
|
+
}
|
|
265
503
|
}
|
|
504
|
+
}
|
|
266
505
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
506
|
+
/**
|
|
507
|
+
* Auto-discovery flow for `raf do --worktree` without a project identifier.
|
|
508
|
+
* Lists worktree projects, finds latest completed main-tree project, filters,
|
|
509
|
+
* and shows an interactive picker.
|
|
510
|
+
*
|
|
511
|
+
* @returns Selected project info or null if cancelled/no projects
|
|
512
|
+
*/
|
|
513
|
+
async function discoverAndPickWorktreeProject(
|
|
514
|
+
repoBasename: string,
|
|
515
|
+
rafDir: string,
|
|
516
|
+
rafRelativePath: string,
|
|
517
|
+
): Promise<{ worktreeRoot: string; projectFolder: string } | null> {
|
|
518
|
+
// List all worktree projects for this repo
|
|
519
|
+
const wtProjects = listWorktreeProjects(repoBasename);
|
|
520
|
+
|
|
521
|
+
if (wtProjects.length === 0) {
|
|
522
|
+
logger.error('No worktree projects found. Did you plan with --worktree?');
|
|
270
523
|
process.exit(1);
|
|
271
524
|
}
|
|
525
|
+
|
|
526
|
+
// Find the highest-numbered completed project in the MAIN tree
|
|
527
|
+
const mainProjects = discoverProjects(rafDir);
|
|
528
|
+
let highestCompletedNumber = 0;
|
|
529
|
+
|
|
530
|
+
for (const project of mainProjects) {
|
|
531
|
+
const state = deriveProjectState(project.path);
|
|
532
|
+
if (isProjectComplete(state) && state.tasks.length > 0) {
|
|
533
|
+
if (project.number > highestCompletedNumber) {
|
|
534
|
+
highestCompletedNumber = project.number;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// Filter threshold: highest completed - 3 (or 0 if none completed)
|
|
540
|
+
const threshold = highestCompletedNumber > 3 ? highestCompletedNumber - 3 : 0;
|
|
541
|
+
|
|
542
|
+
// Filter worktree projects by number threshold and completion status
|
|
543
|
+
const uncompletedProjects: Array<{
|
|
544
|
+
folder: string;
|
|
545
|
+
worktreeRoot: string;
|
|
546
|
+
projectPath: string;
|
|
547
|
+
completedTasks: number;
|
|
548
|
+
totalTasks: number;
|
|
549
|
+
projectNumber: number;
|
|
550
|
+
}> = [];
|
|
551
|
+
|
|
552
|
+
for (const wtProjectDir of wtProjects) {
|
|
553
|
+
// Extract project number from the worktree directory name
|
|
554
|
+
const numPrefix = extractProjectNumber(wtProjectDir);
|
|
555
|
+
if (!numPrefix) continue;
|
|
556
|
+
const projectNumber = parseProjectPrefix(numPrefix);
|
|
557
|
+
if (projectNumber === null) continue;
|
|
558
|
+
|
|
559
|
+
// Apply threshold filter
|
|
560
|
+
if (projectNumber < threshold) continue;
|
|
561
|
+
|
|
562
|
+
// Check if this worktree has a valid project
|
|
563
|
+
const wtPath = computeWorktreePath(repoBasename, wtProjectDir);
|
|
564
|
+
const wtProjectPath = path.join(wtPath, rafRelativePath, wtProjectDir);
|
|
565
|
+
|
|
566
|
+
if (!fs.existsSync(wtProjectPath)) continue;
|
|
567
|
+
|
|
568
|
+
// Derive project state from worktree
|
|
569
|
+
const state = deriveProjectState(wtProjectPath);
|
|
570
|
+
if (state.tasks.length === 0) continue;
|
|
571
|
+
|
|
572
|
+
// Keep only uncompleted projects
|
|
573
|
+
if (isProjectComplete(state)) continue;
|
|
574
|
+
|
|
575
|
+
const stats = getDerivedStats(state);
|
|
576
|
+
uncompletedProjects.push({
|
|
577
|
+
folder: wtProjectDir,
|
|
578
|
+
worktreeRoot: wtPath,
|
|
579
|
+
projectPath: wtProjectPath,
|
|
580
|
+
completedTasks: stats.completed,
|
|
581
|
+
totalTasks: stats.total,
|
|
582
|
+
projectNumber,
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
if (uncompletedProjects.length === 0) {
|
|
587
|
+
logger.info('All worktree projects are completed.');
|
|
588
|
+
return null;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// Sort by project number
|
|
592
|
+
uncompletedProjects.sort((a, b) => a.projectNumber - b.projectNumber);
|
|
593
|
+
|
|
594
|
+
// Show interactive picker (even if only one project)
|
|
595
|
+
const choices = uncompletedProjects.map((p) => {
|
|
596
|
+
const name = extractProjectName(p.folder) ?? p.folder;
|
|
597
|
+
const numPrefix = extractProjectNumber(p.folder) ?? '';
|
|
598
|
+
return {
|
|
599
|
+
name: `${numPrefix} ${name} (${p.completedTasks}/${p.totalTasks} tasks)`,
|
|
600
|
+
value: p,
|
|
601
|
+
};
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
try {
|
|
605
|
+
const selected = await select({
|
|
606
|
+
message: 'Select a worktree project to execute:',
|
|
607
|
+
choices,
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
return {
|
|
611
|
+
worktreeRoot: selected.worktreeRoot,
|
|
612
|
+
projectFolder: selected.folder,
|
|
613
|
+
};
|
|
614
|
+
} catch (error) {
|
|
615
|
+
// Handle Ctrl+C (user cancellation)
|
|
616
|
+
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
617
|
+
return null;
|
|
618
|
+
}
|
|
619
|
+
throw error;
|
|
620
|
+
}
|
|
272
621
|
}
|
|
273
622
|
|
|
274
623
|
interface SingleProjectOptions {
|
|
@@ -280,6 +629,8 @@ interface SingleProjectOptions {
|
|
|
280
629
|
autoCommit: boolean;
|
|
281
630
|
showModel: boolean;
|
|
282
631
|
model: string;
|
|
632
|
+
/** Worktree root directory. When set, Claude runs with cwd in the worktree. */
|
|
633
|
+
worktreeCwd?: string;
|
|
283
634
|
}
|
|
284
635
|
|
|
285
636
|
async function executeSingleProject(
|
|
@@ -287,7 +638,7 @@ async function executeSingleProject(
|
|
|
287
638
|
projectName: string,
|
|
288
639
|
options: SingleProjectOptions
|
|
289
640
|
): Promise<ProjectExecutionResult> {
|
|
290
|
-
const { timeout, verbose, debug, force, maxRetries, autoCommit, showModel, model } = options;
|
|
641
|
+
const { timeout, verbose, debug, force, maxRetries, autoCommit, showModel, model, worktreeCwd } = options;
|
|
291
642
|
|
|
292
643
|
if (!validatePlansExist(projectPath)) {
|
|
293
644
|
return {
|
|
@@ -446,6 +797,7 @@ async function executeSingleProject(
|
|
|
446
797
|
const taskName = extractTaskNameFromPlanFile(task.planFile);
|
|
447
798
|
const displayName = taskName ?? task.id;
|
|
448
799
|
const taskId = task.id; // Capture for closure
|
|
800
|
+
const taskLabel = displayName !== task.id ? `${task.id} (${displayName})` : task.id;
|
|
449
801
|
|
|
450
802
|
// Handle blocked tasks separately - skip Claude execution
|
|
451
803
|
if (task.status === 'blocked') {
|
|
@@ -459,7 +811,7 @@ async function executeSingleProject(
|
|
|
459
811
|
if (verbose) {
|
|
460
812
|
const taskContext = `[Task ${taskNumber}/${totalTasks}: ${displayName}]`;
|
|
461
813
|
logger.setContext(taskContext);
|
|
462
|
-
logger.warn(`Task ${
|
|
814
|
+
logger.warn(`Task ${taskLabel} blocked by failed dependency: ${blockingDep}`);
|
|
463
815
|
} else {
|
|
464
816
|
// Minimal mode: show blocked task line with distinct symbol
|
|
465
817
|
logger.info(formatTaskProgress(taskNumber, totalTasks, 'blocked', displayName, undefined, task.id));
|
|
@@ -484,11 +836,11 @@ async function executeSingleProject(
|
|
|
484
836
|
|
|
485
837
|
// Log task execution status
|
|
486
838
|
if (task.status === 'failed') {
|
|
487
|
-
logger.info(`Retrying task ${
|
|
839
|
+
logger.info(`Retrying task ${taskLabel} (previously failed)...`);
|
|
488
840
|
} else if (task.status === 'completed' && force) {
|
|
489
|
-
logger.info(`Re-running task ${
|
|
841
|
+
logger.info(`Re-running task ${taskLabel} (force mode)...`);
|
|
490
842
|
} else {
|
|
491
|
-
logger.info(`Executing task ${
|
|
843
|
+
logger.info(`Executing task ${taskLabel}...`);
|
|
492
844
|
}
|
|
493
845
|
}
|
|
494
846
|
|
|
@@ -527,7 +879,7 @@ async function executeSingleProject(
|
|
|
527
879
|
attempts++;
|
|
528
880
|
|
|
529
881
|
if (verbose && attempts > 1) {
|
|
530
|
-
logger.info(` Retry ${attempts}/${maxRetries}...`);
|
|
882
|
+
logger.info(` Retry ${attempts}/${maxRetries} for task ${taskLabel}...`);
|
|
531
883
|
}
|
|
532
884
|
|
|
533
885
|
// Build execution prompt (inside loop to include retry context on retries)
|
|
@@ -552,10 +904,18 @@ async function executeSingleProject(
|
|
|
552
904
|
dependencyOutcomes,
|
|
553
905
|
});
|
|
554
906
|
|
|
555
|
-
//
|
|
907
|
+
// Capture HEAD hash before execution for commit verification
|
|
908
|
+
const preExecutionHead = isGitRepo(worktreeCwd) ? getHeadCommitHash(worktreeCwd) : null;
|
|
909
|
+
const commitContext = preExecutionHead ? {
|
|
910
|
+
preExecutionHead,
|
|
911
|
+
expectedPrefix: `RAF[${projectNumber}:${task.id}]`,
|
|
912
|
+
outcomeFilePath,
|
|
913
|
+
} : undefined;
|
|
914
|
+
|
|
915
|
+
// Run Claude (use worktree root as cwd if in worktree mode)
|
|
556
916
|
const result = verbose
|
|
557
|
-
? await claudeRunner.runVerbose(prompt, { timeout })
|
|
558
|
-
: await claudeRunner.run(prompt, { timeout });
|
|
917
|
+
? await claudeRunner.runVerbose(prompt, { timeout, outcomeFilePath, commitContext, cwd: worktreeCwd })
|
|
918
|
+
: await claudeRunner.run(prompt, { timeout, outcomeFilePath, commitContext, cwd: worktreeCwd });
|
|
559
919
|
|
|
560
920
|
lastOutput = result.output;
|
|
561
921
|
|
|
@@ -667,7 +1027,7 @@ Task completed. No detailed report provided.
|
|
|
667
1027
|
projectManager.saveOutcome(projectPath, task.id, outcomeContent);
|
|
668
1028
|
|
|
669
1029
|
if (verbose) {
|
|
670
|
-
logger.success(` Task ${
|
|
1030
|
+
logger.success(` Task ${taskLabel} completed (${elapsedFormatted})`);
|
|
671
1031
|
} else {
|
|
672
1032
|
// Minimal mode: show completed task line
|
|
673
1033
|
logger.info(formatTaskProgress(taskNumber, totalTasks, 'completed', displayName, elapsedMs, task.id));
|
|
@@ -676,17 +1036,17 @@ Task completed. No detailed report provided.
|
|
|
676
1036
|
} else {
|
|
677
1037
|
// Stash any uncommitted changes on complete failure
|
|
678
1038
|
let stashName: string | undefined;
|
|
679
|
-
if (hasUncommittedChanges()) {
|
|
1039
|
+
if (hasUncommittedChanges(worktreeCwd)) {
|
|
680
1040
|
const projectNum = extractProjectNumber(projectPath) ?? '000';
|
|
681
1041
|
stashName = `raf-${projectNum}-task-${task.id}-failed`;
|
|
682
|
-
const stashed = stashChanges(stashName);
|
|
1042
|
+
const stashed = stashChanges(stashName, worktreeCwd);
|
|
683
1043
|
if (verbose && stashed) {
|
|
684
|
-
logger.info(` Changes stashed as: ${stashName}`);
|
|
1044
|
+
logger.info(` Changes for task ${taskLabel} stashed as: ${stashName}`);
|
|
685
1045
|
}
|
|
686
1046
|
}
|
|
687
1047
|
|
|
688
1048
|
if (verbose) {
|
|
689
|
-
logger.error(` Task ${
|
|
1049
|
+
logger.error(` Task ${taskLabel} failed: ${failureReason} (${elapsedFormatted})`);
|
|
690
1050
|
logger.info(' Analyzing failure...');
|
|
691
1051
|
} else {
|
|
692
1052
|
// Minimal mode: show failed task line
|
|
@@ -823,34 +1183,3 @@ ${stashName ? `- Stash: ${stashName}` : ''}
|
|
|
823
1183
|
};
|
|
824
1184
|
}
|
|
825
1185
|
|
|
826
|
-
function printMultiProjectSummary(results: ProjectExecutionResult[], verbose: boolean): void {
|
|
827
|
-
logger.newline();
|
|
828
|
-
|
|
829
|
-
if (verbose) {
|
|
830
|
-
logger.info('=== Multi-Project Summary ===');
|
|
831
|
-
logger.newline();
|
|
832
|
-
|
|
833
|
-
for (const result of results) {
|
|
834
|
-
const statusSymbol = result.success ? SYMBOLS.completed : SYMBOLS.failed;
|
|
835
|
-
const statusText = result.success
|
|
836
|
-
? `Completed (${result.tasksCompleted}/${result.totalTasks} tasks)`
|
|
837
|
-
: result.error
|
|
838
|
-
? `Error: ${result.error}`
|
|
839
|
-
: `Failed (${result.tasksCompleted}/${result.totalTasks} tasks)`;
|
|
840
|
-
|
|
841
|
-
logger.info(`${statusSymbol} ${result.projectName}: ${statusText}`);
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
const completed = results.filter((r) => r.success).length;
|
|
845
|
-
const failed = results.length - completed;
|
|
846
|
-
|
|
847
|
-
logger.newline();
|
|
848
|
-
logger.info(`Total: ${completed} completed, ${failed} failed`);
|
|
849
|
-
} else {
|
|
850
|
-
// Minimal multi-project summary: just show each project result
|
|
851
|
-
for (const result of results) {
|
|
852
|
-
const symbol = result.success ? SYMBOLS.completed : SYMBOLS.failed;
|
|
853
|
-
logger.info(`${symbol} ${result.projectName}`);
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
}
|