@fitlab-ai/agent-infra 0.9.13 → 0.9.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (428) hide show
  1. package/README.md +10 -0
  2. package/README.zh-CN.md +10 -0
  3. package/bin/cli.ts +26 -9
  4. package/bin/internal-cli.sh +45 -0
  5. package/dist/bin/cli.js +173 -157
  6. package/dist/bin/internal-cli.js +126 -42
  7. package/dist/lib/agent-client.js +5 -0
  8. package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +165 -27
  9. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +3 -2
  10. package/dist/lib/defaults.json +103 -103
  11. package/dist/lib/fs/durable-write.js +37 -0
  12. package/dist/lib/fs/file-lock.js +111 -0
  13. package/dist/lib/host-control/audit.js +19 -0
  14. package/dist/lib/host-control/client.js +142 -0
  15. package/dist/lib/host-control/command.js +49 -0
  16. package/dist/lib/host-control/path.js +160 -0
  17. package/dist/lib/host-control/secure-fs.js +140 -0
  18. package/dist/lib/host-control/server.js +159 -0
  19. package/dist/lib/host-control/service.js +112 -0
  20. package/dist/lib/init.js +11 -2
  21. package/dist/lib/internal/agent-client.js +5 -2
  22. package/dist/lib/internal/cli-route-inventory.js +154 -0
  23. package/dist/lib/internal/codex-lifecycle.js +15 -12
  24. package/dist/lib/internal/codex-sandbox-controller.js +8 -2
  25. package/dist/lib/internal/demo-promotion.js +322 -0
  26. package/dist/lib/internal/demo-transcript.js +454 -0
  27. package/dist/lib/internal/git-workflow.js +10 -6
  28. package/dist/lib/internal/host-control.js +28 -0
  29. package/dist/lib/internal/manual-validation.js +322 -0
  30. package/dist/lib/internal/platform-checks.js +16 -4
  31. package/dist/lib/internal/platform-comment.js +16 -4
  32. package/dist/lib/internal/platform-context.js +4 -1
  33. package/dist/lib/internal/platform-issue.js +12 -4
  34. package/dist/lib/internal/platform-metadata.js +88 -0
  35. package/dist/lib/internal/platform-pr-review.js +16 -3
  36. package/dist/lib/internal/platform-pr.js +42 -14
  37. package/dist/lib/internal/platform-release-notes.js +6 -3
  38. package/dist/lib/internal/platform-security.js +93 -0
  39. package/dist/lib/internal/pr-review-grade.js +14 -3
  40. package/dist/lib/internal/release-workflow.js +82 -89
  41. package/dist/lib/internal/sandbox-control.js +171 -7
  42. package/dist/lib/internal/task-activity.js +13 -4
  43. package/dist/lib/internal/task-artifact.js +19 -107
  44. package/dist/lib/internal/task-context.js +4 -1
  45. package/dist/lib/internal/task-create.js +48 -14
  46. package/dist/lib/internal/task-delivery.js +4 -1
  47. package/dist/lib/internal/task-event.js +38 -35
  48. package/dist/lib/internal/task-finalization.js +4 -1
  49. package/dist/lib/internal/task-invalidation.js +4 -1
  50. package/dist/lib/internal/task-ledger.js +12 -1
  51. package/dist/lib/internal/task-lifecycle.js +4 -1
  52. package/dist/lib/internal/task-operation-registry.js +519 -0
  53. package/dist/lib/internal/task-orchestration.js +12 -0
  54. package/dist/lib/internal/task-override.js +10 -3
  55. package/dist/lib/internal/task-qualification.js +90 -0
  56. package/dist/lib/internal/task-review.js +10 -52
  57. package/dist/lib/internal/task-short-id.js +11 -1
  58. package/dist/lib/internal/task-snapshot.js +4 -1
  59. package/dist/lib/internal/task-validate.js +37 -12
  60. package/dist/lib/internal/task-verify.js +5 -1
  61. package/dist/lib/internal/task-warning.js +8 -1
  62. package/dist/lib/owned-path.js +33 -0
  63. package/dist/lib/platform/check-status.js +11 -0
  64. package/dist/lib/platform/comment-safety.js +229 -0
  65. package/dist/lib/platform/completion-backfill.js +1 -1
  66. package/dist/lib/platform/github-data.js +241 -0
  67. package/dist/lib/platform/github-provider.js +248 -26
  68. package/dist/lib/platform/issue-comments.js +146 -34
  69. package/dist/lib/platform/issues.js +1 -179
  70. package/dist/lib/platform/pr-change-report.js +6 -12
  71. package/dist/lib/platform/pr-checks.js +12 -65
  72. package/dist/lib/platform/pr-summary.js +83 -10
  73. package/dist/lib/platform/provider-contract.d.ts +67 -1
  74. package/dist/lib/platform/provider-contract.js +6 -2
  75. package/dist/lib/platform/provider-validation.js +76 -3
  76. package/dist/lib/platform/pull-requests.js +117 -275
  77. package/dist/lib/platform/repository-metadata.js +377 -0
  78. package/dist/lib/platform/security-alerts.js +155 -0
  79. package/dist/lib/platform/snapshots.js +2 -0
  80. package/dist/lib/platform/verification-sync.js +154 -162
  81. package/dist/lib/process-data/index.js +7 -0
  82. package/dist/lib/release/workflow.js +1 -1
  83. package/dist/lib/run/index.js +5 -0
  84. package/dist/lib/sandbox/commands/control-status.js +22 -0
  85. package/dist/lib/sandbox/commands/create.js +39 -8
  86. package/dist/lib/sandbox/commands/ls.js +5 -0
  87. package/dist/lib/sandbox/commands/rm.js +3 -807
  88. package/dist/lib/sandbox/commands/show.js +16 -0
  89. package/dist/lib/sandbox/control/audit.js +203 -0
  90. package/dist/lib/sandbox/control/client.js +125 -12
  91. package/dist/lib/sandbox/control/completed-reentry.js +85 -0
  92. package/dist/lib/sandbox/control/container-identity.js +28 -31
  93. package/dist/lib/sandbox/control/executor.js +233 -34
  94. package/dist/lib/sandbox/control/finalization-response.js +27 -0
  95. package/dist/lib/sandbox/control/identity-sentinel.js +107 -0
  96. package/dist/lib/sandbox/control/lifecycle.js +656 -128
  97. package/dist/lib/sandbox/control/native-file-lock.js +85 -0
  98. package/dist/lib/sandbox/control/protocol.js +55 -4
  99. package/dist/lib/sandbox/control/server.js +720 -79
  100. package/dist/lib/sandbox/control/state.js +63 -3
  101. package/dist/lib/sandbox/control/task-view.js +183 -0
  102. package/dist/lib/sandbox/control/task-workflow.js +74 -0
  103. package/dist/lib/sandbox/control/workflow-executor.js +99 -0
  104. package/dist/lib/sandbox/engines/authority.js +289 -0
  105. package/dist/lib/sandbox/engines/docker-exact-discovery.js +97 -0
  106. package/dist/lib/sandbox/index.js +7 -2
  107. package/dist/lib/sandbox/recovery.js +49 -5
  108. package/dist/lib/sandbox/removal.js +1717 -0
  109. package/dist/lib/sandbox/task-cleanup.js +217 -0
  110. package/dist/lib/sandbox/workspace-view.js +15 -15
  111. package/dist/lib/sandbox/worktree-safety.js +4 -1
  112. package/dist/lib/server/index.js +8 -0
  113. package/dist/lib/task/activity-intent.js +2 -1
  114. package/dist/lib/task/activity-log.js +30 -24
  115. package/dist/lib/task/artifact-command.js +101 -0
  116. package/dist/lib/task/artifact-lifecycle.js +71 -40
  117. package/dist/lib/task/artifact-name.js +36 -0
  118. package/dist/lib/task/artifact-operations.js +474 -0
  119. package/dist/lib/task/artifact-receipts.js +3 -15
  120. package/dist/lib/task/artifact-repair-intent.js +130 -0
  121. package/dist/lib/task/artifact-schema.js +127 -0
  122. package/dist/lib/task/capabilities.js +83 -19
  123. package/dist/lib/task/codex-orchestration.js +71 -25
  124. package/dist/lib/task/commit-identity.js +28 -0
  125. package/dist/lib/task/commit-operation.js +2 -16
  126. package/dist/lib/task/control-authority.js +375 -5
  127. package/dist/lib/task/control-recovery.js +128 -0
  128. package/dist/lib/task/create-service.js +103 -4
  129. package/dist/lib/task/create.js +80 -2
  130. package/dist/lib/task/decision-details.js +2 -46
  131. package/dist/lib/task/events.js +306 -76
  132. package/dist/lib/task/finalization-state.js +9 -0
  133. package/dist/lib/task/human-override.js +3 -6
  134. package/dist/lib/task/implementation-inputs.js +3 -3
  135. package/dist/lib/task/index.js +11 -3
  136. package/dist/lib/task/intermediate-cleanup.js +383 -0
  137. package/dist/lib/task/invalidation.js +18 -65
  138. package/dist/lib/task/ledger-intents.js +7 -22
  139. package/dist/lib/task/ledger.js +1 -3
  140. package/dist/lib/task/lifecycle.js +19 -1
  141. package/dist/lib/task/local-artifact-finalization.js +190 -290
  142. package/dist/lib/task/manual-validation-completion.js +26 -0
  143. package/dist/lib/task/manual-validation-evidence.js +130 -0
  144. package/dist/lib/task/manual-validation-receipt.js +101 -0
  145. package/dist/lib/task/manual-validation-shared.js +40 -0
  146. package/dist/lib/task/manual-validation-transaction.js +243 -0
  147. package/dist/lib/task/markdown.js +47 -0
  148. package/dist/lib/task/orchestration.js +206 -69
  149. package/dist/lib/task/qualification-audit.js +476 -0
  150. package/dist/lib/task/qualification-confirmation.js +109 -0
  151. package/dist/lib/task/qualification-intents.js +148 -0
  152. package/dist/lib/task/review-artifacts.js +23 -40
  153. package/dist/lib/task/review-command.js +25 -0
  154. package/dist/lib/task/review-finalization.js +146 -97
  155. package/dist/lib/task/review-fingerprint.js +2 -2
  156. package/dist/lib/task/sections.js +34 -54
  157. package/dist/lib/task/verification-config.js +11 -0
  158. package/dist/lib/task/verification-engine.js +170 -327
  159. package/dist/lib/task/verification.js +1 -1
  160. package/dist/lib/task/workflow-command.js +17 -0
  161. package/dist/lib/task/workflow-warning-intents.js +0 -16
  162. package/dist/lib/task/workflow-warnings.js +28 -2
  163. package/dist/lib/update.js +2 -0
  164. package/dist/lifecycle-build-manifest.json +3 -3
  165. package/lib/agent-client.ts +9 -0
  166. package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +223 -33
  167. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +3 -2
  168. package/lib/fs/durable-write.ts +29 -0
  169. package/lib/fs/file-lock.ts +113 -0
  170. package/lib/host-control/audit.ts +22 -0
  171. package/lib/host-control/client.ts +172 -0
  172. package/lib/host-control/command.ts +60 -0
  173. package/lib/host-control/path.ts +167 -0
  174. package/lib/host-control/secure-fs.ts +135 -0
  175. package/lib/host-control/server.ts +180 -0
  176. package/lib/host-control/service.ts +133 -0
  177. package/lib/init.ts +15 -2
  178. package/lib/internal/agent-client.ts +4 -2
  179. package/lib/internal/cli-route-inventory.ts +142 -0
  180. package/lib/internal/codex-lifecycle.ts +14 -12
  181. package/lib/internal/codex-sandbox-controller.ts +7 -2
  182. package/lib/internal/demo-promotion.ts +354 -0
  183. package/lib/internal/demo-transcript.ts +419 -0
  184. package/lib/internal/git-workflow.ts +9 -6
  185. package/lib/internal/host-control.ts +28 -0
  186. package/lib/internal/manual-validation.ts +306 -0
  187. package/lib/internal/platform-checks.ts +12 -4
  188. package/lib/internal/platform-comment.ts +12 -4
  189. package/lib/internal/platform-context.ts +3 -1
  190. package/lib/internal/platform-issue.ts +11 -4
  191. package/lib/internal/platform-metadata.ts +70 -0
  192. package/lib/internal/platform-pr-review.ts +14 -3
  193. package/lib/internal/platform-pr.ts +38 -14
  194. package/lib/internal/platform-release-notes.ts +5 -3
  195. package/lib/internal/platform-security.ts +83 -0
  196. package/lib/internal/pr-review-grade.ts +10 -3
  197. package/lib/internal/release-workflow.ts +91 -87
  198. package/lib/internal/sandbox-control.ts +181 -6
  199. package/lib/internal/task-activity.ts +12 -4
  200. package/lib/internal/task-artifact.ts +15 -79
  201. package/lib/internal/task-context.ts +3 -1
  202. package/lib/internal/task-create.ts +76 -15
  203. package/lib/internal/task-delivery.ts +3 -1
  204. package/lib/internal/task-event.ts +21 -10
  205. package/lib/internal/task-finalization.ts +3 -1
  206. package/lib/internal/task-invalidation.ts +3 -1
  207. package/lib/internal/task-ledger.ts +11 -1
  208. package/lib/internal/task-lifecycle.ts +3 -1
  209. package/lib/internal/task-operation-registry.ts +590 -0
  210. package/lib/internal/task-orchestration.ts +12 -0
  211. package/lib/internal/task-override.ts +9 -3
  212. package/lib/internal/task-qualification.ts +61 -0
  213. package/lib/internal/task-review.ts +7 -50
  214. package/lib/internal/task-short-id.ts +10 -1
  215. package/lib/internal/task-snapshot.ts +3 -1
  216. package/lib/internal/task-validate.ts +32 -12
  217. package/lib/internal/task-verify.ts +4 -1
  218. package/lib/internal/task-warning.ts +7 -1
  219. package/lib/owned-path.ts +26 -0
  220. package/lib/platform/check-status.ts +9 -0
  221. package/lib/platform/comment-safety.ts +255 -0
  222. package/lib/platform/completion-backfill.ts +1 -1
  223. package/lib/platform/github-data.ts +322 -0
  224. package/lib/platform/github-provider.ts +244 -27
  225. package/lib/platform/issue-comments.ts +159 -35
  226. package/lib/platform/issues.ts +4 -245
  227. package/lib/platform/pr-change-report.ts +6 -12
  228. package/lib/platform/pr-checks.ts +13 -77
  229. package/lib/platform/pr-summary.ts +88 -11
  230. package/lib/platform/provider-contract.ts +78 -3
  231. package/lib/platform/provider-validation.ts +85 -3
  232. package/lib/platform/pull-requests.ts +129 -348
  233. package/lib/platform/repository-metadata.ts +453 -0
  234. package/lib/platform/security-alerts.ts +191 -0
  235. package/lib/platform/snapshots.ts +53 -0
  236. package/lib/platform/verification-sync.ts +171 -177
  237. package/lib/process-data/index.ts +7 -0
  238. package/lib/release/workflow.ts +3 -3
  239. package/lib/run/index.ts +5 -0
  240. package/lib/sandbox/commands/control-status.ts +26 -0
  241. package/lib/sandbox/commands/create.ts +53 -12
  242. package/lib/sandbox/commands/ls.ts +7 -0
  243. package/lib/sandbox/commands/rm.ts +3 -996
  244. package/lib/sandbox/commands/show.ts +16 -0
  245. package/lib/sandbox/control/audit.ts +253 -0
  246. package/lib/sandbox/control/client.ts +150 -13
  247. package/lib/sandbox/control/completed-reentry.ts +98 -0
  248. package/lib/sandbox/control/container-identity.ts +27 -43
  249. package/lib/sandbox/control/executor.ts +262 -37
  250. package/lib/sandbox/control/finalization-response.ts +29 -0
  251. package/lib/sandbox/control/identity-sentinel.ts +137 -0
  252. package/lib/sandbox/control/lifecycle.ts +672 -18
  253. package/lib/sandbox/control/native-file-lock.ts +108 -0
  254. package/lib/sandbox/control/protocol.ts +80 -8
  255. package/lib/sandbox/control/server.ts +779 -82
  256. package/lib/sandbox/control/state.ts +84 -3
  257. package/lib/sandbox/control/task-view.ts +240 -0
  258. package/lib/sandbox/control/task-workflow.ts +95 -0
  259. package/lib/sandbox/control/workflow-executor.ts +102 -0
  260. package/lib/sandbox/engines/authority.ts +365 -0
  261. package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
  262. package/lib/sandbox/index.ts +9 -2
  263. package/lib/sandbox/recovery.ts +49 -6
  264. package/lib/sandbox/removal.ts +2144 -0
  265. package/lib/sandbox/task-cleanup.ts +209 -0
  266. package/lib/sandbox/workspace-view.ts +26 -18
  267. package/lib/sandbox/worktree-safety.ts +4 -1
  268. package/lib/server/index.ts +10 -0
  269. package/lib/task/activity-intent.ts +2 -2
  270. package/lib/task/activity-log.ts +27 -19
  271. package/lib/task/artifact-command.ts +104 -0
  272. package/lib/task/artifact-lifecycle.ts +66 -39
  273. package/lib/task/artifact-name.ts +55 -0
  274. package/lib/task/artifact-operations.ts +580 -0
  275. package/lib/task/artifact-receipts.ts +3 -14
  276. package/lib/task/artifact-repair-intent.ts +152 -0
  277. package/lib/task/artifact-schema.ts +163 -0
  278. package/lib/task/capabilities.ts +82 -22
  279. package/lib/task/codex-orchestration.ts +85 -24
  280. package/lib/task/commit-identity.ts +31 -0
  281. package/lib/task/commit-operation.ts +2 -16
  282. package/lib/task/control-authority.ts +513 -6
  283. package/lib/task/control-recovery.ts +174 -0
  284. package/lib/task/create-service.ts +131 -6
  285. package/lib/task/create.ts +83 -1
  286. package/lib/task/decision-details.ts +3 -71
  287. package/lib/task/events.ts +292 -75
  288. package/lib/task/finalization-state.ts +11 -0
  289. package/lib/task/human-override.ts +3 -8
  290. package/lib/task/implementation-inputs.ts +3 -3
  291. package/lib/task/index.ts +16 -3
  292. package/lib/task/intermediate-cleanup.ts +455 -0
  293. package/lib/task/invalidation.ts +18 -62
  294. package/lib/task/ledger-intents.ts +7 -24
  295. package/lib/task/ledger.ts +1 -3
  296. package/lib/task/lifecycle.ts +17 -1
  297. package/lib/task/local-artifact-finalization.ts +223 -388
  298. package/lib/task/manual-validation-completion.ts +40 -0
  299. package/lib/task/manual-validation-evidence.ts +209 -0
  300. package/lib/task/manual-validation-receipt.ts +152 -0
  301. package/lib/task/manual-validation-shared.ts +50 -0
  302. package/lib/task/manual-validation-transaction.ts +304 -0
  303. package/lib/task/markdown.ts +70 -0
  304. package/lib/task/orchestration.ts +191 -68
  305. package/lib/task/qualification-audit.ts +588 -0
  306. package/lib/task/qualification-confirmation.ts +117 -0
  307. package/lib/task/qualification-intents.ts +150 -0
  308. package/lib/task/review-artifacts.ts +21 -41
  309. package/lib/task/review-command.ts +23 -0
  310. package/lib/task/review-finalization.ts +154 -153
  311. package/lib/task/review-fingerprint.ts +2 -2
  312. package/lib/task/sections.ts +33 -52
  313. package/lib/task/verification-config.ts +12 -0
  314. package/lib/task/verification-engine.ts +165 -370
  315. package/lib/task/verification-types.ts +17 -0
  316. package/lib/task/verification.ts +1 -1
  317. package/lib/task/workflow-command.ts +18 -0
  318. package/lib/task/workflow-warning-intents.ts +0 -13
  319. package/lib/task/workflow-warnings.ts +21 -2
  320. package/lib/update.ts +6 -0
  321. package/package.json +7 -2
  322. package/templates/.agents/hooks/lifecycle-delegation.js +6 -6
  323. package/templates/.agents/rules/README.en.md +2 -0
  324. package/templates/.agents/rules/README.zh-CN.md +2 -0
  325. package/templates/.agents/rules/decision-qualification.en.md +22 -0
  326. package/templates/.agents/rules/decision-qualification.zh-CN.md +22 -0
  327. package/templates/.agents/rules/evidence-reporting.en.md +28 -0
  328. package/templates/.agents/rules/evidence-reporting.zh-CN.md +28 -0
  329. package/templates/.agents/rules/label-milestone-setup.en.md +7 -7
  330. package/templates/.agents/rules/label-milestone-setup.zh-CN.md +7 -7
  331. package/templates/.agents/rules/local-artifact-repair.en.md +5 -1
  332. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +5 -1
  333. package/templates/.agents/rules/security-alerts.en.md +8 -8
  334. package/templates/.agents/rules/security-alerts.zh-CN.md +8 -8
  335. package/templates/.agents/rules/testing-discipline.en.md +2 -0
  336. package/templates/.agents/rules/testing-discipline.zh-CN.md +2 -0
  337. package/templates/.agents/scripts/package.json +3 -0
  338. package/templates/.agents/skills/analyze-task/SKILL.en.md +15 -2
  339. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +19 -2
  340. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -12
  341. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -12
  342. package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
  343. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
  344. package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
  345. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
  346. package/templates/.agents/skills/code-task/SKILL.en.md +14 -1
  347. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +14 -1
  348. package/templates/.agents/skills/code-task/config/verify.en.json +5 -14
  349. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +5 -14
  350. package/templates/.agents/skills/code-task/reference/code-rules.en.md +5 -4
  351. package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +5 -4
  352. package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
  353. package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
  354. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +3 -1
  355. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +3 -1
  356. package/templates/.agents/skills/code-task/reference/report-template.en.md +42 -15
  357. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +39 -12
  358. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +37 -21
  359. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +37 -21
  360. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
  361. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
  362. package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +4 -0
  363. package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +4 -0
  364. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +16 -7
  365. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +16 -7
  366. package/templates/.agents/skills/complete-task/SKILL.en.md +10 -23
  367. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +10 -23
  368. package/templates/.agents/skills/create-task/SKILL.en.md +8 -0
  369. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +7 -0
  370. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  371. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  372. package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
  373. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
  374. package/templates/.agents/skills/init-labels/SKILL.en.md +8 -8
  375. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +8 -8
  376. package/templates/.agents/skills/init-milestones/SKILL.en.md +9 -11
  377. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +9 -11
  378. package/templates/.agents/skills/plan-task/SKILL.en.md +14 -1
  379. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +16 -1
  380. package/templates/.agents/skills/plan-task/config/verify.en.json +4 -14
  381. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +4 -14
  382. package/templates/.agents/skills/release/SKILL.en.md +7 -3
  383. package/templates/.agents/skills/release/SKILL.zh-CN.md +7 -3
  384. package/templates/.agents/skills/review-analysis/SKILL.en.md +14 -1
  385. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +14 -1
  386. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -18
  387. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -18
  388. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +50 -23
  389. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +45 -18
  390. package/templates/.agents/skills/review-code/SKILL.en.md +14 -1
  391. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +14 -1
  392. package/templates/.agents/skills/review-code/config/verify.en.json +1 -23
  393. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -23
  394. package/templates/.agents/skills/review-code/reference/report-template.en.md +49 -22
  395. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +45 -18
  396. package/templates/.agents/skills/review-plan/SKILL.en.md +14 -1
  397. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +14 -1
  398. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -18
  399. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -18
  400. package/templates/.agents/skills/review-plan/reference/report-template.en.md +49 -22
  401. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +45 -18
  402. package/templates/.agents/skills/review-pr/SKILL.en.md +5 -1
  403. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +5 -1
  404. package/templates/.agents/skills/review-pr/reference/report-template.en.md +4 -3
  405. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +4 -3
  406. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +25 -4
  407. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +25 -4
  408. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +4 -1
  409. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +4 -1
  410. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +5 -1
  411. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +5 -1
  412. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  413. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  414. package/templates/.agents/skills/test/SKILL.en.md +29 -7
  415. package/templates/.agents/skills/test/SKILL.zh-CN.md +29 -7
  416. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +14 -0
  417. package/templates/.agents/templates/task.en.md +6 -0
  418. package/templates/.agents/templates/task.zh-CN.md +6 -0
  419. package/templates/.claude/commands/run-manual-validation.en.md +1 -1
  420. package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
  421. package/dist/lib/platform/adapters.js +0 -56
  422. package/lib/platform/adapters.ts +0 -197
  423. package/templates/.agents/scripts/security-alerts.github.sh +0 -151
  424. package/templates/.agents/scripts/security-alerts.sh +0 -31
  425. package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +0 -146
  426. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +0 -32
  427. package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +0 -294
  428. package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +0 -6
