@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,3 +1,18 @@
1
+ import type fs from 'node:fs';
2
+
3
+ export type VerificationShared = {
4
+ repoRoot: string;
5
+ loadTask: (taskDir: string) => { ok: true; content: string; metadata: Record<string, string> } | { ok: false; message: string };
6
+ getCheckedRequirements: (content: string) => string[];
7
+ normalizeContent: (text: unknown) => string;
8
+ isBlank: (value: unknown) => boolean;
9
+ escapeRegExp: (value: string) => string;
10
+ passResult: (type: string, message: string, warnings?: string[]) => VerificationCheckResult;
11
+ failResult: (type: string, message: string, failType?: string) => VerificationCheckResult;
12
+ blockedResult: (type: string, message: string, failType?: string) => VerificationCheckResult;
13
+ safeStat: (filePath: string) => fs.Stats | null;
14
+ };
15
+
1
16
  type VerificationStatus = 'pass' | 'fail' | 'blocked';
2
17
  type VerificationCheckResult = {
3
18
  type: string;
@@ -3,7 +3,7 @@ import path from 'node:path';
3
3
  // checks are provided by typed domain modules without a stdout protocol.
4
4
  import { verifyInProcess } from './verification-engine.ts';
5
5
 
6
- import { parseArtifactName } from './artifact-lifecycle.ts';
6
+ import { parseArtifactName } from './artifact-name.ts';
7
7
  import type { ArtifactFamily } from './artifact-lifecycle.ts';
8
8
  import { resolveTaskRef } from './resolve-ref.ts';
9
9
  import type { TaskWorkspaceState } from './resolve-ref.ts';
@@ -0,0 +1,17 @@
1
+ export const TASK_WORKFLOW_COMMANDS = Object.freeze({
2
+ 'artifact-inspect': ['task-artifact', 'inspect'],
3
+ 'artifact-init': ['task-artifact', 'init'],
4
+ 'artifact-finalize-local': ['task-artifact', 'finalize-local'],
5
+ 'review-finalize-summary': ['task-review', 'finalize-summary'],
6
+ event: ['task-event', null],
7
+ 'ledger-finding-response': ['task-ledger', 'finding-respond'],
8
+ 'ledger-finding-review': ['task-ledger', 'finding-review'],
9
+ 'ledger-finding-upsert': ['task-ledger', 'finding-upsert'],
10
+ 'decision-next-id': ['task-ledger', 'decision-next-id'],
11
+ 'decision-upsert': ['task-ledger', 'decision-upsert'],
12
+ 'invalidation-reconcile': ['task-invalidation', 'reconcile'],
13
+ 'warning-add': ['task-warning', 'add']
14
+ } as const);
15
+ export type TaskWorkflowOperation = keyof typeof TASK_WORKFLOW_COMMANDS;
16
+ export const TASK_WORKFLOW_OPERATIONS = Object.freeze(Object.keys(TASK_WORKFLOW_COMMANDS) as TaskWorkflowOperation[]);
17
+ export type WorkflowCommand = typeof TASK_WORKFLOW_COMMANDS[TaskWorkflowOperation][0];
@@ -52,17 +52,6 @@ function nextWarningId(rows: readonly WorkflowWarning[]): string {
52
52
  return `WW-${max + 1}`;
53
53
  }
54
54
 
55
- function validateRows(rows: readonly WorkflowWarning[]): { code: string; message: string } | null {
56
- const ids = new Set<string>();
57
- for (const row of rows) {
58
- if (!/^WW-[1-9]\d*$/.test(row.id)) return { code: 'WARNING_ID_INVALID', message: `warning id '${row.id}' is invalid` };
59
- if (ids.has(row.id)) return { code: 'WARNING_DUPLICATE_ID', message: `duplicate warning id '${row.id}'` };
60
- ids.add(row.id);
61
- if (!WORKFLOW_WARNING_SEVERITIES.has(row.severity) || !WORKFLOW_WARNING_STATUSES.has(row.status)) return { code: 'WARNING_DOCUMENT_INVALID', message: `warning '${row.id}' has invalid severity or status` };
62
- }
63
- return null;
64
- }
65
-
66
55
  function sectionMutation(content: string): TaskMutation[] {
67
56
  if (/^##\s+(工作流告警|Workflow Warnings)\s*$/m.test(content)) return [];
68
57
  const english = /^##\s+Activity Log\s*$/m.test(content);
@@ -98,8 +87,6 @@ function applyWorkflowWarningIntent(intent: WorkflowWarningIntent, options: Task
98
87
  const code = error && typeof error === 'object' && 'code' in error ? String(error.code) : 'WARNING_DOCUMENT_INVALID';
99
88
  return failed(intent, code, error instanceof Error ? error.message : String(error), resolved.taskId);
100
89
  }
101
- const invalid = validateRows(rows);
102
- if (invalid) return failed(intent, invalid.code, invalid.message, resolved.taskId);
103
90
  if (intent.kind === 'list') {
104
91
  if (intent.status && !WORKFLOW_WARNING_STATUSES.has(intent.status)) return failed(intent, 'WARNING_PAYLOAD_INVALID', 'warning status is invalid', resolved.taskId);
105
92
  const warnings = rows.filter((row) => !intent.status || row.status === intent.status);
@@ -4,6 +4,7 @@ const WORKFLOW_WARNING_HEADINGS = ['工作流告警', 'Workflow Warnings'];
4
4
  const WORKFLOW_WARNING_STATUSES = new Set(['open', 'resolved', 'ignored']);
5
5
  const WORKFLOW_WARNING_SEVERITIES = new Set(['IMPORTANT', 'ACTION_REQUIRED']);
6
6
  const WORKFLOW_WARNING_COLUMNS = ['id', 'time', 'step', 'severity', 'code', 'status', 'target', 'message', 'action', 'resolved_at', 'resolution'] as const;
7
+ const WARNING_TIME_PATTERN = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?$/;
7
8
 
8
9
  type WorkflowWarning = {
9
10
  id: string;
@@ -19,14 +20,32 @@ type WorkflowWarning = {
19
20
  resolution: string;
20
21
  };
21
22
 
22
- /** Parses workflow warning rows and fails closed on malformed table structure. */
23
+ /** Parses warning structure and lifecycle fields using one contract for all readers. */
23
24
  function parseWorkflowWarnings(content: string): WorkflowWarning[] {
24
25
  const table = parseTable(content, { sectionAliases: WORKFLOW_WARNING_HEADINGS, columns: WORKFLOW_WARNING_COLUMNS });
25
- return table?.rows.map(({ values }) => ({
26
+ const warnings = table?.rows.map(({ values }) => ({
26
27
  id: values.id!, time: values.time!, step: values.step!, severity: values.severity!,
27
28
  code: values.code!, status: values.status!, target: values.target!, message: values.message!,
28
29
  action: values.action!, resolvedAt: values.resolved_at!, resolution: values.resolution!
29
30
  })) ?? [];
31
+ const errors: { code: string; message: string }[] = [];
32
+ const invalid = (message: string, code = 'WARNING_DOCUMENT_INVALID') => errors.push({ code, message });
33
+ for (const warning of warnings) {
34
+ const { id, time, severity, status, action, resolvedAt, resolution } = warning;
35
+ if (!/^WW-[1-9]\d*$/.test(id)) invalid(`${id || '(empty id)'}: invalid id`, 'WARNING_ID_INVALID');
36
+ if (!WARNING_TIME_PATTERN.test(time)) invalid(`${id}: invalid time '${time}'`);
37
+ for (const field of ['step', 'code', 'target', 'message'] as const) {
38
+ if (!warning[field].trim()) invalid(`${id}: ${field} is required`);
39
+ }
40
+ if (!WORKFLOW_WARNING_SEVERITIES.has(severity)) invalid(`${id}: illegal severity '${severity}'`);
41
+ if (!WORKFLOW_WARNING_STATUSES.has(status)) invalid(`${id}: illegal status '${status}'`);
42
+ if (status === 'open' && !action.trim()) invalid(`${id}: open warning requires action`);
43
+ if ((status === 'resolved' || status === 'ignored') && (!resolvedAt.trim() || !resolution.trim())) {
44
+ invalid(`${id}: ${status} warning requires resolved_at and resolution`);
45
+ }
46
+ }
47
+ if (errors.length) throw Object.assign(new Error(errors.map((error) => error.message).join('; ')), { code: errors[0]!.code });
48
+ return warnings;
30
49
  }
31
50
 
32
51
  function getOpenWorkflowWarnings(content: string): WorkflowWarning[] {
package/lib/update.ts CHANGED
@@ -119,6 +119,12 @@ async function cmdSync(): Promise<void> {
119
119
  replacements
120
120
  );
121
121
  ok('Updated .agents/scripts/lib/agent-infra-package.js');
122
+ renderFile(
123
+ path.join(templateDir, '.agents', 'scripts', 'package.json'),
124
+ path.join('.agents', 'scripts', 'package.json'),
125
+ replacements
126
+ );
127
+ ok('Updated .agents/scripts/package.json');
122
128
  const added = {
123
129
  managed: workflowPlan.projectAssets.registry.managed.filter(
124
130
  (entry) => !currentRegistry.managed.includes(entry)
package/lib/version.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
- import semver from 'semver';
3
2
 
4
3
  const packageJsonUrl = [
5
4
  new URL('../package.json', import.meta.url),
@@ -13,22 +12,9 @@ if (!packageJsonUrl) {
13
12
  const { version } = JSON.parse(readFileSync(packageJsonUrl, 'utf8'));
14
13
  const VERSION = `v${version}`;
15
14
  const AGENT_INFRA_VERSION_PATTERN = /^v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
16
- const LEGACY_COMPATIBILITY_CUTOFF_VERSION = '1.0.0';
17
15
 
18
16
  function isValidAgentInfraVersion(value: unknown): value is string {
19
17
  return typeof value === 'string' && AGENT_INFRA_VERSION_PATTERN.test(value);
20
18
  }
21
19
 
22
- function isLegacyCompatibilityEnabled(runtimeVersion = VERSION): boolean {
23
- const normalized = runtimeVersion.startsWith('v') ? runtimeVersion.slice(1) : runtimeVersion;
24
- const parsed = semver.valid(normalized);
25
- return parsed !== null && semver.lt(parsed, LEGACY_COMPATIBILITY_CUTOFF_VERSION);
26
- }
27
-
28
- function legacyCompatibilityError(resource: string, runtimeVersion = VERSION): Error & { code: string } {
29
- return Object.assign(new Error(
30
- `PLATFORM_IDENTITY_LEGACY_UNSUPPORTED: ${resource} requires migration to the current schema before v${LEGACY_COMPATIBILITY_CUTOFF_VERSION} runtime ${runtimeVersion}`
31
- ), { code: 'PLATFORM_IDENTITY_LEGACY_UNSUPPORTED' });
32
- }
33
-
34
- export { LEGACY_COMPATIBILITY_CUTOFF_VERSION, VERSION, isLegacyCompatibilityEnabled, isValidAgentInfraVersion, legacyCompatibilityError };
20
+ export { VERSION, isValidAgentInfraVersion };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fitlab-ai/agent-infra",
3
- "version": "0.9.14",
3
+ "version": "0.10.0",
4
4
  "description": "Bootstrap tool for AI multi-tool collaboration infrastructure — works with Claude Code, Codex, Antigravity CLI, and OpenCode",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -26,12 +26,13 @@
26
26
  "bin": {
27
27
  "agent-infra": "./dist/bin/cli.js",
28
28
  "ai": "./dist/bin/cli.js",
29
- "agent-infra-internal": "./dist/bin/internal-cli.js"
29
+ "agent-infra-internal": "./bin/internal-cli.sh"
30
30
  },
31
31
  "files": [
32
32
  "dist/",
33
33
  "!dist/**/*.map",
34
34
  "bin/cli.ts",
35
+ "bin/internal-cli.sh",
35
36
  "lib/",
36
37
  "runtime/",
37
38
  "templates/"
@@ -54,7 +55,7 @@
54
55
  "@clack/prompts": "1.7.0",
55
56
  "@larksuiteoapi/node-sdk": "^1.68.0",
56
57
  "cross-spawn": "^7.0.6",
57
- "fs-ext-extra-prebuilt": "2.2.13",
58
+ "fs-native-extensions": "1.5.1",
58
59
  "picocolors": "1.1.1",
59
60
  "semver": "^7.8.1",
60
61
  "smol-toml": "^1.6.1",
@@ -67,6 +68,8 @@
67
68
  "typecheck": "tsc -p tsconfig.test.json --noEmit && tsc -p tsconfig.jschecks.json --noEmit",
68
69
  "test:smoke": "node scripts/run-tests.js \"tests/unit/**/*.test.ts\"",
69
70
  "test:smoke:fast": "node scripts/run-tests.js --skip-build \"tests/unit/**/*.test.ts\"",
71
+ "test:platform-smoke": "node scripts/run-tests.js \"tests/integration/platform-smoke/**/*.test.ts\"",
72
+ "test:platform-smoke:fast": "node scripts/run-tests.js --skip-build \"tests/integration/platform-smoke/**/*.test.ts\"",
70
73
  "test:core": "node scripts/run-tests.js \"tests/unit/**/*.test.ts\" \"tests/integration/**/*.test.ts\"",
71
74
  "test:integration": "node scripts/run-tests.js \"tests/integration/**/*.test.ts\" \"tests/e2e/**/*.test.ts\"",
72
75
  "check": "npm run typecheck && npm test",
@@ -85,8 +88,5 @@
85
88
  },
86
89
  "overrides": {
87
90
  "axios": "1.18.1"
88
- },
89
- "allowScripts": {
90
- "fs-ext-extra-prebuilt@2.2.13": true
91
91
  }
92
92
  }
@@ -16,7 +16,7 @@ function internalCliInvocation(args) {
16
16
  return { command: 'agent-infra-internal', commandArgs: args, shell: process.platform === 'win32' };
17
17
  }
18
18
 
19
- function findCapabilityToken(value, depth = 0) {
19
+ function findCapabilityRef(value, depth = 0) {
20
20
  if (depth > 5 || value == null) return '';
21
21
  if (typeof value === 'string') {
22
22
  const match = /agent-infra-codex-capability:([A-Za-z0-9_-]{20,})/.exec(value);
@@ -24,14 +24,14 @@ function findCapabilityToken(value, depth = 0) {
24
24
  }
25
25
  if (Array.isArray(value)) {
26
26
  for (const entry of value) {
27
- const found = findCapabilityToken(entry, depth + 1);
27
+ const found = findCapabilityRef(entry, depth + 1);
28
28
  if (found) return found;
29
29
  }
30
30
  return '';
31
31
  }
32
32
  if (typeof value === 'object') {
33
33
  for (const entry of Object.values(value)) {
34
- const found = findCapabilityToken(entry, depth + 1);
34
+ const found = findCapabilityRef(entry, depth + 1);
35
35
  if (found) return found;
36
36
  }
37
37
  }
@@ -77,11 +77,11 @@ process.stdin.on('end', () => {
77
77
  process.exit(1);
78
78
  }
79
79
  const managedAgent = /^agent-infra-lifecycle-(executor|reviewer)$/.test(String(nativeAgent || ''));
80
- const capabilityToken = hook === 'post-tool' ? findCapabilityToken(toolResponse) : '';
80
+ const capabilityRef = hook === 'post-tool' ? findCapabilityRef(toolResponse) : '';
81
81
  const parentReconcile = hook === 'post-tool'
82
82
  && toolName === 'collaborationwait_agent'
83
83
  && toolResponse.timed_out !== true;
84
- if (!managedAgent && !parentReconcile && !capabilityToken) process.exit(0);
84
+ if (!managedAgent && !parentReconcile && !capabilityRef) process.exit(0);
85
85
  const hookDefinitionHash = createHash('sha256').update(readFileSync(codexHooks)).digest('hex');
86
86
  const normalized = {
87
87
  sessionId: String(event.session_id || ''),
@@ -96,7 +96,7 @@ process.stdin.on('end', () => {
96
96
  taskName: String(toolInput.task_name || ''),
97
97
  transcriptPath: String(event.transcript_path || '')
98
98
  };
99
- if (capabilityToken) normalized.capabilityToken = capabilityToken;
99
+ if (capabilityRef) normalized.capabilityRef = capabilityRef;
100
100
  const args = ['codex-lifecycle', 'hook-event', '--event', hook, '--bridge', 'true'];
101
101
  try {
102
102
  const { command, commandArgs, shell } = internalCliInvocation(args);
@@ -9,6 +9,6 @@ agent-infra-internal platform-issue create {task-id} --agent {standard-agent-tok
9
9
  agent-infra-internal platform-issue sync {task-id} --agent {standard-agent-token} --status waiting-for-triage --assignees current --milestone initial --issue-type --fields
10
10
  ```
11
11
 
12
- The core reads only persisted task identity, title, type, description, and requirements, and reuses deterministic `ai task issue-body` rendering. It owns template selection, upstream/capabilities, duplicate prevention, POST outcome boundaries, response validation, and atomic `issue_number` binding.
12
+ The core reads only persisted task identity, title, type, description, and requirements, and reuses deterministic `ai task issue-body` rendering. It owns template selection, upstream/capabilities, duplicate prevention, POST outcome boundaries, response validation, and atomic `platform_issue_identity` binding.
13
13
 
14
14
  `planned|applied|no-op|degraded` exit 0, `failed` exits 1, and `blocked` exits 2. Callers must not fall back to direct platform CLI or GraphQL orchestration.
@@ -8,7 +8,7 @@
8
8
  agent-infra-internal platform-issue create {task-id} --agent {standard-agent-token}
9
9
  ```
10
10
 
11
- 命令只从已落盘 task.md 读取身份、标题、类型、描述与需求,并复用 `ai task issue-body` 的确定性正文渲染。它负责模板选择、upstream/capability、已有绑定检查、非幂等 POST 边界、响应身份校验及通过任务写入内核回写 `issue_number`。
11
+ 命令只从已落盘 task.md 读取身份、标题、类型、描述与需求,并复用 `ai task issue-body` 的确定性正文渲染。它负责模板选择、upstream/capability、已有绑定检查、非幂等 POST 边界、响应身份校验及通过任务写入内核回写 `platform_issue_identity`。
12
12
 
13
13
  创建后的初始元数据使用同一适配层同步:
14
14
 
@@ -12,19 +12,21 @@
12
12
  | `summary` | `<!-- sync-issue:{task-id}:summary -->` |
13
13
  | `cancel` | `<!-- sync-issue:{task-id}:cancel -->` |
14
14
 
15
- `pr-review` content is synced only as an Issue artifact comment (via the `artifact` / `artifactChunk` markers) and is never a `restore-task` recovery source; restore still accepts only an Issue number and reads only registered Issue markers, with no PR source.
15
+ `pr-review` content is synced only as an Issue artifact comment (via the `artifact` / `artifactChunk` markers) and is never a `restore-task` recovery source; restore still accepts only an Issue token and reads only registered Issue markers, with no PR source.
16
16
 
17
17
  Comments use `platform-comment`; Issue resources use `platform-issue`:
18
18
 
19
19
  ```bash
20
20
  agent-infra-internal platform-issue inspect {task-id}
21
21
  agent-infra-internal platform-issue create {task-id} --agent {standard-agent-token}
22
- agent-infra-internal platform-issue bind {task-id} --issue {number} --agent {standard-agent-token}
22
+ agent-infra-internal platform-issue bind {task-id} --issue {issue-token} --agent {standard-agent-token}
23
23
  agent-infra-internal platform-issue sync {task-id} --agent {standard-agent-token} {desired-state-flags}
24
24
  ```
25
25
 
26
26
  The core owns status/in labels, assignees, milestones, Issue Type, pinned fields, requirements, state, capabilities, dry-run, retries, errors, and idempotency. Omitted flags preserve values; `none` explicitly clears them. Status labels converge to at most one, and ambiguous requirement identity fails closed.
27
27
 
28
+ Task content over the platform comment byte limit is not uploaded; the core returns a skipped operation with `COMMENT_PAYLOAD_TOO_LARGE`. The local task file is unchanged, and platform verification skips the task marker/content check for the same oversized input.
29
+
28
30
  PR event `in:` synchronization uses `agent-infra-internal platform-pr sync-in-labels --pr <N> [--cwd <path>]`. PR files are the event evidence; a unique closing Issue is written and re-read before the PR. Zero or multiple closing Issues update only the PR and return `degraded`; unknown side effects or failed convergence return `blocked` with `IN_LABEL_SYNC_PARTIAL`.
29
31
 
30
32
  `planned|applied|no-op|degraded` exit 0; `failed` exits 1; `blocked` exits 2.
@@ -16,7 +16,7 @@
16
16
 
17
17
  `prSummary` 属于 `.agents/rules/pr-sync.md`,本规则不实现 PR 聚合。
18
18
 
19
- `pr-review` 原文只通过 `artifact` / `artifactChunk` marker 同步为 Issue artifact 评论,不作为 `restore-task` 恢复来源;恢复仍只接受 Issue 编号并只读注册的 Issue marker,不新增 PR 来源。
19
+ `pr-review` 原文只通过 `artifact` / `artifactChunk` marker 同步为 Issue artifact 评论,不作为 `restore-task` 恢复来源;恢复仍只接受 Issue 原始 token 并只读注册的 Issue marker,不新增 PR 来源。
20
20
 
21
21
  ## 平台 intent
22
22
 
@@ -24,7 +24,7 @@
24
24
 
25
25
  ```bash
26
26
  agent-infra-internal platform-context resolve [--cwd <path>]
27
- agent-infra-internal platform-comment list --issue <N> [--cwd <path>]
27
+ agent-infra-internal platform-comment list --issue <issue-token> [--cwd <path>]
28
28
  agent-infra-internal platform-comment owner <task-ref>
29
29
  agent-infra-internal platform-comment sync <task-ref> \
30
30
  --kind task|artifact|summary|cancel --agent {standard-agent-token} \
@@ -33,6 +33,7 @@ agent-infra-internal platform-comment sync <task-ref> \
33
33
 
34
34
  - `applied|no-op|degraded` → exit 0;`failed` → exit 1;`blocked` → exit 2。
35
35
  - task 评论保持 `<details>` frontmatter 可逆格式;artifact 原文内联并在超过 profile 上限时使用 `artifactChunk`。
36
+ - task 内容超过平台评论字节上限时不上传,返回 `COMMENT_PAYLOAD_TOO_LARGE` 的 skipped 操作;本地 task 文件保持不变,platform verification 同样跳过 task marker/content 检查。
36
37
  - 相同 intent 重放必须收敛为 `no-op`;重复 marker 返回 `COMMENT_MARKER_CONFLICT` 且不写入。
37
38
  - 外部贡献者锁定统一使用 `platform-comment owner`;不同作者且无 triage 时返回 `COMMENT_OWNER_CONFLICT`。
38
39
 
@@ -59,7 +60,7 @@ agent-infra-internal task-warning {task-id} add \
59
60
  ```bash
60
61
  agent-infra-internal platform-issue inspect {task-id}
61
62
  agent-infra-internal platform-issue create {task-id} --agent {standard-agent-token}
62
- agent-infra-internal platform-issue bind {task-id} --issue {number} --agent {standard-agent-token}
63
+ agent-infra-internal platform-issue bind {task-id} --issue {issue-token} --agent {standard-agent-token}
63
64
  agent-infra-internal platform-issue sync {task-id} --agent {standard-agent-token} {desired-state-flags}
64
65
  ```
65
66
 
@@ -1,57 +1,64 @@
1
- # General Rule - Model-Driven Local Artifact Repair
1
+ # General Rule - Model-Driven Local Artifact Recovery
2
2
 
3
- This rule applies when `analyze-task`, `plan-task`, or `code-task` handles **the same controlled local artifact** before its completed event, and when `review-analysis`, `review-plan`, or `review-code` handles a finalizer failure for **the same controlled review artifact**. It does not apply to `task.md`, the ledger, receipts, source code, Git, platform resources, or lifecycle state.
3
+ This rule covers the pre-completion gate for `analyze-task`, `plan-task`, and `code-task`, plus the summary finalizers for the three review skills. It handles one canonical artifact in the current task directory only. It does not authorize changes to `task.md`, ledgers, receipts, source code, Git, platform resources, or lifecycle state.
4
4
 
5
- ## Pre-completion gate for analysis, plan, and code artifacts
5
+ ## Pre-completion gate
6
6
 
7
- - `analyze-task`, `plan-task`, and `code-task` must call `task-artifact ... finalize-local` before publishing a completed event; pass only that call's `artifactSha256` and `semanticDigest` to the completed event.
8
- - `finalize-local` does not modify the artifact or task state, but it writes a one-shot local provenance intent in the repository workspace. After `failed`, the model may make one minimal edit in the same artifact only when `repairable=true` and the diagnostic explicitly describes one provably safe structural operation (the current shared engine operations are `replace-line` and `insert-section`), then rerun the same call completely; count each byte-changing edit, up to 8.
9
- - The first repairable failure's semantic digest is retained in that intent; a later `passed` result must match the baseline, and the completed event must verify and atomically transition the same intent to `consumed` before writing `task.md` under the task lock. A consumption failure must not write the task; the consumed intent is durable and retryable, so no failure-prone post-write deletion is attempted. Do not replace a failed baseline with a newly computed digest or publish a completed event without the finalizer.
10
- - After `failed`, no progress, or a repeated diagnostic or fingerprint, do not publish a completed event. After `passed`, do not rescan or manually write summary data.
7
+ - Run the applicable finalizer before a completed event; pass only that invocation's `artifactSha256` and `semanticDigest` to the event.
8
+ - When artifact content is invalid, the finalizer returns a controlled `recovery` with a `recoveryId`, `candidatePath`, and baseline digests. The formal artifact remains unchanged until recovery commit.
9
+ - After the mechanical safety gates pass, the model may edit only the returned `candidatePath`. After each byte-changing edit, rerun the complete finalizer with the same task, stage/family, artifact, and `--recovery-id`. Never edit the formal artifact directly and call it a candidate.
10
+ - A successful finalizer commits through `finalize-ready → commit-started → passed`; completed events accept only matching `passed` final digests and consume the intent under the task lock.
11
+ - Before `finalize-ready`, the recovery core seals the validated final bytes in the controlled `final.md`; later commit ignores the editable `candidate.md` and validates/publishes only that sealed snapshot, so a post-prepare candidate replacement cannot be published.
12
+ - Candidate-only is a protocol authorization boundary, not OS isolation: a same-UID process with arbitrary host filesystem write access may tamper with recovery internals. Identity, fingerprint, and state checks detect such anomalies and fail closed, but the protocol does not claim an independent security principal or cross-platform isolation.
11
13
 
12
- ## Authorization Boundary
14
+ ## Authorization boundary
13
15
 
14
- - The finalizer only reads facts, validates state, normalizes successful results, and performs atomic writes. It does not maintain a recoverable-error allowlist, infer repairability, or choose report content to delete.
15
- - The initial finalizer call is not counted as a repair attempt. Editing is allowed only after the mechanical safety gates pass and the model explicitly determines that the current problem can be solved by a minimal, explainable artifact change.
16
- - The model may edit only the one ordinary local artifact declared by the current skill, and the file must be inside the current task directory. It must not edit `task.md`, the review disagreement ledger, receipts, source code, other reports, or remote resources.
17
- - `changed=false`, an error code, or a format shape is diagnostic evidence, not automatic authorization. The model must judge each case using the complete diagnostic, artifact content, and context.
16
+ - The finalizer and recovery core validate identity, state, permissions, stable reads, complete artifact semantics, and fingerprints. They do not infer repairability or expose a text-operation allow-list.
17
+ - The model may edit only the one ordinary artifact declared by the current skill. It must not edit `task.md`, ledgers, receipts, source code, other reports, or remote resources.
18
+ - `changed=false`, an error code, or a format shape is diagnostic evidence, not edit authorization. Stop on unproven human-decision semantics, concurrency, permission, I/O, identity, provenance, or unknown state.
18
19
 
19
- ## Non-bypassable Mechanical Safety Gates
20
+ ## Non-bypassable mechanical gates
20
21
 
21
- Before every model edit, confirm that:
22
+ Before every candidate edit, confirm that:
22
23
 
23
- 1. the finalizer returned a failure and no artifact operation was committed;
24
- 2. the task, stage, artifact, review round, identity, and provenance still match;
25
- 3. the target is an ordinary file inside the current task directory, with no concurrency conflict, permission error, I/O uncertainty, or target replacement;
26
- 4. the change does not alter human-decision semantics, decision-detail or ledger identity, and does not involve task state, receipts, Git, platform, or any other external side effect. A known and verifiable pending human decision may remain when the model proves the edit is unrelated to that decision.
24
+ 1. the finalizer failed with the same controlled recovery context and nothing formal was committed;
25
+ 2. task, family/stage, round, artifact, request/authority, and baseline fingerprints still match;
26
+ 3. `candidatePath` is the ordinary file generated by the recovery core and the formal target has not changed externally;
27
+ 4. the edit does not change human-decision semantics, detail or ledger identity, and introduces no other side effect.
27
28
 
28
- If any condition fails, stop immediately without invoking a model edit. The model cannot bypass these gates.
29
+ If any condition fails, stop without editing or publishing a completed event.
29
30
 
30
- ## Dynamic Convergence Loop
31
+ ## Durable recovery states
31
32
 
32
- 1. Run the initial finalizer with the fixed task, stage, artifact, and orchestrated intent.
33
- 2. On success, use that complete result for the existing completion gates; do not rescan the ledger or write summary fields manually.
34
- 3. On failure with the safety gates passed, let the model read the structured diagnostic, current artifact, and required context, then decide whether to repair or stop. It must explain the scope and reason for the proposed change.
35
- 4. If the model continues, perform one minimal edit to the artifact. Increment `repairAttempts` only when the file bytes actually change, then rerun the same finalizer intent completely.
36
- 5. Re-run every safety check after each retry. A new, independent problem still limited to the same artifact may be offered to the model for another decision; the previous repairability decision must not be reused automatically.
37
- 6. Stop immediately when the model cannot establish safety or identifies an environment, permission, concurrency, identity, provenance, unknown-state, uncertain human-decision semantics/details, or other non-local problem. A known human decision is not itself a stop condition.
38
- 7. Stop when the diagnostic or artifact fingerprint repeats, no byte-level progress occurs, or the model cannot propose a verifiable minimal change.
39
- 8. Allow at most 8 actual artifact edits per skill invocation as an emergency circuit breaker. This cap only prevents infinite loops and resource exhaustion; it is not a normal business stop condition and does not mean that at most eight problems may be repaired. Preserve the final structured diagnostic when the cap is reached.
33
+ | State | Formal artifact | Allowed action |
34
+ | --- | --- | --- |
35
+ | `awaiting-recovery` | baseline `B` | Edit only controlled candidate `S`; rerun the same finalizer |
36
+ | `finalize-ready` | `B` | Recovery core starts the commit under the task lock |
37
+ | `commit-started` | `B` or final `F` | Reconcile only; retry, confirm, or restore from verified `B/F` fingerprints |
38
+ | `passed` | `F` | Completed event validates the final digest and consumes the intent |
39
+ | `consumed` | `F` | Cleanup may reclaim the controlled staging and backup |
40
+ | `aborted` | verified restored `B` | Preserve diagnostics; never fabricate success |
40
41
 
41
- The repair count exists only in the in-memory context of the current skill invocation. Do not write it to `task.md`, the ledger, or a public receipt. Do not create different normal budgets by error code, skill, or problem type.
42
+ The intent is current-only schema version 3. Legacy schemas fail closed; do not add migration, adapters, or dual writes. Candidate, baseline, and intent files live in controlled repo-local directories and use canonical recovery IDs, regular-file checks, stable reads, the task lock, and expected-value CAS. No cross-file atomicity is claimed; unknown combinations remain indeterminate and retain their evidence.
42
43
 
43
- ## Shared Structural Engine
44
+ ## Dynamic convergence loop
44
45
 
45
- The report skeleton is created by `agent-infra-internal task-artifact {task-id} init --family {family} --artifact {artifact}`. The skeleton writes only identity, headings, and `artifact-section:{family}:{section-id}` markers; it does not represent semantic completion. The current skill must fill each slot with real content. When the finalizer returns one provably safe structural operation, use that result's SHA and semantic digest with `task-artifact {task-id} repair --family {family} --artifact {artifact} --expected-sha256 {artifact-sha256} --expected-semantic-digest {semantic-digest}`. Repair executes only the one operation from the shared engine, does not write `task.md`, the ledger, receipts, Git, or platform resources, and must be followed by a complete rerun of the original finalizer.
46
+ 1. Run the finalizer with the fixed invocation.
47
+ 2. If it fails and the gates pass, read the structured diagnostic and `candidatePath`, then make one minimal, explainable candidate edit.
48
+ 3. Confirm byte-level progress and rerun every finalizer check with the same `--recovery-id`.
49
+ 4. Stop on repeated diagnostics or fingerprints, no byte progress, unknown recovery state, or the eight-edit limit for the current invocation. Do not publish a completed event or generate a cross-stage next step.
46
50
 
47
- ## Completion Events and User Output
51
+ ## Shared entry points
48
52
 
49
- - After the final complete finalizer result succeeds, publish the review completed event using that same result's provenance, ledger state, verdict, and counts. Generate cross-stage next-step commands only when `stageStatus.canAdvance=true` and the verdict is Approved; when `canAdvance=false`, still record the result and route to same-stage revision/review.
50
- - On failure, model stop, lack of progress, repeated diagnostics, or the emergency cap, do not publish a completed event, advance the lifecycle, generate cross-stage commands, or fabricate an approval.
51
- - Stopping advancement does not discard review results. User output must show the artifact path, the last safely readable summary/findings, actual `repairAttempts`, the last structured diagnostic, and the stop reason.
52
- - If the summary cannot be safely parsed, show only the artifact path and the raw structured diagnostic; do not infer counts or add a conclusion, and state that lifecycle advancement stopped while the artifact remains available.
53
- - A stop path may only suggest rerunning the current review skill or handling the issue manually. It must not invoke cross-stage helpers such as `code-task` or `complete-task`.
53
+ The current entry points are `task-artifact ... inspect|init|finalize-local` and `task-review ... finalize-summary`. Recovery retries use the `recoveryId` returned by the finalizer, for example:
54
54
 
55
- ## Lifecycle Isolation
55
+ ```text
56
+ agent-infra-internal task-artifact {task-id} finalize-local --family code --artifact {code-artifact} --recovery-id {recovery-id}
57
+ agent-infra-internal task-review {task-id} finalize-summary --stage code --artifact {review-artifact} --recovery-id {recovery-id}
58
+ ```
56
59
 
57
- `complete-task`, alert closing, task restoration, and other task-lifecycle/task-finalization entry points involve task state, receipts, remote results, or archival side effects and do not consume this rule. They retain their own hard-stop, same-intent retry, and unknown-state semantics.
60
+ There is no `task-artifact repair`, `replace-line`, `insert-section`, or `repairable` authorization. The structural engine returns diagnostics and digests only; the current skill's gates and the model decide whether and how to edit the candidate.
61
+
62
+ ## Lifecycle isolation
63
+
64
+ A completed event may legitimately modify `task.md`, but only after finalizer recovery is `passed` and digest, round, request, and authority all match. If authority consumption fails after the event write, retain the formal artifact and use the existing lifecycle recovery compensation; do not replay the completed write or roll back a passed artifact.
@@ -1,57 +1,64 @@
1
- # 通用规则 - 模型驱动的本地产物修复
1
+ # 通用规则 - 模型驱动的本地产物恢复
2
2
 
3
- 本规则适用于 `analyze-task`、`plan-task`、`code-task` 在 completed 事件前处理**同一个受控本地产物**,以及 `review-analysis`、`review-plan`、`review-code` 在 finalizer 失败后处理**同一个受控 review artifact** 的场景。它不适用于 task.md、账本、receipt、源码、Git、平台资源或生命周期状态。
3
+ 本规则适用于 `analyze-task`、`plan-task`、`code-task` 的本地产物完成前门禁,以及三个 review skill 的 summary finalizer。它只处理当前 task 目录内的一个 canonical artifact;不适用于 `task.md`、账本、receipt、源码、Git、平台资源或生命周期状态。
4
4
 
5
- ## 分析、方案和代码产物完成前门禁
5
+ ## 完成前门禁
6
6
 
7
- - `analyze-task`、`plan-task` 和 `code-task` 必须在发布 completed 事件前调用 `task-artifact ... finalize-local`;只有同一次返回的 `artifactSha256` 和 `semanticDigest` 才能传给 completed 事件。
8
- - `finalize-local` 不修改产物或任务状态,但会在仓库工作区写入一次性的本地 provenance intent。返回 `failed` 时,只有 `repairable=true` 且诊断明确为一个可证明安全的结构操作(当前共享引擎操作为 `replace-line` 或 `insert-section`),模型才可在同一产物中执行一次最小编辑,然后完整重跑同一调用;每次实际字节修改计一次,最多 8 次。
9
- - 首次可修复失败的 semantic digest 会保存在该 intent 中;后续 `passed` 必须匹配该基线,completed event 还必须在任务锁内验证并在写 task.md 前原子转换为 `consumed` 状态。消费失败时不得写任务;转换后的 intent 是可重试的 durable 记录,成功写入后不再执行可能失败的后置删除。不得用重新计算的新摘要替换失败基线,也不得绕过 finalizer 直接发布 completed event。
10
- - 返回 `failed`、无进展、诊断或指纹重复时不得发布 completed 事件;返回 `passed` 后也不得重新扫描或手工补写摘要。
7
+ - 完成事件前必须运行对应 finalizer;只有同一次返回的 `artifactSha256` 和 `semanticDigest` 才能传给 completed event。
8
+ - finalizer 发现 artifact 内容错误时,返回受控 `recovery`(`recoveryId`、`candidatePath`、baseline 指纹)。正式 artifact 在 recovery commit 前必须保持不变。
9
+ - 只有在机械安全门通过后,模型才可编辑返回的 `candidatePath`;每次实际字节变化后,用同一 task、stage/family、artifact 和 `--recovery-id` 完整重跑 finalizer。不得直接编辑正式 artifact 后假设它属于候选。
10
+ - finalizer 通过后,recovery core 按 `finalize-ready → commit-started → passed` 提交候选;completed event 只接受匹配的 `passed`/final digest,并在任务锁内消费 intent。
11
+ - `finalize-ready` 前 recovery core 会把已校验的最终字节封存为受控 `final.md`;后续 commit 忽略可编辑的 `candidate.md`,只校验并发布该封存快照,避免候选在准备后被替换。
12
+ - candidate-only 是协议授权边界,不是操作系统隔离:拥有同一 UID 且可任意写入宿主文件系统的进程可能篡改 recovery 内部文件;协议会通过身份、指纹和状态校验发现异常并失败关闭,但不承诺独立权限主体或跨平台隔离。
11
13
 
12
14
  ## 授权边界
13
15
 
14
- - finalizer 只负责读取事实、校验状态、规范化成功结果和原子写入;它不维护可修复错误码白名单,不推断 repairability,也不自动选择要删除的报告内容。
15
- - 首次 finalizer 调用不计入修复次数。只有在机械安全门通过后,模型明确判断当前问题能通过最小、可解释的 artifact 修改解决时,才允许编辑。
16
- - 模型只能修改当前 skill 声明的一个普通本地产物,且该文件必须位于当前 task 目录。不得修改 task.md、审查分歧账本、receipt、源码、其他报告或远端资源。
17
- - `changed=false`、错误码或某个格式形状只是诊断事实,不是自动批准。模型必须结合完整诊断、artifact 内容和上下文逐例判断。
16
+ - finalizer 和 recovery core 只校验身份、状态、权限、稳定读取、完整 artifact 语义和指纹;不根据错误码猜测“可修复”,也不提供文本操作白名单。
17
+ - 模型只能修改当前 skill 声明的一个普通 artifact。不得修改 task.md、账本、receipt、源码、其他报告或远端资源。
18
+ - `changed=false`、错误码和格式形状只是诊断事实,不是编辑授权。人工裁决、并发、权限、I/O、身份、provenance 或未知状态无法证明安全时,立即停止。
18
19
 
19
20
  ## 不可绕过的机械安全门
20
21
 
21
- 在每次模型编辑前确认:
22
+ 每次编辑候选前确认:
22
23
 
23
- 1. finalizer 返回失败,且没有已提交的 artifact operation;
24
- 2. 任务、stage、artifact、review round、身份和 provenance 仍然一致;
25
- 3. 目标是当前 task 目录内的普通文件,没有并发冲突、权限错误、I/O 不确定性或目标被替换;
26
- 4. 不改变人工裁决语义、裁决详情或账本身份,也不涉及任务状态、receipt、Git、平台或其他外部副作用;已知且可核验的 pending 人工裁决可以保留,但模型必须证明本次修改与该裁决无关。
24
+ 1. finalizer 返回失败并提供同一 recovery context,且没有正式提交;
25
+ 2. task、family/stage、round、artifact、request/authority 和 baseline 指纹仍匹配;
26
+ 3. `candidatePath` 是 recovery core 生成的受控普通文件,formal target 没有外部变化;
27
+ 4. 修改不改变人工裁决语义、详情或账本身份,也不引入其他副作用。
27
28
 
28
- 任一条件不满足,立即停止,不调用模型编辑。安全门不能被模型的语义判断绕过。
29
+ 任一条件不满足,停止,不编辑、不发布 completed。
29
30
 
30
- ## 动态收敛循环
31
+ ## Durable recovery 状态
32
+
33
+ | 状态 | formal artifact | 允许动作 |
34
+ | --- | --- | --- |
35
+ | `awaiting-recovery` | baseline `B` | 只编辑受控 candidate `S`,重跑同一 finalizer |
36
+ | `finalize-ready` | `B` | recovery core 在锁内开始提交 |
37
+ | `commit-started` | `B` 或 final `F` | 只允许 reconcile;按 `B/F` 指纹重试、确认或回滚 |
38
+ | `passed` | `F` | completed event 校验 final digest 后消费 |
39
+ | `consumed` | `F` | 可由中间产物清理流程回收受控 staging/backup |
40
+ | `aborted` | 已确认恢复的 `B` | 只保留诊断,不得伪造成功 |
31
41
 
32
- 1. 使用固定的 task、stage、artifact 和 orchestrated intent 执行首次 finalizer。
33
- 2. 成功时使用这一次完整结果进入既有完成前门禁;不得重新扫描账本或手工补写摘要。
34
- 3. 失败且安全门通过时,模型读取结构化诊断、当前 artifact 和必要上下文,决定继续修复或停止,并说明修改范围和理由。
35
- 4. 模型选择继续时,只做一次最小 artifact 编辑。只有文件字节实际发生变化,才增加一次 `repairAttempts`,然后完整重跑同一个 finalizer intent。
36
- 5. 每次重跑都重新执行全部安全校验。修复后出现新的、独立且仍局限于该 artifact 的问题,可以再次交给模型判断;不能沿用上一次“可修复”的结论。
37
- 6. 模型无法证明下一步安全,或判断问题属于环境、权限、并发、身份、provenance、状态未知、人工裁决语义/详情不确定或其他非本地问题时,立即停止。已知人工裁决本身不是停止条件。
38
- 7. 诊断重复、artifact 指纹重复、没有实际字节进展或模型没有提出可验证的最小修改时,立即停止。
39
- 8. 每次 skill invocation 最多允许 8 次实际 artifact 修改作为紧急熔断。该上限只防止死循环和资源失控,不是正常业务停止条件,也不表示最多只能修复 8 个问题。达到上限时保留最后结构化诊断并停止。
42
+ intent 使用 current-only schema version 3。旧 schema 直接失败关闭;不添加迁移、adapter 或双写。candidate、baseline 和 intent 位于 repo-local 受控目录,使用 canonical recovery ID、普通文件检查、stable read、task lock 和 expected-value CAS。跨文件不宣称原子性;未知组合返回 indeterminate 并保留现场。
43
+
44
+ ## 动态收敛循环
40
45
 
41
- 修复次数只存在于当前 skill invocation 的内存上下文,不写入 task.md、ledger 或公共 receipt。不得按错误码、技能或问题类型设置不同的正常预算。
46
+ 1. 用固定 invocation 运行 finalizer。
47
+ 2. 失败且安全门通过时,读取结构化诊断和 `candidatePath`,只作一次最小、可解释的候选编辑。
48
+ 3. 确认字节变化后,使用同一 `--recovery-id` 完整重跑全部 finalizer 校验。
49
+ 4. 诊断或指纹重复、无字节进展、恢复状态未知或达到当前 invocation 的 8 次编辑上限时停止;不发布 completed,不生成跨阶段 next-step。
42
50
 
43
- ## 共享结构引擎
51
+ ## 共享入口
44
52
 
45
- 报告骨架由 `agent-infra-internal task-artifact {task-id} init --family {family} --artifact {artifact}` 创建。骨架只写身份、标题和 `artifact-section:{family}:{section-id}` marker,不代表语义完成;槽位必须由当前 skill 填入真实内容。finalizer 返回单一可证明结构操作时,使用同一返回值的 SHA 和 semantic digest 调用 `task-artifact {task-id} repair --family {family} --artifact {artifact} --expected-sha256 {artifact-sha256} --expected-semantic-digest {semantic-digest}`。repair 只执行共享引擎给出的一个结构操作,不写 task.md、ledger、receipt、Git 或平台资源,之后必须完整重跑原 finalizer。
53
+ `task-artifact ... inspect|init|finalize-local` 和 `task-review ... finalize-summary` 是当前入口。恢复重试使用 finalizer 返回的 `recoveryId`,例如:
46
54
 
47
- ## 完成事件与用户输出
55
+ ```text
56
+ agent-infra-internal task-artifact {task-id} finalize-local --family code --artifact {code-artifact} --recovery-id {recovery-id}
57
+ agent-infra-internal task-review {task-id} finalize-summary --stage code --artifact {review-artifact} --recovery-id {recovery-id}
58
+ ```
48
59
 
49
- - 最终一次完整 finalizer 成功后,必须使用同一次返回的 provenance、账本状态、verdict 和计数发布 review completed 事件;`stageStatus.canAdvance=true` 且结论为 Approved 时才可生成跨阶段 next-step 命令,`canAdvance=false` 时仍须登记结果并路由到同阶段修订/复审。
50
- - 失败、模型停止、无进展、诊断重复或紧急熔断时,不发布 completed 事件,不推进生命周期,不生成跨阶段命令,也不伪造通过结论。
51
- - 停止推进不等于丢弃审查结果。用户输出必须展示 artifact 路径、已安全读取的最后有效 summary/findings、实际 `repairAttempts`、最后结构化诊断和停止原因。
52
- - summary 无法安全解析时,只展示 artifact 路径和原始结构化诊断,不推算计数、不补写结论,并明确生命周期推进已停止但产物仍可查看。
53
- - 停止路径只提示重新运行当前 review skill 或进行人工处理;不能调用 `code-task`、`complete-task` 等跨阶段 helper。
60
+ 不再存在 `task-artifact repair`、`replace-line`、`insert-section` 或 `repairable` 授权。结构引擎只返回诊断和 digest;候选是否安全、如何修改以及何时停止由当前 skill 的机械门和模型逐例判断。
54
61
 
55
62
  ## 生命周期隔离
56
63
 
57
- `complete-task`、告警关闭、恢复任务和其他 task-lifecycle/task-finalization 入口涉及任务状态、receipt、远端结果或归档副作用,不消费本规则。它们继续使用各自的硬失败、同一 intent 重试和状态未知语义。
64
+ completed event 合法地修改 task.md,但必须发生在 finalizer recovery 已 `passed` 且 digest、round、request/authority 全部匹配之后。若 event 写入后 authority 消费失败,保留正式 artifact,使用既有 lifecycle recovery compensation;不得重放 completed 写入或回滚已通过的 artifact。
@@ -43,6 +43,8 @@ This mirrors "Goal-Driven Execution" in AGENTS.md: define a verifiable success c
43
43
 
44
44
  Complete each item below for this repository. Record the chosen behavior and its boundaries so contributors can select and validate tests consistently.
45
45
 
46
+ When a project uses a cross-platform smoke boundary, keep real CLI, git, shell, environment-forwarding, and process-lifecycle tests outside the unit tier. Document which operating systems execute that boundary and keep structural tier checks separate from line coverage.
47
+
46
48
  ### 1. Test commands
47
49
 
48
50
  > TODO: Document the complete test command and any faster commands used during development.
@@ -43,6 +43,8 @@ assert.match(content, /^name: code-task$/m); // 正向断言已足够
43
43
 
44
44
  请为本仓库填写以下各项,记录选定行为及其边界,以便贡献者一致地选择并验证测试。
45
45
 
46
+ 如果项目使用跨平台 smoke 边界,应将真实 CLI、git、shell、环境透传和进程生命周期测试放在 unit 层之外;记录该边界运行的操作系统,并将测试层级结构检查与代码行覆盖率分开。
47
+
46
48
  ### 1. 测试命令
47
49
 
48
50
  > TODO: 记录完整测试命令,以及开发期间使用的可选快速命令。