@fitlab-ai/agent-infra 0.9.13 → 0.9.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (428) hide show
  1. package/README.md +10 -0
  2. package/README.zh-CN.md +10 -0
  3. package/bin/cli.ts +26 -9
  4. package/bin/internal-cli.sh +45 -0
  5. package/dist/bin/cli.js +173 -157
  6. package/dist/bin/internal-cli.js +126 -42
  7. package/dist/lib/agent-client.js +5 -0
  8. package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +165 -27
  9. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +3 -2
  10. package/dist/lib/defaults.json +103 -103
  11. package/dist/lib/fs/durable-write.js +37 -0
  12. package/dist/lib/fs/file-lock.js +111 -0
  13. package/dist/lib/host-control/audit.js +19 -0
  14. package/dist/lib/host-control/client.js +142 -0
  15. package/dist/lib/host-control/command.js +49 -0
  16. package/dist/lib/host-control/path.js +160 -0
  17. package/dist/lib/host-control/secure-fs.js +140 -0
  18. package/dist/lib/host-control/server.js +159 -0
  19. package/dist/lib/host-control/service.js +112 -0
  20. package/dist/lib/init.js +11 -2
  21. package/dist/lib/internal/agent-client.js +5 -2
  22. package/dist/lib/internal/cli-route-inventory.js +154 -0
  23. package/dist/lib/internal/codex-lifecycle.js +15 -12
  24. package/dist/lib/internal/codex-sandbox-controller.js +8 -2
  25. package/dist/lib/internal/demo-promotion.js +322 -0
  26. package/dist/lib/internal/demo-transcript.js +454 -0
  27. package/dist/lib/internal/git-workflow.js +10 -6
  28. package/dist/lib/internal/host-control.js +28 -0
  29. package/dist/lib/internal/manual-validation.js +322 -0
  30. package/dist/lib/internal/platform-checks.js +16 -4
  31. package/dist/lib/internal/platform-comment.js +16 -4
  32. package/dist/lib/internal/platform-context.js +4 -1
  33. package/dist/lib/internal/platform-issue.js +12 -4
  34. package/dist/lib/internal/platform-metadata.js +88 -0
  35. package/dist/lib/internal/platform-pr-review.js +16 -3
  36. package/dist/lib/internal/platform-pr.js +42 -14
  37. package/dist/lib/internal/platform-release-notes.js +6 -3
  38. package/dist/lib/internal/platform-security.js +93 -0
  39. package/dist/lib/internal/pr-review-grade.js +14 -3
  40. package/dist/lib/internal/release-workflow.js +82 -89
  41. package/dist/lib/internal/sandbox-control.js +171 -7
  42. package/dist/lib/internal/task-activity.js +13 -4
  43. package/dist/lib/internal/task-artifact.js +19 -107
  44. package/dist/lib/internal/task-context.js +4 -1
  45. package/dist/lib/internal/task-create.js +48 -14
  46. package/dist/lib/internal/task-delivery.js +4 -1
  47. package/dist/lib/internal/task-event.js +38 -35
  48. package/dist/lib/internal/task-finalization.js +4 -1
  49. package/dist/lib/internal/task-invalidation.js +4 -1
  50. package/dist/lib/internal/task-ledger.js +12 -1
  51. package/dist/lib/internal/task-lifecycle.js +4 -1
  52. package/dist/lib/internal/task-operation-registry.js +519 -0
  53. package/dist/lib/internal/task-orchestration.js +12 -0
  54. package/dist/lib/internal/task-override.js +10 -3
  55. package/dist/lib/internal/task-qualification.js +90 -0
  56. package/dist/lib/internal/task-review.js +10 -52
  57. package/dist/lib/internal/task-short-id.js +11 -1
  58. package/dist/lib/internal/task-snapshot.js +4 -1
  59. package/dist/lib/internal/task-validate.js +37 -12
  60. package/dist/lib/internal/task-verify.js +5 -1
  61. package/dist/lib/internal/task-warning.js +8 -1
  62. package/dist/lib/owned-path.js +33 -0
  63. package/dist/lib/platform/check-status.js +11 -0
  64. package/dist/lib/platform/comment-safety.js +229 -0
  65. package/dist/lib/platform/completion-backfill.js +1 -1
  66. package/dist/lib/platform/github-data.js +241 -0
  67. package/dist/lib/platform/github-provider.js +248 -26
  68. package/dist/lib/platform/issue-comments.js +146 -34
  69. package/dist/lib/platform/issues.js +1 -179
  70. package/dist/lib/platform/pr-change-report.js +6 -12
  71. package/dist/lib/platform/pr-checks.js +12 -65
  72. package/dist/lib/platform/pr-summary.js +83 -10
  73. package/dist/lib/platform/provider-contract.d.ts +67 -1
  74. package/dist/lib/platform/provider-contract.js +6 -2
  75. package/dist/lib/platform/provider-validation.js +76 -3
  76. package/dist/lib/platform/pull-requests.js +117 -275
  77. package/dist/lib/platform/repository-metadata.js +377 -0
  78. package/dist/lib/platform/security-alerts.js +155 -0
  79. package/dist/lib/platform/snapshots.js +2 -0
  80. package/dist/lib/platform/verification-sync.js +154 -162
  81. package/dist/lib/process-data/index.js +7 -0
  82. package/dist/lib/release/workflow.js +1 -1
  83. package/dist/lib/run/index.js +5 -0
  84. package/dist/lib/sandbox/commands/control-status.js +22 -0
  85. package/dist/lib/sandbox/commands/create.js +39 -8
  86. package/dist/lib/sandbox/commands/ls.js +5 -0
  87. package/dist/lib/sandbox/commands/rm.js +3 -807
  88. package/dist/lib/sandbox/commands/show.js +16 -0
  89. package/dist/lib/sandbox/control/audit.js +203 -0
  90. package/dist/lib/sandbox/control/client.js +125 -12
  91. package/dist/lib/sandbox/control/completed-reentry.js +85 -0
  92. package/dist/lib/sandbox/control/container-identity.js +28 -31
  93. package/dist/lib/sandbox/control/executor.js +233 -34
  94. package/dist/lib/sandbox/control/finalization-response.js +27 -0
  95. package/dist/lib/sandbox/control/identity-sentinel.js +107 -0
  96. package/dist/lib/sandbox/control/lifecycle.js +656 -128
  97. package/dist/lib/sandbox/control/native-file-lock.js +85 -0
  98. package/dist/lib/sandbox/control/protocol.js +55 -4
  99. package/dist/lib/sandbox/control/server.js +720 -79
  100. package/dist/lib/sandbox/control/state.js +63 -3
  101. package/dist/lib/sandbox/control/task-view.js +183 -0
  102. package/dist/lib/sandbox/control/task-workflow.js +74 -0
  103. package/dist/lib/sandbox/control/workflow-executor.js +99 -0
  104. package/dist/lib/sandbox/engines/authority.js +289 -0
  105. package/dist/lib/sandbox/engines/docker-exact-discovery.js +97 -0
  106. package/dist/lib/sandbox/index.js +7 -2
  107. package/dist/lib/sandbox/recovery.js +49 -5
  108. package/dist/lib/sandbox/removal.js +1717 -0
  109. package/dist/lib/sandbox/task-cleanup.js +217 -0
  110. package/dist/lib/sandbox/workspace-view.js +15 -15
  111. package/dist/lib/sandbox/worktree-safety.js +4 -1
  112. package/dist/lib/server/index.js +8 -0
  113. package/dist/lib/task/activity-intent.js +2 -1
  114. package/dist/lib/task/activity-log.js +30 -24
  115. package/dist/lib/task/artifact-command.js +101 -0
  116. package/dist/lib/task/artifact-lifecycle.js +71 -40
  117. package/dist/lib/task/artifact-name.js +36 -0
  118. package/dist/lib/task/artifact-operations.js +474 -0
  119. package/dist/lib/task/artifact-receipts.js +3 -15
  120. package/dist/lib/task/artifact-repair-intent.js +130 -0
  121. package/dist/lib/task/artifact-schema.js +127 -0
  122. package/dist/lib/task/capabilities.js +83 -19
  123. package/dist/lib/task/codex-orchestration.js +71 -25
  124. package/dist/lib/task/commit-identity.js +28 -0
  125. package/dist/lib/task/commit-operation.js +2 -16
  126. package/dist/lib/task/control-authority.js +375 -5
  127. package/dist/lib/task/control-recovery.js +128 -0
  128. package/dist/lib/task/create-service.js +103 -4
  129. package/dist/lib/task/create.js +80 -2
  130. package/dist/lib/task/decision-details.js +2 -46
  131. package/dist/lib/task/events.js +306 -76
  132. package/dist/lib/task/finalization-state.js +9 -0
  133. package/dist/lib/task/human-override.js +3 -6
  134. package/dist/lib/task/implementation-inputs.js +3 -3
  135. package/dist/lib/task/index.js +11 -3
  136. package/dist/lib/task/intermediate-cleanup.js +383 -0
  137. package/dist/lib/task/invalidation.js +18 -65
  138. package/dist/lib/task/ledger-intents.js +7 -22
  139. package/dist/lib/task/ledger.js +1 -3
  140. package/dist/lib/task/lifecycle.js +19 -1
  141. package/dist/lib/task/local-artifact-finalization.js +190 -290
  142. package/dist/lib/task/manual-validation-completion.js +26 -0
  143. package/dist/lib/task/manual-validation-evidence.js +130 -0
  144. package/dist/lib/task/manual-validation-receipt.js +101 -0
  145. package/dist/lib/task/manual-validation-shared.js +40 -0
  146. package/dist/lib/task/manual-validation-transaction.js +243 -0
  147. package/dist/lib/task/markdown.js +47 -0
  148. package/dist/lib/task/orchestration.js +206 -69
  149. package/dist/lib/task/qualification-audit.js +476 -0
  150. package/dist/lib/task/qualification-confirmation.js +109 -0
  151. package/dist/lib/task/qualification-intents.js +148 -0
  152. package/dist/lib/task/review-artifacts.js +23 -40
  153. package/dist/lib/task/review-command.js +25 -0
  154. package/dist/lib/task/review-finalization.js +146 -97
  155. package/dist/lib/task/review-fingerprint.js +2 -2
  156. package/dist/lib/task/sections.js +34 -54
  157. package/dist/lib/task/verification-config.js +11 -0
  158. package/dist/lib/task/verification-engine.js +170 -327
  159. package/dist/lib/task/verification.js +1 -1
  160. package/dist/lib/task/workflow-command.js +17 -0
  161. package/dist/lib/task/workflow-warning-intents.js +0 -16
  162. package/dist/lib/task/workflow-warnings.js +28 -2
  163. package/dist/lib/update.js +2 -0
  164. package/dist/lifecycle-build-manifest.json +3 -3
  165. package/lib/agent-client.ts +9 -0
  166. package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +223 -33
  167. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +3 -2
  168. package/lib/fs/durable-write.ts +29 -0
  169. package/lib/fs/file-lock.ts +113 -0
  170. package/lib/host-control/audit.ts +22 -0
  171. package/lib/host-control/client.ts +172 -0
  172. package/lib/host-control/command.ts +60 -0
  173. package/lib/host-control/path.ts +167 -0
  174. package/lib/host-control/secure-fs.ts +135 -0
  175. package/lib/host-control/server.ts +180 -0
  176. package/lib/host-control/service.ts +133 -0
  177. package/lib/init.ts +15 -2
  178. package/lib/internal/agent-client.ts +4 -2
  179. package/lib/internal/cli-route-inventory.ts +142 -0
  180. package/lib/internal/codex-lifecycle.ts +14 -12
  181. package/lib/internal/codex-sandbox-controller.ts +7 -2
  182. package/lib/internal/demo-promotion.ts +354 -0
  183. package/lib/internal/demo-transcript.ts +419 -0
  184. package/lib/internal/git-workflow.ts +9 -6
  185. package/lib/internal/host-control.ts +28 -0
  186. package/lib/internal/manual-validation.ts +306 -0
  187. package/lib/internal/platform-checks.ts +12 -4
  188. package/lib/internal/platform-comment.ts +12 -4
  189. package/lib/internal/platform-context.ts +3 -1
  190. package/lib/internal/platform-issue.ts +11 -4
  191. package/lib/internal/platform-metadata.ts +70 -0
  192. package/lib/internal/platform-pr-review.ts +14 -3
  193. package/lib/internal/platform-pr.ts +38 -14
  194. package/lib/internal/platform-release-notes.ts +5 -3
  195. package/lib/internal/platform-security.ts +83 -0
  196. package/lib/internal/pr-review-grade.ts +10 -3
  197. package/lib/internal/release-workflow.ts +91 -87
  198. package/lib/internal/sandbox-control.ts +181 -6
  199. package/lib/internal/task-activity.ts +12 -4
  200. package/lib/internal/task-artifact.ts +15 -79
  201. package/lib/internal/task-context.ts +3 -1
  202. package/lib/internal/task-create.ts +76 -15
  203. package/lib/internal/task-delivery.ts +3 -1
  204. package/lib/internal/task-event.ts +21 -10
  205. package/lib/internal/task-finalization.ts +3 -1
  206. package/lib/internal/task-invalidation.ts +3 -1
  207. package/lib/internal/task-ledger.ts +11 -1
  208. package/lib/internal/task-lifecycle.ts +3 -1
  209. package/lib/internal/task-operation-registry.ts +590 -0
  210. package/lib/internal/task-orchestration.ts +12 -0
  211. package/lib/internal/task-override.ts +9 -3
  212. package/lib/internal/task-qualification.ts +61 -0
  213. package/lib/internal/task-review.ts +7 -50
  214. package/lib/internal/task-short-id.ts +10 -1
  215. package/lib/internal/task-snapshot.ts +3 -1
  216. package/lib/internal/task-validate.ts +32 -12
  217. package/lib/internal/task-verify.ts +4 -1
  218. package/lib/internal/task-warning.ts +7 -1
  219. package/lib/owned-path.ts +26 -0
  220. package/lib/platform/check-status.ts +9 -0
  221. package/lib/platform/comment-safety.ts +255 -0
  222. package/lib/platform/completion-backfill.ts +1 -1
  223. package/lib/platform/github-data.ts +322 -0
  224. package/lib/platform/github-provider.ts +244 -27
  225. package/lib/platform/issue-comments.ts +159 -35
  226. package/lib/platform/issues.ts +4 -245
  227. package/lib/platform/pr-change-report.ts +6 -12
  228. package/lib/platform/pr-checks.ts +13 -77
  229. package/lib/platform/pr-summary.ts +88 -11
  230. package/lib/platform/provider-contract.ts +78 -3
  231. package/lib/platform/provider-validation.ts +85 -3
  232. package/lib/platform/pull-requests.ts +129 -348
  233. package/lib/platform/repository-metadata.ts +453 -0
  234. package/lib/platform/security-alerts.ts +191 -0
  235. package/lib/platform/snapshots.ts +53 -0
  236. package/lib/platform/verification-sync.ts +171 -177
  237. package/lib/process-data/index.ts +7 -0
  238. package/lib/release/workflow.ts +3 -3
  239. package/lib/run/index.ts +5 -0
  240. package/lib/sandbox/commands/control-status.ts +26 -0
  241. package/lib/sandbox/commands/create.ts +53 -12
  242. package/lib/sandbox/commands/ls.ts +7 -0
  243. package/lib/sandbox/commands/rm.ts +3 -996
  244. package/lib/sandbox/commands/show.ts +16 -0
  245. package/lib/sandbox/control/audit.ts +253 -0
  246. package/lib/sandbox/control/client.ts +150 -13
  247. package/lib/sandbox/control/completed-reentry.ts +98 -0
  248. package/lib/sandbox/control/container-identity.ts +27 -43
  249. package/lib/sandbox/control/executor.ts +262 -37
  250. package/lib/sandbox/control/finalization-response.ts +29 -0
  251. package/lib/sandbox/control/identity-sentinel.ts +137 -0
  252. package/lib/sandbox/control/lifecycle.ts +672 -18
  253. package/lib/sandbox/control/native-file-lock.ts +108 -0
  254. package/lib/sandbox/control/protocol.ts +80 -8
  255. package/lib/sandbox/control/server.ts +779 -82
  256. package/lib/sandbox/control/state.ts +84 -3
  257. package/lib/sandbox/control/task-view.ts +240 -0
  258. package/lib/sandbox/control/task-workflow.ts +95 -0
  259. package/lib/sandbox/control/workflow-executor.ts +102 -0
  260. package/lib/sandbox/engines/authority.ts +365 -0
  261. package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
  262. package/lib/sandbox/index.ts +9 -2
  263. package/lib/sandbox/recovery.ts +49 -6
  264. package/lib/sandbox/removal.ts +2144 -0
  265. package/lib/sandbox/task-cleanup.ts +209 -0
  266. package/lib/sandbox/workspace-view.ts +26 -18
  267. package/lib/sandbox/worktree-safety.ts +4 -1
  268. package/lib/server/index.ts +10 -0
  269. package/lib/task/activity-intent.ts +2 -2
  270. package/lib/task/activity-log.ts +27 -19
  271. package/lib/task/artifact-command.ts +104 -0
  272. package/lib/task/artifact-lifecycle.ts +66 -39
  273. package/lib/task/artifact-name.ts +55 -0
  274. package/lib/task/artifact-operations.ts +580 -0
  275. package/lib/task/artifact-receipts.ts +3 -14
  276. package/lib/task/artifact-repair-intent.ts +152 -0
  277. package/lib/task/artifact-schema.ts +163 -0
  278. package/lib/task/capabilities.ts +82 -22
  279. package/lib/task/codex-orchestration.ts +85 -24
  280. package/lib/task/commit-identity.ts +31 -0
  281. package/lib/task/commit-operation.ts +2 -16
  282. package/lib/task/control-authority.ts +513 -6
  283. package/lib/task/control-recovery.ts +174 -0
  284. package/lib/task/create-service.ts +131 -6
  285. package/lib/task/create.ts +83 -1
  286. package/lib/task/decision-details.ts +3 -71
  287. package/lib/task/events.ts +292 -75
  288. package/lib/task/finalization-state.ts +11 -0
  289. package/lib/task/human-override.ts +3 -8
  290. package/lib/task/implementation-inputs.ts +3 -3
  291. package/lib/task/index.ts +16 -3
  292. package/lib/task/intermediate-cleanup.ts +455 -0
  293. package/lib/task/invalidation.ts +18 -62
  294. package/lib/task/ledger-intents.ts +7 -24
  295. package/lib/task/ledger.ts +1 -3
  296. package/lib/task/lifecycle.ts +17 -1
  297. package/lib/task/local-artifact-finalization.ts +223 -388
  298. package/lib/task/manual-validation-completion.ts +40 -0
  299. package/lib/task/manual-validation-evidence.ts +209 -0
  300. package/lib/task/manual-validation-receipt.ts +152 -0
  301. package/lib/task/manual-validation-shared.ts +50 -0
  302. package/lib/task/manual-validation-transaction.ts +304 -0
  303. package/lib/task/markdown.ts +70 -0
  304. package/lib/task/orchestration.ts +191 -68
  305. package/lib/task/qualification-audit.ts +588 -0
  306. package/lib/task/qualification-confirmation.ts +117 -0
  307. package/lib/task/qualification-intents.ts +150 -0
  308. package/lib/task/review-artifacts.ts +21 -41
  309. package/lib/task/review-command.ts +23 -0
  310. package/lib/task/review-finalization.ts +154 -153
  311. package/lib/task/review-fingerprint.ts +2 -2
  312. package/lib/task/sections.ts +33 -52
  313. package/lib/task/verification-config.ts +12 -0
  314. package/lib/task/verification-engine.ts +165 -370
  315. package/lib/task/verification-types.ts +17 -0
  316. package/lib/task/verification.ts +1 -1
  317. package/lib/task/workflow-command.ts +18 -0
  318. package/lib/task/workflow-warning-intents.ts +0 -13
  319. package/lib/task/workflow-warnings.ts +21 -2
  320. package/lib/update.ts +6 -0
  321. package/package.json +7 -2
  322. package/templates/.agents/hooks/lifecycle-delegation.js +6 -6
  323. package/templates/.agents/rules/README.en.md +2 -0
  324. package/templates/.agents/rules/README.zh-CN.md +2 -0
  325. package/templates/.agents/rules/decision-qualification.en.md +22 -0
  326. package/templates/.agents/rules/decision-qualification.zh-CN.md +22 -0
  327. package/templates/.agents/rules/evidence-reporting.en.md +28 -0
  328. package/templates/.agents/rules/evidence-reporting.zh-CN.md +28 -0
  329. package/templates/.agents/rules/label-milestone-setup.en.md +7 -7
  330. package/templates/.agents/rules/label-milestone-setup.zh-CN.md +7 -7
  331. package/templates/.agents/rules/local-artifact-repair.en.md +5 -1
  332. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +5 -1
  333. package/templates/.agents/rules/security-alerts.en.md +8 -8
  334. package/templates/.agents/rules/security-alerts.zh-CN.md +8 -8
  335. package/templates/.agents/rules/testing-discipline.en.md +2 -0
  336. package/templates/.agents/rules/testing-discipline.zh-CN.md +2 -0
  337. package/templates/.agents/scripts/package.json +3 -0
  338. package/templates/.agents/skills/analyze-task/SKILL.en.md +15 -2
  339. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +19 -2
  340. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -12
  341. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -12
  342. package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
  343. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
  344. package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
  345. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
  346. package/templates/.agents/skills/code-task/SKILL.en.md +14 -1
  347. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +14 -1
  348. package/templates/.agents/skills/code-task/config/verify.en.json +5 -14
  349. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +5 -14
  350. package/templates/.agents/skills/code-task/reference/code-rules.en.md +5 -4
  351. package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +5 -4
  352. package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
  353. package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
  354. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +3 -1
  355. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +3 -1
  356. package/templates/.agents/skills/code-task/reference/report-template.en.md +42 -15
  357. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +39 -12
  358. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +37 -21
  359. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +37 -21
  360. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
  361. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
  362. package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +4 -0
  363. package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +4 -0
  364. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +16 -7
  365. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +16 -7
  366. package/templates/.agents/skills/complete-task/SKILL.en.md +10 -23
  367. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +10 -23
  368. package/templates/.agents/skills/create-task/SKILL.en.md +8 -0
  369. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +7 -0
  370. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  371. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  372. package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
  373. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
  374. package/templates/.agents/skills/init-labels/SKILL.en.md +8 -8
  375. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +8 -8
  376. package/templates/.agents/skills/init-milestones/SKILL.en.md +9 -11
  377. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +9 -11
  378. package/templates/.agents/skills/plan-task/SKILL.en.md +14 -1
  379. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +16 -1
  380. package/templates/.agents/skills/plan-task/config/verify.en.json +4 -14
  381. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +4 -14
  382. package/templates/.agents/skills/release/SKILL.en.md +7 -3
  383. package/templates/.agents/skills/release/SKILL.zh-CN.md +7 -3
  384. package/templates/.agents/skills/review-analysis/SKILL.en.md +14 -1
  385. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +14 -1
  386. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -18
  387. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -18
  388. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +50 -23
  389. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +45 -18
  390. package/templates/.agents/skills/review-code/SKILL.en.md +14 -1
  391. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +14 -1
  392. package/templates/.agents/skills/review-code/config/verify.en.json +1 -23
  393. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -23
  394. package/templates/.agents/skills/review-code/reference/report-template.en.md +49 -22
  395. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +45 -18
  396. package/templates/.agents/skills/review-plan/SKILL.en.md +14 -1
  397. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +14 -1
  398. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -18
  399. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -18
  400. package/templates/.agents/skills/review-plan/reference/report-template.en.md +49 -22
  401. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +45 -18
  402. package/templates/.agents/skills/review-pr/SKILL.en.md +5 -1
  403. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +5 -1
  404. package/templates/.agents/skills/review-pr/reference/report-template.en.md +4 -3
  405. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +4 -3
  406. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +25 -4
  407. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +25 -4
  408. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +4 -1
  409. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +4 -1
  410. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +5 -1
  411. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +5 -1
  412. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  413. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  414. package/templates/.agents/skills/test/SKILL.en.md +29 -7
  415. package/templates/.agents/skills/test/SKILL.zh-CN.md +29 -7
  416. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +14 -0
  417. package/templates/.agents/templates/task.en.md +6 -0
  418. package/templates/.agents/templates/task.zh-CN.md +6 -0
  419. package/templates/.claude/commands/run-manual-validation.en.md +1 -1
  420. package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
  421. package/dist/lib/platform/adapters.js +0 -56
  422. package/lib/platform/adapters.ts +0 -197
  423. package/templates/.agents/scripts/security-alerts.github.sh +0 -151
  424. package/templates/.agents/scripts/security-alerts.sh +0 -31
  425. package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +0 -146
  426. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +0 -32
  427. package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +0 -294
  428. package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +0 -6
