@fitlab-ai/agent-infra 0.9.13 → 0.9.15

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 (428) hide show
  1. package/README.md +10 -0
  2. package/README.zh-CN.md +10 -0
  3. package/bin/cli.ts +26 -9
  4. package/bin/internal-cli.sh +45 -0
  5. package/dist/bin/cli.js +173 -157
  6. package/dist/bin/internal-cli.js +126 -42
  7. package/dist/lib/agent-client.js +5 -0
  8. package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +165 -27
  9. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +3 -2
  10. package/dist/lib/defaults.json +103 -103
  11. package/dist/lib/fs/durable-write.js +37 -0
  12. package/dist/lib/fs/file-lock.js +111 -0
  13. package/dist/lib/host-control/audit.js +19 -0
  14. package/dist/lib/host-control/client.js +142 -0
  15. package/dist/lib/host-control/command.js +49 -0
  16. package/dist/lib/host-control/path.js +160 -0
  17. package/dist/lib/host-control/secure-fs.js +140 -0
  18. package/dist/lib/host-control/server.js +159 -0
  19. package/dist/lib/host-control/service.js +112 -0
  20. package/dist/lib/init.js +11 -2
  21. package/dist/lib/internal/agent-client.js +5 -2
  22. package/dist/lib/internal/cli-route-inventory.js +154 -0
  23. package/dist/lib/internal/codex-lifecycle.js +15 -12
  24. package/dist/lib/internal/codex-sandbox-controller.js +8 -2
  25. package/dist/lib/internal/demo-promotion.js +322 -0
  26. package/dist/lib/internal/demo-transcript.js +454 -0
  27. package/dist/lib/internal/git-workflow.js +10 -6
  28. package/dist/lib/internal/host-control.js +28 -0
  29. package/dist/lib/internal/manual-validation.js +322 -0
  30. package/dist/lib/internal/platform-checks.js +16 -4
  31. package/dist/lib/internal/platform-comment.js +16 -4
  32. package/dist/lib/internal/platform-context.js +4 -1
  33. package/dist/lib/internal/platform-issue.js +12 -4
  34. package/dist/lib/internal/platform-metadata.js +88 -0
  35. package/dist/lib/internal/platform-pr-review.js +16 -3
  36. package/dist/lib/internal/platform-pr.js +42 -14
  37. package/dist/lib/internal/platform-release-notes.js +6 -3
  38. package/dist/lib/internal/platform-security.js +93 -0
  39. package/dist/lib/internal/pr-review-grade.js +14 -3
  40. package/dist/lib/internal/release-workflow.js +82 -89
  41. package/dist/lib/internal/sandbox-control.js +171 -7
  42. package/dist/lib/internal/task-activity.js +13 -4
  43. package/dist/lib/internal/task-artifact.js +19 -107
  44. package/dist/lib/internal/task-context.js +4 -1
  45. package/dist/lib/internal/task-create.js +48 -14
  46. package/dist/lib/internal/task-delivery.js +4 -1
  47. package/dist/lib/internal/task-event.js +38 -35
  48. package/dist/lib/internal/task-finalization.js +4 -1
  49. package/dist/lib/internal/task-invalidation.js +4 -1
  50. package/dist/lib/internal/task-ledger.js +12 -1
  51. package/dist/lib/internal/task-lifecycle.js +4 -1
  52. package/dist/lib/internal/task-operation-registry.js +519 -0
  53. package/dist/lib/internal/task-orchestration.js +12 -0
  54. package/dist/lib/internal/task-override.js +10 -3
  55. package/dist/lib/internal/task-qualification.js +90 -0
  56. package/dist/lib/internal/task-review.js +10 -52
  57. package/dist/lib/internal/task-short-id.js +11 -1
  58. package/dist/lib/internal/task-snapshot.js +4 -1
  59. package/dist/lib/internal/task-validate.js +37 -12
  60. package/dist/lib/internal/task-verify.js +5 -1
  61. package/dist/lib/internal/task-warning.js +8 -1
  62. package/dist/lib/owned-path.js +33 -0
  63. package/dist/lib/platform/check-status.js +11 -0
  64. package/dist/lib/platform/comment-safety.js +229 -0
  65. package/dist/lib/platform/completion-backfill.js +1 -1
  66. package/dist/lib/platform/github-data.js +241 -0
  67. package/dist/lib/platform/github-provider.js +248 -26
  68. package/dist/lib/platform/issue-comments.js +146 -34
  69. package/dist/lib/platform/issues.js +1 -179
  70. package/dist/lib/platform/pr-change-report.js +6 -12
  71. package/dist/lib/platform/pr-checks.js +12 -65
  72. package/dist/lib/platform/pr-summary.js +83 -10
  73. package/dist/lib/platform/provider-contract.d.ts +67 -1
  74. package/dist/lib/platform/provider-contract.js +6 -2
  75. package/dist/lib/platform/provider-validation.js +76 -3
  76. package/dist/lib/platform/pull-requests.js +117 -275
  77. package/dist/lib/platform/repository-metadata.js +377 -0
  78. package/dist/lib/platform/security-alerts.js +155 -0
  79. package/dist/lib/platform/snapshots.js +2 -0
  80. package/dist/lib/platform/verification-sync.js +154 -162
  81. package/dist/lib/process-data/index.js +7 -0
  82. package/dist/lib/release/workflow.js +1 -1
  83. package/dist/lib/run/index.js +5 -0
  84. package/dist/lib/sandbox/commands/control-status.js +22 -0
  85. package/dist/lib/sandbox/commands/create.js +39 -8
  86. package/dist/lib/sandbox/commands/ls.js +5 -0
  87. package/dist/lib/sandbox/commands/rm.js +3 -807
  88. package/dist/lib/sandbox/commands/show.js +16 -0
  89. package/dist/lib/sandbox/control/audit.js +203 -0
  90. package/dist/lib/sandbox/control/client.js +125 -12
  91. package/dist/lib/sandbox/control/completed-reentry.js +85 -0
  92. package/dist/lib/sandbox/control/container-identity.js +28 -31
  93. package/dist/lib/sandbox/control/executor.js +233 -34
  94. package/dist/lib/sandbox/control/finalization-response.js +27 -0
  95. package/dist/lib/sandbox/control/identity-sentinel.js +107 -0
  96. package/dist/lib/sandbox/control/lifecycle.js +656 -128
  97. package/dist/lib/sandbox/control/native-file-lock.js +85 -0
  98. package/dist/lib/sandbox/control/protocol.js +55 -4
  99. package/dist/lib/sandbox/control/server.js +720 -79
  100. package/dist/lib/sandbox/control/state.js +63 -3
  101. package/dist/lib/sandbox/control/task-view.js +183 -0
  102. package/dist/lib/sandbox/control/task-workflow.js +74 -0
  103. package/dist/lib/sandbox/control/workflow-executor.js +99 -0
  104. package/dist/lib/sandbox/engines/authority.js +289 -0
  105. package/dist/lib/sandbox/engines/docker-exact-discovery.js +97 -0
  106. package/dist/lib/sandbox/index.js +7 -2
  107. package/dist/lib/sandbox/recovery.js +49 -5
  108. package/dist/lib/sandbox/removal.js +1717 -0
  109. package/dist/lib/sandbox/task-cleanup.js +217 -0
  110. package/dist/lib/sandbox/workspace-view.js +15 -15
  111. package/dist/lib/sandbox/worktree-safety.js +4 -1
  112. package/dist/lib/server/index.js +8 -0
  113. package/dist/lib/task/activity-intent.js +2 -1
  114. package/dist/lib/task/activity-log.js +30 -24
  115. package/dist/lib/task/artifact-command.js +101 -0
  116. package/dist/lib/task/artifact-lifecycle.js +71 -40
  117. package/dist/lib/task/artifact-name.js +36 -0
  118. package/dist/lib/task/artifact-operations.js +474 -0
  119. package/dist/lib/task/artifact-receipts.js +3 -15
  120. package/dist/lib/task/artifact-repair-intent.js +130 -0
  121. package/dist/lib/task/artifact-schema.js +127 -0
  122. package/dist/lib/task/capabilities.js +83 -19
  123. package/dist/lib/task/codex-orchestration.js +71 -25
  124. package/dist/lib/task/commit-identity.js +28 -0
  125. package/dist/lib/task/commit-operation.js +2 -16
  126. package/dist/lib/task/control-authority.js +375 -5
  127. package/dist/lib/task/control-recovery.js +128 -0
  128. package/dist/lib/task/create-service.js +103 -4
  129. package/dist/lib/task/create.js +80 -2
  130. package/dist/lib/task/decision-details.js +2 -46
  131. package/dist/lib/task/events.js +306 -76
  132. package/dist/lib/task/finalization-state.js +9 -0
  133. package/dist/lib/task/human-override.js +3 -6
  134. package/dist/lib/task/implementation-inputs.js +3 -3
  135. package/dist/lib/task/index.js +11 -3
  136. package/dist/lib/task/intermediate-cleanup.js +383 -0
  137. package/dist/lib/task/invalidation.js +18 -65
  138. package/dist/lib/task/ledger-intents.js +7 -22
  139. package/dist/lib/task/ledger.js +1 -3
  140. package/dist/lib/task/lifecycle.js +19 -1
  141. package/dist/lib/task/local-artifact-finalization.js +190 -290
  142. package/dist/lib/task/manual-validation-completion.js +26 -0
  143. package/dist/lib/task/manual-validation-evidence.js +130 -0
  144. package/dist/lib/task/manual-validation-receipt.js +101 -0
  145. package/dist/lib/task/manual-validation-shared.js +40 -0
  146. package/dist/lib/task/manual-validation-transaction.js +243 -0
  147. package/dist/lib/task/markdown.js +47 -0
  148. package/dist/lib/task/orchestration.js +206 -69
  149. package/dist/lib/task/qualification-audit.js +476 -0
  150. package/dist/lib/task/qualification-confirmation.js +109 -0
  151. package/dist/lib/task/qualification-intents.js +148 -0
  152. package/dist/lib/task/review-artifacts.js +23 -40
  153. package/dist/lib/task/review-command.js +25 -0
  154. package/dist/lib/task/review-finalization.js +146 -97
  155. package/dist/lib/task/review-fingerprint.js +2 -2
  156. package/dist/lib/task/sections.js +34 -54
  157. package/dist/lib/task/verification-config.js +11 -0
  158. package/dist/lib/task/verification-engine.js +170 -327
  159. package/dist/lib/task/verification.js +1 -1
  160. package/dist/lib/task/workflow-command.js +17 -0
  161. package/dist/lib/task/workflow-warning-intents.js +0 -16
  162. package/dist/lib/task/workflow-warnings.js +28 -2
  163. package/dist/lib/update.js +2 -0
  164. package/dist/lifecycle-build-manifest.json +3 -3
  165. package/lib/agent-client.ts +9 -0
  166. package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +223 -33
  167. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +3 -2
  168. package/lib/fs/durable-write.ts +29 -0
  169. package/lib/fs/file-lock.ts +113 -0
  170. package/lib/host-control/audit.ts +22 -0
  171. package/lib/host-control/client.ts +172 -0
  172. package/lib/host-control/command.ts +60 -0
  173. package/lib/host-control/path.ts +167 -0
  174. package/lib/host-control/secure-fs.ts +135 -0
  175. package/lib/host-control/server.ts +180 -0
  176. package/lib/host-control/service.ts +133 -0
  177. package/lib/init.ts +15 -2
  178. package/lib/internal/agent-client.ts +4 -2
  179. package/lib/internal/cli-route-inventory.ts +142 -0
  180. package/lib/internal/codex-lifecycle.ts +14 -12
  181. package/lib/internal/codex-sandbox-controller.ts +7 -2
  182. package/lib/internal/demo-promotion.ts +354 -0
  183. package/lib/internal/demo-transcript.ts +419 -0
  184. package/lib/internal/git-workflow.ts +9 -6
  185. package/lib/internal/host-control.ts +28 -0
  186. package/lib/internal/manual-validation.ts +306 -0
  187. package/lib/internal/platform-checks.ts +12 -4
  188. package/lib/internal/platform-comment.ts +12 -4
  189. package/lib/internal/platform-context.ts +3 -1
  190. package/lib/internal/platform-issue.ts +11 -4
  191. package/lib/internal/platform-metadata.ts +70 -0
  192. package/lib/internal/platform-pr-review.ts +14 -3
  193. package/lib/internal/platform-pr.ts +38 -14
  194. package/lib/internal/platform-release-notes.ts +5 -3
  195. package/lib/internal/platform-security.ts +83 -0
  196. package/lib/internal/pr-review-grade.ts +10 -3
  197. package/lib/internal/release-workflow.ts +91 -87
  198. package/lib/internal/sandbox-control.ts +181 -6
  199. package/lib/internal/task-activity.ts +12 -4
  200. package/lib/internal/task-artifact.ts +15 -79
  201. package/lib/internal/task-context.ts +3 -1
  202. package/lib/internal/task-create.ts +76 -15
  203. package/lib/internal/task-delivery.ts +3 -1
  204. package/lib/internal/task-event.ts +21 -10
  205. package/lib/internal/task-finalization.ts +3 -1
  206. package/lib/internal/task-invalidation.ts +3 -1
  207. package/lib/internal/task-ledger.ts +11 -1
  208. package/lib/internal/task-lifecycle.ts +3 -1
  209. package/lib/internal/task-operation-registry.ts +590 -0
  210. package/lib/internal/task-orchestration.ts +12 -0
  211. package/lib/internal/task-override.ts +9 -3
  212. package/lib/internal/task-qualification.ts +61 -0
  213. package/lib/internal/task-review.ts +7 -50
  214. package/lib/internal/task-short-id.ts +10 -1
  215. package/lib/internal/task-snapshot.ts +3 -1
  216. package/lib/internal/task-validate.ts +32 -12
  217. package/lib/internal/task-verify.ts +4 -1
  218. package/lib/internal/task-warning.ts +7 -1
  219. package/lib/owned-path.ts +26 -0
  220. package/lib/platform/check-status.ts +9 -0
  221. package/lib/platform/comment-safety.ts +255 -0
  222. package/lib/platform/completion-backfill.ts +1 -1
  223. package/lib/platform/github-data.ts +322 -0
  224. package/lib/platform/github-provider.ts +244 -27
  225. package/lib/platform/issue-comments.ts +159 -35
  226. package/lib/platform/issues.ts +4 -245
  227. package/lib/platform/pr-change-report.ts +6 -12
  228. package/lib/platform/pr-checks.ts +13 -77
  229. package/lib/platform/pr-summary.ts +88 -11
  230. package/lib/platform/provider-contract.ts +78 -3
  231. package/lib/platform/provider-validation.ts +85 -3
  232. package/lib/platform/pull-requests.ts +129 -348
  233. package/lib/platform/repository-metadata.ts +453 -0
  234. package/lib/platform/security-alerts.ts +191 -0
  235. package/lib/platform/snapshots.ts +53 -0
  236. package/lib/platform/verification-sync.ts +171 -177
  237. package/lib/process-data/index.ts +7 -0
  238. package/lib/release/workflow.ts +3 -3
  239. package/lib/run/index.ts +5 -0
  240. package/lib/sandbox/commands/control-status.ts +26 -0
  241. package/lib/sandbox/commands/create.ts +53 -12
  242. package/lib/sandbox/commands/ls.ts +7 -0
  243. package/lib/sandbox/commands/rm.ts +3 -996
  244. package/lib/sandbox/commands/show.ts +16 -0
  245. package/lib/sandbox/control/audit.ts +253 -0
  246. package/lib/sandbox/control/client.ts +150 -13
  247. package/lib/sandbox/control/completed-reentry.ts +98 -0
  248. package/lib/sandbox/control/container-identity.ts +27 -43
  249. package/lib/sandbox/control/executor.ts +262 -37
  250. package/lib/sandbox/control/finalization-response.ts +29 -0
  251. package/lib/sandbox/control/identity-sentinel.ts +137 -0
  252. package/lib/sandbox/control/lifecycle.ts +672 -18
  253. package/lib/sandbox/control/native-file-lock.ts +108 -0
  254. package/lib/sandbox/control/protocol.ts +80 -8
  255. package/lib/sandbox/control/server.ts +779 -82
  256. package/lib/sandbox/control/state.ts +84 -3
  257. package/lib/sandbox/control/task-view.ts +240 -0
  258. package/lib/sandbox/control/task-workflow.ts +95 -0
  259. package/lib/sandbox/control/workflow-executor.ts +102 -0
  260. package/lib/sandbox/engines/authority.ts +365 -0
  261. package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
  262. package/lib/sandbox/index.ts +9 -2
  263. package/lib/sandbox/recovery.ts +49 -6
  264. package/lib/sandbox/removal.ts +2144 -0
  265. package/lib/sandbox/task-cleanup.ts +209 -0
  266. package/lib/sandbox/workspace-view.ts +26 -18
  267. package/lib/sandbox/worktree-safety.ts +4 -1
  268. package/lib/server/index.ts +10 -0
  269. package/lib/task/activity-intent.ts +2 -2
  270. package/lib/task/activity-log.ts +27 -19
  271. package/lib/task/artifact-command.ts +104 -0
  272. package/lib/task/artifact-lifecycle.ts +66 -39
  273. package/lib/task/artifact-name.ts +55 -0
  274. package/lib/task/artifact-operations.ts +580 -0
  275. package/lib/task/artifact-receipts.ts +3 -14
  276. package/lib/task/artifact-repair-intent.ts +152 -0
  277. package/lib/task/artifact-schema.ts +163 -0
  278. package/lib/task/capabilities.ts +82 -22
  279. package/lib/task/codex-orchestration.ts +85 -24
  280. package/lib/task/commit-identity.ts +31 -0
  281. package/lib/task/commit-operation.ts +2 -16
  282. package/lib/task/control-authority.ts +513 -6
  283. package/lib/task/control-recovery.ts +174 -0
  284. package/lib/task/create-service.ts +131 -6
  285. package/lib/task/create.ts +83 -1
  286. package/lib/task/decision-details.ts +3 -71
  287. package/lib/task/events.ts +292 -75
  288. package/lib/task/finalization-state.ts +11 -0
  289. package/lib/task/human-override.ts +3 -8
  290. package/lib/task/implementation-inputs.ts +3 -3
  291. package/lib/task/index.ts +16 -3
  292. package/lib/task/intermediate-cleanup.ts +455 -0
  293. package/lib/task/invalidation.ts +18 -62
  294. package/lib/task/ledger-intents.ts +7 -24
  295. package/lib/task/ledger.ts +1 -3
  296. package/lib/task/lifecycle.ts +17 -1
  297. package/lib/task/local-artifact-finalization.ts +223 -388
  298. package/lib/task/manual-validation-completion.ts +40 -0
  299. package/lib/task/manual-validation-evidence.ts +209 -0
  300. package/lib/task/manual-validation-receipt.ts +152 -0
  301. package/lib/task/manual-validation-shared.ts +50 -0
  302. package/lib/task/manual-validation-transaction.ts +304 -0
  303. package/lib/task/markdown.ts +70 -0
  304. package/lib/task/orchestration.ts +191 -68
  305. package/lib/task/qualification-audit.ts +588 -0
  306. package/lib/task/qualification-confirmation.ts +117 -0
  307. package/lib/task/qualification-intents.ts +150 -0
  308. package/lib/task/review-artifacts.ts +21 -41
  309. package/lib/task/review-command.ts +23 -0
  310. package/lib/task/review-finalization.ts +154 -153
  311. package/lib/task/review-fingerprint.ts +2 -2
  312. package/lib/task/sections.ts +33 -52
  313. package/lib/task/verification-config.ts +12 -0
  314. package/lib/task/verification-engine.ts +165 -370
  315. package/lib/task/verification-types.ts +17 -0
  316. package/lib/task/verification.ts +1 -1
  317. package/lib/task/workflow-command.ts +18 -0
  318. package/lib/task/workflow-warning-intents.ts +0 -13
  319. package/lib/task/workflow-warnings.ts +21 -2
  320. package/lib/update.ts +6 -0
  321. package/package.json +7 -2
  322. package/templates/.agents/hooks/lifecycle-delegation.js +6 -6
  323. package/templates/.agents/rules/README.en.md +2 -0
  324. package/templates/.agents/rules/README.zh-CN.md +2 -0
  325. package/templates/.agents/rules/decision-qualification.en.md +22 -0
  326. package/templates/.agents/rules/decision-qualification.zh-CN.md +22 -0
  327. package/templates/.agents/rules/evidence-reporting.en.md +28 -0
  328. package/templates/.agents/rules/evidence-reporting.zh-CN.md +28 -0
  329. package/templates/.agents/rules/label-milestone-setup.en.md +7 -7
  330. package/templates/.agents/rules/label-milestone-setup.zh-CN.md +7 -7
  331. package/templates/.agents/rules/local-artifact-repair.en.md +5 -1
  332. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +5 -1
  333. package/templates/.agents/rules/security-alerts.en.md +8 -8
  334. package/templates/.agents/rules/security-alerts.zh-CN.md +8 -8
  335. package/templates/.agents/rules/testing-discipline.en.md +2 -0
  336. package/templates/.agents/rules/testing-discipline.zh-CN.md +2 -0
  337. package/templates/.agents/scripts/package.json +3 -0
  338. package/templates/.agents/skills/analyze-task/SKILL.en.md +15 -2
  339. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +19 -2
  340. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -12
  341. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -12
  342. package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
  343. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
  344. package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
  345. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
  346. package/templates/.agents/skills/code-task/SKILL.en.md +14 -1
  347. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +14 -1
  348. package/templates/.agents/skills/code-task/config/verify.en.json +5 -14
  349. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +5 -14
  350. package/templates/.agents/skills/code-task/reference/code-rules.en.md +5 -4
  351. package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +5 -4
  352. package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
  353. package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
  354. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +3 -1
  355. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +3 -1
  356. package/templates/.agents/skills/code-task/reference/report-template.en.md +42 -15
  357. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +39 -12
  358. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +37 -21
  359. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +37 -21
  360. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
  361. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
  362. package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +4 -0
  363. package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +4 -0
  364. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +16 -7
  365. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +16 -7
  366. package/templates/.agents/skills/complete-task/SKILL.en.md +10 -23
  367. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +10 -23
  368. package/templates/.agents/skills/create-task/SKILL.en.md +8 -0
  369. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +7 -0
  370. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  371. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  372. package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
  373. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
  374. package/templates/.agents/skills/init-labels/SKILL.en.md +8 -8
  375. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +8 -8
  376. package/templates/.agents/skills/init-milestones/SKILL.en.md +9 -11
  377. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +9 -11
  378. package/templates/.agents/skills/plan-task/SKILL.en.md +14 -1
  379. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +16 -1
  380. package/templates/.agents/skills/plan-task/config/verify.en.json +4 -14
  381. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +4 -14
  382. package/templates/.agents/skills/release/SKILL.en.md +7 -3
  383. package/templates/.agents/skills/release/SKILL.zh-CN.md +7 -3
  384. package/templates/.agents/skills/review-analysis/SKILL.en.md +14 -1
  385. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +14 -1
  386. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -18
  387. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -18
  388. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +50 -23
  389. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +45 -18
  390. package/templates/.agents/skills/review-code/SKILL.en.md +14 -1
  391. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +14 -1
  392. package/templates/.agents/skills/review-code/config/verify.en.json +1 -23
  393. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -23
  394. package/templates/.agents/skills/review-code/reference/report-template.en.md +49 -22
  395. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +45 -18
  396. package/templates/.agents/skills/review-plan/SKILL.en.md +14 -1
  397. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +14 -1
  398. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -18
  399. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -18
  400. package/templates/.agents/skills/review-plan/reference/report-template.en.md +49 -22
  401. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +45 -18
  402. package/templates/.agents/skills/review-pr/SKILL.en.md +5 -1
  403. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +5 -1
  404. package/templates/.agents/skills/review-pr/reference/report-template.en.md +4 -3
  405. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +4 -3
  406. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +25 -4
  407. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +25 -4
  408. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +4 -1
  409. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +4 -1
  410. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +5 -1
  411. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +5 -1
  412. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  413. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  414. package/templates/.agents/skills/test/SKILL.en.md +29 -7
  415. package/templates/.agents/skills/test/SKILL.zh-CN.md +29 -7
  416. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +14 -0
  417. package/templates/.agents/templates/task.en.md +6 -0
  418. package/templates/.agents/templates/task.zh-CN.md +6 -0
  419. package/templates/.claude/commands/run-manual-validation.en.md +1 -1
  420. package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
  421. package/dist/lib/platform/adapters.js +0 -56
  422. package/lib/platform/adapters.ts +0 -197
  423. package/templates/.agents/scripts/security-alerts.github.sh +0 -151
  424. package/templates/.agents/scripts/security-alerts.sh +0 -31
  425. package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +0 -146
  426. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +0 -32
  427. package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +0 -294
  428. package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +0 -6