@@ -1,7 +1,8 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { appendActivityEntry, locateActivityLog, pairEntries, startedBackedRows } from './activity-log.js';
4
- import { buildArtifactLinkSection, artifactName, inspectArtifactDirectory, parseReviewedInputReference, parseCodePlanInputReference, parseArtifactName, resolveArtifactContext, validateCompletedArtifact } from './artifact-lifecycle.js';
4
+ import { buildArtifactLinkSection, inspectArtifactDirectory, parseReviewedInputReference, parseCodePlanInputReference, resolveArtifactContext, validateCompletedArtifact } from './artifact-lifecycle.js';
5
+ import { artifactName, parseArtifactName } from './artifact-name.js';
5
6
  import { ArtifactReceiptError, parseArtifactReceipts, sha256File, upsertArtifactReceipt } from './artifact-receipts.js';
6
7
  import { parseTypedTaskFrontmatter } from './frontmatter.js';
7
8
  import { consumeImplementationInput, IMPLEMENTATION_INPUT_ALIASES, parseImplementationInputs, renderImplementationInputs } from './implementation-inputs.js';
@@ -14,11 +15,16 @@ import { commitOrchestrationStageCompletion } from './orchestration.js';
14
15
  import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.js';
15
16
  import { captureTaskWriteMetadata, writeTask } from './write.js';