@@ -2,7 +2,8 @@ import { createHash } from 'node:crypto';
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import { appendActivityEntry, locateActivityLog } from './activity-log.js';
5
- import { artifactFamilyCatalog, inspectArtifactDirectory, parseArtifactName } from './artifact-lifecycle.js';
5
+ import { artifactFamilyCatalog, inspectArtifactDirectory } from './artifact-lifecycle.js';
6
+ import { parseArtifactName } from './artifact-name.js';
6
7
  import { parseTypedTaskFrontmatter } from './frontmatter.js';
7
8
  import { locateHotTaskDirs, resolveTaskRef, TASK_ID_RE } from './resolve-ref.js';
8
9
  import { configuredShortIdLength, executeShortIdCommand, loadShortIdByTaskId, mutateShortIdRegistry } from './short-id.js';
@@ -296,6 +297,23 @@ function parseJournal(content) {
296
297
  }
297
298
  return value;
298
299
  }
300
+ /** Recovery reads the same journal contract as the lifecycle writer. */
301
+ export function readLifecycleJournalEvidence(repoRoot, taskId) {
302
+ const journalPath = locateHotTaskDirs(repoRoot, taskId)
303
+ .map((entry) => path.join(entry.taskDir, '.task-lifecycle.json'))
304
+ .find((candidate) => fs.existsSync(candidate));
305
+ if (!journalPath)
306
+ return { exists: false, completedSteps: [], failure: null };
307
+ try {
308
+ const journal = parseJournal(fs.readFileSync(journalPath, 'utf8'));
309
+ if (journal.taskId !== taskId)
310
+ throw new Error('journal task identity mismatch');
311
+ return { exists: true, completedSteps: journal.completedSteps, failure: journal.failure?.code ?? null };
312
+ }
313
+ catch {
314
+ return { exists: true, completedSteps: [], failure: 'SANDBOX_CONTROL_LIFECYCLE_JOURNAL_INVALID' };
315
+ }
316
+ }
299
317
  function directoryManifest(root) {
300
318
  const entries = [];
301
319
  const visit = (current, relative = '') => {
@@ -1,198 +1,131 @@
1
1
  import fs from 'node:fs';
2
- import { createHash } from 'node:crypto';
3
- import path from 'node:path';
4
- import { inspectDecisionDetailDuplicates, scanVisibleMarkdown } from './decision-details.js';
5
- import { parseArtifactName, validateCompletedArtifact } from './artifact-lifecycle.js';
2
+ import { inspectDecisionDetailDuplicates } from './decision-details.js';
3
+ import { scanVisibleMarkdown } from './markdown.js';
4
+ import { parseArtifactName } from './artifact-name.js';
5
+ import { hasOpenArtifactRound, validateArtifactPublication, validateCompletedArtifact } from './artifact-lifecycle.js';
6
6
  import { resolveTaskRef } from './resolve-ref.js';
7
+ import { expectedQualificationRelations, validateQualificationAudit } from './qualification-audit.js';
8
+ import { canonicalSemanticDigest, inspectArtifactPatterns, inspectArtifactStructure, sha256Content } from './artifact-operations.js';
9
+ import { getArtifactSchema } from './artifact-schema.js';
10
+ import { readArtifactRepairIntent, writeArtifactRepairIntent } from './artifact-repair-intent.js';
11
+ import { consumeLifecycleRecoveryAttestation, lifecycleRecoveryAttestationDigest, validateLifecycleRecoveryAttestation } from './control-authority.js';
7
12
  const LOCAL_ARTIFACT_REQUIRED_SECTIONS = {
8
- analysis: [
9
- '需求来源', '需求理解', '相关文件', '影响评估', '技术风险',
10
- '工作量和复杂度评估', '状态核对'
11
- ],
12
- plan: [
13
- '问题理解', '约束条件', '方案对比', '技术方法', '实施步骤',
14
- '文件清单', '验证策略', '状态核对'
15
- ],
16
- code: [
17
- '实现输入', '变更文件', '关键代码说明', '测试结果', '与方案的差异',
18
- '供审查关注的内容', '状态核对', '证据原文'
19
- ]
13
+ analysis: getArtifactSchema('analysis').sections.map((section) => section.headings.zh),
14
+ plan: getArtifactSchema('plan').sections.map((section) => section.headings.zh),
15
+ code: getArtifactSchema('code').sections.map((section) => section.headings.zh)
20
16
  };
21
- const LOCAL_ARTIFACT_REQUIRED_PATTERNS = ['^\\$ '];
22
- function finalizationIntentRoot(repoRoot) {
23
- return path.join(repoRoot, '.agents', 'workspace', '.local-artifact-finalization-intents');
17
+ function authorityDigest(authority) {
18
+ return lifecycleRecoveryAttestationDigest(authority);
24
19
  }
25
- function finalizationIntentPath(repoRoot, taskId, family, artifact) {
26
- return path.join(finalizationIntentRoot(repoRoot), `${taskId}-${family}-${artifact}.json`);
27
- }
28
- function isFinalizationIntent(value) {
29
- if (!value || typeof value !== 'object' || Array.isArray(value))
20
+ function validFinalizerAuthority(authority, request, taskId) {
21
+ if (!authority)
30
22
  return false;
31
- const intent = value;
32
- return intent.version === 1
33
- && typeof intent.taskId === 'string' && intent.taskId.length > 0
34
- && (intent.family === 'analysis' || intent.family === 'plan' || intent.family === 'code')
35
- && typeof intent.artifact === 'string' && intent.artifact.length > 0
36
- && (intent.state === 'awaiting-repair' || intent.state === 'passed' || intent.state === 'consumed')
37
- && (intent.baselineSemanticDigest === null || (typeof intent.baselineSemanticDigest === 'string' && /^[a-f0-9]{64}$/.test(intent.baselineSemanticDigest)))
38
- && typeof intent.artifactSha256 === 'string' && /^[a-f0-9]{64}$/.test(intent.artifactSha256)
39
- && typeof intent.semanticDigest === 'string' && /^[a-f0-9]{64}$/.test(intent.semanticDigest)
40
- && (intent.state === 'awaiting-repair' ? intent.baselineSemanticDigest === intent.semanticDigest : true);
41
- }
42
- function readLocalArtifactFinalizationIntent(repoRoot, taskId, family, artifact) {
43
- const target = finalizationIntentPath(repoRoot, taskId, family, artifact);
44
- if (!fs.existsSync(target))
45
- return null;
46
- const value = JSON.parse(fs.readFileSync(target, 'utf8'));
47
- if (!isFinalizationIntent(value) || value.taskId !== taskId || value.family !== family || value.artifact !== artifact) {
48
- throw new Error('LOCAL_FINALIZATION_INTENT_INVALID: finalization provenance schema is invalid');
49
- }
50
- return value;
51
- }
52
- function writeLocalArtifactFinalizationIntent(repoRoot, value) {
53
- if (!isFinalizationIntent(value))
54
- throw new Error('LOCAL_FINALIZATION_INTENT_INVALID: finalization provenance schema is invalid');
55
- const directory = finalizationIntentRoot(repoRoot);
56
- fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
57
- const target = finalizationIntentPath(repoRoot, value.taskId, value.family, value.artifact);
58
- const temporary = `${target}.${process.pid}.${Date.now()}.tmp`;
59
- fs.writeFileSync(temporary, `${JSON.stringify(value)}\n`, { encoding: 'utf8', mode: 0o600, flag: 'wx' });
60
23
  try {
61
- fs.renameSync(temporary, target);
24
+ validateLifecycleRecoveryAttestation(authority);
62
25
  }
63
- catch (error) {
64
- try {
65
- fs.unlinkSync(temporary);
66
- }
67
- catch { /* preserve primary error */ }
68
- throw error;
26
+ catch {
27
+ return false;
69
28
  }
29
+ return authority.version === 1
30
+ && authority.phase === 'artifact.finalize-local'
31
+ && authority.taskId === taskId
32
+ && authority.family === request.family
33
+ && authority.artifact === request.artifact
34
+ && authority.round === (parseArtifactName(request.artifact)?.round ?? 0)
35
+ && authority.requestId.length > 0
36
+ && authority.operationId.length > 0;
70
37
  }
71
38
  function consumeLocalArtifactFinalizationIntent(repoRoot, intent) {
72
39
  if (intent.state === 'consumed')
73
40
  return intent;
74
41
  if (intent.state !== 'passed')
75
42
  throw new Error('LOCAL_FINALIZATION_INTENT_INVALID: only passed provenance can be consumed');
76
- const consumed = { ...intent, state: 'consumed' };
77
- writeLocalArtifactFinalizationIntent(repoRoot, consumed);
43
+ const consumed = { ...intent, state: 'consumed', updatedAt: Date.now() };
44
+ writeArtifactRepairIntent(repoRoot, consumed, { expected: intent });
78
45
  return consumed;
79
46
  }
80
- function requiredSections(family) {
81
- return LOCAL_ARTIFACT_REQUIRED_SECTIONS[family];
82
- }
83
- function lineNumber(content, offset) {
84
- return content.slice(0, offset).split('\n').length;
85
- }
86
- function sectionBody(content, heading) {
87
- const next = scanVisibleMarkdown(content).headings.find((candidate) => (candidate.start > heading.start && candidate.level <= 2));
88
- return content.slice(heading.end, next?.start ?? content.length);
89
- }
90
- function semanticDigest(content, candidate) {
91
- let normalized = content;
92
- if (candidate) {
93
- const raw = content.slice(candidate.start, candidate.end);
94
- const marker = raw.match(/([::])\s*$/);
95
- if (marker?.index !== undefined) {
96
- const canonical = raw.slice(0, marker.index) + raw.slice(marker.index + 1);
97
- normalized = `${content.slice(0, candidate.start)}${canonical}${content.slice(candidate.end)}`;
98
- }
99
- }
100
- return createHash('sha256').update(normalized, 'utf8').digest('hex');
101
- }
102
- function sha256Content(content) {
103
- return createHash('sha256').update(content, 'utf8').digest('hex');
104
- }
105
- function visibleSectionHeadings(content, section) {
106
- return scanVisibleMarkdown(content).headings.filter((heading) => (heading.level === 2 && heading.text === section));
107
- }
108
- function trailingPunctuationCandidates(content, section) {
109
- return scanVisibleMarkdown(content).headings.filter((heading) => (heading.level === 2 && (heading.text === `${section}:` || heading.text === `${section}:`)));
47
+ function localDiagnosticCode(code) {
48
+ const map = {
49
+ ARTIFACT_EMPTY: 'LOCAL_ARTIFACT_EMPTY',
50
+ ARTIFACT_MISSING_SECTION: 'LOCAL_ARTIFACT_MISSING_SECTION',
51
+ ARTIFACT_DUPLICATE_SECTION: 'LOCAL_ARTIFACT_DUPLICATE_SECTION',
52
+ ARTIFACT_HEADING_TRAILING_PUNCTUATION: 'LOCAL_SECTION_HEADING_TRAILING_PUNCTUATION'
53
+ };
54
+ return map[code] ?? 'LOCAL_STRUCTURAL_INVALID';
110
55
  }
111
- function diagnostic(code, message, content, heading, extra = {}) {
56
+ function localDiagnostic(item) {
57
+ const code = localDiagnosticCode(item.code);
58
+ if (!code)
59
+ return null;
112
60
  return {
113
- code, message, repairable: false,
114
- line: heading ? lineNumber(content, heading.start) : null,
115
- ...extra
61
+ code,
62
+ message: item.message,
63
+ repairable: item.repairable,
64
+ line: item.line,
65
+ ...(item.operation?.kind === 'replace-line'
66
+ ? { from: item.operation.from, to: item.operation.to, operation: 'replace-line' }
67
+ : {})
116
68
  };
117
69
  }
118
70
  function isStatusPattern(pattern) {
119
71
  return pattern === '^\\$ ';
120
72
  }
121
73
  function validateLocalArtifact(content, options) {
122
- const sections = options.requiredSections ?? requiredSections(options.family);
123
- const patterns = options.requiredPatterns ?? LOCAL_ARTIFACT_REQUIRED_PATTERNS;
74
+ const schema = getArtifactSchema(options.family);
75
+ const patterns = schema.requiredPatterns;
124
76
  const diagnostics = [];
125
- const candidates = [];
126
77
  const scanned = scanVisibleMarkdown(content);
127
- if (!content.trim()) {
128
- diagnostics.push(diagnostic('LOCAL_ARTIFACT_EMPTY', 'artifact is empty', content));
129
- }
130
- for (const section of sections) {
131
- const exact = scanned.headings.filter((heading) => heading.level === 2 && heading.text === section);
132
- const punctuated = trailingPunctuationCandidates(content, section);
133
- if (exact.length > 1 || punctuated.length > 0 && exact.length > 0 || punctuated.length > 1) {
134
- const first = exact[1] ?? punctuated[0] ?? exact[0];
135
- diagnostics.push(diagnostic('LOCAL_ARTIFACT_DUPLICATE_SECTION', `required section '${section}' is duplicated or has an ambiguous punctuation variant`, content, first));
136
- }
137
- else if (exact.length === 0 && punctuated.length === 1) {
138
- candidates.push(punctuated[0]);
139
- }
140
- else if (exact.length === 0) {
141
- diagnostics.push(diagnostic('LOCAL_ARTIFACT_MISSING_SECTION', `required section '${section}' is missing`, content));
142
- }
78
+ const structure = inspectArtifactStructure(content, schema);
79
+ for (const item of structure.diagnostics) {
80
+ const mapped = localDiagnostic(item);
81
+ if (mapped)
82
+ diagnostics.push(mapped);
143
83
  }
144
- const statusSection = sections.find((section) => section === '状态核对' || section.toLowerCase() === 'state check');
84
+ const statusSection = schema.sections.find((section) => section.id === 'state-check');
145
85
  if (statusSection) {
146
- const statusHeading = visibleSectionHeadings(content, statusSection)[0]
147
- ?? candidates.find((heading) => heading.text === `${statusSection}:` || heading.text === `${statusSection}:`);
86
+ const statusHeading = scanned.headings.find((heading) => (heading.level === 2 && [statusSection.headings.zh, statusSection.headings.en].some((name) => (heading.text === name || heading.text === `${name}:` || heading.text === `${name}:`))));
148
87
  if (statusHeading) {
149
- const body = sectionBody(content, statusHeading);
88
+ const next = scanned.headings.find((candidate) => candidate.start > statusHeading.start && candidate.level <= 2);
89
+ const body = content.slice(statusHeading.end, next?.start ?? content.length);
150
90
  for (const pattern of patterns.filter(isStatusPattern)) {
151
91
  if (!new RegExp(pattern, 'm').test(body)) {
152
- diagnostics.push(diagnostic('LOCAL_STATUS_COMMAND_MISSING', `status section '${statusSection}' is missing required command output`, content, statusHeading));
92
+ diagnostics.push({ code: 'LOCAL_STATUS_COMMAND_MISSING', message: `status section '${statusHeading.text}' is missing required command output`, repairable: false, line: content.slice(0, statusHeading.start).split('\n').length });
153
93
  }
154
94
  }
155
95
  }
156
96
  }
157
- for (const pattern of patterns.filter((item) => !isStatusPattern(item))) {
158
- if (!new RegExp(pattern, 'm').test(content)) {
159
- diagnostics.push(diagnostic('LOCAL_REQUIRED_PATTERN_MISSING', `artifact is missing required pattern '${pattern}'`, content));
160
- }
97
+ const patternInspection = inspectArtifactPatterns(content, {
98
+ ...schema,
99
+ requiredPatterns: patterns.filter((item) => !isStatusPattern(item))
100
+ });
101
+ for (const item of patternInspection.diagnostics) {
102
+ diagnostics.push({ code: 'LOCAL_REQUIRED_PATTERN_MISSING', message: item.message, repairable: false, line: null });
161
103
  }
162
104
  const decisionDetails = inspectDecisionDetailDuplicates(content);
163
105
  if (!decisionDetails.ok) {
164
- diagnostics.push(diagnostic('LOCAL_DECISION_DETAIL_DUPLICATE', decisionDetails.message, content, decisionDetails.duplicates[0]?.blocks[0]
165
- ? scanned.headings.find((heading) => heading.start === decisionDetails.duplicates[0].blocks[0].start)
166
- : undefined));
106
+ diagnostics.push({ code: 'LOCAL_DECISION_DETAIL_DUPLICATE', message: decisionDetails.message, repairable: false, line: null });
167
107
  }
168
- if (candidates.length === 1 && diagnostics.length === 0) {
169
- const candidate = candidates[0];
170
- const section = candidate.text.slice(0, -1);
171
- const repair = diagnostic('LOCAL_SECTION_HEADING_TRAILING_PUNCTUATION', `visible required H2 '${candidate.text}' may be normalized to '${section}'`, content, candidate, {
172
- repairable: true,
173
- from: candidate.text,
174
- to: section,
175
- operation: 'replace-line'
108
+ if (options.taskContent !== undefined) {
109
+ const expected = expectedQualificationRelations(options.taskContent, options.family);
110
+ if (!expected.ok) {
111
+ diagnostics.push({ code: 'LOCAL_QUALIFICATION_AUDIT_INVALID', message: `${expected.code}: ${expected.message}`, repairable: false, line: null });
112
+ }
113
+ const qualification = validateQualificationAudit(options.taskContent, content, {
114
+ family: options.family === 'analysis' ? 'analysis' : options.family === 'plan' ? 'plan' : 'code',
115
+ artifact: options.artifact,
116
+ expectedUpstreamRelations: expected.ok ? expected.relations : undefined
176
117
  });
177
- return {
178
- ok: false,
179
- family: options.family,
180
- semanticDigest: semanticDigest(content, candidate),
181
- repairable: true,
182
- diagnostics: [repair]
183
- };
184
- }
185
- if (candidates.length > 0) {
186
- for (const candidate of candidates) {
187
- const section = candidate.text.slice(0, -1);
188
- diagnostics.push(diagnostic('LOCAL_ARTIFACT_MISSING_SECTION', `required section '${section}' is missing and cannot be repaired while other structural defects exist`, content, candidate));
118
+ if (!qualification.ok) {
119
+ diagnostics.push({ code: 'LOCAL_QUALIFICATION_AUDIT_INVALID', message: `${qualification.code}: ${qualification.message}`, repairable: false, line: null });
189
120
  }
190
121
  }
122
+ const repairable = structure.repair !== null && diagnostics.length === 1 && diagnostics[0]?.repairable === true;
123
+ const semanticDigestValue = canonicalSemanticDigest(content, structure.repair);
191
124
  return {
192
125
  ok: diagnostics.length === 0,
193
126
  family: options.family,
194
- semanticDigest: semanticDigest(content),
195
- repairable: false,
127
+ semanticDigest: semanticDigestValue,
128
+ repairable,
196
129
  diagnostics
197
130
  };
198
131
  }
@@ -205,170 +138,137 @@ function failedFinalization(request, error, extra = {}) {
205
138
  repairable: false, diagnostics: [], error, ...extra
206
139
  };
207
140
  }
208
- function provenanceFailure(request, resolved, content, artifactSha256, semanticDigestValue, code, message) {
209
- return failedFinalization(request, { code, message }, {
210
- taskId: resolved.taskId,
211
- taskDir: resolved.taskDir,
212
- artifactSha256,
213
- semanticDigest: semanticDigestValue,
214
- diagnostics: [diagnostic(code, message, content)]
141
+ /** Read and validate once; callers publish this content before committing provenance. */
142
+ function prepareLocalArtifact(request, candidate, authority) {
143
+ const failed = (code, message) => ({
144
+ result: failedFinalization(request, { code, message }), content: candidate ?? ''
215
145
  });
216
- }
217
- function finalizeLocalArtifact(request) {
218
146
  const resolved = resolveTaskRef(request.taskRef, { repoRoot: request.repoRoot });
219
147
  if (!resolved.ok)
220
- return failedFinalization(request, { code: resolved.code, message: resolved.message });
148
+ return failed(resolved.code, resolved.message);
221
149
  const parsed = parseArtifactName(request.artifact);
222
- if (!parsed || parsed.family !== request.family) {
223
- return failedFinalization(request, {
224
- code: 'ARTIFACT_IDENTITY_INVALID',
225
- message: `artifact '${request.artifact}' does not match ${request.family}`
226
- }, { taskId: resolved.taskId, taskDir: resolved.taskDir });
227
- }
228
- const validated = validateCompletedArtifact(resolved.taskDir, request.family, request.artifact, parsed.round);
229
- if (!validated.ok) {
230
- return failedFinalization(request, validated.error, { taskId: resolved.taskId, taskDir: resolved.taskDir });
231
- }
150
+ if (!parsed || parsed.family !== request.family)
151
+ return failed('ARTIFACT_IDENTITY_INVALID', `artifact '${request.artifact}' does not match ${request.family}`);
232
152
  let content;
153
+ let taskContent;
233
154
  try {
234
- content = fs.readFileSync(validated.artifact.path, 'utf8');
155
+ taskContent = fs.readFileSync(resolved.taskMdPath, 'utf8');
156
+ if (candidate !== undefined) {
157
+ const error = validateArtifactPublication(resolved.taskDir, request.family, request.artifact);
158
+ if (error)
159
+ return failed(error.code, error.message);
160
+ if (resolved.state !== 'active' || !hasOpenArtifactRound(taskContent, request.family, parsed.round)) {
161
+ return failed('ARTIFACT_IDENTITY_INVALID', 'candidate must match one open started round in an active task');
162
+ }
163
+ content = candidate;
164
+ }
165
+ else {
166
+ const validated = validateCompletedArtifact(resolved.taskDir, request.family, request.artifact, parsed.round);
167
+ if (!validated.ok)
168
+ return failed(validated.error.code, validated.error.message);
169
+ content = fs.readFileSync(validated.artifact.path, 'utf8');
170
+ }
235
171
  }
236
172
  catch (error) {
237
- return failedFinalization(request, { code: 'ARTIFACT_NOT_READABLE', message: String(error) }, {
238
- taskId: resolved.taskId, taskDir: resolved.taskDir
239
- });
173
+ return failed('ARTIFACT_NOT_READABLE', String(error));
240
174
  }
241
- const result = validateLocalArtifact(content, {
242
- family: request.family,
243
- requiredSections: request.requiredSections,
244
- requiredPatterns: request.requiredPatterns
175
+ const validation = validateLocalArtifact(content, {
176
+ family: request.family, requiredSections: request.requiredSections, taskContent, artifact: request.artifact
245
177
  });
246
178
  const artifactSha256 = sha256Content(content);
179
+ const { semanticDigest, repairable, diagnostics } = validation;
180
+ const result = failedFinalization(request, {
181
+ code: 'LOCAL_ARTIFACT_INVALID', message: diagnostics.map((item) => `${item.code}: ${item.message}`).join('; ')
182
+ }, { taskId: resolved.taskId, taskDir: resolved.taskDir, artifactSha256, semanticDigest, repairable, diagnostics });
183
+ const preparedBase = { result, content, repoRoot: resolved.repoRoot };
184
+ if (authority !== undefined && !validFinalizerAuthority(authority, request, resolved.taskId)) {
185
+ return {
186
+ ...preparedBase,
187
+ result: { ...result, repairable: false, error: {
188
+ code: 'LOCAL_EXECUTION_AUTHORITY_INVALID',
189
+ message: 'finalizer authority does not match the artifact tuple'
190
+ }, diagnostics: [] }
191
+ };
192
+ }
193
+ const reject = (code, message) => ({
194
+ ...prepared, result: { ...result, repairable: false, error: { code, message },
195
+ diagnostics: [{ code, message, repairable: false, line: null }] }
196
+ });
247
197
  let intent;
248
198
  try {
249
- intent = readLocalArtifactFinalizationIntent(resolved.repoRoot, resolved.taskId, request.family, request.artifact);
199
+ intent = readArtifactRepairIntent(resolved.repoRoot, resolved.taskId, request.family, request.artifact);
250
200
  }
251
201
  catch (error) {
252
- return failedFinalization(request, {
253
- code: 'LOCAL_FINALIZATION_INTENT_INVALID',
254
- message: error instanceof Error ? error.message : String(error)
255
- }, { taskId: resolved.taskId, taskDir: resolved.taskDir, artifactSha256, semanticDigest: result.semanticDigest });
202
+ return { ...preparedBase, result: { ...result, repairable: false, diagnostics: [],
203
+ error: { code: 'LOCAL_FINALIZATION_INTENT_INVALID', message: String(error) } } };
256
204
  }
257
- if (result.repairable) {
258
- if (intent && (intent.state !== 'awaiting-repair' || intent.baselineSemanticDigest !== result.semanticDigest)) {
259
- return provenanceFailure(request, resolved, content, artifactSha256, result.semanticDigest, 'LOCAL_REPAIR_PROVENANCE_CONFLICT', 'a different local repair baseline is already recorded for this artifact');
260
- }
261
- if (!intent) {
262
- try {
263
- writeLocalArtifactFinalizationIntent(resolved.repoRoot, {
264
- version: 1,
265
- taskId: resolved.taskId,
266
- family: request.family,
267
- artifact: request.artifact,
268
- state: 'awaiting-repair',
269
- baselineSemanticDigest: result.semanticDigest,
270
- artifactSha256,
271
- semanticDigest: result.semanticDigest
272
- });
273
- }
274
- catch (error) {
275
- return failedFinalization(request, {
276
- code: 'LOCAL_FINALIZATION_INTENT_WRITE_FAILED',
277
- message: error instanceof Error ? error.message : String(error)
278
- }, { taskId: resolved.taskId, taskDir: resolved.taskDir, artifactSha256, semanticDigest: result.semanticDigest });
279
- }
280
- }
281
- return {
282
- status: 'failed',
283
- changed: false,
284
- taskId: resolved.taskId,
285
- taskDir: resolved.taskDir,
286
- family: request.family,
287
- artifact: request.artifact,
288
- artifactSha256,
289
- semanticDigest: result.semanticDigest,
290
- repairable: true,
291
- diagnostics: result.diagnostics,
292
- error: {
293
- code: 'LOCAL_ARTIFACT_INVALID',
294
- message: result.diagnostics.map((item) => `${item.code}: ${item.message}`).join('; ')
295
- }
296
- };
205
+ const prepared = { ...preparedBase, expectedIntent: intent };
206
+ if (intent && intent.recoveryOperationId !== null
207
+ && (!authority || intent.recoveryOperationId !== authority.operationId)) {
208
+ return reject('LOCAL_REPAIR_PROVENANCE_CONFLICT', 'local repair provenance is owned by another recovery operation');
297
209
  }
298
- if (!result.ok) {
299
- return {
300
- status: 'failed',
301
- changed: false,
302
- taskId: resolved.taskId,
303
- taskDir: resolved.taskDir,
304
- family: request.family,
305
- artifact: request.artifact,
306
- artifactSha256,
307
- semanticDigest: result.semanticDigest,
308
- repairable: false,
309
- diagnostics: result.diagnostics,
310
- error: {
311
- code: 'LOCAL_ARTIFACT_INVALID',
312
- message: result.diagnostics.map((item) => `${item.code}: ${item.message}`).join('; ')
313
- }
314
- };
315
- }
316
- if (intent?.state === 'awaiting-repair' && intent.baselineSemanticDigest !== result.semanticDigest) {
317
- return provenanceFailure(request, resolved, content, artifactSha256, result.semanticDigest, 'LOCAL_REPAIR_BASELINE_MISMATCH', 'the repaired artifact semantic digest does not match the recorded repair baseline');
318
- }
319
- if ((intent?.state === 'passed' || intent?.state === 'consumed')
320
- && (intent.artifactSha256 !== artifactSha256 || intent.semanticDigest !== result.semanticDigest)) {
321
- return provenanceFailure(request, resolved, content, artifactSha256, result.semanticDigest, 'LOCAL_REPAIR_PROVENANCE_CONFLICT', 'the artifact changed after its finalization provenance was recorded');
210
+ if (repairable) {
211
+ if (intent && (intent.state !== 'awaiting-repair' || intent.baselineSemanticDigest !== semanticDigest)) {
212
+ return reject('LOCAL_REPAIR_PROVENANCE_CONFLICT', 'a different local repair baseline is already recorded for this artifact');
213
+ }
214
+ if (intent && !authority)
215
+ return prepared;
322
216
  }
323
- if (intent?.state === 'consumed') {
324
- return {
325
- status: 'passed',
326
- changed: false,
327
- taskId: resolved.taskId,
328
- taskDir: resolved.taskDir,
329
- family: request.family,
330
- artifact: request.artifact,
331
- artifactSha256,
332
- semanticDigest: result.semanticDigest,
333
- repairable: false,
334
- diagnostics: result.diagnostics,
335
- error: null
336
- };
217
+ else {
218
+ if (!validation.ok)
219
+ return prepared;
220
+ if (intent?.state === 'awaiting-repair' && intent.baselineSemanticDigest !== semanticDigest) {
221
+ return reject('LOCAL_REPAIR_BASELINE_MISMATCH', 'the repaired artifact semantic digest does not match the recorded repair baseline');
222
+ }
223
+ if ((intent?.state === 'passed' || intent?.state === 'consumed')
224
+ && (intent.artifactSha256 !== artifactSha256 || intent.semanticDigest !== semanticDigest)) {
225
+ return reject('LOCAL_REPAIR_PROVENANCE_CONFLICT', 'the artifact changed after its finalization provenance was recorded');
226
+ }
227
+ prepared.result = { ...result, status: 'passed', error: null };
228
+ if (intent?.state === 'consumed')
229
+ return prepared;
337
230
  }
231
+ const timestamp = Date.now();
232
+ return { ...prepared, provenance: {
233
+ version: 2, taskId: resolved.taskId, family: request.family, artifact: request.artifact,
234
+ state: repairable ? 'awaiting-repair' : 'passed',
235
+ baselineSemanticDigest: repairable ? semanticDigest : intent?.baselineSemanticDigest ?? null,
236
+ artifactSha256, semanticDigest,
237
+ recoveryOperationId: authority?.operationId ?? intent?.recoveryOperationId ?? null,
238
+ phase: authority?.phase ?? intent?.phase ?? null,
239
+ authorityDigest: authority ? authorityDigest(authority) : intent?.authorityDigest ?? null,
240
+ requestId: authority?.lifecycleRequestId ?? intent?.requestId ?? `local-finalize:${resolved.taskId}`,
241
+ createdAt: intent?.createdAt ?? timestamp,
242
+ updatedAt: timestamp
243
+ } };
244
+ }
245
+ function commitLocalArtifactProvenance(prepared) {
338
246
  try {
339
- writeLocalArtifactFinalizationIntent(resolved.repoRoot, {
340
- version: 1,
341
- taskId: resolved.taskId,
342
- family: request.family,
343
- artifact: request.artifact,
344
- state: 'passed',
345
- baselineSemanticDigest: intent?.baselineSemanticDigest ?? null,
346
- artifactSha256,
347
- semanticDigest: result.semanticDigest
348
- });
247
+ if (prepared.provenance) {
248
+ writeArtifactRepairIntent(prepared.repoRoot, prepared.provenance, { expected: prepared.expectedIntent ?? null });
249
+ }
250
+ return prepared.result;
349
251
  }
350
252
  catch (error) {
351
- return failedFinalization(request, {
352
- code: 'LOCAL_FINALIZATION_INTENT_WRITE_FAILED',
353
- message: error instanceof Error ? error.message : String(error)
354
- }, { taskId: resolved.taskId, taskDir: resolved.taskDir, artifactSha256, semanticDigest: result.semanticDigest });
253
+ return { ...prepared.result, status: 'failed', error: {
254
+ code: 'LOCAL_FINALIZATION_INTENT_WRITE_FAILED', message: String(error)
255
+ } };
355
256
  }
356
- return {
357
- status: result.ok ? 'passed' : 'failed',
358
- changed: false,
359
- taskId: resolved.taskId,
360
- taskDir: resolved.taskDir,
361
- family: request.family,
362
- artifact: request.artifact,
363
- artifactSha256,
364
- semanticDigest: result.semanticDigest,
365
- repairable: result.repairable,
366
- diagnostics: result.diagnostics,
367
- error: result.ok ? null : {
368
- code: 'LOCAL_ARTIFACT_INVALID',
369
- message: result.diagnostics.map((item) => `${item.code}: ${item.message}`).join('; ')
257
+ }
258
+ function finalizeLocalArtifact(request, authority, options = {}) {
259
+ const result = commitLocalArtifactProvenance(prepareLocalArtifact(request, undefined, authority));
260
+ if (authority && !options.deferLifecycleRecoveryConsumption && result.status === 'passed') {
261
+ try {
262
+ consumeLifecycleRecoveryAttestation(authority);
370
263
  }
371
- };
264
+ catch (error) {
265
+ return { ...result, status: 'failed', error: {
266
+ code: 'LOCAL_EXECUTION_AUTHORITY_CONSUME_FAILED',
267
+ message: error instanceof Error ? error.message : String(error)
268
+ } };
269
+ }
270
+ }
271
+ return result;
372
272
  }
373
- export { LOCAL_ARTIFACT_REQUIRED_PATTERNS, LOCAL_ARTIFACT_REQUIRED_SECTIONS, consumeLocalArtifactFinalizationIntent, finalizeLocalArtifact, readLocalArtifactFinalizationIntent, semanticDigest, sha256Content, validateLocalArtifact };
273
+ export { LOCAL_ARTIFACT_REQUIRED_SECTIONS, consumeLocalArtifactFinalizationIntent, finalizeLocalArtifact, prepareLocalArtifact, commitLocalArtifactProvenance, readArtifactRepairIntent as readLocalArtifactFinalizationIntent, canonicalSemanticDigest as semanticDigest, sha256Content, validateLocalArtifact };
374
274
  //# sourceMappingURL=local-artifact-finalization.js.map
@@ -0,0 +1,26 @@
1
+ import { readManualValidationReceipt } from './manual-validation-receipt.js';
2
+ import { readManualValidationTransaction } from './manual-validation-transaction.js';
3
+ function readManualValidationCompletion(taskDir, expected = {}) {
4
+ const { receiptDigest: expectedReceiptDigest, ...receiptIdentity } = expected;
5
+ const receipt = readManualValidationReceipt(taskDir, receiptIdentity);
6
+ if (!receipt.ok)
7
+ return receipt;
8
+ if (expectedReceiptDigest !== undefined && receipt.value.receiptDigest !== expectedReceiptDigest) {
9
+ return { ok: false, error: { code: 'MANUAL_VALIDATION_RECEIPT_IDENTITY_MISMATCH', message: 'receipt digest does not match the expected completion' } };
10
+ }
11
+ const transaction = readManualValidationTransaction(taskDir, {
12
+ transactionId: receipt.value.transactionId,
13
+ taskId: receipt.value.taskId,
14
+ prNumber: receipt.value.prNumber,
15
+ prHeadSha: receipt.value.prHeadSha,
16
+ artifact: receipt.value.artifact
17
+ });
18
+ if (!transaction.ok)
19
+ return transaction;
20
+ if (transaction.value.committedReceipt !== receipt.value.receiptDigest) {
21
+ return { ok: false, error: { code: 'MANUAL_VALIDATION_TRANSACTION_PHASE_INVALID', message: 'completion transaction is not bound to the canonical receipt' } };
22
+ }
23
+ return { ok: true, value: { receipt: receipt.value, transaction: transaction.value } };
24
+ }
25
+ export { readManualValidationCompletion };
26
+ //# sourceMappingURL=manual-validation-completion.js.map