@fitlab-ai/agent-infra 0.9.1 → 0.9.3

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 (476) hide show
  1. package/README.md +24 -11
  2. package/README.zh-CN.md +24 -11
  3. package/bin/cli.ts +12 -0
  4. package/dist/bin/cli.js +14 -0
  5. package/dist/bin/internal-cli.js +30 -0
  6. package/dist/lib/agent-client.js +163 -0
  7. package/dist/lib/agent-clients/adapter.js +337 -0
  8. package/dist/lib/agent-clients/adapters/antigravity-cli.js +64 -0
  9. package/dist/lib/agent-clients/adapters/claude-code.js +71 -0
  10. package/dist/lib/agent-clients/adapters/codex-sandbox.js +210 -0
  11. package/dist/lib/agent-clients/adapters/codex.js +63 -0
  12. package/dist/lib/agent-clients/adapters/index.js +20 -0
  13. package/dist/lib/agent-clients/adapters/opencode.js +73 -0
  14. package/dist/lib/agent-clients/config.js +215 -0
  15. package/dist/lib/agent-clients/custom-tuis.js +99 -0
  16. package/dist/lib/agent-clients/invocation.js +9 -0
  17. package/dist/lib/agent-clients/next-steps.js +47 -0
  18. package/dist/lib/agent-clients/project-assets.js +45 -0
  19. package/dist/lib/agent-clients/reconcile.js +236 -0
  20. package/dist/lib/agent-clients/registry.js +78 -0
  21. package/dist/lib/agent-clients/schema.js +75 -0
  22. package/dist/lib/agent-clients/tokens.js +49 -0
  23. package/dist/lib/agent-clients/types.js +29 -0
  24. package/dist/lib/builtin-tuis.js +9 -14
  25. package/dist/lib/defaults.json +85 -73
  26. package/dist/lib/git/review-snapshot.js +25 -10
  27. package/dist/lib/git/reviewed-commit-equivalence.js +110 -0
  28. package/dist/lib/git/workflow.js +54 -1
  29. package/dist/lib/init.js +47 -91
  30. package/dist/lib/internal/agent-client.js +174 -0
  31. package/dist/lib/internal/git-workflow.js +7 -2
  32. package/dist/lib/internal/platform-checks.js +3 -3
  33. package/dist/lib/internal/platform-comment.js +29 -2
  34. package/dist/lib/internal/platform-issue.js +7 -0
  35. package/dist/lib/internal/platform-pr-review.js +132 -0
  36. package/dist/lib/internal/platform-pr.js +20 -2
  37. package/dist/lib/internal/platform-release-notes.js +52 -16
  38. package/dist/lib/internal/pr-review-grade.js +140 -0
  39. package/dist/lib/internal/release-workflow.js +82 -20
  40. package/dist/lib/internal/task-activity.js +73 -0
  41. package/dist/lib/internal/task-event.js +17 -1
  42. package/dist/lib/internal/task-lifecycle.js +7 -0
  43. package/dist/lib/internal/task-orchestration.js +196 -0
  44. package/dist/lib/internal/task-review.js +70 -0
  45. package/dist/lib/merge.js +2 -1
  46. package/dist/lib/platform/adapters.js +45 -1
  47. package/dist/lib/platform/change-request-git-evidence.js +113 -0
  48. package/dist/lib/platform/completion-backfill.js +122 -0
  49. package/dist/lib/platform/issue-comments.js +3 -2
  50. package/dist/lib/platform/merged-pr-equivalence.js +156 -16
  51. package/dist/lib/platform/pr-checks.js +101 -50
  52. package/dist/lib/platform/pr-review.js +166 -0
  53. package/dist/lib/platform/pull-requests.js +432 -7
  54. package/dist/lib/platform/release-notes.js +85 -3
  55. package/dist/lib/platform/releases.js +1 -1
  56. package/dist/lib/platform/verification-required.js +8 -10
  57. package/dist/lib/pr-review/evidence-grading.js +229 -0
  58. package/dist/lib/prompt.js +15 -3
  59. package/dist/lib/release/channels.js +4 -1
  60. package/dist/lib/release/workflow.js +4 -2
  61. package/dist/lib/remove-dir.js +25 -0
  62. package/dist/lib/run/tui.js +11 -7
  63. package/dist/lib/sandbox/agent-client-reconciler.js +234 -0
  64. package/dist/lib/sandbox/clipboard/linux.js +2 -1
  65. package/dist/lib/sandbox/commands/create.js +76 -200
  66. package/dist/lib/sandbox/commands/enter.js +17 -1
  67. package/dist/lib/sandbox/commands/prune.js +2 -2
  68. package/dist/lib/sandbox/commands/rm.js +3 -2
  69. package/dist/lib/sandbox/commands/show.js +1 -1
  70. package/dist/lib/sandbox/config.js +21 -4
  71. package/dist/lib/sandbox/constants.js +3 -0
  72. package/dist/lib/sandbox/dockerfile.js +2 -1
  73. package/dist/lib/sandbox/managed-fs.js +10 -5
  74. package/dist/lib/sandbox/recovery.js +52 -36
  75. package/dist/lib/sandbox/shell.js +1 -1
  76. package/dist/lib/sandbox/tool-types.js +8 -0
  77. package/dist/lib/sandbox/tools.js +2 -126
  78. package/dist/lib/task/activity-intent.js +101 -0
  79. package/dist/lib/task/artifact-lifecycle.js +3 -50
  80. package/dist/lib/task/commands/decisions.js +50 -20
  81. package/dist/lib/task/commands/log.js +15 -14
  82. package/dist/lib/task/delegation-receipts.js +128 -0
  83. package/dist/lib/task/events.js +146 -8
  84. package/dist/lib/task/finalization-artifacts.js +35 -0
  85. package/dist/lib/task/lifecycle-execution.js +46 -0
  86. package/dist/lib/task/orchestration.js +784 -0
  87. package/dist/lib/task/review-artifacts.js +143 -59
  88. package/dist/lib/task/review-finalization.js +186 -0
  89. package/dist/lib/task/review-fingerprint.js +4 -0
  90. package/dist/lib/task/task-execution-lock.js +231 -0
  91. package/dist/lib/task/verification-checks.js +2 -1
  92. package/dist/lib/task/verification-engine.js +372 -28
  93. package/dist/lib/task/verification-review.js +1 -1
  94. package/dist/lib/task/verification.js +5 -2
  95. package/dist/lib/task/workspace-snapshot.js +46 -0
  96. package/dist/lib/update.js +42 -161
  97. package/lib/agent-client.ts +214 -0
  98. package/lib/agent-clients/adapter.ts +534 -0
  99. package/lib/agent-clients/adapters/antigravity-cli.ts +65 -0
  100. package/lib/agent-clients/adapters/claude-code.ts +79 -0
  101. package/lib/agent-clients/adapters/codex-sandbox.ts +245 -0
  102. package/lib/agent-clients/adapters/codex.ts +67 -0
  103. package/lib/agent-clients/adapters/index.ts +27 -0
  104. package/lib/agent-clients/adapters/opencode.ts +75 -0
  105. package/lib/agent-clients/config.ts +323 -0
  106. package/lib/agent-clients/custom-tuis.ts +149 -0
  107. package/lib/agent-clients/invocation.ts +19 -0
  108. package/lib/agent-clients/next-steps.ts +85 -0
  109. package/lib/agent-clients/project-assets.ts +96 -0
  110. package/lib/agent-clients/reconcile.ts +325 -0
  111. package/lib/agent-clients/registry.ts +154 -0
  112. package/lib/agent-clients/schema.ts +80 -0
  113. package/lib/agent-clients/tokens.ts +53 -0
  114. package/lib/agent-clients/types.ts +92 -0
  115. package/lib/benchmark/schemas/v1.0.0/case-manifest.schema.json +120 -0
  116. package/lib/benchmark/schemas/v1.0.0/common.schema.json +109 -0
  117. package/lib/benchmark/schemas/v1.0.0/grader-result.schema.json +160 -0
  118. package/lib/benchmark/schemas/v1.0.0/run-manifest.schema.json +122 -0
  119. package/lib/benchmark/schemas/v1.0.0/subject.schema.json +227 -0
  120. package/lib/builtin-tuis.ts +16 -15
  121. package/lib/defaults.json +24 -12
  122. package/lib/git/review-snapshot.ts +39 -9
  123. package/lib/git/reviewed-commit-equivalence.ts +135 -0
  124. package/lib/git/workflow.ts +66 -2
  125. package/lib/init.ts +53 -121
  126. package/lib/internal/agent-client.ts +186 -0
  127. package/lib/internal/git-workflow.ts +6 -2
  128. package/lib/internal/platform-checks.ts +4 -4
  129. package/lib/internal/platform-comment.ts +17 -2
  130. package/lib/internal/platform-issue.ts +4 -0
  131. package/lib/internal/platform-pr-review.ts +104 -0
  132. package/lib/internal/platform-pr.ts +14 -1
  133. package/lib/internal/platform-release-notes.ts +59 -16
  134. package/lib/internal/pr-review-grade.ts +130 -0
  135. package/lib/internal/release-workflow.ts +79 -20
  136. package/lib/internal/task-activity.ts +55 -0
  137. package/lib/internal/task-event.ts +9 -1
  138. package/lib/internal/task-lifecycle.ts +4 -0
  139. package/lib/internal/task-orchestration.ts +171 -0
  140. package/lib/internal/task-review.ts +70 -0
  141. package/lib/merge.ts +2 -1
  142. package/lib/platform/adapters.ts +169 -3
  143. package/lib/platform/change-request-git-evidence.ts +159 -0
  144. package/lib/platform/completion-backfill.ts +134 -0
  145. package/lib/platform/issue-comments.ts +3 -2
  146. package/lib/platform/merged-pr-equivalence.ts +178 -19
  147. package/lib/platform/pr-checks.ts +121 -66
  148. package/lib/platform/pr-review.ts +201 -0
  149. package/lib/platform/pull-requests.ts +529 -27
  150. package/lib/platform/release-notes.ts +100 -4
  151. package/lib/platform/releases.ts +1 -1
  152. package/lib/platform/verification-required.ts +12 -10
  153. package/lib/pr-review/evidence-grading.ts +318 -0
  154. package/lib/prompt.ts +16 -3
  155. package/lib/release/channels.ts +4 -1
  156. package/lib/release/workflow.ts +4 -3
  157. package/lib/remove-dir.ts +28 -0
  158. package/lib/run/tui.ts +12 -5
  159. package/lib/sandbox/agent-client-reconciler.ts +378 -0
  160. package/lib/sandbox/clipboard/linux.ts +2 -1
  161. package/lib/sandbox/commands/create.ts +111 -212
  162. package/lib/sandbox/commands/enter.ts +23 -1
  163. package/lib/sandbox/commands/prune.ts +2 -2
  164. package/lib/sandbox/commands/rm.ts +3 -2
  165. package/lib/sandbox/commands/show.ts +1 -1
  166. package/lib/sandbox/config.ts +31 -4
  167. package/lib/sandbox/constants.ts +6 -0
  168. package/lib/sandbox/dockerfile.ts +2 -1
  169. package/lib/sandbox/managed-fs.ts +18 -5
  170. package/lib/sandbox/recovery.ts +98 -67
  171. package/lib/sandbox/shell.ts +1 -1
  172. package/lib/sandbox/tool-types.ts +143 -0
  173. package/lib/sandbox/tools.ts +5 -157
  174. package/lib/server/server.schema.json +2 -2
  175. package/lib/task/activity-intent.ts +128 -0
  176. package/lib/task/artifact-lifecycle.ts +3 -39
  177. package/lib/task/commands/decisions.ts +53 -20
  178. package/lib/task/commands/log.ts +15 -14
  179. package/lib/task/delegation-receipts.ts +199 -0
  180. package/lib/task/events.ts +164 -11
  181. package/lib/task/finalization-artifacts.ts +58 -0
  182. package/lib/task/lifecycle-execution.ts +106 -0
  183. package/lib/task/orchestration.ts +1022 -0
  184. package/lib/task/review-artifacts.ts +201 -69
  185. package/lib/task/review-finalization.ts +306 -0
  186. package/lib/task/review-fingerprint.ts +5 -0
  187. package/lib/task/task-execution-lock.ts +296 -0
  188. package/lib/task/verification-checks.ts +2 -1
  189. package/lib/task/verification-engine.ts +424 -28
  190. package/lib/task/verification-review.ts +1 -0
  191. package/lib/task/verification.ts +8 -3
  192. package/lib/task/workspace-snapshot.ts +57 -0
  193. package/lib/update.ts +48 -184
  194. package/package.json +4 -4
  195. package/templates/.agents/QUICKSTART.en.md +25 -8
  196. package/templates/.agents/QUICKSTART.zh-CN.md +25 -8
  197. package/templates/.agents/README.en.md +29 -25
  198. package/templates/.agents/README.zh-CN.md +29 -25
  199. package/templates/.agents/hooks/lifecycle-delegation.js +75 -0
  200. package/templates/.agents/rules/README.en.md +2 -0
  201. package/templates/.agents/rules/README.zh-CN.md +2 -0
  202. package/templates/.agents/rules/commit-and-pr.en.md +1 -0
  203. package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -0
  204. package/templates/.agents/rules/create-issue.github.en.md +4 -2
  205. package/templates/.agents/rules/create-issue.github.zh-CN.md +4 -2
  206. package/templates/.agents/rules/human-decision-context.en.md +14 -12
  207. package/templates/.agents/rules/human-decision-context.zh-CN.md +14 -12
  208. package/templates/.agents/rules/issue-fields.github.en.md +3 -1
  209. package/templates/.agents/rules/issue-fields.github.zh-CN.md +3 -1
  210. package/templates/.agents/rules/issue-pr-commands.en.md +5 -3
  211. package/templates/.agents/rules/issue-pr-commands.github.en.md +5 -3
  212. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +5 -3
  213. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +5 -3
  214. package/templates/.agents/rules/issue-sync.github.en.md +7 -3
  215. package/templates/.agents/rules/issue-sync.github.zh-CN.md +8 -4
  216. package/templates/.agents/rules/lifecycle-orchestration.en.md +24 -0
  217. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +24 -0
  218. package/templates/.agents/rules/milestone-inference.github.en.md +4 -2
  219. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +4 -2
  220. package/templates/.agents/rules/next-step-output.en.md +18 -0
  221. package/templates/.agents/rules/next-step-output.zh-CN.md +18 -0
  222. package/templates/.agents/rules/no-mid-flow-questions.en.md +19 -0
  223. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +19 -0
  224. package/templates/.agents/rules/pr-checks-commands.en.md +3 -3
  225. package/templates/.agents/rules/pr-checks-commands.github.en.md +2 -2
  226. package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +2 -2
  227. package/templates/.agents/rules/pr-checks-commands.zh-CN.md +3 -3
  228. package/templates/.agents/rules/pr-sync.en.md +3 -1
  229. package/templates/.agents/rules/pr-sync.github.en.md +11 -1
  230. package/templates/.agents/rules/pr-sync.github.zh-CN.md +11 -1
  231. package/templates/.agents/rules/pr-sync.zh-CN.md +3 -1
  232. package/templates/.agents/rules/release-commands.en.md +1 -1
  233. package/templates/.agents/rules/release-commands.github.en.md +21 -5
  234. package/templates/.agents/rules/release-commands.github.zh-CN.md +21 -5
  235. package/templates/.agents/rules/release-commands.zh-CN.md +1 -1
  236. package/templates/.agents/rules/review-handshake.en.md +4 -4
  237. package/templates/.agents/rules/review-handshake.zh-CN.md +4 -4
  238. package/templates/.agents/rules/review-method.en.md +113 -0
  239. package/templates/.agents/rules/review-method.zh-CN.md +98 -0
  240. package/templates/.agents/rules/task-management.en.md +11 -0
  241. package/templates/.agents/rules/task-management.zh-CN.md +11 -0
  242. package/templates/.agents/skills/analyze-task/SKILL.en.md +15 -12
  243. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +15 -12
  244. package/templates/.agents/skills/block-task/SKILL.en.md +11 -9
  245. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +11 -9
  246. package/templates/.agents/skills/cancel-task/SKILL.en.md +10 -8
  247. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +11 -9
  248. package/templates/.agents/skills/check-task/SKILL.en.md +16 -16
  249. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -16
  250. package/templates/.agents/skills/close-codescan/SKILL.en.md +7 -5
  251. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +7 -5
  252. package/templates/.agents/skills/close-dependabot/SKILL.en.md +7 -5
  253. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +7 -5
  254. package/templates/.agents/skills/code-task/SKILL.en.md +10 -7
  255. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +13 -10
  256. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +14 -16
  257. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +14 -16
  258. package/templates/.agents/skills/code-task/reference/output-template.en.md +3 -3
  259. package/templates/.agents/skills/code-task/reference/output-template.zh-CN.md +3 -3
  260. package/templates/.agents/skills/commit/SKILL.en.md +13 -1
  261. package/templates/.agents/skills/commit/SKILL.zh-CN.md +13 -1
  262. package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -1
  263. package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -1
  264. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +1 -1
  265. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +1 -1
  266. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
  267. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
  268. package/templates/.agents/skills/commit/reference/task-status-update.en.md +24 -28
  269. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +24 -28
  270. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +6 -4
  271. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +6 -4
  272. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +1 -1
  273. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +1 -1
  274. package/templates/.agents/skills/complete-task/SKILL.en.md +23 -8
  275. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +23 -8
  276. package/templates/.agents/skills/complete-task/config/verify.en.json +1 -0
  277. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +1 -0
  278. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +17 -0
  279. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +17 -0
  280. package/templates/.agents/skills/create-pr/SKILL.en.md +13 -11
  281. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +13 -11
  282. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +1 -1
  283. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +1 -1
  284. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +3 -3
  285. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +3 -3
  286. package/templates/.agents/skills/create-release-note/SKILL.en.md +17 -16
  287. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +17 -16
  288. package/templates/.agents/skills/create-task/SKILL.en.md +16 -14
  289. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +16 -14
  290. package/templates/.agents/skills/import-codescan/SKILL.en.md +5 -5
  291. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +5 -5
  292. package/templates/.agents/skills/import-dependabot/SKILL.en.md +5 -5
  293. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +5 -5
  294. package/templates/.agents/skills/import-issue/SKILL.en.md +10 -8
  295. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +10 -8
  296. package/templates/.agents/skills/init-labels/SKILL.en.md +4 -4
  297. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +4 -4
  298. package/templates/.agents/skills/init-milestones/SKILL.en.md +4 -4
  299. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +4 -4
  300. package/templates/.agents/skills/plan-task/SKILL.en.md +13 -10
  301. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +13 -10
  302. package/templates/.agents/skills/post-release/SKILL.en.md +2 -0
  303. package/templates/.agents/skills/post-release/SKILL.zh-CN.md +2 -0
  304. package/templates/.agents/skills/refine-title/SKILL.en.md +1 -1
  305. package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +1 -1
  306. package/templates/.agents/skills/release/SKILL.en.md +16 -10
  307. package/templates/.agents/skills/release/SKILL.zh-CN.md +16 -10
  308. package/templates/.agents/skills/restore-task/SKILL.en.md +4 -1
  309. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +4 -1
  310. package/templates/.agents/skills/review-analysis/SKILL.en.md +18 -4
  311. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +19 -5
  312. package/templates/.agents/skills/review-analysis/config/verify.en.json +6 -0
  313. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +6 -0
  314. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +13 -15
  315. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +13 -15
  316. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +51 -5
  317. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +52 -6
  318. package/templates/.agents/skills/review-analysis/reference/review-criteria.en.md +25 -22
  319. package/templates/.agents/skills/review-analysis/reference/review-criteria.zh-CN.md +25 -22
  320. package/templates/.agents/skills/review-code/SKILL.en.md +35 -12
  321. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +35 -12
  322. package/templates/.agents/skills/review-code/config/verify.en.json +7 -0
  323. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +7 -0
  324. package/templates/.agents/skills/review-code/reference/concurrency-risks.en.md +25 -0
  325. package/templates/.agents/skills/review-code/reference/concurrency-risks.zh-CN.md +25 -0
  326. package/templates/.agents/skills/review-code/reference/cross-platform-risks.en.md +27 -0
  327. package/templates/.agents/skills/review-code/reference/cross-platform-risks.zh-CN.md +27 -0
  328. package/templates/.agents/skills/review-code/reference/documentation-antipatterns.en.md +13 -0
  329. package/templates/.agents/skills/review-code/reference/documentation-antipatterns.zh-CN.md +13 -0
  330. package/templates/.agents/skills/review-code/reference/migration-risks.en.md +25 -0
  331. package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +25 -0
  332. package/templates/.agents/skills/review-code/reference/output-templates.en.md +22 -24
  333. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +22 -24
  334. package/templates/.agents/skills/review-code/reference/report-template.en.md +54 -7
  335. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +54 -7
  336. package/templates/.agents/skills/review-code/reference/review-criteria.en.md +29 -24
  337. package/templates/.agents/skills/review-code/reference/review-criteria.zh-CN.md +29 -24
  338. package/templates/.agents/skills/review-code/reference/security-risks.en.md +25 -0
  339. package/templates/.agents/skills/review-code/reference/security-risks.zh-CN.md +25 -0
  340. package/templates/.agents/skills/review-plan/SKILL.en.md +18 -4
  341. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +19 -5
  342. package/templates/.agents/skills/review-plan/config/verify.en.json +6 -0
  343. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +6 -0
  344. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +13 -15
  345. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +13 -15
  346. package/templates/.agents/skills/review-plan/reference/report-template.en.md +61 -5
  347. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +61 -5
  348. package/templates/.agents/skills/review-plan/reference/review-criteria.en.md +21 -24
  349. package/templates/.agents/skills/review-plan/reference/review-criteria.zh-CN.md +21 -24
  350. package/templates/.agents/skills/review-pr/SKILL.en.md +158 -0
  351. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +158 -0
  352. package/templates/.agents/skills/review-pr/config/verify.en.json +37 -0
  353. package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +37 -0
  354. package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +65 -0
  355. package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +65 -0
  356. package/templates/.agents/skills/review-pr/reference/output-guidance.en.md +18 -0
  357. package/templates/.agents/skills/review-pr/reference/output-guidance.zh-CN.md +18 -0
  358. package/templates/.agents/skills/review-pr/reference/report-template.en.md +85 -0
  359. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +85 -0
  360. package/templates/.agents/skills/run-task/SKILL.en.md +22 -0
  361. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +22 -0
  362. package/templates/.agents/skills/run-task/config/verify.en.json +10 -0
  363. package/templates/.agents/skills/run-task/config/verify.zh-CN.json +10 -0
  364. package/templates/.agents/skills/run-task/reference/host-validation.en.md +20 -0
  365. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +20 -0
  366. package/templates/.agents/skills/test/SKILL.en.md +4 -4
  367. package/templates/.agents/skills/test/SKILL.zh-CN.md +4 -4
  368. package/templates/.agents/skills/test-integration/SKILL.en.md +4 -4
  369. package/templates/.agents/skills/test-integration/SKILL.zh-CN.md +4 -4
  370. package/templates/.agents/skills/update-agent-infra/SKILL.en.md +5 -5
  371. package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +5 -5
  372. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +664 -246
  373. package/templates/.agents/skills/upgrade-dependency/SKILL.en.md +4 -4
  374. package/templates/.agents/skills/upgrade-dependency/SKILL.zh-CN.md +4 -4
  375. package/templates/.agents/skills/watch-pr/SKILL.en.md +21 -21
  376. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +21 -21
  377. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +27 -6
  378. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +26 -5
  379. package/templates/.agents/templates/task.en.md +1 -1
  380. package/templates/.agents/templates/task.zh-CN.md +1 -1
  381. package/templates/.agents/workflows/bug-fix.en.yaml +3 -3
  382. package/templates/.agents/workflows/bug-fix.zh-CN.yaml +3 -3
  383. package/templates/.agents/workflows/code-review.en.yaml +1 -1
  384. package/templates/.agents/workflows/code-review.zh-CN.yaml +1 -1
  385. package/templates/.agents/workflows/feature-development.en.yaml +4 -4
  386. package/templates/.agents/workflows/feature-development.zh-CN.yaml +4 -4
  387. package/templates/.agents/workflows/refactoring.en.yaml +3 -3
  388. package/templates/.agents/workflows/refactoring.zh-CN.yaml +3 -3
  389. package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +6 -0
  390. package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +6 -0
  391. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +6 -0
  392. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +6 -0
  393. package/templates/.claude/commands/post-release.en.md +1 -0
  394. package/templates/.claude/commands/post-release.zh-CN.md +1 -0
  395. package/templates/.claude/commands/review-pr.en.md +8 -0
  396. package/templates/.claude/commands/review-pr.zh-CN.md +8 -0
  397. package/templates/.claude/commands/run-task.en.md +8 -0
  398. package/templates/.claude/commands/run-task.zh-CN.md +8 -0
  399. package/templates/.claude/settings.json +24 -0
  400. package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +3 -0
  401. package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +3 -0
  402. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +3 -0
  403. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +3 -0
  404. package/templates/.gemini/commands/_project_/review-pr.en.toml +10 -0
  405. package/templates/.gemini/commands/_project_/review-pr.zh-CN.toml +10 -0
  406. package/templates/.opencode/commands/post-release.en.md +2 -0
  407. package/templates/.opencode/commands/post-release.zh-CN.md +2 -0
  408. package/templates/.opencode/commands/review-pr.en.md +11 -0
  409. package/templates/.opencode/commands/review-pr.zh-CN.md +11 -0
  410. package/templates/.opencode/commands/run-task.en.md +11 -0
  411. package/templates/.opencode/commands/run-task.zh-CN.md +11 -0
  412. package/templates/.gemini/commands/_project_/analyze-task.en.toml +0 -10
  413. package/templates/.gemini/commands/_project_/analyze-task.zh-CN.toml +0 -10
  414. package/templates/.gemini/commands/_project_/archive-tasks.en.toml +0 -10
  415. package/templates/.gemini/commands/_project_/archive-tasks.zh-CN.toml +0 -10
  416. package/templates/.gemini/commands/_project_/block-task.en.toml +0 -10
  417. package/templates/.gemini/commands/_project_/block-task.zh-CN.toml +0 -10
  418. package/templates/.gemini/commands/_project_/cancel-task.en.toml +0 -10
  419. package/templates/.gemini/commands/_project_/cancel-task.zh-CN.toml +0 -10
  420. package/templates/.gemini/commands/_project_/check-task.en.toml +0 -10
  421. package/templates/.gemini/commands/_project_/check-task.zh-CN.toml +0 -10
  422. package/templates/.gemini/commands/_project_/close-codescan.en.toml +0 -8
  423. package/templates/.gemini/commands/_project_/close-codescan.zh-CN.toml +0 -8
  424. package/templates/.gemini/commands/_project_/close-dependabot.en.toml +0 -8
  425. package/templates/.gemini/commands/_project_/close-dependabot.zh-CN.toml +0 -8
  426. package/templates/.gemini/commands/_project_/code-task.en.toml +0 -10
  427. package/templates/.gemini/commands/_project_/code-task.zh-CN.toml +0 -10
  428. package/templates/.gemini/commands/_project_/commit.en.toml +0 -10
  429. package/templates/.gemini/commands/_project_/commit.zh-CN.toml +0 -10
  430. package/templates/.gemini/commands/_project_/complete-manual-validation.en.toml +0 -10
  431. package/templates/.gemini/commands/_project_/complete-manual-validation.zh-CN.toml +0 -10
  432. package/templates/.gemini/commands/_project_/complete-task.en.toml +0 -10
  433. package/templates/.gemini/commands/_project_/complete-task.zh-CN.toml +0 -10
  434. package/templates/.gemini/commands/_project_/create-pr.en.toml +0 -10
  435. package/templates/.gemini/commands/_project_/create-pr.zh-CN.toml +0 -10
  436. package/templates/.gemini/commands/_project_/create-release-note.en.toml +0 -8
  437. package/templates/.gemini/commands/_project_/create-release-note.zh-CN.toml +0 -8
  438. package/templates/.gemini/commands/_project_/create-task.en.toml +0 -8
  439. package/templates/.gemini/commands/_project_/create-task.zh-CN.toml +0 -8
  440. package/templates/.gemini/commands/_project_/import-codescan.en.toml +0 -8
  441. package/templates/.gemini/commands/_project_/import-codescan.zh-CN.toml +0 -8
  442. package/templates/.gemini/commands/_project_/import-dependabot.en.toml +0 -8
  443. package/templates/.gemini/commands/_project_/import-dependabot.zh-CN.toml +0 -8
  444. package/templates/.gemini/commands/_project_/import-issue.en.toml +0 -8
  445. package/templates/.gemini/commands/_project_/import-issue.zh-CN.toml +0 -8
  446. package/templates/.gemini/commands/_project_/init-labels.en.toml +0 -8
  447. package/templates/.gemini/commands/_project_/init-labels.zh-CN.toml +0 -8
  448. package/templates/.gemini/commands/_project_/init-milestones.en.toml +0 -10
  449. package/templates/.gemini/commands/_project_/init-milestones.zh-CN.toml +0 -10
  450. package/templates/.gemini/commands/_project_/plan-task.en.toml +0 -10
  451. package/templates/.gemini/commands/_project_/plan-task.zh-CN.toml +0 -10
  452. package/templates/.gemini/commands/_project_/post-release.en.toml +0 -6
  453. package/templates/.gemini/commands/_project_/post-release.zh-CN.toml +0 -6
  454. package/templates/.gemini/commands/_project_/refine-title.en.toml +0 -8
  455. package/templates/.gemini/commands/_project_/refine-title.zh-CN.toml +0 -8
  456. package/templates/.gemini/commands/_project_/release.en.toml +0 -8
  457. package/templates/.gemini/commands/_project_/release.zh-CN.toml +0 -8
  458. package/templates/.gemini/commands/_project_/restore-task.en.toml +0 -8
  459. package/templates/.gemini/commands/_project_/restore-task.zh-CN.toml +0 -8
  460. package/templates/.gemini/commands/_project_/review-analysis.en.toml +0 -10
  461. package/templates/.gemini/commands/_project_/review-analysis.zh-CN.toml +0 -10
  462. package/templates/.gemini/commands/_project_/review-code.en.toml +0 -10
  463. package/templates/.gemini/commands/_project_/review-code.zh-CN.toml +0 -10
  464. package/templates/.gemini/commands/_project_/review-plan.en.toml +0 -10
  465. package/templates/.gemini/commands/_project_/review-plan.zh-CN.toml +0 -10
  466. package/templates/.gemini/commands/_project_/test-integration.en.toml +0 -6
  467. package/templates/.gemini/commands/_project_/test-integration.zh-CN.toml +0 -6
  468. package/templates/.gemini/commands/_project_/test.en.toml +0 -6
  469. package/templates/.gemini/commands/_project_/test.zh-CN.toml +0 -6
  470. package/templates/.gemini/commands/_project_/update-agent-infra.en.toml +0 -6
  471. package/templates/.gemini/commands/_project_/update-agent-infra.zh-CN.toml +0 -6
  472. package/templates/.gemini/commands/_project_/upgrade-dependency.en.toml +0 -8
  473. package/templates/.gemini/commands/_project_/upgrade-dependency.zh-CN.toml +0 -8
  474. package/templates/.gemini/commands/_project_/watch-pr.en.toml +0 -10
  475. package/templates/.gemini/commands/_project_/watch-pr.zh-CN.toml +0 -10
  476. package/templates/.gemini/settings.json +0 -3
