@fitlab-ai/agent-infra 0.9.12 → 0.9.14

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 (402) hide show
  1. package/README.md +11 -11
  2. package/README.zh-CN.md +11 -11
  3. package/bin/cli.ts +26 -9
  4. package/dist/bin/cli.js +173 -157
  5. package/dist/bin/internal-cli.js +66 -40
  6. package/dist/lib/agent-client.js +5 -0
  7. package/dist/lib/agent-clients/next-steps.js +6 -1
  8. package/dist/lib/decide.js +3 -3
  9. package/dist/lib/internal/agent-client.js +5 -2
  10. package/dist/lib/internal/cli-route-inventory.js +152 -0
  11. package/dist/lib/internal/codex-lifecycle.js +9 -6
  12. package/dist/lib/internal/codex-sandbox-controller.js +8 -2
  13. package/dist/lib/internal/git-workflow.js +10 -6
  14. package/dist/lib/internal/platform-checks.js +19 -7
  15. package/dist/lib/internal/platform-comment.js +25 -13
  16. package/dist/lib/internal/platform-context.js +6 -3
  17. package/dist/lib/internal/platform-issue.js +20 -13
  18. package/dist/lib/internal/platform-metadata.js +88 -0
  19. package/dist/lib/internal/platform-pr-review.js +26 -13
  20. package/dist/lib/internal/platform-pr.js +84 -31
  21. package/dist/lib/internal/platform-release-notes.js +9 -6
  22. package/dist/lib/internal/platform-security.js +93 -0
  23. package/dist/lib/internal/pr-review-grade.js +25 -12
  24. package/dist/lib/internal/release-workflow.js +23 -9
  25. package/dist/lib/internal/sandbox-control.js +50 -7
  26. package/dist/lib/internal/task-activity.js +16 -7
  27. package/dist/lib/internal/task-artifact.js +235 -24
  28. package/dist/lib/internal/task-context.js +4 -1
  29. package/dist/lib/internal/task-create.js +50 -17
  30. package/dist/lib/internal/task-delivery.js +4 -1
  31. package/dist/lib/internal/task-event.js +10 -4
  32. package/dist/lib/internal/task-finalization.js +6 -3
  33. package/dist/lib/internal/task-invalidation.js +63 -0
  34. package/dist/lib/internal/task-ledger.js +20 -6
  35. package/dist/lib/internal/task-lifecycle.js +6 -3
  36. package/dist/lib/internal/task-operation-registry.js +421 -0
  37. package/dist/lib/internal/task-orchestration.js +12 -0
  38. package/dist/lib/internal/task-override.js +14 -7
  39. package/dist/lib/internal/task-qualification.js +90 -0
  40. package/dist/lib/internal/task-review.js +7 -4
  41. package/dist/lib/internal/task-short-id.js +11 -1
  42. package/dist/lib/internal/task-snapshot.js +4 -1
  43. package/dist/lib/internal/task-validate.js +7 -2
  44. package/dist/lib/internal/task-verify.js +11 -7
  45. package/dist/lib/internal/task-warning.js +11 -4
  46. package/dist/lib/platform/adapters.js +1 -3
  47. package/dist/lib/platform/change-request-git-evidence.js +27 -7
  48. package/dist/lib/platform/comment-safety.js +226 -0
  49. package/dist/lib/platform/completion-backfill.js +6 -5
  50. package/dist/lib/platform/context.js +70 -130
  51. package/dist/lib/platform/github-client.js +1 -1
  52. package/dist/lib/platform/github-provider.js +1130 -0
  53. package/dist/lib/platform/in-label-sync.js +143 -0
  54. package/dist/lib/platform/issue-comments.js +237 -72
  55. package/dist/lib/platform/issues.js +335 -189
  56. package/dist/lib/platform/metadata-labels.js +6 -2
  57. package/dist/lib/platform/none-provider.js +28 -0
  58. package/dist/lib/platform/pr-change-report.js +545 -0
  59. package/dist/lib/platform/pr-checks.js +119 -104
  60. package/dist/lib/platform/pr-review.js +88 -72
  61. package/dist/lib/platform/pr-summary.js +541 -50
  62. package/dist/lib/platform/provider-bridge.js +45 -0
  63. package/dist/lib/platform/provider-contract.d.ts +553 -0
  64. package/dist/lib/platform/provider-contract.js +99 -0
  65. package/dist/lib/platform/provider-loader.js +251 -0
  66. package/dist/lib/platform/provider-validation.js +577 -0
  67. package/dist/lib/platform/pull-request-metadata.js +8 -6
  68. package/dist/lib/platform/pull-requests.js +734 -543
  69. package/dist/lib/platform/release-notes.js +78 -55
  70. package/dist/lib/platform/releases.js +79 -50
  71. package/dist/lib/platform/repository-metadata.js +377 -0
  72. package/dist/lib/platform/resource-identity.d.ts +26 -0
  73. package/dist/lib/platform/resource-identity.js +92 -0
  74. package/dist/lib/platform/security-alerts.js +155 -0
  75. package/dist/lib/platform/task-identities.js +31 -0
  76. package/dist/lib/platform/verification-required.js +11 -12
  77. package/dist/lib/platform/verification-sync.js +129 -248
  78. package/dist/lib/pr-review/evidence-grading.js +19 -6
  79. package/dist/lib/process-data/index.js +7 -0
  80. package/dist/lib/run/index.js +68 -23
  81. package/dist/lib/sandbox/commands/control-status.js +22 -0
  82. package/dist/lib/sandbox/commands/create.js +32 -6
  83. package/dist/lib/sandbox/commands/ls.js +5 -0
  84. package/dist/lib/sandbox/commands/rm.js +827 -120
  85. package/dist/lib/sandbox/commands/show.js +16 -0
  86. package/dist/lib/sandbox/control/client.js +174 -19
  87. package/dist/lib/sandbox/control/completed-reentry.js +85 -0
  88. package/dist/lib/sandbox/control/container-identity.js +28 -31
  89. package/dist/lib/sandbox/control/executor.js +151 -16
  90. package/dist/lib/sandbox/control/lifecycle.js +621 -127
  91. package/dist/lib/sandbox/control/native-file-lock.js +177 -0
  92. package/dist/lib/sandbox/control/protocol.js +77 -0
  93. package/dist/lib/sandbox/control/server.js +677 -34
  94. package/dist/lib/sandbox/control/state.js +209 -4
  95. package/dist/lib/sandbox/control/task-view.js +183 -0
  96. package/dist/lib/sandbox/engines/authority.js +289 -0
  97. package/dist/lib/sandbox/engines/docker-exact-discovery.js +97 -0
  98. package/dist/lib/sandbox/index.js +5 -0
  99. package/dist/lib/sandbox/recovery.js +21 -1
  100. package/dist/lib/sandbox/workspace-view.js +2 -1
  101. package/dist/lib/sandbox/worktree-safety.js +4 -1
  102. package/dist/lib/server/index.js +8 -0
  103. package/dist/lib/server/protocol.js +38 -1
  104. package/dist/lib/task/activity-log.js +8 -1
  105. package/dist/lib/task/artifact-lifecycle.js +75 -18
  106. package/dist/lib/task/artifact-operations.js +520 -0
  107. package/dist/lib/task/artifact-repair-intent.js +59 -0
  108. package/dist/lib/task/artifact-schema.js +135 -0
  109. package/dist/lib/task/capabilities.js +310 -0
  110. package/dist/lib/task/commands/status.js +32 -0
  111. package/dist/lib/task/commit-operation.js +12 -1
  112. package/dist/lib/task/control-authority.js +12 -5
  113. package/dist/lib/task/create-service.js +111 -12
  114. package/dist/lib/task/create.js +25 -0
  115. package/dist/lib/task/current-contract.js +5 -1
  116. package/dist/lib/task/decision-details.js +1 -1
  117. package/dist/lib/task/events.js +416 -17
  118. package/dist/lib/task/finalization.js +37 -13
  119. package/dist/lib/task/human-override.js +58 -36
  120. package/dist/lib/task/index.js +11 -3
  121. package/dist/lib/task/invalidation-command.js +86 -0
  122. package/dist/lib/task/invalidation.js +260 -0
  123. package/dist/lib/task/ledger-intents.js +37 -0
  124. package/dist/lib/task/local-artifact-finalization.js +299 -0
  125. package/dist/lib/task/orchestration.js +240 -144
  126. package/dist/lib/task/pr-delivery-fact.js +102 -101
  127. package/dist/lib/task/qualification-audit.js +490 -0
  128. package/dist/lib/task/qualification-confirmation.js +109 -0
  129. package/dist/lib/task/qualification-intents.js +148 -0
  130. package/dist/lib/task/review-artifacts.js +22 -23
  131. package/dist/lib/task/review-finalization.js +121 -4
  132. package/dist/lib/task/review-fingerprint.js +24 -2
  133. package/dist/lib/task/rework-intent.js +138 -0
  134. package/dist/lib/task/sections.js +6 -4
  135. package/dist/lib/task/skill-scope.js +23 -0
  136. package/dist/lib/task/task-execution-lock.js +27 -17
  137. package/dist/lib/task/verification-config.js +11 -0
  138. package/dist/lib/task/verification-engine.js +93 -16
  139. package/dist/lib/task/verification.js +3 -3
  140. package/dist/lib/task/workflow-warning-intents.js +1 -1
  141. package/dist/lib/task/write.js +11 -0
  142. package/dist/lib/version.js +11 -1
  143. package/dist/lifecycle-build-manifest.json +3 -3
  144. package/lib/agent-client.ts +9 -0
  145. package/lib/agent-clients/next-steps.ts +6 -1
  146. package/lib/decide.ts +3 -3
  147. package/lib/init.ts +1 -1
  148. package/lib/internal/agent-client.ts +4 -2
  149. package/lib/internal/cli-route-inventory.ts +140 -0
  150. package/lib/internal/codex-lifecycle.ts +8 -6
  151. package/lib/internal/codex-sandbox-controller.ts +7 -2
  152. package/lib/internal/git-workflow.ts +9 -6
  153. package/lib/internal/platform-checks.ts +14 -6
  154. package/lib/internal/platform-comment.ts +20 -12
  155. package/lib/internal/platform-context.ts +5 -3
  156. package/lib/internal/platform-issue.ts +17 -11
  157. package/lib/internal/platform-metadata.ts +70 -0
  158. package/lib/internal/platform-pr-review.ts +23 -12
  159. package/lib/internal/platform-pr.ts +65 -27
  160. package/lib/internal/platform-release-notes.ts +8 -6
  161. package/lib/internal/platform-security.ts +83 -0
  162. package/lib/internal/pr-review-grade.ts +20 -11
  163. package/lib/internal/release-workflow.ts +21 -9
  164. package/lib/internal/sandbox-control.ts +44 -6
  165. package/lib/internal/task-activity.ts +15 -7
  166. package/lib/internal/task-artifact.ts +204 -22
  167. package/lib/internal/task-context.ts +3 -1
  168. package/lib/internal/task-create.ts +78 -17
  169. package/lib/internal/task-delivery.ts +3 -1
  170. package/lib/internal/task-event.ts +9 -4
  171. package/lib/internal/task-finalization.ts +6 -4
  172. package/lib/internal/task-invalidation.ts +41 -0
  173. package/lib/internal/task-ledger.ts +21 -8
  174. package/lib/internal/task-lifecycle.ts +5 -3
  175. package/lib/internal/task-operation-registry.ts +482 -0
  176. package/lib/internal/task-orchestration.ts +12 -0
  177. package/lib/internal/task-override.ts +15 -9
  178. package/lib/internal/task-qualification.ts +61 -0
  179. package/lib/internal/task-review.ts +6 -4
  180. package/lib/internal/task-short-id.ts +10 -1
  181. package/lib/internal/task-snapshot.ts +3 -1
  182. package/lib/internal/task-validate.ts +6 -2
  183. package/lib/internal/task-verify.ts +10 -7
  184. package/lib/internal/task-warning.ts +10 -4
  185. package/lib/platform/adapters.ts +3 -2
  186. package/lib/platform/change-request-git-evidence.ts +36 -9
  187. package/lib/platform/comment-safety.ts +250 -0
  188. package/lib/platform/completion-backfill.ts +9 -8
  189. package/lib/platform/context.ts +97 -134
  190. package/lib/platform/github-client.ts +2 -2
  191. package/lib/platform/github-provider.ts +1132 -0
  192. package/lib/platform/in-label-sync.ts +208 -0
  193. package/lib/platform/issue-comments.ts +255 -80
  194. package/lib/platform/issues.ts +344 -174
  195. package/lib/platform/metadata-labels.ts +5 -2
  196. package/lib/platform/none-provider.ts +35 -0
  197. package/lib/platform/pr-change-report.ts +639 -0
  198. package/lib/platform/pr-checks.ts +126 -106
  199. package/lib/platform/pr-review.ts +88 -85
  200. package/lib/platform/pr-summary.ts +581 -53
  201. package/lib/platform/provider-bridge.ts +82 -0
  202. package/lib/platform/provider-contract.ts +611 -0
  203. package/lib/platform/provider-loader.ts +307 -0
  204. package/lib/platform/provider-validation.ts +611 -0
  205. package/lib/platform/pull-request-metadata.ts +10 -7
  206. package/lib/platform/pull-requests.ts +781 -550
  207. package/lib/platform/release-notes.ts +76 -59
  208. package/lib/platform/releases.ts +77 -43
  209. package/lib/platform/repository-metadata.ts +453 -0
  210. package/lib/platform/resource-identity.ts +121 -0
  211. package/lib/platform/security-alerts.ts +191 -0
  212. package/lib/platform/task-identities.ts +40 -0
  213. package/lib/platform/types.ts +4 -2
  214. package/lib/platform/verification-required.ts +11 -13
  215. package/lib/platform/verification-sync.ts +128 -304
  216. package/lib/pr-review/evidence-grading.ts +25 -8
  217. package/lib/process-data/index.ts +7 -0
  218. package/lib/run/index.ts +62 -22
  219. package/lib/sandbox/commands/control-status.ts +26 -0
  220. package/lib/sandbox/commands/create.ts +46 -6
  221. package/lib/sandbox/commands/ls.ts +7 -0
  222. package/lib/sandbox/commands/rm.ts +1000 -87
  223. package/lib/sandbox/commands/show.ts +16 -0
  224. package/lib/sandbox/control/client.ts +203 -19
  225. package/lib/sandbox/control/completed-reentry.ts +98 -0
  226. package/lib/sandbox/control/container-identity.ts +27 -43
  227. package/lib/sandbox/control/executor.ts +180 -15
  228. package/lib/sandbox/control/lifecycle.ts +629 -17
  229. package/lib/sandbox/control/native-file-lock.ts +209 -0
  230. package/lib/sandbox/control/protocol.ts +118 -2
  231. package/lib/sandbox/control/server.ts +724 -34
  232. package/lib/sandbox/control/state.ts +257 -4
  233. package/lib/sandbox/control/task-view.ts +240 -0
  234. package/lib/sandbox/engines/authority.ts +365 -0
  235. package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
  236. package/lib/sandbox/index.ts +7 -0
  237. package/lib/sandbox/recovery.ts +21 -1
  238. package/lib/sandbox/workspace-view.ts +9 -3
  239. package/lib/sandbox/worktree-safety.ts +4 -1
  240. package/lib/server/index.ts +10 -0
  241. package/lib/server/protocol.ts +36 -1
  242. package/lib/task/activity-log.ts +8 -0
  243. package/lib/task/artifact-lifecycle.ts +70 -22
  244. package/lib/task/artifact-operations.ts +626 -0
  245. package/lib/task/artifact-repair-intent.ts +71 -0
  246. package/lib/task/artifact-schema.ts +192 -0
  247. package/lib/task/capabilities.ts +331 -0
  248. package/lib/task/commands/status.ts +38 -0
  249. package/lib/task/commit-operation.ts +12 -1
  250. package/lib/task/control-authority.ts +22 -9
  251. package/lib/task/create-service.ts +139 -14
  252. package/lib/task/create.ts +27 -0
  253. package/lib/task/current-contract.ts +6 -1
  254. package/lib/task/decision-details.ts +6 -2
  255. package/lib/task/events.ts +392 -16
  256. package/lib/task/finalization.ts +50 -14
  257. package/lib/task/human-override.ts +70 -46
  258. package/lib/task/index.ts +16 -3
  259. package/lib/task/invalidation-command.ts +86 -0
  260. package/lib/task/invalidation.ts +332 -0
  261. package/lib/task/ledger-intents.ts +35 -1
  262. package/lib/task/local-artifact-finalization.ts +432 -0
  263. package/lib/task/orchestration.ts +223 -133
  264. package/lib/task/pr-delivery-fact.ts +131 -148
  265. package/lib/task/qualification-audit.ts +599 -0
  266. package/lib/task/qualification-confirmation.ts +117 -0
  267. package/lib/task/qualification-intents.ts +150 -0
  268. package/lib/task/review-artifacts.ts +21 -22
  269. package/lib/task/review-finalization.ts +133 -4
  270. package/lib/task/review-fingerprint.ts +23 -2
  271. package/lib/task/rework-intent.ts +165 -0
  272. package/lib/task/sections.ts +6 -4
  273. package/lib/task/skill-scope.ts +24 -0
  274. package/lib/task/task-execution-lock.ts +23 -14
  275. package/lib/task/verification-config.ts +12 -0
  276. package/lib/task/verification-engine.ts +103 -17
  277. package/lib/task/verification.ts +4 -4
  278. package/lib/task/workflow-warning-intents.ts +1 -1
  279. package/lib/task/write.ts +19 -0
  280. package/lib/update.ts +1 -1
  281. package/lib/version.ts +15 -1
  282. package/package.json +12 -1
  283. package/templates/.agents/rules/README.en.md +3 -1
  284. package/templates/.agents/rules/README.zh-CN.md +3 -1
  285. package/templates/.agents/rules/decision-qualification.en.md +22 -0
  286. package/templates/.agents/rules/decision-qualification.zh-CN.md +22 -0
  287. package/templates/.agents/rules/evidence-reporting.en.md +28 -0
  288. package/templates/.agents/rules/evidence-reporting.zh-CN.md +28 -0
  289. package/templates/.agents/rules/issue-pr-commands.en.md +1 -1
  290. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
  291. package/templates/.agents/rules/issue-sync.en.md +2 -0
  292. package/templates/.agents/rules/issue-sync.zh-CN.md +2 -0
  293. package/templates/.agents/rules/label-milestone-setup.en.md +7 -7
  294. package/templates/.agents/rules/label-milestone-setup.zh-CN.md +7 -7
  295. package/templates/.agents/rules/local-artifact-repair.en.md +13 -2
  296. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +13 -2
  297. package/templates/.agents/rules/pr-sync.en.md +10 -4
  298. package/templates/.agents/rules/pr-sync.zh-CN.md +17 -4
  299. package/templates/.agents/rules/security-alerts.en.md +8 -8
  300. package/templates/.agents/rules/security-alerts.zh-CN.md +8 -8
  301. package/templates/.agents/rules/task-short-id.en.md +1 -4
  302. package/templates/.agents/rules/task-short-id.zh-CN.md +1 -3
  303. package/templates/.agents/skills/analyze-task/SKILL.en.md +28 -5
  304. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +29 -5
  305. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -12
  306. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -12
  307. package/templates/.agents/skills/check-task/SKILL.en.md +16 -37
  308. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -37
  309. package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
  310. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
  311. package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
  312. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
  313. package/templates/.agents/skills/code-task/SKILL.en.md +41 -9
  314. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +43 -11
  315. package/templates/.agents/skills/code-task/config/verify.en.json +6 -14
  316. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +6 -14
  317. package/templates/.agents/skills/code-task/reference/code-rules.en.md +5 -4
  318. package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +5 -4
  319. package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
  320. package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
  321. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +3 -1
  322. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +3 -1
  323. package/templates/.agents/skills/code-task/reference/report-template.en.md +42 -15
  324. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +39 -12
  325. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +2 -0
  326. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +2 -0
  327. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +3 -3
  328. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +3 -3
  329. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +10 -4
  330. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +10 -4
  331. package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +2 -0
  332. package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +2 -0
  333. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +4 -3
  334. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +4 -3
  335. package/templates/.agents/skills/complete-task/SKILL.en.md +26 -21
  336. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +25 -21
  337. package/templates/.agents/skills/create-pr/SKILL.en.md +7 -6
  338. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +7 -7
  339. package/templates/.agents/skills/create-pr/config/verify.json +1 -0
  340. package/templates/.agents/skills/create-pr/reference/change-report.en.md +16 -4
  341. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +16 -4
  342. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +5 -3
  343. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +5 -3
  344. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +1 -1
  345. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +1 -1
  346. package/templates/.agents/skills/create-pr/scripts/change-report.mjs +3 -0
  347. package/templates/.agents/skills/create-task/SKILL.en.md +8 -0
  348. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +7 -0
  349. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  350. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  351. package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
  352. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
  353. package/templates/.agents/skills/init-labels/SKILL.en.md +8 -8
  354. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +8 -8
  355. package/templates/.agents/skills/init-milestones/SKILL.en.md +9 -11
  356. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +9 -11
  357. package/templates/.agents/skills/plan-task/SKILL.en.md +27 -4
  358. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +26 -4
  359. package/templates/.agents/skills/plan-task/config/verify.en.json +4 -14
  360. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +4 -14
  361. package/templates/.agents/skills/review-analysis/SKILL.en.md +17 -4
  362. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +17 -4
  363. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -18
  364. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -18
  365. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +50 -23
  366. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +45 -18
  367. package/templates/.agents/skills/review-code/SKILL.en.md +18 -5
  368. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +18 -5
  369. package/templates/.agents/skills/review-code/config/verify.en.json +1 -23
  370. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -23
  371. package/templates/.agents/skills/review-code/reference/report-template.en.md +49 -22
  372. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +45 -18
  373. package/templates/.agents/skills/review-plan/SKILL.en.md +17 -4
  374. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +17 -4
  375. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -18
  376. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -18
  377. package/templates/.agents/skills/review-plan/reference/report-template.en.md +49 -22
  378. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +45 -18
  379. package/templates/.agents/skills/review-pr/SKILL.en.md +5 -1
  380. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +5 -1
  381. package/templates/.agents/skills/review-pr/reference/report-template.en.md +4 -3
  382. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +4 -3
  383. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +9 -3
  384. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +9 -3
  385. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +3 -1
  386. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +3 -1
  387. package/templates/.agents/skills/test/SKILL.en.md +13 -2
  388. package/templates/.agents/skills/test/SKILL.zh-CN.md +13 -2
  389. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +14 -0
  390. package/templates/.agents/skills/watch-pr/SKILL.en.md +2 -2
  391. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +2 -2
  392. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +6 -0
  393. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +6 -0
  394. package/templates/.agents/templates/task.en.md +24 -1
  395. package/templates/.agents/templates/task.zh-CN.md +24 -1
  396. package/templates/.github/workflows/pr-label.yml +7 -26
  397. package/templates/.agents/scripts/security-alerts.github.sh +0 -151
  398. package/templates/.agents/scripts/security-alerts.sh +0 -31
  399. package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +0 -146
  400. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +0 -32
  401. package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +0 -294
  402. package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +0 -6
