agentplane 0.3.10 → 0.3.12

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.
Files changed (271) hide show
  1. package/assets/AGENTS.md +2 -2
  2. package/assets/agents/CODER.json +4 -0
  3. package/assets/agents/CREATOR.json +1 -0
  4. package/assets/agents/DOCS.json +2 -1
  5. package/assets/agents/INTEGRATOR.json +2 -1
  6. package/assets/agents/ORCHESTRATOR.json +2 -0
  7. package/assets/agents/PLANNER.json +3 -1
  8. package/assets/agents/REVIEWER.json +1 -0
  9. package/assets/agents/TESTER.json +2 -2
  10. package/assets/agents/UPDATER.json +1 -0
  11. package/assets/agents/UPGRADER.json +1 -1
  12. package/assets/policy/governance.md +3 -4
  13. package/assets/policy/incidents.md +20 -88
  14. package/assets/policy/workflow.branch_pr.md +1 -1
  15. package/assets/policy/workflow.direct.md +2 -2
  16. package/bin/agentplane.js +114 -4
  17. package/bin/runtime-watch.js +1 -0
  18. package/bin/stale-dist-policy.d.ts +1 -1
  19. package/bin/stale-dist-policy.js +19 -1
  20. package/dist/.build-manifest.json +251 -166
  21. package/dist/cli/bootstrap-guide.d.ts.map +1 -1
  22. package/dist/cli/bootstrap-guide.js +3 -2
  23. package/dist/cli/command-guide.d.ts.map +1 -1
  24. package/dist/cli/command-guide.js +2 -1
  25. package/dist/cli/command-invocations.d.ts.map +1 -1
  26. package/dist/cli/command-invocations.js +4 -1
  27. package/dist/cli/run-cli/command-catalog/core.d.ts +1 -1
  28. package/dist/cli/run-cli/command-catalog/core.d.ts.map +1 -1
  29. package/dist/cli/run-cli/command-catalog/core.js +6 -1
  30. package/dist/cli/run-cli/command-catalog/project.d.ts +1 -1
  31. package/dist/cli/run-cli/command-catalog/project.d.ts.map +1 -1
  32. package/dist/cli/run-cli/command-catalog/project.js +3 -1
  33. package/dist/cli/run-cli/command-catalog/task.d.ts +1 -1
  34. package/dist/cli/run-cli/command-catalog/task.d.ts.map +1 -1
  35. package/dist/cli/run-cli/command-catalog/task.js +10 -0
  36. package/dist/cli/run-cli/command-catalog.d.ts +1 -1
  37. package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
  38. package/dist/cli/run-cli/commands/core/preflight.d.ts.map +1 -1
  39. package/dist/cli/run-cli/commands/core/preflight.js +44 -1
  40. package/dist/cli/run-cli.test-helpers.d.ts +1 -0
  41. package/dist/cli/run-cli.test-helpers.d.ts.map +1 -1
  42. package/dist/cli/run-cli.test-helpers.js +26 -0
  43. package/dist/commands/branch/cleanup-merged.d.ts +3 -0
  44. package/dist/commands/branch/cleanup-merged.d.ts.map +1 -1
  45. package/dist/commands/branch/cleanup-merged.js +149 -36
  46. package/dist/commands/branch/work-start.d.ts.map +1 -1
  47. package/dist/commands/branch/work-start.js +137 -1
  48. package/dist/commands/cleanup/merged.command.d.ts +2 -0
  49. package/dist/commands/cleanup/merged.command.d.ts.map +1 -1
  50. package/dist/commands/cleanup/merged.command.js +24 -0
  51. package/dist/commands/doctor/branch-pr.d.ts +4 -0
  52. package/dist/commands/doctor/branch-pr.d.ts.map +1 -0
  53. package/dist/commands/doctor/branch-pr.js +96 -0
  54. package/dist/commands/doctor/fixes.d.ts +5 -0
  55. package/dist/commands/doctor/fixes.d.ts.map +1 -1
  56. package/dist/commands/doctor/fixes.js +70 -0
  57. package/dist/commands/doctor.run.d.ts.map +1 -1
  58. package/dist/commands/doctor.run.js +6 -1
  59. package/dist/commands/finish.run.d.ts.map +1 -1
  60. package/dist/commands/finish.run.js +11 -0
  61. package/dist/commands/finish.spec.d.ts +11 -0
  62. package/dist/commands/finish.spec.d.ts.map +1 -1
  63. package/dist/commands/finish.spec.js +51 -0
  64. package/dist/commands/guard/impl/close-message.d.ts.map +1 -1
  65. package/dist/commands/guard/impl/close-message.js +23 -6
  66. package/dist/commands/guard/impl/commands.d.ts +1 -0
  67. package/dist/commands/guard/impl/commands.d.ts.map +1 -1
  68. package/dist/commands/guard/impl/commands.js +94 -2
  69. package/dist/commands/guard/impl/env.d.ts +1 -0
  70. package/dist/commands/guard/impl/env.d.ts.map +1 -1
  71. package/dist/commands/guard/impl/env.js +1 -0
  72. package/dist/commands/hooks/index.d.ts +1 -1
  73. package/dist/commands/hooks/index.d.ts.map +1 -1
  74. package/dist/commands/hooks/index.js +139 -6
  75. package/dist/commands/incidents/collect.command.d.ts.map +1 -1
  76. package/dist/commands/incidents/collect.command.js +12 -7
  77. package/dist/commands/incidents/incidents.command.js +1 -1
  78. package/dist/commands/incidents/shared.d.ts +34 -0
  79. package/dist/commands/incidents/shared.d.ts.map +1 -1
  80. package/dist/commands/incidents/shared.js +166 -12
  81. package/dist/commands/pr/check.d.ts.map +1 -1
  82. package/dist/commands/pr/check.js +241 -135
  83. package/dist/commands/pr/close-superseded.d.ts +9 -0
  84. package/dist/commands/pr/close-superseded.d.ts.map +1 -0
  85. package/dist/commands/pr/close-superseded.js +129 -0
  86. package/dist/commands/pr/close.d.ts +11 -0
  87. package/dist/commands/pr/close.d.ts.map +1 -0
  88. package/dist/commands/pr/close.js +116 -0
  89. package/dist/commands/pr/index.d.ts +2 -0
  90. package/dist/commands/pr/index.d.ts.map +1 -1
  91. package/dist/commands/pr/index.js +2 -0
  92. package/dist/commands/pr/integrate/artifacts.d.ts +7 -0
  93. package/dist/commands/pr/integrate/artifacts.d.ts.map +1 -1
  94. package/dist/commands/pr/integrate/artifacts.js +66 -1
  95. package/dist/commands/pr/integrate/cmd.d.ts.map +1 -1
  96. package/dist/commands/pr/integrate/cmd.js +43 -2
  97. package/dist/commands/pr/integrate/internal/bootstrap-guidance.d.ts +8 -0
  98. package/dist/commands/pr/integrate/internal/bootstrap-guidance.d.ts.map +1 -0
  99. package/dist/commands/pr/integrate/internal/bootstrap-guidance.js +59 -0
  100. package/dist/commands/pr/integrate/internal/cleanup.d.ts +1 -11
  101. package/dist/commands/pr/integrate/internal/cleanup.d.ts.map +1 -1
  102. package/dist/commands/pr/integrate/internal/cleanup.js +1 -46
  103. package/dist/commands/pr/integrate/internal/finalize.d.ts.map +1 -1
  104. package/dist/commands/pr/integrate/internal/finalize.js +43 -12
  105. package/dist/commands/pr/integrate/internal/github-protection.d.ts +5 -0
  106. package/dist/commands/pr/integrate/internal/github-protection.d.ts.map +1 -0
  107. package/dist/commands/pr/integrate/internal/github-protection.js +13 -0
  108. package/dist/commands/pr/integrate/internal/merge.d.ts.map +1 -1
  109. package/dist/commands/pr/integrate/internal/merge.js +36 -13
  110. package/dist/commands/pr/integrate/internal/post-integrate-bootstrap.d.ts +13 -0
  111. package/dist/commands/pr/integrate/internal/post-integrate-bootstrap.d.ts.map +1 -0
  112. package/dist/commands/pr/integrate/internal/post-integrate-bootstrap.js +25 -0
  113. package/dist/commands/pr/integrate/internal/pre-integrate-bootstrap.d.ts +15 -0
  114. package/dist/commands/pr/integrate/internal/pre-integrate-bootstrap.d.ts.map +1 -0
  115. package/dist/commands/pr/integrate/internal/pre-integrate-bootstrap.js +35 -0
  116. package/dist/commands/pr/integrate/internal/prepare.d.ts +4 -2
  117. package/dist/commands/pr/integrate/internal/prepare.d.ts.map +1 -1
  118. package/dist/commands/pr/integrate/internal/prepare.js +109 -38
  119. package/dist/commands/pr/internal/auto-commit.d.ts +7 -0
  120. package/dist/commands/pr/internal/auto-commit.d.ts.map +1 -0
  121. package/dist/commands/pr/internal/auto-commit.js +64 -0
  122. package/dist/commands/pr/internal/freshness.d.ts +21 -0
  123. package/dist/commands/pr/internal/freshness.d.ts.map +1 -0
  124. package/dist/commands/pr/internal/freshness.js +52 -0
  125. package/dist/commands/pr/internal/gh-api.d.ts +6 -0
  126. package/dist/commands/pr/internal/gh-api.d.ts.map +1 -0
  127. package/dist/commands/pr/internal/gh-api.js +80 -0
  128. package/dist/commands/pr/internal/pr-paths.d.ts +10 -0
  129. package/dist/commands/pr/internal/pr-paths.d.ts.map +1 -1
  130. package/dist/commands/pr/internal/pr-paths.js +10 -0
  131. package/dist/commands/pr/internal/review-template.d.ts.map +1 -1
  132. package/dist/commands/pr/internal/review-template.js +37 -4
  133. package/dist/commands/pr/internal/sync.d.ts +9 -0
  134. package/dist/commands/pr/internal/sync.d.ts.map +1 -1
  135. package/dist/commands/pr/internal/sync.js +531 -124
  136. package/dist/commands/pr/open.d.ts +1 -0
  137. package/dist/commands/pr/open.d.ts.map +1 -1
  138. package/dist/commands/pr/open.js +24 -2
  139. package/dist/commands/pr/pr.command.d.ts +15 -0
  140. package/dist/commands/pr/pr.command.d.ts.map +1 -1
  141. package/dist/commands/pr/pr.command.js +118 -2
  142. package/dist/commands/pr/update.d.ts.map +1 -1
  143. package/dist/commands/pr/update.js +71 -2
  144. package/dist/commands/release/apply.command.d.ts +3 -1
  145. package/dist/commands/release/apply.command.d.ts.map +1 -1
  146. package/dist/commands/release/apply.command.js +356 -34
  147. package/dist/commands/release/apply.mutation.d.ts.map +1 -1
  148. package/dist/commands/release/apply.mutation.js +1 -0
  149. package/dist/commands/release/apply.preflight.d.ts.map +1 -1
  150. package/dist/commands/release/apply.preflight.js +1 -1
  151. package/dist/commands/release/apply.reporting.d.ts +1 -0
  152. package/dist/commands/release/apply.reporting.d.ts.map +1 -1
  153. package/dist/commands/release/apply.reporting.js +12 -8
  154. package/dist/commands/release/apply.types.d.ts +13 -0
  155. package/dist/commands/release/apply.types.d.ts.map +1 -1
  156. package/dist/commands/release/plan.command.d.ts.map +1 -1
  157. package/dist/commands/release/plan.command.js +48 -0
  158. package/dist/commands/shared/gh-transport.d.ts +16 -0
  159. package/dist/commands/shared/gh-transport.d.ts.map +1 -0
  160. package/dist/commands/shared/gh-transport.js +71 -0
  161. package/dist/commands/shared/git-diff.d.ts +3 -1
  162. package/dist/commands/shared/git-diff.d.ts.map +1 -1
  163. package/dist/commands/shared/git-diff.js +10 -2
  164. package/dist/commands/shared/git-ops.d.ts +1 -0
  165. package/dist/commands/shared/git-ops.d.ts.map +1 -1
  166. package/dist/commands/shared/git-ops.js +15 -0
  167. package/dist/commands/shared/git-worktree.d.ts +2 -0
  168. package/dist/commands/shared/git-worktree.d.ts.map +1 -1
  169. package/dist/commands/shared/git-worktree.js +22 -2
  170. package/dist/commands/shared/merged-branch-cleanup.d.ts +12 -0
  171. package/dist/commands/shared/merged-branch-cleanup.d.ts.map +1 -0
  172. package/dist/commands/shared/merged-branch-cleanup.js +46 -0
  173. package/dist/commands/shared/post-commit-pr-artifacts.d.ts +9 -0
  174. package/dist/commands/shared/post-commit-pr-artifacts.d.ts.map +1 -0
  175. package/dist/commands/shared/post-commit-pr-artifacts.js +57 -0
  176. package/dist/commands/shared/pr-meta.d.ts +20 -0
  177. package/dist/commands/shared/pr-meta.d.ts.map +1 -1
  178. package/dist/commands/shared/pr-meta.js +125 -0
  179. package/dist/commands/shared/task-backend.d.ts +7 -0
  180. package/dist/commands/shared/task-backend.d.ts.map +1 -1
  181. package/dist/commands/shared/task-backend.js +71 -27
  182. package/dist/commands/shared/task-local-freshness.d.ts +2 -0
  183. package/dist/commands/shared/task-local-freshness.d.ts.map +1 -1
  184. package/dist/commands/shared/task-local-freshness.js +7 -1
  185. package/dist/commands/task/close-duplicate.d.ts.map +1 -1
  186. package/dist/commands/task/close-duplicate.js +34 -1
  187. package/dist/commands/task/derive.js +1 -1
  188. package/dist/commands/task/doc-template.d.ts.map +1 -1
  189. package/dist/commands/task/doc-template.js +7 -11
  190. package/dist/commands/task/findings-add.command.d.ts +20 -0
  191. package/dist/commands/task/findings-add.command.d.ts.map +1 -0
  192. package/dist/commands/task/findings-add.command.js +165 -0
  193. package/dist/commands/task/findings.command.d.ts +7 -0
  194. package/dist/commands/task/findings.command.d.ts.map +1 -0
  195. package/dist/commands/task/findings.command.js +20 -0
  196. package/dist/commands/task/findings.d.ts +63 -0
  197. package/dist/commands/task/findings.d.ts.map +1 -0
  198. package/dist/commands/task/findings.js +188 -0
  199. package/dist/commands/task/finish-shared.d.ts +2 -0
  200. package/dist/commands/task/finish-shared.d.ts.map +1 -1
  201. package/dist/commands/task/finish-shared.js +56 -1
  202. package/dist/commands/task/finish.d.ts +10 -0
  203. package/dist/commands/task/finish.d.ts.map +1 -1
  204. package/dist/commands/task/finish.js +125 -6
  205. package/dist/commands/task/hosted-close-pr.command.d.ts +11 -0
  206. package/dist/commands/task/hosted-close-pr.command.d.ts.map +1 -0
  207. package/dist/commands/task/hosted-close-pr.command.js +449 -0
  208. package/dist/commands/task/hosted-close.command.d.ts.map +1 -1
  209. package/dist/commands/task/hosted-close.command.js +234 -19
  210. package/dist/commands/task/hosted-merge-sync.d.ts +41 -0
  211. package/dist/commands/task/hosted-merge-sync.d.ts.map +1 -1
  212. package/dist/commands/task/hosted-merge-sync.js +291 -17
  213. package/dist/commands/task/index.d.ts +1 -0
  214. package/dist/commands/task/index.d.ts.map +1 -1
  215. package/dist/commands/task/index.js +1 -0
  216. package/dist/commands/task/new.d.ts +1 -0
  217. package/dist/commands/task/new.d.ts.map +1 -1
  218. package/dist/commands/task/new.js +71 -1
  219. package/dist/commands/task/new.spec.d.ts.map +1 -1
  220. package/dist/commands/task/new.spec.js +7 -0
  221. package/dist/commands/task/normalize.command.d.ts +2 -0
  222. package/dist/commands/task/normalize.command.d.ts.map +1 -1
  223. package/dist/commands/task/normalize.command.js +45 -0
  224. package/dist/commands/task/normalize.d.ts +2 -0
  225. package/dist/commands/task/normalize.d.ts.map +1 -1
  226. package/dist/commands/task/normalize.js +85 -8
  227. package/dist/commands/task/plan.d.ts.map +1 -1
  228. package/dist/commands/task/plan.js +7 -10
  229. package/dist/commands/task/shared/docs.d.ts +6 -0
  230. package/dist/commands/task/shared/docs.d.ts.map +1 -1
  231. package/dist/commands/task/shared/docs.js +14 -0
  232. package/dist/commands/task/shared/transitions.d.ts.map +1 -1
  233. package/dist/commands/task/shared/transitions.js +11 -1
  234. package/dist/commands/task/shared.d.ts +1 -1
  235. package/dist/commands/task/shared.d.ts.map +1 -1
  236. package/dist/commands/task/shared.js +1 -1
  237. package/dist/commands/task/start.d.ts.map +1 -1
  238. package/dist/commands/task/start.js +7 -10
  239. package/dist/commands/task/task.command.d.ts.map +1 -1
  240. package/dist/commands/task/task.command.js +4 -0
  241. package/dist/commands/task/verify-command-shared.d.ts +19 -0
  242. package/dist/commands/task/verify-command-shared.d.ts.map +1 -1
  243. package/dist/commands/task/verify-command-shared.js +152 -1
  244. package/dist/commands/task/verify-ok.command.d.ts.map +1 -1
  245. package/dist/commands/task/verify-ok.command.js +15 -2
  246. package/dist/commands/task/verify-record.d.ts +36 -0
  247. package/dist/commands/task/verify-record.d.ts.map +1 -1
  248. package/dist/commands/task/verify-record.js +166 -11
  249. package/dist/commands/task/verify-rework.command.d.ts.map +1 -1
  250. package/dist/commands/task/verify-rework.command.js +15 -2
  251. package/dist/commands/task/verify-show.command.d.ts +1 -1
  252. package/dist/commands/task/verify-show.command.d.ts.map +1 -1
  253. package/dist/commands/task/verify-show.command.js +28 -1
  254. package/dist/commands/verify.run.d.ts.map +1 -1
  255. package/dist/commands/verify.run.js +12 -0
  256. package/dist/commands/verify.spec.d.ts +2 -6
  257. package/dist/commands/verify.spec.d.ts.map +1 -1
  258. package/dist/commands/verify.spec.js +30 -3
  259. package/dist/runtime/incidents/index.d.ts +1 -1
  260. package/dist/runtime/incidents/index.d.ts.map +1 -1
  261. package/dist/runtime/incidents/resolve.d.ts.map +1 -1
  262. package/dist/runtime/incidents/resolve.js +319 -73
  263. package/dist/runtime/incidents/types.d.ts +14 -2
  264. package/dist/runtime/incidents/types.d.ts.map +1 -1
  265. package/dist/shared/env.d.ts +1 -0
  266. package/dist/shared/env.d.ts.map +1 -1
  267. package/dist/shared/env.js +22 -1
  268. package/dist/shared/protected-paths.d.ts +1 -1
  269. package/dist/shared/protected-paths.d.ts.map +1 -1
  270. package/dist/shared/protected-paths.js +4 -0
  271. package/package.json +2 -2