@@ -0,0 +1,323 @@
1
+ import {
2
+ AGENT_CLIENT_IDS,
3
+ isAgentClientId
4
+ } from './types.ts';
5
+ import type {
6
+ AgentClientConfig,
7
+ AgentClientId,
8
+ AgentClientsConfig,
9
+ AgentClientState,
10
+ OrchestrationModelPolicy
11
+ } from './types.ts';
12
+
13
+ type AgentClientConfigInput = Readonly<{
14
+ agentClients?: unknown;
15
+ tuis?: unknown;
16
+ sandbox?: unknown;
17
+ customTUIs?: unknown;
18
+ }>;
19
+
20
+ type AgentClientDiagnosticCode =
21
+ | 'INVALID_AGENT_CLIENTS'
22
+ | 'DUPLICATE_AGENT_CLIENT'
23
+ | 'MISSING_AGENT_CLIENT'
24
+ | 'UNKNOWN_AGENT_CLIENT'
25
+ | 'LEGACY_CONFLICT'
26
+ | 'LEGACY_VALUE_IGNORED';
27
+
28
+ type AgentClientDiagnostic = Readonly<{
29
+ code: AgentClientDiagnosticCode;
30
+ path: string;
31
+ }>;
32
+
33
+ type NormalizeAgentClientsResult = Readonly<{
34
+ source: 'canonical' | 'legacy';
35
+ state: AgentClientState;
36
+ canonical: AgentClientsConfig;
37
+ remainingSandboxTools: readonly string[] | undefined;
38
+ removeLegacyTuis: boolean;
39
+ changed: boolean;
40
+ diagnostics: readonly AgentClientDiagnostic[];
41
+ }>;
42
+
43
+ class AgentClientConfigError extends Error {
44
+ readonly code: AgentClientDiagnosticCode;
45
+ readonly path: string;
46
+ readonly diagnostics: readonly AgentClientDiagnostic[];
47
+
48
+ constructor(diagnostic: AgentClientDiagnostic) {
49
+ super(`${diagnostic.code} at ${diagnostic.path}`);
50
+ this.name = 'AgentClientConfigError';
51
+ this.code = diagnostic.code;
52
+ this.path = diagnostic.path;
53
+ this.diagnostics = [diagnostic];
54
+ }
55
+ }
56
+
57
+ function hasOwn(value: object, key: PropertyKey): boolean {
58
+ return Object.prototype.hasOwnProperty.call(value, key);
59
+ }
60
+
61
+ function isRecord(value: unknown): value is Record<string, unknown> {
62
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
63
+ }
64
+
65
+ function fail(code: AgentClientDiagnosticCode, path: string): never {
66
+ throw new AgentClientConfigError({ code, path });
67
+ }
68
+
69
+ function parseExactText(value: unknown, path: string): string {
70
+ if (typeof value !== 'string' || value.length === 0 || value.trim() !== value) {
71
+ fail('INVALID_AGENT_CLIENTS', path);
72
+ }
73
+ return value;
74
+ }
75
+
76
+ function parseOrchestrationPolicy(value: unknown, path: string): OrchestrationModelPolicy {
77
+ if (!isRecord(value)) fail('INVALID_AGENT_CLIENTS', path);
78
+ const keys = Object.keys(value);
79
+ if (
80
+ keys.length !== 2
81
+ || !hasOwn(value, 'executor')
82
+ || !hasOwn(value, 'reviewer')
83
+ ) {
84
+ fail('INVALID_AGENT_CLIENTS', path);
85
+ }
86
+ const parseRole = (candidate: unknown, rolePath: string) => {
87
+ if (
88
+ !isRecord(candidate)
89
+ || Object.keys(candidate).length !== 2
90
+ || !hasOwn(candidate, 'model')
91
+ || !hasOwn(candidate, 'reasoningEffort')
92
+ ) {
93
+ fail('INVALID_AGENT_CLIENTS', rolePath);
94
+ }
95
+ return Object.freeze({
96
+ model: parseExactText(candidate.model, `${rolePath}.model`),
97
+ reasoningEffort: parseExactText(candidate.reasoningEffort, `${rolePath}.reasoningEffort`)
98
+ });
99
+ };
100
+ const executor = parseRole(value.executor, `${path}.executor`);
101
+ const reviewer = parseRole(value.reviewer, `${path}.reviewer`);
102
+ return Object.freeze({ executor, reviewer });
103
+ }
104
+
105
+ function parseCanonical(value: unknown): AgentClientState {
106
+ if (!Array.isArray(value)) fail('INVALID_AGENT_CLIENTS', 'agentClients');
107
+
108
+ const entries = new Map<AgentClientId, Readonly<{
109
+ enabled: boolean;
110
+ installInSandbox: boolean;
111
+ orchestration?: OrchestrationModelPolicy;
112
+ }>>();
113
+
114
+ for (const [index, candidate] of value.entries()) {
115
+ const path = `agentClients[${index}]`;
116
+ if (!isRecord(candidate)) fail('INVALID_AGENT_CLIENTS', path);
117
+
118
+ const keys = Object.keys(candidate);
119
+ if (
120
+ (keys.length !== 3 && keys.length !== 4)
121
+ || !hasOwn(candidate, 'id')
122
+ || !hasOwn(candidate, 'enabled')
123
+ || !hasOwn(candidate, 'installInSandbox')
124
+ || (keys.length === 4 && !hasOwn(candidate, 'orchestration'))
125
+ ) {
126
+ fail('INVALID_AGENT_CLIENTS', path);
127
+ }
128
+ if (!isAgentClientId(candidate.id)) {
129
+ fail('UNKNOWN_AGENT_CLIENT', `${path}.id`);
130
+ }
131
+ if (entries.has(candidate.id)) {
132
+ fail('DUPLICATE_AGENT_CLIENT', `${path}.id`);
133
+ }
134
+ if (
135
+ typeof candidate.enabled !== 'boolean'
136
+ || typeof candidate.installInSandbox !== 'boolean'
137
+ ) {
138
+ fail('INVALID_AGENT_CLIENTS', path);
139
+ }
140
+ entries.set(candidate.id, {
141
+ enabled: candidate.enabled,
142
+ installInSandbox: candidate.installInSandbox,
143
+ ...(hasOwn(candidate, 'orchestration')
144
+ ? { orchestration: parseOrchestrationPolicy(candidate.orchestration, `${path}.orchestration`) }
145
+ : {})
146
+ });
147
+ }
148
+
149
+ for (const id of AGENT_CLIENT_IDS) {
150
+ if (!entries.has(id)) fail('MISSING_AGENT_CLIENT', 'agentClients');
151
+ }
152
+
153
+ return Object.fromEntries(
154
+ AGENT_CLIENT_IDS.map((id) => [id, entries.get(id)!])
155
+ ) as AgentClientState;
156
+ }
157
+
158
+ function serializeAgentClients(state: AgentClientState): AgentClientsConfig {
159
+ return AGENT_CLIENT_IDS.map((id): AgentClientConfig => ({
160
+ id,
161
+ enabled: state[id].enabled,
162
+ installInSandbox: state[id].installInSandbox,
163
+ ...(state[id].orchestration
164
+ ? { orchestration: structuredClone(state[id].orchestration) }
165
+ : {})
166
+ }));
167
+ }
168
+
169
+ function projectLegacyTuis(
170
+ value: unknown,
171
+ diagnostics: AgentClientDiagnostic[]
172
+ ): Readonly<Record<AgentClientId, boolean>> {
173
+ if (!Array.isArray(value)) {
174
+ return Object.fromEntries(
175
+ AGENT_CLIENT_IDS.map((id) => [id, true])
176
+ ) as Readonly<Record<AgentClientId, boolean>>;
177
+ }
178
+
179
+ const enabled = new Set<AgentClientId>();
180
+ for (const [index, candidate] of value.entries()) {
181
+ if (isAgentClientId(candidate)) {
182
+ enabled.add(candidate);
183
+ } else {
184
+ diagnostics.push({
185
+ code: 'LEGACY_VALUE_IGNORED',
186
+ path: `tuis[${index}]`
187
+ });
188
+ }
189
+ }
190
+ return Object.fromEntries(
191
+ AGENT_CLIENT_IDS.map((id) => [id, enabled.has(id)])
192
+ ) as Readonly<Record<AgentClientId, boolean>>;
193
+ }
194
+
195
+ type SandboxProjection = Readonly<{
196
+ installed: Readonly<Record<AgentClientId, boolean>>;
197
+ clientSignals: ReadonlySet<AgentClientId>;
198
+ remainingTools: readonly string[] | undefined;
199
+ }>;
200
+
201
+ function projectLegacySandbox(
202
+ value: unknown,
203
+ diagnostics: AgentClientDiagnostic[]
204
+ ): SandboxProjection {
205
+ if (!Array.isArray(value) || value.length === 0) {
206
+ return {
207
+ installed: Object.fromEntries(
208
+ AGENT_CLIENT_IDS.map((id) => [id, true])
209
+ ) as Readonly<Record<AgentClientId, boolean>>,
210
+ clientSignals: new Set<AgentClientId>(),
211
+ remainingTools: Array.isArray(value) ? [] : undefined
212
+ };
213
+ }
214
+
215
+ const installed = new Set<AgentClientId>();
216
+ const remainingTools: string[] = [];
217
+ for (const [index, candidate] of value.entries()) {
218
+ if (isAgentClientId(candidate)) {
219
+ installed.add(candidate);
220
+ } else if (typeof candidate === 'string') {
221
+ remainingTools.push(candidate);
222
+ } else {
223
+ diagnostics.push({
224
+ code: 'LEGACY_VALUE_IGNORED',
225
+ path: `sandbox.tools[${index}]`
226
+ });
227
+ }
228
+ }
229
+ return {
230
+ installed: Object.fromEntries(
231
+ AGENT_CLIENT_IDS.map((id) => [id, installed.has(id)])
232
+ ) as Readonly<Record<AgentClientId, boolean>>,
233
+ clientSignals: installed,
234
+ remainingTools
235
+ };
236
+ }
237
+
238
+ function stateFromLegacy(
239
+ enabled: Readonly<Record<AgentClientId, boolean>>,
240
+ installed: Readonly<Record<AgentClientId, boolean>>
241
+ ): AgentClientState {
242
+ return Object.fromEntries(
243
+ AGENT_CLIENT_IDS.map((id) => [
244
+ id,
245
+ {
246
+ enabled: enabled[id],
247
+ installInSandbox: installed[id]
248
+ }
249
+ ])
250
+ ) as AgentClientState;
251
+ }
252
+
253
+ function sameCanonicalOrder(value: unknown): boolean {
254
+ return Array.isArray(value)
255
+ && value.every((entry, index) => isRecord(entry) && entry.id === AGENT_CLIENT_IDS[index]);
256
+ }
257
+
258
+ function normalizeAgentClients(
259
+ input: AgentClientConfigInput
260
+ ): NormalizeAgentClientsResult {
261
+ const diagnostics: AgentClientDiagnostic[] = [];
262
+ const hasCanonical = hasOwn(input, 'agentClients');
263
+ const hasLegacyTuis = hasOwn(input, 'tuis');
264
+ const sandbox = isRecord(input.sandbox) ? input.sandbox : undefined;
265
+ const hasLegacySandboxTools = sandbox !== undefined && hasOwn(sandbox, 'tools');
266
+ const tuiProjection = projectLegacyTuis(input.tuis, diagnostics);
267
+ const sandboxProjection = projectLegacySandbox(sandbox?.tools, diagnostics);
268
+
269
+ if (!hasCanonical) {
270
+ const state = stateFromLegacy(tuiProjection, sandboxProjection.installed);
271
+ return {
272
+ source: 'legacy',
273
+ state,
274
+ canonical: serializeAgentClients(state),
275
+ remainingSandboxTools: sandboxProjection.remainingTools,
276
+ removeLegacyTuis: hasLegacyTuis,
277
+ changed: true,
278
+ diagnostics
279
+ };
280
+ }
281
+
282
+ const state = parseCanonical(input.agentClients);
283
+ if (hasLegacyTuis) {
284
+ for (const id of AGENT_CLIENT_IDS) {
285
+ if (state[id].enabled !== tuiProjection[id]) {
286
+ fail('LEGACY_CONFLICT', 'tuis');
287
+ }
288
+ }
289
+ }
290
+ if (hasLegacySandboxTools) {
291
+ for (const id of sandboxProjection.clientSignals) {
292
+ if (!state[id].installInSandbox) {
293
+ fail('LEGACY_CONFLICT', 'sandbox.tools');
294
+ }
295
+ }
296
+ }
297
+
298
+ return {
299
+ source: 'canonical',
300
+ state,
301
+ canonical: serializeAgentClients(state),
302
+ remainingSandboxTools: hasLegacySandboxTools
303
+ ? sandboxProjection.remainingTools
304
+ : undefined,
305
+ removeLegacyTuis: hasLegacyTuis,
306
+ changed: hasLegacyTuis
307
+ || sandboxProjection.clientSignals.size > 0
308
+ || !sameCanonicalOrder(input.agentClients),
309
+ diagnostics
310
+ };
311
+ }
312
+
313
+ export {
314
+ AgentClientConfigError,
315
+ normalizeAgentClients,
316
+ serializeAgentClients
317
+ };
318
+ export type {
319
+ AgentClientConfigInput,
320
+ AgentClientDiagnostic,
321
+ AgentClientDiagnosticCode,
322
+ NormalizeAgentClientsResult
323
+ };
@@ -0,0 +1,149 @@
1
+ import path from 'node:path';
2
+
3
+ type CustomTUI = Readonly<{
4
+ name: string;
5
+ dir: string;
6
+ invocation: string;
7
+ }>;
8
+
9
+ type CustomTUIDiagnosticCode =
10
+ | 'INVALID_CUSTOM_TUIS'
11
+ | 'INVALID_CUSTOM_TUI'
12
+ | 'INVALID_CUSTOM_TUI_PLACEHOLDER';
13
+
14
+ type CustomTUIDiagnostic = Readonly<{
15
+ code: CustomTUIDiagnosticCode;
16
+ path: string;
17
+ }>;
18
+
19
+ type NormalizeCustomTUIsResult = Readonly<{
20
+ items: readonly CustomTUI[];
21
+ diagnostics: readonly CustomTUIDiagnostic[];
22
+ }>;
23
+
24
+ const CUSTOM_TUI_CONTRACT = Object.freeze({
25
+ requiredFields: Object.freeze(['name', 'dir', 'invoke']),
26
+ allowedPlaceholders: Object.freeze(['skillName', 'projectName'])
27
+ });
28
+
29
+ function isRecord(value: unknown): value is Record<string, unknown> {
30
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
31
+ }
32
+
33
+ function isNonEmptySingleLine(value: unknown): value is string {
34
+ return typeof value === 'string'
35
+ && value.trim() !== ''
36
+ && !/[\r\n]/.test(value);
37
+ }
38
+
39
+ function normalizeDir(projectRoot: string, value: unknown): string | null {
40
+ if (
41
+ !isNonEmptySingleLine(value)
42
+ || value.includes('\\')
43
+ || path.isAbsolute(value)
44
+ || /^[a-zA-Z]:/.test(value)
45
+ ) {
46
+ return null;
47
+ }
48
+ const normalized = path.posix.normalize(value);
49
+ if (
50
+ normalized === '.'
51
+ || normalized === '..'
52
+ || normalized.startsWith('../')
53
+ || normalized.split('/').includes('..')
54
+ ) {
55
+ return null;
56
+ }
57
+ const relative = path.relative(
58
+ path.resolve(projectRoot),
59
+ path.resolve(projectRoot, normalized)
60
+ );
61
+ return relative === ''
62
+ || path.isAbsolute(relative)
63
+ || relative === '..'
64
+ || relative.startsWith(`..${path.sep}`)
65
+ ? null
66
+ : normalized;
67
+ }
68
+
69
+ function hasValidPlaceholders(invocation: string): boolean {
70
+ const placeholders = [
71
+ ...invocation.matchAll(/\$\{([^}]+)\}/g)
72
+ ].map((match) => match[1]!);
73
+ return placeholders.includes('skillName')
74
+ && placeholders.every((placeholder) =>
75
+ CUSTOM_TUI_CONTRACT.allowedPlaceholders.includes(placeholder)
76
+ )
77
+ && !invocation
78
+ .replaceAll('${skillName}', '')
79
+ .replaceAll('${projectName}', '')
80
+ .includes('${');
81
+ }
82
+
83
+ function normalizeCustomTUIs(
84
+ projectRoot: string,
85
+ input: unknown
86
+ ): NormalizeCustomTUIsResult {
87
+ const items: CustomTUI[] = [];
88
+ const diagnostics: CustomTUIDiagnostic[] = [];
89
+
90
+ if (!Array.isArray(input)) {
91
+ return Object.freeze({
92
+ items: Object.freeze([]),
93
+ diagnostics: Object.freeze([
94
+ Object.freeze({
95
+ code: 'INVALID_CUSTOM_TUIS' as const,
96
+ path: 'customTUIs'
97
+ })
98
+ ])
99
+ });
100
+ }
101
+
102
+ for (const [index, candidate] of input.entries()) {
103
+ const base = `customTUIs[${index}]`;
104
+ if (!isRecord(candidate)) {
105
+ diagnostics.push({ code: 'INVALID_CUSTOM_TUI', path: base });
106
+ continue;
107
+ }
108
+ if (!isNonEmptySingleLine(candidate.name)) {
109
+ diagnostics.push({ code: 'INVALID_CUSTOM_TUI', path: `${base}.name` });
110
+ continue;
111
+ }
112
+ const dir = normalizeDir(projectRoot, candidate.dir);
113
+ if (!dir) {
114
+ diagnostics.push({ code: 'INVALID_CUSTOM_TUI', path: `${base}.dir` });
115
+ continue;
116
+ }
117
+ if (!isNonEmptySingleLine(candidate.invoke)) {
118
+ diagnostics.push({ code: 'INVALID_CUSTOM_TUI', path: `${base}.invoke` });
119
+ continue;
120
+ }
121
+ if (!hasValidPlaceholders(candidate.invoke)) {
122
+ diagnostics.push({
123
+ code: 'INVALID_CUSTOM_TUI_PLACEHOLDER',
124
+ path: `${base}.invoke`
125
+ });
126
+ continue;
127
+ }
128
+ items.push(Object.freeze({
129
+ name: candidate.name,
130
+ dir,
131
+ invocation: candidate.invoke
132
+ }));
133
+ }
134
+
135
+ return Object.freeze({
136
+ items: Object.freeze(items),
137
+ diagnostics: Object.freeze(
138
+ diagnostics.map((diagnostic) => Object.freeze(diagnostic))
139
+ )
140
+ });
141
+ }
142
+
143
+ export { CUSTOM_TUI_CONTRACT, normalizeCustomTUIs };
144
+ export type {
145
+ CustomTUI,
146
+ CustomTUIDiagnostic,
147
+ CustomTUIDiagnosticCode,
148
+ NormalizeCustomTUIsResult
149
+ };
@@ -0,0 +1,19 @@
1
+ type AgentClientInvocationInput = Readonly<{
2
+ skillName: string;
3
+ projectName?: string;
4
+ args?: readonly string[];
5
+ }>;
6
+
7
+ function renderAgentClientInvocation(
8
+ template: string,
9
+ input: AgentClientInvocationInput
10
+ ): string {
11
+ let command = template.replaceAll('${skillName}', input.skillName);
12
+ if (input.projectName !== undefined) {
13
+ command = command.replaceAll('${projectName}', input.projectName);
14
+ }
15
+ return [command, ...(input.args ?? [])].join(' ').trim();
16
+ }
17
+
18
+ export { renderAgentClientInvocation };
19
+ export type { AgentClientInvocationInput };
@@ -0,0 +1,85 @@
1
+ import { listEnabledAgentClientAdapters } from './registry.ts';
2
+ import { renderAgentClientInvocation } from './invocation.ts';
3
+ import semver from 'semver';
4
+ import type { CustomTUI } from './custom-tuis.ts';
5
+ import type { AgentClientId, AgentClientState } from './types.ts';
6
+
7
+ type NextStepCommand = Readonly<{
8
+ source: 'builtin' | 'custom';
9
+ clientId?: AgentClientId;
10
+ displayName: string;
11
+ command: string;
12
+ }>;
13
+
14
+ type RenderNextStepsInput = Readonly<{
15
+ projectName: string;
16
+ state: AgentClientState;
17
+ customTUIs: readonly CustomTUI[];
18
+ skillName: string;
19
+ taskRef?: string;
20
+ version?: string;
21
+ }>;
22
+
23
+ const SAFE_NAME = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
24
+ const SAFE_TASK_REF = /^(?:\d+|TASK-\d{8}-\d{6})$/;
25
+
26
+ function requireSafeName(value: string, field: string): void {
27
+ if (!SAFE_NAME.test(value)) {
28
+ throw new Error(`Invalid ${field}`);
29
+ }
30
+ }
31
+
32
+ function renderNextStepCommands(
33
+ input: RenderNextStepsInput
34
+ ): readonly NextStepCommand[] {
35
+ requireSafeName(input.projectName, 'project name');
36
+ requireSafeName(input.skillName, 'skill name');
37
+ if (input.taskRef !== undefined && !SAFE_TASK_REF.test(input.taskRef)) {
38
+ throw new Error('Invalid task ref');
39
+ }
40
+ if (
41
+ input.version !== undefined
42
+ && (!/^[0-9]/.test(input.version) || semver.valid(input.version) !== input.version)
43
+ ) {
44
+ throw new Error('Invalid version');
45
+ }
46
+
47
+ const args = [
48
+ ...(input.taskRef === undefined ? [] : [input.taskRef]),
49
+ ...(input.version === undefined ? [] : [input.version])
50
+ ];
51
+
52
+ const builtins = listEnabledAgentClientAdapters(input.state).map(
53
+ (adapter): NextStepCommand => Object.freeze({
54
+ source: 'builtin',
55
+ clientId: adapter.id,
56
+ displayName: adapter.displayName,
57
+ command: renderAgentClientInvocation(
58
+ adapter.invocation,
59
+ {
60
+ projectName: input.projectName,
61
+ skillName: input.skillName,
62
+ args
63
+ }
64
+ )
65
+ })
66
+ );
67
+ const custom = input.customTUIs.map(
68
+ (tool): NextStepCommand => Object.freeze({
69
+ source: 'custom',
70
+ displayName: tool.name,
71
+ command: renderAgentClientInvocation(
72
+ tool.invocation,
73
+ {
74
+ projectName: input.projectName,
75
+ skillName: input.skillName,
76
+ args
77
+ }
78
+ )
79
+ })
80
+ );
81
+ return Object.freeze([...builtins, ...custom]);
82
+ }
83
+
84
+ export { renderNextStepCommands };
85
+ export type { NextStepCommand, RenderNextStepsInput };
@@ -0,0 +1,96 @@
1
+ import type { AgentClientAdapter } from './adapter.ts';
2
+
3
+ type ProjectFileRegistry = Readonly<{
4
+ managed: readonly string[];
5
+ merged: readonly string[];
6
+ ejected: readonly string[];
7
+ }>;
8
+
9
+ type AgentClientProjectAssetPlan = Readonly<{
10
+ registry: ProjectFileRegistry;
11
+ enabledManaged: readonly string[];
12
+ enabledMerged: readonly string[];
13
+ enabledEjected: readonly string[];
14
+ disabledManaged: readonly string[];
15
+ }>;
16
+
17
+ function unique(values: readonly string[]): readonly string[] {
18
+ return Object.freeze([...new Set(values)]);
19
+ }
20
+
21
+ function planAgentClientProjectAssets(input: Readonly<{
22
+ current: ProjectFileRegistry;
23
+ sharedDefaults: ProjectFileRegistry;
24
+ enabledAdapters: readonly AgentClientAdapter[];
25
+ allAdapters: readonly AgentClientAdapter[];
26
+ }>): AgentClientProjectAssetPlan {
27
+ const enabledIds = new Set(input.enabledAdapters.map((adapter) => adapter.id));
28
+ const enabledAdapters = input.allAdapters.filter((adapter) =>
29
+ enabledIds.has(adapter.id)
30
+ );
31
+ const disabledAdapters = input.allAdapters.filter((adapter) =>
32
+ !enabledIds.has(adapter.id)
33
+ );
34
+
35
+ const enabledManaged = unique(
36
+ enabledAdapters.flatMap((adapter) => adapter.project.managed)
37
+ );
38
+ const enabledMerged = unique(
39
+ enabledAdapters.flatMap((adapter) => adapter.project.merged)
40
+ );
41
+ const enabledEjected = unique(
42
+ enabledAdapters.flatMap((adapter) => adapter.project.ejected)
43
+ );
44
+ const disabledManaged = unique(
45
+ disabledAdapters.flatMap((adapter) => adapter.project.managed)
46
+ );
47
+
48
+ const allAdapterAssets = new Set(
49
+ input.allAdapters.flatMap((adapter) => [
50
+ ...adapter.project.managed,
51
+ ...adapter.project.merged,
52
+ ...adapter.project.ejected
53
+ ])
54
+ );
55
+ const ejected = unique([
56
+ ...input.current.ejected,
57
+ ...enabledEjected,
58
+ ...input.sharedDefaults.ejected
59
+ ]);
60
+ const ejectedSet = new Set(ejected);
61
+
62
+ const preserveCurrent = (
63
+ values: readonly string[],
64
+ enabledValues: readonly string[]
65
+ ) => values.filter((entry) =>
66
+ !ejectedSet.has(entry)
67
+ && (!allAdapterAssets.has(entry) || enabledValues.includes(entry))
68
+ );
69
+
70
+ const managed = unique([
71
+ ...preserveCurrent(input.current.managed, enabledManaged),
72
+ ...enabledManaged.filter((entry) => !ejectedSet.has(entry)),
73
+ ...input.sharedDefaults.managed.filter((entry) => !ejectedSet.has(entry))
74
+ ]);
75
+ const managedSet = new Set(managed);
76
+ const merged = unique([
77
+ ...preserveCurrent(input.current.merged, enabledMerged),
78
+ ...enabledMerged.filter((entry) =>
79
+ !ejectedSet.has(entry) && !managedSet.has(entry)
80
+ ),
81
+ ...input.sharedDefaults.merged.filter((entry) =>
82
+ !ejectedSet.has(entry) && !managedSet.has(entry)
83
+ )
84
+ ]);
85
+
86
+ return Object.freeze({
87
+ registry: Object.freeze({ managed, merged, ejected }),
88
+ enabledManaged,
89
+ enabledMerged,
90
+ enabledEjected,
91
+ disabledManaged
92
+ });
93
+ }
94
+
95
+ export { planAgentClientProjectAssets };
96
+ export type { AgentClientProjectAssetPlan, ProjectFileRegistry };