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
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
1
2
|
import * as pty from 'node-pty';
|
|
2
3
|
import type { IDisposable } from 'node-pty';
|
|
3
4
|
import { execSync, spawn } from 'node:child_process';
|
|
4
5
|
import { logger } from '../utils/logger.js';
|
|
6
|
+
import { renderStreamEvent } from '../parsers/stream-renderer.js';
|
|
7
|
+
import { getHeadCommitHash, getHeadCommitMessage, isFileCommittedInHead } from './git.js';
|
|
5
8
|
|
|
6
9
|
function getClaudePath(): string {
|
|
7
10
|
try {
|
|
@@ -26,6 +29,27 @@ export interface ClaudeRunnerOptions {
|
|
|
26
29
|
* Claude will still ask planning interview questions.
|
|
27
30
|
*/
|
|
28
31
|
dangerouslySkipPermissions?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Path to the outcome file. When provided, enables completion detection:
|
|
34
|
+
* - Monitors stdout for completion markers (<promise>COMPLETE/FAILED</promise>)
|
|
35
|
+
* - Polls the outcome file for completion markers
|
|
36
|
+
* When detected, starts a grace period before terminating the process,
|
|
37
|
+
* allowing time for git commit operations to complete.
|
|
38
|
+
*/
|
|
39
|
+
outcomeFilePath?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Commit verification context. When provided, the grace period will verify
|
|
42
|
+
* that the expected git commit has been made before terminating.
|
|
43
|
+
* Only applies when a COMPLETE marker is detected (not FAILED).
|
|
44
|
+
*/
|
|
45
|
+
commitContext?: {
|
|
46
|
+
/** HEAD commit hash recorded before task execution began. */
|
|
47
|
+
preExecutionHead: string;
|
|
48
|
+
/** Expected commit message prefix (e.g., "RAF[005:01]"). */
|
|
49
|
+
expectedPrefix: string;
|
|
50
|
+
/** Path to the outcome file that should be committed. */
|
|
51
|
+
outcomeFilePath: string;
|
|
52
|
+
};
|
|
29
53
|
}
|
|
30
54
|
|
|
31
55
|
export interface ClaudeRunnerConfig {
|
|
@@ -50,6 +74,180 @@ const CONTEXT_OVERFLOW_PATTERNS = [
|
|
|
50
74
|
/context window/i,
|
|
51
75
|
];
|
|
52
76
|
|
|
77
|
+
const COMPLETION_MARKER_PATTERN = /<promise>(COMPLETE|FAILED)<\/promise>/i;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Grace period in ms after completion marker is detected before terminating.
|
|
81
|
+
* Allows time for git commit operations to complete.
|
|
82
|
+
*/
|
|
83
|
+
export const COMPLETION_GRACE_PERIOD_MS = 60_000;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Hard maximum grace period in ms. If the commit hasn't landed by this point,
|
|
87
|
+
* the process is killed regardless.
|
|
88
|
+
*/
|
|
89
|
+
export const COMPLETION_HARD_MAX_MS = 180_000;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Interval in ms for polling commit verification after the initial grace period expires.
|
|
93
|
+
*/
|
|
94
|
+
export const COMMIT_POLL_INTERVAL_MS = 10_000;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Interval in ms for polling the outcome file for completion markers.
|
|
98
|
+
*/
|
|
99
|
+
export const OUTCOME_POLL_INTERVAL_MS = 5_000;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Context for commit verification during grace period.
|
|
103
|
+
*/
|
|
104
|
+
export interface CommitContext {
|
|
105
|
+
/** HEAD commit hash recorded before task execution began. */
|
|
106
|
+
preExecutionHead: string;
|
|
107
|
+
/** Expected commit message prefix (e.g., "RAF[005:01]"). */
|
|
108
|
+
expectedPrefix: string;
|
|
109
|
+
/** Path to the outcome file that should be committed. */
|
|
110
|
+
outcomeFilePath: string;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Monitors for task completion markers in stdout and outcome files.
|
|
115
|
+
* When a marker is detected, starts a grace period before killing the process.
|
|
116
|
+
*/
|
|
117
|
+
interface CompletionDetector {
|
|
118
|
+
/** Check accumulated stdout output for completion markers. */
|
|
119
|
+
checkOutput(output: string): void;
|
|
120
|
+
/** Clean up all timers. Must be called when the process exits. */
|
|
121
|
+
cleanup(): void;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const COMPLETE_MARKER_PATTERN = /<promise>COMPLETE<\/promise>/i;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Verify that the expected commit has been made.
|
|
128
|
+
* Checks: HEAD changed, commit message matches prefix, outcome file is committed.
|
|
129
|
+
*/
|
|
130
|
+
function verifyCommit(commitContext: CommitContext): boolean {
|
|
131
|
+
const currentHead = getHeadCommitHash();
|
|
132
|
+
if (!currentHead || currentHead === commitContext.preExecutionHead) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const message = getHeadCommitMessage();
|
|
137
|
+
if (!message || !message.startsWith(commitContext.expectedPrefix)) {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (!isFileCommittedInHead(commitContext.outcomeFilePath)) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function createCompletionDetector(
|
|
149
|
+
killFn: () => void,
|
|
150
|
+
outcomeFilePath?: string,
|
|
151
|
+
commitContext?: CommitContext,
|
|
152
|
+
): CompletionDetector {
|
|
153
|
+
let graceHandle: ReturnType<typeof setTimeout> | null = null;
|
|
154
|
+
let commitPollHandle: ReturnType<typeof setInterval> | null = null;
|
|
155
|
+
let hardMaxHandle: ReturnType<typeof setTimeout> | null = null;
|
|
156
|
+
let pollHandle: ReturnType<typeof setInterval> | null = null;
|
|
157
|
+
let initialMtime = 0;
|
|
158
|
+
let detectedMarkerIsComplete = false;
|
|
159
|
+
|
|
160
|
+
// Record initial mtime of outcome file to avoid false positives from previous runs
|
|
161
|
+
if (outcomeFilePath) {
|
|
162
|
+
try {
|
|
163
|
+
if (fs.existsSync(outcomeFilePath)) {
|
|
164
|
+
initialMtime = fs.statSync(outcomeFilePath).mtimeMs;
|
|
165
|
+
}
|
|
166
|
+
} catch {
|
|
167
|
+
// Ignore stat errors
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Called when the initial grace period expires.
|
|
173
|
+
* If commit verification is needed and the commit hasn't landed yet,
|
|
174
|
+
* start polling for the commit up to the hard maximum.
|
|
175
|
+
*/
|
|
176
|
+
function onGracePeriodExpired(): void {
|
|
177
|
+
if (commitContext && detectedMarkerIsComplete) {
|
|
178
|
+
// Check if commit already landed
|
|
179
|
+
if (verifyCommit(commitContext)) {
|
|
180
|
+
logger.debug('Grace period expired - commit verified, terminating Claude process');
|
|
181
|
+
killFn();
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Commit not found yet - extend with polling
|
|
186
|
+
logger.debug('Grace period expired but commit not verified - extending with polling');
|
|
187
|
+
const remainingMs = COMPLETION_HARD_MAX_MS - COMPLETION_GRACE_PERIOD_MS;
|
|
188
|
+
|
|
189
|
+
hardMaxHandle = setTimeout(() => {
|
|
190
|
+
logger.warn('Hard maximum grace period reached without commit verification - terminating Claude process');
|
|
191
|
+
if (commitPollHandle) clearInterval(commitPollHandle);
|
|
192
|
+
killFn();
|
|
193
|
+
}, remainingMs);
|
|
194
|
+
|
|
195
|
+
commitPollHandle = setInterval(() => {
|
|
196
|
+
if (commitContext && verifyCommit(commitContext)) {
|
|
197
|
+
logger.debug('Commit verified during extended grace period - terminating Claude process');
|
|
198
|
+
if (commitPollHandle) clearInterval(commitPollHandle);
|
|
199
|
+
if (hardMaxHandle) clearTimeout(hardMaxHandle);
|
|
200
|
+
killFn();
|
|
201
|
+
}
|
|
202
|
+
}, COMMIT_POLL_INTERVAL_MS);
|
|
203
|
+
} else {
|
|
204
|
+
// No commit verification needed (FAILED marker or no context) - kill immediately
|
|
205
|
+
logger.debug('Grace period expired - terminating Claude process');
|
|
206
|
+
killFn();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function startGracePeriod(markerOutput: string): void {
|
|
211
|
+
if (graceHandle) return; // Already started
|
|
212
|
+
detectedMarkerIsComplete = COMPLETE_MARKER_PATTERN.test(markerOutput);
|
|
213
|
+
logger.debug('Completion marker detected - starting grace period before termination');
|
|
214
|
+
graceHandle = setTimeout(onGracePeriodExpired, COMPLETION_GRACE_PERIOD_MS);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function checkOutput(output: string): void {
|
|
218
|
+
if (!graceHandle && COMPLETION_MARKER_PATTERN.test(output)) {
|
|
219
|
+
startGracePeriod(output);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Start outcome file polling if path provided
|
|
224
|
+
if (outcomeFilePath) {
|
|
225
|
+
const filePath = outcomeFilePath;
|
|
226
|
+
pollHandle = setInterval(() => {
|
|
227
|
+
try {
|
|
228
|
+
if (!fs.existsSync(filePath)) return;
|
|
229
|
+
const stat = fs.statSync(filePath);
|
|
230
|
+
if (stat.mtimeMs <= initialMtime) return; // File unchanged from before execution
|
|
231
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
232
|
+
if (COMPLETION_MARKER_PATTERN.test(content)) {
|
|
233
|
+
startGracePeriod(content);
|
|
234
|
+
}
|
|
235
|
+
} catch {
|
|
236
|
+
// Ignore read errors - file may be mid-write
|
|
237
|
+
}
|
|
238
|
+
}, OUTCOME_POLL_INTERVAL_MS);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function cleanup(): void {
|
|
242
|
+
if (graceHandle) clearTimeout(graceHandle);
|
|
243
|
+
if (pollHandle) clearInterval(pollHandle);
|
|
244
|
+
if (commitPollHandle) clearInterval(commitPollHandle);
|
|
245
|
+
if (hardMaxHandle) clearTimeout(hardMaxHandle);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return { checkOutput, cleanup };
|
|
249
|
+
}
|
|
250
|
+
|
|
53
251
|
export class ClaudeRunner {
|
|
54
252
|
private activeProcess: pty.IPty | null = null;
|
|
55
253
|
private killed = false;
|
|
@@ -169,7 +367,7 @@ export class ClaudeRunner {
|
|
|
169
367
|
* - Default timeout is 60 minutes if not specified
|
|
170
368
|
*/
|
|
171
369
|
async run(prompt: string, options: ClaudeRunnerOptions = {}): Promise<RunResult> {
|
|
172
|
-
const { timeout = 60, cwd = process.cwd() } = options;
|
|
370
|
+
const { timeout = 60, cwd = process.cwd(), outcomeFilePath, commitContext } = options;
|
|
173
371
|
// Ensure timeout is a positive number, fallback to 60 minutes
|
|
174
372
|
const validatedTimeout = Number(timeout) > 0 ? Number(timeout) : 60;
|
|
175
373
|
const timeoutMs = validatedTimeout * 60 * 1000;
|
|
@@ -213,11 +411,21 @@ export class ClaudeRunner {
|
|
|
213
411
|
proc.kill('SIGTERM');
|
|
214
412
|
}, timeoutMs);
|
|
215
413
|
|
|
414
|
+
// Set up completion detection (stdout marker + outcome file polling)
|
|
415
|
+
const completionDetector = createCompletionDetector(
|
|
416
|
+
() => proc.kill('SIGTERM'),
|
|
417
|
+
outcomeFilePath,
|
|
418
|
+
commitContext,
|
|
419
|
+
);
|
|
420
|
+
|
|
216
421
|
// Collect stdout
|
|
217
422
|
proc.stdout.on('data', (data) => {
|
|
218
423
|
const text = data.toString();
|
|
219
424
|
output += text;
|
|
220
425
|
|
|
426
|
+
// Check for completion marker to start grace period
|
|
427
|
+
completionDetector.checkOutput(output);
|
|
428
|
+
|
|
221
429
|
// Check for context overflow
|
|
222
430
|
for (const pattern of CONTEXT_OVERFLOW_PATTERNS) {
|
|
223
431
|
if (pattern.test(text)) {
|
|
@@ -236,6 +444,7 @@ export class ClaudeRunner {
|
|
|
236
444
|
|
|
237
445
|
proc.on('close', (exitCode) => {
|
|
238
446
|
clearTimeout(timeoutHandle);
|
|
447
|
+
completionDetector.cleanup();
|
|
239
448
|
this.activeProcess = null;
|
|
240
449
|
|
|
241
450
|
if (stderr) {
|
|
@@ -254,7 +463,8 @@ export class ClaudeRunner {
|
|
|
254
463
|
|
|
255
464
|
/**
|
|
256
465
|
* Run Claude non-interactively with verbose output to stdout.
|
|
257
|
-
* Uses
|
|
466
|
+
* Uses --output-format stream-json --verbose to get real-time streaming
|
|
467
|
+
* of tool calls, file operations, and thinking steps.
|
|
258
468
|
*
|
|
259
469
|
* TIMEOUT BEHAVIOR:
|
|
260
470
|
* - The timeout is applied per individual call to this method
|
|
@@ -264,7 +474,7 @@ export class ClaudeRunner {
|
|
|
264
474
|
* - Default timeout is 60 minutes if not specified
|
|
265
475
|
*/
|
|
266
476
|
async runVerbose(prompt: string, options: ClaudeRunnerOptions = {}): Promise<RunResult> {
|
|
267
|
-
const { timeout = 60, cwd = process.cwd() } = options;
|
|
477
|
+
const { timeout = 60, cwd = process.cwd(), outcomeFilePath, commitContext } = options;
|
|
268
478
|
// Ensure timeout is a positive number, fallback to 60 minutes
|
|
269
479
|
const validatedTimeout = Number(timeout) > 0 ? Number(timeout) : 60;
|
|
270
480
|
const timeoutMs = validatedTimeout * 60 * 1000;
|
|
@@ -277,13 +487,13 @@ export class ClaudeRunner {
|
|
|
277
487
|
|
|
278
488
|
const claudePath = getClaudePath();
|
|
279
489
|
|
|
280
|
-
logger.debug(`Starting Claude execution session (verbose) with model: ${this.model}`);
|
|
490
|
+
logger.debug(`Starting Claude execution session (verbose/stream-json) with model: ${this.model}`);
|
|
281
491
|
logger.debug(`Prompt length: ${prompt.length}, timeout: ${timeoutMs}ms, cwd: ${cwd}`);
|
|
282
492
|
logger.debug(`Claude path: ${claudePath}`);
|
|
283
493
|
|
|
284
494
|
logger.debug('Spawning process...');
|
|
285
|
-
// Use --
|
|
286
|
-
//
|
|
495
|
+
// Use --output-format stream-json --verbose to get real-time streaming events
|
|
496
|
+
// including tool calls, file operations, and intermediate output.
|
|
287
497
|
// --dangerously-skip-permissions bypasses interactive prompts
|
|
288
498
|
// -p enables print mode (non-interactive)
|
|
289
499
|
const proc = spawn(claudePath, [
|
|
@@ -292,6 +502,9 @@ export class ClaudeRunner {
|
|
|
292
502
|
this.model,
|
|
293
503
|
'--append-system-prompt',
|
|
294
504
|
prompt,
|
|
505
|
+
'--output-format',
|
|
506
|
+
'stream-json',
|
|
507
|
+
'--verbose',
|
|
295
508
|
'-p',
|
|
296
509
|
'Execute the task as described in the system prompt.',
|
|
297
510
|
], {
|
|
@@ -311,24 +524,52 @@ export class ClaudeRunner {
|
|
|
311
524
|
proc.kill('SIGTERM');
|
|
312
525
|
}, timeoutMs);
|
|
313
526
|
|
|
314
|
-
//
|
|
527
|
+
// Set up completion detection (stdout marker + outcome file polling)
|
|
528
|
+
const completionDetector = createCompletionDetector(
|
|
529
|
+
() => proc.kill('SIGTERM'),
|
|
530
|
+
outcomeFilePath,
|
|
531
|
+
commitContext,
|
|
532
|
+
);
|
|
533
|
+
|
|
534
|
+
// Buffer for incomplete NDJSON lines (data chunks may split across line boundaries)
|
|
535
|
+
let lineBuffer = '';
|
|
315
536
|
let dataReceived = false;
|
|
537
|
+
|
|
316
538
|
proc.stdout.on('data', (data) => {
|
|
317
539
|
if (!dataReceived) {
|
|
318
540
|
logger.debug('First data chunk received');
|
|
319
541
|
dataReceived = true;
|
|
320
542
|
}
|
|
321
|
-
const text = data.toString();
|
|
322
|
-
output += text;
|
|
323
|
-
process.stdout.write(text);
|
|
324
543
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
544
|
+
lineBuffer += data.toString();
|
|
545
|
+
|
|
546
|
+
// Process complete lines from the NDJSON stream
|
|
547
|
+
let newlineIndex: number;
|
|
548
|
+
while ((newlineIndex = lineBuffer.indexOf('\n')) !== -1) {
|
|
549
|
+
const line = lineBuffer.substring(0, newlineIndex);
|
|
550
|
+
lineBuffer = lineBuffer.substring(newlineIndex + 1);
|
|
551
|
+
|
|
552
|
+
const { display, textContent } = renderStreamEvent(line);
|
|
553
|
+
|
|
554
|
+
if (textContent) {
|
|
555
|
+
output += textContent;
|
|
556
|
+
|
|
557
|
+
// Check for completion marker to start grace period
|
|
558
|
+
completionDetector.checkOutput(output);
|
|
559
|
+
|
|
560
|
+
// Check for context overflow
|
|
561
|
+
for (const pattern of CONTEXT_OVERFLOW_PATTERNS) {
|
|
562
|
+
if (pattern.test(textContent)) {
|
|
563
|
+
contextOverflow = true;
|
|
564
|
+
logger.warn('Context overflow detected');
|
|
565
|
+
proc.kill('SIGTERM');
|
|
566
|
+
break;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
if (display) {
|
|
572
|
+
process.stdout.write(display);
|
|
332
573
|
}
|
|
333
574
|
}
|
|
334
575
|
});
|
|
@@ -339,7 +580,19 @@ export class ClaudeRunner {
|
|
|
339
580
|
});
|
|
340
581
|
|
|
341
582
|
proc.on('close', (exitCode) => {
|
|
583
|
+
// Process any remaining data in the line buffer
|
|
584
|
+
if (lineBuffer.trim()) {
|
|
585
|
+
const { display, textContent } = renderStreamEvent(lineBuffer);
|
|
586
|
+
if (textContent) {
|
|
587
|
+
output += textContent;
|
|
588
|
+
}
|
|
589
|
+
if (display) {
|
|
590
|
+
process.stdout.write(display);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
342
594
|
clearTimeout(timeoutHandle);
|
|
595
|
+
completionDetector.cleanup();
|
|
343
596
|
this.activeProcess = null;
|
|
344
597
|
logger.debug(`Claude exited with code ${exitCode}, output length: ${output.length}, timedOut: ${timedOut}, contextOverflow: ${contextOverflow}`);
|
|
345
598
|
|
package/src/core/git.ts
CHANGED
|
@@ -12,9 +12,9 @@ export interface GitStatus {
|
|
|
12
12
|
/**
|
|
13
13
|
* Check if we're in a git repository.
|
|
14
14
|
*/
|
|
15
|
-
export function isGitRepo(): boolean {
|
|
15
|
+
export function isGitRepo(cwd?: string): boolean {
|
|
16
16
|
try {
|
|
17
|
-
execSync('git rev-parse --is-inside-work-tree', { encoding: 'utf-8', stdio: 'pipe' });
|
|
17
|
+
execSync('git rev-parse --is-inside-work-tree', { encoding: 'utf-8', stdio: 'pipe', ...(cwd ? { cwd } : {}) });
|
|
18
18
|
return true;
|
|
19
19
|
} catch {
|
|
20
20
|
return false;
|
|
@@ -58,9 +58,9 @@ export function getGitStatus(): GitStatus {
|
|
|
58
58
|
/**
|
|
59
59
|
* Check if there are uncommitted changes.
|
|
60
60
|
*/
|
|
61
|
-
export function hasUncommittedChanges(): boolean {
|
|
61
|
+
export function hasUncommittedChanges(cwd?: string): boolean {
|
|
62
62
|
try {
|
|
63
|
-
const status = execSync('git status --porcelain', { encoding: 'utf-8', stdio: 'pipe' });
|
|
63
|
+
const status = execSync('git status --porcelain', { encoding: 'utf-8', stdio: 'pipe', ...(cwd ? { cwd } : {}) });
|
|
64
64
|
return status.trim().length > 0;
|
|
65
65
|
} catch {
|
|
66
66
|
return false;
|
|
@@ -141,16 +141,16 @@ export function getChangedFiles(): string[] {
|
|
|
141
141
|
|
|
142
142
|
/**
|
|
143
143
|
* Stash uncommitted changes with a descriptive name.
|
|
144
|
-
* @param name - Name for the stash (e.g., "raf-001-task-
|
|
144
|
+
* @param name - Name for the stash (e.g., "raf-001-task-03-failed")
|
|
145
145
|
* @returns true if stash was created, false otherwise
|
|
146
146
|
*/
|
|
147
|
-
export function stashChanges(name: string): boolean {
|
|
148
|
-
if (!isGitRepo()) {
|
|
147
|
+
export function stashChanges(name: string, cwd?: string): boolean {
|
|
148
|
+
if (!isGitRepo(cwd)) {
|
|
149
149
|
logger.warn('Not in a git repository, skipping stash');
|
|
150
150
|
return false;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
if (!hasUncommittedChanges()) {
|
|
153
|
+
if (!hasUncommittedChanges(cwd)) {
|
|
154
154
|
logger.debug('No uncommitted changes to stash');
|
|
155
155
|
return false;
|
|
156
156
|
}
|
|
@@ -159,6 +159,7 @@ export function stashChanges(name: string): boolean {
|
|
|
159
159
|
execSync(`git stash push -m "${name.replace(/"/g, '\\"')}"`, {
|
|
160
160
|
encoding: 'utf-8',
|
|
161
161
|
stdio: 'pipe',
|
|
162
|
+
...(cwd ? { cwd } : {}),
|
|
162
163
|
});
|
|
163
164
|
return true;
|
|
164
165
|
} catch (error) {
|
|
@@ -167,16 +168,67 @@ export function stashChanges(name: string): boolean {
|
|
|
167
168
|
}
|
|
168
169
|
}
|
|
169
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Get the current HEAD commit hash.
|
|
173
|
+
* Returns null if not in a git repo or HEAD doesn't exist.
|
|
174
|
+
*/
|
|
175
|
+
export function getHeadCommitHash(cwd?: string): string | null {
|
|
176
|
+
try {
|
|
177
|
+
return execSync('git rev-parse HEAD', { encoding: 'utf-8', stdio: 'pipe', ...(cwd ? { cwd } : {}) }).trim() || null;
|
|
178
|
+
} catch {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Get the current HEAD commit message (first line only).
|
|
185
|
+
* Returns null if not in a git repo or HEAD doesn't exist.
|
|
186
|
+
*/
|
|
187
|
+
export function getHeadCommitMessage(): string | null {
|
|
188
|
+
try {
|
|
189
|
+
return execSync('git log -1 --format=%s', { encoding: 'utf-8', stdio: 'pipe' }).trim() || null;
|
|
190
|
+
} catch {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Check if a file is tracked in the HEAD commit.
|
|
197
|
+
* Returns true if the file appears in the latest commit's tree.
|
|
198
|
+
*/
|
|
199
|
+
export function isFileCommittedInHead(filePath: string): boolean {
|
|
200
|
+
try {
|
|
201
|
+
// Use git ls-tree to check if the file exists in HEAD
|
|
202
|
+
// We need the path relative to the repo root
|
|
203
|
+
const repoRoot = execSync('git rev-parse --show-toplevel', { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
204
|
+
const relativePath = path.relative(repoRoot, path.resolve(filePath));
|
|
205
|
+
const result = execSync(`git ls-tree HEAD -- "${relativePath.replace(/"/g, '\\"')}"`, {
|
|
206
|
+
encoding: 'utf-8',
|
|
207
|
+
stdio: 'pipe',
|
|
208
|
+
}).trim();
|
|
209
|
+
return result.length > 0;
|
|
210
|
+
} catch {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
170
215
|
/**
|
|
171
216
|
* Commit planning artifacts (input.md and decisions.md) for a project.
|
|
172
217
|
* Uses commit message format: RAF[NNN] Plan: project-name
|
|
218
|
+
* For amendments: RAF[NNN] Amend: project-name
|
|
173
219
|
*
|
|
174
220
|
* @param projectPath - Full path to the project folder (e.g., /path/to/RAF/017-decision-vault)
|
|
221
|
+
* @param options - Optional settings
|
|
222
|
+
* @param options.cwd - Working directory for git commands (worktree support)
|
|
223
|
+
* @param options.additionalFiles - Extra file paths to stage (e.g., plan files for amend)
|
|
224
|
+
* @param options.isAmend - Use "Amend:" prefix instead of "Plan:" in commit message
|
|
175
225
|
* @returns Promise that resolves when commit is complete (or fails silently)
|
|
176
226
|
*/
|
|
177
|
-
export async function commitPlanningArtifacts(projectPath: string): Promise<void> {
|
|
227
|
+
export async function commitPlanningArtifacts(projectPath: string, options?: { cwd?: string; additionalFiles?: string[]; isAmend?: boolean }): Promise<void> {
|
|
228
|
+
const execCwd = options?.cwd;
|
|
229
|
+
|
|
178
230
|
// Check if we're in a git repository
|
|
179
|
-
if (!isGitRepo()) {
|
|
231
|
+
if (!isGitRepo(execCwd)) {
|
|
180
232
|
logger.warn('Not in a git repository, skipping planning artifacts commit');
|
|
181
233
|
return;
|
|
182
234
|
}
|
|
@@ -190,25 +242,52 @@ export async function commitPlanningArtifacts(projectPath: string): Promise<void
|
|
|
190
242
|
return;
|
|
191
243
|
}
|
|
192
244
|
|
|
193
|
-
// Build file paths
|
|
245
|
+
// Build absolute file paths
|
|
194
246
|
const inputFile = path.join(projectPath, 'input.md');
|
|
195
247
|
const decisionsFile = path.join(projectPath, 'decisions.md');
|
|
196
248
|
|
|
197
249
|
// Build commit message
|
|
198
|
-
const
|
|
250
|
+
const prefix = options?.isAmend ? 'Amend' : 'Plan';
|
|
251
|
+
const commitMessage = `RAF[${projectNumber}] ${prefix}: ${projectName}`;
|
|
252
|
+
|
|
253
|
+
// Build list of files to stage (absolute paths)
|
|
254
|
+
const absoluteFiles = [inputFile, decisionsFile, ...(options?.additionalFiles ?? [])];
|
|
255
|
+
|
|
256
|
+
// Convert to relative paths when cwd is provided (worktree mode).
|
|
257
|
+
// Git resolves paths relative to the working directory. Using relative paths
|
|
258
|
+
// avoids issues with symlink resolution (e.g., /tmp → /private/tmp on macOS)
|
|
259
|
+
// that can cause absolute paths to not match git's internal worktree paths.
|
|
260
|
+
const filesToStage = execCwd
|
|
261
|
+
? absoluteFiles.map(f => path.relative(execCwd, f))
|
|
262
|
+
: absoluteFiles;
|
|
263
|
+
|
|
264
|
+
// Stage each file individually so one missing file doesn't block the others
|
|
265
|
+
let stagedCount = 0;
|
|
266
|
+
for (const file of filesToStage) {
|
|
267
|
+
try {
|
|
268
|
+
execSync(`git add -- "${file}"`, {
|
|
269
|
+
encoding: 'utf-8',
|
|
270
|
+
stdio: 'pipe',
|
|
271
|
+
...(execCwd ? { cwd: execCwd } : {}),
|
|
272
|
+
});
|
|
273
|
+
stagedCount++;
|
|
274
|
+
} catch (error) {
|
|
275
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
276
|
+
logger.warn(`Failed to stage ${file}: ${msg}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
199
279
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
encoding: 'utf-8',
|
|
205
|
-
stdio: 'pipe',
|
|
206
|
-
});
|
|
280
|
+
if (stagedCount === 0) {
|
|
281
|
+
logger.debug('No files were staged for planning artifacts commit');
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
207
284
|
|
|
285
|
+
try {
|
|
208
286
|
// Check if there's anything staged to commit
|
|
209
287
|
const stagedStatus = execSync('git diff --cached --name-only', {
|
|
210
288
|
encoding: 'utf-8',
|
|
211
289
|
stdio: 'pipe',
|
|
290
|
+
...(execCwd ? { cwd: execCwd } : {}),
|
|
212
291
|
}).trim();
|
|
213
292
|
|
|
214
293
|
if (!stagedStatus) {
|
|
@@ -220,6 +299,7 @@ export async function commitPlanningArtifacts(projectPath: string): Promise<void
|
|
|
220
299
|
execSync(`git commit -m "${commitMessage.replace(/"/g, '\\"')}"`, {
|
|
221
300
|
encoding: 'utf-8',
|
|
222
301
|
stdio: 'pipe',
|
|
302
|
+
...(execCwd ? { cwd: execCwd } : {}),
|
|
223
303
|
});
|
|
224
304
|
|
|
225
305
|
logger.debug(`Committed planning artifacts: ${commitMessage}`);
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
getDecisionsPath,
|
|
12
12
|
getInputPath,
|
|
13
13
|
listProjects,
|
|
14
|
+
TASK_ID_PATTERN,
|
|
14
15
|
} from '../utils/paths.js';
|
|
15
16
|
import { sanitizeProjectName } from '../utils/validation.js';
|
|
16
17
|
import { logger } from '../utils/logger.js';
|
|
@@ -145,7 +146,7 @@ export class ProjectManager {
|
|
|
145
146
|
const files = fs.readdirSync(outcomesDir).filter((f) => f.endsWith('.md')).sort();
|
|
146
147
|
|
|
147
148
|
for (const file of files) {
|
|
148
|
-
const match = file.match(
|
|
149
|
+
const match = file.match(new RegExp(`^(${TASK_ID_PATTERN})-`));
|
|
149
150
|
if (match && match[1]) {
|
|
150
151
|
const content = fs.readFileSync(path.join(outcomesDir, file), 'utf-8');
|
|
151
152
|
outcomes.push({ taskId: match[1], content });
|