agentplane 0.3.9 → 0.3.11
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/assets/AGENTS.md +4 -2
- package/assets/agents/CODER.json +1 -1
- package/assets/policy/dod.core.md +1 -1
- package/assets/policy/governance.md +5 -3
- package/assets/policy/incidents.md +19 -77
- package/assets/policy/workflow.branch_pr.md +2 -0
- package/assets/policy/workflow.direct.md +3 -1
- package/bin/agentplane.js +56 -1
- package/bin/runtime-watch.js +1 -0
- package/bin/stale-dist-policy.d.ts +1 -1
- package/bin/stale-dist-policy.js +13 -0
- package/dist/.build-manifest.json +462 -202
- package/dist/cli/bootstrap-guide.d.ts +1 -0
- package/dist/cli/bootstrap-guide.d.ts.map +1 -1
- package/dist/cli/bootstrap-guide.js +20 -1
- package/dist/cli/command-guide.d.ts.map +1 -1
- package/dist/cli/command-guide.js +2 -1
- package/dist/cli/command-invocations.d.ts.map +1 -1
- package/dist/cli/command-invocations.js +6 -1
- package/dist/cli/command-snippets.d.ts +2 -0
- package/dist/cli/command-snippets.d.ts.map +1 -1
- package/dist/cli/command-snippets.js +2 -0
- package/dist/cli/run-cli/command-catalog/core.d.ts +1 -1
- package/dist/cli/run-cli/command-catalog/core.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog/core.js +10 -0
- package/dist/cli/run-cli/command-catalog/project.d.ts +1 -1
- package/dist/cli/run-cli/command-catalog/project.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog/project.js +3 -1
- package/dist/cli/run-cli/command-catalog/task.d.ts +1 -1
- package/dist/cli/run-cli/command-catalog/task.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog/task.js +10 -0
- package/dist/cli/run-cli/command-catalog.d.ts +1 -1
- package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/config.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/config.js +13 -0
- package/dist/cli/run-cli/commands/core/preflight.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/core/preflight.js +44 -1
- package/dist/cli/run-cli.js +2 -2
- package/dist/cli/run-cli.test-helpers.d.ts.map +1 -1
- package/dist/cli/run-cli.test-helpers.js +12 -0
- package/dist/commands/backend.d.ts.map +1 -1
- package/dist/commands/backend.js +4 -0
- package/dist/commands/branch/cleanup-merged.d.ts +2 -0
- package/dist/commands/branch/cleanup-merged.d.ts.map +1 -1
- package/dist/commands/branch/cleanup-merged.js +132 -28
- package/dist/commands/branch/work-start.d.ts.map +1 -1
- package/dist/commands/branch/work-start.js +60 -1
- package/dist/commands/cleanup/merged.command.d.ts +2 -0
- package/dist/commands/cleanup/merged.command.d.ts.map +1 -1
- package/dist/commands/cleanup/merged.command.js +24 -0
- package/dist/commands/doctor/branch-pr.d.ts +4 -0
- package/dist/commands/doctor/branch-pr.d.ts.map +1 -0
- package/dist/commands/doctor/branch-pr.js +96 -0
- package/dist/commands/doctor/fixes.d.ts +5 -0
- package/dist/commands/doctor/fixes.d.ts.map +1 -1
- package/dist/commands/doctor/fixes.js +70 -0
- package/dist/commands/doctor.run.d.ts.map +1 -1
- package/dist/commands/doctor.run.js +6 -1
- package/dist/commands/finish.run.d.ts.map +1 -1
- package/dist/commands/finish.run.js +11 -0
- package/dist/commands/finish.spec.d.ts +11 -0
- package/dist/commands/finish.spec.d.ts.map +1 -1
- package/dist/commands/finish.spec.js +51 -0
- package/dist/commands/guard/impl/close-message.d.ts.map +1 -1
- package/dist/commands/guard/impl/close-message.js +23 -6
- package/dist/commands/guard/impl/commands.d.ts.map +1 -1
- package/dist/commands/guard/impl/commands.js +24 -2
- package/dist/commands/guard/impl/env.d.ts +1 -0
- package/dist/commands/guard/impl/env.d.ts.map +1 -1
- package/dist/commands/guard/impl/env.js +1 -0
- package/dist/commands/hooks/index.d.ts.map +1 -1
- package/dist/commands/hooks/index.js +98 -1
- package/dist/commands/incidents/advise.command.d.ts +15 -0
- package/dist/commands/incidents/advise.command.d.ts.map +1 -0
- package/dist/commands/incidents/advise.command.js +139 -0
- package/dist/commands/incidents/collect.command.d.ts +11 -0
- package/dist/commands/incidents/collect.command.d.ts.map +1 -0
- package/dist/commands/incidents/collect.command.js +72 -0
- package/dist/commands/incidents/incidents.command.d.ts +5 -0
- package/dist/commands/incidents/incidents.command.d.ts.map +1 -0
- package/dist/commands/incidents/incidents.command.js +21 -0
- package/dist/commands/incidents/shared.d.ts +76 -0
- package/dist/commands/incidents/shared.d.ts.map +1 -0
- package/dist/commands/incidents/shared.js +261 -0
- package/dist/commands/pr/check.d.ts.map +1 -1
- package/dist/commands/pr/check.js +249 -75
- package/dist/commands/pr/close-superseded.d.ts +9 -0
- package/dist/commands/pr/close-superseded.d.ts.map +1 -0
- package/dist/commands/pr/close-superseded.js +129 -0
- package/dist/commands/pr/close.d.ts +11 -0
- package/dist/commands/pr/close.d.ts.map +1 -0
- package/dist/commands/pr/close.js +116 -0
- package/dist/commands/pr/index.d.ts +2 -0
- package/dist/commands/pr/index.d.ts.map +1 -1
- package/dist/commands/pr/index.js +2 -0
- package/dist/commands/pr/integrate/artifacts.d.ts +7 -0
- package/dist/commands/pr/integrate/artifacts.d.ts.map +1 -1
- package/dist/commands/pr/integrate/artifacts.js +66 -1
- package/dist/commands/pr/integrate/cmd.d.ts.map +1 -1
- package/dist/commands/pr/integrate/cmd.js +20 -0
- package/dist/commands/pr/integrate/internal/bootstrap-guidance.d.ts +8 -0
- package/dist/commands/pr/integrate/internal/bootstrap-guidance.d.ts.map +1 -0
- package/dist/commands/pr/integrate/internal/bootstrap-guidance.js +59 -0
- package/dist/commands/pr/integrate/internal/finalize.d.ts.map +1 -1
- package/dist/commands/pr/integrate/internal/finalize.js +40 -12
- package/dist/commands/pr/integrate/internal/merge.d.ts +4 -0
- package/dist/commands/pr/integrate/internal/merge.d.ts.map +1 -1
- package/dist/commands/pr/integrate/internal/merge.js +59 -15
- package/dist/commands/pr/integrate/internal/post-integrate-bootstrap.d.ts +13 -0
- package/dist/commands/pr/integrate/internal/post-integrate-bootstrap.d.ts.map +1 -0
- package/dist/commands/pr/integrate/internal/post-integrate-bootstrap.js +25 -0
- package/dist/commands/pr/integrate/internal/prepare.d.ts +3 -2
- package/dist/commands/pr/integrate/internal/prepare.d.ts.map +1 -1
- package/dist/commands/pr/integrate/internal/prepare.js +107 -19
- package/dist/commands/pr/internal/freshness.d.ts +20 -0
- package/dist/commands/pr/internal/freshness.d.ts.map +1 -0
- package/dist/commands/pr/internal/freshness.js +50 -0
- package/dist/commands/pr/internal/gh-api.d.ts +6 -0
- package/dist/commands/pr/internal/gh-api.d.ts.map +1 -0
- package/dist/commands/pr/internal/gh-api.js +80 -0
- package/dist/commands/pr/internal/note-store.d.ts +18 -0
- package/dist/commands/pr/internal/note-store.d.ts.map +1 -0
- package/dist/commands/pr/internal/note-store.js +66 -0
- package/dist/commands/pr/internal/pr-paths.d.ts +13 -0
- package/dist/commands/pr/internal/pr-paths.d.ts.map +1 -1
- package/dist/commands/pr/internal/pr-paths.js +13 -0
- package/dist/commands/pr/internal/review-template.d.ts +24 -4
- package/dist/commands/pr/internal/review-template.d.ts.map +1 -1
- package/dist/commands/pr/internal/review-template.js +221 -33
- package/dist/commands/pr/internal/sync.d.ts +41 -0
- package/dist/commands/pr/internal/sync.d.ts.map +1 -0
- package/dist/commands/pr/internal/sync.js +598 -0
- package/dist/commands/pr/note.d.ts.map +1 -1
- package/dist/commands/pr/note.js +37 -4
- package/dist/commands/pr/open.d.ts +1 -0
- package/dist/commands/pr/open.d.ts.map +1 -1
- package/dist/commands/pr/open.js +18 -54
- package/dist/commands/pr/pr.command.d.ts +15 -0
- package/dist/commands/pr/pr.command.d.ts.map +1 -1
- package/dist/commands/pr/pr.command.js +124 -5
- package/dist/commands/pr/update.d.ts.map +1 -1
- package/dist/commands/pr/update.js +58 -74
- package/dist/commands/recipes/impl/commands/cache-prune.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/cache-prune.js +14 -0
- package/dist/commands/recipes/impl/commands/install.js +1 -1
- package/dist/commands/recipes/impl/commands/list-remote.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/list-remote.js +1 -0
- package/dist/commands/recipes/impl/commands/remove.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/remove.js +9 -1
- package/dist/commands/release/apply.command.d.ts.map +1 -1
- package/dist/commands/release/apply.command.js +12 -17
- package/dist/commands/release/apply.preflight.d.ts.map +1 -1
- package/dist/commands/release/apply.preflight.js +1 -1
- package/dist/commands/shared/approval-requirements.d.ts +5 -7
- package/dist/commands/shared/approval-requirements.d.ts.map +1 -1
- package/dist/commands/shared/approval-requirements.js +3 -73
- package/dist/commands/shared/gh-transport.d.ts +16 -0
- package/dist/commands/shared/gh-transport.d.ts.map +1 -0
- package/dist/commands/shared/gh-transport.js +71 -0
- package/dist/commands/shared/git-diff.d.ts +3 -1
- package/dist/commands/shared/git-diff.d.ts.map +1 -1
- package/dist/commands/shared/git-diff.js +10 -2
- package/dist/commands/shared/git-ops.d.ts +1 -0
- package/dist/commands/shared/git-ops.d.ts.map +1 -1
- package/dist/commands/shared/git-ops.js +15 -0
- package/dist/commands/shared/git-worktree.d.ts +2 -0
- package/dist/commands/shared/git-worktree.d.ts.map +1 -1
- package/dist/commands/shared/git-worktree.js +22 -2
- package/dist/commands/shared/network-approval.d.ts +2 -0
- package/dist/commands/shared/network-approval.d.ts.map +1 -1
- package/dist/commands/shared/network-approval.js +1 -1
- package/dist/commands/shared/post-commit-pr-artifacts.d.ts +9 -0
- package/dist/commands/shared/post-commit-pr-artifacts.d.ts.map +1 -0
- package/dist/commands/shared/post-commit-pr-artifacts.js +22 -0
- package/dist/commands/shared/pr-meta.d.ts +29 -0
- package/dist/commands/shared/pr-meta.d.ts.map +1 -1
- package/dist/commands/shared/pr-meta.js +152 -3
- package/dist/commands/shared/task-backend.d.ts +9 -0
- package/dist/commands/shared/task-backend.d.ts.map +1 -1
- package/dist/commands/shared/task-backend.js +34 -22
- package/dist/commands/shared/task-local-freshness.d.ts +13 -0
- package/dist/commands/shared/task-local-freshness.d.ts.map +1 -0
- package/dist/commands/shared/task-local-freshness.js +20 -0
- package/dist/commands/shared/task-mutation.d.ts +2 -0
- package/dist/commands/shared/task-mutation.d.ts.map +1 -1
- package/dist/commands/shared/task-mutation.js +7 -0
- package/dist/commands/task/block.d.ts.map +1 -1
- package/dist/commands/task/block.js +1 -0
- package/dist/commands/task/close-duplicate.d.ts.map +1 -1
- package/dist/commands/task/close-duplicate.js +34 -1
- package/dist/commands/task/close-shared.d.ts.map +1 -1
- package/dist/commands/task/close-shared.js +1 -0
- package/dist/commands/task/derive.js +1 -1
- package/dist/commands/task/doc-template.d.ts.map +1 -1
- package/dist/commands/task/doc-template.js +7 -11
- package/dist/commands/task/findings-add.command.d.ts +20 -0
- package/dist/commands/task/findings-add.command.d.ts.map +1 -0
- package/dist/commands/task/findings-add.command.js +165 -0
- package/dist/commands/task/findings.command.d.ts +7 -0
- package/dist/commands/task/findings.command.d.ts.map +1 -0
- package/dist/commands/task/findings.command.js +20 -0
- package/dist/commands/task/findings.d.ts +63 -0
- package/dist/commands/task/findings.d.ts.map +1 -0
- package/dist/commands/task/findings.js +188 -0
- package/dist/commands/task/finish-shared.d.ts +1 -0
- package/dist/commands/task/finish-shared.d.ts.map +1 -1
- package/dist/commands/task/finish-shared.js +60 -3
- package/dist/commands/task/finish.d.ts +10 -0
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +143 -0
- package/dist/commands/task/hosted-close-pr.command.d.ts +11 -0
- package/dist/commands/task/hosted-close-pr.command.d.ts.map +1 -0
- package/dist/commands/task/hosted-close-pr.command.js +414 -0
- package/dist/commands/task/hosted-close.command.d.ts.map +1 -1
- package/dist/commands/task/hosted-close.command.js +49 -1
- package/dist/commands/task/hosted-merge-sync.d.ts +38 -0
- package/dist/commands/task/hosted-merge-sync.d.ts.map +1 -1
- package/dist/commands/task/hosted-merge-sync.js +249 -17
- package/dist/commands/task/index.d.ts +1 -0
- package/dist/commands/task/index.d.ts.map +1 -1
- package/dist/commands/task/index.js +1 -0
- package/dist/commands/task/new.d.ts +1 -0
- package/dist/commands/task/new.d.ts.map +1 -1
- package/dist/commands/task/new.js +140 -30
- package/dist/commands/task/new.spec.d.ts.map +1 -1
- package/dist/commands/task/new.spec.js +7 -0
- package/dist/commands/task/normalize.command.d.ts +2 -0
- package/dist/commands/task/normalize.command.d.ts.map +1 -1
- package/dist/commands/task/normalize.command.js +45 -0
- package/dist/commands/task/normalize.d.ts +2 -0
- package/dist/commands/task/normalize.d.ts.map +1 -1
- package/dist/commands/task/normalize.js +85 -8
- package/dist/commands/task/plan.d.ts.map +1 -1
- package/dist/commands/task/plan.js +7 -10
- package/dist/commands/task/set-status.d.ts.map +1 -1
- package/dist/commands/task/set-status.js +1 -0
- package/dist/commands/task/shared/docs.d.ts +6 -0
- package/dist/commands/task/shared/docs.d.ts.map +1 -1
- package/dist/commands/task/shared/docs.js +14 -0
- package/dist/commands/task/shared/transition-command.d.ts +2 -0
- package/dist/commands/task/shared/transition-command.d.ts.map +1 -1
- package/dist/commands/task/shared/transition-command.js +1 -0
- package/dist/commands/task/shared/transitions.d.ts.map +1 -1
- package/dist/commands/task/shared/transitions.js +11 -1
- package/dist/commands/task/shared.d.ts +1 -1
- package/dist/commands/task/shared.d.ts.map +1 -1
- package/dist/commands/task/shared.js +1 -1
- package/dist/commands/task/start-ready.d.ts.map +1 -1
- package/dist/commands/task/start-ready.js +98 -1
- package/dist/commands/task/start.d.ts.map +1 -1
- package/dist/commands/task/start.js +18 -10
- package/dist/commands/task/task.command.d.ts.map +1 -1
- package/dist/commands/task/task.command.js +4 -0
- package/dist/commands/task/verify-command-shared.d.ts +19 -0
- package/dist/commands/task/verify-command-shared.d.ts.map +1 -1
- package/dist/commands/task/verify-command-shared.js +152 -1
- package/dist/commands/task/verify-ok.command.d.ts.map +1 -1
- package/dist/commands/task/verify-ok.command.js +15 -2
- package/dist/commands/task/verify-record.d.ts +36 -0
- package/dist/commands/task/verify-record.d.ts.map +1 -1
- package/dist/commands/task/verify-record.js +193 -11
- package/dist/commands/task/verify-rework.command.d.ts.map +1 -1
- package/dist/commands/task/verify-rework.command.js +15 -2
- package/dist/commands/task/verify-show.command.d.ts +1 -1
- package/dist/commands/task/verify-show.command.d.ts.map +1 -1
- package/dist/commands/task/verify-show.command.js +28 -1
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +6 -1
- package/dist/commands/verify.run.d.ts.map +1 -1
- package/dist/commands/verify.run.js +12 -0
- package/dist/commands/verify.spec.d.ts +2 -6
- package/dist/commands/verify.spec.d.ts.map +1 -1
- package/dist/commands/verify.spec.js +30 -3
- package/dist/policy/engine.d.ts +3 -1
- package/dist/policy/engine.d.ts.map +1 -1
- package/dist/policy/engine.js +5 -6
- package/dist/policy/taxonomy.d.ts +17 -0
- package/dist/policy/taxonomy.d.ts.map +1 -0
- package/dist/policy/taxonomy.js +302 -0
- package/dist/policy/types.d.ts +2 -1
- package/dist/policy/types.d.ts.map +1 -1
- package/dist/runner/artifacts.d.ts.map +1 -1
- package/dist/runner/artifacts.js +2 -0
- package/dist/runner/context/base-prompts.d.ts +25 -0
- package/dist/runner/context/base-prompts.d.ts.map +1 -1
- package/dist/runner/context/base-prompts.js +182 -54
- package/dist/runner/context/recipe-context.d.ts.map +1 -1
- package/dist/runner/context/recipe-context.js +5 -0
- package/dist/runner/types.d.ts +12 -0
- package/dist/runner/types.d.ts.map +1 -1
- package/dist/runner/usecases/scenario-materialize-task.d.ts.map +1 -1
- package/dist/runner/usecases/scenario-materialize-task.js +81 -11
- package/dist/runner/usecases/task-run-inspect.d.ts.map +1 -1
- package/dist/runner/usecases/task-run-inspect.js +9 -7
- package/dist/runner/usecases/task-run-lifecycle-shared.d.ts.map +1 -1
- package/dist/runner/usecases/task-run-lifecycle-shared.js +8 -6
- package/dist/runner/usecases/task-run.d.ts.map +1 -1
- package/dist/runner/usecases/task-run.js +59 -12
- package/dist/runtime/approvals/index.d.ts +3 -0
- package/dist/runtime/approvals/index.d.ts.map +1 -0
- package/dist/runtime/approvals/index.js +1 -0
- package/dist/runtime/approvals/runtime.d.ts +12 -0
- package/dist/runtime/approvals/runtime.d.ts.map +1 -0
- package/dist/runtime/approvals/runtime.js +154 -0
- package/dist/runtime/approvals/types.d.ts +31 -0
- package/dist/runtime/approvals/types.d.ts.map +1 -0
- package/dist/runtime/approvals/types.js +1 -0
- package/dist/runtime/behavior/index.d.ts +3 -0
- package/dist/runtime/behavior/index.d.ts.map +1 -0
- package/dist/runtime/behavior/index.js +1 -0
- package/dist/runtime/behavior/resolve.d.ts +7 -0
- package/dist/runtime/behavior/resolve.d.ts.map +1 -0
- package/dist/runtime/behavior/resolve.js +66 -0
- package/dist/runtime/behavior/types.d.ts +25 -0
- package/dist/runtime/behavior/types.d.ts.map +1 -0
- package/dist/runtime/behavior/types.js +1 -0
- package/dist/runtime/capabilities/backend.d.ts +7 -0
- package/dist/runtime/capabilities/backend.d.ts.map +1 -0
- package/dist/runtime/capabilities/backend.js +104 -0
- package/dist/runtime/capabilities/index.d.ts +6 -0
- package/dist/runtime/capabilities/index.d.ts.map +1 -0
- package/dist/runtime/capabilities/index.js +4 -0
- package/dist/runtime/capabilities/recipe.d.ts +10 -0
- package/dist/runtime/capabilities/recipe.d.ts.map +1 -0
- package/dist/runtime/capabilities/recipe.js +123 -0
- package/dist/runtime/capabilities/registry.d.ts +6 -0
- package/dist/runtime/capabilities/registry.d.ts.map +1 -0
- package/dist/runtime/capabilities/registry.js +69 -0
- package/dist/runtime/capabilities/runner.d.ts +8 -0
- package/dist/runtime/capabilities/runner.d.ts.map +1 -0
- package/dist/runtime/capabilities/runner.js +73 -0
- package/dist/runtime/capabilities/types.d.ts +28 -0
- package/dist/runtime/capabilities/types.d.ts.map +1 -0
- package/dist/runtime/capabilities/types.js +1 -0
- package/dist/runtime/execution-profile/index.d.ts +3 -0
- package/dist/runtime/execution-profile/index.d.ts.map +1 -0
- package/dist/runtime/execution-profile/index.js +1 -0
- package/dist/runtime/execution-profile/resolve.d.ts +9 -0
- package/dist/runtime/execution-profile/resolve.d.ts.map +1 -0
- package/dist/runtime/execution-profile/resolve.js +80 -0
- package/dist/runtime/execution-profile/types.d.ts +27 -0
- package/dist/runtime/execution-profile/types.d.ts.map +1 -0
- package/dist/runtime/execution-profile/types.js +1 -0
- package/dist/runtime/explain/index.d.ts +3 -0
- package/dist/runtime/explain/index.d.ts.map +1 -0
- package/dist/runtime/explain/index.js +1 -0
- package/dist/runtime/explain/resolve.d.ts +14 -0
- package/dist/runtime/explain/resolve.d.ts.map +1 -0
- package/dist/runtime/explain/resolve.js +50 -0
- package/dist/runtime/explain/types.d.ts +28 -0
- package/dist/runtime/explain/types.d.ts.map +1 -0
- package/dist/runtime/explain/types.js +1 -0
- package/dist/runtime/harness/index.d.ts +4 -0
- package/dist/runtime/harness/index.d.ts.map +1 -0
- package/dist/runtime/harness/index.js +2 -0
- package/dist/runtime/harness/resolve-from-command-context.d.ts +4 -0
- package/dist/runtime/harness/resolve-from-command-context.d.ts.map +1 -0
- package/dist/runtime/harness/resolve-from-command-context.js +11 -0
- package/dist/runtime/harness/resolve.d.ts +13 -0
- package/dist/runtime/harness/resolve.d.ts.map +1 -0
- package/dist/runtime/harness/resolve.js +146 -0
- package/dist/runtime/harness/types.d.ts +65 -0
- package/dist/runtime/harness/types.d.ts.map +1 -0
- package/dist/runtime/harness/types.js +1 -0
- package/dist/runtime/incidents/index.d.ts +3 -0
- package/dist/runtime/incidents/index.d.ts.map +1 -0
- package/dist/runtime/incidents/index.js +1 -0
- package/dist/runtime/incidents/resolve.d.ts +26 -0
- package/dist/runtime/incidents/resolve.d.ts.map +1 -0
- package/dist/runtime/incidents/resolve.js +683 -0
- package/dist/runtime/incidents/types.d.ts +84 -0
- package/dist/runtime/incidents/types.d.ts.map +1 -0
- package/dist/runtime/incidents/types.js +1 -0
- package/dist/runtime/protocol/index.d.ts +3 -0
- package/dist/runtime/protocol/index.d.ts.map +1 -0
- package/dist/runtime/protocol/index.js +2 -0
- package/dist/runtime/protocol/resolve.d.ts +16 -0
- package/dist/runtime/protocol/resolve.d.ts.map +1 -0
- package/dist/runtime/protocol/resolve.js +36 -0
- package/dist/runtime/protocol/types.d.ts +36 -0
- package/dist/runtime/protocol/types.d.ts.map +1 -0
- package/dist/runtime/protocol/types.js +1 -0
- package/dist/runtime/task-intake/index.d.ts +3 -0
- package/dist/runtime/task-intake/index.d.ts.map +1 -0
- package/dist/runtime/task-intake/index.js +1 -0
- package/dist/runtime/task-intake/resolve.d.ts +48 -0
- package/dist/runtime/task-intake/resolve.d.ts.map +1 -0
- package/dist/runtime/task-intake/resolve.js +316 -0
- package/dist/runtime/task-intake/types.d.ts +117 -0
- package/dist/runtime/task-intake/types.d.ts.map +1 -0
- package/dist/runtime/task-intake/types.js +1 -0
- package/dist/shared/env.d.ts +1 -0
- package/dist/shared/env.d.ts.map +1 -1
- package/dist/shared/env.js +22 -1
- package/dist/shared/protected-paths.d.ts +4 -0
- package/dist/shared/protected-paths.d.ts.map +1 -1
- package/dist/shared/protected-paths.js +8 -4
- package/dist/usecases/context/resolve-context.d.ts +55 -6
- package/dist/usecases/context/resolve-context.d.ts.map +1 -1
- package/dist/usecases/context/resolve-context.js +96 -6
- package/dist/usecases/task/task-list-usecase.d.ts.map +1 -1
- package/dist/usecases/task/task-list-usecase.js +8 -2
- package/dist/usecases/task/task-new-usecase.js +4 -4
- package/package.json +2 -2
|
@@ -1,13 +1,19 @@
|
|
|
1
|
+
import { resolveBaseBranch } from "@agentplaneorg/core";
|
|
1
2
|
import { mapBackendError } from "../../cli/error-map.js";
|
|
3
|
+
import { exitCodeForError } from "../../cli/exit-codes.js";
|
|
2
4
|
import { infoMessage, invalidValueMessage, successMessage } from "../../cli/output.js";
|
|
3
5
|
import { CliError } from "../../shared/errors.js";
|
|
4
6
|
import { readFile, rm } from "node:fs/promises";
|
|
5
7
|
import path from "node:path";
|
|
6
8
|
import { ensureActionApproved } from "../shared/approval-requirements.js";
|
|
7
9
|
import { ensureReconciledBeforeMutation } from "../shared/reconcile-check.js";
|
|
10
|
+
import { gitCurrentBranch } from "../shared/git-ops.js";
|
|
8
11
|
import { loadCommandContext } from "../shared/task-backend.js";
|
|
9
12
|
import { backendIsLocalFileBackend, getTaskStore } from "../shared/task-store.js";
|
|
13
|
+
import { applyTaskMutation } from "../shared/task-mutation.js";
|
|
14
|
+
import { collectTaskIncidents, renderIncidentCollectionPlanOutcome } from "../incidents/shared.js";
|
|
10
15
|
import { createTaskCloseCommit, existingCommitInfo, loadTaskForFinish, writeFinishedTasks, } from "./finish-shared.js";
|
|
16
|
+
import { buildStructuredFindingMutationPlan } from "./findings.js";
|
|
11
17
|
import { defaultCommitEmojiForStatus, enforceStatusCommitPolicy, prepareTaskTransitionComment, readCommitInfo, requireStructuredComment, runTaskTransitionCommentCommit, } from "./shared.js";
|
|
12
18
|
async function clearDirectWorkLockIfMatches(opts) {
|
|
13
19
|
const lockPath = path.join(opts.agentplaneDir, "cache", "direct-work.json");
|
|
@@ -25,11 +31,68 @@ async function clearDirectWorkLockIfMatches(opts) {
|
|
|
25
31
|
// best-effort
|
|
26
32
|
}
|
|
27
33
|
}
|
|
34
|
+
async function ensureFinishRunsOnBaseBranch(opts) {
|
|
35
|
+
if (opts.ctx.config.workflow_mode !== "branch_pr")
|
|
36
|
+
return;
|
|
37
|
+
const baseBranch = await resolveBaseBranch({
|
|
38
|
+
cwd: opts.cwd,
|
|
39
|
+
rootOverride: opts.rootOverride ?? null,
|
|
40
|
+
cliBaseOpt: opts.baseBranchOverride ?? null,
|
|
41
|
+
mode: opts.ctx.config.workflow_mode,
|
|
42
|
+
});
|
|
43
|
+
if (!baseBranch) {
|
|
44
|
+
throw new CliError({
|
|
45
|
+
exitCode: exitCodeForError("E_USAGE"),
|
|
46
|
+
code: "E_USAGE",
|
|
47
|
+
message: "Base branch could not be resolved (use `agentplane branch base set` or --base).",
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const currentBranch = await gitCurrentBranch(opts.ctx.resolvedProject.gitRoot);
|
|
51
|
+
if (currentBranch === baseBranch)
|
|
52
|
+
return;
|
|
53
|
+
throw new CliError({
|
|
54
|
+
exitCode: exitCodeForError("E_GIT"),
|
|
55
|
+
code: "E_GIT",
|
|
56
|
+
message: `finish must run on base branch ${baseBranch} in branch_pr mode ` +
|
|
57
|
+
`(current: ${currentBranch}); integrate first or reconcile from the base checkout.`,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async function appendFinishStructuredFinding(opts) {
|
|
61
|
+
await applyTaskMutation({
|
|
62
|
+
ctx: opts.ctx,
|
|
63
|
+
taskId: opts.taskId,
|
|
64
|
+
build: (current) => {
|
|
65
|
+
const plan = buildStructuredFindingMutationPlan({
|
|
66
|
+
current,
|
|
67
|
+
config: opts.ctx.config,
|
|
68
|
+
observation: opts.finding.observation,
|
|
69
|
+
impact: opts.finding.impact,
|
|
70
|
+
resolution: opts.finding.resolution,
|
|
71
|
+
promote: !opts.finding.localOnly,
|
|
72
|
+
external: !opts.finding.localOnly,
|
|
73
|
+
fixability: opts.finding.repoFixable ? "repo-fixable" : null,
|
|
74
|
+
incidentScope: opts.finding.incidentScope,
|
|
75
|
+
incidentTags: opts.finding.incidentTags,
|
|
76
|
+
incidentMatch: opts.finding.incidentMatch,
|
|
77
|
+
incidentAdvice: opts.finding.incidentAdvice,
|
|
78
|
+
incidentRule: opts.finding.incidentRule,
|
|
79
|
+
updatedBy: opts.author,
|
|
80
|
+
});
|
|
81
|
+
return plan ? { intents: plan.intents } : null;
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
}
|
|
28
85
|
export async function cmdFinish(opts) {
|
|
29
86
|
try {
|
|
30
87
|
const ctx = opts.ctx ??
|
|
31
88
|
(await loadCommandContext({ cwd: opts.cwd, rootOverride: opts.rootOverride ?? null }));
|
|
32
89
|
await ensureReconciledBeforeMutation({ ctx, command: "finish" });
|
|
90
|
+
await ensureFinishRunsOnBaseBranch({
|
|
91
|
+
ctx,
|
|
92
|
+
cwd: opts.cwd,
|
|
93
|
+
rootOverride: opts.rootOverride,
|
|
94
|
+
baseBranchOverride: opts.baseBranchOverride,
|
|
95
|
+
});
|
|
33
96
|
if (opts.force) {
|
|
34
97
|
await ensureActionApproved({
|
|
35
98
|
action: "force_action",
|
|
@@ -139,6 +202,49 @@ export async function cmdFinish(opts) {
|
|
|
139
202
|
const resultSummary = typeof opts.result === "string" ? opts.result.trim() : "";
|
|
140
203
|
const riskLevel = opts.risk;
|
|
141
204
|
const breaking = opts.breaking === true;
|
|
205
|
+
const finishFinding = typeof opts.observation === "string" &&
|
|
206
|
+
typeof opts.impact === "string" &&
|
|
207
|
+
typeof opts.resolution === "string"
|
|
208
|
+
? {
|
|
209
|
+
observation: opts.observation,
|
|
210
|
+
impact: opts.impact,
|
|
211
|
+
resolution: opts.resolution,
|
|
212
|
+
localOnly: opts.localOnly === true,
|
|
213
|
+
repoFixable: opts.repoFixable === true,
|
|
214
|
+
incidentScope: opts.incidentScope,
|
|
215
|
+
incidentTags: opts.incidentTags ?? [],
|
|
216
|
+
incidentMatch: opts.incidentMatch ?? [],
|
|
217
|
+
incidentAdvice: opts.incidentAdvice,
|
|
218
|
+
incidentRule: opts.incidentRule,
|
|
219
|
+
}
|
|
220
|
+
: null;
|
|
221
|
+
if (finishFinding && opts.taskIds.length !== 1) {
|
|
222
|
+
throw new CliError({
|
|
223
|
+
exitCode: 2,
|
|
224
|
+
code: "E_USAGE",
|
|
225
|
+
message: "--observation/--impact/--resolution and incident finding options require exactly one task id",
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
if (finishFinding && primaryTaskId) {
|
|
229
|
+
await loadTaskForFinish({
|
|
230
|
+
ctx,
|
|
231
|
+
store,
|
|
232
|
+
useStore,
|
|
233
|
+
taskId: primaryTaskId,
|
|
234
|
+
taskCount: opts.taskIds.length,
|
|
235
|
+
metaTaskId,
|
|
236
|
+
resultProvided,
|
|
237
|
+
resultSummary,
|
|
238
|
+
force: opts.force,
|
|
239
|
+
capturePrimaryLifecycleMeta: false,
|
|
240
|
+
});
|
|
241
|
+
await appendFinishStructuredFinding({
|
|
242
|
+
ctx,
|
|
243
|
+
taskId: primaryTaskId,
|
|
244
|
+
author: opts.author,
|
|
245
|
+
finding: finishFinding,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
142
248
|
let primaryStatusFrom = null;
|
|
143
249
|
let primaryTag = null;
|
|
144
250
|
const loadedTasks = [];
|
|
@@ -161,6 +267,15 @@ export async function cmdFinish(opts) {
|
|
|
161
267
|
primaryTag = loaded.primaryTag;
|
|
162
268
|
}
|
|
163
269
|
}
|
|
270
|
+
for (const taskId of opts.taskIds) {
|
|
271
|
+
const loadedTask = loadedTasks.find((candidate) => candidate.taskId === taskId) ?? null;
|
|
272
|
+
await collectTaskIncidents({
|
|
273
|
+
ctx,
|
|
274
|
+
taskId,
|
|
275
|
+
task: loadedTask?.task ?? null,
|
|
276
|
+
write: false,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
164
279
|
const tasksMissingCommit = loadedTasks
|
|
165
280
|
.filter(({ task }) => !existingCommitInfo(task))
|
|
166
281
|
.map(({ taskId }) => taskId);
|
|
@@ -263,6 +378,20 @@ export async function cmdFinish(opts) {
|
|
|
263
378
|
breaking,
|
|
264
379
|
taskCommitInfo,
|
|
265
380
|
});
|
|
381
|
+
const incidentPlans = [];
|
|
382
|
+
const incidentRegistryPaths = [];
|
|
383
|
+
for (const taskId of opts.taskIds) {
|
|
384
|
+
const loadedTask = loadedTasks.find((candidate) => candidate.taskId === taskId) ?? null;
|
|
385
|
+
const collected = await collectTaskIncidents({
|
|
386
|
+
ctx,
|
|
387
|
+
taskId,
|
|
388
|
+
task: loadedTask?.task ?? null,
|
|
389
|
+
write: true,
|
|
390
|
+
});
|
|
391
|
+
incidentPlans.push(collected.plan);
|
|
392
|
+
incidentRegistryPaths.push(collected.registryPaths);
|
|
393
|
+
}
|
|
394
|
+
const promotedIncidents = incidentPlans.reduce((sum, plan) => sum + plan.promotable.length, 0);
|
|
266
395
|
// tasks.json is export-only; generated via `agentplane task export`.
|
|
267
396
|
if (shouldCloseCommit && primaryTaskId) {
|
|
268
397
|
if (!opts.quiet) {
|
|
@@ -276,6 +405,7 @@ export async function cmdFinish(opts) {
|
|
|
276
405
|
baseBranchOverride: opts.baseBranchOverride,
|
|
277
406
|
quiet: opts.quiet,
|
|
278
407
|
closeUnstageOthers: opts.closeCommit === true && opts.closeUnstageOthers === true,
|
|
408
|
+
allowPolicy: promotedIncidents > 0,
|
|
279
409
|
});
|
|
280
410
|
}
|
|
281
411
|
if (ctx.config.workflow_mode === "direct") {
|
|
@@ -285,6 +415,19 @@ export async function cmdFinish(opts) {
|
|
|
285
415
|
});
|
|
286
416
|
}
|
|
287
417
|
if (!opts.quiet) {
|
|
418
|
+
const incidentPlan = incidentPlans[0] ?? {
|
|
419
|
+
candidates: [],
|
|
420
|
+
skipped: [],
|
|
421
|
+
promotable: [],
|
|
422
|
+
duplicates: [],
|
|
423
|
+
};
|
|
424
|
+
process.stdout.write(`${infoMessage(renderIncidentCollectionPlanOutcome(incidentPlan, {
|
|
425
|
+
wrote: promotedIncidents > 0,
|
|
426
|
+
context: "finish",
|
|
427
|
+
promotedIds: incidentPlan.promotable.map((item) => item.entry.id),
|
|
428
|
+
registryPaths: incidentRegistryPaths[0] ?? [],
|
|
429
|
+
taskId: opts.taskIds[0] ?? null,
|
|
430
|
+
}))}\n`);
|
|
288
431
|
process.stdout.write(`${successMessage("finished")}\n`);
|
|
289
432
|
}
|
|
290
433
|
return 0;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CommandCtx, CommandSpec } from "../../cli/spec/spec.js";
|
|
2
|
+
import { type CommandContext } from "../shared/task-backend.js";
|
|
3
|
+
type TaskHostedClosePrParsed = {
|
|
4
|
+
taskIds: string[];
|
|
5
|
+
branch: string | null;
|
|
6
|
+
repo: string | null;
|
|
7
|
+
};
|
|
8
|
+
export declare const taskHostedClosePrSpec: CommandSpec<TaskHostedClosePrParsed>;
|
|
9
|
+
export declare function makeRunTaskHostedClosePrHandler(getCtx: (cmd: string) => Promise<CommandContext>): (ctx: CommandCtx, p: TaskHostedClosePrParsed) => Promise<number>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=hosted-close-pr.command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hosted-close-pr.command.d.ts","sourceRoot":"","sources":["../../../src/commands/task/hosted-close-pr.command.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAQtE,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAQnC,KAAK,uBAAuB,GAAG;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,CAAC;AAgBF,eAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC,uBAAuB,CAoEtE,CAAC;AAmYF,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,IAChF,KAAK,UAAU,EAAE,GAAG,uBAAuB,KAAG,OAAO,CAAC,MAAM,CAAC,CAsB5E"}
|
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { usageError } from "../../cli/spec/errors.js";
|
|
3
|
+
import { createCliEmitter } from "../../cli/output.js";
|
|
4
|
+
import { mapBackendError } from "../../cli/error-map.js";
|
|
5
|
+
import { exitCodeForError } from "../../cli/exit-codes.js";
|
|
6
|
+
import { fileExists } from "../../cli/fs-utils.js";
|
|
7
|
+
import { CliError } from "../../shared/errors.js";
|
|
8
|
+
import { execFileAsync, gitEnv } from "../shared/git.js";
|
|
9
|
+
import { loadTaskFromContext, resolveTaskBranchFromContext, } from "../shared/task-backend.js";
|
|
10
|
+
import { parseTaskIdFromCloseBranch } from "../shared/git-worktree.js";
|
|
11
|
+
import { parsePrMeta } from "../shared/pr-meta.js";
|
|
12
|
+
import { resolveDefaultGithubRepo, runGhApiJson } from "../pr/internal/gh-api.js";
|
|
13
|
+
import { resolvePrPaths } from "../pr/internal/pr-paths.js";
|
|
14
|
+
import { resolveBaseBranch } from "@agentplaneorg/core";
|
|
15
|
+
export const taskHostedClosePrSpec = {
|
|
16
|
+
id: ["task", "hosted-close-pr"],
|
|
17
|
+
group: "Task",
|
|
18
|
+
summary: "Open one or more follow-up hosted closure PRs from remote task-close branches.",
|
|
19
|
+
args: [{ name: "task-id", required: true, variadic: true, valueHint: "<task-id>" }],
|
|
20
|
+
options: [
|
|
21
|
+
{
|
|
22
|
+
kind: "string",
|
|
23
|
+
name: "branch",
|
|
24
|
+
valueHint: "<name>",
|
|
25
|
+
description: "Optional explicit task-close branch name (default: derive from task PR metadata or remote refs).",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
kind: "string",
|
|
29
|
+
name: "repo",
|
|
30
|
+
valueHint: "<owner/name>",
|
|
31
|
+
description: "Optional GitHub owner/repo override (defaults to origin remote).",
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
examples: [
|
|
35
|
+
{
|
|
36
|
+
cmd: "agentplane task hosted-close-pr 202604091218-JREJ4K",
|
|
37
|
+
why: "Open the hosted closure PR after the workflow left a manual handoff comment.",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
cmd: "agentplane task hosted-close-pr 202604091725-CB0Y6S 202604091725-H21SCP",
|
|
41
|
+
why: "Open multiple pending hosted closure PRs in one batch after a closure-wave merge.",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
validateRaw: (raw) => {
|
|
45
|
+
const taskIds = Array.isArray(raw.args["task-id"])
|
|
46
|
+
? raw.args["task-id"]
|
|
47
|
+
: typeof raw.args["task-id"] === "string"
|
|
48
|
+
? [raw.args["task-id"]]
|
|
49
|
+
: [];
|
|
50
|
+
const normalizedTaskIds = taskIds.map((taskId) => String(taskId).trim()).filter(Boolean);
|
|
51
|
+
if (normalizedTaskIds.length === 0) {
|
|
52
|
+
throw usageError({
|
|
53
|
+
spec: taskHostedClosePrSpec,
|
|
54
|
+
message: "Invalid value for task-id: empty.",
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
if (typeof raw.opts.branch === "string" && raw.opts.branch.trim() === "") {
|
|
58
|
+
throw usageError({
|
|
59
|
+
spec: taskHostedClosePrSpec,
|
|
60
|
+
message: "Invalid value for --branch: empty.",
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (typeof raw.opts.repo === "string" && raw.opts.repo.trim() === "") {
|
|
64
|
+
throw usageError({
|
|
65
|
+
spec: taskHostedClosePrSpec,
|
|
66
|
+
message: "Invalid value for --repo: empty.",
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
parse: (raw) => ({
|
|
71
|
+
taskIds: (Array.isArray(raw.args["task-id"])
|
|
72
|
+
? raw.args["task-id"]
|
|
73
|
+
: typeof raw.args["task-id"] === "string"
|
|
74
|
+
? [raw.args["task-id"]]
|
|
75
|
+
: [])
|
|
76
|
+
.map((taskId) => String(taskId).trim())
|
|
77
|
+
.filter(Boolean),
|
|
78
|
+
branch: typeof raw.opts.branch === "string" ? raw.opts.branch : null,
|
|
79
|
+
repo: typeof raw.opts.repo === "string" ? raw.opts.repo : null,
|
|
80
|
+
}),
|
|
81
|
+
};
|
|
82
|
+
async function resolveGithubRepo(opts) {
|
|
83
|
+
const repo = opts.repoOverride?.trim() ?? "";
|
|
84
|
+
if (repo)
|
|
85
|
+
return repo;
|
|
86
|
+
return await resolveDefaultGithubRepo(opts.gitRoot);
|
|
87
|
+
}
|
|
88
|
+
function selectMergedPullRecord(opts) {
|
|
89
|
+
const merged = opts.pulls.filter((record) => {
|
|
90
|
+
if (typeof record.merged_at !== "string" || record.merged_at.trim().length === 0)
|
|
91
|
+
return false;
|
|
92
|
+
const headRef = record.head?.ref?.trim() ?? "";
|
|
93
|
+
if (opts.sourceBranch && headRef && headRef !== opts.sourceBranch)
|
|
94
|
+
return false;
|
|
95
|
+
const baseRef = record.base?.ref?.trim() ?? "";
|
|
96
|
+
if (opts.baseBranch && baseRef && baseRef !== opts.baseBranch)
|
|
97
|
+
return false;
|
|
98
|
+
return true;
|
|
99
|
+
});
|
|
100
|
+
if (merged.length === 0)
|
|
101
|
+
return null;
|
|
102
|
+
if (typeof opts.prNumber === "number" && opts.prNumber > 0) {
|
|
103
|
+
const exact = merged.find((record) => Number(record.number ?? 0) === opts.prNumber);
|
|
104
|
+
if (exact)
|
|
105
|
+
return exact;
|
|
106
|
+
}
|
|
107
|
+
return ([...merged].toSorted((left, right) => {
|
|
108
|
+
const leftAt = Date.parse(left.merged_at ?? "");
|
|
109
|
+
const rightAt = Date.parse(right.merged_at ?? "");
|
|
110
|
+
return Number.isNaN(rightAt) || Number.isNaN(leftAt) ? 0 : rightAt - leftAt;
|
|
111
|
+
})[0] ?? null);
|
|
112
|
+
}
|
|
113
|
+
async function resolveHostedCloseMergeRecord(opts) {
|
|
114
|
+
const owner = opts.repo.split("/")[0]?.trim() ?? "";
|
|
115
|
+
if (!owner)
|
|
116
|
+
return null;
|
|
117
|
+
const query = new URLSearchParams({
|
|
118
|
+
state: "closed",
|
|
119
|
+
head: `${owner}:${opts.sourceBranch}`,
|
|
120
|
+
});
|
|
121
|
+
if (opts.baseBranch)
|
|
122
|
+
query.set("base", opts.baseBranch);
|
|
123
|
+
const records = await runGhApiJson(opts.gitRoot, [
|
|
124
|
+
`repos/${opts.repo}/pulls?${query.toString()}`,
|
|
125
|
+
]);
|
|
126
|
+
return selectMergedPullRecord({
|
|
127
|
+
pulls: Array.isArray(records) ? records : [],
|
|
128
|
+
sourceBranch: opts.sourceBranch,
|
|
129
|
+
baseBranch: opts.baseBranch,
|
|
130
|
+
prNumber: opts.prNumber,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
async function resolveHostedCloseMergeRecordByCommit(opts) {
|
|
134
|
+
const records = await runGhApiJson(opts.gitRoot, [
|
|
135
|
+
`repos/${opts.repo}/commits/${opts.mergeCommit}/pulls`,
|
|
136
|
+
]);
|
|
137
|
+
return selectMergedPullRecord({
|
|
138
|
+
pulls: Array.isArray(records) ? records : [],
|
|
139
|
+
sourceBranch: opts.sourceBranch,
|
|
140
|
+
baseBranch: opts.baseBranch,
|
|
141
|
+
prNumber: opts.prNumber,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
async function readHostedCloseState(opts) {
|
|
145
|
+
const task = await loadTaskFromContext({ ctx: opts.ctx, taskId: opts.taskId });
|
|
146
|
+
const taskBranch = await resolveTaskBranchFromContext({ ctx: opts.ctx, taskId: opts.taskId });
|
|
147
|
+
const { metaPath, config } = await resolvePrPaths({
|
|
148
|
+
ctx: opts.ctx,
|
|
149
|
+
cwd: opts.cwd,
|
|
150
|
+
rootOverride: opts.rootOverride,
|
|
151
|
+
taskId: opts.taskId,
|
|
152
|
+
});
|
|
153
|
+
if (config.workflow_mode !== "branch_pr") {
|
|
154
|
+
throw new CliError({
|
|
155
|
+
exitCode: exitCodeForError("E_USAGE"),
|
|
156
|
+
code: "E_USAGE",
|
|
157
|
+
message: `Invalid workflow_mode: ${config.workflow_mode} (expected branch_pr)`,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (!(await fileExists(metaPath))) {
|
|
161
|
+
return { meta: null, task, taskBranch };
|
|
162
|
+
}
|
|
163
|
+
const meta = parsePrMeta(await readFile(metaPath, "utf8"), opts.taskId);
|
|
164
|
+
return { meta, task, taskBranch };
|
|
165
|
+
}
|
|
166
|
+
async function listRemoteTaskCloseBranches(opts) {
|
|
167
|
+
const { stdout } = await execFileAsync("git", ["ls-remote", "--heads", "origin", `task-close/${opts.taskId}/*`], {
|
|
168
|
+
cwd: opts.gitRoot,
|
|
169
|
+
env: gitEnv(),
|
|
170
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
171
|
+
});
|
|
172
|
+
return stdout
|
|
173
|
+
.split("\n")
|
|
174
|
+
.map((line) => line.trim())
|
|
175
|
+
.filter((line) => line.length > 0)
|
|
176
|
+
.map((line) => line.split(/\s+/, 2)[1] ?? "")
|
|
177
|
+
.map((ref) => ref.replace(/^refs\/heads\//, ""))
|
|
178
|
+
.filter((ref) => ref.length > 0);
|
|
179
|
+
}
|
|
180
|
+
function shortSha(value) {
|
|
181
|
+
return value.trim().slice(0, 12);
|
|
182
|
+
}
|
|
183
|
+
function stripBranchRef(branch) {
|
|
184
|
+
return branch.startsWith("refs/heads/") ? branch.slice("refs/heads/".length) : branch;
|
|
185
|
+
}
|
|
186
|
+
async function resolveHostedCloseBranch(opts) {
|
|
187
|
+
const remoteBranches = await listRemoteTaskCloseBranches({
|
|
188
|
+
gitRoot: opts.gitRoot,
|
|
189
|
+
taskId: opts.taskId,
|
|
190
|
+
});
|
|
191
|
+
const explicitBranch = stripBranchRef(opts.explicitBranch?.trim() ?? "");
|
|
192
|
+
if (explicitBranch) {
|
|
193
|
+
const parsedTaskId = parseTaskIdFromCloseBranch(explicitBranch);
|
|
194
|
+
if (parsedTaskId && parsedTaskId !== opts.taskId) {
|
|
195
|
+
throw new CliError({
|
|
196
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
197
|
+
code: "E_VALIDATION",
|
|
198
|
+
message: `Branch ${explicitBranch} does not belong to task ${opts.taskId}.`,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
if (!remoteBranches.includes(explicitBranch)) {
|
|
202
|
+
throw new CliError({
|
|
203
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
204
|
+
code: "E_VALIDATION",
|
|
205
|
+
message: `Remote hosted closure branch not found: ${explicitBranch}.`,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return explicitBranch;
|
|
209
|
+
}
|
|
210
|
+
if (opts.mergeCommit) {
|
|
211
|
+
const expected = `task-close/${opts.taskId}/${shortSha(opts.mergeCommit)}`;
|
|
212
|
+
if (remoteBranches.includes(expected))
|
|
213
|
+
return expected;
|
|
214
|
+
if (remoteBranches.length === 1)
|
|
215
|
+
return remoteBranches[0] ?? expected;
|
|
216
|
+
if (remoteBranches.length > 1) {
|
|
217
|
+
throw new CliError({
|
|
218
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
219
|
+
code: "E_VALIDATION",
|
|
220
|
+
message: `Multiple remote hosted closure branches match ${opts.taskId}: ${remoteBranches.join(", ")} (use --branch).`,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
throw new CliError({
|
|
224
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
225
|
+
code: "E_VALIDATION",
|
|
226
|
+
message: `Remote hosted closure branch not found for ${opts.taskId}: ${expected}.`,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
if (remoteBranches.length === 1)
|
|
230
|
+
return remoteBranches[0] ?? "";
|
|
231
|
+
if (remoteBranches.length > 1) {
|
|
232
|
+
throw new CliError({
|
|
233
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
234
|
+
code: "E_VALIDATION",
|
|
235
|
+
message: `Multiple remote hosted closure branches match ${opts.taskId}: ${remoteBranches.join(", ")} (use --branch).`,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
throw new CliError({
|
|
239
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
240
|
+
code: "E_VALIDATION",
|
|
241
|
+
message: `Could not resolve remote hosted closure branch for ${opts.taskId}.`,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
function buildHostedClosePrTitle(taskId) {
|
|
245
|
+
return `📝 ${taskId} task: close after hosted merge`;
|
|
246
|
+
}
|
|
247
|
+
function buildHostedClosePrBody(opts) {
|
|
248
|
+
const prLine = typeof opts.prNumber === "number" && opts.prNumber > 0
|
|
249
|
+
? `Automated closure for merged task PR #${opts.prNumber}.`
|
|
250
|
+
: "Automated closure for merged task PR.";
|
|
251
|
+
return [
|
|
252
|
+
prLine,
|
|
253
|
+
"",
|
|
254
|
+
`- task_id: \`${opts.taskId}\``,
|
|
255
|
+
`- source_branch: \`${opts.sourceBranch}\``,
|
|
256
|
+
`- merge_sha: \`${opts.mergeSha}\``,
|
|
257
|
+
"",
|
|
258
|
+
"This PR contains only tracked task artifacts produced by the hosted branch_pr closure flow.",
|
|
259
|
+
].join("\n");
|
|
260
|
+
}
|
|
261
|
+
function normalizeGithubPrLink(prNumber, prUrl, verb) {
|
|
262
|
+
return prUrl?.trim()
|
|
263
|
+
? `${verb} GitHub PR #${prNumber}: ${prUrl.trim()}`
|
|
264
|
+
: `${verb} GitHub PR #${prNumber}`;
|
|
265
|
+
}
|
|
266
|
+
async function openHostedClosePr(opts) {
|
|
267
|
+
const output = createCliEmitter();
|
|
268
|
+
const { meta, task, taskBranch } = await readHostedCloseState({
|
|
269
|
+
ctx: opts.ctx,
|
|
270
|
+
cwd: opts.cwd,
|
|
271
|
+
rootOverride: opts.rootOverride,
|
|
272
|
+
taskId: opts.taskId,
|
|
273
|
+
});
|
|
274
|
+
const gitRoot = opts.ctx.resolvedProject.gitRoot;
|
|
275
|
+
const repo = await resolveGithubRepo({ gitRoot, repoOverride: opts.repo ?? null });
|
|
276
|
+
const defaultBaseBranch = await resolveBaseBranch({
|
|
277
|
+
cwd: opts.cwd,
|
|
278
|
+
rootOverride: opts.rootOverride ?? null,
|
|
279
|
+
cliBaseOpt: null,
|
|
280
|
+
mode: opts.ctx.config.workflow_mode,
|
|
281
|
+
});
|
|
282
|
+
let sourceBranch = meta?.branch?.trim() ?? taskBranch?.trim() ?? "";
|
|
283
|
+
let baseBranch = meta?.base?.trim() ?? defaultBaseBranch?.trim() ?? "";
|
|
284
|
+
let mergedRecord = sourceBranch.length > 0 &&
|
|
285
|
+
(meta?.status !== "MERGED" || !(meta?.merge_commit?.trim() ?? task.commit?.hash?.trim() ?? ""))
|
|
286
|
+
? await resolveHostedCloseMergeRecord({
|
|
287
|
+
gitRoot,
|
|
288
|
+
repo,
|
|
289
|
+
sourceBranch,
|
|
290
|
+
baseBranch: baseBranch || null,
|
|
291
|
+
prNumber: typeof meta?.pr_number === "number" ? meta.pr_number : null,
|
|
292
|
+
})
|
|
293
|
+
: null;
|
|
294
|
+
const localMergeCommit = meta?.merge_commit?.trim() ?? task.commit?.hash?.trim() ?? "";
|
|
295
|
+
if (!mergedRecord && localMergeCommit) {
|
|
296
|
+
mergedRecord = await resolveHostedCloseMergeRecordByCommit({
|
|
297
|
+
gitRoot,
|
|
298
|
+
repo,
|
|
299
|
+
mergeCommit: localMergeCommit,
|
|
300
|
+
sourceBranch: sourceBranch || null,
|
|
301
|
+
baseBranch: baseBranch || null,
|
|
302
|
+
prNumber: typeof meta?.pr_number === "number" ? meta.pr_number : null,
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
if (!sourceBranch) {
|
|
306
|
+
sourceBranch = mergedRecord?.head?.ref?.trim() ?? "";
|
|
307
|
+
}
|
|
308
|
+
if (!baseBranch) {
|
|
309
|
+
baseBranch = mergedRecord?.base?.ref?.trim() ?? defaultBaseBranch?.trim() ?? "";
|
|
310
|
+
}
|
|
311
|
+
const mergeCommit = meta?.merge_commit?.trim() ??
|
|
312
|
+
task.commit?.hash?.trim() ??
|
|
313
|
+
mergedRecord?.merge_commit_sha?.trim() ??
|
|
314
|
+
"";
|
|
315
|
+
if (!sourceBranch) {
|
|
316
|
+
throw new CliError({
|
|
317
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
318
|
+
code: "E_VALIDATION",
|
|
319
|
+
message: `Missing hosted close source branch for ${opts.taskId}.`,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
if (!mergeCommit) {
|
|
323
|
+
throw new CliError({
|
|
324
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
325
|
+
code: "E_VALIDATION",
|
|
326
|
+
message: `Missing hosted close merge commit for ${opts.taskId}.`,
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
if (meta?.status !== "MERGED" && !mergedRecord?.merged_at) {
|
|
330
|
+
throw new CliError({
|
|
331
|
+
exitCode: exitCodeForError("E_USAGE"),
|
|
332
|
+
code: "E_USAGE",
|
|
333
|
+
message: `Task ${opts.taskId} is not in MERGED hosted-close state.`,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
const branch = await resolveHostedCloseBranch({
|
|
337
|
+
gitRoot,
|
|
338
|
+
taskId: opts.taskId,
|
|
339
|
+
explicitBranch: opts.branch ?? null,
|
|
340
|
+
mergeCommit,
|
|
341
|
+
});
|
|
342
|
+
const owner = repo.split("/")[0]?.trim() ?? "";
|
|
343
|
+
const existingQuery = new URLSearchParams({
|
|
344
|
+
state: "open",
|
|
345
|
+
head: `${owner}:${branch}`,
|
|
346
|
+
});
|
|
347
|
+
const existing = await runGhApiJson(gitRoot, [
|
|
348
|
+
`repos/${repo}/pulls?${existingQuery.toString()}`,
|
|
349
|
+
]);
|
|
350
|
+
const existingPr = Array.isArray(existing) ? (existing[0] ?? null) : null;
|
|
351
|
+
const existingNumber = Number(existingPr?.number ?? 0);
|
|
352
|
+
if (Number.isInteger(existingNumber) && existingNumber > 0) {
|
|
353
|
+
output.success("task hosted-close-pr", opts.taskId, normalizeGithubPrLink(existingNumber, existingPr?.html_url ?? null, "linked to"));
|
|
354
|
+
return 0;
|
|
355
|
+
}
|
|
356
|
+
const created = await runGhApiJson(gitRoot, [
|
|
357
|
+
`repos/${repo}/pulls`,
|
|
358
|
+
"-X",
|
|
359
|
+
"POST",
|
|
360
|
+
"-f",
|
|
361
|
+
`title=${buildHostedClosePrTitle(opts.taskId)}`,
|
|
362
|
+
"-f",
|
|
363
|
+
`body=${buildHostedClosePrBody({
|
|
364
|
+
taskId: opts.taskId,
|
|
365
|
+
prNumber: typeof meta?.pr_number === "number"
|
|
366
|
+
? meta.pr_number
|
|
367
|
+
: typeof mergedRecord?.number === "number"
|
|
368
|
+
? mergedRecord.number
|
|
369
|
+
: null,
|
|
370
|
+
sourceBranch,
|
|
371
|
+
mergeSha: mergeCommit,
|
|
372
|
+
})}`,
|
|
373
|
+
"-f",
|
|
374
|
+
`head=${branch}`,
|
|
375
|
+
"-f",
|
|
376
|
+
`base=${baseBranch}`,
|
|
377
|
+
]);
|
|
378
|
+
const createdNumber = Number(created.number ?? 0);
|
|
379
|
+
if (!Number.isInteger(createdNumber) || createdNumber <= 0) {
|
|
380
|
+
throw new CliError({
|
|
381
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
382
|
+
code: "E_VALIDATION",
|
|
383
|
+
message: `GitHub did not return a valid PR number for hosted closure branch ${branch}.`,
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
output.success("task hosted-close-pr", opts.taskId, normalizeGithubPrLink(createdNumber, created.html_url ?? null, "created"));
|
|
387
|
+
return 0;
|
|
388
|
+
}
|
|
389
|
+
export function makeRunTaskHostedClosePrHandler(getCtx) {
|
|
390
|
+
return async (ctx, p) => {
|
|
391
|
+
try {
|
|
392
|
+
const commandCtx = await getCtx("task hosted-close-pr");
|
|
393
|
+
for (const taskId of p.taskIds) {
|
|
394
|
+
await openHostedClosePr({
|
|
395
|
+
ctx: commandCtx,
|
|
396
|
+
cwd: ctx.cwd,
|
|
397
|
+
rootOverride: ctx.rootOverride,
|
|
398
|
+
taskId,
|
|
399
|
+
branch: p.branch,
|
|
400
|
+
repo: p.repo,
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
return 0;
|
|
404
|
+
}
|
|
405
|
+
catch (err) {
|
|
406
|
+
if (err instanceof CliError)
|
|
407
|
+
throw err;
|
|
408
|
+
throw mapBackendError(err, {
|
|
409
|
+
command: "task hosted-close-pr",
|
|
410
|
+
root: ctx.rootOverride ?? null,
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hosted-close.command.d.ts","sourceRoot":"","sources":["../../../src/commands/task/hosted-close.command.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAStE,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"hosted-close.command.d.ts","sourceRoot":"","sources":["../../../src/commands/task/hosted-close.command.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAStE,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAMrF,MAAM,MAAM,qBAAqB,GAAG;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,qBAAqB,CAqClE,CAAC;AAwMF,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,IAC9E,KAAK,UAAU,EAAE,QAAQ,qBAAqB,KAAG,OAAO,CAAC,MAAM,CAAC,CA2B/E"}
|