@@ -1,11 +1,10 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { randomUUID } from 'node:crypto';
3
+ import { createHash, randomUUID } from 'node:crypto';
4
4
 
5
5
  import { parseTypedTaskFrontmatter } from './frontmatter.ts';
6
6
  import { validateCurrentTaskContract } from './current-contract.ts';
7
- import { parseReviewSummary, resolveCanonicalVerdict } from './review-artifacts.ts';
8
- import { inspectArtifactDirectory } from './artifact-lifecycle.ts';
7
+ import { parseReviewSummary } from './review-artifacts.ts';
9
8
  import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from './ledger.ts';
10
9
  import type { LedgerDocument } from './ledger.ts';
11
10
  import { resolveTaskRef } from './resolve-ref.ts';
@@ -53,6 +52,11 @@ import { hasActiveCodexLifecycleEvidence } from '../agent-clients/adapters/codex
53
52
  import type { CodexCapabilityProvenanceDetail } from '../agent-clients/adapters/codex-lifecycle/capability-store.ts';
54
53
  import { extractReviewBaseline, extractReviewDiffBase, extractReviewTargetHead, extractReviewedHead } from './review-fingerprint.ts';
55
54
  import { resolveDeliveryTarget, resolveDiffBase, resolveTargetHead } from './delivery-target.ts';
