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
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
import { execSync, spawn } from 'node:child_process';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as os from 'node:os';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
import { logger } from '../utils/logger.js';
|
|
6
|
+
import { extractProjectName, getInputPath, getDecisionsPath, getOutcomesDir, TASK_ID_PATTERN } from '../utils/paths.js';
|
|
7
|
+
|
|
8
|
+
export interface PrCreateResult {
|
|
9
|
+
success: boolean;
|
|
10
|
+
prUrl?: string;
|
|
11
|
+
error?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface PrPreflightResult {
|
|
15
|
+
ready: boolean;
|
|
16
|
+
ghInstalled: boolean;
|
|
17
|
+
ghAuthenticated: boolean;
|
|
18
|
+
isGitHubRemote: boolean;
|
|
19
|
+
branchPushed: boolean;
|
|
20
|
+
error?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Check if the `gh` CLI is installed.
|
|
25
|
+
*/
|
|
26
|
+
export function isGhInstalled(): boolean {
|
|
27
|
+
try {
|
|
28
|
+
execSync('gh --version', { encoding: 'utf-8', stdio: 'pipe' });
|
|
29
|
+
return true;
|
|
30
|
+
} catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Check if the `gh` CLI is authenticated.
|
|
37
|
+
*/
|
|
38
|
+
export function isGhAuthenticated(): boolean {
|
|
39
|
+
try {
|
|
40
|
+
execSync('gh auth status', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
41
|
+
return true;
|
|
42
|
+
} catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Check if the git remote is a GitHub repository.
|
|
49
|
+
*/
|
|
50
|
+
export function isGitHubRemote(cwd?: string): boolean {
|
|
51
|
+
try {
|
|
52
|
+
const remoteUrl = execSync('git remote get-url origin', {
|
|
53
|
+
encoding: 'utf-8',
|
|
54
|
+
stdio: 'pipe',
|
|
55
|
+
...(cwd ? { cwd } : {}),
|
|
56
|
+
}).trim();
|
|
57
|
+
return remoteUrl.includes('github.com');
|
|
58
|
+
} catch {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Push the current branch to the remote origin.
|
|
65
|
+
* Returns true if the push succeeds.
|
|
66
|
+
*/
|
|
67
|
+
export function pushBranch(branch: string, cwd?: string): boolean {
|
|
68
|
+
try {
|
|
69
|
+
execSync(`git push -u origin "${branch}"`, {
|
|
70
|
+
encoding: 'utf-8',
|
|
71
|
+
stdio: 'pipe',
|
|
72
|
+
...(cwd ? { cwd } : {}),
|
|
73
|
+
});
|
|
74
|
+
return true;
|
|
75
|
+
} catch {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Check if the branch has been pushed to the remote.
|
|
82
|
+
*/
|
|
83
|
+
export function isBranchPushed(branch: string, cwd?: string): boolean {
|
|
84
|
+
try {
|
|
85
|
+
const output = execSync(`git ls-remote --heads origin "${branch}"`, {
|
|
86
|
+
encoding: 'utf-8',
|
|
87
|
+
stdio: 'pipe',
|
|
88
|
+
...(cwd ? { cwd } : {}),
|
|
89
|
+
}).trim();
|
|
90
|
+
return output.length > 0;
|
|
91
|
+
} catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Detect the base branch for a PR.
|
|
98
|
+
* Returns the branch from which the worktree was forked (typically main or master).
|
|
99
|
+
*/
|
|
100
|
+
export function detectBaseBranch(cwd?: string): string | null {
|
|
101
|
+
// Try to find the default branch from the remote
|
|
102
|
+
try {
|
|
103
|
+
const output = execSync('git symbolic-ref refs/remotes/origin/HEAD', {
|
|
104
|
+
encoding: 'utf-8',
|
|
105
|
+
stdio: 'pipe',
|
|
106
|
+
...(cwd ? { cwd } : {}),
|
|
107
|
+
}).trim();
|
|
108
|
+
// Output is like "refs/remotes/origin/main"
|
|
109
|
+
const parts = output.split('/');
|
|
110
|
+
return parts[parts.length - 1] ?? null;
|
|
111
|
+
} catch {
|
|
112
|
+
// Fallback: check for common branch names
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Try common default branches
|
|
116
|
+
for (const branch of ['main', 'master']) {
|
|
117
|
+
try {
|
|
118
|
+
execSync(`git rev-parse --verify "refs/heads/${branch}"`, {
|
|
119
|
+
encoding: 'utf-8',
|
|
120
|
+
stdio: 'pipe',
|
|
121
|
+
...(cwd ? { cwd } : {}),
|
|
122
|
+
});
|
|
123
|
+
return branch;
|
|
124
|
+
} catch {
|
|
125
|
+
// Try next
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Run preflight checks for PR creation.
|
|
134
|
+
* Returns detailed status of each prerequisite.
|
|
135
|
+
*/
|
|
136
|
+
export function prPreflight(branch: string, cwd?: string): PrPreflightResult {
|
|
137
|
+
const result: PrPreflightResult = {
|
|
138
|
+
ready: false,
|
|
139
|
+
ghInstalled: false,
|
|
140
|
+
ghAuthenticated: false,
|
|
141
|
+
isGitHubRemote: false,
|
|
142
|
+
branchPushed: false,
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
result.ghInstalled = isGhInstalled();
|
|
146
|
+
if (!result.ghInstalled) {
|
|
147
|
+
result.error = 'GitHub CLI (gh) is not installed. Install it from https://cli.github.com/';
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
result.ghAuthenticated = isGhAuthenticated();
|
|
152
|
+
if (!result.ghAuthenticated) {
|
|
153
|
+
result.error = 'GitHub CLI is not authenticated. Run `gh auth login` to authenticate.';
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
result.isGitHubRemote = isGitHubRemote(cwd);
|
|
158
|
+
if (!result.isGitHubRemote) {
|
|
159
|
+
result.error = 'The git remote is not a GitHub repository. PR creation requires a GitHub remote.';
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
result.branchPushed = isBranchPushed(branch, cwd);
|
|
164
|
+
// Branch not pushed is not a blocker - we'll push it
|
|
165
|
+
|
|
166
|
+
result.ready = true;
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Generate a human-readable PR title from the project folder name.
|
|
172
|
+
* E.g., "021b5g-merge-guardian" -> "Merge guardian"
|
|
173
|
+
*/
|
|
174
|
+
export function generatePrTitle(projectPath: string): string {
|
|
175
|
+
const name = extractProjectName(projectPath);
|
|
176
|
+
if (!name) {
|
|
177
|
+
return 'Feature branch';
|
|
178
|
+
}
|
|
179
|
+
// Convert kebab-case to space-separated, capitalize first letter
|
|
180
|
+
const words = name.split('-');
|
|
181
|
+
words[0] = words[0]!.charAt(0).toUpperCase() + words[0]!.slice(1);
|
|
182
|
+
return words.join(' ');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Read project context for PR body generation.
|
|
187
|
+
* Gathers input.md, decisions.md, and outcome files.
|
|
188
|
+
*/
|
|
189
|
+
export function readProjectContext(projectPath: string): {
|
|
190
|
+
input: string | null;
|
|
191
|
+
decisions: string | null;
|
|
192
|
+
outcomes: Array<{ taskId: string; content: string }>;
|
|
193
|
+
} {
|
|
194
|
+
let input: string | null = null;
|
|
195
|
+
let decisions: string | null = null;
|
|
196
|
+
const outcomes: Array<{ taskId: string; content: string }> = [];
|
|
197
|
+
|
|
198
|
+
const inputPath = getInputPath(projectPath);
|
|
199
|
+
if (fs.existsSync(inputPath)) {
|
|
200
|
+
input = fs.readFileSync(inputPath, 'utf-8');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const decisionsPath = getDecisionsPath(projectPath);
|
|
204
|
+
if (fs.existsSync(decisionsPath)) {
|
|
205
|
+
decisions = fs.readFileSync(decisionsPath, 'utf-8');
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const outcomesDir = getOutcomesDir(projectPath);
|
|
209
|
+
if (fs.existsSync(outcomesDir)) {
|
|
210
|
+
const files = fs.readdirSync(outcomesDir).filter(f => f.endsWith('.md')).sort();
|
|
211
|
+
const taskIdPattern = new RegExp(`^(${TASK_ID_PATTERN})-`);
|
|
212
|
+
for (const file of files) {
|
|
213
|
+
const match = file.match(taskIdPattern);
|
|
214
|
+
if (match && match[1]) {
|
|
215
|
+
const content = fs.readFileSync(path.join(outcomesDir, file), 'utf-8');
|
|
216
|
+
outcomes.push({ taskId: match[1], content });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return { input, decisions, outcomes };
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Generate a PR body by calling Claude Sonnet to summarize project context.
|
|
226
|
+
* Falls back to a simple body if Claude is unavailable.
|
|
227
|
+
*/
|
|
228
|
+
export async function generatePrBody(
|
|
229
|
+
projectPath: string,
|
|
230
|
+
timeoutMs: number = 120000,
|
|
231
|
+
): Promise<string> {
|
|
232
|
+
const context = readProjectContext(projectPath);
|
|
233
|
+
|
|
234
|
+
// Build context for Claude
|
|
235
|
+
const parts: string[] = [];
|
|
236
|
+
|
|
237
|
+
if (context.input) {
|
|
238
|
+
parts.push(`## Project Input\n${context.input}`);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (context.decisions) {
|
|
242
|
+
parts.push(`## Key Decisions\n${context.decisions}`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (context.outcomes.length > 0) {
|
|
246
|
+
const outcomeSummaries = context.outcomes.map(o => {
|
|
247
|
+
// Truncate long outcomes
|
|
248
|
+
const truncated = o.content.length > 1000
|
|
249
|
+
? o.content.slice(0, 1000) + '\n...(truncated)'
|
|
250
|
+
: o.content;
|
|
251
|
+
return `### Task ${o.taskId}\n${truncated}`;
|
|
252
|
+
}).join('\n\n');
|
|
253
|
+
parts.push(`## Task Outcomes\n${outcomeSummaries}`);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (parts.length === 0) {
|
|
257
|
+
return generateFallbackBody(projectPath);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const projectContext = parts.join('\n\n');
|
|
261
|
+
|
|
262
|
+
const prompt = `You are generating a Pull Request description for a GitHub PR. Use the project context below to produce a clean, well-structured PR body.
|
|
263
|
+
|
|
264
|
+
${projectContext}
|
|
265
|
+
|
|
266
|
+
Respond with ONLY the PR body in this exact format (no extra text, no code fences):
|
|
267
|
+
|
|
268
|
+
## Summary
|
|
269
|
+
[Proofread, clean version of the project requirements from the input — 2-5 sentences describing what this PR accomplishes and why]
|
|
270
|
+
|
|
271
|
+
## Key Decisions
|
|
272
|
+
[The most important design decisions that were made — only include significant ones, not every detail. Use bullet points.]
|
|
273
|
+
|
|
274
|
+
## What Was Done
|
|
275
|
+
[Clear outline of the completed work, organized by task or area. Use bullet points.]
|
|
276
|
+
|
|
277
|
+
## Test Plan
|
|
278
|
+
[1-3 bullet points describing how to verify these changes work correctly]`;
|
|
279
|
+
|
|
280
|
+
try {
|
|
281
|
+
const body = await callClaudeForPrBody(prompt, timeoutMs);
|
|
282
|
+
return body;
|
|
283
|
+
} catch (error) {
|
|
284
|
+
logger.debug(`PR body generation via Claude failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
285
|
+
return generateFallbackBody(projectPath);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Generate a simple fallback PR body when Claude is unavailable.
|
|
291
|
+
*/
|
|
292
|
+
function generateFallbackBody(projectPath: string): string {
|
|
293
|
+
const context = readProjectContext(projectPath);
|
|
294
|
+
const lines: string[] = ['## Summary'];
|
|
295
|
+
|
|
296
|
+
if (context.input) {
|
|
297
|
+
const firstLine = context.input.split('\n').find(l => l.trim() && !l.startsWith('#'));
|
|
298
|
+
if (firstLine) {
|
|
299
|
+
lines.push(firstLine.trim());
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
lines.push('');
|
|
304
|
+
lines.push('## Key Decisions');
|
|
305
|
+
if (context.decisions) {
|
|
306
|
+
const firstDecision = context.decisions.split('\n').find(l => l.trim() && !l.startsWith('#'));
|
|
307
|
+
if (firstDecision) {
|
|
308
|
+
lines.push(`- ${firstDecision.trim()}`);
|
|
309
|
+
}
|
|
310
|
+
} else {
|
|
311
|
+
lines.push('- No decisions recorded');
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
lines.push('');
|
|
315
|
+
lines.push('## What Was Done');
|
|
316
|
+
if (context.outcomes.length > 0) {
|
|
317
|
+
lines.push(`- ${context.outcomes.length} task(s) completed`);
|
|
318
|
+
} else {
|
|
319
|
+
lines.push('- No tasks completed yet');
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
lines.push('');
|
|
323
|
+
lines.push('## Test Plan');
|
|
324
|
+
lines.push('- Review the changes and verify correctness');
|
|
325
|
+
|
|
326
|
+
return lines.join('\n');
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Filter Claude CLI output to remove non-markdown log/warning lines.
|
|
331
|
+
* Claude CLI stdout may include warning or progress lines mixed with the response.
|
|
332
|
+
*/
|
|
333
|
+
export function filterClaudeOutput(output: string): string {
|
|
334
|
+
const lines = output.split('\n');
|
|
335
|
+
const filtered = lines.filter(line => {
|
|
336
|
+
const trimmed = line.trim();
|
|
337
|
+
// Skip empty lines at the boundary (we'll let markdown's own blank lines through)
|
|
338
|
+
if (!trimmed) return true;
|
|
339
|
+
// Skip common log/warning patterns
|
|
340
|
+
if (/^(⚠|⚡|🔄|⏳|✓|✗|›|>)\s/.test(trimmed)) return false;
|
|
341
|
+
if (/^\[?(warn|warning|info|debug|error|log)\]?[:\s]/i.test(trimmed)) return false;
|
|
342
|
+
if (/^console\.(warn|log|error|info)/i.test(trimmed)) return false;
|
|
343
|
+
if (/^Note:/i.test(trimmed)) return false;
|
|
344
|
+
if (/^(Loading|Connecting|Fetching|Processing)\b/i.test(trimmed)) return false;
|
|
345
|
+
return true;
|
|
346
|
+
});
|
|
347
|
+
return filtered.join('\n').trim();
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Call Claude Sonnet to generate a PR body.
|
|
352
|
+
*/
|
|
353
|
+
async function callClaudeForPrBody(prompt: string, timeoutMs: number): Promise<string> {
|
|
354
|
+
let claudePath: string;
|
|
355
|
+
try {
|
|
356
|
+
claudePath = execSync('which claude', { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
357
|
+
} catch {
|
|
358
|
+
throw new Error('Claude CLI not found');
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
return new Promise((resolve, reject) => {
|
|
362
|
+
let output = '';
|
|
363
|
+
let stderr = '';
|
|
364
|
+
|
|
365
|
+
const proc = spawn(claudePath, [
|
|
366
|
+
'--model', 'sonnet',
|
|
367
|
+
'--dangerously-skip-permissions',
|
|
368
|
+
'-p',
|
|
369
|
+
prompt,
|
|
370
|
+
], {
|
|
371
|
+
env: process.env,
|
|
372
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
const timeout = setTimeout(() => {
|
|
376
|
+
proc.kill('SIGTERM');
|
|
377
|
+
reject(new Error('PR body generation timed out'));
|
|
378
|
+
}, timeoutMs);
|
|
379
|
+
|
|
380
|
+
proc.stdout.on('data', (data) => {
|
|
381
|
+
output += data.toString();
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
proc.stderr.on('data', (data) => {
|
|
385
|
+
stderr += data.toString();
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
proc.on('close', (exitCode) => {
|
|
389
|
+
clearTimeout(timeout);
|
|
390
|
+
|
|
391
|
+
if (exitCode !== 0) {
|
|
392
|
+
reject(new Error(`Claude exited with code ${exitCode}: ${stderr}`));
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const filtered = filterClaudeOutput(output);
|
|
397
|
+
if (!filtered) {
|
|
398
|
+
reject(new Error('Claude returned empty output'));
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
resolve(filtered);
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
proc.on('error', (error) => {
|
|
406
|
+
clearTimeout(timeout);
|
|
407
|
+
reject(error);
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Create a GitHub Pull Request using the `gh` CLI.
|
|
414
|
+
*
|
|
415
|
+
* @param branch - The head branch (worktree branch name)
|
|
416
|
+
* @param projectPath - Path to the project folder (for context generation)
|
|
417
|
+
* @param options - Optional overrides
|
|
418
|
+
*/
|
|
419
|
+
export async function createPullRequest(
|
|
420
|
+
branch: string,
|
|
421
|
+
projectPath: string,
|
|
422
|
+
options?: {
|
|
423
|
+
baseBranch?: string;
|
|
424
|
+
title?: string;
|
|
425
|
+
cwd?: string;
|
|
426
|
+
},
|
|
427
|
+
): Promise<PrCreateResult> {
|
|
428
|
+
const cwd = options?.cwd;
|
|
429
|
+
|
|
430
|
+
// Run preflight checks
|
|
431
|
+
const preflight = prPreflight(branch, cwd);
|
|
432
|
+
if (!preflight.ready) {
|
|
433
|
+
return { success: false, error: preflight.error };
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Detect base branch
|
|
437
|
+
const baseBranch = options?.baseBranch ?? detectBaseBranch(cwd);
|
|
438
|
+
if (!baseBranch) {
|
|
439
|
+
return { success: false, error: 'Could not detect base branch. Specify it explicitly.' };
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// Push branch if not already pushed
|
|
443
|
+
if (!preflight.branchPushed) {
|
|
444
|
+
logger.info(`Pushing branch "${branch}" to origin...`);
|
|
445
|
+
const pushed = pushBranch(branch, cwd);
|
|
446
|
+
if (!pushed) {
|
|
447
|
+
return { success: false, error: `Failed to push branch "${branch}" to origin.` };
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Generate PR title
|
|
452
|
+
const title = options?.title ?? generatePrTitle(projectPath);
|
|
453
|
+
|
|
454
|
+
// Generate PR body
|
|
455
|
+
const body = await generatePrBody(projectPath);
|
|
456
|
+
|
|
457
|
+
// Write body to temp file to avoid shell escaping issues
|
|
458
|
+
const bodyFile = path.join(os.tmpdir(), `raf-pr-body-${Date.now()}.md`);
|
|
459
|
+
try {
|
|
460
|
+
fs.writeFileSync(bodyFile, body, 'utf-8');
|
|
461
|
+
|
|
462
|
+
const result = execSync(
|
|
463
|
+
`gh pr create --title "${title.replace(/"/g, '\\"')}" --base "${baseBranch}" --head "${branch}" --body-file "${bodyFile}"`,
|
|
464
|
+
{
|
|
465
|
+
encoding: 'utf-8',
|
|
466
|
+
stdio: 'pipe',
|
|
467
|
+
...(cwd ? { cwd } : {}),
|
|
468
|
+
},
|
|
469
|
+
);
|
|
470
|
+
|
|
471
|
+
const prUrl = result.trim();
|
|
472
|
+
return { success: true, prUrl };
|
|
473
|
+
} catch (error) {
|
|
474
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
475
|
+
return { success: false, error: `Failed to create PR: ${msg}` };
|
|
476
|
+
} finally {
|
|
477
|
+
// Clean up temp file
|
|
478
|
+
try { fs.unlinkSync(bodyFile); } catch { /* ignore */ }
|
|
479
|
+
}
|
|
480
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
|
-
import { getPlansDir, getOutcomesDir, getInputPath } from '../utils/paths.js';
|
|
3
|
+
import { getPlansDir, getOutcomesDir, getInputPath, decodeBase26, TASK_ID_PATTERN } from '../utils/paths.js';
|
|
4
4
|
|
|
5
5
|
export type DerivedTaskStatus = 'pending' | 'completed' | 'failed' | 'blocked';
|
|
6
6
|
|
|
@@ -39,7 +39,7 @@ export interface DerivedStats {
|
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* Discover all projects in the RAF directory.
|
|
42
|
-
* Projects are directories matching the pattern
|
|
42
|
+
* Projects are directories matching the pattern XXXXXX-project-name (6-char base26 prefix).
|
|
43
43
|
*/
|
|
44
44
|
export function discoverProjects(rafDir: string): DiscoveredProject[] {
|
|
45
45
|
if (!fs.existsSync(rafDir)) {
|
|
@@ -51,13 +51,16 @@ export function discoverProjects(rafDir: string): DiscoveredProject[] {
|
|
|
51
51
|
|
|
52
52
|
for (const entry of entries) {
|
|
53
53
|
if (entry.isDirectory()) {
|
|
54
|
-
const match = entry.name.match(/^(
|
|
54
|
+
const match = entry.name.match(/^([a-z]{6})-(.+)$/i);
|
|
55
55
|
if (match && match[1] && match[2]) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
const decoded = decodeBase26(match[1].toLowerCase());
|
|
57
|
+
if (decoded !== null) {
|
|
58
|
+
projects.push({
|
|
59
|
+
number: decoded,
|
|
60
|
+
name: match[2],
|
|
61
|
+
path: path.join(rafDir, entry.name),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
61
64
|
}
|
|
62
65
|
}
|
|
63
66
|
}
|
|
@@ -67,7 +70,7 @@ export function discoverProjects(rafDir: string): DiscoveredProject[] {
|
|
|
67
70
|
|
|
68
71
|
/**
|
|
69
72
|
* Parse the Dependencies section from plan file content.
|
|
70
|
-
* Format: `## Dependencies\
|
|
73
|
+
* Format: `## Dependencies\n01, 02` → ["01", "02"]
|
|
71
74
|
* Returns empty array if no Dependencies section exists.
|
|
72
75
|
*/
|
|
73
76
|
export function parseDependencies(content: string): string[] {
|
|
@@ -81,11 +84,12 @@ export function parseDependencies(content: string): string[] {
|
|
|
81
84
|
return [];
|
|
82
85
|
}
|
|
83
86
|
|
|
84
|
-
// Parse comma-separated task IDs
|
|
87
|
+
// Parse comma-separated task IDs (2-char base36)
|
|
88
|
+
const taskIdRegex = new RegExp(`^${TASK_ID_PATTERN}$`);
|
|
85
89
|
return dependenciesLine
|
|
86
90
|
.split(',')
|
|
87
91
|
.map((id) => id.trim())
|
|
88
|
-
.filter((id) =>
|
|
92
|
+
.filter((id) => taskIdRegex.test(id));
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
/**
|
|
@@ -175,7 +179,7 @@ export function deriveProjectStatus(
|
|
|
175
179
|
/**
|
|
176
180
|
* Derive project state from the folder structure.
|
|
177
181
|
* Scans plans/ for plan files and outcomes/ for outcome files.
|
|
178
|
-
* Matches them by task ID (
|
|
182
|
+
* Matches them by task ID (2-char base36 prefix for tasks) and determines status.
|
|
179
183
|
* Also parses dependencies and derives blocked status.
|
|
180
184
|
*/
|
|
181
185
|
export function deriveProjectState(projectPath: string): DerivedProjectState {
|
|
@@ -202,7 +206,7 @@ export function deriveProjectState(projectPath: string): DerivedProjectState {
|
|
|
202
206
|
.sort();
|
|
203
207
|
|
|
204
208
|
for (const outcomeFile of outcomeFiles) {
|
|
205
|
-
const match = outcomeFile.match(
|
|
209
|
+
const match = outcomeFile.match(new RegExp(`^(${TASK_ID_PATTERN})-`));
|
|
206
210
|
if (match && match[1]) {
|
|
207
211
|
const taskId = match[1];
|
|
208
212
|
const content = fs.readFileSync(path.join(outcomesDir, outcomeFile), 'utf-8');
|
|
@@ -216,7 +220,7 @@ export function deriveProjectState(projectPath: string): DerivedProjectState {
|
|
|
216
220
|
|
|
217
221
|
// First pass: Match plan files to outcomes and parse dependencies
|
|
218
222
|
for (const planFile of planFiles) {
|
|
219
|
-
const match = planFile.match(
|
|
223
|
+
const match = planFile.match(new RegExp(`^(${TASK_ID_PATTERN})-(.+)\\.md$`));
|
|
220
224
|
if (match && match[1]) {
|
|
221
225
|
const taskId = match[1];
|
|
222
226
|
const status = outcomeStatuses.get(taskId) ?? 'pending';
|