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
@@ -12,6 +12,7 @@ import { loadTaskFromContext } from "../shared/task-backend.js";
12
12
  import { createTaskCloseCommit, writeFinishedTasks } from "./finish-shared.js";
13
13
  import { resolveHostedMergeTargetFromEvent } from "./hosted-merge-sync.js";
14
14
  import { readCommitInfo } from "./shared.js";
15
+ import { collectTaskIncidents, renderIncidentCollectionPlanOutcome } from "../incidents/shared.js";
15
16
  export const taskHostedCloseSpec = {
16
17
  id: ["task", "hosted-close"],
17
18
  group: "Task",
@@ -50,6 +51,30 @@ export const taskHostedCloseSpec = {
50
51
  quiet: raw.opts.quiet === true,
51
52
  }),
52
53
  };
54
+ function isMissingCommitObjectError(err) {
55
+ const stderr = err.stderr;
56
+ const text = err instanceof Error
57
+ ? [err.message, typeof stderr === "string" ? stderr : ""]
58
+ .filter((part) => part.trim().length > 0)
59
+ .join("\n")
60
+ : String(err);
61
+ return (/bad object/i.test(text) || /unknown revision/i.test(text) || /ambiguous argument/i.test(text));
62
+ }
63
+ async function resolveHostedTaskCommitInfo(opts) {
64
+ const mergeHash = opts.mergedPr.mergeCommit?.oid ?? "";
65
+ try {
66
+ return await readCommitInfo(opts.gitRoot, mergeHash);
67
+ }
68
+ catch (err) {
69
+ if (!isMissingCommitObjectError(err))
70
+ throw err;
71
+ return {
72
+ hash: mergeHash,
73
+ message: opts.mergedPr.title?.trim() ??
74
+ `Hosted PR #${opts.mergedPr.number} merged on GitHub ${opts.mergedPr.baseRefName ?? "main"}`,
75
+ };
76
+ }
77
+ }
53
78
  async function hasTaskArtifactChanges(opts) {
54
79
  const { stdout } = await execFileAsync("git", ["status", "--short", "--", opts.taskDirRelative], {
55
80
  cwd: opts.gitRoot,
@@ -57,6 +82,154 @@ async function hasTaskArtifactChanges(opts) {
57
82
  });
58
83
  return stdout.trim().length > 0;
59
84
  }
85
+ function buildFallbackPrMeta(opts) {
86
+ const at = opts.mergedPr.mergedAt ?? new Date().toISOString();
87
+ const headShaRaw = opts.mergedPr.headRefOid?.trim();
88
+ const headSha = headShaRaw && headShaRaw.length > 0 ? headShaRaw : undefined;
89
+ const prUrlRaw = opts.mergedPr.url?.trim();
90
+ const prUrl = prUrlRaw && prUrlRaw.length > 0 ? prUrlRaw : undefined;
91
+ return {
92
+ schema_version: 1,
93
+ task_id: opts.taskId,
94
+ branch: opts.branch,
95
+ ...(opts.mergedPr.baseRefName ? { base: opts.mergedPr.baseRefName } : {}),
96
+ pr_number: opts.mergedPr.number,
97
+ ...(prUrl ? { pr_url: prUrl } : {}),
98
+ created_at: at,
99
+ updated_at: at,
100
+ status: "OPEN",
101
+ ...(headSha ? { head_sha: headSha } : {}),
102
+ last_verified_sha: null,
103
+ last_verified_at: null,
104
+ verify: { status: "skipped" },
105
+ };
106
+ }
107
+ function escapeRegExp(value) {
108
+ return value.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw `\$&`);
109
+ }
110
+ function extractMarkdownSection(markdown, heading) {
111
+ const pattern = new RegExp(String.raw `^## ${escapeRegExp(heading)}\n\n([\s\S]*?)(?=\n## [^\n]+\n|$)`, "m");
112
+ const match = pattern.exec(markdown);
113
+ return match?.[1]?.trim() ?? "";
114
+ }
115
+ function fallbackTaskTitleFromPrTitle(taskId, prTitle) {
116
+ const trimmed = prTitle?.trim() ?? "";
117
+ if (!trimmed)
118
+ return `Hosted close recovery for ${taskId}`;
119
+ const suffix = taskId.split("-").at(-1)?.trim();
120
+ if (suffix) {
121
+ const stripped = trimmed.replace(new RegExp(String.raw `\s*\(${escapeRegExp(suffix)}\)\s*$`), "");
122
+ if (stripped.trim().length > 0)
123
+ return stripped.trim();
124
+ }
125
+ return trimmed;
126
+ }
127
+ function isMissingTaskReadmeError(err, readmePath) {
128
+ if (!(err instanceof CliError))
129
+ return false;
130
+ return err.code === "E_IO" && err.message.includes(readmePath);
131
+ }
132
+ async function buildHostedTaskFromTrackedPrArtifacts(opts) {
133
+ const bodyPath = path.join(opts.gitRoot, opts.taskDirRelative, "pr", "github-body.md");
134
+ let bodyText = "";
135
+ try {
136
+ bodyText = await readFile(bodyPath, "utf8");
137
+ }
138
+ catch (err) {
139
+ const code = err?.code;
140
+ if (code === "ENOENT")
141
+ return null;
142
+ throw err;
143
+ }
144
+ const summary = extractMarkdownSection(bodyText, "Summary");
145
+ const scope = extractMarkdownSection(bodyText, "Scope");
146
+ const verification = extractMarkdownSection(bodyText, "Verification");
147
+ const handoff = extractMarkdownSection(bodyText, "Handoff Notes");
148
+ const summaryLines = summary
149
+ .split("\n")
150
+ .map((line) => line.trim())
151
+ .filter((line) => line.length > 0);
152
+ const title = summaryLines[0] || fallbackTaskTitleFromPrTitle(opts.taskId, opts.mergedPr.title);
153
+ const description = summaryLines.slice(1).join("\n").trim() ||
154
+ `Recovered hosted-close state from tracked PR artifacts for merged PR #${opts.mergedPr.number}.`;
155
+ const scopeText = scope || `- In scope: record canonical task closure for merged PR #${opts.mergedPr.number}.`;
156
+ const verificationText = verification || "- State: pending\n- Note: Recovered during hosted-close.";
157
+ const handoffText = handoff || "- No handoff notes recorded.";
158
+ const planText = `Recovered hosted-close state from tracked PR artifacts for merged PR #${opts.mergedPr.number}.`;
159
+ const rollbackText = [
160
+ "- Revert the hosted closure commit if the merged PR metadata was recorded incorrectly.",
161
+ "- Re-run the required checks after rollback.",
162
+ ].join("\n");
163
+ const doc = [
164
+ "## Summary",
165
+ "",
166
+ title,
167
+ "",
168
+ description,
169
+ "",
170
+ "## Scope",
171
+ "",
172
+ scopeText,
173
+ "",
174
+ "## Plan",
175
+ "",
176
+ planText,
177
+ "",
178
+ "## Verification",
179
+ "",
180
+ verificationText,
181
+ "",
182
+ "## Rollback Plan",
183
+ "",
184
+ rollbackText,
185
+ "",
186
+ "## Handoff Notes",
187
+ "",
188
+ handoffText,
189
+ "",
190
+ "## Findings",
191
+ "",
192
+ ].join("\n");
193
+ return {
194
+ id: opts.taskId,
195
+ title,
196
+ description,
197
+ status: "DOING",
198
+ priority: "med",
199
+ owner: "INTEGRATOR",
200
+ revision: 1,
201
+ origin: { system: "manual" },
202
+ depends_on: [],
203
+ tags: [],
204
+ verify: [],
205
+ plan_approval: { state: "pending", updated_at: null, updated_by: null, note: null },
206
+ verification: { state: "pending", updated_at: null, updated_by: null, note: null },
207
+ commit: null,
208
+ doc,
209
+ doc_version: 3,
210
+ doc_updated_at: opts.mergedPr.mergedAt ?? new Date().toISOString(),
211
+ doc_updated_by: "INTEGRATOR",
212
+ id_source: "generated",
213
+ };
214
+ }
215
+ async function readHostedPrMetaOrFallback(opts) {
216
+ const metaPath = path.join(opts.gitRoot, opts.taskDirRelative, "pr", "meta.json");
217
+ if (!(await fileExists(metaPath))) {
218
+ return {
219
+ metaPath,
220
+ meta: buildFallbackPrMeta({
221
+ taskId: opts.target.taskId,
222
+ branch: opts.target.branch,
223
+ mergedPr: opts.target.mergedPr,
224
+ }),
225
+ };
226
+ }
227
+ const rawMeta = await readFile(metaPath, "utf8");
228
+ return {
229
+ metaPath,
230
+ meta: parsePrMeta(rawMeta, opts.target.taskId),
231
+ };
232
+ }
60
233
  async function closeHostedTask(opts) {
61
234
  const rawEvent = await readFile(opts.eventJson, "utf8");
62
235
  const parsedEvent = JSON.parse(rawEvent);
@@ -69,24 +242,43 @@ async function closeHostedTask(opts) {
69
242
  }
70
243
  const gitRoot = opts.ctx.resolvedProject.gitRoot;
71
244
  const taskDirRelative = path.join(opts.ctx.config.paths.workflow_dir, target.taskId);
72
- const task = await loadTaskFromContext({ ctx: opts.ctx, taskId: target.taskId });
73
- const metaPath = path.join(gitRoot, taskDirRelative, "pr", "meta.json");
74
- if (!(await fileExists(metaPath))) {
75
- throw new CliError({
76
- exitCode: 3,
77
- code: "E_VALIDATION",
78
- message: `Hosted task closure could not find pr/meta.json for ${target.taskId}`,
245
+ const taskReadmePath = path.join(gitRoot, taskDirRelative, "README.md");
246
+ let task;
247
+ try {
248
+ task = await loadTaskFromContext({
249
+ ctx: opts.ctx,
250
+ taskId: target.taskId,
251
+ preferBranchSnapshot: true,
252
+ branchSnapshotBranch: target.branch,
79
253
  });
80
254
  }
81
- const rawMeta = await readFile(metaPath, "utf8");
82
- const meta = parsePrMeta(rawMeta, target.taskId);
83
- const alreadyClosed = String(task.status || "TODO").toUpperCase() === "DONE" &&
84
- (task.commit?.hash ?? "") === target.mergedPr.mergeCommit.oid &&
85
- meta.status === "MERGED" &&
86
- (meta.merge_commit ?? "") === target.mergedPr.mergeCommit.oid;
87
- if (String(task.status || "TODO").toUpperCase() === "DONE" &&
88
- (task.commit?.hash ?? "") !== "" &&
89
- (task.commit?.hash ?? "") !== target.mergedPr.mergeCommit.oid) {
255
+ catch (err) {
256
+ if (!isMissingTaskReadmeError(err, taskReadmePath))
257
+ throw err;
258
+ const recovered = await buildHostedTaskFromTrackedPrArtifacts({
259
+ gitRoot,
260
+ taskDirRelative,
261
+ taskId: target.taskId,
262
+ mergedPr: target.mergedPr,
263
+ });
264
+ if (!recovered)
265
+ throw err;
266
+ task = recovered;
267
+ }
268
+ if (!(await fileExists(taskReadmePath))) {
269
+ await opts.ctx.taskBackend.writeTask(task);
270
+ }
271
+ const { metaPath, meta } = await readHostedPrMetaOrFallback({
272
+ gitRoot,
273
+ taskDirRelative,
274
+ target,
275
+ });
276
+ const taskStatus = String(task.status || "TODO").toUpperCase();
277
+ const taskCommitHash = task.commit?.hash ?? "";
278
+ const alreadyClosed = taskStatus === "DONE" && taskCommitHash === target.mergedPr.mergeCommit.oid;
279
+ if (taskStatus === "DONE" &&
280
+ taskCommitHash !== "" &&
281
+ taskCommitHash !== target.mergedPr.mergeCommit.oid) {
90
282
  throw new CliError({
91
283
  exitCode: 3,
92
284
  code: "E_VALIDATION",
@@ -119,7 +311,7 @@ async function closeHostedTask(opts) {
119
311
  cwd: opts.cwd,
120
312
  rootOverride: opts.rootOverride,
121
313
  taskId: target.taskId,
122
- baseBranchOverride: target.mergedPr.baseRefName ?? meta.base ?? "main",
314
+ baseBranchOverride: nextMeta.base ?? "main",
123
315
  quiet: opts.quiet,
124
316
  });
125
317
  return {
@@ -128,10 +320,19 @@ async function closeHostedTask(opts) {
128
320
  mergeHash: target.mergedPr.mergeCommit.oid,
129
321
  };
130
322
  }
131
- const taskCommitInfo = await readCommitInfo(gitRoot, target.mergedPr.mergeCommit.oid);
323
+ const taskCommitInfo = await resolveHostedTaskCommitInfo({
324
+ gitRoot,
325
+ mergedPr: target.mergedPr,
326
+ });
132
327
  const prLabel = `PR #${target.mergedPr.number}`;
133
328
  const finishBody = `Verified: ${prLabel} merged on GitHub ${target.mergedPr.baseRefName ?? "main"}; ` +
134
329
  "hosted closure automation recorded canonical task artifacts.";
330
+ await collectTaskIncidents({
331
+ ctx: opts.ctx,
332
+ taskId: target.taskId,
333
+ task,
334
+ write: false,
335
+ });
135
336
  await writeFinishedTasks({
136
337
  ctx: opts.ctx,
137
338
  loadedTasks: [{ taskId: target.taskId, task }],
@@ -145,13 +346,27 @@ async function closeHostedTask(opts) {
145
346
  breaking: false,
146
347
  taskCommitInfo,
147
348
  });
349
+ const collectedIncidents = await collectTaskIncidents({
350
+ ctx: opts.ctx,
351
+ taskId: target.taskId,
352
+ write: true,
353
+ });
354
+ if (!opts.quiet) {
355
+ process.stdout.write(`${infoMessage(renderIncidentCollectionPlanOutcome(collectedIncidents.plan, {
356
+ wrote: collectedIncidents.wrote,
357
+ context: "finish",
358
+ promotedIds: collectedIncidents.plan.promotable.map((item) => item.entry.id),
359
+ registryPaths: collectedIncidents.registryPaths,
360
+ }))}\n`);
361
+ }
148
362
  await createTaskCloseCommit({
149
363
  ctx: opts.ctx,
150
364
  cwd: opts.cwd,
151
365
  rootOverride: opts.rootOverride,
152
366
  taskId: target.taskId,
153
- baseBranchOverride: target.mergedPr.baseRefName ?? meta.base ?? "main",
367
+ baseBranchOverride: nextMeta.base ?? "main",
154
368
  quiet: opts.quiet,
369
+ allowPolicy: collectedIncidents.wrote,
155
370
  });
156
371
  return {
157
372
  outcome: "closed",
@@ -1,3 +1,4 @@
1
+ import { type TaskPrMeta } from "@agentplaneorg/core";
1
2
  import type { TaskData } from "../../backends/task-backend.js";
2
3
  import type { CommandContext } from "../shared/task-backend.js";
3
4
  export type HostedMergedPr = {
@@ -21,10 +22,38 @@ type HostedMergeSyncResult = {
21
22
  tasks: TaskData[];
22
23
  synced: number;
23
24
  };
25
+ export type LocalBranchPrSyncCandidate = {
26
+ taskId: string;
27
+ branch: string;
28
+ base: string;
29
+ commitHash: string;
30
+ verificationSource: "task" | "pr" | null;
31
+ metaPath: string | null;
32
+ meta: TaskPrMeta | null;
33
+ taskStatus: string;
34
+ };
35
+ export type LocalDoneBranchPrDrift = {
36
+ taskId: string;
37
+ branch: string;
38
+ base: string;
39
+ commitHash: string;
40
+ };
41
+ export type LocalMergedPrMeta = {
42
+ branch: string;
43
+ base?: string | null;
44
+ mergedAt?: string | null;
45
+ mergeCommit: string;
46
+ headSha?: string | null;
47
+ };
48
+ export declare function resolveLocalMergedPrMeta(meta: TaskPrMeta | null): LocalMergedPrMeta | null;
24
49
  export declare function resolveHostedMergeTargetFromEvent(opts: {
25
50
  event: unknown;
26
51
  branchPrefix: string;
27
52
  }): HostedMergeTarget | null;
53
+ export declare function resolveHostedMergedPr(opts: {
54
+ cwd: string;
55
+ branch: string;
56
+ }): Promise<HostedMergedPr | null>;
28
57
  export declare function syncHostedMergedTask(opts: {
29
58
  ctx: CommandContext;
30
59
  tasks: TaskData[];
@@ -32,6 +61,18 @@ export declare function syncHostedMergedTask(opts: {
32
61
  missingTask?: "noop" | "error";
33
62
  missingPrMeta?: "noop" | "error";
34
63
  }): Promise<HostedMergeSyncResult>;
64
+ export declare function findLocallyShippedBranchPrTasks(opts: {
65
+ ctx: CommandContext;
66
+ tasks: TaskData[];
67
+ }): Promise<LocalBranchPrSyncCandidate[]>;
68
+ export declare function findDoneBranchPrTasksWithOpenPrArtifacts(opts: {
69
+ ctx: CommandContext;
70
+ tasks: TaskData[];
71
+ }): Promise<LocalDoneBranchPrDrift[]>;
72
+ export declare function syncLocallyShippedBranchPrTasks(opts: {
73
+ ctx: CommandContext;
74
+ tasks: TaskData[];
75
+ }): Promise<HostedMergeSyncResult>;
35
76
  export declare function syncHostedMergedTasks(opts: {
36
77
  ctx: CommandContext;
37
78
  tasks: TaskData[];
@@ -1 +1 @@
1
- {"version":3,"file":"hosted-merge-sync.d.ts","sourceRoot":"","sources":["../../../src/commands/task/hosted-merge-sync.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAM/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAGhE,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,cAAc,CAAC;CAC1B,CAAC;AAEF,KAAK,qBAAqB,GAAG;IAC3B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AA6EF,wBAAgB,iCAAiC,CAAC,IAAI,EAAE;IACtD,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,iBAAiB,GAAG,IAAI,CAY3B;AA2HD,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,GAAG,EAAE,cAAc,CAAC;IACpB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAClC,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAuDjC;AAED,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,GAAG,EAAE,cAAc,CAAC;IACpB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA0CjC"}
1
+ {"version":3,"file":"hosted-merge-sync.d.ts","sourceRoot":"","sources":["../../../src/commands/task/hosted-merge-sync.ts"],"names":[],"mappings":"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"}