55
+ import { buildLifecycleFacts, canStart, recommendNext } from './capabilities.ts';
56
+ import { hasOpenLifecycleExecution } from './activity-log.ts';
57
+ import { invalidationBlocks } from './invalidation.ts';
58
+ import type { InvalidationDocument } from './invalidation.ts';
59
+ import type { LifecycleAction, LifecycleFacts } from './capabilities.ts';
56
60
 
57
61
  type OrchestrationStatus = 'running' | 'paused' | 'completed';
58
62
  type ModelPolicySource = Readonly<{
@@ -108,7 +112,7 @@ type OrchestrationRun = Readonly<{
108
112
  updatedAt: string;
109
113
  }>;
110
114
  type OrchestrationNext = Readonly<{
111
- action: 'analyze-task' | 'review-analysis' | 'plan-task' | 'review-plan' | 'code-task' | 'review-code' | 'commit';
115
+ action: 'analyze-task' | 'review-analysis' | 'plan-task' | 'review-plan' | 'code-task' | 'review-code';
112
116
  role: DelegationRole;
113
117
  stage: DelegationStage;
114
118
  round: number;
@@ -150,6 +154,7 @@ type OrchestrationCompletionPlanResult = Readonly<{
150
154
  type OrchestrationOptions = {
151
155
  repoRoot?: string;
152
156
  gitWorktreeRoot?: string;
157
+ diagnosticLog?: OrchestrationDiagnosticLogger;
153
158
  id?: () => string;
154
159
  now?: () => string;
155
160
  maxSteps?: number;
@@ -174,6 +179,10 @@ type OrchestrationOptions = {
174
179
  hasActiveLifecycleEvidence?: (receipt: DelegationReceipt) => boolean;
175
180
  };
176
181
 
182
+ export type OrchestrationDiagnosticValue = string | number | boolean | null;
183
+ export type OrchestrationDiagnosticFields = Readonly<Record<string, OrchestrationDiagnosticValue>>;
184
+ export type OrchestrationDiagnosticLogger = (event: string, fields: OrchestrationDiagnosticFields) => void;
185
+
177
186
  function supportsLifecycleDelegation(client: AgentClientId): boolean {
178
187
  return getAgentClientCapability(client, 'subagents').level !== 'unsupported'
179
188
  && getAgentClientCapability(client, 'orchestration').level !== 'unsupported'
@@ -190,11 +199,13 @@ const ORCHESTRATION_STATE_INVALID_MESSAGE = 'orchestration.json does not match t
190
199
  class OrchestrationStateError extends Error {
191
200
  readonly code = 'ORCHESTRATION_STATE_INVALID';
192
201
  readonly taskId: string | null;
202
+ readonly reasonCodes: readonly string[];
193
203
 
194
- constructor(taskId: string | null = null) {
204
+ constructor(taskId: string | null = null, reasonCodes: readonly string[] = []) {
195
205
  super(ORCHESTRATION_STATE_INVALID_MESSAGE);
196
206
  this.name = 'OrchestrationStateError';
197
207
  this.taskId = taskId;
208
+ this.reasonCodes = Object.freeze([...reasonCodes]);
198
209
  }
199
210
  }
200
211
 
@@ -284,46 +295,128 @@ const ORCHESTRATION_RUN_KEYS = [
284
295
  'pause', 'commitAuthorization', 'completionEvidence', 'createdAt', 'updatedAt'
285
296
  ] as const;
286
297
 
287
- function parseOrchestrationRun(value: unknown, expectedTaskId?: string): OrchestrationRun {
288
- if (!hasExactKeys(value, ORCHESTRATION_RUN_KEYS)
289
- || !exactText(value.taskId)
290
- || (expectedTaskId !== undefined && value.taskId !== expectedTaskId)
291
- || !exactText(value.runId)
292
- || !['running', 'paused', 'completed'].includes(value.status as string)
293
- || !(value.nextStage === null || ['analysis', 'review-analysis', 'plan', 'review-plan', 'code', 'review-code', 'commit'].includes(value.nextStage as string))
294
- || !Number.isSafeInteger(value.stepCount) || (value.stepCount as number) < 0
295
- || !Number.isSafeInteger(value.maxSteps) || (value.maxSteps as number) < 1
296
- || !isModelPolicy(value.modelPolicy)
297
- || !isModelPolicySource(value.modelPolicySource)
298
- || !Array.isArray(value.recoveryHistory) || !value.recoveryHistory.every(isRecovery)
299
- || typeof value.baseline !== 'string'
300
- || !(value.pendingDelegation === null || isDelegationReceipt(value.pendingDelegation))
301
- || !Array.isArray(value.receipts) || !value.receipts.every(isDelegationReceipt)
302
- || !(value.pause === null || isPause(value.pause))
303
- || !hasExactKeys(value.commitAuthorization, ['issuedAt', 'consumedAt'])
304
- || !nullableText(value.commitAuthorization.issuedAt)
305
- || !nullableText(value.commitAuthorization.consumedAt)
306
- || !(value.completionEvidence === null || isCompletionEvidence(value.completionEvidence))
307
- || !exactText(value.createdAt)
308
- || !exactText(value.updatedAt)) {
309
- throw new OrchestrationStateError();
298
+ function orchestrationStateReasonCodes(value: unknown, expectedTaskId?: string): string[] {
299
+ if (!hasExactKeys(value, ORCHESTRATION_RUN_KEYS)) return ['top-level-keys'];
300
+ const record = value;
301
+ const reasons: string[] = [];
302
+ if (!exactText(record.taskId)) reasons.push('taskId');
303
+ else if (expectedTaskId !== undefined && record.taskId !== expectedTaskId) reasons.push('taskId-mismatch');
304
+ if (!exactText(record.runId)) reasons.push('runId');
305
+ if (!['running', 'paused', 'completed'].includes(record.status as string)) reasons.push('status');
306
+ if (!(record.nextStage === null || ['analysis', 'review-analysis', 'plan', 'review-plan', 'code', 'review-code', 'commit'].includes(record.nextStage as string))) {
307
+ reasons.push('nextStage');
308
+ }
309
+ if (!Number.isSafeInteger(record.stepCount) || (record.stepCount as number) < 0) reasons.push('stepCount');
310
+ if (!Number.isSafeInteger(record.maxSteps) || (record.maxSteps as number) < 1) reasons.push('maxSteps');
311
+ if (!isModelPolicy(record.modelPolicy)) reasons.push('modelPolicy');
312
+ if (!isModelPolicySource(record.modelPolicySource)) reasons.push('modelPolicySource');
313
+ if (!Array.isArray(record.recoveryHistory) || !record.recoveryHistory.every(isRecovery)) reasons.push('recoveryHistory');
314
+ if (typeof record.baseline !== 'string') reasons.push('baseline');
315
+ if (!(record.pendingDelegation === null || isDelegationReceipt(record.pendingDelegation))) reasons.push('pendingDelegation');
316
+ if (!Array.isArray(record.receipts) || !record.receipts.every(isDelegationReceipt)) reasons.push('receipts');
317
+ if (!(record.pause === null || isPause(record.pause))) reasons.push('pause');
318
+ if (!hasExactKeys(record.commitAuthorization, ['issuedAt', 'consumedAt'])) {
319
+ reasons.push('commitAuthorization');
320
+ } else {
321
+ if (!nullableText(record.commitAuthorization.issuedAt)) reasons.push('commitAuthorization.issuedAt');
322
+ if (!nullableText(record.commitAuthorization.consumedAt)) reasons.push('commitAuthorization.consumedAt');
323
+ }
324
+ if (!(record.completionEvidence === null || isCompletionEvidence(record.completionEvidence))) reasons.push('completionEvidence');
325
+ if (!exactText(record.createdAt)) reasons.push('createdAt');
326
+ if (!exactText(record.updatedAt)) reasons.push('updatedAt');
327
+ if (Array.isArray(record.receipts) && record.receipts.every(isDelegationReceipt)
328
+ && (record.pendingDelegation === null || isDelegationReceipt(record.pendingDelegation))) {
329
+ const receipts = [...record.receipts, ...(record.pendingDelegation ? [record.pendingDelegation] : [])];
330
+ if (receipts.some((receipt) => receipt.taskId !== record.taskId || receipt.runId !== record.runId)) {
331
+ reasons.push('receipt-identity');
332
+ }
333
+ }
334
+ return reasons;
335
+ }
336
+
337
+ function emitDiagnostic(options: Pick<OrchestrationOptions, 'diagnosticLog'> | undefined, event: string, fields: OrchestrationDiagnosticFields): void {
338
+ try {
339
+ options?.diagnosticLog?.(event, fields);
340
+ } catch {
341
+ // Diagnostics must never change lifecycle behavior.
310
342
  }
311
- const receipts = [...value.receipts, ...(value.pendingDelegation ? [value.pendingDelegation] : [])];
312
- if (receipts.some((receipt) => receipt.taskId !== value.taskId || receipt.runId !== value.runId)) {
313
- throw new OrchestrationStateError();
343
+ }
344
+
345
+ function fileObservation(file: string): OrchestrationDiagnosticFields {
346
+ try {
347
+ const stat = fs.lstatSync(file);
348
+ let realpath: string | null = null;
349
+ try { realpath = fs.realpathSync.native(file); } catch { /* retain the lstat observation */ }
350
+ return {
351
+ file,
352
+ exists: true,
353
+ fileType: stat.isFile() ? 'file' : stat.isDirectory() ? 'directory' : 'other',
354
+ symbolicLink: stat.isSymbolicLink(),
355
+ bytes: stat.isFile() ? stat.size : null,
356
+ mtimeMs: stat.mtimeMs,
357
+ device: stat.dev,
358
+ inode: stat.ino,
359
+ realpath
360
+ };
361
+ } catch (error) {
362
+ return {
363
+ file,
364
+ exists: false,
365
+ fileType: null,
366
+ symbolicLink: null,
367
+ bytes: null,
368
+ mtimeMs: null,
369
+ device: null,
370
+ inode: null,
371
+ realpath: null,
372
+ fsError: error instanceof Error && 'code' in error ? String(error.code) : null
373
+ };
314
374
  }
375
+ }
376
+
377
+ function parseOrchestrationRun(value: unknown, expectedTaskId?: string): OrchestrationRun {
378
+ const reasonCodes = orchestrationStateReasonCodes(value, expectedTaskId);
379
+ if (reasonCodes.length > 0) throw new OrchestrationStateError(expectedTaskId ?? null, reasonCodes);
315
380
  return value as OrchestrationRun;
316
381
  }
317
382
 
318
- function readRun(taskDir: string): OrchestrationRun | null {
383
+ function readRun(taskDir: string, options: Pick<OrchestrationOptions, 'diagnosticLog'> = {}): OrchestrationRun | null {
319
384
  const file = orchestrationPath(taskDir);
320
- if (!fs.existsSync(file)) return null;
321
385
  const taskId = path.basename(taskDir);
386
+ const observed = options.diagnosticLog ? fileObservation(file) : {};
387
+ if (!fs.existsSync(file)) {
388
+ emitDiagnostic(options, 'orchestration-state-missing', { taskId, taskDir, ...observed });
389
+ return null;
390
+ }
391
+ emitDiagnostic(options, 'orchestration-state-read-start', { taskId, taskDir, ...observed });
392
+ let rawBytes: number | null = null;
393
+ let rawSha256: string | null = null;
322
394
  try {
323
- return parseOrchestrationRun(JSON.parse(fs.readFileSync(file, 'utf8')), taskId);
395
+ const raw = fs.readFileSync(file, 'utf8');
396
+ if (options.diagnosticLog) {
397
+ rawBytes = Buffer.byteLength(raw, 'utf8');
398
+ rawSha256 = createHash('sha256').update(raw, 'utf8').digest('hex');
399
+ }
400
+ const run = parseOrchestrationRun(JSON.parse(raw), taskId);
401
+ emitDiagnostic(options, 'orchestration-state-read-ok', {
402
+ taskId, taskDir, file, rawBytes, rawSha256, status: run.status, runId: run.runId,
403
+ stepCount: run.stepCount, pendingDelegation: run.pendingDelegation !== null
404
+ });
405
+ return run;
324
406
  } catch (error) {
325
- if (error instanceof OrchestrationStateError) throw new OrchestrationStateError(taskId);
326
- throw new OrchestrationStateError(taskId);
407
+ const reasonCodes = error instanceof OrchestrationStateError && error.reasonCodes.length > 0
408
+ ? error.reasonCodes
409
+ : [error instanceof SyntaxError ? 'json-parse' : 'file-read'];
410
+ emitDiagnostic(options, 'orchestration-state-read-failed', {
411
+ taskId,
412
+ taskDir,
413
+ ...observed,
414
+ rawBytes,
415
+ rawSha256,
416
+ reasonCodes: reasonCodes.join(','),
417
+ errorType: error instanceof Error ? error.name : typeof error,
418
+ });
419
+ throw new OrchestrationStateError(taskId, reasonCodes);
327
420
  }
328
421
  }
329
422
 
@@ -413,7 +506,7 @@ function beginOrResumeOrchestration(taskRef: string, options: OrchestrationOptio
413
506
  }
414
507
  let existing: OrchestrationRun | null;
415
508
  try {
416
- existing = readRun(resolved.taskDir);
509
+ existing = readRun(resolved.taskDir, options);
417
510
  } catch (error) {
418
511
  return failed('ORCHESTRATION_STATE_INVALID', error instanceof Error ? error.message : String(error), resolved.taskId);
419
512
  }
@@ -561,78 +654,19 @@ function validateSavedCurrentDiffBase(
561
654
  return null;
562
655
  }
563
656
 
564
- function hasReviewAfterArtifact(taskDir: string, family: string, reviewFamily: string): boolean {
565
- const artifact = inspectArtifactDirectory(taskDir, family as 'analysis' | 'plan' | 'code');
566
- const review = inspectArtifactDirectory(taskDir, reviewFamily as 'review-analysis' | 'review-plan' | 'review-code');
567
- return artifact.status === 'ready'
568
- && review.status === 'ready'
569
- && artifact.latest !== null
570
- && review.reviewedInput?.name === artifact.latest.name;
571
- }
572
-
573
- function latestReviewApproved(taskDir: string, family: 'review-analysis' | 'review-plan' | 'review-code'): { approved: boolean; error: string | null } {
574
- const round = highestRound(taskDir, family);
575
- if (round === 0) return { approved: false, error: null };
576
- let content: string;
577
- try { content = fs.readFileSync(path.join(taskDir, artifactName(family, round)), 'utf8'); }
578
- catch (error) { return { approved: false, error: String(error) }; }
579
- const parsed = parseReviewSummary(content);
580
- if (!parsed.ok) return { approved: false, error: `${parsed.code}: ${parsed.message}` };
581
- const verdict = resolveCanonicalVerdict(parsed.summary);
582
- if (!verdict.ok) return { approved: false, error: `${verdict.code}: ${verdict.message}` };
583
- return { approved: verdict.verdict === 'Approved', error: null };
584
- }
585
-
586
- function routeFromFacts(taskDir: string): Omit<OrchestrationNext, 'requestedModel' | 'requestedReasoningEffort'> | { error: string } | null {
587
- const analysisRound = highestRound(taskDir, 'analysis');
588
- const analysisReviewRound = highestRound(taskDir, 'review-analysis');
589
- const planRound = highestRound(taskDir, 'plan');
590
- const planReviewRound = highestRound(taskDir, 'review-plan');
591
- const codeRound = highestRound(taskDir, 'code');
592
- const codeReviewRound = highestRound(taskDir, 'review-code');
593
- if (analysisRound === 0) {
594
- const round = analysisRound + 1;
595
- return { action: 'analyze-task', role: 'executor', stage: 'analysis', round, artifact: artifactName('analysis', round) };
596
- }
597
- if (!hasReviewAfterArtifact(taskDir, 'analysis', 'review-analysis')) {
598
- const round = analysisReviewRound + 1;
599
- return { action: 'review-analysis', role: 'reviewer', stage: 'review-analysis', round, artifact: artifactName('review-analysis', round) };
600
- }
601
- const analysisVerdict = latestReviewApproved(taskDir, 'review-analysis');
602
- if (analysisVerdict.error) return { error: analysisVerdict.error };
603
- if (!analysisVerdict.approved) {
604
- const round = analysisRound + 1;
605
- return { action: 'analyze-task', role: 'executor', stage: 'analysis', round, artifact: artifactName('analysis', round) };
606
- }
607
- if (planRound === 0) {
608
- const round = planRound + 1;
609
- return { action: 'plan-task', role: 'executor', stage: 'plan', round, artifact: artifactName('plan', round) };
610
- }
611
- if (!hasReviewAfterArtifact(taskDir, 'plan', 'review-plan')) {
612
- const round = planReviewRound + 1;
613
- return { action: 'review-plan', role: 'reviewer', stage: 'review-plan', round, artifact: artifactName('review-plan', round) };
614
- }
615
- const planVerdict = latestReviewApproved(taskDir, 'review-plan');
616
- if (planVerdict.error) return { error: planVerdict.error };
617
- if (!planVerdict.approved) {
618
- const round = planRound + 1;
619
- return { action: 'plan-task', role: 'executor', stage: 'plan', round, artifact: artifactName('plan', round) };
620
- }
621
- if (codeRound === 0) {
622
- const round = codeRound + 1;
623
- return { action: 'code-task', role: 'executor', stage: 'code', round, artifact: artifactName('code', round) };
624
- }
625
- if (!hasReviewAfterArtifact(taskDir, 'code', 'review-code')) {
626
- const round = codeReviewRound + 1;
627
- return { action: 'review-code', role: 'reviewer', stage: 'review-code', round, artifact: artifactName('review-code', round) };
628
- }
629
- const codeVerdict = latestReviewApproved(taskDir, 'review-code');
630
- if (codeVerdict.error) return { error: codeVerdict.error };
631
- if (!codeVerdict.approved) {
632
- const round = codeRound + 1;
633
- return { action: 'code-task', role: 'executor', stage: 'code', round, artifact: artifactName('code', round) };
634
- }
635
- return { action: 'commit', role: 'executor', stage: 'commit', round: 1, artifact: 'commit' };
657
+ function routeFromFacts(facts: LifecycleFacts): Omit<OrchestrationNext, 'requestedModel' | 'requestedReasoningEffort'> | { completion: true } | null {
658
+ const recommendation = recommendNext(facts);
659
+ if (!recommendation.action) return { completion: true };
660
+ const action = recommendation.action;
661
+ if (action === 'manual-validation' || action === 'validation-run') return null;
662
+ const family = action === 'analysis' ? 'analysis' : action;
663
+ const round = Math.max(0, ...[...(facts.artifacts[family] ?? []), ...(facts.staleArtifacts?.[family] ?? [])].map((name) => {
664
+ const match = /-r(\d+)\.md$/.exec(name);
665
+ return match ? Number(match[1]) : 1;
666
+ })) + 1;
667
+ const command = action === 'analysis' ? 'analyze-task' : action === 'plan' ? 'plan-task' : action === 'code' ? 'code-task' : action;
668
+ const role = action.startsWith('review-') ? 'reviewer' : 'executor';
669
+ return { action: command, role, stage: action, round, artifact: artifactName(family, round) };
636
670
  }
637
671
 
638
672
  function routeOrchestration(taskRef: string, options: OrchestrationOptions = {}): OrchestrationResult {
@@ -652,11 +686,13 @@ function routeOrchestration(taskRef: string, options: OrchestrationOptions = {})
652
686
  }
653
687
  let metadata: ReturnType<typeof parseTypedTaskFrontmatter>;
654
688
  let currentLedger: LedgerDocument | null = null;
689
+ let currentInvalidation: InvalidationDocument = { operations: [], targets: [] };
655
690
  if (resolved.state === 'active') {
656
691
  const contract = validateCurrentTaskContract(content);
657
692
  if (!contract.ok) return failed('ORCHESTRATION_CURRENT_CONTRACT_INVALID', contract.message, resolved.taskId);
658
693
  metadata = contract.metadata;
659
694
  currentLedger = contract.ledger;
695
+ currentInvalidation = contract.invalidation;
660
696
  } else {
661
697
  try {
662
698
  metadata = parseTypedTaskFrontmatter(content);
@@ -664,17 +700,25 @@ function routeOrchestration(taskRef: string, options: OrchestrationOptions = {})
664
700
  return failed('ORCHESTRATION_TASK_INVALID', error instanceof Error ? error.message : String(error), resolved.taskId);
665
701
  }
666
702
  }
667
- const routed = routeFromFacts(resolved.taskDir);
668
- if (routed && 'error' in routed) return failed('ORCHESTRATION_REVIEW_INVALID', routed.error, resolved.taskId);
703
+ if (invalidationBlocks(currentInvalidation)) {
704
+ return failed('ORCHESTRATION_INVALIDATION_INCOMPLETE', 'artifact invalidation is incomplete; reconcile task.md before routing downstream work', resolved.taskId);
705
+ }
706
+ let run: OrchestrationRun | null;
707
+ try {
708
+ run = readRun(resolved.taskDir, options);
709
+ } catch (error) {
710
+ return failed('ORCHESTRATION_STATE_INVALID', error instanceof Error ? error.message : String(error), resolved.taskId);
711
+ }
712
+ const facts = buildLifecycleFacts(
713
+ resolved.taskDir,
714
+ content,
715
+ resolved.state,
716
+ hasOpenLifecycleExecution(content) || Boolean(run?.pendingDelegation)
717
+ );
718
+ if (!facts.ok) return failed('ORCHESTRATION_CAPABILITY_FACTS_INVALID', facts.message, resolved.taskId);
719
+ const routed = routeFromFacts(facts.facts);
669
720
  if (!routed) return failed('ORCHESTRATION_ROUTE_UNKNOWN', 'cannot determine a unique lifecycle action', resolved.taskId);
670
- const run = readRun(resolved.taskDir);
671
- const policy = run ? rolePolicy(run, routed.role) : null;
672
- const next: OrchestrationNext = {
673
- ...routed,
674
- requestedModel: policy?.model ?? null,
675
- requestedReasoningEffort: policy?.reasoningEffort ?? null
676
- };
677
- if (next.stage === 'commit') {
721
+ if ('completion' in routed) {
678
722
  const reviewRound = highestRound(resolved.taskDir, 'review-code');
679
723
  const review = parseReviewSummary(fs.readFileSync(
680
724
  path.join(resolved.taskDir, artifactName('review-code', reviewRound)),
@@ -756,13 +800,25 @@ function routeOrchestration(taskRef: string, options: OrchestrationOptions = {})
756
800
  saveRun(resolved.taskDir, completed);
757
801
  return { status: 'completed', changed: true, taskId: resolved.taskId, run: completed, next: null, error: null };
758
802
  }
803
+ const action = routed.stage as LifecycleAction;
804
+ const capability = canStart(action, facts.facts, {
805
+ initiator: 'orchestrator', requestId: `orchestration:${resolved.taskId}:${routed.stage}:${routed.round}`,
806
+ requestedAction: action, reasonCode: 'user-request', explicitRequest: true
807
+ });
808
+ if (!capability.allowed) return failed('ORCHESTRATION_CAPABILITY_DENIED', `${capability.reasonCode}: ${capability.evidence.join(', ')}`, resolved.taskId);
809
+ const policy = run ? rolePolicy(run, routed.role) : null;
810
+ const next: OrchestrationNext = {
811
+ ...routed,
812
+ requestedModel: policy?.model ?? null,
813
+ requestedReasoningEffort: policy?.reasoningEffort ?? null
814
+ };
759
815
  return { status: 'running', changed: false, taskId: resolved.taskId, run, next, error: null };
760
816
  }
761
817
 
762
818
  function statusOrchestration(taskRef: string, options: OrchestrationOptions = {}): OrchestrationResult {
763
819
  const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
764
820
  if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
765
- const run = readRun(resolved.taskDir);
821
+ const run = readRun(resolved.taskDir, options);
766
822
  if (!run) return failed('ORCHESTRATION_RUN_MISSING', 'no orchestration run exists', resolved.taskId);
767
823
  return { status: run.status, changed: false, taskId: resolved.taskId, run, next: null, error: null };
768
824
  }
@@ -782,7 +838,15 @@ function prepareOrchestrationDelegationUnlocked(
782
838
  if (!(options.supportsLifecycleDelegation ?? supportsLifecycleDelegation)(input.client)) {
783
839
  return failed('ORCHESTRATION_CLIENT_UNSUPPORTED', `client '${input.client}' does not support lifecycle orchestration`, resolved.taskId);
784
840
  }
785
- const run = readRun(resolved.taskDir);
841
+ emitDiagnostic(options, 'orchestration-prepare-start', {
842
+ taskId: resolved.taskId,
843
+ taskDir: resolved.taskDir,
844
+ repoRoot: resolved.repoRoot,
845
+ client: input.client,
846
+ requestedModel: input.requestedModel ?? null,
847
+ requestedReasoningEffort: input.requestedReasoningEffort ?? null
848
+ });
849
+ const run = readRun(resolved.taskDir, options);
786
850
  if (!run || run.status !== 'running') return failed('ORCHESTRATION_RUN_NOT_RUNNING', 'a running orchestration is required', resolved.taskId);
787
851
  if (run.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_BUSY', 'the run already has a pending delegation', resolved.taskId);
788
852
  const repositoryPending = matchingDelegations(() => true, options);
@@ -895,7 +959,7 @@ function dispatchOrchestrationDelegationUnlocked(
895
959
  ): OrchestrationResult {
896
960
  const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
897
961
  if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
898
- const run = readRun(resolved.taskDir);
962
+ const run = readRun(resolved.taskDir, options);
899
963
  if (!run?.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
900
964
  if (run.status !== 'running') {
901
965
  return failed('ORCHESTRATION_STATE_INVALID', 'spawn dispatch requires a running orchestration', resolved.taskId);
@@ -941,16 +1005,42 @@ function matchingDelegations(
941
1005
  const repoRoot = options.repoRoot ?? process.cwd();
942
1006
  const activeRoot = path.join(repoRoot, '.agents', 'workspace', 'active');
943
1007
  if (!fs.existsSync(activeRoot)) return [];
944
- return fs.readdirSync(activeRoot, { withFileTypes: true })
1008
+ emitDiagnostic(options, 'orchestration-active-scan-start', {
1009
+ activeRoot
1010
+ });
1011
+ const matches = fs.readdirSync(activeRoot, { withFileTypes: true })
945
1012
  .filter((entry) => entry.isDirectory())
946
1013
  .flatMap((entry) => {
947
- const run = readRun(path.join(activeRoot, entry.name));
1014
+ const candidateTaskId = entry.name;
1015
+ const candidateTaskDir = path.join(activeRoot, candidateTaskId);
1016
+ emitDiagnostic(options, 'orchestration-active-scan-candidate', {
1017
+ candidateTaskId,
1018
+ candidateTaskDir,
1019
+ orchestrationPath: orchestrationPath(candidateTaskDir)
1020
+ });
1021
+ let run: OrchestrationRun | null;
1022
+ try {
1023
+ run = readRun(candidateTaskDir, options);
1024
+ } catch (error) {
1025
+ emitDiagnostic(options, 'orchestration-active-scan-candidate-failed', {
1026
+ candidateTaskId,
1027
+ candidateTaskDir,
1028
+ errorType: error instanceof Error ? error.name : typeof error,
1029
+ reasonCodes: error instanceof OrchestrationStateError ? error.reasonCodes.join(',') : null
1030
+ });
1031
+ throw error;
1032
+ }
948
1033
  if (!run || run.status !== 'running' || !run.pendingDelegation) return [];
949
1034
  const receipt = run.pendingDelegation;
950
1035
  return predicate(receipt)
951
- ? [{ taskId: entry.name, run }]
1036
+ ? [{ taskId: candidateTaskId, run }]
952
1037
  : [];
953
1038
  });
1039
+ emitDiagnostic(options, 'orchestration-active-scan-finished', {
1040
+ activeRoot,
1041
+ matchingDelegations: matches.length
1042
+ });
1043
+ return matches;
954
1044
  }
955
1045
 
956
1046
  function uniqueMatchingDelegation(
@@ -1196,7 +1286,7 @@ function activateOrchestrationDelegation(
1196
1286
  ): OrchestrationResult {
1197
1287
  const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
1198
1288
  if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
1199
- const run = readRun(resolved.taskDir);
1289
+ const run = readRun(resolved.taskDir, options);
1200
1290
  if (!run?.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
1201
1291
  if (run.status !== 'running') {
1202
1292
  return { status: run.status, changed: false, taskId: resolved.taskId, run, next: null, error: null };
@@ -1224,7 +1314,7 @@ async function awaitOrchestrationDelegationActivation(
1224
1314
  while (true) {
1225
1315
  const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
1226
1316
  if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
1227
- const run = readRun(resolved.taskDir);
1317
+ const run = readRun(resolved.taskDir, options);
1228
1318
  if (!run?.pendingDelegation) {
1229
1319
  return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
1230
1320
  }
@@ -1290,7 +1380,7 @@ function recoverPreparedOrchestrationDelegation(
1290
1380
  if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
1291
1381
  try {
1292
1382
  return withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-orchestration.recover-prepared', () => {
1293
- const run = readRun(resolved.taskDir);
1383
+ const run = readRun(resolved.taskDir, options);
1294
1384
  const receipt = run?.pendingDelegation;
1295
1385
  if (!run || !receipt) {
1296
1386
  return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
@@ -1362,7 +1452,7 @@ function completeOrchestrationStage(
1362
1452
  ): OrchestrationResult {
1363
1453
  const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
1364
1454
  if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
1365
- const run = readRun(resolved.taskDir);
1455
+ const run = readRun(resolved.taskDir, options);
1366
1456
  if (!run) return { status: 'running', changed: false, taskId: resolved.taskId, run: null, next: null, error: null };
1367
1457
  if (!run.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_MISSING', 'active run has no pending delegation', resolved.taskId);
1368
1458
  const result = completeDelegationStage(run.pendingDelegation, event);
@@ -1381,7 +1471,7 @@ function inspectOrchestrationStage(
1381
1471
  if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
1382
1472
  let run: OrchestrationRun | null;
1383
1473
  try {
1384
- run = readRun(resolved.taskDir);
1474
+ run = readRun(resolved.taskDir, options);
1385
1475
  } catch (error) {
1386
1476
  return failed('ORCHESTRATION_STATE_INVALID', error instanceof Error ? error.message : String(error), resolved.taskId);
1387
1477
  }
@@ -1442,7 +1532,7 @@ function sealOrchestrationDelegation(
1442
1532
  ): OrchestrationResult {
1443
1533
  const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
1444
1534
  if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
1445
- const run = readRun(resolved.taskDir);
1535
+ const run = readRun(resolved.taskDir, options);
1446
1536
  if (!run?.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
1447
1537
  const result = sealDelegation(run.pendingDelegation, event, { now: options.now });
1448
1538
  if (!result.ok) return pauseOrchestration(taskRef, result.code, result.message, true, options);
@@ -1454,7 +1544,7 @@ function sealOrchestrationDelegation(
1454
1544
  function advanceOrchestration(taskRef: string, options: OrchestrationOptions = {}): OrchestrationResult {
1455
1545
  const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
1456
1546
  if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
1457
- const run = readRun(resolved.taskDir);
1547
+ const run = readRun(resolved.taskDir, options);
1458
1548
  if (!run?.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
1459
1549
  const result = consumeDelegation(run.pendingDelegation, { now: options.now });
1460
1550
  if (!result.ok) return pauseOrchestration(taskRef, result.code, result.message, true, options);
@@ -1481,7 +1571,7 @@ function pauseOrchestration(
1481
1571
  ): OrchestrationResult {
1482
1572
  const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
1483
1573
  if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
1484
- const run = readRun(resolved.taskDir);
1574
+ const run = readRun(resolved.taskDir, options);
1485
1575
  if (!run) return failed('ORCHESTRATION_RUN_MISSING', 'no orchestration run exists', resolved.taskId);
1486
1576
  const updated = withUpdatedRun(run, { status: 'paused', pause: { code, message, recoverable } });
1487
1577
  saveRun(resolved.taskDir, updated);