@fitlab-ai/agent-infra 0.9.12 → 0.9.14

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 (402) hide show
  1. package/README.md +11 -11
  2. package/README.zh-CN.md +11 -11
  3. package/bin/cli.ts +26 -9
  4. package/dist/bin/cli.js +173 -157
  5. package/dist/bin/internal-cli.js +66 -40
  6. package/dist/lib/agent-client.js +5 -0
  7. package/dist/lib/agent-clients/next-steps.js +6 -1
  8. package/dist/lib/decide.js +3 -3
  9. package/dist/lib/internal/agent-client.js +5 -2
  10. package/dist/lib/internal/cli-route-inventory.js +152 -0
  11. package/dist/lib/internal/codex-lifecycle.js +9 -6
  12. package/dist/lib/internal/codex-sandbox-controller.js +8 -2
  13. package/dist/lib/internal/git-workflow.js +10 -6
  14. package/dist/lib/internal/platform-checks.js +19 -7
  15. package/dist/lib/internal/platform-comment.js +25 -13
  16. package/dist/lib/internal/platform-context.js +6 -3
  17. package/dist/lib/internal/platform-issue.js +20 -13
  18. package/dist/lib/internal/platform-metadata.js +88 -0
  19. package/dist/lib/internal/platform-pr-review.js +26 -13
  20. package/dist/lib/internal/platform-pr.js +84 -31
  21. package/dist/lib/internal/platform-release-notes.js +9 -6
  22. package/dist/lib/internal/platform-security.js +93 -0
  23. package/dist/lib/internal/pr-review-grade.js +25 -12
  24. package/dist/lib/internal/release-workflow.js +23 -9
  25. package/dist/lib/internal/sandbox-control.js +50 -7
  26. package/dist/lib/internal/task-activity.js +16 -7
  27. package/dist/lib/internal/task-artifact.js +235 -24
  28. package/dist/lib/internal/task-context.js +4 -1
  29. package/dist/lib/internal/task-create.js +50 -17
  30. package/dist/lib/internal/task-delivery.js +4 -1
  31. package/dist/lib/internal/task-event.js +10 -4
  32. package/dist/lib/internal/task-finalization.js +6 -3
  33. package/dist/lib/internal/task-invalidation.js +63 -0
  34. package/dist/lib/internal/task-ledger.js +20 -6
  35. package/dist/lib/internal/task-lifecycle.js +6 -3
  36. package/dist/lib/internal/task-operation-registry.js +421 -0
  37. package/dist/lib/internal/task-orchestration.js +12 -0
  38. package/dist/lib/internal/task-override.js +14 -7
  39. package/dist/lib/internal/task-qualification.js +90 -0
  40. package/dist/lib/internal/task-review.js +7 -4
  41. package/dist/lib/internal/task-short-id.js +11 -1
  42. package/dist/lib/internal/task-snapshot.js +4 -1
  43. package/dist/lib/internal/task-validate.js +7 -2
  44. package/dist/lib/internal/task-verify.js +11 -7
  45. package/dist/lib/internal/task-warning.js +11 -4
  46. package/dist/lib/platform/adapters.js +1 -3
  47. package/dist/lib/platform/change-request-git-evidence.js +27 -7
  48. package/dist/lib/platform/comment-safety.js +226 -0
  49. package/dist/lib/platform/completion-backfill.js +6 -5
  50. package/dist/lib/platform/context.js +70 -130
  51. package/dist/lib/platform/github-client.js +1 -1
  52. package/dist/lib/platform/github-provider.js +1130 -0
  53. package/dist/lib/platform/in-label-sync.js +143 -0
  54. package/dist/lib/platform/issue-comments.js +237 -72
  55. package/dist/lib/platform/issues.js +335 -189
  56. package/dist/lib/platform/metadata-labels.js +6 -2
  57. package/dist/lib/platform/none-provider.js +28 -0
  58. package/dist/lib/platform/pr-change-report.js +545 -0
  59. package/dist/lib/platform/pr-checks.js +119 -104
  60. package/dist/lib/platform/pr-review.js +88 -72
  61. package/dist/lib/platform/pr-summary.js +541 -50
  62. package/dist/lib/platform/provider-bridge.js +45 -0
  63. package/dist/lib/platform/provider-contract.d.ts +553 -0
  64. package/dist/lib/platform/provider-contract.js +99 -0
  65. package/dist/lib/platform/provider-loader.js +251 -0
  66. package/dist/lib/platform/provider-validation.js +577 -0
  67. package/dist/lib/platform/pull-request-metadata.js +8 -6
  68. package/dist/lib/platform/pull-requests.js +734 -543
  69. package/dist/lib/platform/release-notes.js +78 -55
  70. package/dist/lib/platform/releases.js +79 -50
  71. package/dist/lib/platform/repository-metadata.js +377 -0
  72. package/dist/lib/platform/resource-identity.d.ts +26 -0
  73. package/dist/lib/platform/resource-identity.js +92 -0
  74. package/dist/lib/platform/security-alerts.js +155 -0
  75. package/dist/lib/platform/task-identities.js +31 -0
  76. package/dist/lib/platform/verification-required.js +11 -12
  77. package/dist/lib/platform/verification-sync.js +129 -248
  78. package/dist/lib/pr-review/evidence-grading.js +19 -6
  79. package/dist/lib/process-data/index.js +7 -0
  80. package/dist/lib/run/index.js +68 -23
  81. package/dist/lib/sandbox/commands/control-status.js +22 -0
  82. package/dist/lib/sandbox/commands/create.js +32 -6
  83. package/dist/lib/sandbox/commands/ls.js +5 -0
  84. package/dist/lib/sandbox/commands/rm.js +827 -120
  85. package/dist/lib/sandbox/commands/show.js +16 -0
  86. package/dist/lib/sandbox/control/client.js +174 -19
  87. package/dist/lib/sandbox/control/completed-reentry.js +85 -0
  88. package/dist/lib/sandbox/control/container-identity.js +28 -31
  89. package/dist/lib/sandbox/control/executor.js +151 -16
  90. package/dist/lib/sandbox/control/lifecycle.js +621 -127
  91. package/dist/lib/sandbox/control/native-file-lock.js +177 -0
  92. package/dist/lib/sandbox/control/protocol.js +77 -0
  93. package/dist/lib/sandbox/control/server.js +677 -34
  94. package/dist/lib/sandbox/control/state.js +209 -4
  95. package/dist/lib/sandbox/control/task-view.js +183 -0
  96. package/dist/lib/sandbox/engines/authority.js +289 -0
  97. package/dist/lib/sandbox/engines/docker-exact-discovery.js +97 -0
  98. package/dist/lib/sandbox/index.js +5 -0
  99. package/dist/lib/sandbox/recovery.js +21 -1
  100. package/dist/lib/sandbox/workspace-view.js +2 -1
  101. package/dist/lib/sandbox/worktree-safety.js +4 -1
  102. package/dist/lib/server/index.js +8 -0
  103. package/dist/lib/server/protocol.js +38 -1
  104. package/dist/lib/task/activity-log.js +8 -1
  105. package/dist/lib/task/artifact-lifecycle.js +75 -18
  106. package/dist/lib/task/artifact-operations.js +520 -0
  107. package/dist/lib/task/artifact-repair-intent.js +59 -0
  108. package/dist/lib/task/artifact-schema.js +135 -0
  109. package/dist/lib/task/capabilities.js +310 -0
  110. package/dist/lib/task/commands/status.js +32 -0
  111. package/dist/lib/task/commit-operation.js +12 -1
  112. package/dist/lib/task/control-authority.js +12 -5
  113. package/dist/lib/task/create-service.js +111 -12
  114. package/dist/lib/task/create.js +25 -0
  115. package/dist/lib/task/current-contract.js +5 -1
  116. package/dist/lib/task/decision-details.js +1 -1
  117. package/dist/lib/task/events.js +416 -17
  118. package/dist/lib/task/finalization.js +37 -13
  119. package/dist/lib/task/human-override.js +58 -36
  120. package/dist/lib/task/index.js +11 -3
  121. package/dist/lib/task/invalidation-command.js +86 -0
  122. package/dist/lib/task/invalidation.js +260 -0
  123. package/dist/lib/task/ledger-intents.js +37 -0
  124. package/dist/lib/task/local-artifact-finalization.js +299 -0
  125. package/dist/lib/task/orchestration.js +240 -144
  126. package/dist/lib/task/pr-delivery-fact.js +102 -101
  127. package/dist/lib/task/qualification-audit.js +490 -0
  128. package/dist/lib/task/qualification-confirmation.js +109 -0
  129. package/dist/lib/task/qualification-intents.js +148 -0
  130. package/dist/lib/task/review-artifacts.js +22 -23
  131. package/dist/lib/task/review-finalization.js +121 -4
  132. package/dist/lib/task/review-fingerprint.js +24 -2
  133. package/dist/lib/task/rework-intent.js +138 -0
  134. package/dist/lib/task/sections.js +6 -4
  135. package/dist/lib/task/skill-scope.js +23 -0
  136. package/dist/lib/task/task-execution-lock.js +27 -17
  137. package/dist/lib/task/verification-config.js +11 -0
  138. package/dist/lib/task/verification-engine.js +93 -16
  139. package/dist/lib/task/verification.js +3 -3
  140. package/dist/lib/task/workflow-warning-intents.js +1 -1
  141. package/dist/lib/task/write.js +11 -0
  142. package/dist/lib/version.js +11 -1
  143. package/dist/lifecycle-build-manifest.json +3 -3
  144. package/lib/agent-client.ts +9 -0
  145. package/lib/agent-clients/next-steps.ts +6 -1
  146. package/lib/decide.ts +3 -3
  147. package/lib/init.ts +1 -1
  148. package/lib/internal/agent-client.ts +4 -2
  149. package/lib/internal/cli-route-inventory.ts +140 -0
  150. package/lib/internal/codex-lifecycle.ts +8 -6
  151. package/lib/internal/codex-sandbox-controller.ts +7 -2
  152. package/lib/internal/git-workflow.ts +9 -6
  153. package/lib/internal/platform-checks.ts +14 -6
  154. package/lib/internal/platform-comment.ts +20 -12
  155. package/lib/internal/platform-context.ts +5 -3
  156. package/lib/internal/platform-issue.ts +17 -11
  157. package/lib/internal/platform-metadata.ts +70 -0
  158. package/lib/internal/platform-pr-review.ts +23 -12
  159. package/lib/internal/platform-pr.ts +65 -27
  160. package/lib/internal/platform-release-notes.ts +8 -6
  161. package/lib/internal/platform-security.ts +83 -0
  162. package/lib/internal/pr-review-grade.ts +20 -11
  163. package/lib/internal/release-workflow.ts +21 -9
  164. package/lib/internal/sandbox-control.ts +44 -6
  165. package/lib/internal/task-activity.ts +15 -7
  166. package/lib/internal/task-artifact.ts +204 -22
  167. package/lib/internal/task-context.ts +3 -1
  168. package/lib/internal/task-create.ts +78 -17
  169. package/lib/internal/task-delivery.ts +3 -1
  170. package/lib/internal/task-event.ts +9 -4
  171. package/lib/internal/task-finalization.ts +6 -4
  172. package/lib/internal/task-invalidation.ts +41 -0
  173. package/lib/internal/task-ledger.ts +21 -8
  174. package/lib/internal/task-lifecycle.ts +5 -3
  175. package/lib/internal/task-operation-registry.ts +482 -0
  176. package/lib/internal/task-orchestration.ts +12 -0
  177. package/lib/internal/task-override.ts +15 -9
  178. package/lib/internal/task-qualification.ts +61 -0
  179. package/lib/internal/task-review.ts +6 -4
  180. package/lib/internal/task-short-id.ts +10 -1
  181. package/lib/internal/task-snapshot.ts +3 -1
  182. package/lib/internal/task-validate.ts +6 -2
  183. package/lib/internal/task-verify.ts +10 -7
  184. package/lib/internal/task-warning.ts +10 -4
  185. package/lib/platform/adapters.ts +3 -2
  186. package/lib/platform/change-request-git-evidence.ts +36 -9
  187. package/lib/platform/comment-safety.ts +250 -0
  188. package/lib/platform/completion-backfill.ts +9 -8
  189. package/lib/platform/context.ts +97 -134
  190. package/lib/platform/github-client.ts +2 -2
  191. package/lib/platform/github-provider.ts +1132 -0
  192. package/lib/platform/in-label-sync.ts +208 -0
  193. package/lib/platform/issue-comments.ts +255 -80
  194. package/lib/platform/issues.ts +344 -174
  195. package/lib/platform/metadata-labels.ts +5 -2
  196. package/lib/platform/none-provider.ts +35 -0
  197. package/lib/platform/pr-change-report.ts +639 -0
  198. package/lib/platform/pr-checks.ts +126 -106
  199. package/lib/platform/pr-review.ts +88 -85
  200. package/lib/platform/pr-summary.ts +581 -53
  201. package/lib/platform/provider-bridge.ts +82 -0
  202. package/lib/platform/provider-contract.ts +611 -0
  203. package/lib/platform/provider-loader.ts +307 -0
  204. package/lib/platform/provider-validation.ts +611 -0
  205. package/lib/platform/pull-request-metadata.ts +10 -7
  206. package/lib/platform/pull-requests.ts +781 -550
  207. package/lib/platform/release-notes.ts +76 -59
  208. package/lib/platform/releases.ts +77 -43
  209. package/lib/platform/repository-metadata.ts +453 -0
  210. package/lib/platform/resource-identity.ts +121 -0
  211. package/lib/platform/security-alerts.ts +191 -0
  212. package/lib/platform/task-identities.ts +40 -0
  213. package/lib/platform/types.ts +4 -2
  214. package/lib/platform/verification-required.ts +11 -13
  215. package/lib/platform/verification-sync.ts +128 -304
  216. package/lib/pr-review/evidence-grading.ts +25 -8
  217. package/lib/process-data/index.ts +7 -0
  218. package/lib/run/index.ts +62 -22
  219. package/lib/sandbox/commands/control-status.ts +26 -0
  220. package/lib/sandbox/commands/create.ts +46 -6
  221. package/lib/sandbox/commands/ls.ts +7 -0
  222. package/lib/sandbox/commands/rm.ts +1000 -87
  223. package/lib/sandbox/commands/show.ts +16 -0
  224. package/lib/sandbox/control/client.ts +203 -19
  225. package/lib/sandbox/control/completed-reentry.ts +98 -0
  226. package/lib/sandbox/control/container-identity.ts +27 -43
  227. package/lib/sandbox/control/executor.ts +180 -15
  228. package/lib/sandbox/control/lifecycle.ts +629 -17
  229. package/lib/sandbox/control/native-file-lock.ts +209 -0
  230. package/lib/sandbox/control/protocol.ts +118 -2
  231. package/lib/sandbox/control/server.ts +724 -34
  232. package/lib/sandbox/control/state.ts +257 -4
  233. package/lib/sandbox/control/task-view.ts +240 -0
  234. package/lib/sandbox/engines/authority.ts +365 -0
  235. package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
  236. package/lib/sandbox/index.ts +7 -0
  237. package/lib/sandbox/recovery.ts +21 -1
  238. package/lib/sandbox/workspace-view.ts +9 -3
  239. package/lib/sandbox/worktree-safety.ts +4 -1
  240. package/lib/server/index.ts +10 -0
  241. package/lib/server/protocol.ts +36 -1
  242. package/lib/task/activity-log.ts +8 -0
  243. package/lib/task/artifact-lifecycle.ts +70 -22
  244. package/lib/task/artifact-operations.ts +626 -0
  245. package/lib/task/artifact-repair-intent.ts +71 -0
  246. package/lib/task/artifact-schema.ts +192 -0
  247. package/lib/task/capabilities.ts +331 -0
  248. package/lib/task/commands/status.ts +38 -0
  249. package/lib/task/commit-operation.ts +12 -1
  250. package/lib/task/control-authority.ts +22 -9
  251. package/lib/task/create-service.ts +139 -14
  252. package/lib/task/create.ts +27 -0
  253. package/lib/task/current-contract.ts +6 -1
  254. package/lib/task/decision-details.ts +6 -2
  255. package/lib/task/events.ts +392 -16
  256. package/lib/task/finalization.ts +50 -14
  257. package/lib/task/human-override.ts +70 -46
  258. package/lib/task/index.ts +16 -3
  259. package/lib/task/invalidation-command.ts +86 -0
  260. package/lib/task/invalidation.ts +332 -0
  261. package/lib/task/ledger-intents.ts +35 -1
  262. package/lib/task/local-artifact-finalization.ts +432 -0
  263. package/lib/task/orchestration.ts +223 -133
  264. package/lib/task/pr-delivery-fact.ts +131 -148
  265. package/lib/task/qualification-audit.ts +599 -0
  266. package/lib/task/qualification-confirmation.ts +117 -0
  267. package/lib/task/qualification-intents.ts +150 -0
  268. package/lib/task/review-artifacts.ts +21 -22
  269. package/lib/task/review-finalization.ts +133 -4
  270. package/lib/task/review-fingerprint.ts +23 -2
  271. package/lib/task/rework-intent.ts +165 -0
  272. package/lib/task/sections.ts +6 -4
  273. package/lib/task/skill-scope.ts +24 -0
  274. package/lib/task/task-execution-lock.ts +23 -14
  275. package/lib/task/verification-config.ts +12 -0
  276. package/lib/task/verification-engine.ts +103 -17
  277. package/lib/task/verification.ts +4 -4
  278. package/lib/task/workflow-warning-intents.ts +1 -1
  279. package/lib/task/write.ts +19 -0
  280. package/lib/update.ts +1 -1
  281. package/lib/version.ts +15 -1
  282. package/package.json +12 -1
  283. package/templates/.agents/rules/README.en.md +3 -1
  284. package/templates/.agents/rules/README.zh-CN.md +3 -1
  285. package/templates/.agents/rules/decision-qualification.en.md +22 -0
  286. package/templates/.agents/rules/decision-qualification.zh-CN.md +22 -0
  287. package/templates/.agents/rules/evidence-reporting.en.md +28 -0
  288. package/templates/.agents/rules/evidence-reporting.zh-CN.md +28 -0
  289. package/templates/.agents/rules/issue-pr-commands.en.md +1 -1
  290. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
  291. package/templates/.agents/rules/issue-sync.en.md +2 -0
  292. package/templates/.agents/rules/issue-sync.zh-CN.md +2 -0
  293. package/templates/.agents/rules/label-milestone-setup.en.md +7 -7
  294. package/templates/.agents/rules/label-milestone-setup.zh-CN.md +7 -7
  295. package/templates/.agents/rules/local-artifact-repair.en.md +13 -2
  296. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +13 -2
  297. package/templates/.agents/rules/pr-sync.en.md +10 -4
  298. package/templates/.agents/rules/pr-sync.zh-CN.md +17 -4
  299. package/templates/.agents/rules/security-alerts.en.md +8 -8
  300. package/templates/.agents/rules/security-alerts.zh-CN.md +8 -8
  301. package/templates/.agents/rules/task-short-id.en.md +1 -4
  302. package/templates/.agents/rules/task-short-id.zh-CN.md +1 -3
  303. package/templates/.agents/skills/analyze-task/SKILL.en.md +28 -5
  304. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +29 -5
  305. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -12
  306. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -12
  307. package/templates/.agents/skills/check-task/SKILL.en.md +16 -37
  308. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -37
  309. package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
  310. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
  311. package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
  312. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
  313. package/templates/.agents/skills/code-task/SKILL.en.md +41 -9
  314. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +43 -11
  315. package/templates/.agents/skills/code-task/config/verify.en.json +6 -14
  316. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +6 -14
  317. package/templates/.agents/skills/code-task/reference/code-rules.en.md +5 -4
  318. package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +5 -4
  319. package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
  320. package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
  321. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +3 -1
  322. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +3 -1
  323. package/templates/.agents/skills/code-task/reference/report-template.en.md +42 -15
  324. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +39 -12
  325. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +2 -0
  326. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +2 -0
  327. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +3 -3
  328. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +3 -3
  329. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +10 -4
  330. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +10 -4
  331. package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +2 -0
  332. package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +2 -0
  333. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +4 -3
  334. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +4 -3
  335. package/templates/.agents/skills/complete-task/SKILL.en.md +26 -21
  336. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +25 -21
  337. package/templates/.agents/skills/create-pr/SKILL.en.md +7 -6
  338. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +7 -7
  339. package/templates/.agents/skills/create-pr/config/verify.json +1 -0
  340. package/templates/.agents/skills/create-pr/reference/change-report.en.md +16 -4
  341. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +16 -4
  342. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +5 -3
  343. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +5 -3
  344. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +1 -1
  345. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +1 -1
  346. package/templates/.agents/skills/create-pr/scripts/change-report.mjs +3 -0
  347. package/templates/.agents/skills/create-task/SKILL.en.md +8 -0
  348. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +7 -0
  349. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  350. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  351. package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
  352. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
  353. package/templates/.agents/skills/init-labels/SKILL.en.md +8 -8
  354. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +8 -8
  355. package/templates/.agents/skills/init-milestones/SKILL.en.md +9 -11
  356. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +9 -11
  357. package/templates/.agents/skills/plan-task/SKILL.en.md +27 -4
  358. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +26 -4
  359. package/templates/.agents/skills/plan-task/config/verify.en.json +4 -14
  360. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +4 -14
  361. package/templates/.agents/skills/review-analysis/SKILL.en.md +17 -4
  362. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +17 -4
  363. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -18
  364. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -18
  365. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +50 -23
  366. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +45 -18
  367. package/templates/.agents/skills/review-code/SKILL.en.md +18 -5
  368. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +18 -5
  369. package/templates/.agents/skills/review-code/config/verify.en.json +1 -23
  370. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -23
  371. package/templates/.agents/skills/review-code/reference/report-template.en.md +49 -22
  372. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +45 -18
  373. package/templates/.agents/skills/review-plan/SKILL.en.md +17 -4
  374. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +17 -4
  375. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -18
  376. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -18
  377. package/templates/.agents/skills/review-plan/reference/report-template.en.md +49 -22
  378. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +45 -18
  379. package/templates/.agents/skills/review-pr/SKILL.en.md +5 -1
  380. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +5 -1
  381. package/templates/.agents/skills/review-pr/reference/report-template.en.md +4 -3
  382. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +4 -3
  383. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +9 -3
  384. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +9 -3
  385. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +3 -1
  386. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +3 -1
  387. package/templates/.agents/skills/test/SKILL.en.md +13 -2
  388. package/templates/.agents/skills/test/SKILL.zh-CN.md +13 -2
  389. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +14 -0
  390. package/templates/.agents/skills/watch-pr/SKILL.en.md +2 -2
  391. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +2 -2
  392. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +6 -0
  393. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +6 -0
  394. package/templates/.agents/templates/task.en.md +24 -1
  395. package/templates/.agents/templates/task.zh-CN.md +24 -1
  396. package/templates/.github/workflows/pr-label.yml +7 -26
  397. package/templates/.agents/scripts/security-alerts.github.sh +0 -151
  398. package/templates/.agents/scripts/security-alerts.sh +0 -31
  399. package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +0 -146
  400. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +0 -32
  401. package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +0 -294
  402. package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +0 -6