16
17
  import { allowsManualOverride } from './guard-override.js';
17
- import { LOCAL_ARTIFACT_REQUIRED_PATTERNS, LOCAL_ARTIFACT_REQUIRED_SECTIONS, consumeLocalArtifactFinalizationIntent, readLocalArtifactFinalizationIntent, validateLocalArtifact } from './local-artifact-finalization.js';
18
- import { loadVerificationConfig } from './verification-config.js';
18
+ import { consumeLocalArtifactFinalizationIntent, readLocalArtifactFinalizationIntent, validateLocalArtifact } from './local-artifact-finalization.js';
19
+ import { writeArtifactRepairIntent } from './artifact-repair-intent.js';
19
20
  import { buildLifecycleFacts, canStart } from './capabilities.js';
20
21
  import { createInvalidationOperation, invalidationMutation, parseInvalidationDocument, targetIdFor, upsertInvalidation } from './invalidation.js';
21
22
  import { consumeReworkIntents, parseReworkIntentDocument, reworkIntentMutation, supersedeReworkIntents } from './rework-intent.js';
23
+ import { ARTIFACT_FAMILIES, expectedQualificationRelations, parseQualificationAudit, parseTaskQualification, upstreamArtifactDigest, validateQualificationAudit } from './qualification-audit.js';
24
+ import { getArtifactSchema } from './artifact-schema.js';
25
+ import { inspectArtifactContract } from './artifact-operations.js';
26
+ import { consumeLifecycleRecoveryAttestation, lifecycleRecoveryAttestationDigest, validateLifecycleRecoveryAttestation } from './control-authority.js';
27
+ import { readManualValidationCompletion } from './manual-validation-completion.js';
22
28
  const eventCatalog = [
23
29
  'analyze.started', 'analyze.awaiting-input', 'analyze.completed',
24
30
  'review-analysis.started', 'review-analysis.completed',
@@ -44,36 +50,11 @@ const SCHEMAS = {
44
50
  'code.completed': { required: ['artifact', 'artifactSha256', 'semanticDigest'], optional: ['round', 'fixFor', 'implementationInput', 'filesModified', 'testsPassed', 'blockers', 'major', 'minor', 'manualValidation', 'orchestrated'] },
45
51
  'review-code.started': { optional: ['round'] },
46
52
  'review-code.completed': { required: ['artifact', 'verdict', 'blockers', 'major', 'minor', 'manualValidation'], optional: ['round', 'orchestrated'] },
47
- 'manual-validation.started': { optional: ['round'] },
48
- 'manual-validation.completed': { required: ['artifact', 'summaryResult'], optional: ['round'] },
53
+ 'manual-validation.started': { optional: ['round', 'transactionId'] },
54
+ 'manual-validation.completed': { required: ['artifact', 'summaryResult', 'transactionId', 'receiptDigest', 'prHeadSha'], optional: ['round'] },
49
55
  'validation-run.started': { optional: ['round'] },
50
56
  'validation-run.completed': { required: ['artifact'], optional: ['round'] }
51
57
  };
52
- function localArtifactValidationConfig(repoRoot, family) {
53
- const fallback = {
54
- requiredSections: LOCAL_ARTIFACT_REQUIRED_SECTIONS[family],
55
- requiredPatterns: LOCAL_ARTIFACT_REQUIRED_PATTERNS
56
- };
57
- const skillName = family === 'analysis' ? 'analyze-task' : family === 'plan' ? 'plan-task' : 'code-task';
58
- try {
59
- const artifact = loadVerificationConfig(repoRoot, skillName).checks.artifact;
60
- if (!artifact || typeof artifact !== 'object' || Array.isArray(artifact))
61
- return fallback;
62
- const sections = artifact.required_sections;
63
- const patterns = artifact.required_patterns;
64
- return {
65
- requiredSections: Array.isArray(sections)
66
- ? sections.filter((value) => typeof value === 'string')
67
- : fallback.requiredSections,
68
- requiredPatterns: Array.isArray(patterns)
69
- ? patterns.filter((value) => typeof value === 'string')
70
- : fallback.requiredPatterns
71
- };
72
- }
73
- catch {
74
- return fallback;
75
- }
76
- }
77
58
  function validateTaskEventRequest(request) {
78
59
  if (!eventCatalog.includes(request.event))
79
60
  return { code: 'EVENT_UNKNOWN', message: `unknown task event '${request.event}'` };
@@ -115,7 +96,7 @@ function validateTaskEventRequest(request) {
115
96
  if (modeRequired.some((key) => request[key] === undefined) || forbidden.some((key) => request[key] !== undefined))
116
97
  return { code: 'EVENT_PAYLOAD_INVALID', message: 'code.completed requires either initial or fix completion payload' };
117
98
  }
118
- if (request.fixFor && !/^review-code(?:-r(?:[2-9]|[1-9]\d+))?\.md$/.test(request.fixFor))
99
+ if (request.fixFor && parseArtifactName(request.fixFor)?.family !== 'review-code')
119
100
  return { code: 'EVENT_PAYLOAD_INVALID', message: 'fixFor must reference a canonical review-code artifact' };
120
101
  if (request.implementationInput && !/^II-[1-9]\d*$/.test(request.implementationInput))
121
102
  return { code: 'EVENT_PAYLOAD_INVALID', message: 'implementationInput must be a canonical II-N id' };
@@ -127,6 +108,19 @@ function validateTaskEventRequest(request) {
127
108
  return { code: 'EVENT_PAYLOAD_INVALID', message: 'fixFor and implementationInput are mutually exclusive' };
128
109
  if (request.summaryResult !== undefined && (!request.summaryResult.trim() || /[\r\n]/.test(request.summaryResult)))
129
110
  return { code: 'EVENT_PAYLOAD_INVALID', message: 'summaryResult must be a non-empty single line' };
111
+ if (request.event === 'manual-validation.completed') {
112
+ for (const [name, value, pattern] of [
113
+ ['transactionId', request.transactionId, /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u],
114
+ ['receiptDigest', request.receiptDigest, /^[a-f0-9]{64}$/u],
115
+ ['prHeadSha', request.prHeadSha, /^[a-f0-9]{40}$/u]
116
+ ])
117
+ if (!value || !pattern.test(value))
118
+ return { code: 'EVENT_PAYLOAD_INVALID', message: `manual-validation.completed requires a valid ${name}` };
119
+ }
120
+ if (request.event === 'manual-validation.started' && request.transactionId !== undefined
121
+ && !/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(request.transactionId)) {
122
+ return { code: 'EVENT_PAYLOAD_INVALID', message: 'manual-validation.started requires a valid transactionId' };
123
+ }
130
124
  if (request.event !== 'analyze.awaiting-input' && /\.(?:started|completed)$/.test(request.event)) {
131
125
  if (!request.initiator || !request.requestId || !request.reasonCode) {
132
126
  return { code: 'EVENT_TRIGGER_REQUIRED', message: `${request.event} requires --initiator, --request-id, and --reason-code` };
@@ -225,7 +219,9 @@ function identity(request) {
225
219
  if (family === 'manual-validation') {
226
220
  return {
227
221
  family, phase, action: spec.label,
228
- note: phase === 'started' ? 'started' : `Manual validation passed → ${request.artifact}; ${request.summaryResult}`,
222
+ note: phase === 'started'
223
+ ? `started${request.transactionId ? `; transaction=${request.transactionId}` : ''}`
224
+ : `Manual validation passed → ${request.artifact}; ${request.summaryResult}; transaction=${request.transactionId}; receipt=${request.receiptDigest}; head=${request.prHeadSha}`,
229
225
  target: null
230
226
  };
231
227
  }
@@ -280,6 +276,24 @@ function normalizeStarted(request, repoRoot) {
280
276
  return { error: { code: 'EVENT_ARTIFACT_CONFLICT', message: `implementationInput '${request.implementationInput ?? ''}' conflicts with artifact context` }, context };
281
277
  return { request: { ...request, round, artifact: context.next.name, fixFor: expectedFix, implementationInput: expectedImplementation }, context };
282
278
  }
279
+ function validateManualValidationCompletion(taskDir, taskId, request, artifactPath) {
280
+ const completion = readManualValidationCompletion(taskDir, {
281
+ transactionId: request.transactionId,
282
+ taskId,
283
+ prHeadSha: request.prHeadSha,
284
+ artifact: request.artifact,
285
+ receiptDigest: request.receiptDigest
286
+ });
287
+ if (!completion.ok)
288
+ return completion.error;
289
+ const { receipt, transaction } = completion.value;
290
+ if (!['receipt-committed', 'final-promotion-in-progress', 'committed'].includes(transaction.phase)) {
291
+ return { code: 'MANUAL_VALIDATION_TRANSACTION_PHASE_INVALID', message: 'manual validation completion requires the receipt-backed transaction phase' };
292
+ }
293
+ if (sha256File(artifactPath) !== receipt.artifactSha256)
294
+ return { code: 'MANUAL_VALIDATION_RECEIPT_INVALID', message: 'manual-validation artifact digest does not match the receipt' };
295
+ return null;
296
+ }
283
297
  function openStartedIdentity(rows, family) {
284
298
  const spec = FAMILY[family];
285
299
  if (family === 'manual-validation') {
@@ -300,6 +314,24 @@ function openStartedIdentity(rows, family) {
300
314
  function reviewInputFamily(family) {
301
315
  return family === 'review-analysis' ? 'analysis' : family === 'review-plan' ? 'plan' : 'code';
302
316
  }
317
+ function relationForStartedInput(family, input) {
318
+ if (family.startsWith('review-')) {
319
+ return input.family === reviewInputFamily(family) ? 'reviewed-input' : 'approval-context';
320
+ }
321
+ const consumer = family === 'analyze' ? 'analysis' : family;
322
+ if ((consumer === 'plan' && input.family === 'analysis') || (consumer === 'code' && input.family === 'plan'))
323
+ return 'required-input';
324
+ return 'review-context';
325
+ }
326
+ function qualificationRelationsForStarted(family, inputs) {
327
+ return inputs.map((input) => ({
328
+ upstreamFamily: input.family,
329
+ upstreamArtifact: input.name,
330
+ upstreamRound: input.round,
331
+ upstreamSha256: sha256File(input.path),
332
+ relation: relationForStartedInput(family, input)
333
+ }));
334
+ }
303
335
  function lifecycleAction(family) {
304
336
  return family === 'analyze' ? 'analysis' : family;
305
337
  }
@@ -328,6 +360,7 @@ function invalidationMutationForCompletion(content, taskDir, family, artifact, t
328
360
  code: ['review-code']
329
361
  };
330
362
  const sourceFamily = family;
363
+ const sourceArtifactFamily = sourceFamily === 'analyze' ? 'analysis' : sourceFamily;
331
364
  let receipts = [];
332
365
  try {
333
366
  receipts = parseArtifactReceipts(content).rows;
@@ -335,46 +368,134 @@ function invalidationMutationForCompletion(content, taskDir, family, artifact, t
335
368
  catch (error) {
336
369
  return { error: error instanceof Error ? error.message : String(error) };
337
370
  }
338
- const targets = downstream[sourceFamily].flatMap((targetFamily) => {
339
- const names = fs.readdirSync(taskDir).filter((name) => {
340
- const pattern = targetFamily === 'review-analysis' ? /^review-analysis(?:-r\d+)?\.md$/
341
- : targetFamily === 'review-plan' ? /^review-plan(?:-r\d+)?\.md$/
342
- : targetFamily === 'review-code' ? /^review-code(?:-r\d+)?\.md$/
343
- : new RegExp(`^${targetFamily}(?:-r\\d+)?\\.md$`);
344
- return pattern.test(name);
345
- });
346
- return names.flatMap((name) => {
347
- try {
348
- const stat = fs.lstatSync(path.join(taskDir, name));
349
- if (!stat.isFile() || stat.isSymbolicLink())
350
- return [];
351
- const targetRound = parseArtifactName(name)?.round ?? 1;
352
- const targetSha256 = sha256File(path.join(taskDir, name));
353
- const shapes = [
354
- { targetKind: 'artifact', targetFamily, targetArtifact: name, targetRound, targetSha256 }
355
- ];
356
- const receipt = receipts.find((candidate) => candidate.output === name);
357
- if (receipt)
358
- shapes.push({
359
- targetKind: 'receipt', targetFamily, targetArtifact: name, targetRound,
360
- targetSha256: receipt.inputSha256
361
- });
362
- if (targetFamily.startsWith('review-')) {
363
- shapes.push({ targetKind: 'approval', targetFamily, targetArtifact: name, targetRound, targetSha256 });
364
- }
365
- if (targetFamily === 'review-code') {
366
- shapes.push({ targetKind: 'reviewed-snapshot', targetFamily, targetArtifact: name, targetRound, targetSha256 });
371
+ const inventory = fs.readdirSync(taskDir).flatMap((name) => {
372
+ const identity = parseArtifactName(name);
373
+ if (!identity || !ARTIFACT_FAMILIES.includes(identity.family))
374
+ return [];
375
+ try {
376
+ const stat = fs.lstatSync(path.join(taskDir, name));
377
+ if (!stat.isFile() || stat.isSymbolicLink())
378
+ return [];
379
+ return [{ family: identity.family, name, round: identity.round, sha256: sha256File(path.join(taskDir, name)) }];
380
+ }
381
+ catch (error) {
382
+ throw new Error(`cannot inspect invalidation artifact '${name}': ${error instanceof Error ? error.message : String(error)}`);
383
+ }
384
+ });
385
+ const taskQualification = parseTaskQualification(content);
386
+ if (!taskQualification.ok)
387
+ return { error: taskQualification.message };
388
+ const nodeMap = new Map(inventory.map((node) => [`${node.family}/${node.name}`, node]));
389
+ const audits = new Map();
390
+ let taskInputChanged = false;
391
+ let graphUsable = taskQualification.qualification.present;
392
+ if (graphUsable) {
393
+ for (const node of inventory) {
394
+ const artifactContent = fs.readFileSync(path.join(taskDir, node.name), 'utf8');
395
+ const parsedAudit = parseQualificationAudit(artifactContent);
396
+ if (!parsedAudit.ok || !parsedAudit.audit.present || !parsedAudit.audit.snapshot) {
397
+ graphUsable = false;
398
+ break;
399
+ }
400
+ audits.set(`${node.family}/${node.name}`, parsedAudit.audit);
401
+ if (parsedAudit.audit.snapshot.taskInputDigest !== taskQualification.qualification.taskInputDigest)
402
+ taskInputChanged = true;
403
+ if (parsedAudit.audit.snapshot.nonConstraintInputDigest !== taskQualification.qualification.nonConstraintInputDigest) {
404
+ graphUsable = false;
405
+ break;
406
+ }
407
+ if (parsedAudit.audit.snapshot.upstreamArtifactDigest !== upstreamArtifactDigest(parsedAudit.audit.upstreamRelations)) {
408
+ graphUsable = false;
409
+ break;
410
+ }
411
+ for (const relation of parsedAudit.audit.upstreamRelations) {
412
+ const upstream = nodeMap.get(`${relation.upstreamFamily}/${relation.upstreamArtifact}`);
413
+ if (!upstream || upstream.round !== relation.upstreamRound || upstream.sha256 !== relation.upstreamSha256) {
414
+ graphUsable = false;
415
+ break;
367
416
  }
368
- return shapes.map((targetShape) => ({
369
- ...targetShape,
370
- targetId: targetIdFor('pending', targetShape), operationId: 'pending', status: 'pending',
371
- reasonCode: 'upstream-replaced', updatedAt: timestamp
372
- }));
373
417
  }
374
- catch (error) {
375
- throw new Error(`cannot inspect invalidation target '${name}': ${error instanceof Error ? error.message : String(error)}`);
418
+ if (!graphUsable)
419
+ break;
420
+ }
421
+ }
422
+ const selected = new Set();
423
+ if (graphUsable) {
424
+ const changedConstraints = new Set();
425
+ for (const audit of audits.values()) {
426
+ for (const dependency of audit.constraintDependencies) {
427
+ const current = taskQualification.qualification.constraints.find((row) => row.constraintId === dependency.constraintId);
428
+ if (!current || current.digest !== dependency.constraintDigest)
429
+ changedConstraints.add(dependency.constraintId);
376
430
  }
377
- });
431
+ }
432
+ const currentCandidates = new Map(taskQualification.qualification.candidates.map((candidate) => [candidate.candidateId, candidate]));
433
+ const candidateSnapshotMatches = [...audits.values()].every((audit) => audit.candidateQualifications.length === currentCandidates.size && audit.candidateQualifications.every((row) => {
434
+ const current = currentCandidates.get(row.candidateId);
435
+ return Boolean(current && current.status === row.status && current.impact === row.impact
436
+ && current.evidence === row.evidence && current.constraintIds.join(',') === row.constraintIds.join(','));
437
+ }));
438
+ // A task-input digest also covers candidates. A narrowed invalidation graph
439
+ // is safe only when the old audit rows show that the candidate projection
440
+ // stayed unchanged and the change is explained by at least one constraint.
441
+ if (taskInputChanged && (changedConstraints.size === 0 || !candidateSnapshotMatches))
442
+ graphUsable = false;
443
+ for (const node of inventory) {
444
+ const audit = audits.get(`${node.family}/${node.name}`);
445
+ if (audit.constraintDependencies.some((dependency) => changedConstraints.has(dependency.constraintId)))
446
+ selected.add(`${node.family}/${node.name}`);
447
+ if (audit.upstreamRelations.some((relation) => relation.upstreamFamily === sourceArtifactFamily))
448
+ selected.add(`${node.family}/${node.name}`);
449
+ }
450
+ // Relation rows point from a consumer to its actual upstream artifact. Walk
451
+ // that reverse edge so review-only seeds and multi-hop consumers receive the
452
+ // same derived targets as ordinary executor seeds.
453
+ let changed = true;
454
+ while (changed) {
455
+ changed = false;
456
+ for (const node of inventory) {
457
+ const key = `${node.family}/${node.name}`;
458
+ const audit = audits.get(key);
459
+ if (audit.upstreamRelations.some((relation) => selected.has(`${relation.upstreamFamily}/${relation.upstreamArtifact}`)) && !selected.has(key)) {
460
+ selected.add(key);
461
+ changed = true;
462
+ }
463
+ }
464
+ }
465
+ // A relation cycle cannot establish a safe downstream closure.
466
+ const visiting = new Set();
467
+ const visited = new Set();
468
+ const hasCycle = (key) => {
469
+ if (visiting.has(key))
470
+ return true;
471
+ if (visited.has(key))
472
+ return false;
473
+ visiting.add(key);
474
+ const cycle = audits.get(key)?.upstreamRelations.some((relation) => hasCycle(`${relation.upstreamFamily}/${relation.upstreamArtifact}`)) ?? false;
475
+ visiting.delete(key);
476
+ visited.add(key);
477
+ return cycle;
478
+ };
479
+ if ([...nodeMap.keys()].some(hasCycle))
480
+ graphUsable = false;
481
+ }
482
+ const reasonCode = graphUsable ? 'qualification-changed' : 'upstream-replaced';
483
+ const targetNodes = (graphUsable
484
+ ? inventory.filter((node) => selected.has(`${node.family}/${node.name}`))
485
+ : inventory.filter((node) => downstream[sourceFamily].includes(node.family)))
486
+ .filter((node) => !(node.family === FAMILY[family].artifact && node.name === artifact.name));
487
+ const targets = targetNodes.flatMap((node) => {
488
+ const shapes = [
489
+ { targetKind: 'artifact', targetFamily: node.family, targetArtifact: node.name, targetRound: node.round, targetSha256: node.sha256 }
490
+ ];
491
+ const receipt = receipts.find((candidate) => candidate.output === node.name);
492
+ if (receipt)
493
+ shapes.push({ targetKind: 'receipt', targetFamily: node.family, targetArtifact: node.name, targetRound: node.round, targetSha256: receipt.inputSha256 });
494
+ if (node.family.startsWith('review-'))
495
+ shapes.push({ targetKind: 'approval', targetFamily: node.family, targetArtifact: node.name, targetRound: node.round, targetSha256: node.sha256 });
496
+ if (node.family === 'review-code')
497
+ shapes.push({ targetKind: 'reviewed-snapshot', targetFamily: node.family, targetArtifact: node.name, targetRound: node.round, targetSha256: node.sha256 });
498
+ return shapes.map((targetShape) => ({ ...targetShape, targetId: targetIdFor('pending', targetShape), operationId: 'pending', status: 'pending', reasonCode, updatedAt: timestamp }));
378
499
  });
379
500
  if (targets.length === 0)
380
501
  return { mutation: null };
@@ -539,6 +660,11 @@ function applyTaskEventUnlocked(request, options = {}) {
539
660
  if (openIdentity) {
540
661
  if (openIdentity.row.agent !== request.agent)
541
662
  return failed(request, { code: 'EVENT_LOG_CONFLICT', message: 'open started event has a different agent' }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
663
+ if (initialParts.family === 'manual-validation' && request.transactionId !== undefined) {
664
+ const existingTransactionId = /(?:^|;\s*)transaction=([A-Za-z0-9][A-Za-z0-9._-]{0,127})(?:;|$)/u.exec(openIdentity.row.note)?.[1];
665
+ if (existingTransactionId !== undefined && existingTransactionId !== request.transactionId)
666
+ return failed(request, { code: 'EVENT_LOG_CONFLICT', message: 'open manual-validation started event has a different transactionId' }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
667
+ }
542
668
  if (request.round !== undefined && request.round !== openIdentity.round)
543
669
  return failed(request, { code: 'EVENT_ARTIFACT_CONFLICT', message: `round ${request.round} conflicts with open round ${openIdentity.round}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
544
670
  if (request.fixFor !== undefined && request.fixFor !== openIdentity.fixFor)
@@ -560,6 +686,25 @@ function applyTaskEventUnlocked(request, options = {}) {
560
686
  normalized = { ...request, round: identity.round };
561
687
  }
562
688
  const eventIdentity = identity(normalized);
689
+ const lifecycleAuthority = options.lifecycleRecoveryAttestation ?? null;
690
+ if (lifecycleAuthority) {
691
+ try {
692
+ validateLifecycleRecoveryAttestation(lifecycleAuthority);
693
+ }
694
+ catch (error) {
695
+ return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: error instanceof Error ? error.message : String(error) }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
696
+ }
697
+ const expectedFamily = eventIdentity.family === 'analyze' ? 'analysis' : eventIdentity.family;
698
+ if (eventIdentity.phase !== 'completed'
699
+ || lifecycleAuthority.phase !== 'task-event.completed'
700
+ || lifecycleAuthority.taskId !== resolved.taskId
701
+ || lifecycleAuthority.family !== expectedFamily
702
+ || lifecycleAuthority.artifact !== normalized.artifact
703
+ || lifecycleAuthority.round !== normalized.round
704
+ || (normalized.requestId !== undefined && lifecycleAuthority.lifecycleRequestId !== normalized.requestId)) {
705
+ return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: 'lifecycle completion authority does not match the event tuple' }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
706
+ }
707
+ }
563
708
  const currentStep = typeof frontmatter.current_step === 'string' ? frontmatter.current_step : '';
564
709
  const matchingRows = rows.filter((item) => item.step === eventIdentity.action);
565
710
  const manual = eventIdentity.family === 'manual-validation';
@@ -573,6 +718,12 @@ function applyTaskEventUnlocked(request, options = {}) {
573
718
  if (eventIdentity.phase === 'started' && row) {
574
719
  if (row.agent !== normalized.agent)
575
720
  return failed(normalized, { code: 'EVENT_LOG_CONFLICT', message: 'open started event has a different agent' }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
721
+ if (manual && normalized.transactionId !== undefined) {
722
+ const existingTransactionId = /(?:^|;\s*)transaction=([A-Za-z0-9][A-Za-z0-9._-]{0,127})(?:;|$)/u.exec(row.note)?.[1];
723
+ if (existingTransactionId !== undefined && existingTransactionId !== normalized.transactionId) {
724
+ return failed(normalized, { code: 'EVENT_LOG_CONFLICT', message: 'open manual-validation started event has a different transactionId' }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
725
+ }
726
+ }
576
727
  return successNoOp(normalized, resolved.taskId, resolved.taskMdPath, currentStep, eventIdentity, row.started, frontmatter, artifactContext);
577
728
  }
578
729
  if (eventIdentity.phase === 'started' && !manual && completedRows.length > 0)
@@ -589,6 +740,37 @@ function applyTaskEventUnlocked(request, options = {}) {
589
740
  if (!validated.ok)
590
741
  return failed(normalized, validated.error, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
591
742
  completedArtifact = validated.artifact;
743
+ if (eventIdentity.family === 'manual-validation') {
744
+ const validationError = validateManualValidationCompletion(resolved.taskDir, resolved.taskId, normalized, completedArtifact.path);
745
+ if (validationError)
746
+ return failed(normalized, validationError, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
747
+ }
748
+ if (eventIdentity.family.startsWith('review-')) {
749
+ let reviewContent;
750
+ try {
751
+ reviewContent = fs.readFileSync(completedArtifact.path, 'utf8');
752
+ }
753
+ catch (error) {
754
+ return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: `cannot read qualification audit from ${completedArtifact.name}: ${error instanceof Error ? error.message : String(error)}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
755
+ }
756
+ const schema = getArtifactSchema(eventIdentity.family);
757
+ const structure = schema ? inspectArtifactContract(reviewContent, schema) : null;
758
+ if (structure && !structure.ok) {
759
+ return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: `shared artifact structure invalid: ${structure.diagnostics.map((item) => `${item.code}: ${item.message}`).join('; ')}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
760
+ }
761
+ const expected = expectedQualificationRelations(content, eventIdentity.family);
762
+ if (!expected.ok) {
763
+ return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: `${expected.code}: ${expected.message}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
764
+ }
765
+ const qualification = validateQualificationAudit(content, reviewContent, {
766
+ family: eventIdentity.family,
767
+ artifact: completedArtifact.name,
768
+ expectedUpstreamRelations: expected.relations
769
+ });
770
+ if (!qualification.ok) {
771
+ return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: `${qualification.code}: ${qualification.message}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
772
+ }
773
+ }
592
774
  if (eventIdentity.family === 'analyze' || eventIdentity.family === 'plan' || eventIdentity.family === 'code') {
593
775
  const localFamily = eventIdentity.family === 'analyze'
594
776
  ? 'analysis'
@@ -600,11 +782,10 @@ function applyTaskEventUnlocked(request, options = {}) {
600
782
  catch (error) {
601
783
  return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: `cannot read ${completedArtifact.name}: ${String(error)}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
602
784
  }
603
- const validationConfig = localArtifactValidationConfig(resolved.repoRoot, localFamily);
604
785
  const local = validateLocalArtifact(artifactContent, {
605
786
  family: localFamily,
606
- requiredSections: validationConfig.requiredSections,
607
- requiredPatterns: validationConfig.requiredPatterns
787
+ taskContent: content,
788
+ artifact: completedArtifact.name
608
789
  });
609
790
  if (!local.ok) {
610
791
  return failed(normalized, {
@@ -634,7 +815,7 @@ function applyTaskEventUnlocked(request, options = {}) {
634
815
  message: `cannot read local finalizer provenance for ${completedArtifact.name}: ${error instanceof Error ? error.message : String(error)}`
635
816
  }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
636
817
  }
637
- if (!localFinalizationIntent || !['passed', 'consumed'].includes(localFinalizationIntent.state)) {
818
+ if (!localFinalizationIntent || !['passed', 'consumed', 'finalize-ready', 'commit-started'].includes(localFinalizationIntent.state)) {
638
819
  return failed(normalized, {
639
820
  code: 'EVENT_ARTIFACT_CONFLICT',
640
821
  message: `local finalizer provenance is missing or incomplete for ${completedArtifact.name}`
@@ -646,6 +827,18 @@ function applyTaskEventUnlocked(request, options = {}) {
646
827
  message: `local finalizer provenance does not match ${completedArtifact.name}`
647
828
  }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
648
829
  }
830
+ if (localFinalizationIntent.recoveryOperationId !== null) {
831
+ if (!lifecycleAuthority
832
+ || localFinalizationIntent.recoveryOperationId !== lifecycleAuthority.operationId
833
+ || localFinalizationIntent.requestId !== lifecycleAuthority.lifecycleRequestId
834
+ || (localFinalizationIntent.phase !== 'artifact.finalize-local'
835
+ && localFinalizationIntent.authorityDigest !== lifecycleRecoveryAttestationDigest(lifecycleAuthority))) {
836
+ return failed(normalized, {
837
+ code: 'EVENT_ARTIFACT_CONFLICT',
838
+ message: `local finalizer provenance does not match lifecycle completion authority for ${completedArtifact.name}`
839
+ }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase, artifactContext });
840
+ }
841
+ }
649
842
  }
650
843
  }
651
844
  if (eventIdentity.phase === 'waiting' && section.entries.some((entry) => entry.step === eventIdentity.action && entry.note === eventIdentity.note)) {
@@ -726,6 +919,14 @@ function applyTaskEventUnlocked(request, options = {}) {
726
919
  const body = appendActivityEntry(section, { time: metadata.timestamp, step: logStep, agent: normalized.agent, note: eventIdentity.note });
727
920
  const frontmatterSet = { current_step: step, assigned_to: normalized.agent };
728
921
  let frontmatterRemove;
922
+ if (eventIdentity.phase === 'started' && artifactContext) {
923
+ try {
924
+ frontmatterSet.qualification_input_relations = JSON.stringify(qualificationRelationsForStarted(eventIdentity.family, artifactContext.inputs));
925
+ }
926
+ catch (error) {
927
+ return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: `cannot capture qualification input relations: ${error instanceof Error ? error.message : String(error)}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: step, action: eventIdentity.action, phase: eventIdentity.phase, artifactContext });
928
+ }
929
+ }
729
930
  if (eventIdentity.phase === 'started' && eventIdentity.family === 'code') {
730
931
  const planInput = artifactContext?.inputs.find((input) => input.family === 'plan');
731
932
  if (!planInput)
@@ -757,6 +958,8 @@ function applyTaskEventUnlocked(request, options = {}) {
757
958
  else if (eventIdentity.phase === 'completed' && eventIdentity.family.startsWith('review-')) {
758
959
  frontmatterRemove = ['review_input_artifact', 'review_input_sha256'];
759
960
  }
961
+ if (eventIdentity.phase === 'completed')
962
+ frontmatterRemove = [...(frontmatterRemove ?? []), 'qualification_input_relations'];
760
963
  if (eventIdentity.phase === 'started' && normalized.implementationInput)
761
964
  frontmatterSet.last_reviewed_commit = '';
762
965
  const mutations = [
@@ -795,14 +998,28 @@ function applyTaskEventUnlocked(request, options = {}) {
795
998
  });
796
999
  }
797
1000
  mutations.push({ kind: 'section', aliases: ['活动日志', 'Activity Log'], heading: section.heading, body });
798
- if (!normalized.dryRun && localFinalizationIntent && completedArtifact && localFinalizationIntent.state === 'passed') {
1001
+ if (!normalized.dryRun && localFinalizationIntent && completedArtifact) {
799
1002
  try {
800
- localFinalizationIntent = consumeLocalArtifactFinalizationIntent(resolved.repoRoot, localFinalizationIntent);
1003
+ if (lifecycleAuthority && localFinalizationIntent.state === 'passed') {
1004
+ const expectedIntent = localFinalizationIntent;
1005
+ localFinalizationIntent = {
1006
+ ...localFinalizationIntent,
1007
+ state: 'commit-started',
1008
+ phase: 'task-event.completed',
1009
+ authorityDigest: lifecycleRecoveryAttestationDigest(lifecycleAuthority),
1010
+ requestId: lifecycleAuthority.lifecycleRequestId,
1011
+ updatedAt: Date.now()
1012
+ };
1013
+ writeArtifactRepairIntent(resolved.repoRoot, localFinalizationIntent, { expected: expectedIntent });
1014
+ }
1015
+ else if (!lifecycleAuthority && localFinalizationIntent.state === 'passed') {
1016
+ localFinalizationIntent = consumeLocalArtifactFinalizationIntent(resolved.repoRoot, localFinalizationIntent);
1017
+ }
801
1018
  }
802
1019
  catch (error) {
803
1020
  return failed(normalized, {
804
1021
  code: 'EVENT_ARTIFACT_CONFLICT',
805
- message: `local finalizer provenance could not be consumed before task write for ${completedArtifact.name}: ${error instanceof Error ? error.message : String(error)}`
1022
+ message: `local finalizer provenance could not be advanced before task write for ${completedArtifact.name}: ${error instanceof Error ? error.message : String(error)}`
806
1023
  }, {
807
1024
  taskId: resolved.taskId,
808
1025
  taskMdPath: resolved.taskMdPath,
@@ -819,6 +1036,19 @@ function applyTaskEventUnlocked(request, options = {}) {
819
1036
  const result = writeTask({ taskRef: normalized.taskRef, expectedState: stateOverride ? resolved.state : 'active', dryRun: normalized.dryRun, mutations }, { ...options, invalidationContext: sourceCompletion ? 'source-completion' : 'standard', metadataProvider: () => metadata });
820
1037
  if (result.status === 'failed')
821
1038
  return failed(normalized, result.error, { taskId: result.taskId, taskMdPath: result.taskMdPath, fromStep: currentStep, toStep: step, action: eventIdentity.action, phase: eventIdentity.phase, timestamp: result.timestamp, agentInfraVersion: result.agentInfraVersion, operations: result.operations, artifactContext });
1039
+ if (!normalized.dryRun && lifecycleAuthority && localFinalizationIntent && completedArtifact) {
1040
+ try {
1041
+ if (!options.deferLifecycleRecoveryConsumption)
1042
+ consumeLifecycleRecoveryAttestation(lifecycleAuthority);
1043
+ writeArtifactRepairIntent(resolved.repoRoot, { ...localFinalizationIntent, state: 'consumed', updatedAt: Date.now() }, { expected: localFinalizationIntent });
1044
+ }
1045
+ catch (error) {
1046
+ return failed(normalized, {
1047
+ code: 'EVENT_ARTIFACT_CONFLICT',
1048
+ message: `task completion was written but lifecycle recovery consumption is incomplete: ${error instanceof Error ? error.message : String(error)}`
1049
+ }, { taskId: result.taskId, taskMdPath: result.taskMdPath, fromStep: currentStep, toStep: step, action: eventIdentity.action, phase: eventIdentity.phase, timestamp: result.timestamp, agentInfraVersion: result.agentInfraVersion, operations: result.operations, artifactContext });
1050
+ }
1051
+ }
822
1052
  if (!normalized.dryRun && orchestrationCompletion) {
823
1053
  try {
824
1054
  (options.commitOrchestrationCompletion ?? commitOrchestrationStageCompletion)(orchestrationCompletion);
@@ -0,0 +1,9 @@
1
+ export function taskFinalizationReceiptState(receipt) {
2
+ if (receipt.lifecycle !== 'done' || receipt.taskComment === 'pending'
3
+ || receipt.verification === 'pending' || receipt.warningProjection !== 'done')
4
+ return 'pending';
5
+ if (receipt.lastError !== null || receipt.warnings.some((warning) => warning.status === 'open'))
6
+ return 'unresolved';
7
+ return 'complete';
8
+ }
9
+ //# sourceMappingURL=finalization-state.js.map
@@ -1,6 +1,7 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { createHash, randomUUID } from 'node:crypto';
4
+ import { parseArtifactName } from './artifact-name.js';
4
5
  import { locateActivityLog } from './activity-log.js';
5
6
  import { applyPrReviewActivityIntent } from './activity-intent.js';
6
7
  import { applyHumanDecision } from './decision-intents.js';
@@ -577,12 +578,8 @@ function latestArtifact(taskDir, family) {
577
578
  catch {
578
579
  return undefined;
579
580
  }
580
- const candidates = names.filter((name) => (name === `${family}.md` || new RegExp(`^${family}-r\\d+\\.md$`).test(name)));
581
- candidates.sort((a, b) => {
582
- const round = (name) => Number(/-r(\d+)\.md$/.exec(name)?.[1] ?? 1);
583
- return round(b) - round(a);
584
- });
585
- return candidates[0];
581
+ return names.map(parseArtifactName).filter((identity) => identity !== null)
582
+ .filter((identity) => identity.family === family).sort((left, right) => right.round - left.round)[0]?.name;
586
583
  }
587
584
  async function probeVerificationEngineFailure(policy, resolved) {
588
585
  const candidates = [
@@ -1,3 +1,4 @@
1
+ import { parseArtifactName } from './artifact-name.js';
1
2
  import { parseTable } from './sections.js';
2
3
  const SECTION_ALIASES = ['实现输入', 'Implementation Inputs'];
3
4
  const COLUMNS = [
@@ -5,7 +6,6 @@ const COLUMNS = [
5
6
  'decided_at', 'status', 'consumed_by'
6
7
  ];
7
8
  const TIMESTAMP_RE = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}$/;
8
- const ARTIFACT_RE = /^code(?:-r(?:[2-9]|[1-9]\d+))?\.md$/;
9
9
  function validateInput(row) {
10
10
  if (!/^II-[1-9]\d*$/.test(row.id))
11
11
  throw new Error(`implementation input id '${row.id}' is invalid`);
@@ -17,7 +17,7 @@ function validateInput(row) {
17
17
  const valid = (row.status === 'declared' && row.decidedAt === '' && row.consumedBy === '') ||
18
18
  (hasValidTimestamp && row.needsImplementation && row.status === 'pending' && row.consumedBy === '') ||
19
19
  (hasValidTimestamp && !row.needsImplementation && row.status === 'not-required' && row.consumedBy === '') ||
20
- (hasValidTimestamp && row.needsImplementation && row.status === 'consumed' && ARTIFACT_RE.test(row.consumedBy));
20
+ (hasValidTimestamp && row.needsImplementation && row.status === 'consumed' && parseArtifactName(row.consumedBy)?.family === 'code');
21
21
  if (!valid)
22
22
  throw new Error(`implementation input ${row.id} has an invalid state combination`);
23
23
  }
@@ -122,7 +122,7 @@ function selectPendingImplementationInput(rows) {
122
122
  })[0] ?? null;
123
123
  }
124
124
  function consumeImplementationInput(rows, id, artifact) {
125
- if (!ARTIFACT_RE.test(artifact))
125
+ if (parseArtifactName(artifact)?.family !== 'code')
126
126
  throw new Error(`implementation input artifact '${artifact}' is invalid`);
127
127
  let found = false;
128
128
  const next = rows.map((row) => {