@fitlab-ai/agent-infra 0.9.14 → 0.10.0

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 (354) hide show
  1. package/README.md +10 -0
  2. package/README.zh-CN.md +10 -0
  3. package/bin/internal-cli.sh +45 -0
  4. package/dist/bin/internal-cli.js +93 -30
  5. package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +165 -27
  6. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +9 -4
  7. package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +43 -3
  8. package/dist/lib/defaults.json +103 -103
  9. package/dist/lib/fs/durable-write.js +39 -0
  10. package/dist/lib/fs/file-lock.js +111 -0
  11. package/dist/lib/host-control/audit.js +19 -0
  12. package/dist/lib/host-control/client.js +142 -0
  13. package/dist/lib/host-control/command.js +49 -0
  14. package/dist/lib/host-control/path.js +160 -0
  15. package/dist/lib/host-control/secure-fs.js +140 -0
  16. package/dist/lib/host-control/server.js +159 -0
  17. package/dist/lib/host-control/service.js +112 -0
  18. package/dist/lib/init.js +11 -2
  19. package/dist/lib/internal/cli-route-inventory.js +4 -2
  20. package/dist/lib/internal/codex-lifecycle.js +6 -6
  21. package/dist/lib/internal/demo-promotion.js +322 -0
  22. package/dist/lib/internal/demo-transcript.js +454 -0
  23. package/dist/lib/internal/host-control.js +28 -0
  24. package/dist/lib/internal/manual-validation.js +331 -0
  25. package/dist/lib/internal/platform-pr.js +18 -4
  26. package/dist/lib/internal/release-workflow.js +63 -84
  27. package/dist/lib/internal/sandbox-control.js +149 -2
  28. package/dist/lib/internal/task-artifact.js +16 -263
  29. package/dist/lib/internal/task-create.js +6 -5
  30. package/dist/lib/internal/task-event.js +37 -37
  31. package/dist/lib/internal/task-lifecycle.js +2 -2
  32. package/dist/lib/internal/task-operation-registry.js +101 -4
  33. package/dist/lib/internal/task-review.js +11 -56
  34. package/dist/lib/internal/task-validate.js +30 -10
  35. package/dist/lib/owned-path.js +33 -0
  36. package/dist/lib/platform/check-status.js +11 -0
  37. package/dist/lib/platform/comment-safety.js +4 -1
  38. package/dist/lib/platform/completion-backfill.js +1 -1
  39. package/dist/lib/platform/github-data.js +241 -0
  40. package/dist/lib/platform/github-provider.js +15 -20
  41. package/dist/lib/platform/issue-comments.js +18 -12
  42. package/dist/lib/platform/issues.js +2 -180
  43. package/dist/lib/platform/pr-change-report.js +5 -4
  44. package/dist/lib/platform/pr-checks.js +12 -65
  45. package/dist/lib/platform/pr-summary.js +117 -33
  46. package/dist/lib/platform/pull-requests.js +5 -108
  47. package/dist/lib/platform/snapshots.js +2 -0
  48. package/dist/lib/platform/task-identities.js +2 -9
  49. package/dist/lib/platform/verification-sync.js +132 -143
  50. package/dist/lib/pr-review/evidence-grading.js +4 -8
  51. package/dist/lib/release/workflow.js +1 -1
  52. package/dist/lib/sandbox/commands/create.js +7 -2
  53. package/dist/lib/sandbox/commands/rm.js +19 -1511
  54. package/dist/lib/sandbox/control/audit.js +203 -0
  55. package/dist/lib/sandbox/control/client.js +93 -54
  56. package/dist/lib/sandbox/control/executor.js +129 -65
  57. package/dist/lib/sandbox/control/finalization-response.js +27 -0
  58. package/dist/lib/sandbox/control/identity-sentinel.js +107 -0
  59. package/dist/lib/sandbox/control/lifecycle.js +36 -2
  60. package/dist/lib/sandbox/control/native-file-lock.js +6 -98
  61. package/dist/lib/sandbox/control/protocol.js +55 -4
  62. package/dist/lib/sandbox/control/server.js +518 -127
  63. package/dist/lib/sandbox/control/state.js +64 -0
  64. package/dist/lib/sandbox/control/task-workflow.js +74 -0
  65. package/dist/lib/sandbox/control/workflow-executor.js +89 -0
  66. package/dist/lib/sandbox/index.js +1 -2
  67. package/dist/lib/sandbox/recovery.js +28 -4
  68. package/dist/lib/sandbox/removal.js +822 -0
  69. package/dist/lib/sandbox/task-cleanup.js +217 -0
  70. package/dist/lib/sandbox/workspace-identity.js +17 -1
  71. package/dist/lib/sandbox/workspace-view.js +13 -14
  72. package/dist/lib/task/activity-intent.js +2 -1
  73. package/dist/lib/task/activity-log.js +30 -24
  74. package/dist/lib/task/artifact-command.js +79 -0
  75. package/dist/lib/task/artifact-lifecycle.js +30 -28
  76. package/dist/lib/task/artifact-name.js +36 -0
  77. package/dist/lib/task/artifact-operations.js +29 -289
  78. package/dist/lib/task/artifact-receipts.js +3 -15
  79. package/dist/lib/task/artifact-recovery.js +430 -0
  80. package/dist/lib/task/artifact-repair-intent.js +134 -29
  81. package/dist/lib/task/artifact-schema.js +6 -14
  82. package/dist/lib/task/capabilities.js +12 -19
  83. package/dist/lib/task/codex-orchestration.js +71 -25
  84. package/dist/lib/task/commit-identity.js +28 -0
  85. package/dist/lib/task/commit-operation.js +33 -20
  86. package/dist/lib/task/control-authority.js +403 -6
  87. package/dist/lib/task/control-recovery.js +140 -0
  88. package/dist/lib/task/create-service.js +1 -8
  89. package/dist/lib/task/create.js +62 -9
  90. package/dist/lib/task/decision-details.js +2 -46
  91. package/dist/lib/task/delegation-receipts.js +64 -3
  92. package/dist/lib/task/events.js +275 -22
  93. package/dist/lib/task/finalization-state.js +9 -0
  94. package/dist/lib/task/human-override.js +8 -14
  95. package/dist/lib/task/implementation-inputs.js +3 -3
  96. package/dist/lib/task/intermediate-cleanup.js +441 -0
  97. package/dist/lib/task/invalidation.js +18 -65
  98. package/dist/lib/task/ledger-intents.js +7 -22
  99. package/dist/lib/task/ledger.js +1 -3
  100. package/dist/lib/task/lifecycle-recovery.js +549 -0
  101. package/dist/lib/task/lifecycle.js +31 -4
  102. package/dist/lib/task/local-artifact-finalization.js +197 -197
  103. package/dist/lib/task/manual-validation-completion.js +26 -0
  104. package/dist/lib/task/manual-validation-evidence.js +130 -0
  105. package/dist/lib/task/manual-validation-receipt.js +105 -0
  106. package/dist/lib/task/manual-validation-shared.js +40 -0
  107. package/dist/lib/task/manual-validation-transaction.js +243 -0
  108. package/dist/lib/task/markdown.js +47 -0
  109. package/dist/lib/task/orchestration.js +66 -19
  110. package/dist/lib/task/pr-delivery-fact.js +12 -56
  111. package/dist/lib/task/qualification-audit.js +20 -34
  112. package/dist/lib/task/recovery-warning.js +19 -0
  113. package/dist/lib/task/review-artifacts.js +2 -18
  114. package/dist/lib/task/review-command.js +26 -0
  115. package/dist/lib/task/review-finalization.js +175 -216
  116. package/dist/lib/task/review-fingerprint.js +2 -2
  117. package/dist/lib/task/sections.js +34 -56
  118. package/dist/lib/task/short-id.js +15 -7
  119. package/dist/lib/task/task-execution-lock.js +1 -1
  120. package/dist/lib/task/verification-engine.js +119 -337
  121. package/dist/lib/task/verification.js +1 -1
  122. package/dist/lib/task/workflow-command.js +16 -0
  123. package/dist/lib/task/workflow-warning-intents.js +0 -16
  124. package/dist/lib/task/workflow-warnings.js +28 -2
  125. package/dist/lib/update.js +2 -0
  126. package/dist/lib/version.js +1 -11
  127. package/dist/lifecycle-build-manifest.json +3 -3
  128. package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +223 -33
  129. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +10 -4
  130. package/lib/agent-clients/adapters/codex-lifecycle/store.ts +55 -3
  131. package/lib/fs/durable-write.ts +30 -0
  132. package/lib/fs/file-lock.ts +113 -0
  133. package/lib/host-control/audit.ts +22 -0
  134. package/lib/host-control/client.ts +172 -0
  135. package/lib/host-control/command.ts +60 -0
  136. package/lib/host-control/path.ts +167 -0
  137. package/lib/host-control/secure-fs.ts +135 -0
  138. package/lib/host-control/server.ts +180 -0
  139. package/lib/host-control/service.ts +133 -0
  140. package/lib/init.ts +15 -2
  141. package/lib/internal/cli-route-inventory.ts +4 -2
  142. package/lib/internal/codex-lifecycle.ts +6 -6
  143. package/lib/internal/demo-promotion.ts +354 -0
  144. package/lib/internal/demo-transcript.ts +419 -0
  145. package/lib/internal/host-control.ts +28 -0
  146. package/lib/internal/manual-validation.ts +315 -0
  147. package/lib/internal/platform-pr.ts +15 -4
  148. package/lib/internal/release-workflow.ts +74 -82
  149. package/lib/internal/sandbox-control.ts +162 -1
  150. package/lib/internal/task-artifact.ts +14 -217
  151. package/lib/internal/task-create.ts +5 -5
  152. package/lib/internal/task-event.ts +20 -11
  153. package/lib/internal/task-lifecycle.ts +4 -3
  154. package/lib/internal/task-operation-registry.ts +111 -4
  155. package/lib/internal/task-review.ts +9 -54
  156. package/lib/internal/task-validate.ts +26 -10
  157. package/lib/owned-path.ts +26 -0
  158. package/lib/platform/check-status.ts +9 -0
  159. package/lib/platform/comment-safety.ts +5 -0
  160. package/lib/platform/completion-backfill.ts +1 -1
  161. package/lib/platform/github-data.ts +322 -0
  162. package/lib/platform/github-provider.ts +15 -20
  163. package/lib/platform/issue-comments.ts +21 -14
  164. package/lib/platform/issues.ts +5 -246
  165. package/lib/platform/pr-change-report.ts +7 -5
  166. package/lib/platform/pr-checks.ts +13 -77
  167. package/lib/platform/pr-summary.ts +123 -35
  168. package/lib/platform/pull-requests.ts +6 -173
  169. package/lib/platform/snapshots.ts +53 -0
  170. package/lib/platform/task-identities.ts +3 -14
  171. package/lib/platform/verification-sync.ts +150 -156
  172. package/lib/pr-review/evidence-grading.ts +4 -9
  173. package/lib/release/workflow.ts +3 -3
  174. package/lib/sandbox/commands/create.ts +7 -6
  175. package/lib/sandbox/commands/rm.ts +21 -1895
  176. package/lib/sandbox/control/audit.ts +253 -0
  177. package/lib/sandbox/control/client.ts +109 -66
  178. package/lib/sandbox/control/executor.ts +134 -74
  179. package/lib/sandbox/control/finalization-response.ts +29 -0
  180. package/lib/sandbox/control/identity-sentinel.ts +137 -0
  181. package/lib/sandbox/control/lifecycle.ts +45 -3
  182. package/lib/sandbox/control/native-file-lock.ts +6 -107
  183. package/lib/sandbox/control/protocol.ts +80 -6
  184. package/lib/sandbox/control/server.ts +567 -132
  185. package/lib/sandbox/control/state.ts +86 -0
  186. package/lib/sandbox/control/task-workflow.ts +95 -0
  187. package/lib/sandbox/control/workflow-executor.ts +92 -0
  188. package/lib/sandbox/index.ts +1 -2
  189. package/lib/sandbox/recovery.ts +28 -5
  190. package/lib/sandbox/removal.ts +1142 -0
  191. package/lib/sandbox/task-cleanup.ts +209 -0
  192. package/lib/sandbox/workspace-identity.ts +19 -3
  193. package/lib/sandbox/workspace-view.ts +17 -15
  194. package/lib/task/activity-intent.ts +2 -2
  195. package/lib/task/activity-log.ts +27 -19
  196. package/lib/task/artifact-command.ts +85 -0
  197. package/lib/task/artifact-lifecycle.ts +31 -26
  198. package/lib/task/artifact-name.ts +55 -0
  199. package/lib/task/artifact-operations.ts +34 -310
  200. package/lib/task/artifact-receipts.ts +3 -14
  201. package/lib/task/artifact-recovery.ts +519 -0
  202. package/lib/task/artifact-repair-intent.ts +162 -33
  203. package/lib/task/artifact-schema.ts +5 -34
  204. package/lib/task/capabilities.ts +13 -22
  205. package/lib/task/codex-orchestration.ts +85 -24
  206. package/lib/task/commit-identity.ts +31 -0
  207. package/lib/task/commit-operation.ts +37 -20
  208. package/lib/task/control-authority.ts +540 -10
  209. package/lib/task/control-recovery.ts +186 -0
  210. package/lib/task/create-service.ts +1 -10
  211. package/lib/task/create.ts +63 -8
  212. package/lib/task/decision-details.ts +3 -71
  213. package/lib/task/delegation-receipts.ts +73 -2
  214. package/lib/task/events.ts +309 -24
  215. package/lib/task/finalization-state.ts +11 -0
  216. package/lib/task/human-override.ts +8 -16
  217. package/lib/task/implementation-inputs.ts +3 -3
  218. package/lib/task/intermediate-cleanup.ts +493 -0
  219. package/lib/task/invalidation.ts +18 -62
  220. package/lib/task/ledger-intents.ts +7 -24
  221. package/lib/task/ledger.ts +1 -3
  222. package/lib/task/lifecycle-recovery.ts +691 -0
  223. package/lib/task/lifecycle.ts +30 -5
  224. package/lib/task/local-artifact-finalization.ts +244 -234
  225. package/lib/task/manual-validation-completion.ts +40 -0
  226. package/lib/task/manual-validation-evidence.ts +209 -0
  227. package/lib/task/manual-validation-receipt.ts +156 -0
  228. package/lib/task/manual-validation-shared.ts +50 -0
  229. package/lib/task/manual-validation-transaction.ts +304 -0
  230. package/lib/task/markdown.ts +70 -0
  231. package/lib/task/orchestration.ts +84 -19
  232. package/lib/task/pr-delivery-fact.ts +15 -62
  233. package/lib/task/qualification-audit.ts +22 -33
  234. package/lib/task/recovery-warning.ts +21 -0
  235. package/lib/task/review-artifacts.ts +1 -20
  236. package/lib/task/review-command.ts +24 -0
  237. package/lib/task/review-finalization.ts +183 -292
  238. package/lib/task/review-fingerprint.ts +2 -2
  239. package/lib/task/sections.ts +33 -54
  240. package/lib/task/short-id.ts +27 -5
  241. package/lib/task/task-execution-lock.ts +1 -1
  242. package/lib/task/verification-engine.ts +113 -383
  243. package/lib/task/verification-types.ts +15 -0
  244. package/lib/task/verification.ts +1 -1
  245. package/lib/task/workflow-command.ts +17 -0
  246. package/lib/task/workflow-warning-intents.ts +0 -13
  247. package/lib/task/workflow-warnings.ts +21 -2
  248. package/lib/update.ts +6 -0
  249. package/lib/version.ts +1 -15
  250. package/package.json +6 -6
  251. package/templates/.agents/hooks/lifecycle-delegation.js +6 -6
  252. package/templates/.agents/rules/create-issue.en.md +1 -1
  253. package/templates/.agents/rules/create-issue.zh-CN.md +1 -1
  254. package/templates/.agents/rules/issue-sync.en.md +4 -2
  255. package/templates/.agents/rules/issue-sync.zh-CN.md +4 -3
  256. package/templates/.agents/rules/local-artifact-repair.en.md +46 -39
  257. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +43 -36
  258. package/templates/.agents/rules/testing-discipline.en.md +2 -0
  259. package/templates/.agents/rules/testing-discipline.zh-CN.md +2 -0
  260. package/templates/.agents/scripts/package.json +3 -0
  261. package/templates/.agents/skills/analyze-task/SKILL.en.md +6 -6
  262. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +6 -6
  263. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -1
  264. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -1
  265. package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
  266. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
  267. package/templates/.agents/skills/block-task/config/verify.json +1 -1
  268. package/templates/.agents/skills/cancel-task/SKILL.en.md +3 -3
  269. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +3 -3
  270. package/templates/.agents/skills/cancel-task/config/verify.json +1 -1
  271. package/templates/.agents/skills/code-task/SKILL.en.md +7 -7
  272. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +7 -7
  273. package/templates/.agents/skills/code-task/config/verify.en.json +1 -1
  274. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -1
  275. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +1 -1
  276. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +1 -1
  277. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +33 -21
  278. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +33 -21
  279. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
  280. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
  281. package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +2 -0
  282. package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +2 -0
  283. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +16 -7
  284. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +16 -7
  285. package/templates/.agents/skills/complete-task/SKILL.en.md +3 -3
  286. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +3 -3
  287. package/templates/.agents/skills/complete-task/config/verify.en.json +2 -2
  288. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +2 -2
  289. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +1 -1
  290. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +1 -1
  291. package/templates/.agents/skills/create-pr/SKILL.en.md +2 -2
  292. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +2 -2
  293. package/templates/.agents/skills/create-pr/config/verify.json +1 -1
  294. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +2 -2
  295. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +2 -2
  296. package/templates/.agents/skills/create-task/SKILL.en.md +5 -5
  297. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +5 -5
  298. package/templates/.agents/skills/create-task/config/verify.json +1 -1
  299. package/templates/.agents/skills/import-issue/SKILL.en.md +8 -8
  300. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +8 -8
  301. package/templates/.agents/skills/import-issue/config/verify.json +2 -2
  302. package/templates/.agents/skills/plan-task/SKILL.en.md +4 -4
  303. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +4 -4
  304. package/templates/.agents/skills/plan-task/config/verify.en.json +1 -1
  305. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -1
  306. package/templates/.agents/skills/release/SKILL.en.md +7 -3
  307. package/templates/.agents/skills/release/SKILL.zh-CN.md +7 -3
  308. package/templates/.agents/skills/restore-task/SKILL.en.md +2 -2
  309. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +2 -2
  310. package/templates/.agents/skills/restore-task/config/verify.json +1 -1
  311. package/templates/.agents/skills/review-analysis/SKILL.en.md +2 -2
  312. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +2 -2
  313. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -1
  314. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -1
  315. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +7 -7
  316. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +6 -6
  317. package/templates/.agents/skills/review-code/SKILL.en.md +2 -2
  318. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +2 -2
  319. package/templates/.agents/skills/review-code/config/verify.en.json +1 -1
  320. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -1
  321. package/templates/.agents/skills/review-code/reference/report-template.en.md +12 -12
  322. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +12 -12
  323. package/templates/.agents/skills/review-plan/SKILL.en.md +2 -2
  324. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +2 -2
  325. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -1
  326. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -1
  327. package/templates/.agents/skills/review-plan/reference/report-template.en.md +7 -7
  328. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +7 -7
  329. package/templates/.agents/skills/review-pr/config/verify.en.json +1 -1
  330. package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +1 -1
  331. package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +3 -3
  332. package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +3 -3
  333. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +20 -3
  334. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +20 -3
  335. package/templates/.agents/skills/run-manual-validation/config/verify.en.json +1 -1
  336. package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +1 -1
  337. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +4 -1
  338. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +4 -1
  339. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -0
  340. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -0
  341. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  342. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  343. package/templates/.agents/skills/test/SKILL.en.md +17 -6
  344. package/templates/.agents/skills/test/SKILL.zh-CN.md +17 -6
  345. package/templates/.agents/templates/task.en.md +1 -1
  346. package/templates/.agents/templates/task.zh-CN.md +1 -1
  347. package/templates/.claude/commands/import-issue.en.md +1 -1
  348. package/templates/.claude/commands/import-issue.zh-CN.md +1 -1
  349. package/templates/.claude/commands/restore-task.en.md +1 -1
  350. package/templates/.claude/commands/restore-task.zh-CN.md +1 -1
  351. package/templates/.claude/commands/run-manual-validation.en.md +1 -1
  352. package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
  353. package/dist/lib/platform/adapters.js +0 -56
  354. package/lib/platform/adapters.ts +0 -197
