@fitlab-ai/agent-infra 0.8.5 → 0.9.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 (425) hide show
  1. package/bin/cli.ts +2 -2
  2. package/dist/bin/cli.js +2 -2
  3. package/dist/bin/internal-cli.js +98 -0
  4. package/dist/lib/decide.js +81 -90
  5. package/dist/lib/defaults.json +1 -0
  6. package/dist/lib/git/review-snapshot.js +79 -0
  7. package/dist/lib/git/workflow.js +101 -0
  8. package/dist/lib/internal/git-workflow.js +42 -0
  9. package/dist/lib/internal/platform-checks.js +119 -0
  10. package/dist/lib/internal/platform-comment.js +129 -0
  11. package/dist/lib/internal/platform-context.js +46 -0
  12. package/dist/lib/internal/platform-issue.js +142 -0
  13. package/dist/lib/internal/platform-pr.js +146 -0
  14. package/dist/lib/internal/release-workflow.js +217 -0
  15. package/dist/lib/internal/task-artifact.js +67 -0
  16. package/dist/lib/internal/task-context.js +43 -0
  17. package/dist/lib/internal/task-event.js +70 -0
  18. package/dist/lib/internal/task-ledger.js +114 -0
  19. package/dist/lib/internal/task-lifecycle.js +58 -0
  20. package/dist/lib/internal/task-short-id.js +83 -0
  21. package/dist/lib/internal/task-snapshot.js +47 -0
  22. package/dist/lib/internal/task-verify.js +50 -0
  23. package/dist/lib/internal/task-warning.js +74 -0
  24. package/dist/lib/platform/adapters.js +14 -0
  25. package/dist/lib/platform/context.js +146 -0
  26. package/dist/lib/platform/github-client.js +124 -0
  27. package/dist/lib/platform/issue-comments.js +409 -0
  28. package/dist/lib/platform/issue-metadata.js +183 -0
  29. package/dist/lib/platform/issues.js +617 -0
  30. package/dist/lib/platform/metadata-labels.js +28 -0
  31. package/dist/lib/platform/pr-checks.js +216 -0
  32. package/dist/lib/platform/pr-summary.js +88 -0
  33. package/dist/lib/platform/pull-request-metadata.js +38 -0
  34. package/dist/lib/platform/pull-requests.js +338 -0
  35. package/dist/lib/platform/releases.js +82 -0
  36. package/dist/lib/platform/types.js +22 -0
  37. package/dist/lib/platform/verification-required.js +78 -0
  38. package/dist/lib/platform/verification-sync.js +1014 -0
  39. package/dist/lib/platform/verification.js +6 -0
  40. package/dist/lib/release/channels.js +31 -0
  41. package/dist/lib/release/workflow.js +32 -0
  42. package/dist/lib/render.js +3 -2
  43. package/dist/lib/run/index.js +24 -7
  44. package/dist/lib/sandbox/capture.js +25 -3
  45. package/dist/lib/sandbox/commands/create.js +36 -22
  46. package/dist/lib/sandbox/commands/enter.js +34 -11
  47. package/dist/lib/sandbox/commands/list-running.js +10 -8
  48. package/dist/lib/sandbox/commands/show.js +2 -2
  49. package/dist/lib/sandbox/commands/start.js +53 -15
  50. package/dist/lib/sandbox/index.js +6 -6
  51. package/dist/lib/sandbox/mounts.js +36 -0
  52. package/dist/lib/sandbox/recovery.js +562 -0
  53. package/dist/lib/sandbox/task-resolver.js +5 -1
  54. package/dist/lib/sandbox/tools.js +19 -0
  55. package/dist/lib/server/protocol.js +5 -5
  56. package/dist/lib/task/activity-log.js +61 -0
  57. package/dist/lib/task/artifact-lifecycle.js +427 -0
  58. package/dist/lib/task/command-options.js +30 -0
  59. package/dist/lib/task/commands/cat.js +36 -6
  60. package/dist/lib/task/commands/decisions.js +80 -46
  61. package/dist/lib/task/commands/files.js +21 -7
  62. package/dist/lib/task/commands/grep.js +55 -7
  63. package/dist/lib/task/commands/issue-body.js +23 -14
  64. package/dist/lib/task/commands/log.js +27 -70
  65. package/dist/lib/task/commands/show.js +20 -7
  66. package/dist/lib/task/commands/status.js +18 -8
  67. package/dist/lib/task/decision-intents.js +154 -0
  68. package/dist/lib/task/decision-items.js +53 -0
  69. package/dist/lib/task/events.js +318 -0
  70. package/dist/lib/task/frontmatter.js +159 -1
  71. package/dist/lib/task/implementation-inputs.js +117 -0
  72. package/dist/lib/task/index.js +12 -9
  73. package/dist/lib/task/issue-form.js +19 -6
  74. package/dist/lib/task/ledger-intents.js +185 -0
  75. package/dist/lib/task/ledger.js +65 -35
  76. package/dist/lib/task/lifecycle.js +484 -0
  77. package/dist/lib/task/resolve-ref.js +152 -32
  78. package/dist/lib/task/review-artifacts.js +101 -0
  79. package/dist/lib/task/review-fingerprint.js +46 -0
  80. package/dist/lib/task/sections.js +358 -4
  81. package/dist/lib/task/short-id.js +292 -7
  82. package/dist/lib/task/snapshot.js +95 -0
  83. package/dist/lib/task/verification-checks.js +8 -0
  84. package/dist/lib/task/verification-config.js +14 -0
  85. package/dist/lib/task/verification-engine.js +906 -0
  86. package/dist/lib/task/verification-review.js +3 -0
  87. package/dist/lib/task/verification-types.js +2 -0
  88. package/dist/lib/task/verification.js +113 -0
  89. package/dist/lib/task/workflow-warning-intents.js +131 -0
  90. package/dist/lib/task/workflow-warnings.js +10 -78
  91. package/dist/lib/task/write.js +241 -0
  92. package/lib/decide.ts +57 -97
  93. package/lib/defaults.json +1 -0
  94. package/lib/git/review-snapshot.ts +73 -0
  95. package/lib/git/workflow.ts +101 -0
  96. package/lib/internal/git-workflow.ts +37 -0
  97. package/lib/internal/platform-checks.ts +101 -0
  98. package/lib/internal/platform-comment.ts +99 -0
  99. package/lib/internal/platform-context.ts +33 -0
  100. package/lib/internal/platform-issue.ts +116 -0
  101. package/lib/internal/platform-pr.ts +119 -0
  102. package/lib/internal/release-workflow.ts +186 -0
  103. package/lib/internal/task-artifact.ts +47 -0
  104. package/lib/internal/task-context.ts +35 -0
  105. package/lib/internal/task-event.ts +51 -0
  106. package/lib/internal/task-ledger.ts +86 -0
  107. package/lib/internal/task-lifecycle.ts +41 -0
  108. package/lib/internal/task-short-id.ts +55 -0
  109. package/lib/internal/task-snapshot.ts +32 -0
  110. package/lib/internal/task-verify.ts +33 -0
  111. package/lib/internal/task-warning.ts +50 -0
  112. package/lib/platform/adapters.ts +30 -0
  113. package/lib/platform/context.ts +164 -0
  114. package/lib/platform/github-client.ts +146 -0
  115. package/lib/platform/issue-comments.ts +479 -0
  116. package/lib/platform/issue-metadata.ts +250 -0
  117. package/lib/platform/issues.ts +691 -0
  118. package/lib/platform/metadata-labels.ts +33 -0
  119. package/lib/platform/pr-checks.ts +246 -0
  120. package/lib/platform/pr-summary.ts +90 -0
  121. package/lib/platform/pull-request-metadata.ts +69 -0
  122. package/lib/platform/pull-requests.ts +380 -0
  123. package/lib/platform/releases.ts +71 -0
  124. package/lib/platform/types.ts +74 -0
  125. package/lib/platform/verification-required.ts +83 -0
  126. package/{runtime/platform-adapters/platform-sync.github.js → lib/platform/verification-sync.ts} +198 -367
  127. package/lib/platform/verification.ts +11 -0
  128. package/lib/release/channels.ts +30 -0
  129. package/lib/release/workflow.ts +31 -0
  130. package/lib/render.ts +3 -2
  131. package/lib/run/index.ts +25 -7
  132. package/lib/sandbox/capture.ts +29 -3
  133. package/lib/sandbox/commands/create.ts +43 -25
  134. package/lib/sandbox/commands/enter.ts +38 -11
  135. package/lib/sandbox/commands/list-running.ts +10 -8
  136. package/lib/sandbox/commands/show.ts +2 -2
  137. package/lib/sandbox/commands/start.ts +50 -16
  138. package/lib/sandbox/index.ts +6 -6
  139. package/lib/sandbox/mounts.ts +55 -0
  140. package/lib/sandbox/recovery.ts +828 -0
  141. package/lib/sandbox/task-resolver.ts +5 -1
  142. package/lib/sandbox/tools.ts +31 -0
  143. package/lib/server/protocol.ts +5 -5
  144. package/lib/task/activity-log.ts +62 -0
  145. package/lib/task/artifact-lifecycle.ts +484 -0
  146. package/lib/task/command-options.ts +32 -0
  147. package/lib/task/commands/cat.ts +22 -9
  148. package/lib/task/commands/decisions.ts +49 -47
  149. package/lib/task/commands/files.ts +14 -6
  150. package/lib/task/commands/grep.ts +34 -7
  151. package/lib/task/commands/issue-body.ts +16 -16
  152. package/lib/task/commands/log.ts +17 -70
  153. package/lib/task/commands/show.ts +14 -6
  154. package/lib/task/commands/status.ts +17 -7
  155. package/lib/task/decision-intents.ts +163 -0
  156. package/lib/task/decision-items.ts +64 -0
  157. package/lib/task/events.ts +320 -0
  158. package/lib/task/frontmatter.ts +202 -2
  159. package/lib/task/implementation-inputs.ts +137 -0
  160. package/lib/task/index.ts +12 -9
  161. package/lib/task/issue-form.ts +20 -6
  162. package/lib/task/ledger-intents.ts +201 -0
  163. package/lib/task/ledger.ts +77 -31
  164. package/lib/task/lifecycle.ts +458 -0
  165. package/lib/task/resolve-ref.ts +197 -36
  166. package/{templates/.agents/scripts/lib/review-artifacts.js → lib/task/review-artifacts.ts} +11 -12
  167. package/{templates/.agents/scripts/lib/post-review-commit.js → lib/task/review-fingerprint.ts} +17 -12
  168. package/lib/task/sections.ts +486 -4
  169. package/lib/task/short-id.ts +403 -9
  170. package/lib/task/snapshot.ts +143 -0
  171. package/lib/task/verification-checks.ts +9 -0
  172. package/lib/task/verification-config.ts +20 -0
  173. package/{templates/.agents/scripts/validate-artifact.js → lib/task/verification-engine.ts} +199 -406
  174. package/lib/task/verification-review.ts +9 -0
  175. package/lib/task/verification-types.ts +29 -0
  176. package/lib/task/verification.ts +156 -0
  177. package/lib/task/workflow-warning-intents.ts +142 -0
  178. package/lib/task/workflow-warnings.ts +10 -78
  179. package/lib/task/write.ts +468 -0
  180. package/package.json +4 -2
  181. package/templates/.agents/README.en.md +4 -3
  182. package/templates/.agents/README.zh-CN.md +4 -3
  183. package/templates/.agents/rules/README.en.md +6 -5
  184. package/templates/.agents/rules/README.zh-CN.md +6 -5
  185. package/templates/.agents/rules/create-issue.en.md +1 -1
  186. package/templates/.agents/rules/create-issue.github.en.md +5 -184
  187. package/templates/.agents/rules/create-issue.github.zh-CN.md +12 -178
  188. package/templates/.agents/rules/create-issue.zh-CN.md +1 -1
  189. package/templates/.agents/rules/human-decision-context.en.md +36 -0
  190. package/templates/.agents/rules/human-decision-context.zh-CN.md +36 -0
  191. package/templates/.agents/rules/issue-fields.github.en.md +4 -148
  192. package/templates/.agents/rules/issue-fields.github.zh-CN.md +9 -144
  193. package/templates/.agents/rules/issue-pr-commands.en.md +43 -3
  194. package/templates/.agents/rules/issue-pr-commands.github.en.md +15 -220
  195. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +23 -213
  196. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +45 -3
  197. package/templates/.agents/rules/issue-sync.en.md +1 -1
  198. package/templates/.agents/rules/issue-sync.github.en.md +14 -301
  199. package/templates/.agents/rules/issue-sync.github.zh-CN.md +36 -287
  200. package/templates/.agents/rules/issue-sync.zh-CN.md +1 -1
  201. package/templates/.agents/rules/milestone-inference.en.md +1 -1
  202. package/templates/.agents/rules/milestone-inference.github.en.md +7 -119
  203. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +8 -108
  204. package/templates/.agents/rules/milestone-inference.zh-CN.md +1 -1
  205. package/templates/.agents/rules/next-step-output.en.md +12 -11
  206. package/templates/.agents/rules/next-step-output.zh-CN.md +12 -11
  207. package/templates/.agents/rules/no-mid-flow-questions.en.md +3 -3
  208. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +3 -3
  209. package/templates/.agents/rules/pr-checks-commands.en.md +16 -3
  210. package/templates/.agents/rules/pr-checks-commands.github.en.md +10 -54
  211. package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +19 -47
  212. package/templates/.agents/rules/pr-checks-commands.zh-CN.md +30 -3
  213. package/templates/.agents/rules/pr-sync.en.md +30 -3
  214. package/templates/.agents/rules/pr-sync.github.en.md +12 -115
  215. package/templates/.agents/rules/pr-sync.github.zh-CN.md +26 -104
  216. package/templates/.agents/rules/pr-sync.zh-CN.md +43 -3
  217. package/templates/.agents/rules/review-handshake.en.md +8 -5
  218. package/templates/.agents/rules/review-handshake.zh-CN.md +8 -5
  219. package/templates/.agents/rules/task-management.en.md +11 -2
  220. package/templates/.agents/rules/task-management.zh-CN.md +11 -3
  221. package/templates/.agents/rules/task-short-id.en.md +25 -29
  222. package/templates/.agents/rules/task-short-id.zh-CN.md +20 -23
  223. package/templates/.agents/scripts/lib/agent-infra-package.js +1 -9
  224. package/templates/.agents/scripts/task-short-id.js +71 -533
  225. package/templates/.agents/skills/analyze-task/SKILL.en.md +22 -55
  226. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +26 -59
  227. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -3
  228. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -3
  229. package/templates/.agents/skills/block-task/SKILL.en.md +21 -47
  230. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +23 -47
  231. package/templates/.agents/skills/block-task/config/verify.json +1 -2
  232. package/templates/.agents/skills/cancel-task/SKILL.en.md +16 -45
  233. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +16 -45
  234. package/templates/.agents/skills/cancel-task/config/verify.json +1 -2
  235. package/templates/.agents/skills/check-task/SKILL.en.md +6 -3
  236. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +6 -3
  237. package/templates/.agents/skills/close-codescan/SKILL.en.md +6 -24
  238. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +6 -24
  239. package/templates/.agents/skills/close-dependabot/SKILL.en.md +6 -24
  240. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +6 -24
  241. package/templates/.agents/skills/code-task/SKILL.en.md +22 -35
  242. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +28 -44
  243. package/templates/.agents/skills/code-task/config/verify.en.json +3 -3
  244. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +3 -3
  245. package/templates/.agents/skills/code-task/reference/dual-mode.en.md +13 -9
  246. package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +13 -9
  247. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +1 -1
  248. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +1 -1
  249. package/templates/.agents/skills/code-task/reference/report-template.en.md +11 -1
  250. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +11 -1
  251. package/templates/.agents/skills/commit/SKILL.en.md +13 -11
  252. package/templates/.agents/skills/commit/SKILL.zh-CN.md +13 -11
  253. package/templates/.agents/skills/commit/config/verify.json +1 -2
  254. package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -11
  255. package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -11
  256. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +4 -8
  257. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +4 -8
  258. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +6 -18
  259. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +5 -17
  260. package/templates/.agents/skills/commit/reference/task-status-update.en.md +13 -0
  261. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +13 -0
  262. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +13 -36
  263. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +13 -36
  264. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -3
  265. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -3
  266. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +10 -54
  267. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +10 -79
  268. package/templates/.agents/skills/complete-task/SKILL.en.md +59 -63
  269. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +59 -63
  270. package/templates/.agents/skills/complete-task/config/verify.en.json +11 -7
  271. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +11 -7
  272. package/templates/.agents/skills/create-pr/SKILL.en.md +19 -44
  273. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +19 -43
  274. package/templates/.agents/skills/create-pr/config/verify.json +1 -2
  275. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +8 -12
  276. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +7 -11
  277. package/templates/.agents/skills/create-task/SKILL.en.md +12 -13
  278. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +12 -13
  279. package/templates/.agents/skills/create-task/config/verify.json +1 -2
  280. package/templates/.agents/skills/import-codescan/SKILL.en.md +2 -2
  281. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +2 -2
  282. package/templates/.agents/skills/import-codescan/config/verify.json +1 -2
  283. package/templates/.agents/skills/import-dependabot/SKILL.en.md +2 -2
  284. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +2 -2
  285. package/templates/.agents/skills/import-dependabot/config/verify.json +1 -2
  286. package/templates/.agents/skills/import-issue/SKILL.en.md +9 -13
  287. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +10 -14
  288. package/templates/.agents/skills/import-issue/config/verify.json +1 -2
  289. package/templates/.agents/skills/plan-task/SKILL.en.md +17 -42
  290. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +22 -49
  291. package/templates/.agents/skills/plan-task/config/verify.en.json +1 -3
  292. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -3
  293. package/templates/.agents/skills/post-release/SKILL.en.md +11 -81
  294. package/templates/.agents/skills/post-release/SKILL.zh-CN.md +8 -78
  295. package/templates/.agents/skills/refine-title/SKILL.en.md +1 -1
  296. package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +1 -1
  297. package/templates/.agents/skills/release/SKILL.en.md +16 -163
  298. package/templates/.agents/skills/release/SKILL.zh-CN.md +15 -162
  299. package/templates/.agents/skills/restore-task/SKILL.en.md +11 -29
  300. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +11 -29
  301. package/templates/.agents/skills/restore-task/config/verify.json +1 -2
  302. package/templates/.agents/skills/review-analysis/SKILL.en.md +13 -25
  303. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +13 -33
  304. package/templates/.agents/skills/review-analysis/config/verify.en.json +3 -4
  305. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +3 -4
  306. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +9 -12
  307. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +9 -12
  308. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +9 -2
  309. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +9 -2
  310. package/templates/.agents/skills/review-analysis/reference/review-criteria.en.md +7 -0
  311. package/templates/.agents/skills/review-analysis/reference/review-criteria.zh-CN.md +7 -0
  312. package/templates/.agents/skills/review-code/SKILL.en.md +22 -36
  313. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +23 -41
  314. package/templates/.agents/skills/review-code/config/verify.en.json +3 -4
  315. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +3 -4
  316. package/templates/.agents/skills/review-code/reference/output-templates.en.md +56 -18
  317. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +56 -18
  318. package/templates/.agents/skills/review-code/reference/report-template.en.md +11 -4
  319. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +11 -4
  320. package/templates/.agents/skills/review-code/reference/review-criteria.en.md +7 -0
  321. package/templates/.agents/skills/review-code/reference/review-criteria.zh-CN.md +7 -0
  322. package/templates/.agents/skills/review-plan/SKILL.en.md +13 -25
  323. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +13 -33
  324. package/templates/.agents/skills/review-plan/config/verify.en.json +3 -4
  325. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +3 -4
  326. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +9 -12
  327. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +9 -12
  328. package/templates/.agents/skills/review-plan/reference/report-template.en.md +9 -2
  329. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +9 -2
  330. package/templates/.agents/skills/review-plan/reference/review-criteria.en.md +7 -0
  331. package/templates/.agents/skills/review-plan/reference/review-criteria.zh-CN.md +7 -0
  332. package/templates/.agents/skills/update-agent-infra/SKILL.en.md +1 -2
  333. package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +1 -2
  334. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +3 -15
  335. package/templates/.agents/skills/watch-pr/SKILL.en.md +24 -14
  336. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +25 -15
  337. package/templates/.agents/skills/watch-pr/config/verify.json +1 -2
  338. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +2 -2
  339. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +2 -2
  340. package/templates/.agents/templates/task.en.md +6 -1
  341. package/templates/.agents/templates/task.zh-CN.md +6 -1
  342. package/templates/.claude/commands/analyze-task.en.md +1 -1
  343. package/templates/.claude/commands/analyze-task.zh-CN.md +1 -1
  344. package/templates/.claude/commands/block-task.en.md +1 -1
  345. package/templates/.claude/commands/block-task.zh-CN.md +1 -1
  346. package/templates/.claude/commands/cancel-task.en.md +1 -1
  347. package/templates/.claude/commands/cancel-task.zh-CN.md +1 -1
  348. package/templates/.claude/commands/check-task.en.md +1 -1
  349. package/templates/.claude/commands/check-task.zh-CN.md +1 -1
  350. package/templates/.claude/commands/code-task.en.md +1 -1
  351. package/templates/.claude/commands/code-task.zh-CN.md +1 -1
  352. package/templates/.claude/commands/commit.en.md +1 -0
  353. package/templates/.claude/commands/commit.zh-CN.md +1 -0
  354. package/templates/.claude/commands/complete-manual-validation.en.md +1 -1
  355. package/templates/.claude/commands/complete-manual-validation.zh-CN.md +1 -1
  356. package/templates/.claude/commands/complete-task.en.md +1 -1
  357. package/templates/.claude/commands/complete-task.zh-CN.md +1 -1
  358. package/templates/.claude/commands/create-pr.en.md +1 -1
  359. package/templates/.claude/commands/create-pr.zh-CN.md +1 -1
  360. package/templates/.claude/commands/plan-task.en.md +1 -1
  361. package/templates/.claude/commands/plan-task.zh-CN.md +1 -1
  362. package/templates/.claude/commands/review-analysis.en.md +1 -1
  363. package/templates/.claude/commands/review-analysis.zh-CN.md +1 -1
  364. package/templates/.claude/commands/review-code.en.md +1 -1
  365. package/templates/.claude/commands/review-code.zh-CN.md +1 -1
  366. package/templates/.claude/commands/review-plan.en.md +1 -1
  367. package/templates/.claude/commands/review-plan.zh-CN.md +1 -1
  368. package/templates/.claude/commands/watch-pr.en.md +1 -1
  369. package/templates/.claude/commands/watch-pr.zh-CN.md +1 -1
  370. package/templates/.gemini/commands/_project_/analyze-task.en.toml +2 -0
  371. package/templates/.gemini/commands/_project_/analyze-task.zh-CN.toml +2 -0
  372. package/templates/.gemini/commands/_project_/block-task.en.toml +2 -0
  373. package/templates/.gemini/commands/_project_/block-task.zh-CN.toml +2 -0
  374. package/templates/.gemini/commands/_project_/cancel-task.en.toml +2 -0
  375. package/templates/.gemini/commands/_project_/cancel-task.zh-CN.toml +2 -0
  376. package/templates/.gemini/commands/_project_/check-task.en.toml +2 -0
  377. package/templates/.gemini/commands/_project_/check-task.zh-CN.toml +2 -0
  378. package/templates/.gemini/commands/_project_/code-task.en.toml +2 -0
  379. package/templates/.gemini/commands/_project_/code-task.zh-CN.toml +2 -0
  380. package/templates/.gemini/commands/_project_/commit.en.toml +4 -0
  381. package/templates/.gemini/commands/_project_/commit.zh-CN.toml +4 -0
  382. package/templates/.gemini/commands/_project_/complete-manual-validation.en.toml +2 -0
  383. package/templates/.gemini/commands/_project_/complete-manual-validation.zh-CN.toml +2 -0
  384. package/templates/.gemini/commands/_project_/complete-task.en.toml +2 -0
  385. package/templates/.gemini/commands/_project_/complete-task.zh-CN.toml +2 -0
  386. package/templates/.gemini/commands/_project_/create-pr.en.toml +2 -0
  387. package/templates/.gemini/commands/_project_/create-pr.zh-CN.toml +2 -0
  388. package/templates/.gemini/commands/_project_/plan-task.en.toml +2 -0
  389. package/templates/.gemini/commands/_project_/plan-task.zh-CN.toml +2 -0
  390. package/templates/.gemini/commands/_project_/review-analysis.en.toml +2 -0
  391. package/templates/.gemini/commands/_project_/review-analysis.zh-CN.toml +2 -0
  392. package/templates/.gemini/commands/_project_/review-code.en.toml +2 -0
  393. package/templates/.gemini/commands/_project_/review-code.zh-CN.toml +2 -0
  394. package/templates/.gemini/commands/_project_/review-plan.en.toml +2 -0
  395. package/templates/.gemini/commands/_project_/review-plan.zh-CN.toml +2 -0
  396. package/templates/.gemini/commands/_project_/watch-pr.en.toml +2 -0
  397. package/templates/.gemini/commands/_project_/watch-pr.zh-CN.toml +2 -0
  398. package/templates/.git-hooks/check-large-files.cjs +92 -0
  399. package/templates/.git-hooks/check-version-format.sh +5 -1
  400. package/templates/.git-hooks/pre-commit +1 -0
  401. package/templates/.opencode/commands/analyze-task.en.md +1 -1
  402. package/templates/.opencode/commands/analyze-task.zh-CN.md +1 -1
  403. package/templates/.opencode/commands/check-task.en.md +1 -1
  404. package/templates/.opencode/commands/check-task.zh-CN.md +1 -1
  405. package/templates/.opencode/commands/code-task.en.md +1 -1
  406. package/templates/.opencode/commands/code-task.zh-CN.md +1 -1
  407. package/templates/.opencode/commands/commit.en.md +2 -0
  408. package/templates/.opencode/commands/commit.zh-CN.md +2 -0
  409. package/templates/.opencode/commands/complete-task.en.md +1 -1
  410. package/templates/.opencode/commands/complete-task.zh-CN.md +1 -1
  411. package/templates/.opencode/commands/plan-task.en.md +1 -1
  412. package/templates/.opencode/commands/plan-task.zh-CN.md +1 -1
  413. package/templates/.opencode/commands/review-analysis.en.md +1 -1
  414. package/templates/.opencode/commands/review-analysis.zh-CN.md +1 -1
  415. package/templates/.opencode/commands/review-code.en.md +1 -1
  416. package/templates/.opencode/commands/review-code.zh-CN.md +1 -1
  417. package/templates/.opencode/commands/review-plan.en.md +1 -1
  418. package/templates/.opencode/commands/review-plan.zh-CN.md +1 -1
  419. package/templates/.agents/scripts/platform-adapters/platform-sync.github.js +0 -40
  420. package/templates/.agents/scripts/platform-adapters/platform-sync.js +0 -13
  421. package/templates/.agents/scripts/review-diff-fingerprint.js +0 -170
  422. package/templates/.agents/scripts/workflow-warnings.js +0 -290
  423. package/templates/.agents/skills/code-task/scripts/detect-mode.js +0 -257
  424. package/templates/.agents/skills/release/scripts/manage-milestones.github.sh +0 -80
  425. package/templates/.agents/skills/release/scripts/manage-milestones.sh +0 -6
