agentplane 0.3.10 → 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.
Files changed (228) hide show
  1. package/assets/policy/governance.md +3 -4
  2. package/assets/policy/incidents.md +19 -88
  3. package/assets/policy/workflow.branch_pr.md +1 -1
  4. package/assets/policy/workflow.direct.md +2 -2
  5. package/bin/agentplane.js +56 -1
  6. package/bin/runtime-watch.js +1 -0
  7. package/bin/stale-dist-policy.d.ts +1 -1
  8. package/bin/stale-dist-policy.js +13 -0
  9. package/dist/.build-manifest.json +219 -154
  10. package/dist/cli/bootstrap-guide.d.ts.map +1 -1
  11. package/dist/cli/bootstrap-guide.js +3 -2
  12. package/dist/cli/command-guide.d.ts.map +1 -1
  13. package/dist/cli/command-guide.js +2 -1
  14. package/dist/cli/command-invocations.d.ts.map +1 -1
  15. package/dist/cli/command-invocations.js +4 -1
  16. package/dist/cli/run-cli/command-catalog/project.d.ts +1 -1
  17. package/dist/cli/run-cli/command-catalog/project.d.ts.map +1 -1
  18. package/dist/cli/run-cli/command-catalog/project.js +3 -1
  19. package/dist/cli/run-cli/command-catalog/task.d.ts +1 -1
  20. package/dist/cli/run-cli/command-catalog/task.d.ts.map +1 -1
  21. package/dist/cli/run-cli/command-catalog/task.js +10 -0
  22. package/dist/cli/run-cli/command-catalog.d.ts +1 -1
  23. package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
  24. package/dist/cli/run-cli/commands/core/preflight.d.ts.map +1 -1
  25. package/dist/cli/run-cli/commands/core/preflight.js +44 -1
  26. package/dist/cli/run-cli.test-helpers.d.ts.map +1 -1
  27. package/dist/cli/run-cli.test-helpers.js +12 -0
  28. package/dist/commands/branch/cleanup-merged.d.ts +2 -0
  29. package/dist/commands/branch/cleanup-merged.d.ts.map +1 -1
  30. package/dist/commands/branch/cleanup-merged.js +132 -28
  31. package/dist/commands/branch/work-start.d.ts.map +1 -1
  32. package/dist/commands/branch/work-start.js +60 -1
  33. package/dist/commands/cleanup/merged.command.d.ts +2 -0
  34. package/dist/commands/cleanup/merged.command.d.ts.map +1 -1
  35. package/dist/commands/cleanup/merged.command.js +24 -0
  36. package/dist/commands/doctor/branch-pr.d.ts +4 -0
  37. package/dist/commands/doctor/branch-pr.d.ts.map +1 -0
  38. package/dist/commands/doctor/branch-pr.js +96 -0
  39. package/dist/commands/doctor/fixes.d.ts +5 -0
  40. package/dist/commands/doctor/fixes.d.ts.map +1 -1
  41. package/dist/commands/doctor/fixes.js +70 -0
  42. package/dist/commands/doctor.run.d.ts.map +1 -1
  43. package/dist/commands/doctor.run.js +6 -1
  44. package/dist/commands/finish.run.d.ts.map +1 -1
  45. package/dist/commands/finish.run.js +11 -0
  46. package/dist/commands/finish.spec.d.ts +11 -0
  47. package/dist/commands/finish.spec.d.ts.map +1 -1
  48. package/dist/commands/finish.spec.js +51 -0
  49. package/dist/commands/guard/impl/close-message.d.ts.map +1 -1
  50. package/dist/commands/guard/impl/close-message.js +23 -6
  51. package/dist/commands/guard/impl/commands.d.ts.map +1 -1
  52. package/dist/commands/guard/impl/commands.js +24 -2
  53. package/dist/commands/guard/impl/env.d.ts +1 -0
  54. package/dist/commands/guard/impl/env.d.ts.map +1 -1
  55. package/dist/commands/guard/impl/env.js +1 -0
  56. package/dist/commands/hooks/index.d.ts.map +1 -1
  57. package/dist/commands/hooks/index.js +98 -1
  58. package/dist/commands/incidents/collect.command.d.ts.map +1 -1
  59. package/dist/commands/incidents/collect.command.js +12 -7
  60. package/dist/commands/incidents/incidents.command.js +1 -1
  61. package/dist/commands/incidents/shared.d.ts +34 -0
  62. package/dist/commands/incidents/shared.d.ts.map +1 -1
  63. package/dist/commands/incidents/shared.js +166 -12
  64. package/dist/commands/pr/check.d.ts.map +1 -1
  65. package/dist/commands/pr/check.js +238 -135
  66. package/dist/commands/pr/close-superseded.d.ts +9 -0
  67. package/dist/commands/pr/close-superseded.d.ts.map +1 -0
  68. package/dist/commands/pr/close-superseded.js +129 -0
  69. package/dist/commands/pr/close.d.ts +11 -0
  70. package/dist/commands/pr/close.d.ts.map +1 -0
  71. package/dist/commands/pr/close.js +116 -0
  72. package/dist/commands/pr/index.d.ts +2 -0
  73. package/dist/commands/pr/index.d.ts.map +1 -1
  74. package/dist/commands/pr/index.js +2 -0
  75. package/dist/commands/pr/integrate/artifacts.d.ts +7 -0
  76. package/dist/commands/pr/integrate/artifacts.d.ts.map +1 -1
  77. package/dist/commands/pr/integrate/artifacts.js +66 -1
  78. package/dist/commands/pr/integrate/cmd.d.ts.map +1 -1
  79. package/dist/commands/pr/integrate/cmd.js +16 -0
  80. package/dist/commands/pr/integrate/internal/bootstrap-guidance.d.ts +8 -0
  81. package/dist/commands/pr/integrate/internal/bootstrap-guidance.d.ts.map +1 -0
  82. package/dist/commands/pr/integrate/internal/bootstrap-guidance.js +59 -0
  83. package/dist/commands/pr/integrate/internal/finalize.d.ts.map +1 -1
  84. package/dist/commands/pr/integrate/internal/finalize.js +40 -12
  85. package/dist/commands/pr/integrate/internal/merge.d.ts.map +1 -1
  86. package/dist/commands/pr/integrate/internal/merge.js +36 -13
  87. package/dist/commands/pr/integrate/internal/post-integrate-bootstrap.d.ts +13 -0
  88. package/dist/commands/pr/integrate/internal/post-integrate-bootstrap.d.ts.map +1 -0
  89. package/dist/commands/pr/integrate/internal/post-integrate-bootstrap.js +25 -0
  90. package/dist/commands/pr/integrate/internal/prepare.d.ts +3 -2
  91. package/dist/commands/pr/integrate/internal/prepare.d.ts.map +1 -1
  92. package/dist/commands/pr/integrate/internal/prepare.js +101 -38
  93. package/dist/commands/pr/internal/freshness.d.ts +20 -0
  94. package/dist/commands/pr/internal/freshness.d.ts.map +1 -0
  95. package/dist/commands/pr/internal/freshness.js +50 -0
  96. package/dist/commands/pr/internal/gh-api.d.ts +6 -0
  97. package/dist/commands/pr/internal/gh-api.d.ts.map +1 -0
  98. package/dist/commands/pr/internal/gh-api.js +80 -0
  99. package/dist/commands/pr/internal/pr-paths.d.ts +10 -0
  100. package/dist/commands/pr/internal/pr-paths.d.ts.map +1 -1
  101. package/dist/commands/pr/internal/pr-paths.js +10 -0
  102. package/dist/commands/pr/internal/review-template.d.ts.map +1 -1
  103. package/dist/commands/pr/internal/review-template.js +37 -4
  104. package/dist/commands/pr/internal/sync.d.ts +9 -0
  105. package/dist/commands/pr/internal/sync.d.ts.map +1 -1
  106. package/dist/commands/pr/internal/sync.js +462 -122
  107. package/dist/commands/pr/open.d.ts +1 -0
  108. package/dist/commands/pr/open.d.ts.map +1 -1
  109. package/dist/commands/pr/open.js +13 -2
  110. package/dist/commands/pr/pr.command.d.ts +15 -0
  111. package/dist/commands/pr/pr.command.d.ts.map +1 -1
  112. package/dist/commands/pr/pr.command.js +118 -2
  113. package/dist/commands/pr/update.d.ts.map +1 -1
  114. package/dist/commands/pr/update.js +59 -1
  115. package/dist/commands/release/apply.command.d.ts.map +1 -1
  116. package/dist/commands/release/apply.command.js +3 -17
  117. package/dist/commands/release/apply.preflight.d.ts.map +1 -1
  118. package/dist/commands/release/apply.preflight.js +1 -1
  119. package/dist/commands/shared/gh-transport.d.ts +16 -0
  120. package/dist/commands/shared/gh-transport.d.ts.map +1 -0
  121. package/dist/commands/shared/gh-transport.js +71 -0
  122. package/dist/commands/shared/git-diff.d.ts +3 -1
  123. package/dist/commands/shared/git-diff.d.ts.map +1 -1
  124. package/dist/commands/shared/git-diff.js +10 -2
  125. package/dist/commands/shared/git-ops.d.ts +1 -0
  126. package/dist/commands/shared/git-ops.d.ts.map +1 -1
  127. package/dist/commands/shared/git-ops.js +15 -0
  128. package/dist/commands/shared/git-worktree.d.ts +2 -0
  129. package/dist/commands/shared/git-worktree.d.ts.map +1 -1
  130. package/dist/commands/shared/git-worktree.js +22 -2
  131. package/dist/commands/shared/post-commit-pr-artifacts.d.ts +9 -0
  132. package/dist/commands/shared/post-commit-pr-artifacts.d.ts.map +1 -0
  133. package/dist/commands/shared/post-commit-pr-artifacts.js +22 -0
  134. package/dist/commands/shared/pr-meta.d.ts +20 -0
  135. package/dist/commands/shared/pr-meta.d.ts.map +1 -1
  136. package/dist/commands/shared/pr-meta.js +125 -0
  137. package/dist/commands/shared/task-backend.d.ts +7 -0
  138. package/dist/commands/shared/task-backend.d.ts.map +1 -1
  139. package/dist/commands/shared/task-backend.js +34 -22
  140. package/dist/commands/task/close-duplicate.d.ts.map +1 -1
  141. package/dist/commands/task/close-duplicate.js +34 -1
  142. package/dist/commands/task/derive.js +1 -1
  143. package/dist/commands/task/doc-template.d.ts.map +1 -1
  144. package/dist/commands/task/doc-template.js +7 -11
  145. package/dist/commands/task/findings-add.command.d.ts +20 -0
  146. package/dist/commands/task/findings-add.command.d.ts.map +1 -0
  147. package/dist/commands/task/findings-add.command.js +165 -0
  148. package/dist/commands/task/findings.command.d.ts +7 -0
  149. package/dist/commands/task/findings.command.d.ts.map +1 -0
  150. package/dist/commands/task/findings.command.js +20 -0
  151. package/dist/commands/task/findings.d.ts +63 -0
  152. package/dist/commands/task/findings.d.ts.map +1 -0
  153. package/dist/commands/task/findings.js +188 -0
  154. package/dist/commands/task/finish-shared.d.ts +1 -0
  155. package/dist/commands/task/finish-shared.d.ts.map +1 -1
  156. package/dist/commands/task/finish-shared.js +55 -1
  157. package/dist/commands/task/finish.d.ts +10 -0
  158. package/dist/commands/task/finish.d.ts.map +1 -1
  159. package/dist/commands/task/finish.js +125 -6
  160. package/dist/commands/task/hosted-close-pr.command.d.ts +11 -0
  161. package/dist/commands/task/hosted-close-pr.command.d.ts.map +1 -0
  162. package/dist/commands/task/hosted-close-pr.command.js +414 -0
  163. package/dist/commands/task/hosted-close.command.d.ts.map +1 -1
  164. package/dist/commands/task/hosted-close.command.js +49 -1
  165. package/dist/commands/task/hosted-merge-sync.d.ts +38 -0
  166. package/dist/commands/task/hosted-merge-sync.d.ts.map +1 -1
  167. package/dist/commands/task/hosted-merge-sync.js +249 -17
  168. package/dist/commands/task/index.d.ts +1 -0
  169. package/dist/commands/task/index.d.ts.map +1 -1
  170. package/dist/commands/task/index.js +1 -0
  171. package/dist/commands/task/new.d.ts +1 -0
  172. package/dist/commands/task/new.d.ts.map +1 -1
  173. package/dist/commands/task/new.js +71 -1
  174. package/dist/commands/task/new.spec.d.ts.map +1 -1
  175. package/dist/commands/task/new.spec.js +7 -0
  176. package/dist/commands/task/normalize.command.d.ts +2 -0
  177. package/dist/commands/task/normalize.command.d.ts.map +1 -1
  178. package/dist/commands/task/normalize.command.js +45 -0
  179. package/dist/commands/task/normalize.d.ts +2 -0
  180. package/dist/commands/task/normalize.d.ts.map +1 -1
  181. package/dist/commands/task/normalize.js +85 -8
  182. package/dist/commands/task/plan.d.ts.map +1 -1
  183. package/dist/commands/task/plan.js +7 -10
  184. package/dist/commands/task/shared/docs.d.ts +6 -0
  185. package/dist/commands/task/shared/docs.d.ts.map +1 -1
  186. package/dist/commands/task/shared/docs.js +14 -0
  187. package/dist/commands/task/shared/transitions.d.ts.map +1 -1
  188. package/dist/commands/task/shared/transitions.js +11 -1
  189. package/dist/commands/task/shared.d.ts +1 -1
  190. package/dist/commands/task/shared.d.ts.map +1 -1
  191. package/dist/commands/task/shared.js +1 -1
  192. package/dist/commands/task/start-ready.d.ts.map +1 -1
  193. package/dist/commands/task/start-ready.js +86 -0
  194. package/dist/commands/task/start.d.ts.map +1 -1
  195. package/dist/commands/task/start.js +7 -10
  196. package/dist/commands/task/task.command.d.ts.map +1 -1
  197. package/dist/commands/task/task.command.js +4 -0
  198. package/dist/commands/task/verify-command-shared.d.ts +19 -0
  199. package/dist/commands/task/verify-command-shared.d.ts.map +1 -1
  200. package/dist/commands/task/verify-command-shared.js +152 -1
  201. package/dist/commands/task/verify-ok.command.d.ts.map +1 -1
  202. package/dist/commands/task/verify-ok.command.js +15 -2
  203. package/dist/commands/task/verify-record.d.ts +36 -0
  204. package/dist/commands/task/verify-record.d.ts.map +1 -1
  205. package/dist/commands/task/verify-record.js +166 -11
  206. package/dist/commands/task/verify-rework.command.d.ts.map +1 -1
  207. package/dist/commands/task/verify-rework.command.js +15 -2
  208. package/dist/commands/task/verify-show.command.d.ts +1 -1
  209. package/dist/commands/task/verify-show.command.d.ts.map +1 -1
  210. package/dist/commands/task/verify-show.command.js +28 -1
  211. package/dist/commands/verify.run.d.ts.map +1 -1
  212. package/dist/commands/verify.run.js +12 -0
  213. package/dist/commands/verify.spec.d.ts +2 -6
  214. package/dist/commands/verify.spec.d.ts.map +1 -1
  215. package/dist/commands/verify.spec.js +30 -3
  216. package/dist/runtime/incidents/index.d.ts +1 -1
  217. package/dist/runtime/incidents/index.d.ts.map +1 -1
  218. package/dist/runtime/incidents/resolve.d.ts.map +1 -1
  219. package/dist/runtime/incidents/resolve.js +319 -73
  220. package/dist/runtime/incidents/types.d.ts +14 -2
  221. package/dist/runtime/incidents/types.d.ts.map +1 -1
  222. package/dist/shared/env.d.ts +1 -0
  223. package/dist/shared/env.d.ts.map +1 -1
  224. package/dist/shared/env.js +22 -1
  225. package/dist/shared/protected-paths.d.ts +1 -1
  226. package/dist/shared/protected-paths.d.ts.map +1 -1
  227. package/dist/shared/protected-paths.js +4 -0
  228. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"merged.command.d.ts","sourceRoot":"","sources":["../../../src/commands/cleanup/merged.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAIhE,KAAK,kBAAkB,GAAG,kBAAkB,CAAC;AAE7C,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,kBAAkB,CAUvD,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,mBAAmB,CAkC9D,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,cAAc,CAAC,kBAAkB,CAQzD,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,IAC5E,KAAK,UAAU,EAAE,GAAG,mBAAmB,KAAG,OAAO,CAAC,MAAM,CAAC,CAWxE"}