@@ -1,7 +1,7 @@
1
1
  import { execFileSync } from 'node:child_process';
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
- import { randomUUID } from 'node:crypto';
4
+ import { createHash, randomUUID } from 'node:crypto';
5
5
  import { buildProcessTreeStopCommand } from '../../server/process-control.ts';
6
6
  import { getProcessIdentityState } from '../../server/process-state.ts';
7
7
  import type { ProcessIdentity, ProcessIdentityProbe } from '../../server/process-state.ts';
@@ -9,8 +9,21 @@ import type {
9
9
  SandboxControlExecution,
10
10
  SandboxControlLease,
11
11
  SandboxControlManifest,
12
+ SandboxControlPayload,
13
+ SandboxControlReservation,
14
+ SandboxControlResultEvidence,
12
15
  SandboxControlStatus
13
16
  } from './protocol.ts';
17
+ import {
18
+ parseSandboxControlResultEvidence,
19
+ parseSandboxControlPayload,
20
+ parseSandboxControlReservation,
21
+ SANDBOX_CONTROL_MAX_RESPONSE_BYTES,
22
+ SANDBOX_CONTROL_MAX_LOGICAL_RECORDS,
23
+ SANDBOX_CONTROL_MAX_TERMINAL_RECORD_BYTES,
24
+ SANDBOX_CONTROL_RESERVATION_BYTES
25
+ } from './protocol.ts';
26
+ import { parseSandboxTaskView, taskViewForManifest, type SandboxTaskView } from './task-view.ts';
14
27
 