@@ -0,0 +1,36 @@
1
+ import path from 'node:path';
2
+ import { shareBranchDir, shareCommonDir, shellConfigDirCandidates, worktreeDirCandidates } from './constants.js';
3
+ export function sandboxCoreBindMounts(config, branch, overrides = {}) {
4
+ return [
5
+ {
6
+ hostPaths: overrides.worktree
7
+ ? [overrides.worktree]
8
+ : worktreeDirCandidates(config, branch),
9
+ containerPath: '/workspace',
10
+ readOnly: false
11
+ },
12
+ {
13
+ hostPaths: [path.join(config.repoRoot, '.agents', 'workspace')],
14
+ containerPath: '/workspace/.agents/workspace',
15
+ readOnly: false
16
+ },
17
+ {
18
+ hostPaths: [shareCommonDir(config)],
19
+ containerPath: '/share/common',
20
+ readOnly: false
21
+ },
22
+ {
23
+ hostPaths: [shareBranchDir(config, branch)],
24
+ containerPath: '/share/branch',
25
+ readOnly: false
26
+ },
27
+ {
28
+ hostPaths: overrides.shellConfigHostDir
29
+ ? [overrides.shellConfigHostDir]
30
+ : shellConfigDirCandidates(config, branch),
31
+ containerPath: '/home/devuser/.host-shell-config',
32
+ readOnly: true
33
+ }
34
+ ];
35
+ }
36
+ //# sourceMappingURL=mounts.js.map
@@ -0,0 +1,562 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { containerNameCandidates, sandboxBranchLabel, sandboxLabel } from './constants.js';
4
+ import { toEnginePath } from './engines/wsl2-paths.js';
5
+ import { sandboxCoreBindMounts } from './mounts.js';
6
+ import { runEngine, runOkEngine, runVerboseEngine } from './shell.js';
7
+ import { declaredTmpfsSeedEntries, resolveTools, toolConfigDirCandidates } from './tools.js';
8
+ import { fetchSandboxRows, selectSandboxContainer, startSandboxContainer } from './commands/list-running.js';
9
+ function findingKey(finding) {
10
+ return `${finding.repairKind}:${finding.path ?? finding.seed?.targetPath ?? finding.message}`;
11
+ }
12
+ export function classifySandboxRecovery(snapshot) {
13
+ const findings = [];
14
+ if (!snapshot.identityOk) {
15
+ findings.push({
16
+ repairKind: 'hard-failure',
17
+ message: 'Container identity does not match the requested sandbox branch.'
18
+ });
19
+ }
20
+ for (const mount of snapshot.mounts) {
21
+ if (mount.actualType !== mount.expectedType
22
+ || !mount.sourceMatches
23
+ || mount.actualRW !== mount.expectedRW
24
+ || !mount.sourceAccessible) {
25
+ findings.push({
26
+ repairKind: 'hard-failure',
27
+ message: `Expected ${mount.expectedType} mount at ${mount.path}`
28
+ + `${mount.expectedSource === null ? '' : ` from ${mount.expectedSource}`}`
29
+ + ` with RW=${mount.expectedRW}, found ${mount.actualType ?? 'none'}`
30
+ + `${mount.actualSource === null ? '' : ` from ${mount.actualSource}`}`
31
+ + ` with RW=${mount.actualRW ?? 'unknown'}.`,
32
+ path: mount.path
33
+ });
34
+ }
35
+ }
36
+ for (const mount of snapshot.tmpfs) {
37
+ if (!mount.permissionsOk || !mount.writable) {
38
+ findings.push({
39
+ repairKind: 'permissions',
40
+ message: `Tmpfs ${mount.path} is not owned and writable by devuser with mode 0700.`,
41
+ path: mount.path
42
+ });
43
+ }
44
+ }
45
+ for (const seed of snapshot.seeds) {
46
+ if (!seed.mounted) {
47
+ continue;
48
+ }
49
+ if (seed.targetState === 'missing' || seed.targetState === 'wrong-type') {
50
+ findings.push({
51
+ repairKind: 'missing-seed',
52
+ message: `Runtime seed target ${seed.targetPath} must be restored from staging.`,
53
+ path: seed.targetPath,
54
+ seed: {
55
+ toolId: seed.toolId,
56
+ containerMount: seed.containerMount ?? seed.targetPath.slice(0, seed.targetPath.lastIndexOf('/')),
57
+ stagingPath: seed.stagingPath,
58
+ targetPath: seed.targetPath
59
+ }
60
+ });
61
+ }
62
+ else if (seed.targetState === 'inaccessible') {
63
+ findings.push({
64
+ repairKind: 'hard-failure',
65
+ message: `Runtime seed target ${seed.targetPath} exists but is not accessible to devuser.`,
66
+ path: seed.targetPath
67
+ });
68
+ }
69
+ }
70
+ if (!snapshot.aliasesReadable) {
71
+ findings.push({
72
+ repairKind: 'hard-failure',
73
+ message: 'Sandbox shell aliases are not readable by devuser.',
74
+ path: '/home/devuser/.bash_aliases'
75
+ });
76
+ }
77
+ if (snapshot.codex) {
78
+ if (!snapshot.codex.commandAvailable) {
79
+ findings.push({
80
+ repairKind: 'hard-failure',
81
+ message: 'Codex is not available on PATH inside the sandbox.'
82
+ });
83
+ }
84
+ if (!snapshot.codex.stateWritable) {
85
+ findings.push({
86
+ repairKind: 'permissions',
87
+ message: 'Codex state directory is not writable by devuser.',
88
+ path: '/home/devuser/.codex'
89
+ });
90
+ }
91
+ if (snapshot.codex.promptsSourceExists && !snapshot.codex.promptsValid) {
92
+ findings.push({
93
+ repairKind: 'builtin-link',
94
+ message: 'Codex prompts link does not point to the workspace commands directory.',
95
+ path: '/home/devuser/.codex/prompts'
96
+ });
97
+ }
98
+ }
99
+ const seen = new Set();
100
+ return findings.filter((finding) => {
101
+ const key = findingKey(finding);
102
+ if (seen.has(key))
103
+ return false;
104
+ seen.add(key);
105
+ return true;
106
+ });
107
+ }
108
+ function inspectContainer(engine, container, runFn) {
109
+ const raw = runFn(engine, 'docker', ['inspect', container]);
110
+ const parsed = JSON.parse(raw);
111
+ if (!Array.isArray(parsed) || !parsed[0] || typeof parsed[0] !== 'object') {
112
+ throw new Error(`Unable to inspect sandbox container '${container}'.`);
113
+ }
114
+ return parsed[0];
115
+ }
116
+ function probe(engine, container, script, args, runOkFn, user = 'devuser') {
117
+ return runOkFn(engine, 'docker', [
118
+ 'exec', '--user', user, container, 'sh', '-c', script, 'agent-infra-recovery', ...args
119
+ ]);
120
+ }
121
+ function normalizeMountSource(engine, source) {
122
+ const normalized = toEnginePath(engine, source).replace(/\\/g, '/').replace(/\/+$/, '');
123
+ return /^[A-Za-z]:\//.test(normalized)
124
+ ? `${normalized[0].toLowerCase()}${normalized.slice(1)}`
125
+ : normalized;
126
+ }
127
+ function sourceCandidates(engine, hostPath) {
128
+ const candidates = [hostPath];
129
+ try {
130
+ candidates.push(fs.realpathSync(hostPath));
131
+ }
132
+ catch {
133
+ // The access check below reports a missing or inaccessible host source.
134
+ }
135
+ return [...new Set(candidates.map((candidate) => normalizeMountSource(engine, candidate)))];
136
+ }
137
+ function sameHostSource(left, right) {
138
+ try {
139
+ const leftStat = fs.statSync(left, { bigint: true });
140
+ const rightStat = fs.statSync(right, { bigint: true });
141
+ return leftStat.dev === rightStat.dev && leftStat.ino === rightStat.ino;
142
+ }
143
+ catch {
144
+ return false;
145
+ }
146
+ }
147
+ function hostSourceAccessible(hostPath, writable) {
148
+ try {
149
+ fs.accessSync(hostPath, fs.constants.R_OK | (writable ? fs.constants.W_OK : 0));
150
+ return true;
151
+ }
152
+ catch {
153
+ return false;
154
+ }
155
+ }
156
+ function expectedMounts(params) {
157
+ const { config, branch, actualMounts } = params;
158
+ const tools = resolveTools(config);
159
+ const core = sandboxCoreBindMounts(config, branch).map((mount) => ({
160
+ path: mount.containerPath,
161
+ expectedType: 'bind',
162
+ hostPaths: mount.hostPaths,
163
+ expectedRW: !mount.readOnly
164
+ }));
165
+ const live = tools.flatMap((tool) => (tool.hostLiveMounts ?? []).flatMap(({ hostPath, containerSubpath }) => {
166
+ const destination = path.posix.join(tool.containerMount, containerSubpath);
167
+ if (!fs.existsSync(hostPath) && !actualMounts.has(destination))
168
+ return [];
169
+ return [{
170
+ path: destination,
171
+ expectedType: 'bind',
172
+ hostPaths: [hostPath],
173
+ expectedRW: true
174
+ }];
175
+ }));
176
+ const persistentTools = tools
177
+ .filter((tool) => !tool.tmpfs && actualMounts.has(tool.containerMount))
178
+ .map((tool) => ({
179
+ path: tool.containerMount,
180
+ expectedType: 'bind',
181
+ hostPaths: toolConfigDirCandidates(tool, config.project, branch),
182
+ expectedRW: true
183
+ }));
184
+ const staging = tools.flatMap((tool) => (tool.tmpfs?.seed ?? []).flatMap((seedEntry, index) => {
185
+ const stagingPath = `/run/agent-infra/tmpfs-seeds/${tool.id}/${index}`;
186
+ if (!actualMounts.has(stagingPath))
187
+ return [];
188
+ return [{
189
+ path: stagingPath,
190
+ expectedType: 'bind',
191
+ hostPaths: toolConfigDirCandidates(tool, config.project, branch)
192
+ .map((candidate) => path.join(candidate, seedEntry)),
193
+ expectedRW: false
194
+ }];
195
+ }));
196
+ return [
197
+ ...core,
198
+ ...persistentTools,
199
+ ...live,
200
+ ...staging,
201
+ ...tools
202
+ .filter((tool) => tool.tmpfs)
203
+ .map((tool) => ({
204
+ path: tool.containerMount,
205
+ expectedType: 'tmpfs',
206
+ hostPaths: [],
207
+ expectedRW: true
208
+ }))
209
+ ];
210
+ }
211
+ function targetState(engine, container, seed, runOkFn) {
212
+ const exists = probe(engine, container, 'test -e "$1" || test -L "$1"', [seed.targetPath], runOkFn);
213
+ if (!exists)
214
+ return 'missing';
215
+ const compatible = probe(engine, container, 'if test -d "$1"; then test -d "$2"; else test -f "$2"; fi', [seed.stagingPath, seed.targetPath], runOkFn);
216
+ if (!compatible)
217
+ return 'wrong-type';
218
+ const readable = runOkFn(engine, 'docker', [
219
+ 'exec', '--user', 'devuser', container, 'test', '-r', seed.targetPath
220
+ ]);
221
+ const writable = runOkFn(engine, 'docker', [
222
+ 'exec', '--user', 'devuser', container, 'test', '-w', seed.targetPath
223
+ ]);
224
+ return readable && writable ? 'ok' : 'inaccessible';
225
+ }
226
+ export function collectSandboxRecoverySnapshot(params) {
227
+ const runFn = params.deps?.run ?? runEngine;
228
+ const runOkFn = params.deps?.runOk ?? runOkEngine;
229
+ const inspection = inspectContainer(params.engine, params.container, runFn);
230
+ const mounts = Array.isArray(inspection.Mounts) ? inspection.Mounts : [];
231
+ const mountsByDestination = new Map(mounts.flatMap((mount) => typeof mount.Destination === 'string'
232
+ ? [[mount.Destination, mount]]
233
+ : []));
234
+ const declaredTmpfs = inspection.HostConfig?.Tmpfs;
235
+ if (declaredTmpfs && typeof declaredTmpfs === 'object' && !Array.isArray(declaredTmpfs)) {
236
+ for (const [destination, rawOptions] of Object.entries(declaredTmpfs)) {
237
+ if (mountsByDestination.has(destination) || typeof rawOptions !== 'string')
238
+ continue;
239
+ const options = rawOptions.split(',').map((option) => option.trim());
240
+ mountsByDestination.set(destination, {
241
+ Type: 'tmpfs',
242
+ Source: '',
243
+ Destination: destination,
244
+ RW: !options.includes('ro')
245
+ });
246
+ }
247
+ }
248
+ const tools = resolveTools(params.config);
249
+ const seeds = declaredTmpfsSeedEntries(tools).map((seed) => {
250
+ const mounted = mountsByDestination.get(seed.stagingPath)?.Type === 'bind';
251
+ return {
252
+ toolId: seed.toolId,
253
+ containerMount: seed.containerMount,
254
+ stagingPath: seed.stagingPath,
255
+ targetPath: seed.targetPath,
256
+ mounted,
257
+ targetState: mounted
258
+ ? targetState(params.engine, params.container, seed, runOkFn)
259
+ : 'missing'
260
+ };
261
+ });
262
+ const tmpfs = tools.filter((tool) => tool.tmpfs).map((tool) => ({
263
+ path: tool.containerMount,
264
+ permissionsOk: probe(params.engine, params.container, 'test "$(stat -c %u:%g:%a -- "$1")" = "$(id -u devuser):$(id -g devuser):700"', [tool.containerMount], runOkFn),
265
+ writable: probe(params.engine, params.container, 'probe="$1/.agent-infra-ready-$$"; trap \'rm -f -- "$probe"\' EXIT; : > "$probe"', [tool.containerMount], runOkFn)
266
+ }));
267
+ const labels = inspection.Config?.Labels ?? {};
268
+ const branchLabel = labels[sandboxBranchLabel(params.config)];
269
+ const hasCodex = tools.some((tool) => tool.id === 'codex');
270
+ const mountSnapshots = expectedMounts({
271
+ config: params.config,
272
+ branch: params.branch,
273
+ engine: params.engine,
274
+ actualMounts: mountsByDestination
275
+ }).map((expected) => {
276
+ const actual = mountsByDestination.get(expected.path);
277
+ const actualSource = typeof actual?.Source === 'string' ? actual.Source : null;
278
+ const actualSourceCandidates = actualSource === null
279
+ ? []
280
+ : sourceCandidates(params.engine, actualSource);
281
+ const matchedHostPath = expected.hostPaths.find((hostPath) => sourceCandidates(params.engine, hostPath).some((candidate) => actualSourceCandidates.includes(candidate))
282
+ || (actualSource !== null && sameHostSource(hostPath, actualSource)));
283
+ const sourceMatches = expected.expectedType === 'tmpfs'
284
+ ? actualSource === '' || actualSource === null
285
+ : matchedHostPath !== undefined;
286
+ return {
287
+ path: expected.path,
288
+ expectedType: expected.expectedType,
289
+ actualType: typeof actual?.Type === 'string' ? actual.Type : null,
290
+ expectedSource: expected.hostPaths[0]
291
+ ? normalizeMountSource(params.engine, expected.hostPaths[0])
292
+ : null,
293
+ actualSource,
294
+ sourceMatches,
295
+ expectedRW: expected.expectedRW,
296
+ actualRW: typeof actual?.RW === 'boolean' ? actual.RW : null,
297
+ sourceAccessible: expected.expectedType === 'tmpfs'
298
+ ? true
299
+ : matchedHostPath !== undefined
300
+ && hostSourceAccessible(matchedHostPath, expected.expectedRW)
301
+ };
302
+ });
303
+ return {
304
+ identityOk: typeof inspection.Id === 'string'
305
+ && inspection.Id.length > 0
306
+ && branchLabel === params.branch,
307
+ mounts: mountSnapshots,
308
+ tmpfs,
309
+ seeds,
310
+ aliasesReadable: probe(params.engine, params.container, 'test -r "$1"', ['/home/devuser/.bash_aliases'], runOkFn),
311
+ codex: hasCodex
312
+ ? {
313
+ commandAvailable: probe(params.engine, params.container, 'command -v codex', [], runOkFn),
314
+ stateWritable: probe(params.engine, params.container, 'probe="$1/.agent-infra-codex-state-$$"; trap \'rm -f -- "$probe"\' EXIT; : > "$probe"', ['/home/devuser/.codex'], runOkFn),
315
+ promptsSourceExists: probe(params.engine, params.container, 'test -d "$1"', ['/workspace/.codex/commands'], runOkFn),
316
+ promptsValid: probe(params.engine, params.container, 'test "$(readlink -- "$1")" = "$2"', ['/home/devuser/.codex/prompts', '/workspace/.codex/commands'], runOkFn)
317
+ }
318
+ : undefined
319
+ };
320
+ }
321
+ export function prepareTmpfsMounts(params) {
322
+ const runVerboseFn = params.deps?.runVerbose ?? runVerboseEngine;
323
+ for (const mountPath of params.mountPaths) {
324
+ runVerboseFn(params.engine, 'docker', [
325
+ 'exec', '--user', 'root', params.container, 'chown', 'devuser:', '--', mountPath
326
+ ]);
327
+ runVerboseFn(params.engine, 'docker', [
328
+ 'exec', '--user', 'root', params.container, 'chmod', '0700', '--', mountPath
329
+ ]);
330
+ }
331
+ }
332
+ export function hydrateTmpfsSeedEntries(params) {
333
+ const runVerboseFn = params.deps?.runVerbose ?? runVerboseEngine;
334
+ for (const entry of params.entries) {
335
+ if (params.replace) {
336
+ runVerboseFn(params.engine, 'docker', [
337
+ 'exec', '--user', 'devuser', params.container, 'rm', '-rf', '--', entry.targetPath
338
+ ]);
339
+ }
340
+ runVerboseFn(params.engine, 'docker', [
341
+ 'exec', '--user', 'devuser', params.container, 'mkdir', '-p',
342
+ entry.targetPath.slice(0, entry.targetPath.lastIndexOf('/'))
343
+ ]);
344
+ runVerboseFn(params.engine, 'docker', [
345
+ 'exec', '--user', 'devuser', params.container, 'cp', '-R', '--',
346
+ entry.stagingPath, entry.targetPath
347
+ ]);
348
+ }
349
+ validateTmpfsSeedEntries(params);
350
+ }
351
+ export function validateTmpfsSeedEntries(params) {
352
+ const runVerboseFn = params.deps?.runVerbose ?? runVerboseEngine;
353
+ const runOkFn = params.deps?.runOk ?? runOkEngine;
354
+ for (const entry of params.entries) {
355
+ runVerboseFn(params.engine, 'docker', [
356
+ 'exec', '--user', 'devuser', params.container, 'diff', '-qr', '--',
357
+ entry.stagingPath, entry.targetPath
358
+ ]);
359
+ const readable = runOkFn(params.engine, 'docker', [
360
+ 'exec', '--user', 'devuser', params.container, 'test', '-r', entry.targetPath
361
+ ]);
362
+ const writable = runOkFn(params.engine, 'docker', [
363
+ 'exec', '--user', 'devuser', params.container, 'test', '-w', entry.targetPath
364
+ ]);
365
+ if (!readable || !writable) {
366
+ throw new Error(`Hydrated seed target ${entry.targetPath} is not writable by devuser.`);
367
+ }
368
+ }
369
+ }
370
+ function mountedSeeds(snapshot) {
371
+ return snapshot.seeds.filter((seed) => seed.mounted).map((seed) => ({
372
+ toolId: seed.toolId,
373
+ containerMount: seed.containerMount ?? seed.targetPath.slice(0, seed.targetPath.lastIndexOf('/')),
374
+ stagingPath: seed.stagingPath,
375
+ targetPath: seed.targetPath
376
+ }));
377
+ }
378
+ function repairFindings(params) {
379
+ const permissionPaths = params.findings
380
+ .filter((finding) => finding.repairKind === 'permissions' && finding.path)
381
+ .map((finding) => finding.path);
382
+ prepareTmpfsMounts({
383
+ engine: params.engine,
384
+ container: params.container,
385
+ mountPaths: [...new Set(permissionPaths)],
386
+ deps: params.deps
387
+ });
388
+ const missingSeeds = params.findings.flatMap((finding) => finding.repairKind === 'missing-seed' && finding.seed ? [finding.seed] : []);
389
+ hydrateTmpfsSeedEntries({
390
+ engine: params.engine,
391
+ container: params.container,
392
+ entries: missingSeeds,
393
+ replace: true,
394
+ deps: params.deps
395
+ });
396
+ const runVerboseFn = params.deps?.runVerbose ?? runVerboseEngine;
397
+ if (params.findings.some((finding) => finding.repairKind === 'builtin-link')) {
398
+ runVerboseFn(params.engine, 'docker', [
399
+ 'exec', '--user', 'devuser', params.container, 'ln', '-sfn',
400
+ '/workspace/.codex/commands', '/home/devuser/.codex/prompts'
401
+ ]);
402
+ }
403
+ }
404
+ function describeFindings(findings) {
405
+ return findings.map((finding) => finding.message).join(' ');
406
+ }
407
+ function assess(params) {
408
+ const snapshot = collectSandboxRecoverySnapshot(params);
409
+ return { snapshot, findings: classifySandboxRecovery(snapshot) };
410
+ }
411
+ export function assertFreshSandboxReady(params) {
412
+ validateTmpfsSeedEntries({
413
+ engine: params.engine,
414
+ container: params.container,
415
+ entries: params.copiedEntries,
416
+ deps: params.deps
417
+ });
418
+ const { findings } = assess(params);
419
+ if (findings.length > 0) {
420
+ throw new Error(`Fresh sandbox readiness check failed: ${describeFindings(findings)}`);
421
+ }
422
+ }
423
+ export async function ensureSandboxReady(params) {
424
+ const deps = params.deps;
425
+ const startFn = deps?.start ?? startSandboxContainer;
426
+ const warnings = [];
427
+ let failure = null;
428
+ try {
429
+ if (!params.row.running) {
430
+ startFn(params.engine, params.row.name);
431
+ const initial = assess({
432
+ config: params.config,
433
+ engine: params.engine,
434
+ branch: params.branch,
435
+ container: params.row.name,
436
+ deps
437
+ });
438
+ if (initial.findings.some((finding) => finding.repairKind === 'hard-failure')) {
439
+ throw new Error(describeFindings(initial.findings.filter((finding) => finding.repairKind === 'hard-failure')));
440
+ }
441
+ const tools = resolveTools(params.config);
442
+ prepareTmpfsMounts({
443
+ engine: params.engine,
444
+ container: params.row.name,
445
+ mountPaths: tools.filter((tool) => tool.tmpfs).map((tool) => tool.containerMount),
446
+ deps
447
+ });
448
+ hydrateTmpfsSeedEntries({
449
+ engine: params.engine,
450
+ container: params.row.name,
451
+ entries: mountedSeeds(initial.snapshot),
452
+ replace: true,
453
+ deps
454
+ });
455
+ let final = assess({
456
+ config: params.config,
457
+ engine: params.engine,
458
+ branch: params.branch,
459
+ container: params.row.name,
460
+ deps
461
+ });
462
+ if (!final.findings.some((finding) => finding.repairKind === 'hard-failure')) {
463
+ repairFindings({
464
+ engine: params.engine,
465
+ container: params.row.name,
466
+ findings: final.findings,
467
+ deps
468
+ });
469
+ final = assess({
470
+ config: params.config,
471
+ engine: params.engine,
472
+ branch: params.branch,
473
+ container: params.row.name,
474
+ deps
475
+ });
476
+ }
477
+ if (final.findings.length > 0) {
478
+ throw new Error(describeFindings(final.findings));
479
+ }
480
+ return { container: params.row.name, path: 'recovered', warnings };
481
+ }
482
+ const initial = assess({
483
+ config: params.config,
484
+ engine: params.engine,
485
+ branch: params.branch,
486
+ container: params.row.name,
487
+ deps
488
+ });
489
+ if (initial.findings.length === 0) {
490
+ return { container: params.row.name, path: 'healthy', warnings };
491
+ }
492
+ if (initial.findings.some((finding) => finding.repairKind === 'hard-failure')) {
493
+ throw new Error(describeFindings(initial.findings));
494
+ }
495
+ let current = initial;
496
+ const permissionFindings = current.findings.filter((finding) => finding.repairKind === 'permissions');
497
+ if (permissionFindings.length > 0) {
498
+ repairFindings({
499
+ engine: params.engine,
500
+ container: params.row.name,
501
+ findings: permissionFindings,
502
+ deps
503
+ });
504
+ current = assess({
505
+ config: params.config,
506
+ engine: params.engine,
507
+ branch: params.branch,
508
+ container: params.row.name,
509
+ deps
510
+ });
511
+ if (current.findings.some((finding) => finding.repairKind === 'hard-failure'
512
+ || finding.repairKind === 'permissions')) {
513
+ throw new Error(describeFindings(current.findings));
514
+ }
515
+ }
516
+ repairFindings({
517
+ engine: params.engine,
518
+ container: params.row.name,
519
+ findings: current.findings,
520
+ deps
521
+ });
522
+ const final = assess({
523
+ config: params.config,
524
+ engine: params.engine,
525
+ branch: params.branch,
526
+ container: params.row.name,
527
+ deps
528
+ });
529
+ if (final.findings.length > 0) {
530
+ throw new Error(describeFindings(final.findings));
531
+ }
532
+ return { container: params.row.name, path: 'recovered', warnings };
533
+ }
534
+ catch (error) {
535
+ failure = error instanceof Error ? error : new Error(String(error));
536
+ }
537
+ const dataBoundary = 'The existing container writable layer, ordinary /tmp data, processes, tmux sessions, and RAM state may be lost by replacement; worktree and host-managed sandbox data are preserved.';
538
+ if (!params.allowRecreate || !params.recreate) {
539
+ throw new Error(`Sandbox recovery failed: ${failure.message} ${dataBoundary} Re-run with --recreate to authorize container-only replacement.`);
540
+ }
541
+ const warning = `Sandbox recovery failed in place. Replacing only the container. ${dataBoundary}`;
542
+ warnings.push(warning);
543
+ (params.writeWarning ?? ((message) => process.stderr.write(`${message}\n`)))(warning);
544
+ await params.recreate(params.branch);
545
+ const rows = (deps?.fetchRows ?? fetchSandboxRows)(params.engine, sandboxLabel(params.config), sandboxBranchLabel(params.config));
546
+ const replacement = selectSandboxContainer([...rows.running, ...rows.nonRunning], containerNameCandidates(params.config, params.branch));
547
+ if (!replacement?.running) {
548
+ throw new Error('Replacement sandbox container was not found in a running state.');
549
+ }
550
+ const final = assess({
551
+ config: params.config,
552
+ engine: params.engine,
553
+ branch: params.branch,
554
+ container: replacement.name,
555
+ deps
556
+ });
557
+ if (final.findings.length > 0) {
558
+ throw new Error(`Replacement sandbox readiness check failed: ${describeFindings(final.findings)}`);
559
+ }
560
+ return { container: replacement.name, path: 'recreated', warnings };
561
+ }
562
+ //# sourceMappingURL=recovery.js.map
@@ -1,8 +1,9 @@
1
1
  import { spawnSync } from 'node:child_process';
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
+ import { isRemovedHashShortIdInput } from '../task/short-id.js';
4
5
  const TASK_ID_RE = /^TASK-\d{8}-\d{6}$/;