1
+ {"version":3,"file":"merged.command.d.ts","sourceRoot":"","sources":["../../../src/commands/cleanup/merged.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAIhE,KAAK,kBAAkB,GAAG,kBAAkB,CAAC;AAE7C,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,kBAAkB,CAUvD,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,mBAAmB,CAwD9D,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,cAAc,CAAC,kBAAkB,CAQzD,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,IAC5E,KAAK,UAAU,EAAE,GAAG,mBAAmB,KAAG,OAAO,CAAC,MAAM,CAAC,CAaxE"}
@@ -25,6 +25,18 @@ export const cleanupMergedSpec = {
25
25
  default: false,
26
26
  description: "Archive PR artifacts before deletion.",
27
27
  },
28
+ {
29
+ kind: "boolean",
30
+ name: "delete-remote-branches",
31
+ default: false,
32
+ description: "Also delete matching remote task branches on origin.",
33
+ },
34
+ {
35
+ kind: "boolean",
36
+ name: "fetch",
37
+ default: false,
38
+ description: "Fetch and prune origin before candidate resolution.",
39
+ },
28
40
  { kind: "boolean", name: "quiet", default: false, description: "Reduce output noise." },
29
41
  ],
30
42
  examples: [
@@ -33,6 +45,14 @@ export const cleanupMergedSpec = {
33
45
  cmd: "agentplane cleanup merged --yes --archive",
34
46
  why: "Delete candidates and archive PR artifacts.",
35
47
  },
48
+ {
49
+ cmd: "agentplane cleanup merged --yes --delete-remote-branches",
50
+ why: "Delete candidates and matching remote task branches on origin.",
51
+ },
52
+ {
53
+ cmd: "agentplane cleanup merged --fetch",
54
+ why: "Refresh origin before evaluating cleanup candidates.",
55
+ },
36
56
  ],
