@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
@@ -1,43 +1,14 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { createHash } from 'node:crypto';
4
- import { scanVisibleMarkdown } from './decision-details.js';
5
- import { locateActivityLog, pairEntries, startedBackedRows } from './activity-log.js';
6
- import { readArtifactRepairIntent } from './artifact-repair-intent.js';
4
+ import { readStableFileSync } from '../host-control/secure-fs.js';
5
+ import { parseArtifactName } from './artifact-name.js';
6
+ import { scanVisibleMarkdown } from './markdown.js';
7
7
  import { getArtifactSchema, renderArtifactSkeleton } from './artifact-schema.js';
8
8
  import { withTaskExecutionLock } from './task-execution-lock.js';
9
9
  function sha256Content(content) {
10
10
  return createHash('sha256').update(content, 'utf8').digest('hex');
11
11
  }
12
- function sourceLines(content) {
13
- const lines = [];
14
- let start = 0;
15
- while (start < content.length) {
16
- const newline = content.indexOf('\n', start);
17
- const end = newline === -1 ? content.length : newline;
18
- lines.push({ start, end, text: content.slice(start, end).replace(/\r$/, '') });
19
- start = newline === -1 ? content.length : newline + 1;
20
- }
21
- if (content.length === 0)
22
- lines.push({ start: 0, end: 0, text: '' });
23
- return lines;
24
- }
25
- function hasUnclosedFence(content) {
26
- let fence = null;
27
- for (const line of sourceLines(content)) {
28
- if (fence) {
29
- const close = line.text.match(/^ {0,3}(`{3,}|~{3,})\s*$/);
30
- if (close && close[1][0] === fence.character && close[1].length >= fence.length)
31
- fence = null;
32
- continue;
33
- }
34
- const open = line.text.match(/^ {0,3}(`{3,}|~{3,})(.*)$/);
35
- if (open && !(open[1][0] === '`' && open[2].includes('`'))) {
36
- fence = { character: open[1][0], length: open[1].length };
37
- }
38
- }
39
- return fence !== null;
40
- }
41
12
  function lineNumber(content, offset) {
42
13
  return content.slice(0, offset).split('\n').length;
43
14
  }
@@ -47,9 +18,9 @@ function markerPattern(marker) {
47
18
  function escapeRegExp(value) {
48
19
  return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
49
20
  }
50
- function markerEntries(content) {
21
+ function markerEntries(content, scanned) {
51
22
  const entries = [];
52
- for (const line of scanVisibleMarkdown(content).lines) {
23
+ for (const line of scanned.lines) {
53
24
  const match = line.text.match(/<!--\s*(artifact-section:[^\s>]+)\s*-->/g);
54
25
  if (!match)
55
26
  continue;
@@ -67,10 +38,9 @@ function markerEntries(content) {
67
38
  }
68
39
  return entries;
69
40
  }
70
- function sectionBodyBounds(content, heading) {
71
- const next = scanVisibleMarkdown(content).headings.find((candidate) => (candidate.start > heading.start && candidate.level <= 2));
72
- const headingEnd = scanVisibleMarkdown(content).headings.find((candidate) => candidate.start === heading.start)?.end ?? heading.start;
73
- return { start: headingEnd, end: next?.start ?? content.length };
41
+ function sectionBodyBounds(content, heading, scanned) {
42
+ const next = scanned.headings.find((candidate) => candidate.start > heading.start && candidate.level <= 2);
43
+ return { start: heading.end, end: next?.start ?? content.length };
74
44
  }
75
45
  function stripHtmlComments(content) {
76
46
  let result = '';
@@ -87,95 +57,48 @@ function stripHtmlComments(content) {
87
57
  }
88
58
  return result;
89
59
  }
90
- function diagnostic(code, message, sectionId, line, repairable = false, operation) {
91
- return {
92
- code, message, sectionId, line, repairable,
93
- ...(operation ? { operation } : {})
94
- };
60
+ function diagnostic(code, message, sectionId, line) {
61
+ return { code, message, sectionId, line };
95
62
  }
96
63
  function sectionHeadings(schema, section) {
97
64
  return [section.headings.zh, section.headings.en];
98
65
  }
99
- function createHeadingRepair(content, section, heading) {
100
- const to = heading.text.slice(0, -1);
101
- return {
102
- kind: 'replace-line',
103
- sectionId: section.id,
104
- line: lineNumber(content, heading.start),
105
- from: heading.text,
106
- to,
107
- start: heading.start,
108
- end: heading.end
109
- };
110
- }
111
- function createSectionInsertionRepair(content, section, marker, locale) {
112
- return {
113
- kind: 'insert-section',
114
- sectionId: section.id,
115
- line: marker.line,
116
- from: '',
117
- to: `## ${section.headings[locale === 'en' ? 'en' : 'zh']}\n`,
118
- start: marker.start,
119
- end: marker.start
120
- };
121
- }
122
- function applyRepairOperation(content, operation) {
123
- if (operation.start < 0 || operation.end < operation.start || operation.end > content.length)
124
- return null;
125
- if (operation.kind === 'insert-section') {
126
- if (operation.from !== '' || operation.start !== operation.end || !operation.to)
127
- return null;
128
- return `${content.slice(0, operation.start)}${operation.to}${content.slice(operation.end)}`;
129
- }
130
- const raw = content.slice(operation.start, operation.end);
131
- const offset = raw.indexOf(operation.from);
132
- if (!operation.from || offset < 0 || raw.indexOf(operation.from, offset + operation.from.length) >= 0)
133
- return null;
134
- return `${content.slice(0, operation.start)}${raw.slice(0, offset)}${operation.to}${raw.slice(offset + operation.from.length)}${content.slice(operation.end)}`;
135
- }
136
- function canonicalContent(content, operation = null) {
66
+ function canonicalContent(content) {
137
67
  let normalized = content;
138
- if (operation) {
139
- normalized = applyRepairOperation(normalized, operation) ?? normalized;
140
- }
141
68
  normalized = normalized.replace(/\r\n/g, '\n');
142
69
  normalized = normalized.replace(/^<!--\s*artifact-context:[^\n]+-->\s*\n?/gm, '');
143
70
  normalized = normalized.replace(/^\s*<!--\s*artifact-section:[^\n]+-->\s*\n?/gm, '');
144
71
  normalized = normalized.replace(/^\s*<!--\s*artifact-slot:empty\s*-->\s*\n?/gm, '');
145
72
  return normalized;
146
73
  }
147
- function canonicalSemanticDigest(content, operation = null) {
148
- return sha256Content(canonicalContent(content, operation));
74
+ function canonicalSemanticDigest(content) {
75
+ return sha256Content(canonicalContent(content));
149
76
  }
150
77
  function inspectArtifactStructure(content, schema) {
151
78
  const diagnostics = [];
152
79
  const scanned = scanVisibleMarkdown(content);
153
- const repairCandidates = [];
154
80
  if (!content.trim())
155
81
  diagnostics.push(diagnostic('ARTIFACT_EMPTY', 'artifact is empty', null, null));
156
- if (hasUnclosedFence(content))
82
+ if (scanned.hasUnclosedFence)
157
83
  diagnostics.push(diagnostic('ARTIFACT_UNCLOSED_FENCE', 'artifact contains an unclosed Markdown fence', null, null));
158
84
  const headingsBySection = new Map();
159
85
  for (const section of schema.sections) {
160
86
  const aliases = sectionHeadings(schema, section);
161
87
  const exact = scanned.headings.filter((heading) => heading.level === 2 && aliases.includes(heading.text));
162
88
  const punctuated = scanned.headings.filter((heading) => heading.level === 2 && aliases.some((alias) => heading.text === `${alias}:` || heading.text === `${alias}:`));
163
- headingsBySection.set(section.id, exact.length === 0 && punctuated.length === 1 ? punctuated : exact);
89
+ headingsBySection.set(section.id, exact.length > 0 ? exact : punctuated);
164
90
  if (exact.length > 1 || punctuated.length > 0 && exact.length > 0 || punctuated.length > 1) {
165
91
  const first = exact[1] ?? punctuated[0] ?? exact[0];
166
92
  diagnostics.push(diagnostic('ARTIFACT_DUPLICATE_SECTION', `required section '${aliases[0]}' is duplicated or has an ambiguous punctuation variant`, section.id, first ? lineNumber(content, first.start) : null));
167
93
  }
168
94
  else if (exact.length === 0 && punctuated.length === 1) {
169
- repairCandidates.push(createHeadingRepair(content, section, punctuated[0]));
95
+ diagnostics.push(diagnostic('ARTIFACT_HEADING_TRAILING_PUNCTUATION', `visible required H2 '${punctuated[0].text}' has trailing punctuation`, section.id, lineNumber(content, punctuated[0].start)));
170
96
  }
171
97
  else if (exact.length === 0) {
172
98
  diagnostics.push(diagnostic('ARTIFACT_MISSING_SECTION', `required section '${aliases[0]}' is missing`, section.id, null));
173
99
  }
174
100
  }
175
- const markers = markerEntries(content);
176
- const englishHeadings = scanned.headings.filter((heading) => heading.level === 2 && schema.sections.some((section) => section.headings.en === heading.text)).length;
177
- const chineseHeadings = scanned.headings.filter((heading) => heading.level === 2 && schema.sections.some((section) => section.headings.zh === heading.text)).length;
178
- const locale = englishHeadings > chineseHeadings ? 'en' : 'zh-CN';
101
+ const markers = markerEntries(content, scanned);
179
102
  for (const section of schema.sections) {
180
103
  const matches = markers.filter((entry) => entry.marker === section.marker);
181
104
  if (matches.length === 0) {
@@ -190,7 +113,7 @@ function inspectArtifactStructure(content, schema) {
190
113
  diagnostics.push(diagnostic('ARTIFACT_MARKER_MISMATCH', `section marker '${section.marker}' must occupy its own visible line`, section.id, marker.line));
191
114
  }
192
115
  if (marker && heading) {
193
- const bounds = sectionBodyBounds(content, heading);
116
+ const bounds = sectionBodyBounds(content, heading, scanned);
194
117
  if (marker.start < bounds.start || marker.start >= bounds.end) {
195
118
  diagnostics.push(diagnostic('ARTIFACT_MARKER_MISMATCH', `section marker '${section.marker}' is outside its section`, section.id, marker.line));
196
119
  }
@@ -201,10 +124,7 @@ function inspectArtifactStructure(content, schema) {
201
124
  if (marker && !heading && marker.standalone) {
202
125
  const nextHeading = scanned.headings.find((candidate) => candidate.start > marker.start && candidate.level <= 2);
203
126
  const body = stripHtmlComments(content.slice(marker.end, nextHeading?.start ?? content.length)).trim();
204
- if (body && repairCandidates.length === 0) {
205
- repairCandidates.push(createSectionInsertionRepair(content, section, marker, locale));
206
- }
207
- else if (!body) {
127
+ if (!body) {
208
128
  diagnostics.push(diagnostic('ARTIFACT_EMPTY_SECTION', `section '${section.headings.zh}' has no semantic body`, section.id, marker.line));
209
129
  }
210
130
  }
@@ -214,17 +134,6 @@ function inspectArtifactStructure(content, schema) {
214
134
  diagnostics.push(diagnostic('ARTIFACT_MARKER_MISMATCH', `unknown section marker '${marker.marker}'`, null, marker.line));
215
135
  }
216
136
  }
217
- for (const candidate of repairCandidates) {
218
- if (candidate.kind === 'replace-line') {
219
- diagnostics.push(diagnostic('ARTIFACT_HEADING_TRAILING_PUNCTUATION', `visible required H2 '${candidate.from}' may be normalized to '${candidate.to}'`, candidate.sectionId, candidate.line, true, candidate));
220
- continue;
221
- }
222
- const missing = diagnostics.findIndex((item) => item.code === 'ARTIFACT_MISSING_SECTION' && item.sectionId === candidate.sectionId);
223
- if (missing >= 0) {
224
- const section = schema.sections.find((item) => item.id === candidate.sectionId);
225
- diagnostics.splice(missing, 1, diagnostic('ARTIFACT_MISSING_SECTION', `required section '${section.headings.zh}' is missing and can be inserted at its unique marker`, candidate.sectionId, candidate.line, true, candidate));
226
- }
227
- }
228
137
  const orderedHeadings = schema.sections.flatMap((section) => {
229
138
  const heading = headingsBySection.get(section.id)?.[0];
230
139
  return heading ? [{ section, start: heading.start }] : [];
@@ -239,14 +148,11 @@ function inspectArtifactStructure(content, schema) {
239
148
  if (orderedMarkers.some((item, index) => index > 0 && item.start <= orderedMarkers[index - 1].start)) {
240
149
  diagnostics.push(diagnostic('ARTIFACT_SECTION_ORDER_INVALID', 'section markers are not in schema order', null, null));
241
150
  }
242
- const repair = repairCandidates.length === 1 && (diagnostics.length === 0 ||
243
- (diagnostics.length === 1 && diagnostics[0]?.operation?.kind === repairCandidates[0]?.kind)) ? repairCandidates[0] : null;
244
151
  return {
245
152
  ok: diagnostics.length === 0,
246
153
  family: schema.family,
247
- semanticDigest: canonicalSemanticDigest(content, repair),
248
- diagnostics,
249
- repair
154
+ semanticDigest: canonicalSemanticDigest(content),
155
+ diagnostics
250
156
  };
251
157
  }
252
158
  function inspectArtifactPatterns(content, schema) {
@@ -257,25 +163,22 @@ function inspectArtifactPatterns(content, schema) {
257
163
  ok: diagnostics.length === 0,
258
164
  family: schema.family,
259
165
  semanticDigest: canonicalSemanticDigest(content),
260
- diagnostics,
261
- repair: null
166
+ diagnostics
262
167
  };
263
168
  }
264
169
  function inspectArtifactContract(content, schema) {
265
170
  const structure = inspectArtifactStructure(content, schema);
266
171
  const patterns = inspectArtifactPatterns(content, schema);
267
172
  const diagnostics = [...structure.diagnostics, ...patterns.diagnostics];
268
- const repair = patterns.diagnostics.length === 0 ? structure.repair : null;
269
173
  return {
270
174
  ok: diagnostics.length === 0,
271
175
  family: schema.family,
272
- semanticDigest: canonicalSemanticDigest(content, repair),
273
- diagnostics,
274
- repair
176
+ semanticDigest: canonicalSemanticDigest(content),
177
+ diagnostics
275
178
  };
276
179
  }
277
180
  function resultFailure(code, message) {
278
- return { status: 'failed', changed: false, artifactSha256: null, semanticDigest: null, operation: null, error: { code, message } };
181
+ return { status: 'failed', changed: false, artifactSha256: null, semanticDigest: null, error: { code, message } };
279
182
  }
280
183
  function resultNoOp(content) {
281
184
  return {
@@ -283,174 +186,12 @@ function resultNoOp(content) {
283
186
  changed: false,
284
187
  artifactSha256: sha256Content(content),
285
188
  semanticDigest: canonicalSemanticDigest(content),
286
- operation: null,
287
189
  error: null
288
190
  };
289
191
  }
290
- function validateRepairContext(request, content) {
291
- const round = artifactRound(request.family, request.artifact);
292
- if (round === null)
293
- return { ok: false, code: 'ARTIFACT_REPAIR_CONTEXT_INVALID', message: 'artifact round is not canonical' };
294
- const contextPattern = /^<!--\s*artifact-context:([^:\s]+):([^:\s]+):(\d+)\s*-->\s*$/;
295
- const contexts = scanVisibleMarkdown(content).lines
296
- .map((line) => line.text.trim().match(contextPattern))
297
- .filter((match) => match !== null);
298
- if (contexts.length !== 1
299
- || contexts[0][1] !== request.taskId
300
- || contexts[0][2] !== request.family
301
- || Number(contexts[0][3]) !== round) {
302
- return { ok: false, code: 'ARTIFACT_REPAIR_CONTEXT_INVALID', message: 'artifact context marker does not match the requested task, family, and round' };
303
- }
304
- let taskContent;
305
- try {
306
- taskContent = fs.readFileSync(path.join(request.taskDir, 'task.md'), 'utf8');
307
- }
308
- catch (error) {
309
- return { ok: false, code: 'ARTIFACT_REPAIR_CONTEXT_INVALID', message: `cannot read task lifecycle context: ${String(error)}` };
310
- }
311
- const activity = locateActivityLog(taskContent);
312
- if (!activity)
313
- return { ok: false, code: 'ARTIFACT_REPAIR_CONTEXT_INVALID', message: 'task has no unique Activity Log section' };
314
- const label = {
315
- analysis: 'Analyze Task',
316
- 'review-analysis': 'Review Analysis',
317
- plan: 'Plan Task',
318
- 'review-plan': 'Review Plan',
319
- code: 'Code Task',
320
- 'review-code': 'Review Code'
321
- };
322
- const escaped = escapeRegExp(label[request.family]);
323
- const qualifier = request.family === 'code'
324
- ? '(?:, (?:fix for review-code(?:-r(?:[2-9]|[1-9]\\d+))?\\.md|decision II-[1-9]\\d+))?'
325
- : '';
326
- const expected = new RegExp(`^${escaped} \\(Round ${round}${qualifier}\\)$`);
327
- const open = startedBackedRows(pairEntries(activity.entries)).filter((row) => expected.test(row.step) && !row.done);
328
- if (open.length !== 1) {
329
- return { ok: false, code: 'ARTIFACT_REPAIR_CONTEXT_INVALID', message: `artifact '${request.artifact}' does not have exactly one matching open started lifecycle event` };
330
- }
331
- let intent;
332
- try {
333
- intent = readArtifactRepairIntent(request.repoRoot, request.taskId, request.family, request.artifact);
334
- }
335
- catch (error) {
336
- return { ok: false, code: 'ARTIFACT_REPAIR_PROVENANCE_INVALID', message: String(error) };
337
- }
338
- if (!intent || intent.state !== 'awaiting-repair') {
339
- return { ok: false, code: 'ARTIFACT_REPAIR_PROVENANCE_INVALID', message: 'artifact has no awaiting-repair finalization provenance' };
340
- }
341
- if (intent.artifactSha256 !== request.expectedSha256 || intent.semanticDigest !== request.expectedSemanticDigest) {
342
- return { ok: false, code: 'ARTIFACT_REPAIR_PROVENANCE_INVALID', message: 'repair request does not match the current finalization provenance' };
343
- }
344
- return { ok: true };
345
- }
346
192
  function artifactRound(family, artifact) {
347
- if (artifact === `${family}.md`)
348
- return 1;
349
- const match = artifact.match(new RegExp(`^${escapeRegExp(family)}-r([2-9]|[1-9]\\d+)\\.md$`));
350
- if (!match)
351
- return null;
352
- const round = Number(match[1]);
353
- return Number.isSafeInteger(round) ? round : null;
354
- }
355
- function validateTarget(taskDir, family, artifact) {
356
- if (path.basename(artifact) !== artifact || artifactRound(family, artifact) === null || !artifact.endsWith('.md'))
357
- return resultFailure('ARTIFACT_REPAIR_TARGET_INVALID', 'artifact must be a canonical top-level Markdown file');
358
- if (!/^TASK-\d{8}-\d{6}$/.test(path.basename(path.resolve(taskDir))))
359
- return resultFailure('ARTIFACT_REPAIR_TARGET_INVALID', 'target directory is not a task directory');
360
- const target = path.join(taskDir, artifact);
361
- if (path.dirname(path.resolve(target)) !== path.resolve(taskDir))
362
- return resultFailure('ARTIFACT_REPAIR_TARGET_INVALID', 'artifact must be inside the current task directory');
363
- let stat;
364
- try {
365
- stat = fs.lstatSync(target);
366
- }
367
- catch (error) {
368
- return resultFailure('ARTIFACT_REPAIR_TARGET_INVALID', `artifact cannot be read: ${String(error)}`);
369
- }
370
- if (stat.isSymbolicLink() || !stat.isFile())
371
- return resultFailure('ARTIFACT_REPAIR_TARGET_INVALID', 'artifact is not a regular file');
372
- try {
373
- fs.accessSync(target, fs.constants.R_OK | fs.constants.W_OK);
374
- }
375
- catch (error) {
376
- return resultFailure('ARTIFACT_REPAIR_TARGET_INVALID', `artifact is not readable and writable: ${String(error)}`);
377
- }
378
- return { path: target };
379
- }
380
- function applyRepairUnlocked(request) {
381
- const schema = getArtifactSchema(request.family);
382
- if (!schema)
383
- return resultFailure('ARTIFACT_FAMILY_UNKNOWN', `unknown artifact family '${request.family}'`);
384
- const target = validateTarget(request.taskDir, request.family, request.artifact);
385
- if ('status' in target)
386
- return target;
387
- let content;
388
- try {
389
- content = fs.readFileSync(target.path, 'utf8');
390
- }
391
- catch (error) {
392
- return resultFailure('ARTIFACT_REPAIR_TARGET_INVALID', String(error));
393
- }
394
- const actualSha256 = sha256Content(content);
395
- if (actualSha256 !== request.expectedSha256)
396
- return resultFailure('ARTIFACT_REPAIR_BASELINE_MISMATCH', 'artifact SHA-256 does not match the expected repair baseline');
397
- const context = validateRepairContext(request, content);
398
- if (!context.ok)
399
- return resultFailure(context.code, context.message);
400
- const inspection = inspectArtifactStructure(content, schema);
401
- if (!inspection.repair || inspection.diagnostics.length !== 1) {
402
- return resultFailure('ARTIFACT_REPAIR_UNSAFE', inspection.diagnostics.map((item) => `${item.code}: ${item.message}`).join('; ') || 'no deterministic structural repair is available');
403
- }
404
- if (inspection.repair.kind !== request.operation.kind
405
- || inspection.repair.sectionId !== request.operation.sectionId
406
- || inspection.repair.from !== request.operation.from
407
- || inspection.repair.to !== request.operation.to
408
- || inspection.repair.start !== request.operation.start
409
- || inspection.repair.end !== request.operation.end) {
410
- return resultFailure('ARTIFACT_REPAIR_OPERATION_MISMATCH', 'repair operation does not match the current artifact structure');
411
- }
412
- if (inspection.semanticDigest !== request.expectedSemanticDigest)
413
- return resultFailure('ARTIFACT_REPAIR_BASELINE_MISMATCH', 'artifact semantic digest does not match the expected repair baseline');
414
- const transformed = applyRepairOperation(content, inspection.repair);
415
- if (transformed === null)
416
- return resultFailure('ARTIFACT_REPAIR_OPERATION_MISMATCH', 'repair operation does not match the current artifact bytes');
417
- if (transformed === content)
418
- return resultFailure('ARTIFACT_REPAIR_NO_PROGRESS', 'repair operation produced no byte change');
419
- const tempPath = path.join(request.taskDir, `.${request.artifact}.repair-${process.pid}-${Date.now()}.tmp`);
420
- let mode = 0o600;
421
- try {
422
- mode = fs.statSync(target.path).mode & 0o777;
423
- fs.writeFileSync(tempPath, transformed, { encoding: 'utf8', mode, flag: 'wx' });
424
- const currentStat = fs.lstatSync(target.path);
425
- if (currentStat.isSymbolicLink() || !currentStat.isFile() || sha256Content(fs.readFileSync(target.path, 'utf8')) !== actualSha256) {
426
- fs.unlinkSync(tempPath);
427
- return resultFailure('ARTIFACT_REPAIR_CONFLICT', 'artifact changed or was replaced during repair');
428
- }
429
- fs.renameSync(tempPath, target.path);
430
- }
431
- catch (error) {
432
- try {
433
- fs.unlinkSync(tempPath);
434
- }
435
- catch { /* preserve primary error */ }
436
- return resultFailure('ARTIFACT_REPAIR_WRITE_FAILED', String(error));
437
- }
438
- return {
439
- status: 'applied',
440
- changed: true,
441
- artifactSha256: sha256Content(transformed),
442
- semanticDigest: canonicalSemanticDigest(transformed),
443
- operation: inspection.repair,
444
- error: null
445
- };
446
- }
447
- function applyArtifactRepair(request) {
448
- try {
449
- return withTaskExecutionLock(request.repoRoot, request.taskId, 'task-artifact.repair', () => applyRepairUnlocked(request));
450
- }
451
- catch (error) {
452
- return resultFailure('ARTIFACT_REPAIR_LOCK_FAILED', String(error));
453
- }
193
+ const identity = parseArtifactName(artifact);
194
+ return identity?.family === family ? identity.round : null;
454
195
  }
455
196
  function initializeArtifactSkeleton(request) {
456
197
  const schema = getArtifactSchema(request.family);
@@ -469,7 +210,7 @@ function initializeArtifactSkeleton(request) {
469
210
  const existing = fs.lstatSync(target);
470
211
  if (existing.isSymbolicLink() || !existing.isFile())
471
212
  return resultFailure('ARTIFACT_INIT_TARGET_INVALID', 'artifact target is not a regular file');
472
- return resultNoOp(fs.readFileSync(target, 'utf8'));
213
+ return resultNoOp(readStableFileSync(target, { maxBytes: 1024 * 1024 }).bytes.toString('utf8'));
473
214
  }
474
215
  catch (error) {
475
216
  if (error.code !== 'ENOENT')
@@ -507,7 +248,6 @@ function initializeArtifactSkeleton(request) {
507
248
  changed: true,
508
249
  artifactSha256: sha256Content(content),
509
250
  semanticDigest: canonicalSemanticDigest(content),
510
- operation: null,
511
251
  error: null
512
252
  };
513
253
  });
@@ -516,5 +256,5 @@ function initializeArtifactSkeleton(request) {
516
256
  return resultFailure('ARTIFACT_INIT_LOCK_FAILED', String(error));
517
257
  }
518
258
  }
519
- export { applyArtifactRepair, canonicalSemanticDigest, initializeArtifactSkeleton, inspectArtifactContract, inspectArtifactPatterns, inspectArtifactStructure, sha256Content };
259
+ export { canonicalSemanticDigest, initializeArtifactSkeleton, inspectArtifactContract, inspectArtifactPatterns, inspectArtifactStructure, sha256Content };
520
260
  //# sourceMappingURL=artifact-operations.js.map
@@ -1,5 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import { createHash } from 'node:crypto';
3
+ import { parseArtifactName } from './artifact-name.js';
3
4
  import { extractSection, findSectionHeading, parseTable } from './sections.js';
4
5
  const RECEIPT_SECTION_ALIASES = ['产物生命周期收据', 'Artifact Lifecycle Receipts'];
5
6
  const RECEIPT_COLUMNS = ['event', 'output', 'input', 'input_sha256', 'completed_at'];
@@ -10,7 +11,6 @@ const RECEIPT_EVENTS = new Set([
10
11
  'code.completed'
11
12
  ]);
12
13
  const SHA256_RE = /^[a-f0-9]{64}$/;
13
- const ARTIFACT_NAME_RE = /^(analysis|review-analysis|plan|review-plan|code|review-code|manual-validation|validation-run|pr-review)(?:-r([2-9]|[1-9]\d+))?\.md$/;
14
14
  const RECEIPT_SHAPES = {
15
15
  'review-analysis.completed': { output: 'review-analysis', input: 'analysis' },
16
16
  'review-plan.completed': { output: 'review-plan', input: 'plan' },
@@ -30,21 +30,9 @@ function sha256Bytes(value) {
30
30
  function sha256File(filePath) {
31
31
  return sha256Bytes(fs.readFileSync(filePath));
32
32
  }
33
- function parseReceiptArtifactName(name) {
34
- const match = ARTIFACT_NAME_RE.exec(name);
35
- if (!match)
36
- return null;
37
- const roundText = match[2];
38
- if (roundText !== undefined) {
39
- const round = Number(roundText);
40
- if (!Number.isSafeInteger(round) || String(round) !== roundText)
41
- return null;
42
- }
43
- return { family: match[1] };
44
- }
45
33
  function validateReceiptShape(event, output, input) {
46
- const outputIdentity = parseReceiptArtifactName(output);
47
- const inputIdentity = parseReceiptArtifactName(input);
34
+ const outputIdentity = parseArtifactName(output);
35
+ const inputIdentity = parseArtifactName(input);
48
36
  if (!outputIdentity || !inputIdentity)
49
37
  throw new ArtifactReceiptError(`receipt artifact identity is invalid: ${output} -> ${input}`);
50
38
  const shape = RECEIPT_SHAPES[event];