@fitlab-ai/agent-infra 0.9.11 → 0.9.13

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 (356) hide show
  1. package/README.md +13 -13
  2. package/README.zh-CN.md +13 -13
  3. package/dist/bin/internal-cli.js +29 -19
  4. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +71 -10
  5. package/dist/lib/agent-clients/next-steps.js +6 -1
  6. package/dist/lib/decide.js +3 -3
  7. package/dist/lib/defaults.json +4 -0
  8. package/dist/lib/git/workflow.js +43 -1
  9. package/dist/lib/init.js +1 -0
  10. package/dist/lib/internal/git-workflow.js +8 -1
  11. package/dist/lib/internal/platform-checks.js +3 -3
  12. package/dist/lib/internal/platform-comment.js +9 -9
  13. package/dist/lib/internal/platform-context.js +2 -2
  14. package/dist/lib/internal/platform-issue.js +8 -9
  15. package/dist/lib/internal/platform-pr-review.js +10 -10
  16. package/dist/lib/internal/platform-pr.js +68 -23
  17. package/dist/lib/internal/platform-release-notes.js +3 -3
  18. package/dist/lib/internal/pr-review-grade.js +11 -9
  19. package/dist/lib/internal/release-workflow.js +4 -4
  20. package/dist/lib/internal/sandbox-control.js +30 -4
  21. package/dist/lib/internal/task-activity.js +3 -3
  22. package/dist/lib/internal/task-artifact.js +76 -24
  23. package/dist/lib/internal/task-create.js +2 -2
  24. package/dist/lib/internal/task-delivery.js +59 -0
  25. package/dist/lib/internal/task-event.js +6 -3
  26. package/dist/lib/internal/task-finalization.js +2 -2
  27. package/dist/lib/internal/task-invalidation.js +60 -0
  28. package/dist/lib/internal/task-ledger.js +9 -6
  29. package/dist/lib/internal/task-lifecycle.js +2 -2
  30. package/dist/lib/internal/task-override.js +4 -4
  31. package/dist/lib/internal/task-review.js +3 -3
  32. package/dist/lib/internal/task-verify.js +6 -6
  33. package/dist/lib/internal/task-warning.js +3 -3
  34. package/dist/lib/platform/adapters.js +1 -3
  35. package/dist/lib/platform/change-request-git-evidence.js +27 -7
  36. package/dist/lib/platform/completion-backfill.js +6 -5
  37. package/dist/lib/platform/context.js +70 -130
  38. package/dist/lib/platform/github-client.js +8 -2
  39. package/dist/lib/platform/github-provider.js +903 -0
  40. package/dist/lib/platform/in-label-sync.js +143 -0
  41. package/dist/lib/platform/issue-comments.js +94 -41
  42. package/dist/lib/platform/issues.js +335 -189
  43. package/dist/lib/platform/metadata-labels.js +6 -2
  44. package/dist/lib/platform/none-provider.js +28 -0
  45. package/dist/lib/platform/pr-change-report.js +551 -0
  46. package/dist/lib/platform/pr-checks.js +124 -106
  47. package/dist/lib/platform/pr-review.js +88 -72
  48. package/dist/lib/platform/pr-summary.js +523 -49
  49. package/dist/lib/platform/provider-bridge.js +45 -0
  50. package/dist/lib/platform/provider-contract.d.ts +487 -0
  51. package/dist/lib/platform/provider-contract.js +95 -0
  52. package/dist/lib/platform/provider-loader.js +251 -0
  53. package/dist/lib/platform/provider-validation.js +504 -0
  54. package/dist/lib/platform/pull-request-metadata.js +8 -6
  55. package/dist/lib/platform/pull-requests.js +1050 -502
  56. package/dist/lib/platform/release-notes.js +78 -55
  57. package/dist/lib/platform/releases.js +79 -50
  58. package/dist/lib/platform/resource-identity.d.ts +26 -0
  59. package/dist/lib/platform/resource-identity.js +92 -0
  60. package/dist/lib/platform/task-identities.js +31 -0
  61. package/dist/lib/platform/verification-required.js +22 -12
  62. package/dist/lib/platform/verification-sync.js +118 -239
  63. package/dist/lib/pr-review/evidence-grading.js +30 -9
  64. package/dist/lib/run/index.js +63 -23
  65. package/dist/lib/sandbox/config.js +5 -0
  66. package/dist/lib/sandbox/control/client.js +96 -15
  67. package/dist/lib/sandbox/control/executor.js +3 -3
  68. package/dist/lib/sandbox/control/lifecycle.js +29 -7
  69. package/dist/lib/sandbox/control/protocol.js +77 -0
  70. package/dist/lib/sandbox/control/server.js +398 -25
  71. package/dist/lib/sandbox/control/state.js +204 -1
  72. package/dist/lib/server/process-state.js +2 -2
  73. package/dist/lib/server/protocol.js +38 -1
  74. package/dist/lib/task/activity-log.js +8 -1
  75. package/dist/lib/task/artifact-lifecycle.js +35 -7
  76. package/dist/lib/task/capabilities.js +239 -0
  77. package/dist/lib/task/commands/status.js +32 -0
  78. package/dist/lib/task/commit-intent.js +100 -0
  79. package/dist/lib/task/commit-operation.js +207 -102
  80. package/dist/lib/task/control-authority.js +8 -5
  81. package/dist/lib/task/create-service.js +8 -8
  82. package/dist/lib/task/create.js +33 -7
  83. package/dist/lib/task/current-contract.js +5 -1
  84. package/dist/lib/task/decision-details.js +3 -48
  85. package/dist/lib/task/delivery-target.js +97 -0
  86. package/dist/lib/task/delivery.js +153 -0
  87. package/dist/lib/task/events.js +297 -17
  88. package/dist/lib/task/finalization.js +37 -13
  89. package/dist/lib/task/human-override.js +61 -36
  90. package/dist/lib/task/invalidation-command.js +86 -0
  91. package/dist/lib/task/invalidation.js +260 -0
  92. package/dist/lib/task/ledger-intents.js +37 -0
  93. package/dist/lib/task/lifecycle.js +106 -9
  94. package/dist/lib/task/local-artifact-finalization.js +374 -0
  95. package/dist/lib/task/orchestration.js +100 -151
  96. package/dist/lib/task/pr-delivery-fact.js +183 -0
  97. package/dist/lib/task/review-finalization.js +4 -8
  98. package/dist/lib/task/review-fingerprint.js +32 -2
  99. package/dist/lib/task/rework-intent.js +138 -0
  100. package/dist/lib/task/skill-scope.js +23 -0
  101. package/dist/lib/task/task-execution-lock.js +27 -17
  102. package/dist/lib/task/verification-engine.js +89 -38
  103. package/dist/lib/task/verification-review.js +1 -1
  104. package/dist/lib/task/verification.js +3 -3
  105. package/dist/lib/task/workflow-warning-intents.js +1 -1
  106. package/dist/lib/task/write.js +11 -0
  107. package/dist/lib/update.js +9 -0
  108. package/dist/lib/version.js +11 -1
  109. package/dist/lifecycle-build-manifest.json +3 -3
  110. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +105 -10
  111. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +12 -1
  112. package/lib/agent-clients/next-steps.ts +6 -1
  113. package/lib/decide.ts +3 -3
  114. package/lib/defaults.json +4 -0
  115. package/lib/git/workflow.ts +38 -1
  116. package/lib/init.ts +4 -1
  117. package/lib/internal/git-workflow.ts +7 -1
  118. package/lib/internal/platform-checks.ts +3 -3
  119. package/lib/internal/platform-comment.ts +8 -8
  120. package/lib/internal/platform-context.ts +2 -2
  121. package/lib/internal/platform-issue.ts +7 -8
  122. package/lib/internal/platform-pr-review.ts +9 -9
  123. package/lib/internal/platform-pr.ts +53 -21
  124. package/lib/internal/platform-release-notes.ts +3 -3
  125. package/lib/internal/pr-review-grade.ts +10 -8
  126. package/lib/internal/release-workflow.ts +4 -4
  127. package/lib/internal/sandbox-control.ts +27 -3
  128. package/lib/internal/task-activity.ts +3 -3
  129. package/lib/internal/task-artifact.ts +65 -22
  130. package/lib/internal/task-create.ts +2 -2
  131. package/lib/internal/task-delivery.ts +53 -0
  132. package/lib/internal/task-event.ts +6 -3
  133. package/lib/internal/task-finalization.ts +3 -3
  134. package/lib/internal/task-invalidation.ts +39 -0
  135. package/lib/internal/task-ledger.ts +11 -8
  136. package/lib/internal/task-lifecycle.ts +2 -2
  137. package/lib/internal/task-override.ts +6 -6
  138. package/lib/internal/task-review.ts +3 -3
  139. package/lib/internal/task-verify.ts +6 -6
  140. package/lib/internal/task-warning.ts +3 -3
  141. package/lib/platform/adapters.ts +3 -2
  142. package/lib/platform/change-request-git-evidence.ts +36 -9
  143. package/lib/platform/completion-backfill.ts +9 -8
  144. package/lib/platform/context.ts +97 -134
  145. package/lib/platform/github-client.ts +10 -3
  146. package/lib/platform/github-provider.ts +910 -0
  147. package/lib/platform/in-label-sync.ts +208 -0
  148. package/lib/platform/issue-comments.ts +97 -47
  149. package/lib/platform/issues.ts +344 -174
  150. package/lib/platform/metadata-labels.ts +5 -2
  151. package/lib/platform/none-provider.ts +35 -0
  152. package/lib/platform/pr-change-report.ts +645 -0
  153. package/lib/platform/pr-checks.ts +129 -107
  154. package/lib/platform/pr-review.ts +88 -85
  155. package/lib/platform/pr-summary.ts +562 -52
  156. package/lib/platform/provider-bridge.ts +82 -0
  157. package/lib/platform/provider-contract.ts +536 -0
  158. package/lib/platform/provider-loader.ts +307 -0
  159. package/lib/platform/provider-validation.ts +529 -0
  160. package/lib/platform/pull-request-metadata.ts +10 -7
  161. package/lib/platform/pull-requests.ts +1126 -505
  162. package/lib/platform/release-notes.ts +76 -59
  163. package/lib/platform/releases.ts +77 -43
  164. package/lib/platform/resource-identity.ts +121 -0
  165. package/lib/platform/task-identities.ts +40 -0
  166. package/lib/platform/types.ts +4 -2
  167. package/lib/platform/verification-required.ts +21 -13
  168. package/lib/platform/verification-sync.ts +118 -293
  169. package/lib/pr-review/evidence-grading.ts +31 -11
  170. package/lib/run/index.ts +57 -22
  171. package/lib/sandbox/config.ts +7 -0
  172. package/lib/sandbox/control/client.ts +105 -15
  173. package/lib/sandbox/control/executor.ts +4 -4
  174. package/lib/sandbox/control/lifecycle.ts +30 -8
  175. package/lib/sandbox/control/protocol.ts +113 -0
  176. package/lib/sandbox/control/server.ts +431 -23
  177. package/lib/sandbox/control/state.ts +251 -1
  178. package/lib/server/process-state.ts +2 -2
  179. package/lib/server/protocol.ts +36 -1
  180. package/lib/task/activity-log.ts +8 -0
  181. package/lib/task/artifact-lifecycle.ts +34 -8
  182. package/lib/task/capabilities.ts +262 -0
  183. package/lib/task/commands/status.ts +38 -0
  184. package/lib/task/commit-intent.ts +137 -0
  185. package/lib/task/commit-operation.ts +186 -88
  186. package/lib/task/control-authority.ts +11 -8
  187. package/lib/task/create-service.ts +8 -8
  188. package/lib/task/create.ts +34 -9
  189. package/lib/task/current-contract.ts +6 -1
  190. package/lib/task/decision-details.ts +8 -64
  191. package/lib/task/delivery-target.ts +130 -0
  192. package/lib/task/delivery.ts +160 -0
  193. package/lib/task/events.ts +296 -16
  194. package/lib/task/finalization.ts +50 -14
  195. package/lib/task/human-override.ts +73 -46
  196. package/lib/task/invalidation-command.ts +86 -0
  197. package/lib/task/invalidation.ts +332 -0
  198. package/lib/task/ledger-intents.ts +35 -1
  199. package/lib/task/lifecycle.ts +93 -4
  200. package/lib/task/local-artifact-finalization.ts +563 -0
  201. package/lib/task/orchestration.ts +110 -146
  202. package/lib/task/pr-delivery-fact.ts +237 -0
  203. package/lib/task/review-finalization.ts +4 -14
  204. package/lib/task/review-fingerprint.ts +33 -2
  205. package/lib/task/rework-intent.ts +165 -0
  206. package/lib/task/skill-scope.ts +24 -0
  207. package/lib/task/task-execution-lock.ts +23 -14
  208. package/lib/task/verification-engine.ts +95 -43
  209. package/lib/task/verification-review.ts +2 -0
  210. package/lib/task/verification.ts +4 -4
  211. package/lib/task/workflow-warning-intents.ts +1 -1
  212. package/lib/task/write.ts +19 -0
  213. package/lib/update.ts +11 -1
  214. package/lib/version.ts +15 -1
  215. package/package.json +7 -1
  216. package/templates/.agents/rules/README.en.md +4 -2
  217. package/templates/.agents/rules/README.zh-CN.md +4 -2
  218. package/templates/.agents/rules/create-issue.en.md +11 -2
  219. package/templates/.agents/rules/create-issue.zh-CN.md +24 -2
  220. package/templates/.agents/rules/issue-pr-commands.en.md +4 -17
  221. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
  222. package/templates/.agents/rules/issue-sync.en.md +28 -5
  223. package/templates/.agents/rules/issue-sync.zh-CN.md +64 -5
  224. package/templates/.agents/rules/label-milestone-setup.en.md +15 -2
  225. package/templates/.agents/rules/label-milestone-setup.zh-CN.md +15 -2
  226. package/templates/.agents/rules/local-artifact-repair.en.md +53 -0
  227. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +53 -0
  228. package/templates/.agents/rules/milestone-inference.en.md +12 -2
  229. package/templates/.agents/rules/milestone-inference.zh-CN.md +25 -3
  230. package/templates/.agents/rules/pr-sync.en.md +28 -13
  231. package/templates/.agents/rules/pr-sync.zh-CN.md +39 -5
  232. package/templates/.agents/rules/release-commands.en.md +42 -3
  233. package/templates/.agents/rules/release-commands.zh-CN.md +42 -3
  234. package/templates/.agents/rules/security-alerts.en.md +17 -2
  235. package/templates/.agents/rules/security-alerts.zh-CN.md +17 -2
  236. package/templates/.agents/rules/sync-content-generation.en.md +8 -0
  237. package/templates/.agents/rules/sync-content-generation.zh-CN.md +8 -0
  238. package/templates/.agents/rules/task-management.en.md +1 -1
  239. package/templates/.agents/rules/task-management.zh-CN.md +1 -1
  240. package/templates/.agents/rules/task-short-id.en.md +1 -4
  241. package/templates/.agents/rules/task-short-id.zh-CN.md +1 -3
  242. package/templates/.agents/scripts/security-alerts.github.sh +151 -0
  243. package/templates/.agents/scripts/security-alerts.sh +31 -0
  244. package/templates/.agents/skills/analyze-task/SKILL.en.md +14 -3
  245. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +11 -3
  246. package/templates/.agents/skills/check-task/SKILL.en.md +16 -37
  247. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -37
  248. package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
  249. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
  250. package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
  251. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
  252. package/templates/.agents/skills/code-task/SKILL.en.md +32 -10
  253. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +35 -13
  254. package/templates/.agents/skills/code-task/config/verify.en.json +1 -0
  255. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -0
  256. package/templates/.agents/skills/commit/SKILL.en.md +3 -3
  257. package/templates/.agents/skills/commit/SKILL.zh-CN.md +3 -3
  258. package/templates/.agents/skills/commit/config/verify.json +1 -1
  259. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +3 -3
  260. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +3 -3
  261. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +2 -0
  262. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +2 -0
  263. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +4 -4
  264. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +4 -4
  265. package/templates/.agents/skills/commit/reference/task-status-update.en.md +2 -2
  266. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +2 -2
  267. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +7 -4
  268. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +7 -4
  269. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
  270. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
  271. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +5 -4
  272. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +5 -4
  273. package/templates/.agents/skills/complete-task/SKILL.en.md +31 -13
  274. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +30 -13
  275. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +2 -2
  276. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +2 -2
  277. package/templates/.agents/skills/create-pr/SKILL.en.md +11 -10
  278. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +11 -11
  279. package/templates/.agents/skills/create-pr/config/verify.json +1 -0
  280. package/templates/.agents/skills/create-pr/reference/change-report.en.md +16 -4
  281. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +16 -4
  282. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +5 -3
  283. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +5 -3
  284. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +1 -1
  285. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +1 -1
  286. package/templates/.agents/skills/create-pr/scripts/change-report.mjs +3 -0
  287. package/templates/.agents/skills/create-task/SKILL.en.md +1 -0
  288. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +1 -0
  289. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  290. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  291. package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
  292. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
  293. package/templates/.agents/skills/init-labels/SKILL.en.md +9 -10
  294. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +9 -10
  295. package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +57 -1
  296. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +27 -1
  297. package/templates/.agents/skills/init-milestones/SKILL.en.md +3 -5
  298. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +3 -5
  299. package/templates/.agents/skills/plan-task/SKILL.en.md +14 -3
  300. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +11 -3
  301. package/templates/.agents/skills/review-analysis/SKILL.en.md +6 -5
  302. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +6 -5
  303. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +18 -0
  304. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +18 -0
  305. package/templates/.agents/skills/review-code/SKILL.en.md +10 -9
  306. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +10 -9
  307. package/templates/.agents/skills/review-code/reference/output-templates.en.md +19 -1
  308. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +19 -1
  309. package/templates/.agents/skills/review-code/reference/report-template.en.md +4 -2
  310. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +4 -2
  311. package/templates/.agents/skills/review-plan/SKILL.en.md +6 -5
  312. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +6 -5
  313. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +18 -0
  314. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +18 -0
  315. package/templates/.agents/skills/review-pr/SKILL.en.md +1 -0
  316. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +1 -0
  317. package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +2 -2
  318. package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +2 -2
  319. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +5 -2
  320. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +5 -2
  321. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  322. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  323. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +4 -0
  324. package/templates/.agents/skills/watch-pr/SKILL.en.md +6 -6
  325. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +6 -6
  326. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +6 -0
  327. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +6 -0
  328. package/templates/.agents/templates/task.en.md +23 -2
  329. package/templates/.agents/templates/task.zh-CN.md +23 -2
  330. package/templates/.agents/workflows/bug-fix.en.yaml +9 -8
  331. package/templates/.agents/workflows/bug-fix.zh-CN.yaml +9 -8
  332. package/templates/.agents/workflows/feature-development.en.yaml +9 -8
  333. package/templates/.agents/workflows/feature-development.zh-CN.yaml +9 -8
  334. package/templates/.agents/workflows/refactoring.en.yaml +9 -8
  335. package/templates/.agents/workflows/refactoring.zh-CN.yaml +9 -8
  336. package/templates/.github/workflows/pr-label.yml +7 -26
  337. package/templates/.agents/rules/create-issue.github.en.md +0 -14
  338. package/templates/.agents/rules/create-issue.github.zh-CN.md +0 -27
  339. package/templates/.agents/rules/issue-pr-commands.github.en.md +0 -34
  340. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +0 -49
  341. package/templates/.agents/rules/issue-sync.github.en.md +0 -40
  342. package/templates/.agents/rules/issue-sync.github.zh-CN.md +0 -76
  343. package/templates/.agents/rules/label-milestone-setup.github.en.md +0 -60
  344. package/templates/.agents/rules/label-milestone-setup.github.zh-CN.md +0 -60
  345. package/templates/.agents/rules/milestone-inference.github.en.md +0 -15
  346. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +0 -27
  347. package/templates/.agents/rules/pr-checks-commands.github.en.md +0 -18
  348. package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +0 -34
  349. package/templates/.agents/rules/pr-sync.github.en.md +0 -43
  350. package/templates/.agents/rules/pr-sync.github.zh-CN.md +0 -69
  351. package/templates/.agents/rules/release-commands.github.en.md +0 -44
  352. package/templates/.agents/rules/release-commands.github.zh-CN.md +0 -44
  353. package/templates/.agents/rules/security-alerts.github.en.md +0 -43
  354. package/templates/.agents/rules/security-alerts.github.zh-CN.md +0 -43
  355. /package/templates/.agents/rules/{issue-fields.github.en.md → issue-fields.en.md} +0 -0
  356. /package/templates/.agents/rules/{issue-fields.github.zh-CN.md → issue-fields.zh-CN.md} +0 -0