5
- const SHORT_ID_RE = /^#?\d+$/;
6
+ const SHORT_ID_RE = /^\d+$/;
6
7
  const WORKSPACE_DIRS = ['active', 'completed', 'blocked', 'archive'];
7
8
  function resolveShortIdStrict(arg, repoRoot) {
8
9
  const scriptPath = path.join(repoRoot, '.agents', 'scripts', 'task-short-id.js');
@@ -39,6 +40,9 @@ function resolveBranchFromTaskContent(content, taskId) {
39
40
  throw new Error(`Task ${taskId} has no branch field in task.md`);
40
41
  }
41
42
  export function resolveTaskBranch(arg, repoRoot) {
43
+ if (isRemovedHashShortIdInput(arg)) {
44
+ throw new Error(`Invalid task short id '${arg}': task short ids must use bare digits`);
45
+ }
42
46
  if (SHORT_ID_RE.test(arg)) {
43
47
  const taskId = resolveShortIdStrict(arg, repoRoot);
44
48
  const content = readTaskContent(repoRoot, taskId);
@@ -1,5 +1,24 @@
1
+ import path from 'node:path';
1
2
  import { safeNameCandidates, sanitizeBranchName } from './constants.js';
2
3
  import { hostJoin } from './engines/wsl2-paths.js';
4
+ export function tmpfsSeedStagingPath(toolId, index) {
5
+ return `/run/agent-infra/tmpfs-seeds/${toolId}/${index}`;
6
+ }
7
+ export function tmpfsSeedTargetPath(containerMount, entry) {
8
+ const normalized = path.posix.normalize(entry);
9
+ if (path.posix.isAbsolute(entry) || normalized === '..' || normalized.startsWith('../')) {
10
+ throw new Error(`tmpfs seed entry must stay within ${containerMount}: ${entry}`);
11
+ }
12
+ return path.posix.join(containerMount, normalized);
13
+ }
14
+ export function declaredTmpfsSeedEntries(tools) {
15
+ return tools.flatMap((tool) => (tool.tmpfs?.seed ?? []).map((entry, index) => ({
16
+ toolId: tool.id,
17
+ containerMount: tool.containerMount,
18
+ stagingPath: tmpfsSeedStagingPath(tool.id, index),
19
+ targetPath: tmpfsSeedTargetPath(tool.containerMount, entry)
20
+ })));
21
+ }
3
22
  const TOOL_ID_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
4
23
  function createBuiltinTools(home, project) {
5
24
  return {
@@ -20,16 +20,16 @@ export function commandHelp() {
20
20
  '/sandbox ls',
21
21
  '/sandbox show {ref}',
22
22
  '/sandbox vm status',
23
- '/task decisions {ref}',
24
- '/task log {ref}',
23
+ '/task decisions [--task {ref}] [--item {selector}]',
24
+ '/task log [--task {ref}]',
25
25
  '/task ls',
26
- '/task show {ref}',
27
- '/task status {ref}',
26
+ '/task show [--task {ref}]',
27
+ '/task status [--task {ref}]',
28
28
  'Write:',
29
29
  '/sandbox create {ref}',
30
30
  '/sandbox start {ref}',
31
31
  'Exec:',
32
- '/decide {task-ref} {HD-id} {decision}',
32
+ '/decide [--task {ref}] --item {ordinal|ledger-id} [--needs-implementation true|false] {decision}',
33
33
  '/run create-task {description}',
34
34
  '/run {skill} {task-ref}'
35
35
  ].join('\n');