@@ -8,11 +8,13 @@ import { gitDiffStat } from "../../../shared/git-diff.js";
8
8
  import { appendVerifyLog, buildIntegratedPrMeta, parsePrMeta, } from "../../../shared/pr-meta.js";
9
9
  import { readCommitInfo } from "../../../task/shared.js";
10
10
  import { createTaskCloseCommit, writeFinishedTasks } from "../../../task/finish-shared.js";
11
+ import { collectTaskIncidents, renderIncidentCollectionPlanOutcome, } from "../../../incidents/shared.js";
11
12
  function nowIso() {
12
13
  return new Date().toISOString();
13
14
  }
14
15
  export async function finalizeIntegrate(opts) {
15
16
  const output = createCliEmitter();
17
+ const taskAlreadyDone = String(opts.task.status || "TODO").toUpperCase() === "DONE";
16
18
  if (!(await fileExists(opts.prDir))) {
17
19
  throw new CliError({
18
20
  exitCode: 3,
@@ -52,20 +54,45 @@ export async function finalizeIntegrate(opts) {
52
54
  : "skipped";
53
55
  const finishBody = `Verified: Integrated via ${opts.mergeStrategy}; verify=${verifyDesc}; pr=${path.relative(opts.gitRoot, opts.prDir)}.`;
54
56
  const resultSummary = `integrate: ${opts.mergeStrategy} ${opts.branch}`;
55
- const taskCommitInfo = await readCommitInfo(opts.gitRoot, opts.mergeHash);
56
- await writeFinishedTasks({
57
+ await collectTaskIncidents({
57
58
  ctx: opts.ctx,
58
- loadedTasks: [{ taskId: opts.taskId, task: opts.task }],
59
- metaTaskId: opts.taskId,
60
- author: "INTEGRATOR",
61
- body: finishBody,
62
- force: false,
63
- resultProvided: true,
64
- resultSummary,
65
- riskLevel: undefined,
66
- breaking: false,
67
- taskCommitInfo,
59
+ taskId: opts.taskId,
60
+ task: opts.task,
61
+ write: false,
68
62
  });
63
+ if (!taskAlreadyDone) {
64
+ const taskCommitInfo = await readCommitInfo(opts.gitRoot, opts.mergeHash);
65
+ await writeFinishedTasks({
66
+ ctx: opts.ctx,
67
+ loadedTasks: [{ taskId: opts.taskId, task: opts.task }],
68
+ metaTaskId: opts.taskId,
69
+ author: "INTEGRATOR",
70
+ body: finishBody,
71
+ force: false,
72
+ resultProvided: true,
73
+ resultSummary,
74
+ riskLevel: undefined,
75
+ breaking: false,
76
+ taskCommitInfo,
77
+ });
78
+ }
79
+ const collectedIncidents = await collectTaskIncidents({
80
+ ctx: opts.ctx,
81
+ taskId: opts.taskId,
82
+ task: opts.task,
83
+ write: true,
84
+ });
85
+ if (!opts.quiet) {
86
+ output.info(renderIncidentCollectionPlanOutcome(collectedIncidents.plan, {
87
+ wrote: collectedIncidents.wrote,
88
+ context: "finish",
89
+ promotedIds: collectedIncidents.plan.promotable.map((item) => item.entry.id),
90
+ registryPaths: collectedIncidents.registryPaths,
91
+ }));
92
+ if (taskAlreadyDone) {
93
+ output.info("task already DONE; integrating only missing PR metadata and close artifacts");
94
+ }
95
+ }
69
96
  await createTaskCloseCommit({
70
97
  ctx: opts.ctx,
71
98
  cwd: opts.cwd,
@@ -73,6 +100,10 @@ export async function finalizeIntegrate(opts) {
73
100
  taskId: opts.taskId,
74
101
  baseBranchOverride: opts.base,
75
102
  quiet: opts.quiet,
103
+ allowPolicy: collectedIncidents.wrote,
104
+ // finalizeIntegrate already wrote the canonical MERGED task packet on the base checkout.
105
+ // Re-running branch-side PR artifact refresh here can regress pr/meta.json back to OPEN.
106
+ closeRefreshTaskArtifacts: false,
76
107
  });
77
108
  if (!opts.quiet) {
78
109
  output.success("integrate", opts.taskId, `merge=${opts.mergeHash.slice(0, 12)}`);
@@ -0,0 +1,5 @@
1
+ export declare function requiresPullRequestMergePath(opts: {
2
+ gitRoot: string;
3
+ baseBranch: string;
4
+ }): Promise<boolean>;
5
+ //# sourceMappingURL=github-protection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-protection.d.ts","sourceRoot":"","sources":["../../../../../src/commands/pr/integrate/internal/github-protection.ts"],"names":[],"mappings":"AAMA,wBAAsB,4BAA4B,CAAC,IAAI,EAAE;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,OAAO,CAAC,CAUnB"}
@@ -0,0 +1,13 @@
1
+ import { resolveDefaultGithubRepo, runGhApiJson } from "../../internal/gh-api.js";
2
+ export async function requiresPullRequestMergePath(opts) {
3
+ try {
4
+ const repo = await resolveDefaultGithubRepo(opts.gitRoot);
5
+ const protection = await runGhApiJson(opts.gitRoot, [
6
+ `repos/${repo}/branches/${opts.baseBranch}/protection`,
7
+ ]);
8
+ return protection.required_pull_request_reviews !== undefined;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../../../../src/commands/pr/integrate/internal/merge.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AA6HzD,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiFlB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkClB;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,GAAG,OAAO,CAAC;IACV,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACrD,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC,CA8DD"}
1
+ {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../../../../src/commands/pr/integrate/internal/merge.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AA+JzD,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB,GAAG,OAAO,CAAC,MAAM,CAAC,CAqFlB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BlB;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,GAAG,OAAO,CAAC;IACV,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACrD,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC,CA8DD"}
@@ -8,6 +8,20 @@ import { gitRevParse } from "../../../shared/git-ops.js";
8
8
  import { buildGithubPrTitle } from "../../internal/review-template.js";
9
9
  import { computeVerifyState, runVerifyCommands } from "../verify.js";
10
10
  const noopPromise = () => Promise.resolve();
11
+ function integrateCommitEnv(taskId) {
12
+ return {
13
+ ...gitEnv(),
14
+ AGENTPLANE_TASK_ID: taskId,
15
+ AGENTPLANE_ALLOW_BASE: "1",
16
+ AGENTPLANE_ALLOW_TASKS: "1",
17
+ AGENTPLANE_ALLOW_CONFIG: "1",
18
+ AGENTPLANE_DEV_ALLOW_STALE_DIST: "1",
19
+ };
20
+ }
21
+ function isTaskArtifactPath(filePath) {
22
+ const normalized = filePath.replaceAll("\\", "/");
23
+ return normalized.startsWith(".agentplane/tasks/") || normalized.startsWith("tasks/");
24
+ }
11
25
  function fallbackIntegrateSummary(opts) {
12
26
  const suffix = extractTaskSuffix(opts.taskId);
13
27
  return buildGithubPrTitle({
@@ -34,6 +48,16 @@ async function listUntrackedTaskArtifacts(opts) {
34
48
  .map((line) => line.slice(3).trim())
35
49
  .filter(Boolean);
36
50
  }
51
+ async function listCommitChangedPaths(opts) {
52
+ const { stdout } = await execFileAsync("git", ["show", "--name-only", "--format=", opts.revision], {
53
+ cwd: opts.gitRoot,
54
+ env: gitEnv(),
55
+ });
56
+ return stdout
57
+ .split("\n")
58
+ .map((line) => line.trim())
59
+ .filter(Boolean);
60
+ }
37
61
  async function moveCollidingTaskArtifacts(opts) {
38
62
  const taskPrefix = `${opts.workflowDir.replaceAll("\\", "/")}/${opts.taskId}`;
39
63
  const candidatePaths = opts.changedPaths.filter((changedPath) => changedPath === taskPrefix || changedPath.startsWith(`${taskPrefix}/`));
@@ -133,16 +157,20 @@ export async function runSquashMerge(opts) {
133
157
  taskId: opts.taskId,
134
158
  genericTokens: opts.genericTokens,
135
159
  });
136
- if (!subjectPolicy.ok) {
160
+ let shouldFallback = !subjectPolicy.ok;
161
+ if (!shouldFallback) {
162
+ const headPaths = await listCommitChangedPaths({
163
+ gitRoot: opts.gitRoot,
164
+ revision: opts.branch,
165
+ });
166
+ shouldFallback =
167
+ headPaths.length > 0 && headPaths.every((filePath) => isTaskArtifactPath(filePath));
168
+ }
169
+ if (shouldFallback) {
137
170
  const suffix = extractTaskSuffix(opts.taskId);
138
171
  subject = `🧩 ${suffix} integrate: ${fallbackIntegrateSummary(opts)}`;
139
172
  }
140
- const env = {
141
- ...process.env,
142
- AGENTPLANE_TASK_ID: opts.taskId,
143
- AGENTPLANE_ALLOW_BASE: "1",
144
- AGENTPLANE_ALLOW_TASKS: "0",
145
- };
173
+ const env = integrateCommitEnv(opts.taskId);
146
174
  try {
147
175
  await execFileAsync("git", ["commit", "-m", subject], {
148
176
  cwd: opts.gitRoot,
@@ -169,12 +197,7 @@ export async function runMergeCommit(opts) {
169
197
  taskId: opts.taskId,
170
198
  changedPaths: opts.changedPaths,
171
199
  });
172
- const env = {
173
- ...process.env,
174
- AGENTPLANE_TASK_ID: opts.taskId,
175
- AGENTPLANE_ALLOW_BASE: "1",
176
- AGENTPLANE_ALLOW_TASKS: "0",
177
- };
200
+ const env = integrateCommitEnv(opts.taskId);
178
201
  try {
179
202
  await execFileAsync("git", [
180
203
  "merge",
@@ -0,0 +1,13 @@
1
+ export type PostIntegrateBootstrapResult = {
2
+ status: "skipped";
3
+ } | {
4
+ status: "ran";
5
+ } | {
6
+ status: "failed";
7
+ error: string;
8
+ };
9
+ export declare function maybeRunPostIntegrateBootstrap(opts: {
10
+ gitRoot: string;
11
+ changedPaths: string[];
12
+ }): Promise<PostIntegrateBootstrapResult>;
13
+ //# sourceMappingURL=post-integrate-bootstrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-integrate-bootstrap.d.ts","sourceRoot":"","sources":["../../../../../src/commands/pr/integrate/internal/post-integrate-bootstrap.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,4BAA4B,GACpC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,KAAK,CAAA;CAAE,GACjB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAUxC,wBAAsB,8BAA8B,CAAC,IAAI,EAAE;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAcxC"}
@@ -0,0 +1,25 @@
1
+ import { execFileAsync } from "../../../shared/git.js";
2
+ import { shouldAutoBootstrapAfterIntegrate } from "./bootstrap-guidance.js";
3
+ function compactError(err) {
4
+ if (err instanceof Error) {
5
+ const text = err.message.trim();
6
+ return text.length > 0 ? text : err.name;
7
+ }
8
+ return String(err);
9
+ }
10
+ export async function maybeRunPostIntegrateBootstrap(opts) {
11
+ if (!shouldAutoBootstrapAfterIntegrate(opts)) {
12
+ return { status: "skipped" };
13
+ }
14
+ try {
15
+ await execFileAsync("bun", ["run", "framework:dev:bootstrap"], {
16
+ cwd: opts.gitRoot,
17
+ env: { ...process.env },
18
+ maxBuffer: 50 * 1024 * 1024,
19
+ });
20
+ return { status: "ran" };
21
+ }
22
+ catch (err) {
23
+ return { status: "failed", error: compactError(err) };
24
+ }
25
+ }
@@ -0,0 +1,15 @@
1
+ export type PreIntegrateBootstrapResult = {
2
+ status: "not-needed";
3
+ } | {
4
+ status: "skipped";
5
+ } | {
6
+ status: "ran";
7
+ } | {
8
+ status: "failed";
9
+ error: string;
10
+ };
11
+ export declare function maybeRunPreIntegrateBootstrap(opts: {
12
+ gitRoot: string;
13
+ changedPaths: string[];
14
+ }): Promise<PreIntegrateBootstrapResult>;
15
+ //# sourceMappingURL=pre-integrate-bootstrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pre-integrate-bootstrap.d.ts","sourceRoot":"","sources":["../../../../../src/commands/pr/integrate/internal/pre-integrate-bootstrap.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,2BAA2B,GACnC;IAAE,MAAM,EAAE,YAAY,CAAA;CAAE,GACxB;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,KAAK,CAAA;CAAE,GACjB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAkBxC,wBAAsB,6BAA6B,CAAC,IAAI,EAAE;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAiBvC"}
@@ -0,0 +1,35 @@
1
+ import { existsSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { execFileAsync } from "../../../shared/git.js";
4
+ import { shouldAutoBootstrapAfterIntegrate } from "./bootstrap-guidance.js";
5
+ function compactError(err) {
6
+ if (err instanceof Error) {
7
+ const text = err.message.trim();
8
+ return text.length > 0 ? text : err.name;
9
+ }
10
+ return String(err);
11
+ }
12
+ function baseRuntimeReady(gitRoot) {
13
+ return (existsSync(path.join(gitRoot, "node_modules")) &&
14
+ existsSync(path.join(gitRoot, "packages", "agentplane", "node_modules")) &&
15
+ existsSync(path.join(gitRoot, "packages", "agentplane", "dist", "cli.js")));
16
+ }
17
+ export async function maybeRunPreIntegrateBootstrap(opts) {
18
+ if (baseRuntimeReady(opts.gitRoot)) {
19
+ return { status: "not-needed" };
20
+ }
21
+ if (!shouldAutoBootstrapAfterIntegrate(opts)) {
22
+ return { status: "skipped" };
23
+ }
24
+ try {
25
+ await execFileAsync("bun", ["run", "framework:dev:bootstrap"], {
26
+ cwd: opts.gitRoot,
27
+ env: { ...process.env },
28
+ maxBuffer: 50 * 1024 * 1024,
29
+ });
30
+ return { status: "ran" };
31
+ }
32
+ catch (err) {
33
+ return { status: "failed", error: compactError(err) };
34
+ }
35
+ }
@@ -1,12 +1,14 @@
1
- import { loadBackendTask, type CommandContext } from "../../../shared/task-backend.js";
1
+ import type { TaskData } from "../../../../backends/task-backend.js";
2
+ import { type CommandContext } from "../../../shared/task-backend.js";
2
3
  import { type PrMeta } from "../../../shared/pr-meta.js";
3
4
  export type PreparedIntegrate = {
4
5
  ctx: CommandContext;
5
6
  resolved: CommandContext["resolvedProject"];
6
7
  loadedConfig: CommandContext["config"];
7
- task: Awaited<ReturnType<typeof loadBackendTask>>["task"];
8
+ task: TaskData;
8
9
  baseBranch: string;
9
10
  currentBranch: string;
11
+ protectedBaseRequiresPrMerge: boolean;
10
12
  prDir: string;
11
13
  metaPath: string;
12
14
  diffstatPath: string;
@@ -1 +1 @@
1
- {"version":3,"file":"prepare.d.ts","sourceRoot":"","sources":["../../../../../src/commands/pr/integrate/internal/prepare.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,eAAe,EAEf,KAAK,cAAc,EACpB,MAAM,iCAAiC,CAAC;AAUzC,OAAO,EAAe,KAAK,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAGtE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,cAAc,CAAC;IACpB,QAAQ,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAC;IAC5C,YAAY,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAE1D,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IAEtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IAEtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IAEb,aAAa,EAAE,MAAM,CAAC;IAEtB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;CACpB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAoL7B"}
1
+ {"version":3,"file":"prepare.d.ts","sourceRoot":"","sources":["../../../../../src/commands/pr/integrate/internal/prepare.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAUrE,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,iCAAiC,CAAC;AAWzC,OAAO,EAAgC,KAAK,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAIvF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,cAAc,CAAC;IACpB,QAAQ,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAC;IAC5C,YAAY,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,EAAE,QAAQ,CAAC;IAEf,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,4BAA4B,EAAE,OAAO,CAAC;IAEtC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IAEtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IAEb,aAAa,EAAE,MAAM,CAAC;IAEtB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;CACpB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAgP7B"}
@@ -6,24 +6,21 @@ import { exitCodeForError } from "../../../../cli/exit-codes.js";
6
6
  import { unknownEntityMessage, workflowModeMessage } from "../../../../cli/output.js";
7
7
  import { CliError } from "../../../../shared/errors.js";
8
8
  import { ensureGitClean } from "../../../guard/index.js";
9
- import { gitDiffNames, gitShowFile, toGitPath } from "../../../shared/git-diff.js";
9
+ import { gitDiffNames } from "../../../shared/git-diff.js";
10
10
  import { gitBranchExists, gitCurrentBranch, gitRevParse } from "../../../shared/git-ops.js";
11
- import { loadBackendTask, loadCommandContext, } from "../../../shared/task-backend.js";
11
+ import { findWorktreeForBranch } from "../../../shared/git-worktree.js";
12
+ import { loadCommandContext, loadTaskFromContext, resolveTaskBranchFromContext, } from "../../../shared/task-backend.js";
12
13
  import { ensurePlanApprovedIfRequired, ensureVerificationSatisfiedIfRequired, } from "../../../task/shared.js";
13
- import { resolvePrPaths } from "../../internal/pr-paths.js";
14
- import { readAndValidatePrArtifacts } from "../artifacts.js";
14
+ import { readPrArtifact, resolvePrPaths } from "../../internal/pr-paths.js";
15
+ import { ensurePrArtifactsSynced } from "../../internal/sync.js";
16
+ import { readAndValidatePrArtifacts, ensureCommittedPrArtifactsOnBranch } from "../artifacts.js";
15
17
  import { computeVerifyState } from "../verify.js";
16
- import { parsePrMeta } from "../../../shared/pr-meta.js";
17
- import { isTaskLocalOnlyAdvance } from "../../../shared/task-local-freshness.js";
18
+ import { parsePrMetaForwardCompatible } from "../../../shared/pr-meta.js";
19
+ import { assessPrArtifactFreshness } from "../../internal/freshness.js";
20
+ import { requiresPullRequestMergePath } from "./github-protection.js";
18
21
  export async function prepareIntegrate(opts) {
19
22
  const ctx = opts.ctx ??
20
23
  (await loadCommandContext({ cwd: opts.cwd, rootOverride: opts.rootOverride ?? null }));
21
- const { task } = await loadBackendTask({
22
- ctx,
23
- cwd: opts.cwd,
24
- rootOverride: opts.rootOverride,
25
- taskId: opts.taskId,
26
- });
27
24
  const resolved = ctx.resolvedProject;
28
25
  const loadedConfig = ctx.config;
29
26
  if (loadedConfig.workflow_mode !== "branch_pr") {
@@ -33,8 +30,6 @@ export async function prepareIntegrate(opts) {
33
30
  message: workflowModeMessage(loadedConfig.workflow_mode, "branch_pr"),
34
31
  });
35
32
  }
36
- ensurePlanApprovedIfRequired(task, loadedConfig);
37
- ensureVerificationSatisfiedIfRequired(task, loadedConfig);
38
33
  await ensureGitClean({ cwd: opts.cwd, rootOverride: opts.rootOverride });
39
34
  if (opts.base?.trim().length === 0) {
40
35
  throw new CliError({
@@ -73,10 +68,16 @@ export async function prepareIntegrate(opts) {
73
68
  let meta = null;
74
69
  let branch = (opts.branch ?? "").trim();
75
70
  if (await fileExists(metaPath)) {
76
- meta = parsePrMeta(await readFile(metaPath, "utf8"), task.id);
71
+ meta = parsePrMetaForwardCompatible(await readFile(metaPath, "utf8"), opts.taskId);
77
72
  if (!branch)
78
73
  branch = (meta.branch ?? "").trim();
79
74
  }
75
+ if (!branch) {
76
+ const inferredBranch = await resolveTaskBranchFromContext({ ctx, taskId: opts.taskId });
77
+ if (inferredBranch) {
78
+ branch = inferredBranch;
79
+ }
80
+ }
80
81
  if (!branch) {
81
82
  throw new CliError({
82
83
  exitCode: 2,
@@ -91,8 +92,27 @@ export async function prepareIntegrate(opts) {
91
92
  message: unknownEntityMessage("branch", branch),
92
93
  });
93
94
  }
94
- const metaSource = meta ??
95
- parsePrMeta(await gitShowFile(resolved.gitRoot, branch, toGitPath(path.relative(resolved.gitRoot, metaPath))), task.id);
95
+ await ensureCommittedPrArtifactsOnBranch({
96
+ resolved,
97
+ prDir,
98
+ branch,
99
+ });
100
+ const worktreePath = await findWorktreeForBranch(resolved.gitRoot, branch);
101
+ const metaText = await readPrArtifact({
102
+ resolved,
103
+ prDir,
104
+ fileName: "meta.json",
105
+ branch,
106
+ worktreePath,
107
+ });
108
+ if (!metaText) {
109
+ throw new CliError({
110
+ exitCode: 4,
111
+ code: "E_IO",
112
+ message: `PR artifacts missing: ${path.relative(resolved.gitRoot, metaPath)} (run \`agentplane pr open\`)`,
113
+ });
114
+ }
115
+ let metaSource = parsePrMetaForwardCompatible(metaText, opts.taskId);
96
116
  const baseCandidate = opts.base ?? metaSource.base ?? baseBranch;
97
117
  const base = typeof baseCandidate === "string" && baseCandidate.trim().length > 0
98
118
  ? baseCandidate.trim()
@@ -103,10 +123,20 @@ export async function prepareIntegrate(opts) {
103
123
  prDir,
104
124
  metaPath,
105
125
  branch,
106
- taskId: task.id,
126
+ taskId: opts.taskId,
107
127
  });
108
128
  // readAndValidatePrArtifacts() throws if verify.log is missing; keep this non-null downstream.
109
- const verifyLogText = verifyLogTextMaybe;
129
+ let verifyLogText = verifyLogTextMaybe;
130
+ const task = await loadTaskFromContext({
131
+ ctx,
132
+ taskId: opts.taskId,
133
+ preferBranchSnapshot: true,
134
+ branchSnapshotBranch: branch,
135
+ });
136
+ const protectedBaseRequiresPrMerge = await requiresPullRequestMergePath({
137
+ gitRoot: resolved.gitRoot,
138
+ baseBranch: base,
139
+ });
110
140
  const changedPaths = await gitDiffNames(resolved.gitRoot, base, branch);
111
141
  const tasksPath = loadedConfig.paths.tasks_path;
112
142
  if (changedPaths.includes(tasksPath)) {
@@ -117,33 +147,73 @@ export async function prepareIntegrate(opts) {
117
147
  });
118
148
  }
119
149
  const branchHeadSha = await gitRevParse(resolved.gitRoot, [branch]);
120
- const reviewFresh = (metaSource.head_sha ?? null) === branchHeadSha ||
121
- (await isTaskLocalOnlyAdvance({
122
- gitRoot: resolved.gitRoot,
123
- workflowDir: loadedConfig.paths.workflow_dir,
124
- taskId: task.id,
125
- fromRef: metaSource.head_sha ?? null,
126
- toRef: branchHeadSha,
127
- }));
128
- if (!reviewFresh) {
150
+ let freshness = await assessPrArtifactFreshness({
151
+ gitRoot: resolved.gitRoot,
152
+ workflowDir: loadedConfig.paths.workflow_dir,
153
+ tasksPath: loadedConfig.paths.tasks_path,
154
+ taskId: opts.taskId,
155
+ branchHeadSha,
156
+ metaHeadSha: metaSource.head_sha ?? null,
157
+ metaLastVerifiedSha: metaSource.last_verified_sha ?? null,
158
+ metaVerifyStatus: metaSource.verify?.status ?? null,
159
+ taskVerificationState: task.verification?.state ?? null,
160
+ verifyLogText,
161
+ requiresVerify: Boolean(task.verify && task.verify.length > 0),
162
+ });
163
+ if (!freshness.reviewFresh && worktreePath) {
164
+ await ensurePrArtifactsSynced({
165
+ cwd: worktreePath,
166
+ taskId: opts.taskId,
167
+ branch,
168
+ });
169
+ const repairedMetaText = await readPrArtifact({
170
+ resolved,
171
+ prDir,
172
+ fileName: "meta.json",
173
+ branch,
174
+ worktreePath,
175
+ });
176
+ if (repairedMetaText) {
177
+ const repairedMetaSource = parsePrMetaForwardCompatible(repairedMetaText, opts.taskId);
178
+ const repairedArtifacts = await readAndValidatePrArtifacts({
179
+ ctx,
180
+ resolved,
181
+ prDir,
182
+ metaPath,
183
+ branch,
184
+ taskId: opts.taskId,
185
+ });
186
+ verifyLogText = repairedArtifacts.verifyLogText ?? verifyLogText;
187
+ freshness = await assessPrArtifactFreshness({
188
+ gitRoot: resolved.gitRoot,
189
+ workflowDir: loadedConfig.paths.workflow_dir,
190
+ tasksPath: loadedConfig.paths.tasks_path,
191
+ taskId: opts.taskId,
192
+ branchHeadSha,
193
+ metaHeadSha: repairedMetaSource.head_sha ?? null,
194
+ metaLastVerifiedSha: repairedMetaSource.last_verified_sha ?? null,
195
+ metaVerifyStatus: repairedMetaSource.verify?.status ?? null,
196
+ taskVerificationState: task.verification?.state ?? null,
197
+ verifyLogText,
198
+ requiresVerify: Boolean(task.verify && task.verify.length > 0),
199
+ });
200
+ meta = repairedMetaSource;
201
+ metaSource = repairedMetaSource;
202
+ }
203
+ }
204
+ if (!freshness.reviewFresh) {
129
205
  throw new CliError({
130
206
  exitCode: exitCodeForError("E_VALIDATION"),
131
207
  code: "E_VALIDATION",
132
- message: `PR artifacts stale for ${task.id}: meta.head_sha=${metaSource.head_sha ?? "<missing>"} ` +
208
+ message: `PR artifacts stale for ${opts.taskId}: meta.head_sha=${metaSource.head_sha ?? "<missing>"} ` +
133
209
  `current_head=${branchHeadSha} (refresh the task branch artifacts before integrate)`,
134
210
  });
135
211
  }
136
- const verifyFresh = (metaSource.last_verified_sha ?? null) === branchHeadSha ||
137
- (await isTaskLocalOnlyAdvance({
138
- gitRoot: resolved.gitRoot,
139
- workflowDir: loadedConfig.paths.workflow_dir,
140
- taskId: task.id,
141
- fromRef: metaSource.last_verified_sha ?? null,
142
- toRef: branchHeadSha,
143
- }));
212
+ ensurePlanApprovedIfRequired(task, loadedConfig);
213
+ ensureVerificationSatisfiedIfRequired(task, loadedConfig);
144
214
  const initialVerifyState = computeVerifyState({
145
215
  rawVerify: task.verify,
146
- metaLastVerifiedSha: verifyFresh ? branchHeadSha : (metaSource?.last_verified_sha ?? null),
216
+ metaLastVerifiedSha: freshness.effectiveVerifiedSha,
147
217
  verifyLogText,
148
218
  branchHeadSha,
149
219
  runVerify: opts.runVerify,
@@ -155,6 +225,7 @@ export async function prepareIntegrate(opts) {
155
225
  task,
156
226
  baseBranch,
157
227
  currentBranch,
228
+ protectedBaseRequiresPrMerge,
158
229
  prDir,
159
230
  metaPath,
160
231
  diffstatPath,
@@ -0,0 +1,7 @@
1
+ import type { CommandContext } from "../../shared/task-backend.js";
2
+ export declare function maybeAutoCommitTaskPrArtifacts(opts: {
3
+ ctx: CommandContext;
4
+ taskId: string;
5
+ branch: string;
6
+ }): Promise<boolean>;
7
+ //# sourceMappingURL=auto-commit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-commit.d.ts","sourceRoot":"","sources":["../../../../src/commands/pr/internal/auto-commit.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AA6BnE,wBAAsB,8BAA8B,CAAC,IAAI,EAAE;IACzD,GAAG,EAAE,cAAc,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,OAAO,CAAC,CA8CnB"}
@@ -0,0 +1,64 @@
1
+ import path from "node:path";
2
+ import { extractTaskSuffix } from "@agentplaneorg/core";
3
+ import { buildGitCommitEnv } from "../../guard/impl/env.js";
4
+ import { toGitPath } from "../../shared/git-diff.js";
5
+ import { execFileAsync, gitEnv } from "../../shared/git.js";
6
+ import { gitCurrentBranch } from "../../shared/git-ops.js";
7
+ function taskPrDirPrefix(workflowDir, taskId) {
8
+ return `${toGitPath(path.join(workflowDir, taskId, "pr"))}/`;
9
+ }
10
+ function isTaskPrArtifactPath(opts) {
11
+ return toGitPath(opts.relPath).startsWith(taskPrDirPrefix(opts.workflowDir, opts.taskId));
12
+ }
13
+ async function readCachedPaths(gitRoot) {
14
+ const { stdout } = await execFileAsync("git", ["diff", "--cached", "--name-only", "--relative"], {
15
+ cwd: gitRoot,
16
+ env: gitEnv(),
17
+ });
18
+ return stdout
19
+ .split("\n")
20
+ .map((line) => line.trim())
21
+ .filter((line) => line.length > 0);
22
+ }
23
+ function taskPrArtifactRefreshMessage(taskId) {
24
+ return `📝 ${extractTaskSuffix(taskId)} task: refresh PR artifacts`;
25
+ }
26
+ export async function maybeAutoCommitTaskPrArtifacts(opts) {
27
+ if (opts.ctx.config.workflow_mode !== "branch_pr")
28
+ return false;
29
+ const branchText = await gitCurrentBranch(opts.ctx.resolvedProject.gitRoot);
30
+ const currentBranch = branchText.trim();
31
+ if (!currentBranch || currentBranch !== opts.branch.trim())
32
+ return false;
33
+ const changedPaths = await opts.ctx.git.statusChangedPaths();
34
+ const prArtifactPaths = changedPaths.filter((relPath) => isTaskPrArtifactPath({
35
+ workflowDir: opts.ctx.config.paths.workflow_dir,
36
+ taskId: opts.taskId,
37
+ relPath,
38
+ }));
39
+ if (prArtifactPaths.length === 0)
40
+ return false;
41
+ const cachedPaths = await readCachedPaths(opts.ctx.resolvedProject.gitRoot);
42
+ if (cachedPaths.some((relPath) => !isTaskPrArtifactPath({
43
+ workflowDir: opts.ctx.config.paths.workflow_dir,
44
+ taskId: opts.taskId,
45
+ relPath,
46
+ }))) {
47
+ return false;
48
+ }
49
+ await opts.ctx.git.stage(prArtifactPaths);
50
+ await opts.ctx.git.commit({
51
+ message: taskPrArtifactRefreshMessage(opts.taskId),
52
+ env: buildGitCommitEnv({
53
+ taskId: opts.taskId,
54
+ allowTasks: true,
55
+ allowBase: false,
56
+ allowPolicy: false,
57
+ allowConfig: false,
58
+ allowHooks: false,
59
+ allowCI: false,
60
+ }),
61
+ });
62
+ opts.ctx.git.invalidateStatus();
63
+ return true;
64
+ }
@@ -0,0 +1,21 @@
1
+ export type PrArtifactFreshness = {
2
+ reviewFresh: boolean;
3
+ verifyFresh: boolean;
4
+ verifySatisfied: boolean;
5
+ verifyLogSha: string | null;
6
+ effectiveVerifiedSha: string | null;
7
+ };
8
+ export declare function assessPrArtifactFreshness(opts: {
9
+ gitRoot: string;
10
+ workflowDir: string;
11
+ tasksPath?: string;
12
+ taskId: string;
13
+ branchHeadSha: string;
14
+ metaHeadSha: unknown;
15
+ metaLastVerifiedSha: unknown;
16
+ metaVerifyStatus: unknown;
17
+ taskVerificationState: unknown;
18
+ verifyLogText: string | null;
19
+ requiresVerify: boolean;
20
+ }): Promise<PrArtifactFreshness>;
21
+ //# sourceMappingURL=freshness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"freshness.d.ts","sourceRoot":"","sources":["../../../../src/commands/pr/internal/freshness.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,mBAAmB,GAAG;IAChC,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,EAAE,OAAO,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,CAAC;AAEF,wBAAsB,yBAAyB,CAAC,IAAI,EAAE;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc,EAAE,OAAO,CAAC;CACzB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAkD/B"}