15
28
  export const SANDBOX_CONTROL_AUDIT_MAX_BYTES = 1024 * 1024;
16
29
  export const SANDBOX_CONTROL_EXECUTION_STOP_MS = 2_000;
@@ -31,11 +44,249 @@ export function atomicWriteJson(filePath: string, value: unknown, mode = 0o600,
31
44
  }
32
45
  }
33
46
 
47
+ export function sandboxControlEncodedJsonBytes(value: unknown): number {
48
+ return Buffer.byteLength(`${JSON.stringify(value)}\n`, 'utf8');
49
+ }
50
+
51
+ export function atomicWriteJsonNoReplace(
52
+ filePath: string,
53
+ value: unknown,
54
+ mode = 0o600,
55
+ createParent = true
56
+ ): void {
57
+ atomicCreateJson(filePath, value, 'SANDBOX_CONTROL_TERMINAL_ALREADY_EXISTS', mode, createParent);
58
+ }
59
+
60
+ function atomicCreateJson(
61
+ filePath: string,
62
+ value: unknown,
63
+ duplicateCode: string,
64
+ mode = 0o600,
65
+ createParent = true
66
+ ): void {
67
+ if (createParent) fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });
68
+ const temporary = path.join(path.dirname(filePath), `.${path.basename(filePath)}.${process.pid}.${randomUUID()}.tmp`);
69
+ try {
70
+ fs.writeFileSync(temporary, `${JSON.stringify(value)}\n`, { mode, flag: 'wx' });
71
+ try {
72
+ fs.linkSync(temporary, filePath);
73
+ } catch (error) {
74
+ if ((error as NodeJS.ErrnoException).code === 'EEXIST') {
75
+ throw new Error(duplicateCode);
76
+ }
77
+ throw error;
78
+ }
79
+ } finally {
80
+ fs.rmSync(temporary, { force: true });
81
+ }
82
+ }
83
+
34
84
  export function readJsonFile(filePath: string): unknown {
35
85
  assertRegularFile(filePath);
36
86
  return JSON.parse(fs.readFileSync(filePath, 'utf8'));
37
87
  }