@@ -0,0 +1,105 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { createHash } from 'node:crypto';
4
+ import { MANUAL_VALIDATION_ARTIFACT as ARTIFACT, MANUAL_VALIDATION_SHA40 as SHA40, MANUAL_VALIDATION_SHA64 as SHA64, MANUAL_VALIDATION_TASK_ID as TASK_ID, exactKeys, isRecord, validTimestamp, writeJsonAtomic } from './manual-validation-shared.js';
5
+ const MANUAL_VALIDATION_RECEIPT_SCHEMA = 'agent-infra/manual-validation-receipt';
6
+ const MANUAL_VALIDATION_RECEIPT_VERSION = 1;
7
+ function invalid(message) {
8
+ return { ok: false, error: { code: 'MANUAL_VALIDATION_RECEIPT_INVALID', message } };
9
+ }
10
+ function canonicalPayload(receipt) {
11
+ return {
12
+ schema: MANUAL_VALIDATION_RECEIPT_SCHEMA,
13
+ version: MANUAL_VALIDATION_RECEIPT_VERSION,
14
+ transactionId: receipt.transactionId,
15
+ taskId: receipt.taskId,
16
+ prNumber: receipt.prNumber,
17
+ prHeadSha: receipt.prHeadSha,
18
+ evidenceDigest: receipt.evidenceDigest,
19
+ artifact: receipt.artifact,
20
+ artifactSha256: receipt.artifactSha256,
21
+ pendingSummaryDigest: receipt.pendingSummaryDigest,
22
+ finalSummaryDigest: receipt.finalSummaryDigest,
23
+ committedAt: receipt.committedAt
24
+ };
25
+ }
26
+ function manualValidationReceiptDigest(receipt) {
27
+ return createHash('sha256').update(JSON.stringify(canonicalPayload(receipt)), 'utf8').digest('hex');
28
+ }
29
+ function manualValidationFinalSummaryDigest(body) {
30
+ const heading = /^###\s+✅\s+(?:Manual Validation Passed|人工验证已通过)\s*$/mu.exec(body);
31
+ const afterHeading = heading ? body.slice(heading.index + heading[0].length) : '';
32
+ const nextSection = heading ? /^#{1,3}\s/mu.exec(afterHeading) : null;
33
+ const projection = heading
34
+ ? body.slice(heading.index, heading.index + heading[0].length + (nextSection?.index ?? afterHeading.length)).replace(/\s+$/u, '')
35
+ : body;
36
+ const preimage = projection.replace(/receipt=(?:[a-f0-9]{64}|<receipt>)/gu, 'receipt=<receipt>');
37
+ return createHash('sha256').update(preimage, 'utf8').digest('hex');
38
+ }
39
+ function manualValidationFinalSummaryProjectionMatches(body, receipt) {
40
+ const identity = `transaction=${receipt.transactionId}; receipt=${receipt.receiptDigest}; evidence=${receipt.evidenceDigest}; head=${receipt.prHeadSha}`;
41
+ return body.includes(identity) && manualValidationFinalSummaryDigest(body) === receipt.finalSummaryDigest;
42
+ }
43
+ function validateManualValidationReceipt(value, expected) {
44
+ if (!isRecord(value))
45
+ return invalid('receipt must be a JSON object');
46
+ const keys = ['schema', 'version', 'transactionId', 'taskId', 'prNumber', 'prHeadSha', 'evidenceDigest', 'artifact', 'artifactSha256', 'pendingSummaryDigest', 'finalSummaryDigest', 'committedAt', 'receiptDigest'];
47
+ const keyError = exactKeys(value, keys, 'receipt');
48
+ if (keyError)
49
+ return invalid(keyError);
50
+ if (value.schema !== MANUAL_VALIDATION_RECEIPT_SCHEMA || value.version !== MANUAL_VALIDATION_RECEIPT_VERSION)
51
+ return invalid('receipt schema or version is unsupported');
52
+ if (typeof value.transactionId !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(value.transactionId))
53
+ return invalid('transactionId is invalid');
54
+ if (typeof value.taskId !== 'string' || !TASK_ID.test(value.taskId))
55
+ return invalid('taskId is invalid');
56
+ const prNumber = value.prNumber;
57
+ if (!Number.isSafeInteger(prNumber) || prNumber <= 0)
58
+ return invalid('prNumber is invalid');
59
+ for (const [name, pattern] of [['prHeadSha', SHA40], ['evidenceDigest', SHA64], ['artifactSha256', SHA64], ['pendingSummaryDigest', SHA64], ['finalSummaryDigest', SHA64], ['receiptDigest', SHA64]]) {
60
+ if (typeof value[name] !== 'string' || !pattern.test(value[name]))
61
+ return invalid(`${name} is invalid`);
62
+ }
63
+ if (typeof value.artifact !== 'string' || !ARTIFACT.test(value.artifact))
64
+ return invalid('artifact is not a canonical manual-validation artifact');
65
+ if (!validTimestamp(value.committedAt))
66
+ return invalid('committedAt is invalid');
67
+ const receipt = value;
68
+ if (manualValidationReceiptDigest(receipt) !== receipt.receiptDigest)
69
+ return invalid('receiptDigest does not match receipt contents');
70
+ if (expected && Object.entries(expected).some(([key, expectedValue]) => expectedValue !== undefined && receipt[key] !== expectedValue)) {
71
+ return { ok: false, error: { code: 'MANUAL_VALIDATION_RECEIPT_IDENTITY_MISMATCH', message: 'receipt identity does not match the expected transaction' } };
72
+ }
73
+ return { ok: true, value: receipt };
74
+ }
75
+ function createManualValidationReceipt(input) {
76
+ const payload = canonicalPayload(input);
77
+ const receipt = { ...payload, receiptDigest: manualValidationReceiptDigest(input) };
78
+ const checked = validateManualValidationReceipt(receipt);
79
+ if (!checked.ok)
80
+ throw new Error(`${checked.error.code}: ${checked.error.message}`);
81
+ return checked.value;
82
+ }
83
+ function manualValidationReceiptPath(taskDir) {
84
+ return path.join(taskDir, '.manual-validation', 'receipt.json');
85
+ }
86
+ function writeManualValidationReceiptAtomic(taskDir, receipt) {
87
+ const checked = validateManualValidationReceipt(receipt);
88
+ if (!checked.ok)
89
+ throw new Error(`${checked.error.code}: ${checked.error.message}`);
90
+ const target = manualValidationReceiptPath(taskDir);
91
+ return writeJsonAtomic(target, receipt);
92
+ }
93
+ function readManualValidationReceipt(taskDir, expected) {
94
+ const file = manualValidationReceiptPath(taskDir);
95
+ let value;
96
+ try {
97
+ value = JSON.parse(fs.readFileSync(file, 'utf8'));
98
+ }
99
+ catch (error) {
100
+ return { ok: false, error: { code: error.code === 'ENOENT' ? 'MANUAL_VALIDATION_RECEIPT_MISSING' : 'MANUAL_VALIDATION_RECEIPT_INVALID', message: error instanceof Error ? error.message : String(error) } };
101
+ }
102
+ return validateManualValidationReceipt(value, expected);
103
+ }
104
+ export { MANUAL_VALIDATION_RECEIPT_SCHEMA, MANUAL_VALIDATION_RECEIPT_VERSION, createManualValidationReceipt, manualValidationFinalSummaryDigest, manualValidationFinalSummaryProjectionMatches, manualValidationReceiptDigest, manualValidationReceiptPath, readManualValidationReceipt, validateManualValidationReceipt, writeManualValidationReceiptAtomic };
105
+ //# sourceMappingURL=manual-validation-receipt.js.map
@@ -0,0 +1,40 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ const MANUAL_VALIDATION_TASK_ID = /^TASK-\d{8}-\d{6}$/u;
5
+ const MANUAL_VALIDATION_SHA40 = /^[a-f0-9]{40}$/u;
6
+ const MANUAL_VALIDATION_SHA64 = /^[a-f0-9]{64}$/u;
7
+ const MANUAL_VALIDATION_ARTIFACT = /^manual-validation(?:-r[2-9]|-r[1-9]\d+)?.md$/u;
8
+ const MANUAL_VALIDATION_TIMESTAMP = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/u;
9
+ function isRecord(value) {
10
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
11
+ }
12
+ function exactKeys(value, keys, label) {
13
+ const allowed = new Set(keys);
14
+ const unknown = Object.keys(value).find((key) => !allowed.has(key));
15
+ if (unknown)
16
+ return `${label} contains unknown field '${unknown}'`;
17
+ const missing = keys.find((key) => !Object.hasOwn(value, key));
18
+ return missing ? `${label} is missing '${missing}'` : null;
19
+ }
20
+ function validTimestamp(value) {
21
+ return typeof value === 'string' && MANUAL_VALIDATION_TIMESTAMP.test(value) && Number.isFinite(Date.parse(value));
22
+ }
23
+ function writeJsonAtomic(file, value) {
24
+ const temporary = `${file}.${process.pid}.${randomUUID()}.tmp`;
25
+ fs.mkdirSync(path.dirname(file), { recursive: true });
26
+ try {
27
+ fs.writeFileSync(temporary, `${JSON.stringify(value)}\n`, { mode: 0o600 });
28
+ fs.renameSync(temporary, file);
29
+ }
30
+ catch (error) {
31
+ try {
32
+ fs.unlinkSync(temporary);
33
+ }
34
+ catch { /* best effort cleanup of our own temp file */ }
35
+ throw error;
36
+ }
37
+ return file;
38
+ }
39
+ export { MANUAL_VALIDATION_ARTIFACT, MANUAL_VALIDATION_SHA40, MANUAL_VALIDATION_SHA64, MANUAL_VALIDATION_TASK_ID, MANUAL_VALIDATION_TIMESTAMP, exactKeys, isRecord, validTimestamp, writeJsonAtomic };
40
+ //# sourceMappingURL=manual-validation-shared.js.map
@@ -0,0 +1,243 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { createHash, randomUUID } from 'node:crypto';
4
+ import { validateManualValidationReceipt } from './manual-validation-receipt.js';
5
+ import { MANUAL_VALIDATION_ARTIFACT as ARTIFACT, MANUAL_VALIDATION_SHA40 as SHA40, MANUAL_VALIDATION_SHA64 as SHA64, MANUAL_VALIDATION_TASK_ID as TASK_ID, exactKeys, isRecord, validTimestamp, writeJsonAtomic } from './manual-validation-shared.js';
6
+ const MANUAL_VALIDATION_TRANSACTION_SCHEMA = 'agent-infra/manual-validation-transaction';
7
+ const MANUAL_VALIDATION_TRANSACTION_VERSION = 1;
8
+ const TRANSACTION_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;
9
+ function invalid(message) {
10
+ return { ok: false, error: { code: 'MANUAL_VALIDATION_TRANSACTION_INVALID', message } };
11
+ }
12
+ function summaryPreimageDigest(body) {
13
+ return createHash('sha256').update(body, 'utf8').digest('hex');
14
+ }
15
+ function validateManualValidationTransaction(value, expected) {
16
+ if (!isRecord(value))
17
+ return invalid('transaction must be a JSON object');
18
+ const keys = ['schema', 'version', 'transactionId', 'taskId', 'prNumber', 'prHeadSha', 'evidenceDigest', 'summaryPreimage', 'pendingSummaryDigest', 'finalSummaryDigest', 'artifact', 'phase', 'committedReceipt', 'eventAppended', 'attempt', 'postWriteVerified', 'createdAt', 'updatedAt', 'error'];
19
+ const keyError = exactKeys(value, keys, 'transaction');
20
+ if (keyError)
21
+ return invalid(keyError);
22
+ if (value.schema !== MANUAL_VALIDATION_TRANSACTION_SCHEMA || value.version !== MANUAL_VALIDATION_TRANSACTION_VERSION)
23
+ return invalid('transaction schema or version is unsupported');
24
+ if (typeof value.transactionId !== 'string' || !TRANSACTION_ID.test(value.transactionId))
25
+ return invalid('transactionId is invalid');
26
+ if (typeof value.taskId !== 'string' || !TASK_ID.test(value.taskId))
27
+ return invalid('taskId is invalid');
28
+ const prNumber = value.prNumber;
29
+ if (!Number.isSafeInteger(prNumber) || prNumber <= 0)
30
+ return invalid('prNumber is invalid');
31
+ if (typeof value.prHeadSha !== 'string' || !SHA40.test(value.prHeadSha))
32
+ return invalid('prHeadSha is invalid');
33
+ if (typeof value.evidenceDigest !== 'string' || !SHA64.test(value.evidenceDigest))
34
+ return invalid('evidenceDigest is invalid');
35
+ if (!isRecord(value.summaryPreimage))
36
+ return invalid('summaryPreimage is invalid');
37
+ const preimage = value.summaryPreimage;
38
+ const preimageKeyError = exactKeys(preimage, ['commentId', 'body', 'digest'], 'summaryPreimage');
39
+ if (preimageKeyError)
40
+ return invalid(preimageKeyError);
41
+ if (preimage.commentId !== null && typeof preimage.commentId !== 'number' && typeof preimage.commentId !== 'string')
42
+ return invalid('summaryPreimage.commentId is invalid');
43
+ if (typeof preimage.body !== 'string' || typeof preimage.digest !== 'string' || !SHA64.test(preimage.digest) || summaryPreimageDigest(preimage.body) !== preimage.digest)
44
+ return invalid('summaryPreimage digest is invalid');
45
+ for (const field of ['pendingSummaryDigest', 'finalSummaryDigest'])
46
+ if (typeof value[field] !== 'string' || !SHA64.test(value[field]))
47
+ return invalid(`${field} is invalid`);
48
+ if (typeof value.artifact !== 'string' || !ARTIFACT.test(value.artifact))
49
+ return invalid('artifact is invalid');
50
+ if (!['prepared', 'summary-staged', 'receipt-committed', 'final-promotion-in-progress', 'committed', 'aborted', 'recovery-required'].includes(value.phase))
51
+ return invalid('phase is invalid');
52
+ if (value.committedReceipt !== null && (typeof value.committedReceipt !== 'string' || !SHA64.test(value.committedReceipt)))
53
+ return invalid('committedReceipt is invalid');
54
+ if (typeof value.eventAppended !== 'boolean' || typeof value.postWriteVerified !== 'boolean')
55
+ return invalid('transaction completion flags are invalid');
56
+ const attempt = value.attempt;
57
+ if (!Number.isSafeInteger(attempt) || attempt < 1)
58
+ return invalid('attempt is invalid');
59
+ if (!validTimestamp(value.createdAt) || !validTimestamp(value.updatedAt))
60
+ return invalid('transaction timestamps are invalid');
61
+ if (value.error !== null && (typeof value.error !== 'string' || !value.error || /[\r\n]/u.test(value.error)))
62
+ return invalid('transaction error is invalid');
63
+ if (['receipt-committed', 'final-promotion-in-progress', 'committed'].includes(value.phase) && value.committedReceipt === null)
64
+ return invalid('receipt-backed phases require committedReceipt');
65
+ if (['final-promotion-in-progress', 'committed'].includes(value.phase) && !value.eventAppended)
66
+ return invalid('final promotion requires an appended completion event');
67
+ if (value.phase === 'committed' && !value.postWriteVerified)
68
+ return invalid('committed phase requires post-write verification');
69
+ const transaction = value;
70
+ if (expected && Object.entries(expected).some(([key, expectedValue]) => expectedValue !== undefined && transaction[key] !== expectedValue)) {
71
+ return { ok: false, error: { code: 'MANUAL_VALIDATION_TRANSACTION_IDENTITY_MISMATCH', message: 'transaction identity does not match the expected operation' } };
72
+ }
73
+ return { ok: true, value: transaction };
74
+ }
75
+ function createManualValidationTransaction(input) {
76
+ const transaction = {
77
+ schema: MANUAL_VALIDATION_TRANSACTION_SCHEMA,
78
+ version: MANUAL_VALIDATION_TRANSACTION_VERSION,
79
+ transactionId: input.transactionId ?? `mv-${randomUUID()}`,
80
+ taskId: input.taskId,
81
+ prNumber: input.prNumber,
82
+ prHeadSha: input.prHeadSha,
83
+ evidenceDigest: input.evidenceDigest,
84
+ summaryPreimage: input.summaryPreimage,
85
+ pendingSummaryDigest: input.pendingSummaryDigest,
86
+ finalSummaryDigest: input.finalSummaryDigest,
87
+ artifact: input.artifact,
88
+ phase: 'prepared',
89
+ committedReceipt: null,
90
+ eventAppended: false,
91
+ attempt: input.attempt,
92
+ postWriteVerified: false,
93
+ createdAt: input.createdAt,
94
+ updatedAt: input.updatedAt,
95
+ error: null
96
+ };
97
+ const checked = validateManualValidationTransaction(transaction);
98
+ if (!checked.ok)
99
+ throw new Error(`${checked.error.code}: ${checked.error.message}`);
100
+ return checked.value;
101
+ }
102
+ const allowedTransitions = {
103
+ prepared: ['prepared', 'summary-staged', 'aborted', 'recovery-required'],
104
+ 'summary-staged': ['summary-staged', 'receipt-committed', 'aborted', 'recovery-required'],
105
+ 'receipt-committed': ['receipt-committed', 'final-promotion-in-progress', 'aborted', 'recovery-required'],
106
+ 'final-promotion-in-progress': ['final-promotion-in-progress', 'committed', 'aborted', 'recovery-required'],
107
+ committed: ['committed'],
108
+ aborted: ['aborted', 'prepared'],
109
+ 'recovery-required': ['recovery-required', 'prepared']
110
+ };
111
+ function transitionManualValidationTransaction(current, phase, patch = {}) {
112
+ if (!allowedTransitions[current.phase].includes(phase))
113
+ return { ok: false, error: { code: 'MANUAL_VALIDATION_TRANSACTION_PHASE_INVALID', message: `cannot transition from ${current.phase} to ${phase}` } };
114
+ if (phase === 'final-promotion-in-progress' && (!current.eventAppended && patch.eventAppended !== true))
115
+ return { ok: false, error: { code: 'MANUAL_VALIDATION_TRANSACTION_PHASE_INVALID', message: 'final promotion requires an appended completion event' } };
116
+ const next = {
117
+ ...current,
118
+ phase,
119
+ committedReceipt: patch.committedReceipt !== undefined ? patch.committedReceipt : current.committedReceipt,
120
+ eventAppended: patch.eventAppended ?? current.eventAppended,
121
+ postWriteVerified: patch.postWriteVerified ?? current.postWriteVerified,
122
+ attempt: patch.attempt ?? current.attempt,
123
+ error: patch.error !== undefined ? patch.error : current.error,
124
+ updatedAt: patch.updatedAt ?? new Date().toISOString()
125
+ };
126
+ const checked = validateManualValidationTransaction(next);
127
+ if (!checked.ok)
128
+ return checked;
129
+ return checked;
130
+ }
131
+ function retryManualValidationTransaction(current, now = new Date().toISOString()) {
132
+ if (!['aborted', 'recovery-required'].includes(current.phase))
133
+ return { ok: false, error: { code: 'MANUAL_VALIDATION_TRANSACTION_PHASE_INVALID', message: 'only aborted or recovery-required transactions can be retried' } };
134
+ return transitionManualValidationTransaction(current, 'prepared', {
135
+ updatedAt: now,
136
+ error: null,
137
+ committedReceipt: null,
138
+ eventAppended: false,
139
+ postWriteVerified: false,
140
+ attempt: current.attempt + 1
141
+ });
142
+ }
143
+ function manualValidationTransactionPath(taskDir) {
144
+ return path.join(taskDir, '.manual-validation', 'transaction.json');
145
+ }
146
+ function manualValidationGenerationPaths(taskDir, transaction) {
147
+ const stateDir = path.join(taskDir, '.manual-validation');
148
+ const historyDir = path.join(stateDir, 'history');
149
+ return {
150
+ receipt: {
151
+ current: path.join(stateDir, 'receipt.json'),
152
+ history: path.join(historyDir, `receipt-${transaction.transactionId}-attempt-${transaction.attempt}.json`)
153
+ },
154
+ transaction: {
155
+ current: manualValidationTransactionPath(taskDir),
156
+ history: path.join(historyDir, `transaction-${transaction.transactionId}-attempt-${transaction.attempt}.json`)
157
+ }
158
+ };
159
+ }
160
+ function readReceiptAt(file, transaction) {
161
+ let value;
162
+ try {
163
+ value = JSON.parse(fs.readFileSync(file, 'utf8'));
164
+ }
165
+ catch (error) {
166
+ if (error.code === 'ENOENT')
167
+ return 'missing';
168
+ throw new Error(`manual-validation receipt is unreadable: ${error instanceof Error ? error.message : String(error)}`);
169
+ }
170
+ const checked = validateManualValidationReceipt(value, {
171
+ transactionId: transaction.transactionId,
172
+ taskId: transaction.taskId,
173
+ prNumber: transaction.prNumber,
174
+ prHeadSha: transaction.prHeadSha,
175
+ evidenceDigest: transaction.evidenceDigest,
176
+ artifact: transaction.artifact
177
+ });
178
+ if (!checked.ok)
179
+ throw new Error(`manual-validation receipt is invalid: ${checked.error.message}`);
180
+ if (transaction.committedReceipt !== null && checked.value.receiptDigest !== transaction.committedReceipt) {
181
+ throw new Error('manual-validation receipt does not match the committed transaction');
182
+ }
183
+ return 'valid';
184
+ }
185
+ function validateManualValidationGenerationArchive(taskDir, transaction, requireReceipt = false) {
186
+ const paths = manualValidationGenerationPaths(taskDir, transaction);
187
+ const currentTransaction = fs.existsSync(paths.transaction.current);
188
+ const archivedTransaction = fs.existsSync(paths.transaction.history);
189
+ if (currentTransaction && archivedTransaction)
190
+ throw new Error(`manual-validation archive has conflicting transaction files for ${transaction.transactionId}`);
191
+ if (!currentTransaction && !archivedTransaction)
192
+ throw new Error(`manual-validation archive source is missing: ${paths.transaction.current}`);
193
+ const currentReceipt = requireReceipt
194
+ ? readReceiptAt(paths.receipt.current, transaction)
195
+ : (fs.existsSync(paths.receipt.current) ? 'valid' : 'missing');
196
+ const archivedReceipt = requireReceipt
197
+ ? readReceiptAt(paths.receipt.history, transaction)
198
+ : (fs.existsSync(paths.receipt.history) ? 'valid' : 'missing');
199
+ if (requireReceipt && currentReceipt === 'missing' && archivedReceipt === 'missing') {
200
+ throw new Error(`manual-validation receipt is missing for transaction ${transaction.transactionId}`);
201
+ }
202
+ if (currentReceipt === 'valid' && archivedReceipt === 'valid') {
203
+ throw new Error(`manual-validation archive has conflicting receipt files for ${transaction.transactionId}`);
204
+ }
205
+ }
206
+ function archiveManualValidationGeneration(taskDir, transaction, requireReceipt = false, options = {}) {
207
+ const paths = manualValidationGenerationPaths(taskDir, transaction);
208
+ validateManualValidationGenerationArchive(taskDir, transaction, requireReceipt);
209
+ fs.mkdirSync(path.dirname(paths.receipt.history), { recursive: true });
210
+ const move = (source, target, required) => {
211
+ if (!fs.existsSync(source)) {
212
+ if (fs.existsSync(target) || !required)
213
+ return;
214
+ throw new Error(`manual-validation archive source is missing: ${source}`);
215
+ }
216
+ if (fs.existsSync(target))
217
+ throw new Error(`manual-validation archive target already exists: ${target}`);
218
+ fs.renameSync(source, target);
219
+ };
220
+ move(paths.receipt.current, paths.receipt.history, requireReceipt);
221
+ options.afterReceiptMove?.();
222
+ move(paths.transaction.current, paths.transaction.history, true);
223
+ }
224
+ function writeManualValidationTransactionAtomic(taskDir, transaction) {
225
+ const checked = validateManualValidationTransaction(transaction);
226
+ if (!checked.ok)
227
+ throw new Error(`${checked.error.code}: ${checked.error.message}`);
228
+ const target = manualValidationTransactionPath(taskDir);
229
+ return writeJsonAtomic(target, transaction);
230
+ }
231
+ function readManualValidationTransaction(taskDir, expected) {
232
+ const file = manualValidationTransactionPath(taskDir);
233
+ let value;
234
+ try {
235
+ value = JSON.parse(fs.readFileSync(file, 'utf8'));
236
+ }
237
+ catch (error) {
238
+ return { ok: false, error: { code: error.code === 'ENOENT' ? 'MANUAL_VALIDATION_TRANSACTION_MISSING' : 'MANUAL_VALIDATION_TRANSACTION_INVALID', message: error instanceof Error ? error.message : String(error) } };
239
+ }
240
+ return validateManualValidationTransaction(value, expected);
241
+ }
242
+ export { MANUAL_VALIDATION_TRANSACTION_SCHEMA, MANUAL_VALIDATION_TRANSACTION_VERSION, archiveManualValidationGeneration, createManualValidationTransaction, manualValidationTransactionPath, validateManualValidationGenerationArchive, readManualValidationTransaction, retryManualValidationTransaction, summaryPreimageDigest, transitionManualValidationTransaction, validateManualValidationTransaction, writeManualValidationTransactionAtomic };
243
+ //# sourceMappingURL=manual-validation-transaction.js.map
@@ -0,0 +1,47 @@
1
+ const HEADING = /^ {0,3}(#{1,6})[ \t]+(.+?)\s*$/;
2
+ const FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})(.*)$/;
3
+ const FENCE_CLOSE = /^ {0,3}(`{3,}|~{3,})\s*$/;
4
+ const ANCHOR = /^\s*<a\s+id=(['"])([^'"]+)\1\s*><\/a>\s*$/;
5
+ function sourceLines(content) {
6
+ const lines = [];
7
+ let start = 0;
8
+ while (start < content.length) {
9
+ const newline = content.indexOf('\n', start);
10
+ const end = newline === -1 ? content.length : newline;
11
+ lines.push({ start, end, text: content.slice(start, end).replace(/\r$/, '') });
12
+ start = newline === -1 ? content.length : newline + 1;
13
+ }
14
+ return lines;
15
+ }
16
+ function scanVisibleMarkdown(content) {
17
+ const lines = sourceLines(content);
18
+ const visible = [];
19
+ const headings = [];
20
+ const anchors = [];
21
+ let fence = null;
22
+ for (const line of lines) {
23
+ if (fence) {
24
+ const close = line.text.match(FENCE_CLOSE);
25
+ if (close && close[1][0] === fence.character && close[1].length >= fence.length)
26
+ fence = null;
27
+ continue;
28
+ }
29
+ const open = line.text.match(FENCE_OPEN);
30
+ const marker = open?.[1];
31
+ const info = open?.[2] ?? '';
32
+ if (marker && !(marker[0] === '`' && info.includes('`'))) {
33
+ fence = { character: marker[0], length: marker.length };
34
+ continue;
35
+ }
36
+ visible.push(line);
37
+ const heading = line.text.match(HEADING);
38
+ if (heading)
39
+ headings.push({ ...line, level: heading[1].length, text: heading[2].trim() });
40
+ const anchor = line.text.match(ANCHOR);
41
+ if (anchor)
42
+ anchors.push({ ...line, id: anchor[2] });
43
+ }
44
+ return { lines: visible, headings, anchors, hasUnclosedFence: fence !== null };
45
+ }
46
+ export { scanVisibleMarkdown };
47
+ //# sourceMappingURL=markdown.js.map
@@ -1,12 +1,13 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { createHash, randomUUID } from 'node:crypto';
4
+ import { artifactName, maxArtifactRound } from './artifact-name.js';
4
5
  import { parseTypedTaskFrontmatter } from './frontmatter.js';
5
6
  import { validateCurrentTaskContract } from './current-contract.js';
6
7
  import { parseReviewSummary } from './review-artifacts.js';
7
8
  import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from './ledger.js';
8
9
  import { resolveTaskRef } from './resolve-ref.js';
9
- import { activateDelegation, abortPreparedDelegation, completeDelegationStage, consumeDelegation, dispatchDelegation, foldBlankToNull, isDelegationReceipt, managedDelegationRole, prepareDelegation, sealDelegation } from './delegation-receipts.js';
10
+ import { activateDelegation, abortActivatedDelegation, abortPreparedDelegation, completeDelegationStage, consumeDelegation, dispatchDelegation, foldBlankToNull, isDelegationReceipt, managedDelegationRole, prepareDelegation, sealDelegation } from './delegation-receipts.js';
10
11
  import { normalizeAgentClients } from '../agent-clients/config.js';
11
12
  import { resolveAgentRuntimeStoreRoot } from '../runtime/agent-runtime.js';
12
13
  import { getAgentClientCapability, getAgentClientDelegationEvidence, getAgentClientModelSelection } from '../agent-clients/registry.js';
@@ -20,6 +21,7 @@ import { resolveDeliveryTarget, resolveDiffBase, resolveTargetHead } from './del
20
21
  import { buildLifecycleFacts, canStart, recommendNext } from './capabilities.js';
21
22
  import { hasOpenLifecycleExecution } from './activity-log.js';
22
23
  import { invalidationBlocks } from './invalidation.js';
24
+ import { normalizeAgentToken } from '../agent-clients/tokens.js';
23
25
  function supportsLifecycleDelegation(client) {
24
26
  return getAgentClientCapability(client, 'subagents').level !== 'unsupported'
25
27
  && getAgentClientCapability(client, 'orchestration').level !== 'unsupported'
@@ -101,7 +103,7 @@ function isRecovery(value) {
101
103
  && guards.completionEvidenceAbsent === true
102
104
  && value.resultingStatus === 'running';
103
105
  }
104
- function isCompletionEvidence(value) {
106
+ export function isCompletionEvidence(value) {
105
107
  return hasExactKeys(value, [
106
108
  'kind', 'observedAt', 'head', 'headTree', 'worktreeTree', 'lastReviewedCommit', 'prNumber', 'prHead'
107
109
  ])
@@ -437,18 +439,8 @@ function beginOrResumeOrchestration(taskRef, options = {}) {
437
439
  atomicWrite(orchestrationPath(resolved.taskDir), run);
438
440
  return { status: 'running', changed: true, taskId: resolved.taskId, run, next: null, error: null };
439
441
  }
440
- function highestRound(taskDir, family) {
441
- const pattern = new RegExp(`^${family}(?:-r(\\d+))?\\.md$`);
442
- return fs.readdirSync(taskDir).reduce((max, name) => {
443
- const match = pattern.exec(name);
444
- return match ? Math.max(max, match[1] ? Number(match[1]) : 1) : max;
445
- }, 0);
446
- }
447
- function artifactName(family, round) {
448
- return round === 1 ? `${family}.md` : `${family}-r${round}.md`;
449
- }
450
442
  function validateSavedCurrentDiffBase(repoRoot, metadata, taskDir, reviewedHead) {
451
- const reviewRound = highestRound(taskDir, 'review-code');
443
+ const reviewRound = maxArtifactRound(fs.readdirSync(taskDir), 'review-code');
452
444
  const reviewContent = fs.readFileSync(path.join(taskDir, artifactName('review-code', reviewRound)), 'utf8');
453
445
  const savedTargetHead = extractReviewTargetHead(reviewContent);
454
446
  const savedDiffBase = extractReviewDiffBase(reviewContent);
@@ -492,10 +484,9 @@ function routeFromFacts(facts) {
492
484
  if (action === 'manual-validation' || action === 'validation-run')
493
485
  return null;
494
486
  const family = action === 'analysis' ? 'analysis' : action;
495
- const round = Math.max(0, ...[...(facts.artifacts[family] ?? []), ...(facts.staleArtifacts?.[family] ?? [])].map((name) => {
496
- const match = /-r(\d+)\.md$/.exec(name);
497
- return match ? Number(match[1]) : 1;
498
- })) + 1;
487
+ const round = maxArtifactRound([
488
+ ...(facts.artifacts[family] ?? []), ...(facts.staleArtifacts?.[family] ?? [])
489
+ ], family) + 1;
499
490
  const command = action === 'analysis' ? 'analyze-task' : action === 'plan' ? 'plan-task' : action === 'code' ? 'code-task' : action;
500
491
  const role = action.startsWith('review-') ? 'reviewer' : 'executor';
501
492
  return { action: command, role, stage: action, round, artifact: artifactName(family, round) };
@@ -554,7 +545,7 @@ function routeOrchestration(taskRef, options = {}) {
554
545
  if (!routed)
555
546
  return failed('ORCHESTRATION_ROUTE_UNKNOWN', 'cannot determine a unique lifecycle action', resolved.taskId);
556
547
  if ('completion' in routed) {
557
- const reviewRound = highestRound(resolved.taskDir, 'review-code');
548
+ const reviewRound = maxArtifactRound(fs.readdirSync(resolved.taskDir), 'review-code');
558
549
  const review = parseReviewSummary(fs.readFileSync(path.join(resolved.taskDir, artifactName('review-code', reviewRound)), 'utf8'));
559
550
  if (!review.ok || review.summary.manualValidation === null) {
560
551
  return failed('ORCHESTRATION_REVIEW_INVALID', 'latest code review has no numeric manual-validation count', resolved.taskId);
@@ -692,6 +683,13 @@ function prepareOrchestrationDelegationUnlocked(taskRef, input, options = {}) {
692
683
  if (input.client === 'codex' && !input.lifecycleProvenance) {
693
684
  return failed('ORCHESTRATION_CODEX_PROVENANCE_REQUIRED', 'Codex prepare requires lifecycle provenance', resolved.taskId);
694
685
  }
686
+ if (input.lifecycleRecoveryAttestation
687
+ && (input.lifecycleRecoveryAttestation.phase !== 'orchestration.prepare'
688
+ || input.lifecycleRecoveryAttestation.taskId !== resolved.taskId
689
+ || input.lifecycleRecoveryAttestation.artifact !== next.artifact
690
+ || input.lifecycleRecoveryAttestation.round !== next.round)) {
691
+ return failed('LIFECYCLE_AUTHORITY_TUPLE_MISMATCH', 'orchestration authority does not match the routed stage', resolved.taskId);
692
+ }
695
693
  const expectedPolicy = run.modelPolicy[next.role];
696
694
  if (input.requestedModel !== expectedPolicy.model) {
697
695
  return failed('ORCHESTRATION_REQUESTED_MODEL_MISMATCH', `requested model does not match the persisted ${next.role} model`, resolved.taskId);
@@ -1093,6 +1091,55 @@ function recoverPreparedOrchestrationDelegation(taskRef, options = {}) {
1093
1091
  return failed('ORCHESTRATION_PREPARED_RECOVERY_FAILED', error instanceof Error ? error.message : String(error), resolved.taskId);
1094
1092
  }
1095
1093
  }
1094
+ function recoverActivatedOrchestrationDelegationUnderLock(taskRef, event, options = {}) {
1095
+ const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
1096
+ if (!resolved.ok)
1097
+ return failed(resolved.code, resolved.message, resolved.taskId);
1098
+ const run = readRun(resolved.taskDir, options);
1099
+ if (!run)
1100
+ return failed('ORCHESTRATION_RUN_MISSING', 'no orchestration run exists', resolved.taskId);
1101
+ const matches = [
1102
+ ...(run.pendingDelegation ? [run.pendingDelegation] : []),
1103
+ ...run.receipts.filter((receipt) => receipt.id === event.receiptId)
1104
+ ];
1105
+ const receipt = matches.find((candidate) => candidate.id === event.receiptId);
1106
+ if (!receipt)
1107
+ return failed('ORCHESTRATION_DELEGATION_MISSING', 'recovery receipt does not exist', resolved.taskId);
1108
+ if (receipt.taskId !== resolved.taskId
1109
+ || receipt.stage !== event.stage
1110
+ || receipt.round !== event.round
1111
+ || receipt.artifact !== event.artifact
1112
+ || receipt.childId !== event.childId
1113
+ || normalizeAgentToken(event.startedAgent) !== normalizeAgentToken(receipt.client)) {
1114
+ return failed('ORCHESTRATION_PROVENANCE_MISMATCH', 'recovery selector does not match the delegation receipt', resolved.taskId);
1115
+ }
1116
+ if (receipt.status === 'aborted' && run.pendingDelegation === null) {
1117
+ return { status: run.status, changed: false, taskId: resolved.taskId, run, next: null, error: null };
1118
+ }
1119
+ if (run.pendingDelegation?.id !== receipt.id || receipt.status !== 'activated') {
1120
+ return failed('ORCHESTRATION_RECOVERY_UNSAFE', 'recovery requires one matching activated pending delegation', resolved.taskId);
1121
+ }
1122
+ if (run.receipts.some((candidate) => candidate.id === receipt.id)) {
1123
+ return failed('ORCHESTRATION_RECEIPT_DUPLICATE', 'recovery receipt already exists in the completed receipt history', resolved.taskId);
1124
+ }
1125
+ const aborted = abortActivatedDelegation(receipt, {
1126
+ childId: event.childId,
1127
+ stopRevision: event.stopRevision,
1128
+ consumer: event.consumer,
1129
+ consumedAt: event.consumedAt
1130
+ });
1131
+ if (!aborted.ok)
1132
+ return failed(aborted.code, aborted.message, resolved.taskId);
1133
+ const updated = withUpdatedRun(run, {
1134
+ status: 'running',
1135
+ pause: null,
1136
+ nextStage: null,
1137
+ pendingDelegation: null,
1138
+ receipts: Object.freeze([...run.receipts, aborted.receipt])
1139
+ }, options.now);
1140
+ saveRun(resolved.taskDir, updated);
1141
+ return { status: 'running', changed: true, taskId: resolved.taskId, run: updated, next: null, error: null };
1142
+ }
1096
1143
  function completeOrchestrationStage(taskRef, event, options = {}) {
1097
1144
  const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
1098
1145
  if (!resolved.ok)
@@ -1207,5 +1254,5 @@ function pauseOrchestration(taskRef, code, message, recoverable, options = {}) {
1207
1254
  saveRun(resolved.taskDir, updated);
1208
1255
  return { status: 'paused', changed: true, taskId: resolved.taskId, run: updated, next: null, error: null };
1209
1256
  }
1210
- export { activateMatchingOrchestrationDelegation, activateOrchestrationDelegation, awaitOrchestrationDelegationActivation, advanceOrchestration, beginOrResumeOrchestration, commitOrchestrationStageCompletion, completeOrchestrationStage, dispatchOrchestrationDelegation, inspectOrchestrationStage, hasActivatableOrchestrationDelegation, hasSealableOrchestrationDelegation, OrchestrationStateError, orchestrationPath, pauseMatchingOrchestrationDelegation, pauseOrchestration, planOrchestrationStageCompletion, prepareOrchestrationDelegation, readRun, reconcileMatchingOrchestrationDelegation, recoverPreparedOrchestrationDelegation, routeOrchestration, sealMatchingOrchestrationDelegation, sealMatchingOrchestrationDelegationWithHostEvidence, sealOrchestrationDelegation, statusOrchestration, };
1257
+ export { activateMatchingOrchestrationDelegation, activateOrchestrationDelegation, awaitOrchestrationDelegationActivation, advanceOrchestration, beginOrResumeOrchestration, commitOrchestrationStageCompletion, completeOrchestrationStage, dispatchOrchestrationDelegation, inspectOrchestrationStage, hasActivatableOrchestrationDelegation, hasSealableOrchestrationDelegation, OrchestrationStateError, orchestrationPath, pauseMatchingOrchestrationDelegation, pauseOrchestration, planOrchestrationStageCompletion, prepareOrchestrationDelegation, readRun, reconcileMatchingOrchestrationDelegation, recoverPreparedOrchestrationDelegation, recoverActivatedOrchestrationDelegationUnderLock, routeOrchestration, sealMatchingOrchestrationDelegation, sealMatchingOrchestrationDelegationWithHostEvidence, sealOrchestrationDelegation, statusOrchestration, };
1211
1258
  //# sourceMappingURL=orchestration.js.map