@@ -2,7 +2,8 @@ import fs from 'node:fs';
2
2
 
3
3
  import { parseTypedTaskFrontmatter } from '../task/frontmatter.ts';
4
4
  import { resolveTaskRef } from '../task/resolve-ref.ts';
5
- import type { PlatformCheckSnapshot } from './adapters.ts';
5
+ import type { PlatformCheckSnapshot } from './snapshots.ts';
6
+ import { checkStatusBucket } from './check-status.ts';
6
7
  import { resolvePlatformProviderContext } from './context.ts';
7
8
  import type { PlatformClient } from './context.ts';
8
9
  import { inspectPlatformPullRequest } from './pull-requests.ts';
@@ -33,7 +34,6 @@ type ChecksResult = PlatformResult & {
33
34
  resolution?: { status: 'resolved' | 'missing' | 'ambiguous'; runId: number | null; jobId: number | null };
34
35
  logs?: { runId: number; jobId?: number; text: string };
35
36
  };
36
- type GitHubClient = PlatformClient;
37
37
  type InspectionOptions = { cwd?: string; client?: PlatformClient; runtimeVersion?: string };
38
38
  type SharedOptions = { cwd?: string; client?: PlatformClient };
39
39
 
@@ -56,18 +56,6 @@ function classifyPullRequestReadiness(input: {
56
56
  return { state: 'ready', headSha: input.headSha };
57
57
  }
58
58
 
59
- function parseRunJobIdentity(detailsUrl: string): { runId: number; jobId: number | null } | null {
60
- try {
61
- const url = new URL(detailsUrl);
62
- if (url.hostname !== 'github.com') return null;
63
- const match = url.pathname.match(/\/actions\/runs\/(\d+)(?:\/job\/(\d+))?/);
64
- if (!match) return null;
65
- return { runId: Number(match[1]), jobId: match[2] ? Number(match[2]) : null };
66
- } catch {
67
- return null;
68
- }
69
- }
70
-
71
59
  function resolveRunCandidate(candidates: RunCandidate[], headSha: string, checkName: string):
72
60
  | { status: 'resolved'; runId: number; jobId: number | null }
73
61
  | { status: 'missing' | 'ambiguous'; runId: null; jobId: null } {
@@ -85,41 +73,6 @@ function checksResult(status: PlatformResult['status'], overrides: Partial<Check
85
73
  };
86
74
  }
87
75
 
88
- function normalizeBucket(value: { bucket?: string; status?: string; state?: string; conclusion?: string }): CheckBucket {
89
- const raw = String(value.bucket || value.status || value.conclusion || value.state || '').toLowerCase();
90
- if (['pass', 'success', 'successful', 'neutral'].includes(raw)) return 'pass';
91
- if (['fail', 'failure', 'failed', 'error', 'timed_out', 'action_required'].includes(raw)) return 'fail';
92
- if (['cancel', 'cancelled', 'canceled', 'skipped', 'stale'].includes(raw)) return 'cancel';
93
- return 'pending';
94
- }
95
-
96
- function normalizeChecks(value: unknown): CheckSnapshot[] {
97
- if (!Array.isArray(value)) return [];
98
- return value.flatMap((raw) => {
99
- const item = raw as Record<string, unknown>;
100
- const name = String(item.name || item.context || '');
101
- return name ? [{
102
- name,
103
- bucket: normalizeBucket(item as { bucket?: string; state?: string; conclusion?: string }),
104
- workflow: item.workflow ? String(item.workflow) : null,
105
- conclusion: item.conclusion ? String(item.conclusion) : item.state ? String(item.state) : null,
106
- detailsUrl: item.link ? String(item.link) : item.detailsUrl ? String(item.detailsUrl) : null,
107
- startedAt: item.startedAt ? String(item.startedAt) : null,
108
- completedAt: item.completedAt ? String(item.completedAt) : null
109
- }] : [];
110
- });
111
- }
112
-
113
- function inspectGitHubRequiredChecks(client: GitHubClient, repository: string, number: number, cwd: string) {
114
- const inspected = client.json<unknown>([
115
- 'pr', 'checks', String(number), '--repo', repository,
116
- '--json', 'name,state,bucket,link,workflow,startedAt,completedAt'
117
- ], { cwd });
118
- return inspected.ok
119
- ? { ok: true as const, value: normalizeChecks(inspected.value) }
120
- : { ok: false as const, error: inspected.error };
121
- }
122
-
123
76
  async function resolvedTask(taskRef: string, options: InspectionOptions) {
124
77
  const resolved = resolveTaskRef(taskRef, options.cwd ? { repoRoot: options.cwd } : {});
125
78
  if (!resolved.ok) return { ok: false as const, output: checksResult('failed', { error: { code: resolved.code, message: resolved.message, retryable: false } }) };
@@ -141,14 +94,12 @@ async function resolvedTask(taskRef: string, options: InspectionOptions) {
141
94
  async function inspectRequiredChecks(taskRef: string, options: InspectionOptions = {}): Promise<ChecksResult> {
142
95
  const base = await resolvedTask(taskRef, options);
143
96
  if (!base.ok) return base.output;
144
- return inspectChecksForResolvedTask(base, options);
97
+ return inspectChecksForResolvedTask(base);
145
98
  }
146
99
 
147
100
  async function inspectChecksForResolvedTask(
148
- base: Extract<Awaited<ReturnType<typeof resolvedTask>>, { ok: true }>,
149
- options: InspectionOptions
101
+ base: Extract<Awaited<ReturnType<typeof resolvedTask>>, { ok: true }>
150
102
  ): Promise<ChecksResult> {
151
- const repository = base.context.platform.repository!;
152
103
  {
153
104
  const inspected = base.provider.checks?.inspectRequired
154
105
  ? await base.provider.checks.inspectRequired({
@@ -164,7 +115,13 @@ async function inspectChecksForResolvedTask(
164
115
  pullRequest: base.pullRequest,
165
116
  error: providerError(inspected.error, 'PLATFORM_PROVIDER_OPERATION_FAILED')
166
117
  });
167
- const required = normalizeChecks(inspected.value);
118
+ const required = inspected.value.map((check): CheckSnapshot => ({
119
+ name: check.name,
120
+ bucket: checkStatusBucket(check.status),
121
+ conclusion: check.conclusion || null,
122
+ detailsUrl: check.detailsUrl || null,
123
+ workflow: null, startedAt: null, completedAt: null
124
+ }));
168
125
  const classified = classifyRequiredChecks(required);
169
126
  const status = classified.state === 'passed' || classified.state === 'no-required'
170
127
  ? 'no-op'
@@ -184,7 +141,7 @@ async function inspectChecksForResolvedTask(
184
141
  async function inspectPullRequestReadiness(taskRef: string, options: InspectionOptions = {}): Promise<ChecksResult> {
185
142
  const base = await resolvedTask(taskRef, options);
186
143
  if (!base.ok) return base.output;
187
- const checked = await inspectChecksForResolvedTask(base, options);
144
+ const checked = await inspectChecksForResolvedTask(base);
188
145
  const classifiedCodes = new Set(['REQUIRED_CHECKS_PENDING', 'REQUIRED_CHECKS_FAILED', 'REQUIRED_CHECKS_CANCELLED']);
189
146
  if (checked.error && !classifiedCodes.has(checked.error.code)) return checked;
190
147
  const readiness = classifyPullRequestReadiness({
@@ -271,15 +228,6 @@ async function resolvePlatformCheckRun(taskRef: string, options: SharedOptions &
271
228
  }
272
229
  }
273
230
 
274
- function fetchCheckLogText(client: GitHubClient, args: string[], cwd: string) {
275
- if (!client.text) return { ok: false as const, error: { code: 'PLATFORM_CLIENT_TEXT_UNAVAILABLE', message: 'Platform client does not support text responses', retryable: false } };
276
- const fetched = client.text(args, { cwd });
277
- if (fetched.ok || args[0] !== 'api' || !/response contains terminal escape sequences/i.test(fetched.error.message)) {
278
- return fetched;
279
- }
280
- return client.text([...args, '--allow-escape-sequences'], { cwd });
281
- }
282
-
283
231
  async function fetchPlatformCheckLogs(taskRef: string, options: SharedOptions & { run: number; job?: number }): Promise<ChecksResult> {
284
232
  const base = await resolvedTask(taskRef, options);
285
233
  if (!base.ok) return base.output;
@@ -308,17 +256,5 @@ async function fetchPlatformCheckLogs(taskRef: string, options: SharedOptions &
308
256
  }
309
257
  }
310
258
 
311
- export {
312
- classifyPullRequestReadiness,
313
- classifyRequiredChecks,
314
- fetchCheckLogText,
315
- fetchPlatformCheckLogs,
316
- inspectGitHubRequiredChecks,
317
- inspectRequiredChecks,
318
- inspectPullRequestReadiness,
319
- parseRunJobIdentity,
320
- resolvePlatformCheckRun,
321
- resolveRunCandidate,
322
- watchPullRequestReadiness
323
- };
259
+ export { classifyPullRequestReadiness, classifyRequiredChecks, fetchPlatformCheckLogs, inspectRequiredChecks, inspectPullRequestReadiness, resolvePlatformCheckRun, resolveRunCandidate, watchPullRequestReadiness };
324
260
  export type { CheckBucket, CheckSnapshot, ChecksResult, ChecksSnapshot, CheckState, ReadinessSnapshot, ReadinessState, RunCandidate };
@@ -11,14 +11,16 @@ import type { PrDeliveryFact } from '../task/pr-delivery-fact.ts';
11
11
  import { resolvePlatformProviderContext } from './context.ts';
12
12
  import type { LoadedContext, PlatformClient } from './context.ts';
13
13
  import { normalizeCommentContent } from './issue-comments.ts';
14
+ import { CONTROL_MARKER_PATTERN, escapeHtmlText, sanitizeMarkdownDocument, splitDocumentPlaceholder } from './comment-safety.ts';
14
15
  import { platformResult } from './types.ts';
15
16
  import type { PlatformResult } from './types.ts';
16
17
  import type { OperationWarning } from '../task/operation-outcome.ts';
17
18
  import { providerError, providerOperationContext, providerStatus, providerResourceToken, resourceIdentityNumber, unsupportedProviderOperation } from './provider-bridge.ts';
18
- import type { PlatformChangeRequestSnapshot } from './adapters.ts';
19
+ import type { PlatformChangeRequestSnapshot } from './snapshots.ts';
19
20
  import type { ChangeRequestSnapshot } from './provider-contract.ts';
20
21
  import {
21
22
  buildPrChangeReport,
23
+ CANONICAL_REPORT_PLACEHOLDER,
22
24
  readPrChangeReport,
23
25
  replaceCanonicalReportPlaceholder,
24
26
  runMechanicalChangeReport,
@@ -31,6 +33,8 @@ import type {
31
33
  MechanicalChangeReport,
32
34
  PrChangeReport
33
35
  } from './pr-change-report.ts';
36
+ import { manualValidationFinalSummaryProjectionMatches } from '../task/manual-validation-receipt.ts';
37
+ import { readManualValidationCompletion } from '../task/manual-validation-completion.ts';
34
38
 
35
39
  type SummaryComment = { id: number | string; body: string };
36
40
  type ChangeReportState = 'ready' | 'missing' | 'stale' | 'invalid';
@@ -48,20 +52,28 @@ type PullRequestSummaryResult = PlatformResult & {
48
52
  };
49
53
  type PullRequestPrimaryResult = 'pr_created' | 'pr_reused' | 'no_op';
50
54
  type SummaryOptions = { cwd?: string; client?: PlatformClient; runtimeVersion?: string };
55
+ type ManualValidationSummaryOptions = {
56
+ phase: 'pending' | 'final';
57
+ transactionId?: string;
58
+ receiptDigest?: string;
59
+ prHeadSha?: string;
60
+ authority?: 'coordinator';
61
+ };
51
62
  type ReportWriteResult = PlatformResult & {
52
63
  report: { path: string; status: 'written' | 'no-op' | 'planned'; precheckVerdict: 'clear' | 'needs-review'; nextAction: 'watch-pr' | 'review-code' } | null;
53
64
  };
65
+ type SummaryCommentStateResult = Omit<PlatformResult, 'comment'> & {
66
+ task: { id: string | null; prNumber: number | null };
67
+ pullRequest: PlatformChangeRequestSnapshot | null;
68
+ comment: SummaryComment | null;
69
+ };
54
70
 
55
71
  function summaryMarker(taskId: string): string {
56
72
  return `<!-- sync-pr:${taskId}:summary -->`;
57
73
  }
58
74
 
59
75
  function escapeSummaryAuditText(value: string): string {
60
- return value
61
- .replace(/&/g, '&amp;')
62
- .replace(/</g, '&lt;')
63
- .replace(/>/g, '&gt;')
64
- .replace(/\r\n?/g, '\n');
76
+ return escapeHtmlText(value).replace(/\r\n?/g, '\n');
65
77
  }
66
78
 
67
79
  function renderSummaryAuditLine(value: string): string {
@@ -356,6 +368,23 @@ async function summaryContext(taskRef: string, options: SummaryOptions = {}): Pr
356
368
  };
357
369
  }
358
370
 
371
+ async function summaryCommentState(taskRef: string, options: SummaryOptions = {}): Promise<SummaryCommentStateResult> {
372
+ const context = await summaryContext(taskRef, options);
373
+ if (!context.task.prNumber || !context.pullRequest) return { ...context, comment: null };
374
+ const loaded = await resolvePlatformProviderContext({ cwd: options.cwd, client: options.client });
375
+ if (!loaded.ok || !loaded.value.provider.comments?.list) return { ...context, comment: null };
376
+ const listed = await loaded.value.provider.comments.list({
377
+ context: providerOperationContext(loaded.value),
378
+ parent: providerResourceToken(loaded.value.provider, 'pull-request', String(context.task.prNumber))
379
+ });
380
+ if (!listed.ok) return { ...context, comment: null };
381
+ const matches = listed.value.filter((comment) => comment.body.includes(summaryMarker(context.task.id!)));
382
+ return {
383
+ ...context,
384
+ comment: matches.length === 1 ? { id: /^\d+$/u.test(matches[0]!.id) ? Number(matches[0]!.id) : matches[0]!.id, body: matches[0]!.body } : null
385
+ };
386
+ }
387
+
359
388
  type ReportWriteOptions = {
360
389
  agent: string;
361
390
  mechanicalFile: string;
@@ -452,7 +481,7 @@ async function reportWrite(taskRef: string, options: ReportWriteOptions): Promis
452
481
 
453
482
  async function syncPullRequestSummary(
454
483
  taskRef: string,
455
- options: { agent: string; body: string; changeReportFile?: string; cwd?: string; client?: PlatformClient; dryRun?: boolean; strict?: boolean; primaryResult: PullRequestPrimaryResult; runtimeVersion?: string }
484
+ options: { agent: string; body: string; changeReportFile?: string; cwd?: string; client?: PlatformClient; dryRun?: boolean; strict?: boolean; primaryResult: PullRequestPrimaryResult; runtimeVersion?: string; manualValidation?: ManualValidationSummaryOptions; lockAlreadyHeld?: boolean }
456
485
  ): Promise<PullRequestSummaryResult> {
457
486
  const warningResult = warningResultForPrimary(options.primaryResult);
458
487
  let knownPrNumber: number | null = null;
@@ -505,7 +534,7 @@ async function syncPullRequestSummary(
505
534
  return preserveFailure(context);
506
535
  }
507
536
  try {
508
- return await withTaskExecutionLock(resolved.repoRoot, resolved.taskId, options.agent, async () => {
537
+ const execute = async (): Promise<PullRequestSummaryResult> => {
509
538
  const { taskContent, boundFact } = readBoundTaskSnapshot(resolved.taskMdPath);
510
539
  if (!boundFact) return {
511
540
  ...platformResult('failed', { resource: { kind: 'pull-request', number: null }, error: { code: 'PR_NOT_LINKED', message: 'Task has no verified bound pull request', retryable: false } }),
@@ -521,6 +550,27 @@ async function syncPullRequestSummary(
521
550
  const prNumber = boundPrNumber;
522
551
  const initial = await inspectBoundPullRequest(context, resolved.repoRoot, boundPrNumber, loaded.value);
523
552
  if (!initial.ok) return fail(initial.status, context, initial.error);
553
+ const manual = options.manualValidation;
554
+ const hasFinalManualValidation = /###\s+✅\s+(?:Manual Validation Passed|人工验证已通过)/u.test(options.body);
555
+ if (hasFinalManualValidation && (!manual || manual.phase !== 'final')) return fail('failed', context, { code: 'MANUAL_VALIDATION_TRANSACTION_REQUIRED', message: 'final manual-validation summary requires the transaction coordinator', retryable: false }, prNumber);
556
+ if (manual && (manual.phase === 'pending' ? hasFinalManualValidation : !hasFinalManualValidation)) return fail('failed', context, { code: 'MANUAL_VALIDATION_SUMMARY_PHASE_INVALID', message: 'manual-validation summary phase does not match the requested writer phase', retryable: false }, prNumber);
557
+ if (manual) {
558
+ if (manual.phase === 'final' && (!manual.transactionId || !manual.receiptDigest || !manual.prHeadSha || manual.prHeadSha !== initial.value.head.sha)) return fail('failed', context, { code: 'MANUAL_VALIDATION_TRANSACTION_REQUIRED', message: 'final manual-validation summary requires transaction, receipt, and current head identity', retryable: false }, prNumber);
559
+ if (manual.phase === 'final') {
560
+ if (manual.authority !== 'coordinator') return fail('failed', context, { code: 'MANUAL_VALIDATION_TRANSACTION_REQUIRED', message: 'final manual-validation summary requires coordinator authority', retryable: false }, prNumber);
561
+ const completion = readManualValidationCompletion(resolved.taskDir, {
562
+ transactionId: manual.transactionId,
563
+ taskId: resolved.taskId,
564
+ prNumber,
565
+ prHeadSha: initial.value.head.sha,
566
+ receiptDigest: manual.receiptDigest
567
+ });
568
+ if (!completion.ok) return fail('failed', context, platformError(completion.error), prNumber);
569
+ const { receipt, transaction } = completion.value;
570
+ if (transaction.phase !== 'final-promotion-in-progress' || !transaction.eventAppended) return fail('failed', context, { code: 'MANUAL_VALIDATION_TRANSACTION_PHASE_INVALID', message: 'final summary requires a receipt-backed promotion intent', retryable: false }, prNumber);
571
+ if (!manualValidationFinalSummaryProjectionMatches(options.body, receipt)) return fail('failed', context, { code: 'MANUAL_VALIDATION_SUMMARY_PROJECTION_INVALID', message: 'final summary body does not match the canonical receipt projection', retryable: false }, prNumber);
572
+ }
573
+ }
524
574
  const expectedReportPath = taskReportPath(resolved.taskDir);
525
575
  const suppliedReportPath = path.resolve(resolved.repoRoot, options.changeReportFile!);
526
576
  if (suppliedReportPath !== expectedReportPath) return fail('failed', context, { code: 'PR_CHANGE_REPORT_PATH_INVALID', message: 'summary-sync must consume the task-bound pr-change-report.json', retryable: false });
@@ -528,7 +578,30 @@ async function syncPullRequestSummary(
528
578
  if (!report.ok) return fail('failed', context, platformError(report.error));
529
579
  const checked = currentReportCheck(report.value, initial.value, taskContent, resolved.repoRoot);
530
580
  if (!checked.ok) return fail('failed', context, checked.error);
531
- const replaced = replaceCanonicalReportPlaceholder(options.body, report.value);
581
+ const placeholder = CANONICAL_REPORT_PLACEHOLDER;
582
+ const split = splitDocumentPlaceholder(options.body, placeholder);
583
+ if (!split.ok) return fail('failed', context, {
584
+ code: 'PR_SUMMARY_BODY_CONTRACT_INVALID',
585
+ message: split.error.message,
586
+ retryable: false
587
+ });
588
+ const prefix = sanitizeMarkdownDocument(split.value.prefix, { reservedMarkers: [CONTROL_MARKER_PATTERN] });
589
+ const suffix = sanitizeMarkdownDocument(split.value.suffix, { reservedMarkers: [CONTROL_MARKER_PATTERN] });
590
+ if (!prefix.ok) {
591
+ return fail('failed', context, {
592
+ code: 'PR_SUMMARY_BODY_CONTRACT_INVALID',
593
+ message: `${prefix.error.message} at offset ${prefix.error.offset}`,
594
+ retryable: false
595
+ });
596
+ }
597
+ if (!suffix.ok) {
598
+ return fail('failed', context, {
599
+ code: 'PR_SUMMARY_BODY_CONTRACT_INVALID',
600
+ message: `${suffix.error.message} at offset ${suffix.error.offset}`,
601
+ retryable: false
602
+ });
603
+ }
604
+ const replaced = replaceCanonicalReportPlaceholder(`${prefix.value}${placeholder}${suffix.value}`, report.value);
532
605
  if (!replaced.ok) return fail('failed', context, platformError(replaced.error));
533
606
  const desired = buildPullRequestSummary(resolved.taskId, replaced.value, initial.value.head.sha, renderHumanOverrideAudit(taskContent));
534
607
  if (!isSafeSummaryEnvelope(desired, resolved.taskId)) return fail('failed', context, {
@@ -630,7 +703,10 @@ async function syncPullRequestSummary(
630
703
  operations: [{ name: `summary:${reconciliation.action}`, status: 'applied', reasonCode: null }],
631
704
  result: null, warnings: [], ...info
632
705
  };
633
- });
706
+ };
707
+ return await (options.lockAlreadyHeld
708
+ ? execute()
709
+ : withTaskExecutionLock(resolved.repoRoot, resolved.taskId, options.agent, execute));
634
710
  } catch (error) {
635
711
  const lockError = error instanceof TaskExecutionLockError
636
712
  ? { code: error.code, message: error.message, retryable: error.code === 'ORCHESTRATION_LOCK_BUSY' }
@@ -643,9 +719,10 @@ export {
643
719
  buildPullRequestSummary,
644
720
  reconcileSummaryComment,
645
721
  reportWrite,
722
+ summaryCommentState,
646
723
  summaryContext,
647
724
  summaryMarker,
648
725
  syncPullRequestSummary,
649
726
  warningResultForPrimary
650
727
  };
651
- export type { PullRequestSummaryResult, ReportWriteOptions, ReportWriteResult, SummaryContextResult };
728
+ export type { ManualValidationSummaryOptions, PullRequestSummaryResult, ReportWriteOptions, ReportWriteResult, SummaryCommentStateResult, SummaryContextResult };
@@ -22,7 +22,7 @@ type PlatformError = {
22
22
 
23
23
  type ProviderResult<T> =
24
24
  | { ok: true; value: T }
25
- | { ok: false; error: PlatformError };
25
+ | { ok: false; error: PlatformError; value?: T };
26
26
 
27
27
  type ProviderOperationContext = {
28
28
  repositoryRoot: string;
@@ -162,6 +162,41 @@ type MutationReceipt = {
162
162
  operationId?: string;
163
163
  };
164
164
 
165
+ type SecurityAlertKind = 'dependabot' | 'code-scanning';
166
+
167
+ type SecurityAlertSnapshot = {
168
+ kind: SecurityAlertKind;
169
+ number: number;
170
+ state: string;
171
+ data: JsonValue;
172
+ };
173
+
174
+ type LabelDefinition = {
175
+ name: string;
176
+ color: string;
177
+ description: string;
178
+ };
179
+
180
+ type LabelReconciliation = {
181
+ changed: boolean;
182
+ created: string[];
183
+ updated: string[];
184
+ removed: string[];
185
+ skipped: string[];
186
+ };
187
+
188
+ type MilestoneDefinition = {
189
+ title: string;
190
+ description: string;
191
+ state: 'open' | 'closed';
192
+ };
193
+
194
+ type MilestoneInitialization = {
195
+ changed: boolean;
196
+ created: string[];
197
+ skipped: string[];
198
+ };
199
+
165
200
  type RepositoryMetadataSnapshot = {
166
201
  repository: { identity: ResourceIdentity; name: string; url: string | null };
167
202
  labels: Array<{ identity: ResourceIdentity; name: string }>;
@@ -286,6 +321,8 @@ type PlatformProvider = {
286
321
  head: string;
287
322
  }): Promise<ProviderResult<{ sha: string }>>;
288
323
  inspect(input: { context: ProviderOperationContext; target: ResourceIdentity }): Promise<ProviderResult<ChangeRequestSnapshot>>;
324
+ listFiles?(input: { context: ProviderOperationContext; target: ResourceIdentity }): Promise<ProviderResult<string[]>>;
325
+ listClosingIssues?(input: { context: ProviderOperationContext; target: ResourceIdentity }): Promise<ProviderResult<ResourceIdentity[]>>;
289
326
  listClosing(input: { context: ProviderOperationContext; issue: ResourceIdentity }): Promise<ProviderResult<ChangeRequestSnapshot[]>>;
290
327
  create(input: {
291
328
  context: ProviderOperationContext;
@@ -383,6 +420,34 @@ type PlatformProvider = {
383
420
  historyLimit: number;
384
421
  }): Promise<ProviderResult<ReleaseNotesFacts>>;
385
422
  };
423
+ securityAlerts?: {
424
+ inspect(input: {
425
+ context: ProviderOperationContext;
426
+ kind: SecurityAlertKind;
427
+ number: number;
428
+ }): Promise<ProviderResult<SecurityAlertSnapshot>>;
429
+ dismiss(input: {
430
+ context: ProviderOperationContext;
431
+ kind: SecurityAlertKind;
432
+ number: number;
433
+ reason: string;
434
+ comment: string;
435
+ mutation: MutationIdentity;
436
+ }): Promise<ProviderResult<MutationReceipt>>;
437
+ };
438
+ repositoryMetadata?: {
439
+ reconcileLabels(input: {
440
+ context: ProviderOperationContext;
441
+ desired: LabelDefinition[];
442
+ cleanupStaleIn: boolean;
443
+ mutation: MutationIdentity;
444
+ }): Promise<ProviderResult<LabelReconciliation>>;
445
+ reconcileMilestones(input: {
446
+ context: ProviderOperationContext;
447
+ desired: MilestoneDefinition[];
448
+ mutation: MutationIdentity;
449
+ }): Promise<ProviderResult<MilestoneInitialization>>;
450
+ };
386
451
  verification?: {
387
452
  fetchRemoteFacts(input: {
388
453
  context: ProviderOperationContext;
@@ -414,12 +479,14 @@ function validatePlatformProvider(
414
479
  providerType: string
415
480
  ): ProviderResult<PlatformProvider> {
416
481
  const operationGroups: Record<string, { required: string[]; optional: string[] }> = {
417
- issues: { required: ['inspect', 'create', 'update', 'describeRepository'], optional: [] },
482
+ issues: { required: ['inspect', 'create', 'update', 'describeRepository'], optional: ['listLabels', 'listMilestones'] },
418
483
  comments: { required: ['list', 'write', 'delete'], optional: [] },
419
- changeRequests: { required: ['inspect', 'listClosing', 'create', 'update', 'resolveGitEvidence'], optional: ['verifyHead'] },
484
+ changeRequests: { required: ['inspect', 'listClosing', 'create', 'update', 'resolveGitEvidence'], optional: ['verifyHead', 'listFiles', 'listClosingIssues'] },
420
485
  checks: { required: ['inspectRequired', 'resolveRun', 'fetchLogs'], optional: [] },
421
486
  reviews: { required: ['list', 'publish'], optional: [] },
422
487
  releases: { required: ['inspect', 'create', 'update', 'reconcileMilestones', 'publishNotes', 'collectNotes'], optional: [] },
488
+ securityAlerts: { required: ['inspect', 'dismiss'], optional: [] },
489
+ repositoryMetadata: { required: ['reconcileLabels', 'reconcileMilestones'], optional: [] },
423
490
  verification: { required: ['fetchRemoteFacts'], optional: [] }
424
491
  };
425
492
  const resourceKindsByGroup: Record<string, PlatformResourceKind[]> = {
@@ -429,6 +496,8 @@ function validatePlatformProvider(
429
496
  checks: ['pull-request'],
430
497
  reviews: ['pull-request'],
431
498
  releases: ['release', 'issue', 'pull-request'],
499
+ securityAlerts: [],
500
+ repositoryMetadata: [],
432
501
  verification: ['issue', 'pull-request']
433
502
  };
434
503
  if (!isRecord(value)
@@ -515,6 +584,10 @@ export type {
515
584
  IssueSnapshot,
516
585
  JsonValue,
517
586
  MilestoneReconciliation,
587
+ MilestoneDefinition,
588
+ MilestoneInitialization,
589
+ LabelDefinition,
590
+ LabelReconciliation,
518
591
  MutationIdentity,
519
592
  MutationReceipt,
520
593
  PlatformCapabilities,
@@ -531,6 +604,8 @@ export type {
531
604
  RepositoryMetadataSnapshot,
532
605
  ReleaseNotesFacts,
533
606
  ResourceIdentity,
607
+ SecurityAlertKind,
608
+ SecurityAlertSnapshot,
534
609
  ReviewSnapshot,
535
610
  VerificationRemoteFacts
536
611
  };
@@ -5,7 +5,11 @@ import type {
5
5
  CheckLogSnapshot,
6
6
  CheckRunSnapshot,
7
7
  GitEvidenceSnapshot,
8
+ LabelDefinition,
9
+ LabelReconciliation,
8
10
  IssueSnapshot,
11
+ MilestoneDefinition,
12
+ MilestoneInitialization,
9
13
  MilestoneReconciliation,
10
14
  MutationReceipt,
11
15
  PlatformContextSnapshot,
@@ -18,6 +22,8 @@ import type {
18
22
  RepositoryMetadataSnapshot,
19
23
  RequiredCheckSnapshot,
20
24
  ReviewSnapshot,
25
+ SecurityAlertKind,
26
+ SecurityAlertSnapshot,
21
27
  VerificationRemoteFacts
22
28
  } from './provider-contract.ts';
23
29
  import type { JsonValue } from './provider-contract.ts';
@@ -273,6 +279,67 @@ function validateReceipt(value: unknown): MutationReceipt {
273
279
  };
274
280
  }
275
281
 
282
+ function positiveInteger(value: unknown, label: string): number {
283
+ if (!Number.isSafeInteger(value) || (value as number) <= 0) throw new Error(`${label} must be a positive integer`);
284
+ return value as number;
285
+ }
286
+
287
+ function validateSecurityAlert(value: unknown): SecurityAlertSnapshot {
288
+ const item = record(value, 'security alert');
289
+ exactKeys(item, ['kind', 'number', 'state', 'data'], 'security alert');
290
+ if (item.kind !== 'dependabot' && item.kind !== 'code-scanning') throw new Error('security alert.kind is invalid');
291
+ return {
292
+ kind: item.kind as SecurityAlertKind,
293
+ number: positiveInteger(item.number, 'security alert.number'),
294
+ state: stringValue(item.state, 'security alert.state'),
295
+ data: jsonValue(item.data, 'security alert.data')
296
+ };
297
+ }
298
+
299
+ function validateLabelDefinition(value: unknown, label: string): LabelDefinition {
300
+ const item = record(value, label);
301
+ exactKeys(item, ['name', 'color', 'description'], label);
302
+ return {
303
+ name: stringValue(item.name, `${label}.name`),
304
+ color: stringValue(item.color, `${label}.color`),
305
+ description: stringValue(item.description, `${label}.description`, true)
306
+ };
307
+ }
308
+
309
+ function validateLabelReconciliation(value: unknown): LabelReconciliation {
310
+ const item = record(value, 'label reconciliation');
311
+ exactKeys(item, ['changed', 'created', 'updated', 'removed', 'skipped'], 'label reconciliation');
312
+ const names = (field: string) => arrayValue(item[field], `label reconciliation.${field}`).map((entry) => stringValue(entry, `${field}[]`));
313
+ return {
314
+ changed: booleanValue(item.changed, 'label reconciliation.changed'),
315
+ created: names('created'),
316
+ updated: names('updated'),
317
+ removed: names('removed'),
318
+ skipped: names('skipped')
319
+ };
320
+ }
321
+
322
+ function validateMilestoneDefinition(value: unknown, label: string): MilestoneDefinition {
323
+ const item = record(value, label);
324
+ exactKeys(item, ['title', 'description', 'state'], label);
325
+ if (item.state !== 'open' && item.state !== 'closed') throw new Error(`${label}.state is invalid`);
326
+ return {
327
+ title: stringValue(item.title, `${label}.title`),
328
+ description: stringValue(item.description, `${label}.description`, true),
329
+ state: item.state
330
+ };
331
+ }
332
+
333
+ function validateMilestoneInitialization(value: unknown): MilestoneInitialization {
334
+ const item = record(value, 'milestone initialization');
335
+ exactKeys(item, ['changed', 'created', 'skipped'], 'milestone initialization');
336
+ return {
337
+ changed: booleanValue(item.changed, 'milestone initialization.changed'),
338
+ created: arrayValue(item.created, 'milestone initialization.created').map((entry) => stringValue(entry, 'created[]')),
339
+ skipped: arrayValue(item.skipped, 'milestone initialization.skipped').map((entry) => stringValue(entry, 'skipped[]'))
340
+ };
341
+ }
342
+
276
343
  function validateMetadata(value: unknown): RepositoryMetadataSnapshot {
277
344
  const item = record(value, 'repository metadata');
278
345
  exactKeys(item, ['repository', 'labels', 'milestones', 'issueTypes', 'fields'], 'repository metadata');
@@ -375,6 +442,11 @@ const PROVIDER_ERROR_CATALOG: Readonly<Record<string, { message: string; retryab
375
442
  ISSUE_NUMBER_INVALID: { message: 'The issue number is invalid', retryable: false },
376
443
  ISSUE_CREATE_RESPONSE_INVALID: { message: 'Issue creation returned an invalid response', retryable: false },
377
444
  COMMENT_ID_INVALID: { message: 'The comment identity is invalid', retryable: false },
445
+ SECURITY_KIND_INVALID: { message: 'The security alert kind is invalid', retryable: false },
446
+ SECURITY_NUMBER_INVALID: { message: 'The security alert number is invalid', retryable: false },
447
+ SECURITY_RESPONSE_INVALID: { message: 'The platform returned an invalid security alert', retryable: false },
448
+ LABEL_RESPONSE_INVALID: { message: 'The platform returned an invalid label response', retryable: false },
449
+ MILESTONE_RESPONSE_INVALID: { message: 'The platform returned an invalid milestone response', retryable: false },
378
450
  MILESTONE_IDENTITY_INVALID: { message: 'The milestone identity is invalid', retryable: false },
379
451
  CHECK_RUN_NOT_FOUND: { message: 'The check run was not found', retryable: false },
380
452
  RELEASE_NOTES_AUTHORS_TRUNCATED: { message: 'Release note commit authors exceeded the supported limit', retryable: false },
@@ -415,6 +487,8 @@ function validators(providerType: string, declaration?: ProviderIdentityDeclarat
415
487
  return { sha: stringValue(item.sha, 'change request head.sha') };
416
488
  },
417
489
  'changeRequests.inspect': (value) => validateChangeRequest(value, declaredIdentityKind(declaration, 'pull-request'), true),
490
+ 'changeRequests.listFiles': (value) => arrayValue(value, 'pull request files').map((entry) => stringValue(entry, 'pull request files[]')),
491
+ 'changeRequests.listClosingIssues': (value) => arrayValue(value, 'closing issues').map((entry) => identity(entry, 'closing issues[]', declaredIdentityKind(declaration, 'issue'))),
418
492
  'changeRequests.listClosing': (value) => arrayValue(value, 'changeRequests').map((entry) => validateChangeRequest(entry, declaredIdentityKind(declaration, 'pull-request'), true)),
419
493
  'changeRequests.create': validateReceipt,
420
494
  'changeRequests.update': validateReceipt,
@@ -458,6 +532,10 @@ function validators(providerType: string, declaration?: ProviderIdentityDeclarat
458
532
  },
459
533
  'releases.publishNotes': validateReceipt,
460
534
  'releases.collectNotes': (value) => validateReleaseNotes(value, declaration),
535
+ 'securityAlerts.inspect': validateSecurityAlert,
536
+ 'securityAlerts.dismiss': validateReceipt,
537
+ 'repositoryMetadata.reconcileLabels': validateLabelReconciliation,
538
+ 'repositoryMetadata.reconcileMilestones': validateMilestoneInitialization,
461
539
  'verification.fetchRemoteFacts': (value) => {
462
540
  const item = record(value, 'verification facts');
463
541
  exactKeys(item, ['issue', 'comments', 'changeRequest', 'commit', 'fields'], 'verification facts');
@@ -491,11 +569,15 @@ async function invokeProviderOperation<T>(
491
569
  }
492
570
  if (envelope.ok === false && envelope.error && typeof envelope.error === 'object' && !Array.isArray(envelope.error)) {
493
571
  try {
494
- exactKeys(envelope, ['ok', 'error'], `${operation} result`);
572
+ exactKeys(envelope, Object.hasOwn(envelope, 'value') ? ['ok', 'error', 'value'] : ['ok', 'error'], `${operation} result`);
495
573
  const error = envelope.error as Record<string, unknown>;
496
574
  exactKeys(error, ['code', 'message', 'retryable'], `${operation} error`);
497
575
  if (typeof error.code !== 'string' || !error.code || typeof error.message !== 'string' || !error.message || typeof error.retryable !== 'boolean') throw new Error('invalid provider error');
498
- return { ok: false, error: safeProviderError(providerType, operation, error) };
576
+ return {
577
+ ok: false,
578
+ error: safeProviderError(providerType, operation, error),
579
+ ...(Object.hasOwn(envelope, 'value') ? { value: validate(envelope.value) } : {})
580
+ };
499
581
  } catch {
500
582
  return { ok: false, error: validationError(providerType, operation, 'Provider operation returned an invalid error') };
501
583
  }
@@ -510,7 +592,7 @@ function wrapProviderOperations(provider: PlatformProvider): PlatformProvider {
510
592
  const map = validators(provider.type, provider.identity);
511
593
  const wrapped: PlatformProvider = { ...provider, context: { ...provider.context } };
512
594
  wrapped.context.resolve = (input) => invokeProviderOperation(provider.type, 'context.resolve', () => provider.context.resolve(input), map['context.resolve']! as ResultValidator<PlatformContextSnapshot>);
513
- for (const groupName of ['issues', 'comments', 'changeRequests', 'checks', 'reviews', 'releases', 'verification'] as const) {
595
+ for (const groupName of ['issues', 'comments', 'changeRequests', 'checks', 'reviews', 'releases', 'securityAlerts', 'repositoryMetadata', 'verification'] as const) {
514
596
  const group = provider[groupName];
515
597
  if (!group) continue;
516
598
  const target: Record<string, unknown> = { ...group };