37
57
  validateRaw: (raw) => {
38
58
  const base = typeof raw.opts.base === "string" ? raw.opts.base.trim() : "";
@@ -44,6 +64,8 @@ export const cleanupMergedSpec = {
44
64
  base: typeof raw.opts.base === "string" ? raw.opts.base : null,
45
65
  yes: raw.opts.yes === true,
46
66
  archive: raw.opts.archive === true,
67
+ deleteRemoteBranches: raw.opts["delete-remote-branches"] === true,
68
+ fetch: raw.opts.fetch === true,
47
69
  quiet: raw.opts.quiet === true,
48
70
  }),
49
71
  };
@@ -65,6 +87,8 @@ export function makeRunCleanupMergedHandler(getCtx) {
65
87
  base: p.base ?? undefined,
66
88
  yes: p.yes,
67
89
  archive: p.archive,
90
+ deleteRemoteBranches: p.deleteRemoteBranches,
91
+ fetch: p.fetch,
68
92
  quiet: p.quiet,
69
93
  });
70
94
  };
@@ -0,0 +1,4 @@
1
+ import type { CommandContext } from "../shared/task-backend.js";
2
+ export declare function checkBranchPrShippedTaskDrift(ctx?: CommandContext): Promise<string[]>;
3
+ export declare function checkBranchPrDoneTaskOpenPrDrift(ctx?: CommandContext): Promise<string[]>;
4
+ //# sourceMappingURL=branch-pr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch-pr.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/branch-pr.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAMhE,wBAAsB,6BAA6B,CAAC,GAAG,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAuC3F;AAED,wBAAsB,gCAAgC,CAAC,GAAG,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAkC9F"}
@@ -0,0 +1,96 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { renderDiagnosticFinding } from "../../shared/diagnostics.js";
4
+ import { findDoneBranchPrTasksWithOpenPrArtifacts, findLocallyShippedBranchPrTasks, } from "../task/hosted-merge-sync.js";
5
+ export async function checkBranchPrShippedTaskDrift(ctx) {
6
+ if (ctx?.backendId !== "local" || ctx.config.workflow_mode !== "branch_pr")
7
+ return [];
8
+ let tasks = [];
9
+ try {
10
+ tasks = await ctx.taskBackend.listTasks();
11
+ }
12
+ catch {
13
+ return [];
14
+ }
15
+ if (tasks.length === 0)
16
+ return [];
17
+ const matches = await findLocallyShippedBranchPrTasks({ ctx, tasks });
18
+ if (matches.length === 0)
19
+ return [];
20
+ const examples = matches
21
+ .slice(0, 5)
22
+ .map((entry) => `${entry.taskId}@${entry.base}:${entry.commitHash.slice(0, 12)} verified_via=${entry.verificationSource}`)
23
+ .join(", ");
24
+ return [
25
+ renderDiagnosticFinding({
26
+ severity: "WARN",
27
+ state: "branch_pr tasks appear shipped on the base branch but remain open",
28
+ likelyCause: "the verified task commit already landed on the base branch, but canonical task closure artifacts were never reconciled",
29
+ nextAction: {
30
+ command: "agentplane task normalize --sync-branch-pr-state",
31
+ reason: "mark locally shipped branch_pr tasks as DONE in the task projection before committing the reconciled task artifacts on the base branch",
32
+ },
33
+ details: [
34
+ `Affected tasks: ${matches.length}`,
35
+ examples ? `Examples: ${examples}` : "Examples unavailable.",
36
+ ],
37
+ }),
38
+ ];
39
+ }
40
+ export async function checkBranchPrDoneTaskOpenPrDrift(ctx) {
41
+ if (ctx?.backendId !== "local" || ctx.config.workflow_mode !== "branch_pr")
42
+ return [];
43
+ const tasks = await readDoneTaskSnapshot(ctx);
44
+ if (tasks.length === 0)
45
+ return [];
46
+ const matches = await findDoneBranchPrTasksWithOpenPrArtifacts({ ctx, tasks });
47
+ if (matches.length === 0)
48
+ return [];
49
+ const examples = matches
50
+ .slice(0, 5)
51
+ .map((entry) => `${entry.taskId}@${entry.base}:${entry.commitHash.slice(0, 12)} branch=${entry.branch}`)
52
+ .join(", ");
53
+ return [
54
+ renderDiagnosticFinding({
55
+ severity: "WARN",
56
+ state: "DONE branch_pr tasks still have open or unmerged PR artifacts",
57
+ likelyCause: "the task was marked DONE, but its branch_pr PR artifacts were never reconciled to MERGED and the task branch still exists",
58
+ nextAction: {
59
+ command: "agentplane task normalize --sync-hosted-merges --task-id <task-id>",
60
+ reason: "reconcile the shipped task's branch_pr PR artifacts to MERGED without scanning unrelated task history",
61
+ },
62
+ details: [
63
+ `Affected tasks: ${matches.length}`,
64
+ examples ? `Examples: ${examples}` : "Examples unavailable.",
65
+ ],
66
+ }),
67
+ ];
68
+ }
69
+ async function readDoneTaskSnapshot(ctx) {
70
+ try {
71
+ const tasks = await ctx.taskBackend.listTasks();
72
+ if (tasks.length > 0) {
73
+ return tasks;
74
+ }
75
+ }
76
+ catch {
77
+ // Fall back to the legacy export snapshot when the live backend read is unavailable.
78
+ }
79
+ const tasksJsonPath = path.join(ctx.resolvedProject.agentplaneDir, "tasks.json");
80
+ try {
81
+ const raw = await readFile(tasksJsonPath, "utf8");
82
+ const parsed = JSON.parse(raw);
83
+ if (!Array.isArray(parsed.tasks))
84
+ return [];
85
+ return parsed.tasks.filter((task) => isTaskDataLike(task));
86
+ }
87
+ catch {
88
+ return [];
89
+ }
90
+ }
91
+ function isTaskDataLike(value) {
92
+ if (!value || typeof value !== "object" || Array.isArray(value))
93
+ return false;
94
+ const record = value;
95
+ return typeof record.id === "string" && typeof record.status === "string";
96
+ }
@@ -1,3 +1,4 @@
1
+ import type { CommandContext } from "../shared/task-backend.js";
1
2
  export declare function safeFixGitignore(repoRoot: string): Promise<{
2
3
  changed: boolean;
3
4
  note: string;
@@ -6,4 +7,8 @@ export declare function safeFixTaskIndex(repoRoot: string): Promise<{
6
7
  changed: boolean;
7
8
  note: string;
8
9
  }>;
10
+ export declare function safeFixLegacyUntrackedTaskReadmes(repoRoot: string, ctx?: CommandContext): Promise<{
11
+ changed: boolean;
12
+ note: string;
13
+ }>;
9
14
  //# sourceMappingURL=fixes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fixes.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/fixes.ts"],"names":[],"mappings":"AAMA,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAyB7C;AAED,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAQ7C"}
1
+ {"version":3,"file":"fixes.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/fixes.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEhE,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAyB7C;AAED,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAQ7C;AAED,wBAAsB,iCAAiC,CACrD,QAAQ,EAAE,MAAM,EAChB,GAAG,CAAC,EAAE,cAAc,GACnB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CA8E7C"}
@@ -1,6 +1,8 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
+ import { parseTaskReadme } from "@agentplaneorg/core";
3
4
  import { RUNTIME_GITIGNORE_LINES } from "../../shared/runtime-artifacts.js";
5
+ import { GitContext } from "../shared/git-context.js";
4
6
  import { loadCommandContext } from "../shared/task-backend.js";
5
7
  export async function safeFixGitignore(repoRoot) {
6
8
  const gitignorePath = path.join(repoRoot, ".gitignore");
@@ -38,3 +40,71 @@ export async function safeFixTaskIndex(repoRoot) {
38
40
  return { changed: false, note: "Skip: could not rebuild tasks index cache." };
39
41
  }
40
42
  }
43
+ export async function safeFixLegacyUntrackedTaskReadmes(repoRoot, ctx) {
44
+ const commandCtx = ctx ??
45
+ (await loadCommandContext({
46
+ cwd: repoRoot,
47
+ rootOverride: null,
48
+ }));
49
+ const workflowDir = (commandCtx.config.paths.workflow_dir ?? ".agentplane/tasks").replaceAll("\\", "/");
50
+ const git = commandCtx.git ?? new GitContext({ gitRoot: repoRoot });
51
+ let untracked = [];
52
+ try {
53
+ untracked = await git.statusUntrackedPaths();
54
+ }
55
+ catch {
56
+ return { changed: false, note: "Skip: could not inspect untracked task README collisions." };
57
+ }
58
+ const candidates = untracked.filter((relPath) => relPath.startsWith(`${workflowDir}/`) && relPath.endsWith("/README.md"));
59
+ if (candidates.length === 0) {
60
+ return { changed: false, note: "OK: no legacy untracked task README collisions." };
61
+ }
62
+ const removed = [];
63
+ for (const relPath of candidates) {
64
+ const absPath = path.join(repoRoot, relPath);
65
+ let text = "";
66
+ try {
67
+ text = await fs.readFile(absPath, "utf8");
68
+ }
69
+ catch {
70
+ continue;
71
+ }
72
+ let parsed;
73
+ try {
74
+ parsed = parseTaskReadme(text);
75
+ }
76
+ catch {
77
+ continue;
78
+ }
79
+ const taskId = path.basename(path.dirname(absPath));
80
+ const parsedId = typeof parsed.frontmatter.id === "string" && parsed.frontmatter.id.trim().length > 0
81
+ ? parsed.frontmatter.id.trim()
82
+ : taskId;
83
+ const status = typeof parsed.frontmatter.status === "string"
84
+ ? parsed.frontmatter.status.trim().toUpperCase()
85
+ : "";
86
+ if (parsedId !== taskId || status !== "DONE")
87
+ continue;
88
+ await fs.rm(absPath, { force: true });
89
+ try {
90
+ const remaining = await fs.readdir(path.dirname(absPath));
91
+ if (remaining.length === 0) {
92
+ await fs.rmdir(path.dirname(absPath));
93
+ }
94
+ }
95
+ catch {
96
+ // Ignore cleanup failures for parent directories; the file removal is the actual fix.
97
+ }
98
+ removed.push(taskId);
99
+ }
100
+ if (removed.length === 0) {
101
+ return {
102
+ changed: false,
103
+ note: "OK: no safe-to-remove legacy untracked DONE task README collisions.",
104
+ };
105
+ }
106
+ return {
107
+ changed: true,
108
+ note: `Fixed: removed legacy untracked DONE task README collisions (${removed.join(", ")}).`,
109
+ };
110
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.run.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.run.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAarD,eAAO,MAAM,SAAS,EAAE,cAAc,CAAC,YAAY,CA6DlD,CAAC"}
1
+ {"version":3,"file":"doctor.run.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.run.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAqBrD,eAAO,MAAM,SAAS,EAAE,cAAc,CAAC,YAAY,CAiElD,CAAC"}
@@ -2,7 +2,8 @@ import { loadConfig, resolveProject } from "@agentplaneorg/core";
2
2
  import { warnMessage, successMessage } from "../cli/output.js";
3
3
  import { loadCommandContext } from "./shared/task-backend.js";
4
4
  import { checkDoneTaskCommitInvariants } from "./doctor/archive.js";
5
- import { safeFixGitignore, safeFixTaskIndex } from "./doctor/fixes.js";
5
+ import { checkBranchPrDoneTaskOpenPrDrift, checkBranchPrShippedTaskDrift, } from "./doctor/branch-pr.js";
6
+ import { safeFixGitignore, safeFixLegacyUntrackedTaskReadmes, safeFixTaskIndex, } from "./doctor/fixes.js";
6
7
  import { checkLayering } from "./doctor/layering.js";
7
8
  import { checkRuntimeSourceFacts, findingSeverity } from "./doctor/runtime.js";
8
9
  import { checkWorkspace } from "./doctor/workspace.js";
@@ -21,6 +22,8 @@ export const runDoctor = async (ctx, p) => {
21
22
  const runChecks = async () => {
22
23
  let checks = [
23
24
  ...(await checkWorkspace(repoRoot, { ctx: commandCtx })),
25
+ ...(await checkBranchPrShippedTaskDrift(commandCtx)),
26
+ ...(await checkBranchPrDoneTaskOpenPrDrift(commandCtx)),
24
27
  ...checkRuntimeSourceFacts(ctx.cwd, loadedConfig.config),
25
28
  ...(await checkDoneTaskCommitInvariants(repoRoot, { fullArchive: p.archiveFull })),
26
29
  ];
@@ -38,6 +41,8 @@ export const runDoctor = async (ctx, p) => {
38
41
  if (p.fix) {
39
42
  const fix = await safeFixGitignore(repoRoot);
40
43
  console.log(successMessage("doctor fix", undefined, fix.note));
44
+ const legacyTaskReadmes = await safeFixLegacyUntrackedTaskReadmes(repoRoot, commandCtx);
45
+ console.log(successMessage("doctor fix", undefined, legacyTaskReadmes.note));
41
46
  const idx = await safeFixTaskIndex(repoRoot);
42
47
  console.log(successMessage("doctor fix", undefined, idx.note));
43
48
  const workflowFix = await safeFixWorkflow(repoRoot);
@@ -1 +1 @@
1
- {"version":3,"file":"finish.run.d.ts","sourceRoot":"","sources":["../../src/commands/finish.run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG/D,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEjE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,IACrE,KAAK,UAAU,EAAE,GAAG,YAAY,KAAG,OAAO,CAAC,MAAM,CAAC,CAuCjE"}
1
+ {"version":3,"file":"finish.run.d.ts","sourceRoot":"","sources":["../../src/commands/finish.run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG/D,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEjE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,IACrE,KAAK,UAAU,EAAE,GAAG,YAAY,KAAG,OAAO,CAAC,MAAM,CAAC,CAkDjE"}
@@ -38,6 +38,17 @@ export function makeRunFinishHandler(getCtx) {
38
38
  closeCommit: p.closeCommit,
39
39
  noCloseCommit: p.noCloseCommit,
40
40
  closeUnstageOthers: p.closeUnstageOthers,
41
+ baseBranchOverride: p.baseBranchOverride,
42
+ observation: p.observation,
43
+ impact: p.impact,
44
+ resolution: p.resolution,
45
+ localOnly: p.localOnly,
46
+ repoFixable: p.repoFixable,
47
+ incidentScope: p.incidentScope,
48
+ incidentTags: p.incidentTags,
49
+ incidentMatch: p.incidentMatch,
50
+ incidentAdvice: p.incidentAdvice,
51
+ incidentRule: p.incidentRule,
41
52
  quiet: p.quiet,
42
53
  });
43
54
  };
@@ -24,6 +24,17 @@ export type FinishParsed = {
24
24
  closeCommit: boolean;
25
25
  noCloseCommit: boolean;
26
26
  closeUnstageOthers: boolean;
27
+ baseBranchOverride?: string;
28
+ observation?: string;
29
+ impact?: string;
30
+ resolution?: string;
31
+ localOnly: boolean;
32
+ repoFixable: boolean;
33
+ incidentScope?: string;
34
+ incidentTags: string[];
35
+ incidentMatch: string[];
36
+ incidentAdvice?: string;
37
+ incidentRule?: string;
27
38
  quiet: boolean;
28
39
  };
29
40
  export declare const finishSpec: CommandSpec<FinishParsed>;
@@ -1 +1 @@
1
- {"version":3,"file":"finish.spec.d.ts","sourceRoot":"","sources":["../../src/commands/finish.spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AASvD,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,wBAAwB,EAAE,OAAO,CAAC;IAClC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC,YAAY,CAqUhD,CAAC"}
1
+ {"version":3,"file":"finish.spec.d.ts","sourceRoot":"","sources":["../../src/commands/finish.spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAUvD,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,wBAAwB,EAAE,OAAO,CAAC;IAClC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC,YAAY,CA4XhD,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { usageError } from "../cli/spec/errors.js";
2
+ import { verifyFindingOptions, validateVerifyFindingSource } from "./task/verify-command-shared.js";
2
3
  import { toStringList } from "../cli/spec/parse-utils.js";
3
4
  import { findRepoWideAllowPrefixes, repoWideAllowPrefixMessage, } from "../shared/allow-prefix-policy.js";
4
5
  export const finishSpec = {
@@ -157,6 +158,13 @@ export const finishSpec = {
157
158
  default: false,
158
159
  description: "With --close-commit: unstage any currently staged paths before staging the task README.",
159
160
  },
161
+ {
162
+ kind: "string",
163
+ name: "base",
164
+ valueHint: "<branch>",
165
+ description: "Optional explicit base branch override for branch_pr finish validation and close-commit reconciliation.",
166
+ },
167
+ ...verifyFindingOptions,
160
168
  { kind: "boolean", name: "quiet", default: false, description: "Suppress output." },
161
169
  ],
162
170
  examples: [
@@ -168,6 +176,10 @@ export const finishSpec = {
168
176
  cmd: 'agentplane finish 202602030608-F1Q8AB --author INTEGRATOR --body "Verified: all checks passed" --commit-from-comment --commit-allow packages/agentplane/src',
169
177
  why: "Finish and create a commit from the comment (single-task only).",
170
178
  },
179
+ {
180
+ cmd: 'agentplane finish 202602030608-F1Q8AB --author INTEGRATOR --body "Verified: all checks passed" --commit abcdef123456 --observation "Recurring manual recovery remained easy to miss." --impact "incidents.md stayed stale until a second command." --resolution "Capture the closeout finding during finish itself."',
181
+ why: "Finish a task while appending a structured finding that can promote into incidents.md.",
182
+ },
171
183
  ],
172
184
  validateRaw: (raw) => {
173
185
  const ids = raw.args["task-id"];
@@ -270,9 +282,29 @@ export const finishSpec = {
270
282
  message: "--close-unstage-others requires --close-commit",
271
283
  });
272
284
  }
285
+ if (typeof raw.opts.base === "string" && raw.opts.base.trim().length === 0) {
286
+ throw usageError({
287
+ spec: finishSpec,
288
+ command: "finish",
289
+ message: "Invalid value for --base: empty.",
290
+ });
291
+ }
273
292
  const hasMeta = typeof raw.opts.result === "string" ||
274
293
  typeof raw.opts.risk === "string" ||
275
294
  raw.opts.breaking === true;
295
+ const hasFindingInput = [
296
+ raw.opts.observation,
297
+ raw.opts.impact,
298
+ raw.opts.resolution,
299
+ raw.opts["incident-scope"],
300
+ raw.opts["incident-advice"],
301
+ raw.opts["incident-rule"],
302
+ ].some((value) => typeof value === "string" && value.trim().length > 0)
303
+ ? true
304
+ : (Array.isArray(raw.opts["incident-tag"]) && raw.opts["incident-tag"].length > 0) ||
305
+ (Array.isArray(raw.opts["incident-match"]) && raw.opts["incident-match"].length > 0) ||
306
+ raw.opts["local-only"] === true ||
307
+ raw.opts["repo-fixable"] === true;
276
308
  if (hasMeta && taskIds.length !== 1) {
277
309
  throw usageError({
278
310
  spec: finishSpec,
@@ -280,6 +312,14 @@ export const finishSpec = {
280
312
  message: "--result/--risk/--breaking requires exactly one task id",
281
313
  });
282
314
  }
315
+ if (hasFindingInput && taskIds.length !== 1) {
316
+ throw usageError({
317
+ spec: finishSpec,
318
+ command: "finish",
319
+ message: "--observation/--impact/--resolution and incident finding options require exactly one task id",
320
+ });
321
+ }
322
+ validateVerifyFindingSource(raw, finishSpec, { command: "finish" });
283
323
  },
284
324
  parse: (raw) => ({
285
325
  taskIds: Array.isArray(raw.args["task-id"])
@@ -308,6 +348,17 @@ export const finishSpec = {
308
348
  closeCommit: raw.opts["close-commit"] === true,
309
349
  noCloseCommit: raw.opts["no-close-commit"] === true,
310
350
  closeUnstageOthers: raw.opts["close-unstage-others"] === true,
351
+ baseBranchOverride: typeof raw.opts.base === "string" ? raw.opts.base : undefined,
352
+ observation: typeof raw.opts.observation === "string" ? raw.opts.observation : undefined,
353
+ impact: typeof raw.opts.impact === "string" ? raw.opts.impact : undefined,
354
+ resolution: typeof raw.opts.resolution === "string" ? raw.opts.resolution : undefined,
355
+ localOnly: raw.opts["local-only"] === true,
356
+ repoFixable: raw.opts["repo-fixable"] === true,
357
+ incidentScope: typeof raw.opts["incident-scope"] === "string" ? raw.opts["incident-scope"] : undefined,
358
+ incidentTags: toStringList(raw.opts["incident-tag"]),
359
+ incidentMatch: toStringList(raw.opts["incident-match"]),
360
+ incidentAdvice: typeof raw.opts["incident-advice"] === "string" ? raw.opts["incident-advice"] : undefined,
361
+ incidentRule: typeof raw.opts["incident-rule"] === "string" ? raw.opts["incident-rule"] : undefined,
311
362
  quiet: raw.opts.quiet === true,
312
363
  }),
313
364
  };
@@ -1 +1 @@
1
- {"version":3,"file":"close-message.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/close-message.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAsHlE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,wBAAsB,uBAAuB,CAAC,IAAI,EAAE;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,QAAQ,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAsD9B;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,MAAM,CAET"}
1
+ {"version":3,"file":"close-message.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/close-message.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAyIlE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,wBAAsB,uBAAuB,CAAC,IAAI,EAAE;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,QAAQ,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAsD9B;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,MAAM,CAET"}
@@ -3,6 +3,15 @@ import { extractTaskSuffix } from "@agentplaneorg/core";
3
3
  import { exitCodeForError } from "../../../cli/exit-codes.js";
4
4
  import { CliError } from "../../../shared/errors.js";
5
5
  import { execFileAsync, gitEnv } from "../../shared/git.js";
6
+ function isMissingCommitObjectError(err) {
7
+ const stderr = err.stderr;
8
+ const text = err instanceof Error
9
+ ? [err.message, typeof stderr === "string" ? stderr : ""]
10
+ .filter((part) => part.trim().length > 0)
11
+ .join("\n")
12
+ : String(err);
13
+ return (/bad object/i.test(text) || /unknown revision/i.test(text) || /ambiguous argument/i.test(text));
14
+ }
6
15
  function uniqSorted(values) {
7
16
  return [...new Set(values)].toSorted((a, b) => a.localeCompare(b));
8
17
  }
@@ -29,12 +38,20 @@ function clampList(items, max) {
29
38
  return items.slice(0, Math.max(0, Math.floor(max)));
30
39
  }
31
40
  async function gitNumstatForCommit(gitRoot, commit) {
32
- const { stdout } = await execFileAsync("git", ["show", "--numstat", "--format=", commit], {
33
- cwd: gitRoot,
34
- env: gitEnv(),
35
- encoding: "buffer",
36
- maxBuffer: 10 * 1024 * 1024,
37
- });
41
+ let stdout;
42
+ try {
43
+ ({ stdout } = await execFileAsync("git", ["show", "--numstat", "--format=", commit], {
44
+ cwd: gitRoot,
45
+ env: gitEnv(),
46
+ encoding: "buffer",
47
+ maxBuffer: 10 * 1024 * 1024,
48
+ }));
49
+ }
50
+ catch (err) {
51
+ if (isMissingCommitObjectError(err))
52
+ return [];
53
+ throw err;
54
+ }
38
55
  const text = Buffer.isBuffer(stdout) ? stdout.toString("utf8") : String(stdout);
39
56
  const entries = [];
40
57
  for (const line of text.split("\n")) {
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/commands.ts"],"names":[],"mappings":"AASA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAQvF,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAsOxE,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBlB;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;CAC1B,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBlB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAa9E;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,kBAAkB,EAAE,OAAO,CAAC;IAC5B,cAAc,EAAE,OAAO,CAAC;IACxB,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC,GAAG,OAAO,CAAC,MAAM,CAAC,CAuNlB"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/commands.ts"],"names":[],"mappings":"AAUA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAQvF,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAsOxE,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBlB;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;CAC1B,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBlB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAa9E;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,kBAAkB,EAAE,OAAO,CAAC;IAC5B,cAAc,EAAE,OAAO,CAAC;IACxB,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC,GAAG,OAAO,CAAC,MAAM,CAAC,CA4OlB"}
@@ -6,6 +6,7 @@ import { infoMessage, successMessage } from "../../../cli/output.js";
6
6
  import { stripAnsi } from "../../../cli/shared/ansi.js";
7
7
  import { withDiagnosticContext } from "../../../shared/diagnostics.js";
8
8
  import { CliError } from "../../../shared/errors.js";
9
+ import { refreshBranchPrArtifactsAfterTaskCommit } from "../../shared/post-commit-pr-artifacts.js";
9
10
  import { loadCommandContext } from "../../shared/task-backend.js";
10
11
  import { loadTaskFromContext } from "../../shared/task-backend.js";
11
12
  import { execFileAsync, gitEnv } from "../../shared/git.js";
@@ -325,11 +326,24 @@ export async function cmdCommit(opts) {
325
326
  }
326
327
  return 0;
327
328
  }
329
+ if (opts.closeStageTaskArtifacts === true) {
330
+ await refreshBranchPrArtifactsAfterTaskCommit({
331
+ ctx,
332
+ cwd: opts.cwd,
333
+ rootOverride: opts.rootOverride,
334
+ taskId: opts.taskId,
335
+ quiet: opts.quiet,
336
+ });
337
+ // Artifact refresh writes tracked task files on disk; invalidate the memoized
338
+ // porcelain snapshot so staging/cleanliness checks see the refreshed state.
339
+ ctx.git.invalidateStatus();
340
+ }
328
341
  await (opts.closeStageTaskArtifacts === true
329
342
  ? stageAllowlist({
330
343
  ctx,
331
344
  allow: [],
332
345
  allowTasks: true,
346
+ allowPolicy: opts.allowPolicy,
333
347
  tasksPath: ctx.config.paths.tasks_path,
334
348
  workflowDir: ctx.config.paths.workflow_dir,
335
349
  taskId: opts.taskId,
@@ -350,7 +364,7 @@ export async function cmdCommit(opts) {
350
364
  allow: [],
351
365
  allowBase: opts.allowBase,
352
366
  allowTasks: true,
353
- allowPolicy: false,
367
+ allowPolicy: opts.allowPolicy,
354
368
  allowConfig: false,
355
369
  allowHooks: false,
356
370
  allowCI: false,
@@ -361,10 +375,11 @@ export async function cmdCommit(opts) {
361
375
  taskId: opts.taskId,
362
376
  allowTasks: true,
363
377
  allowBase: opts.allowBase,
364
- allowPolicy: false,
378
+ allowPolicy: opts.allowPolicy,
365
379
  allowConfig: false,
366
380
  allowHooks: false,
367
381
  allowCI: false,
382
+ allowStaleDist: true,
368
383
  });
369
384
  await ctx.git.commit({ message: msg.subject, body: msg.body, env });
370
385
  if (!opts.quiet) {
@@ -437,6 +452,13 @@ export async function cmdCommit(opts) {
437
452
  allowCI: opts.allowCI,
438
453
  });
439
454
  await ctx.git.commit({ message: opts.message, env });
455
+ await refreshBranchPrArtifactsAfterTaskCommit({
456
+ ctx,
457
+ cwd: opts.cwd,
458
+ rootOverride: opts.rootOverride,
459
+ taskId: opts.taskId,
460
+ quiet: opts.quiet,
461
+ });
440
462
  if (!opts.quiet) {
441
463
  const { hash, subject } = await ctx.git.headHashSubject();
442
464
  process.stdout.write(`${successMessage("committed", `${hash?.slice(0, 12) ?? ""} ${subject ?? ""}`.trim(), autoStaged.length > 0 ? `staged=${autoStaged.join(", ")}` : undefined)}\n`);
@@ -8,5 +8,6 @@ export declare function buildGitCommitEnv(opts: {
8
8
  allowConfig: boolean;
9
9
  allowHooks: boolean;
10
10
  allowCI: boolean;
11
+ allowStaleDist?: boolean;
11
12
  }): NodeJS.ProcessEnv;
12
13
  //# sourceMappingURL=env.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/env.ts"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;CAClB,GAAG,MAAM,CAAC,UAAU,CAapB"}
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/env.ts"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,GAAG,MAAM,CAAC,UAAU,CAcpB"}
@@ -10,5 +10,6 @@ export function buildGitCommitEnv(opts) {
10
10
  AGENTPLANE_ALLOW_CONFIG: opts.allowConfig ? "1" : "0",
11
11
  AGENTPLANE_ALLOW_HOOKS: opts.allowHooks ? "1" : "0",
12
12
  AGENTPLANE_ALLOW_CI: opts.allowCI ? "1" : "0",
13
+ ...(opts.allowStaleDist ? { AGENTPLANE_DEV_ALLOW_STALE_DIST: "1" } : null),
13
14
  };
14
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/hooks/index.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,UAAU,mDAAoD,CAAC;AAkH5E,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmClB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BlB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsGlB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/hooks/index.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,UAAU,mDAAoD,CAAC;AA8K5E,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmClB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BlB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiJlB"}