@@ -11,6 +11,9 @@ import { getOpenWorkflowWarnings, formatWorkflowWarningSummary } from '../workfl
11
11
  import { parseActivityLog, pairEntries, startedBackedRows } from '../activity-log.js';
12
12
  import { readRun } from '../orchestration.js';
13
13
  import { statusCard } from '../../server/display.js';
14
+ import { invalidationBlocks, parseInvalidationDocument } from '../invalidation.js';
15
+ import { parseReworkIntentDocument } from '../rework-intent.js';
16
+ import { buildLifecycleFacts, recommendNext } from '../capabilities.js';
14
17
  const USAGE = `Usage: ai task status [--task <ref> | -t <ref>]
15
18
 
16
19
  Prints an aggregated "health check" view for a task: header, metadata,
@@ -317,6 +320,12 @@ function renderStatus(model) {
317
320
  else {
318
321
  lines.push(...renderPairs(model.artifacts.groups.map((group) => [group.stage, group.files.join(', ')])));
319
322
  }
323
+ lines.push('', 'Invalidation', ...renderPairs([
324
+ ['status', model.invalidation?.status ?? 'unknown'],
325
+ ['processed', `${model.invalidation?.processed ?? 0}/${model.invalidation?.total ?? 0}`],
326
+ ['pending_intents', String(model.invalidation?.pendingIntents ?? 0)]
327
+ ]));
328
+ lines.push('', 'Recommendation', ...renderPairs([['action', model.recommendation ?? DASH]]));
320
329
  lines.push('', 'Orchestration', ...renderPairs([
321
330
  ['status', model.orchestration.status],
322
331
  ['run_id', model.orchestration.runId],
@@ -361,6 +370,10 @@ function renderStatus(model) {
361
370
  return lines;
362
371
  }
363
372
  function modelTone(model) {
373
+ if (model.invalidation?.status === 'invalid')
374
+ return 'danger';
375
+ if (model.invalidation?.status === 'pending' || model.invalidation?.status === 'in-progress')
376
+ return 'warning';
364
377
  if (model.orchestration.status === 'paused')
365
378
  return 'warning';
366
379
  if (model.orchestration.status === 'running')
@@ -382,6 +395,23 @@ function buildFromResolved(input) {
382
395
  const run = input.run ?? makeRunner(input.repoRoot);
383
396
  const artifacts = enumerateArtifacts(input.taskDir);
384
397
  const workflow = collectWorkflow(content, input.now);
398
+ const invalidation = parseInvalidationDocument(content);
399
+ const rework = parseReworkIntentDocument(content);
400
+ const pendingIntents = rework.ok ? rework.intents.filter((intent) => intent.status === 'pending').length : 0;
401
+ const invalidationInfo = !invalidation.ok
402
+ ? { status: 'invalid', processed: 0, total: 0, pendingIntents }
403
+ : {
404
+ status: invalidation.present
405
+ ? invalidationBlocks(invalidation.document)
406
+ ? invalidation.document.operations.some((operation) => operation.status === 'in-progress') ? 'in-progress' : 'pending'
407
+ : 'completed'
408
+ : 'none',
409
+ processed: invalidation.document.operations.reduce((sum, operation) => sum + operation.processed, 0),
410
+ total: invalidation.document.operations.reduce((sum, operation) => sum + operation.total, 0),
411
+ pendingIntents
412
+ };
413
+ const facts = buildLifecycleFacts(input.taskDir, content, fm.status ?? 'active');
414
+ const recommendation = facts.ok ? (recommendNext(facts.facts).action ?? DASH) : DASH;
385
415
  return {
386
416
  taskId: input.taskId,
387
417
  shortId: input.shortId ?? loadShortIdByTaskId(input.repoRoot).get(input.taskId) ?? DASH,
@@ -392,6 +422,8 @@ function buildFromResolved(input) {
392
422
  workflow,
393
423
  runtime: collectRuntime(input.taskDir, workflow, run),
394
424
  orchestration: collectOrchestration(input.taskDir),
425
+ invalidation: invalidationInfo,
426
+ recommendation,
395
427
  git: collectGit(fm.branch ?? '', run)
396
428
  };
397
429
  }
@@ -0,0 +1,100 @@
1
+ import { createHash } from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ function intentRoot(repoRoot) {
5
+ return path.join(repoRoot, '.agents', 'workspace', '.task-commit-intents');
6
+ }
7
+ function intentPath(repoRoot, taskId) {
8
+ return path.join(intentRoot(repoRoot), `${taskId}.json`);
9
+ }
10
+ function checkpointIntentDigest(identity) {
11
+ return createHash('sha256').update(JSON.stringify({
12
+ taskId: identity.taskId,
13
+ branch: identity.branch,
14
+ mode: identity.mode,
15
+ expectedHead: identity.expectedHead,
16
+ expectedTree: identity.expectedTree,
17
+ paths: [...identity.paths],
18
+ message: identity.message,
19
+ round: identity.round
20
+ })).digest('hex');
21
+ }
22
+ function isIntent(value) {
23
+ if (!value || typeof value !== 'object' || Array.isArray(value))
24
+ return false;
25
+ const intent = value;
26
+ return intent.version === 1
27
+ && typeof intent.taskId === 'string' && intent.taskId.length > 0
28
+ && typeof intent.branch === 'string' && intent.branch.length > 0
29
+ && intent.mode === 'local'
30
+ && typeof intent.expectedHead === 'string' && /^[a-f0-9]{40,64}$/.test(intent.expectedHead)
31
+ && typeof intent.expectedTree === 'string' && /^[a-f0-9]{40,64}$/.test(intent.expectedTree)
32
+ && Array.isArray(intent.paths) && intent.paths.every((item) => typeof item === 'string' && item.length > 0)
33
+ && typeof intent.message === 'string' && intent.message.length > 0
34
+ && Number.isSafeInteger(intent.round) && Number(intent.round) > 0
35
+ && typeof intent.digest === 'string' && /^[a-f0-9]{64}$/.test(intent.digest)
36
+ && ['prepared', 'committed', 'synced'].includes(String(intent.state))
37
+ && (intent.committedHead === null || (typeof intent.committedHead === 'string' && /^[a-f0-9]{40,64}$/.test(intent.committedHead)))
38
+ && typeof intent.createdAt === 'string' && intent.createdAt.length > 0
39
+ && typeof intent.updatedAt === 'string' && intent.updatedAt.length > 0
40
+ && intent.digest === checkpointIntentDigest(intent);
41
+ }
42
+ function readCheckpointIntent(repoRoot, taskId) {
43
+ const target = intentPath(repoRoot, taskId);
44
+ if (!fs.existsSync(target))
45
+ return null;
46
+ const value = JSON.parse(fs.readFileSync(target, 'utf8'));
47
+ if (!isIntent(value))
48
+ throw new Error('COMMIT_INTENT_INVALID: checkpoint intent schema is invalid');
49
+ return value;
50
+ }
51
+ function writeCheckpointIntent(repoRoot, value) {
52
+ if (!isIntent(value))
53
+ throw new Error('COMMIT_INTENT_INVALID: checkpoint intent schema is invalid');
54
+ const directory = intentRoot(repoRoot);
55
+ fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
56
+ const target = intentPath(repoRoot, value.taskId);
57
+ const temporary = `${target}.${process.pid}.${Date.now()}.tmp`;
58
+ fs.writeFileSync(temporary, `${JSON.stringify(value)}\n`, { encoding: 'utf8', mode: 0o600, flag: 'wx' });
59
+ try {
60
+ fs.renameSync(temporary, target);
61
+ }
62
+ catch (error) {
63
+ try {
64
+ fs.unlinkSync(temporary);
65
+ }
66
+ catch { /* preserve primary error */ }
67
+ throw error;
68
+ }
69
+ }
70
+ function updateCheckpointIntent(value, patch) {
71
+ const next = { ...value, ...patch };
72
+ if (next.state === 'prepared' && next.committedHead !== null)
73
+ throw new Error('COMMIT_INTENT_INVALID: prepared intent cannot have a committed head');
74
+ if (next.state !== 'prepared' && !next.committedHead)
75
+ throw new Error('COMMIT_INTENT_INVALID: committed intent requires a committed head');
76
+ return next;
77
+ }
78
+ function removeCheckpointIntent(repoRoot, taskId) {
79
+ const target = intentPath(repoRoot, taskId);
80
+ try {
81
+ fs.unlinkSync(target);
82
+ }
83
+ catch (error) {
84
+ if (error.code !== 'ENOENT')
85
+ throw error;
86
+ }
87
+ }
88
+ function sameCheckpointIntent(left, right) {
89
+ return left.digest === checkpointIntentDigest(right)
90
+ && left.taskId === right.taskId
91
+ && left.branch === right.branch
92
+ && left.mode === right.mode
93
+ && left.expectedHead === right.expectedHead
94
+ && left.expectedTree === right.expectedTree
95
+ && left.message === right.message
96
+ && left.round === right.round
97
+ && JSON.stringify(left.paths) === JSON.stringify(right.paths);
98
+ }
99
+ export { checkpointIntentDigest, intentPath, intentRoot, isIntent, readCheckpointIntent, removeCheckpointIntent, sameCheckpointIntent, updateCheckpointIntent, writeCheckpointIntent };
100
+ //# sourceMappingURL=commit-intent.js.map
@@ -8,7 +8,7 @@ import { mergeOperationWarnings } from './operation-outcome.js';
8
8
  import { TaskExecutionLockError, withRepositoryMutationLock, withTaskExecutionLock } from './task-execution-lock.js';
9
9
  import { appendActivityEntry, locateActivityLog } from './activity-log.js';
10
10
  import { captureTaskWriteMetadata, writeTask } from './write.js';
11
- import { commitOrchestrationStageCompletion, planOrchestrationStageCompletion } from './orchestration.js';
11
+ import { checkpointIntentDigest, readCheckpointIntent, removeCheckpointIntent, sameCheckpointIntent, updateCheckpointIntent, writeCheckpointIntent } from './commit-intent.js';
12
12
  const HEAD_REF = /^refs\/heads\/(.+)$/;
13
13
  function isCommitExecutionMode(value) {
14
14
  return value === 'direct' || value === 'orchestrated';
@@ -20,6 +20,13 @@ function gitText(repoRoot, args) {
20
20
  stdio: ['ignore', 'pipe', 'pipe']
21
21
  }).trim();
22
22
  }
23
+ function effectiveDelivery(input) {
24
+ if (input.delivery)
25
+ return input.delivery;
26
+ if (input.push)
27
+ return { mode: 'push', remote: input.push.remote, refs: input.push.refs };
28
+ return null;
29
+ }
23
30
  function canonicalRepositoryRoot(cwd) {
24
31
  return gitText(cwd, ['rev-parse', '--show-toplevel']);
25
32
  }
@@ -86,8 +93,9 @@ function validateCommon(input, branch) {
86
93
  return { code: 'GIT_HEAD_EXPECTATION_REQUIRED', message: 'A valid expected HEAD is required' };
87
94
  if (!/^[a-f0-9]{40,64}$/.test(input.expectedTree))
88
95
  return { code: 'GIT_TREE_EXPECTATION_REQUIRED', message: 'A valid expected tree is required' };
89
- if (!input.push)
90
- return { code: 'GIT_PUSH_INPUT_INVALID', message: 'Commit delivery requires a push policy' };
96
+ const delivery = effectiveDelivery(input);
97
+ if (!delivery)
98
+ return { code: 'GIT_PUSH_INPUT_INVALID', message: 'Commit delivery requires a delivery policy' };
91
99
  if (input.paths.some((candidate) => !candidate || candidate.startsWith('/') || candidate.split(/[\\/]/).includes('..'))) {
92
100
  return { code: 'GIT_COMMIT_INPUT_INVALID', message: 'Commit paths must stay inside the repository' };
93
101
  }
@@ -96,38 +104,16 @@ function validateCommon(input, branch) {
96
104
  }
97
105
  if (branch !== null && branch === '')
98
106
  return { code: 'GIT_BRANCH_INVALID', message: 'A named branch is required' };
99
- if (!input.push.remote || input.push.refs.length !== 1)
100
- return { code: 'GIT_PUSH_INPUT_INVALID', message: 'Push requires one remote and one ref' };
101
- const ref = input.push.refs[0] ?? '';
102
- if (!HEAD_REF.test(ref) || HEAD_REF.exec(ref)?.[1] !== branch) {
103
- return { code: 'GIT_PUSH_INPUT_INVALID', message: 'Push ref must be the current full heads ref' };
107
+ if (delivery.mode === 'push') {
108
+ if (!delivery.remote || delivery.refs.length !== 1)
109
+ return { code: 'GIT_PUSH_INPUT_INVALID', message: 'Push requires one remote and one ref' };
110
+ const ref = delivery.refs[0] ?? '';
111
+ if (!HEAD_REF.test(ref) || HEAD_REF.exec(ref)?.[1] !== branch) {
112
+ return { code: 'GIT_PUSH_INPUT_INVALID', message: 'Push ref must be the current full heads ref' };
113
+ }
104
114
  }
105
115
  return null;
106
116
  }
107
- function validateOrchestrated(input, task) {
108
- if (!input.agent)
109
- return { error: { code: 'ORCHESTRATION_PROVENANCE_MISMATCH', message: 'orchestrated commit requires an agent' } };
110
- const planned = planOrchestrationStageCompletion(task.taskId, {
111
- stage: 'commit',
112
- round: 1,
113
- artifact: 'commit',
114
- role: 'executor',
115
- agent: input.agent
116
- }, { repoRoot: task.repoRoot });
117
- const run = planned.result.run;
118
- if (!planned.plan
119
- || !run
120
- || run.status !== 'running'
121
- || !run.commitAuthorization.issuedAt
122
- || run.commitAuthorization.consumedAt)
123
- return {
124
- error: {
125
- code: planned.result.error?.code ?? 'ORCHESTRATION_PROVENANCE_MISMATCH',
126
- message: planned.result.error?.message ?? 'orchestrated commit requires one matching activated commit delegation'
127
- }
128
- };
129
- return { plan: planned.plan };
130
- }
131
117
  function syncTaskCommit(input, task, committedHead) {
132
118
  let content;
133
119
  try {
@@ -137,7 +123,18 @@ function syncTaskCommit(input, task, committedHead) {
137
123
  return warning('TASK_STATUS_SYNC_FAILED', 'task has no unique Activity Log section', true, 'task', task.taskId, 'ACTION_REQUIRED');
138
124
  const metadata = captureTaskWriteMetadata();
139
125
  const commitNote = gitText(task.repoRoot, ['show', '-s', '--format=%h %s', committedHead]);
140
- const alreadyLogged = activity.entries.some((entry) => entry.step === 'Commit' && entry.note === commitNote);
126
+ let matchingCommitIndex = -1;
127
+ for (let index = activity.entries.length - 1; index >= 0; index -= 1) {
128
+ const entry = activity.entries[index];
129
+ if (entry.step === 'Commit' && entry.note === commitNote) {
130
+ matchingCommitIndex = index;
131
+ break;
132
+ }
133
+ }
134
+ const reviewedAfterCommit = matchingCommitIndex >= 0 && activity.entries
135
+ .slice(matchingCommitIndex + 1)
136
+ .some((entry) => /^Review Code \(Round \d+\)$/.test(entry.step));
137
+ const alreadyLogged = matchingCommitIndex >= 0 && !reviewedAfterCommit;
141
138
  const mutations = [];
142
139
  if (!alreadyLogged)
143
140
  mutations.push({
@@ -146,7 +143,10 @@ function syncTaskCommit(input, task, committedHead) {
146
143
  heading: activity.heading,
147
144
  body: appendActivityEntry(activity, { time: metadata.timestamp, step: 'Commit', agent: input.agent, note: commitNote })
148
145
  });
149
- const frontmatter = { assigned_to: input.agent };
146
+ const frontmatter = {
147
+ assigned_to: input.agent,
148
+ checkpoint_commit: committedHead
149
+ };
150
150
  mutations.push({ kind: 'frontmatter', set: frontmatter });
151
151
  if (mutations.length === 0)
152
152
  return null;
@@ -163,10 +163,44 @@ function syncTaskCommit(input, task, committedHead) {
163
163
  return warning('TASK_STATUS_SYNC_FAILED', error instanceof Error ? error.message : String(error), true, 'task', task.taskId, 'ACTION_REQUIRED');
164
164
  }
165
165
  }
166
+ function checkpointChildMatches(task, intent, head) {
167
+ try {
168
+ const parent = gitText(task.repoRoot, ['rev-parse', `${head}^`]);
169
+ const tree = gitText(task.repoRoot, ['rev-parse', `${head}^{tree}`]);
170
+ const message = gitText(task.repoRoot, ['show', '-s', '--format=%s', head]);
171
+ const changed = gitText(task.repoRoot, ['diff-tree', '--no-commit-id', '--name-only', '-r', head]).split('\n').filter(Boolean).sort();
172
+ return parent === intent.expectedHead
173
+ && tree === intent.expectedTree
174
+ && message === intent.message
175
+ && JSON.stringify(changed) === JSON.stringify([...intent.paths].sort());
176
+ }
177
+ catch {
178
+ return false;
179
+ }
180
+ }
181
+ function checkpointIdentity(input, task, delivery) {
182
+ if (delivery.mode !== 'local')
183
+ throw new Error('checkpoint identity requires local delivery');
184
+ return {
185
+ taskId: task.taskId,
186
+ branch: task.branch,
187
+ mode: 'local',
188
+ expectedHead: input.expectedHead,
189
+ expectedTree: input.expectedTree,
190
+ paths: [...input.paths],
191
+ message: input.message,
192
+ round: input.round ?? 1
193
+ };
194
+ }
195
+ function checkpointTimestamp() {
196
+ return new Date().toISOString();
197
+ }
166
198
  function executeUnlocked(input, task, mode) {
167
199
  const inspected = inspectGitWorkflow(input.cwd);
168
200
  if (!inspected.snapshot)
169
201
  return failure(input, mode, task?.taskId ?? null, 'GIT_INSPECT_FAILED', 'Unable to inspect Git repository');
202
+ if (mode === 'orchestrated')
203
+ return failure(input, mode, task?.taskId ?? null, 'ORCHESTRATED_COMMIT_REMOVED', 'Orchestrated commit is no longer a lifecycle stage; use local checkpoint delivery from code-task', 'blocked', inspected.snapshot);
170
204
  const branch = inspected.snapshot.branch;
171
205
  const commonError = validateCommon(input, branch);
172
206
  if (commonError)
@@ -177,60 +211,131 @@ function executeUnlocked(input, task, mode) {
177
211
  return failure(input, mode, task.taskId, 'GIT_BRANCH_MISMATCH', `Task branch '${task.branch}' does not match current branch '${branch}'`, 'blocked', inspected.snapshot);
178
212
  if (task && !input.agent)
179
213
  return failure(input, mode, task.taskId, 'COMMIT_AGENT_REQUIRED', 'task-bound commit requires an agent', 'blocked', inspected.snapshot);
180
- const orchestrationValidation = mode === 'orchestrated'
181
- ? (task
182
- ? validateOrchestrated(input, task)
183
- : { error: { code: 'ORCHESTRATION_TASK_REQUIRED', message: 'orchestrated commit requires a task context' } })
184
- : null;
185
- if (orchestrationValidation && 'error' in orchestrationValidation) {
186
- const error = orchestrationValidation.error;
187
- return failure(input, mode, task?.taskId ?? null, error.code, error.message, 'blocked', inspected.snapshot);
188
- }
189
- const orchestrationCompletion = orchestrationValidation && 'plan' in orchestrationValidation
190
- ? orchestrationValidation.plan
191
- : null;
192
- const committed = input.paths.length === 0
214
+ const delivery = effectiveDelivery(input);
215
+ if (delivery.mode === 'local' && !task)
216
+ return failure(input, mode, null, 'CHECKPOINT_TASK_REQUIRED', 'local checkpoint delivery requires a task context', 'blocked', inspected.snapshot);
217
+ let pendingIntent = null;
218
+ let checkpointCommittedHead = null;
219
+ const committed = delivery.mode === 'local'
193
220
  ? (() => {
194
- if (inspected.snapshot.worktree.length > 0 || inspected.snapshot.staged.length > 0)
221
+ const identity = checkpointIdentity(input, task, delivery);
222
+ try {
223
+ pendingIntent = readCheckpointIntent(task.repoRoot, task.taskId);
224
+ }
225
+ catch (error) {
195
226
  return {
196
- status: 'failed',
197
- changed: false,
198
- snapshot: inspected.snapshot,
199
- operations: [],
200
- error: { code: 'GIT_COMMIT_INPUT_INVALID', message: 'Push-only retry requires a clean working tree' }
227
+ status: 'failed', changed: false, snapshot: inspected.snapshot, operations: [],
228
+ error: { code: 'COMMIT_INTENT_INVALID', message: error instanceof Error ? error.message : String(error) }
201
229
  };
202
- if (inspected.snapshot.head !== input.expectedHead)
230
+ }
231
+ if (pendingIntent && !sameCheckpointIntent(pendingIntent, identity))
203
232
  return {
204
- status: 'failed',
205
- changed: false,
206
- snapshot: inspected.snapshot,
207
- operations: [],
208
- error: { code: 'GIT_HEAD_MISMATCH', message: `Expected HEAD ${input.expectedHead}, received ${inspected.snapshot.head}` }
233
+ status: 'failed', changed: false, snapshot: inspected.snapshot, operations: [],
234
+ error: { code: 'COMMIT_INTENT_CONFLICT', message: 'A different checkpoint intent is still pending for this task' }
235
+ };
236
+ if (!pendingIntent) {
237
+ const timestamp = checkpointTimestamp();
238
+ pendingIntent = {
239
+ version: 1, ...identity, digest: checkpointIntentDigest(identity), state: 'prepared',
240
+ committedHead: null, createdAt: timestamp, updatedAt: timestamp
241
+ };
242
+ try {
243
+ writeCheckpointIntent(task.repoRoot, pendingIntent);
244
+ }
245
+ catch (error) {
246
+ return {
247
+ status: 'failed', changed: false, snapshot: inspected.snapshot, operations: [],
248
+ error: { code: 'COMMIT_INTENT_WRITE_FAILED', message: error instanceof Error ? error.message : String(error) }
249
+ };
250
+ }
251
+ }
252
+ if (pendingIntent.state !== 'prepared') {
253
+ checkpointCommittedHead = pendingIntent.committedHead;
254
+ return {
255
+ status: 'no-op', changed: false, snapshot: inspected.snapshot,
256
+ operations: [{ name: 'commit', status: 'no-op' }], error: null
257
+ };
258
+ }
259
+ if (inspected.snapshot.head !== identity.expectedHead && !checkpointChildMatches(task, pendingIntent, inspected.snapshot.head))
260
+ return {
261
+ status: 'failed', changed: false, snapshot: inspected.snapshot, operations: [],
262
+ error: { code: 'COMMIT_INTENT_HEAD_CONFLICT', message: 'Current HEAD does not match the pending checkpoint intent' }
263
+ };
264
+ if (inspected.snapshot.head !== identity.expectedHead) {
265
+ checkpointCommittedHead = inspected.snapshot.head;
266
+ pendingIntent = updateCheckpointIntent(pendingIntent, {
267
+ state: 'committed', committedHead: checkpointCommittedHead, updatedAt: checkpointTimestamp()
268
+ });
269
+ writeCheckpointIntent(task.repoRoot, pendingIntent);
270
+ return {
271
+ status: 'no-op', changed: false, snapshot: inspected.snapshot,
272
+ operations: [{ name: 'commit', status: 'no-op' }], error: null
209
273
  };
210
- const currentTree = gitText(input.cwd, ['rev-parse', 'HEAD^{tree}']);
211
- if (currentTree !== input.expectedTree)
274
+ }
275
+ if (input.paths.length === 0)
276
+ return {
277
+ status: 'failed', changed: false, snapshot: inspected.snapshot, operations: [],
278
+ error: { code: 'GIT_COMMIT_INPUT_INVALID', message: 'Local checkpoint requires explicit paths' }
279
+ };
280
+ const created = commitExplicitPaths({
281
+ cwd: input.cwd, paths: input.paths, message: input.message,
282
+ expectedHead: identity.expectedHead, expectedTree: identity.expectedTree
283
+ });
284
+ if (created.status === 'applied' && created.snapshot?.head) {
285
+ checkpointCommittedHead = created.snapshot.head;
286
+ pendingIntent = updateCheckpointIntent(pendingIntent, {
287
+ state: 'committed', committedHead: checkpointCommittedHead, updatedAt: checkpointTimestamp()
288
+ });
289
+ writeCheckpointIntent(task.repoRoot, pendingIntent);
290
+ }
291
+ else if (created.status === 'no-op') {
292
+ removeCheckpointIntent(task.repoRoot, task.taskId);
293
+ pendingIntent = null;
294
+ }
295
+ return created;
296
+ })()
297
+ : input.paths.length === 0
298
+ ? (() => {
299
+ if (inspected.snapshot.worktree.length > 0 || inspected.snapshot.staged.length > 0)
300
+ return {
301
+ status: 'failed',
302
+ changed: false,
303
+ snapshot: inspected.snapshot,
304
+ operations: [],
305
+ error: { code: 'GIT_COMMIT_INPUT_INVALID', message: 'Push-only retry requires a clean working tree' }
306
+ };
307
+ if (inspected.snapshot.head !== input.expectedHead)
308
+ return {
309
+ status: 'failed',
310
+ changed: false,
311
+ snapshot: inspected.snapshot,
312
+ operations: [],
313
+ error: { code: 'GIT_HEAD_MISMATCH', message: `Expected HEAD ${input.expectedHead}, received ${inspected.snapshot.head}` }
314
+ };
315
+ const currentTree = gitText(input.cwd, ['rev-parse', 'HEAD^{tree}']);
316
+ if (currentTree !== input.expectedTree)
317
+ return {
318
+ status: 'failed',
319
+ changed: false,
320
+ snapshot: inspected.snapshot,
321
+ operations: [],
322
+ error: { code: 'GIT_TREE_MISMATCH', message: `Expected current tree ${input.expectedTree}, received ${currentTree}` }
323
+ };
212
324
  return {
213
- status: 'failed',
325
+ status: 'no-op',
214
326
  changed: false,
215
327
  snapshot: inspected.snapshot,
216
- operations: [],
217
- error: { code: 'GIT_TREE_MISMATCH', message: `Expected current tree ${input.expectedTree}, received ${currentTree}` }
328
+ operations: [{ name: 'commit', status: 'no-op' }],
329
+ error: null
218
330
  };
219
- return {
220
- status: 'no-op',
221
- changed: false,
222
- snapshot: inspected.snapshot,
223
- operations: [{ name: 'commit', status: 'no-op' }],
224
- error: null
225
- };
226
- })()
227
- : commitExplicitPaths({
228
- cwd: input.cwd,
229
- paths: input.paths,
230
- message: input.message,
231
- expectedHead: input.expectedHead,
232
- expectedTree: input.expectedTree
233
- });
331
+ })()
332
+ : commitExplicitPaths({
333
+ cwd: input.cwd,
334
+ paths: input.paths,
335
+ message: input.message,
336
+ expectedHead: input.expectedHead,
337
+ expectedTree: input.expectedTree
338
+ });
234
339
  if (committed.status === 'failed')
235
340
  return {
236
341
  ...committed,
@@ -241,42 +346,42 @@ function executeUnlocked(input, task, mode) {
241
346
  snapshot: committed.snapshot
242
347
  };
243
348
  const warnings = [];
244
- if (orchestrationCompletion) {
245
- try {
246
- commitOrchestrationStageCompletion(orchestrationCompletion);
247
- }
248
- catch (error) {
249
- warnings.push(warning('ORCHESTRATION_COMPLETION_FAILED', error instanceof Error ? error.message : String(error), true, 'orchestration', task?.taskId ?? 'orchestration', 'ACTION_REQUIRED'));
250
- }
251
- }
252
349
  let status = committed.status;
253
350
  let result = committed.status === 'applied' ? 'committed' : 'no_op';
254
- const target = `${input.push.remote}:${input.push.refs[0]}`;
255
- const decision = commitPushDecision({ branch }, target);
256
- if (!decision.shouldPush) {
257
- warnings.push(decision.warning);
258
- }
259
- else {
260
- const pushed = pushGitRefs({
261
- cwd: input.cwd,
262
- remote: input.push.remote,
263
- refs: input.push.refs,
264
- expectedSha: committed.snapshot?.head ?? gitText(input.cwd, ['rev-parse', 'HEAD'])
265
- });
266
- if (pushed.status !== 'applied')
267
- warnings.push(warning('COMMIT_PUSH_FAILED', pushed.error?.message ?? 'Git push failed', true, 'push', target, 'ACTION_REQUIRED'));
351
+ if (delivery.mode === 'push') {
352
+ const target = `${delivery.remote}:${delivery.refs[0]}`;
353
+ const decision = commitPushDecision({ branch }, target);
354
+ if (!decision.shouldPush) {
355
+ warnings.push(decision.warning);
356
+ }
357
+ else {
358
+ const pushed = pushGitRefs({
359
+ cwd: input.cwd, remote: delivery.remote, refs: delivery.refs,
360
+ expectedSha: committed.snapshot?.head ?? gitText(input.cwd, ['rev-parse', 'HEAD'])
361
+ });
362
+ if (pushed.status !== 'applied')
363
+ warnings.push(warning('COMMIT_PUSH_FAILED', pushed.error?.message ?? 'Git push failed', true, 'push', target, 'ACTION_REQUIRED'));
364
+ }
268
365
  }
269
366
  if (warnings.length > 0) {
270
367
  status = 'applied';
271
368
  result = 'committed_with_warnings';
272
369
  }
273
370
  if (task && (committed.status === 'applied' || committed.status === 'no-op')) {
274
- const taskWarning = syncTaskCommit(input, task, committed.snapshot?.head ?? gitText(task.repoRoot, ['rev-parse', 'HEAD']));
371
+ const committedHead = checkpointCommittedHead ?? committed.snapshot?.head ?? gitText(task.repoRoot, ['rev-parse', 'HEAD']);
372
+ const taskWarning = syncTaskCommit(input, task, committedHead);
275
373
  if (taskWarning) {
276
374
  warnings.push(taskWarning);
277
375
  status = 'applied';
278
376
  result = 'committed_with_warnings';
279
377
  }
378
+ if (delivery.mode === 'local' && !taskWarning && pendingIntent && checkpointCommittedHead) {
379
+ const synced = updateCheckpointIntent(pendingIntent, {
380
+ state: 'synced', committedHead: checkpointCommittedHead, updatedAt: checkpointTimestamp()
381
+ });
382
+ writeCheckpointIntent(task.repoRoot, synced);
383
+ removeCheckpointIntent(task.repoRoot, task.taskId);
384
+ }
280
385
  }
281
386
  return {
282
387
  status,
@@ -101,12 +101,12 @@ function lifecycleTaskId(request, repoRoot) {
101
101
  return null;
102
102
  }
103
103
  }
104
- function applyLifecycleWithAuthority(context, request) {
104
+ async function applyLifecycleWithAuthority(context, request) {
105
105
  const conflict = overrideDryRunConflict(request);
106
106
  if (conflict) {
107
107
  return taskLifecycleFailure(request, { code: 'LIFECYCLE_PAYLOAD_INVALID', message: conflict.message });
108
108
  }
109
- const execute = () => {
109
+ const execute = async () => {
110
110
  const lifecycleResult = applyTaskLifecycle(request, { repoRoot: context.repoRoot });
111
111
  if (lifecycleResult.status !== 'failed' || !request.overrideTicket)
112
112
  return lifecycleResult;
@@ -116,7 +116,7 @@ function applyLifecycleWithAuthority(context, request) {
116
116
  error: { code: 'OVERRIDE_PAYLOAD_INVALID', message: 'override ticket requires --override-target and --override-scope' }
117
117
  };
118
118
  }
119
- const override = consumeHumanOverride({
119
+ const override = await consumeHumanOverride({
120
120
  taskRef: request.taskRef,
121
121
  ticketId: request.overrideTicket,
122
122
  failureId: failureId('lifecycle.apply', lifecycleResult.error?.code ?? 'LIFECYCLE_FAILED'),
@@ -133,9 +133,9 @@ function applyLifecycleWithAuthority(context, request) {
133
133
  };
134
134
  const taskId = lifecycleTaskId(request, context.repoRoot);
135
135
  if (!taskId)
136
- return execute();
136
+ return await execute();
137
137
  try {
138
- return withTaskExecutionLock(context.repoRoot, taskId, `task-lifecycle.${request.intent}`, execute);
138
+ return await withTaskExecutionLock(context.repoRoot, taskId, `task-lifecycle.${request.intent}`, execute);
139
139
  }
140
140
  catch (error) {
141
141
  if (!(error instanceof TaskExecutionLockError))
@@ -210,6 +210,9 @@ export function dispatchTaskControlOperation(context, operation) {
210
210
  operationTaskId(context, operation.request.taskRef);
211
211
  return applyTaskFinalization(operation.request, {
212
212
  repoRoot: context.repoRoot,
213
+ ...(context.source === 'sandbox-executor' ? {
214
+ controlBinding: { generation: context.generation, requestId: context.requestId }
215
+ } : {}),
213
216
  preflight: (request, options) => verifyTaskEvent({ ...request, event: 'complete-task.hard-preflight' }, options)
214
217
  });
215
218
  }