38
88
 
89
+ export function resultEvidencePath(manifest: SandboxControlManifest, requestId: string): string {
90
+ if (!/^[a-f0-9-]{16,64}$/u.test(requestId)) throw new Error('SANDBOX_CONTROL_RESULT_EVIDENCE_INVALID');
91
+ return path.join(manifest.processingDir, requestId, 'result.json');
92
+ }
93
+
94
+ export function payloadPath(manifest: SandboxControlManifest, requestId: string): string {
95
+ if (!/^[a-f0-9-]{16,64}$/u.test(requestId)) throw new Error('SANDBOX_CONTROL_PAYLOAD_INVALID');
96
+ return path.join(manifest.channelDir, 'responses', `${requestId}.payload.json`);
97
+ }
98
+
99
+ export function reservationPath(manifest: SandboxControlManifest, requestId: string): string {
100
+ if (!/^[a-f0-9-]{16,64}$/u.test(requestId)) throw new Error('SANDBOX_CONTROL_RESERVATION_INVALID');
101
+ return path.join(manifest.processingDir, requestId, 'reservation.json');
102
+ }
103
+
104
+ export function readSandboxControlResultEvidence(filePath: string): SandboxControlResultEvidence {
105
+ assertRegularFile(filePath);
106
+ const raw = fs.readFileSync(filePath, 'utf8');
107
+ if (Buffer.byteLength(raw, 'utf8') > SANDBOX_CONTROL_MAX_TERMINAL_RECORD_BYTES) {
108
+ throw new Error('SANDBOX_CONTROL_RESULT_EVIDENCE_TOO_LARGE');
109
+ }
110
+ try {
111
+ return parseSandboxControlResultEvidence(JSON.parse(raw));
112
+ } catch (error) {
113
+ if (error instanceof Error && error.message === 'SANDBOX_CONTROL_RESULT_EVIDENCE_INVALID') throw error;
114
+ throw new Error('SANDBOX_CONTROL_RESULT_EVIDENCE_INVALID');
115
+ }
116
+ }
117
+
118
+ export function sanitizeSandboxControlOutput(manifest: SandboxControlManifest, output: string): string {
119
+ return manifest.token.length === 0 ? output : output.split(manifest.token).join('[REDACTED]');
120
+ }
121
+
122
+ export function sanitizeSandboxControlResult(
123
+ manifest: SandboxControlManifest,
124
+ result: Readonly<{ exitCode: number; stdout: string; stderr: string }>
125
+ ): { exitCode: number; stdout: string; stderr: string } {
126
+ return {
127
+ exitCode: result.exitCode,
128
+ stdout: sanitizeSandboxControlOutput(manifest, result.stdout),
129
+ stderr: sanitizeSandboxControlOutput(manifest, result.stderr)
130
+ };
131
+ }
132
+
133
+ export function writeSandboxControlResultEvidence(
134
+ manifest: SandboxControlManifest,
135
+ requestId: string,
136
+ result: Readonly<{ exitCode: number; stdout: string; stderr: string }>
137
+ ): SandboxControlResultEvidence {
138
+ const normalized = sanitizeSandboxControlResult(manifest, result);
139
+ const stdout = normalized.stdout;
140
+ const stderr = normalized.stderr;
141
+ if (!/^[a-f0-9-]{16,64}$/u.test(requestId)
142
+ || !Number.isSafeInteger(result.exitCode)
143
+ || Buffer.byteLength(stdout, 'utf8') + Buffer.byteLength(stderr, 'utf8') > SANDBOX_CONTROL_MAX_RESPONSE_BYTES) {
144
+ throw new Error('SANDBOX_CONTROL_RESULT_EVIDENCE_INVALID');
145
+ }
146
+ const evidence: SandboxControlResultEvidence = {
147
+ version: 1,
148
+ id: requestId,
149
+ generation: manifest.generation,
150
+ exitCode: result.exitCode,
151
+ stdoutBytes: Buffer.byteLength(stdout, 'utf8'),
152
+ stderrBytes: Buffer.byteLength(stderr, 'utf8'),
153
+ stdoutSha256: createHash('sha256').update(stdout, 'utf8').digest('hex'),
154
+ stderrSha256: createHash('sha256').update(stderr, 'utf8').digest('hex'),
155
+ captureState: 'metadata-only'
156
+ };
157
+ if (sandboxControlEncodedJsonBytes(evidence) > SANDBOX_CONTROL_MAX_TERMINAL_RECORD_BYTES) {
158
+ throw new Error('SANDBOX_CONTROL_RESULT_EVIDENCE_TOO_LARGE');
159
+ }
160
+ atomicCreateJson(
161
+ resultEvidencePath(manifest, requestId), evidence,
162
+ 'SANDBOX_CONTROL_RESULT_EVIDENCE_ALREADY_EXISTS'
163
+ );
164
+ return readSandboxControlResultEvidence(resultEvidencePath(manifest, requestId));
165
+ }
166
+
167
+ export function writeSandboxControlPayload(
168
+ manifest: SandboxControlManifest,
169
+ requestId: string,
170
+ result: Readonly<{ stdout: string; stderr: string }>
171
+ ): SandboxControlPayload {
172
+ const payload = createSandboxControlPayload(manifest, requestId, result);
173
+ atomicCreateJson(payloadPath(manifest, requestId), payload, 'SANDBOX_CONTROL_PAYLOAD_ALREADY_EXISTS');
174
+ return readSandboxControlPayload(payloadPath(manifest, requestId));
175
+ }
176
+
177
+ export function createSandboxControlPayload(
178
+ manifest: SandboxControlManifest,
179
+ requestId: string,
180
+ result: Readonly<{ stdout: string; stderr: string }>
181
+ ): SandboxControlPayload {
182
+ const stdout = sanitizeSandboxControlOutput(manifest, result.stdout);
183
+ const stderr = sanitizeSandboxControlOutput(manifest, result.stderr);
184
+ const payload: SandboxControlPayload = {
185
+ version: 1,
186
+ id: requestId,
187
+ generation: manifest.generation,
188
+ stdout,
189
+ stderr,
190
+ stdoutBytes: Buffer.byteLength(stdout, 'utf8'),
191
+ stderrBytes: Buffer.byteLength(stderr, 'utf8'),
192
+ stdoutSha256: createHash('sha256').update(stdout, 'utf8').digest('hex'),
193
+ stderrSha256: createHash('sha256').update(stderr, 'utf8').digest('hex')
194
+ };
195
+ if (payload.stdoutBytes + payload.stderrBytes > SANDBOX_CONTROL_MAX_RESPONSE_BYTES) {
196
+ throw new Error('SANDBOX_CONTROL_PAYLOAD_TOO_LARGE');
197
+ }
198
+ if (sandboxControlEncodedJsonBytes(payload) > SANDBOX_CONTROL_MAX_RESPONSE_BYTES) {
199
+ throw new Error('SANDBOX_CONTROL_PAYLOAD_TOO_LARGE');
200
+ }
201
+ return payload;
202
+ }
203
+
204
+ export function readSandboxControlPayload(filePath: string): SandboxControlPayload {
205
+ assertRegularFile(filePath);
206
+ const raw = fs.readFileSync(filePath, 'utf8');
207
+ if (Buffer.byteLength(raw, 'utf8') > SANDBOX_CONTROL_MAX_RESPONSE_BYTES) {
208
+ throw new Error('SANDBOX_CONTROL_PAYLOAD_TOO_LARGE');
209
+ }
210
+ try {
211
+ return parseSandboxControlPayload(JSON.parse(raw));
212
+ } catch {
213
+ throw new Error('SANDBOX_CONTROL_PAYLOAD_INVALID');
214
+ }
215
+ }
216
+
217
+ export function writeSandboxControlReservation(
218
+ manifest: SandboxControlManifest,
219
+ requestId: string,
220
+ usage: Readonly<{ logicalRecords: number; bytes: number }>,
221
+ now = Date.now()
222
+ ): SandboxControlReservation {
223
+ if (usage.logicalRecords >= SANDBOX_CONTROL_MAX_LOGICAL_RECORDS
224
+ || usage.bytes + SANDBOX_CONTROL_RESERVATION_BYTES > SANDBOX_CONTROL_MAX_RESPONSE_BYTES) {
225
+ throw new Error('SANDBOX_CONTROL_CAPACITY_EXHAUSTED');
226
+ }
227
+ const reservation: SandboxControlReservation = {
228
+ version: 1,
229
+ id: requestId,
230
+ generation: manifest.generation,
231
+ logicalRecords: 1,
232
+ bytes: SANDBOX_CONTROL_RESERVATION_BYTES,
233
+ createdAt: now
234
+ };
235
+ atomicCreateJson(reservationPath(manifest, requestId), reservation, 'SANDBOX_CONTROL_RESERVATION_ALREADY_EXISTS');
236
+ return parseSandboxControlReservation(readJsonFile(reservationPath(manifest, requestId)));
237
+ }
238
+
239
+ export function readSandboxControlReservation(filePath: string): SandboxControlReservation {
240
+ return parseSandboxControlReservation(readJsonFile(filePath));
241
+ }
242
+
243
+ export function sandboxControlGenerationUsage(manifest: SandboxControlManifest): { logicalRecords: number; bytes: number } {
244
+ const records = new Map<string, { baseBytes: number; payloadBytes: number; logical: boolean }>();
245
+ const responsesDir = path.join(manifest.channelDir, 'responses');
246
+ if (fs.existsSync(responsesDir)) {
247
+ for (const entry of fs.readdirSync(responsesDir, { withFileTypes: true })) {
248
+ if (!entry.isFile()) continue;
249
+ const terminal = entry.name.match(/^([a-f0-9-]{16,64})\.json$/u);
250
+ const accepted = entry.name.match(/^([a-f0-9-]{16,64})\.accepted\.json$/u);
251
+ const payload = entry.name.match(/^([a-f0-9-]{16,64})\.payload\.json$/u);
252
+ if (!terminal && !accepted && !payload) continue;
253
+ const id = (terminal ?? accepted ?? payload)![1]!;
254
+ const previous = records.get(id) ?? { baseBytes: 0, payloadBytes: 0, logical: false };
255
+ const fileBytes = fs.statSync(path.join(responsesDir, entry.name)).size;
256
+ if (payload) previous.payloadBytes += fileBytes;
257
+ else previous.baseBytes += fileBytes;
258
+ previous.logical ||= Boolean(terminal || accepted);
259
+ records.set(id, previous);
260
+ }
261
+ }
262
+ if (fs.existsSync(manifest.processingDir)) {
263
+ for (const entry of fs.readdirSync(manifest.processingDir, { withFileTypes: true })) {
264
+ if (!entry.isDirectory() || !/^[a-f0-9-]{16,64}$/u.test(entry.name)) continue;
265
+ const resultPath = resultEvidencePath(manifest, entry.name);
266
+ const filePath = reservationPath(manifest, entry.name);
267
+ const previous = records.get(entry.name) ?? { baseBytes: 0, payloadBytes: 0, logical: false };
268
+ if (fs.existsSync(resultPath)) {
269
+ const result = readSandboxControlResultEvidence(resultPath);
270
+ if (result.id !== entry.name || result.generation !== manifest.generation) {
271
+ throw new Error('SANDBOX_CONTROL_RESULT_EVIDENCE_INVALID');
272
+ }
273
+ previous.baseBytes += fs.statSync(resultPath).size;
274
+ previous.logical = true;
275
+ }
276
+ if (fs.existsSync(filePath)) {
277
+ const reservation = readSandboxControlReservation(filePath);
278
+ previous.baseBytes = Math.max(previous.baseBytes, reservation.bytes);
279
+ previous.logical = true;
280
+ }
281
+ records.set(entry.name, previous);
282
+ }
283
+ }
284
+ return {
285
+ logicalRecords: [...records.values()].filter((record) => record.logical).length,
286
+ bytes: [...records.values()].reduce((total, record) => total + record.baseBytes + record.payloadBytes, 0)
287
+ };
288
+ }
289
+
39
290
  export function statusPath(manifest: SandboxControlManifest): string {
40
291
  return path.join(manifest.publicStatusDir, 'status.json');
41
292
  }
@@ -46,10 +297,11 @@ export function writeSandboxControlStatus(
46
297
  state: SandboxControlStatus['state'],
47
298
  reasonCode: string | null,
48
299
  activeRequestId: string | null,
49
- now = Date.now()
300
+ now = Date.now(),
301
+ taskView: SandboxTaskView = taskViewForManifest(manifest)
50
302
  ): SandboxControlStatus {
51
303
  const status: SandboxControlStatus = {
52
- version: 2, generation: manifest.generation, broker, state, reasonCode, activeRequestId, updatedAt: now
304
+ version: 3, generation: manifest.generation, broker, state, reasonCode, activeRequestId, updatedAt: now, taskView
53
305
  };
54
306
  atomicWriteJson(statusPath(manifest), status, 0o600, false);
55
307
  return status;
@@ -57,7 +309,7 @@ export function writeSandboxControlStatus(
57
309
 
58
310
  export function parseSandboxControlStatus(value: unknown): SandboxControlStatus {
59
311
  const status = value as Partial<SandboxControlStatus> | null;
60
- if (!status || status.version !== 2 || typeof status.generation !== 'string'
312
+ if (!status || status.version !== 3 || typeof status.generation !== 'string'
61
313
  || !status.broker || !Number.isSafeInteger(status.broker.pid) || typeof status.broker.startTime !== 'number'
62
314
  || !Number.isSafeInteger(status.broker.startTime) || typeof status.broker.brokerId !== 'string'
63
315
  || status.broker.brokerId.length === 0
@@ -65,6 +317,7 @@ export function parseSandboxControlStatus(value: unknown): SandboxControlStatus
65
317
  || (status.reasonCode !== null && typeof status.reasonCode !== 'string')
66
318
  || (status.activeRequestId !== null && typeof status.activeRequestId !== 'string')
67
319
  || !Number.isSafeInteger(status.updatedAt)) throw new Error('SANDBOX_CONTROL_STATUS_INVALID');
320
+ parseSandboxTaskView(status.taskView);
68
321
  return status as SandboxControlStatus;
69
322
  }
70
323
 
@@ -0,0 +1,240 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ export const SANDBOX_TASK_VIEW_STATES = ['not-applicable', 'current', 'finalized-stale', 'unknown'] as const;
5
+ export const SANDBOX_TASK_VIEW_SOURCES = ['active', 'completed', 'unknown'] as const;
6
+
7
+ export type SandboxTaskViewState = typeof SANDBOX_TASK_VIEW_STATES[number];
8
+ export type SandboxTaskViewSource = typeof SANDBOX_TASK_VIEW_SOURCES[number];
9
+ export type SandboxTaskViewReceipt = Readonly<{
10
+ receiptId: string;
11
+ revision: number;
12
+ generation: string;
13
+ requestId: string;
14
+ }>;
15
+ export type SandboxTaskView = Readonly<{
16
+ state: SandboxTaskViewState;
17
+ taskId: string | null;
18
+ observedSource: SandboxTaskViewSource | null;
19
+ receipt: SandboxTaskViewReceipt | null;
20
+ reasonCode: string | null;
21
+ }>;
22
+
23
+ export type TaskViewProjectionInput = Readonly<{
24
+ mode: 'task-bound' | 'branch-only';
25
+ taskId: string | null;
26
+ generation: string;
27
+ source: SandboxTaskViewSource;
28
+ sourceMatches: boolean;
29
+ receipt?: unknown;
30
+ requestId?: string;
31
+ }>;
32
+
33
+ export type TaskViewAccessEffect =
34
+ | 'diagnostic'
35
+ | 'progress'
36
+ | 'artifact-write'
37
+ | 'terminal-verdict'
38
+ | 'recovery'
39
+ | 'cleanup'
40
+ | 'remote-write';
41
+
42
+ export type TaskViewAccess = Readonly<{
43
+ allowed: boolean;
44
+ state: SandboxTaskViewState;
45
+ reasonCode: string | null;
46
+ message: string | null;
47
+ }>;
48
+
49
+ function invalidView(message: string): Error {
50
+ return new Error(`SANDBOX_TASK_VIEW_INVALID: ${message}`);
51
+ }
52
+
53
+ function receiptIdentity(value: unknown, generation: string, requestId?: string): SandboxTaskViewReceipt | null {
54
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
55
+ const receipt = value as Record<string, unknown>;
56
+ const binding = receipt.controlBinding;
57
+ if (!binding || typeof binding !== 'object' || Array.isArray(binding)) return null;
58
+ const controlBinding = binding as Record<string, unknown>;
59
+ if (receipt.version !== 2 || typeof receipt.receiptId !== 'string' || receipt.receiptId.length === 0
60
+ || !Number.isSafeInteger(receipt.revision) || (receipt.revision as number) < 0
61
+ || receipt.lifecycle !== 'done'
62
+ || controlBinding.generation !== generation
63
+ || typeof controlBinding.requestId !== 'string'
64
+ || !/^[a-f0-9-]{16,64}$/u.test(controlBinding.requestId)
65
+ || (requestId !== undefined && controlBinding.requestId !== requestId)) return null;
66
+ return {
67
+ receiptId: receipt.receiptId,
68
+ revision: receipt.revision as number,
69
+ generation,
70
+ requestId: controlBinding.requestId
71
+ };
72
+ }
73
+
74
+ export function parseSandboxTaskView(value: unknown): SandboxTaskView {
75
+ if (!value || typeof value !== 'object' || Array.isArray(value)) throw invalidView('taskView must be an object');
76
+ const view = value as Record<string, unknown>;
77
+ const receipt = view.receipt === null ? null : parseSandboxTaskViewReceipt(view.receipt);
78
+ if (!SANDBOX_TASK_VIEW_STATES.includes(view.state as SandboxTaskViewState)
79
+ || (view.taskId !== null && typeof view.taskId !== 'string')
80
+ || (view.observedSource !== null && !SANDBOX_TASK_VIEW_SOURCES.includes(view.observedSource as SandboxTaskViewSource))
81
+ || (view.reasonCode !== null && typeof view.reasonCode !== 'string')
82
+ || (view.receipt !== null && receipt === null)) {
83
+ throw invalidView('taskView schema is invalid');
84
+ }
85
+ if (view.state === 'not-applicable' && (view.taskId !== null || view.observedSource !== null || view.receipt !== null)) {
86
+ throw invalidView('not-applicable taskView cannot carry task evidence');
87
+ }
88
+ if (view.state === 'current' && (view.taskId === null || view.observedSource === null)) {
89
+ throw invalidView('current taskView requires taskId and observedSource');
90
+ }
91
+ if (view.state === 'current' && view.observedSource === 'completed' && view.receipt === null) {
92
+ throw invalidView('completed current taskView requires receipt');
93
+ }
94
+ if (view.state === 'finalized-stale' && (view.taskId === null || view.receipt === null)) {
95
+ throw invalidView('finalized-stale taskView requires taskId and receipt');
96
+ }
97
+ return view as SandboxTaskView;
98
+ }
99
+
100
+ function parseSandboxTaskViewReceipt(value: unknown): SandboxTaskViewReceipt | null {
101
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
102
+ const receipt = value as Record<string, unknown>;
103
+ if (Object.keys(receipt).sort().join(',') !== 'generation,receiptId,requestId,revision'
104
+ || typeof receipt.receiptId !== 'string' || receipt.receiptId.length === 0
105
+ || !Number.isSafeInteger(receipt.revision) || (receipt.revision as number) < 0
106
+ || typeof receipt.generation !== 'string' || receipt.generation.length === 0
107
+ || typeof receipt.requestId !== 'string' || !/^[a-f0-9-]{16,64}$/u.test(receipt.requestId)) return null;
108
+ return receipt as SandboxTaskViewReceipt;
109
+ }
110
+
111
+ export function taskViewForManifest(params: Readonly<{
112
+ repoRoot: string;
113
+ mode: 'task-bound' | 'branch-only';
114
+ taskId: string | null;
115
+ generation: string;
116
+ receipt?: unknown;
117
+ }>): SandboxTaskView {
118
+ if (params.mode !== 'task-bound' || !params.taskId) {
119
+ return { state: 'not-applicable', taskId: null, observedSource: null, receipt: null, reasonCode: null };
120
+ }
121
+ const active = path.join(params.repoRoot, '.agents', 'workspace', 'active', params.taskId, 'task.md');
122
+ const completed = path.join(params.repoRoot, '.agents', 'workspace', 'completed', params.taskId, 'task.md');
123
+ const activeExists = fs.existsSync(active);
124
+ const completedExists = fs.existsSync(completed);
125
+ if (activeExists === completedExists) {
126
+ return {
127
+ state: 'unknown', taskId: params.taskId,
128
+ observedSource: activeExists ? 'unknown' : null,
129
+ receipt: null, reasonCode: activeExists ? 'SANDBOX_TASK_VIEW_SOURCE_CONFLICT' : 'SANDBOX_TASK_VIEW_SOURCE_MISSING'
130
+ };
131
+ }
132
+ const source = completedExists ? 'completed' : 'active';
133
+ const receipt = receiptIdentity(params.receipt, params.generation);
134
+ const receiptProvided = params.receipt !== undefined && params.receipt !== null;
135
+ if (source === 'completed' && receipt) {
136
+ return { state: 'current', taskId: params.taskId, observedSource: source, receipt, reasonCode: null };
137
+ }
138
+ if (source === 'active' && receipt) {
139
+ return {
140
+ state: 'finalized-stale', taskId: params.taskId, observedSource: source, receipt,
141
+ reasonCode: 'SANDBOX_TASK_VIEW_SOURCE_STALE'
142
+ };
143
+ }
144
+ if (receiptProvided) {
145
+ return {
146
+ state: 'unknown', taskId: params.taskId, observedSource: source, receipt: null,
147
+ reasonCode: 'SANDBOX_TASK_VIEW_RECEIPT_INVALID'
148
+ };
149
+ }
150
+ if (source === 'active') {
151
+ return { state: 'current', taskId: params.taskId, observedSource: source, receipt: null, reasonCode: null };
152
+ }
153
+ return {
154
+ state: 'unknown', taskId: params.taskId, observedSource: source, receipt: null,
155
+ reasonCode: 'SANDBOX_TASK_VIEW_EVIDENCE_UNAVAILABLE'
156
+ };
157
+ }
158
+
159
+ export function projectSandboxTaskView(input: TaskViewProjectionInput): SandboxTaskView {
160
+ if (input.mode !== 'task-bound' || !input.taskId) {
161
+ return { state: 'not-applicable', taskId: null, observedSource: null, receipt: null, reasonCode: null };
162
+ }
163
+ const receipt = receiptIdentity(input.receipt, input.generation, input.requestId);
164
+ if (input.source === 'completed' && receipt && input.sourceMatches) {
165
+ return { state: 'current', taskId: input.taskId, observedSource: 'completed', receipt, reasonCode: null };
166
+ }
167
+ if (receipt && input.source === 'active' && !input.sourceMatches) {
168
+ return { state: 'finalized-stale', taskId: input.taskId, observedSource: 'active', receipt, reasonCode: 'SANDBOX_TASK_VIEW_SOURCE_STALE' };
169
+ }
170
+ if (!receipt && input.source === 'active' && input.sourceMatches) {
171
+ return { state: 'current', taskId: input.taskId, observedSource: 'active', receipt: null, reasonCode: null };
172
+ }
173
+ return {
174
+ state: 'unknown',
175
+ taskId: input.taskId,
176
+ observedSource: input.source,
177
+ receipt,
178
+ reasonCode: receipt ? 'SANDBOX_TASK_VIEW_SOURCE_UNCONFIRMED' : 'SANDBOX_TASK_VIEW_EVIDENCE_UNAVAILABLE'
179
+ };
180
+ }
181
+
182
+ export function taskViewAfterFinalization(params: Readonly<{
183
+ taskId: string;
184
+ generation: string;
185
+ requestId: string;
186
+ receipt: unknown;
187
+ }>): SandboxTaskView {
188
+ const receipt = receiptIdentity(params.receipt, params.generation, params.requestId);
189
+ if (!receipt) {
190
+ return {
191
+ state: 'unknown', taskId: params.taskId, observedSource: 'unknown', receipt: null,
192
+ reasonCode: 'SANDBOX_TASK_VIEW_RECEIPT_INVALID'
193
+ };
194
+ }
195
+ return {
196
+ state: 'finalized-stale', taskId: params.taskId, observedSource: 'active', receipt,
197
+ reasonCode: 'SANDBOX_TASK_VIEW_FINALIZED'
198
+ };
199
+ }
200
+
201
+ export function mergeSandboxTaskView(
202
+ canonical: SandboxTaskView,
203
+ previous: SandboxTaskView
204
+ ): SandboxTaskView {
205
+ if (previous.state !== 'finalized-stale' && previous.state !== 'unknown') return canonical;
206
+ return previous;
207
+ }
208
+
209
+ export function accessSandboxTaskView(view: SandboxTaskView, effect: TaskViewAccessEffect): TaskViewAccess {
210
+ if (effect === 'diagnostic' || effect === 'cleanup' || effect === 'recovery') {
211
+ return { allowed: true, state: view.state, reasonCode: view.reasonCode, message: null };
212
+ }
213
+ if (view.state === 'current' && view.observedSource === 'active') {
214
+ return { allowed: true, state: view.state, reasonCode: null, message: null };
215
+ }
216
+ const reasonCode = view.state === 'current'
217
+ ? 'SANDBOX_TASK_VIEW_COMPLETED_READ_ONLY'
218
+ : view.reasonCode ?? `SANDBOX_TASK_VIEW_${view.state.toUpperCase().replaceAll('-', '_')}`;
219
+ return {
220
+ allowed: false,
221
+ state: view.state,
222
+ reasonCode,
223
+ message: view.state === 'unknown'
224
+ ? 'task view cannot be confirmed; inspect status, recover the original request, or explicitly clean up the sandbox'
225
+ : view.state === 'finalized-stale'
226
+ ? 'task view is finalized/stale; exit or clean up the sandbox, or use a validated re-entry'
227
+ : 'completed task views are read-only'
228
+ };
229
+ }
230
+
231
+ export function taskViewFromStatus(value: unknown): SandboxTaskView {
232
+ if (!value || typeof value !== 'object' || Array.isArray(value)) throw invalidView('status must be an object');
233
+ const status = value as Record<string, unknown>;
234
+ if (status.version !== 3) throw invalidView('status version is unsupported');
235
+ const taskView = parseSandboxTaskView(status.taskView);
236
+ if (taskView.receipt && taskView.receipt.generation !== status.generation) {
237
+ throw invalidView('taskView receipt generation does not match status generation');
238
+ }
239
+ return taskView;
240
+ }