@fitlab-ai/agent-infra 0.9.12 → 0.9.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (402) hide show
  1. package/README.md +11 -11
  2. package/README.zh-CN.md +11 -11
  3. package/bin/cli.ts +26 -9
  4. package/dist/bin/cli.js +173 -157
  5. package/dist/bin/internal-cli.js +66 -40
  6. package/dist/lib/agent-client.js +5 -0
  7. package/dist/lib/agent-clients/next-steps.js +6 -1
  8. package/dist/lib/decide.js +3 -3
  9. package/dist/lib/internal/agent-client.js +5 -2
  10. package/dist/lib/internal/cli-route-inventory.js +152 -0
  11. package/dist/lib/internal/codex-lifecycle.js +9 -6
  12. package/dist/lib/internal/codex-sandbox-controller.js +8 -2
  13. package/dist/lib/internal/git-workflow.js +10 -6
  14. package/dist/lib/internal/platform-checks.js +19 -7
  15. package/dist/lib/internal/platform-comment.js +25 -13
  16. package/dist/lib/internal/platform-context.js +6 -3
  17. package/dist/lib/internal/platform-issue.js +20 -13
  18. package/dist/lib/internal/platform-metadata.js +88 -0
  19. package/dist/lib/internal/platform-pr-review.js +26 -13
  20. package/dist/lib/internal/platform-pr.js +84 -31
  21. package/dist/lib/internal/platform-release-notes.js +9 -6
  22. package/dist/lib/internal/platform-security.js +93 -0
  23. package/dist/lib/internal/pr-review-grade.js +25 -12
  24. package/dist/lib/internal/release-workflow.js +23 -9
  25. package/dist/lib/internal/sandbox-control.js +50 -7
  26. package/dist/lib/internal/task-activity.js +16 -7
  27. package/dist/lib/internal/task-artifact.js +235 -24
  28. package/dist/lib/internal/task-context.js +4 -1
  29. package/dist/lib/internal/task-create.js +50 -17
  30. package/dist/lib/internal/task-delivery.js +4 -1
  31. package/dist/lib/internal/task-event.js +10 -4
  32. package/dist/lib/internal/task-finalization.js +6 -3
  33. package/dist/lib/internal/task-invalidation.js +63 -0
  34. package/dist/lib/internal/task-ledger.js +20 -6
  35. package/dist/lib/internal/task-lifecycle.js +6 -3
  36. package/dist/lib/internal/task-operation-registry.js +421 -0
  37. package/dist/lib/internal/task-orchestration.js +12 -0
  38. package/dist/lib/internal/task-override.js +14 -7
  39. package/dist/lib/internal/task-qualification.js +90 -0
  40. package/dist/lib/internal/task-review.js +7 -4
  41. package/dist/lib/internal/task-short-id.js +11 -1
  42. package/dist/lib/internal/task-snapshot.js +4 -1
  43. package/dist/lib/internal/task-validate.js +7 -2
  44. package/dist/lib/internal/task-verify.js +11 -7
  45. package/dist/lib/internal/task-warning.js +11 -4
  46. package/dist/lib/platform/adapters.js +1 -3
  47. package/dist/lib/platform/change-request-git-evidence.js +27 -7
  48. package/dist/lib/platform/comment-safety.js +226 -0
  49. package/dist/lib/platform/completion-backfill.js +6 -5
  50. package/dist/lib/platform/context.js +70 -130
  51. package/dist/lib/platform/github-client.js +1 -1
  52. package/dist/lib/platform/github-provider.js +1130 -0
  53. package/dist/lib/platform/in-label-sync.js +143 -0
  54. package/dist/lib/platform/issue-comments.js +237 -72
  55. package/dist/lib/platform/issues.js +335 -189
  56. package/dist/lib/platform/metadata-labels.js +6 -2
  57. package/dist/lib/platform/none-provider.js +28 -0
  58. package/dist/lib/platform/pr-change-report.js +545 -0
  59. package/dist/lib/platform/pr-checks.js +119 -104
  60. package/dist/lib/platform/pr-review.js +88 -72
  61. package/dist/lib/platform/pr-summary.js +541 -50
  62. package/dist/lib/platform/provider-bridge.js +45 -0
  63. package/dist/lib/platform/provider-contract.d.ts +553 -0
  64. package/dist/lib/platform/provider-contract.js +99 -0
  65. package/dist/lib/platform/provider-loader.js +251 -0
  66. package/dist/lib/platform/provider-validation.js +577 -0
  67. package/dist/lib/platform/pull-request-metadata.js +8 -6
  68. package/dist/lib/platform/pull-requests.js +734 -543
  69. package/dist/lib/platform/release-notes.js +78 -55
  70. package/dist/lib/platform/releases.js +79 -50
  71. package/dist/lib/platform/repository-metadata.js +377 -0
  72. package/dist/lib/platform/resource-identity.d.ts +26 -0
  73. package/dist/lib/platform/resource-identity.js +92 -0
  74. package/dist/lib/platform/security-alerts.js +155 -0
  75. package/dist/lib/platform/task-identities.js +31 -0
  76. package/dist/lib/platform/verification-required.js +11 -12
  77. package/dist/lib/platform/verification-sync.js +129 -248
  78. package/dist/lib/pr-review/evidence-grading.js +19 -6
  79. package/dist/lib/process-data/index.js +7 -0
  80. package/dist/lib/run/index.js +68 -23
  81. package/dist/lib/sandbox/commands/control-status.js +22 -0
  82. package/dist/lib/sandbox/commands/create.js +32 -6
  83. package/dist/lib/sandbox/commands/ls.js +5 -0
  84. package/dist/lib/sandbox/commands/rm.js +827 -120
  85. package/dist/lib/sandbox/commands/show.js +16 -0
  86. package/dist/lib/sandbox/control/client.js +174 -19
  87. package/dist/lib/sandbox/control/completed-reentry.js +85 -0
  88. package/dist/lib/sandbox/control/container-identity.js +28 -31
  89. package/dist/lib/sandbox/control/executor.js +151 -16
  90. package/dist/lib/sandbox/control/lifecycle.js +621 -127
  91. package/dist/lib/sandbox/control/native-file-lock.js +177 -0
  92. package/dist/lib/sandbox/control/protocol.js +77 -0
  93. package/dist/lib/sandbox/control/server.js +677 -34
  94. package/dist/lib/sandbox/control/state.js +209 -4
  95. package/dist/lib/sandbox/control/task-view.js +183 -0
  96. package/dist/lib/sandbox/engines/authority.js +289 -0
  97. package/dist/lib/sandbox/engines/docker-exact-discovery.js +97 -0
  98. package/dist/lib/sandbox/index.js +5 -0
  99. package/dist/lib/sandbox/recovery.js +21 -1
  100. package/dist/lib/sandbox/workspace-view.js +2 -1
  101. package/dist/lib/sandbox/worktree-safety.js +4 -1
  102. package/dist/lib/server/index.js +8 -0
  103. package/dist/lib/server/protocol.js +38 -1
  104. package/dist/lib/task/activity-log.js +8 -1
  105. package/dist/lib/task/artifact-lifecycle.js +75 -18
  106. package/dist/lib/task/artifact-operations.js +520 -0
  107. package/dist/lib/task/artifact-repair-intent.js +59 -0
  108. package/dist/lib/task/artifact-schema.js +135 -0
  109. package/dist/lib/task/capabilities.js +310 -0
  110. package/dist/lib/task/commands/status.js +32 -0
  111. package/dist/lib/task/commit-operation.js +12 -1
  112. package/dist/lib/task/control-authority.js +12 -5
  113. package/dist/lib/task/create-service.js +111 -12
  114. package/dist/lib/task/create.js +25 -0
  115. package/dist/lib/task/current-contract.js +5 -1
  116. package/dist/lib/task/decision-details.js +1 -1
  117. package/dist/lib/task/events.js +416 -17
  118. package/dist/lib/task/finalization.js +37 -13
  119. package/dist/lib/task/human-override.js +58 -36
  120. package/dist/lib/task/index.js +11 -3
  121. package/dist/lib/task/invalidation-command.js +86 -0
  122. package/dist/lib/task/invalidation.js +260 -0
  123. package/dist/lib/task/ledger-intents.js +37 -0
  124. package/dist/lib/task/local-artifact-finalization.js +299 -0
  125. package/dist/lib/task/orchestration.js +240 -144
  126. package/dist/lib/task/pr-delivery-fact.js +102 -101
  127. package/dist/lib/task/qualification-audit.js +490 -0
  128. package/dist/lib/task/qualification-confirmation.js +109 -0
  129. package/dist/lib/task/qualification-intents.js +148 -0
  130. package/dist/lib/task/review-artifacts.js +22 -23
  131. package/dist/lib/task/review-finalization.js +121 -4
  132. package/dist/lib/task/review-fingerprint.js +24 -2
  133. package/dist/lib/task/rework-intent.js +138 -0
  134. package/dist/lib/task/sections.js +6 -4
  135. package/dist/lib/task/skill-scope.js +23 -0
  136. package/dist/lib/task/task-execution-lock.js +27 -17
  137. package/dist/lib/task/verification-config.js +11 -0
  138. package/dist/lib/task/verification-engine.js +93 -16
  139. package/dist/lib/task/verification.js +3 -3
  140. package/dist/lib/task/workflow-warning-intents.js +1 -1
  141. package/dist/lib/task/write.js +11 -0
  142. package/dist/lib/version.js +11 -1
  143. package/dist/lifecycle-build-manifest.json +3 -3
  144. package/lib/agent-client.ts +9 -0
  145. package/lib/agent-clients/next-steps.ts +6 -1
  146. package/lib/decide.ts +3 -3
  147. package/lib/init.ts +1 -1
  148. package/lib/internal/agent-client.ts +4 -2
  149. package/lib/internal/cli-route-inventory.ts +140 -0
  150. package/lib/internal/codex-lifecycle.ts +8 -6
  151. package/lib/internal/codex-sandbox-controller.ts +7 -2
  152. package/lib/internal/git-workflow.ts +9 -6
  153. package/lib/internal/platform-checks.ts +14 -6
  154. package/lib/internal/platform-comment.ts +20 -12
  155. package/lib/internal/platform-context.ts +5 -3
  156. package/lib/internal/platform-issue.ts +17 -11
  157. package/lib/internal/platform-metadata.ts +70 -0
  158. package/lib/internal/platform-pr-review.ts +23 -12
  159. package/lib/internal/platform-pr.ts +65 -27
  160. package/lib/internal/platform-release-notes.ts +8 -6
  161. package/lib/internal/platform-security.ts +83 -0
  162. package/lib/internal/pr-review-grade.ts +20 -11
  163. package/lib/internal/release-workflow.ts +21 -9
  164. package/lib/internal/sandbox-control.ts +44 -6
  165. package/lib/internal/task-activity.ts +15 -7
  166. package/lib/internal/task-artifact.ts +204 -22
  167. package/lib/internal/task-context.ts +3 -1
  168. package/lib/internal/task-create.ts +78 -17
  169. package/lib/internal/task-delivery.ts +3 -1
  170. package/lib/internal/task-event.ts +9 -4
  171. package/lib/internal/task-finalization.ts +6 -4
  172. package/lib/internal/task-invalidation.ts +41 -0
  173. package/lib/internal/task-ledger.ts +21 -8
  174. package/lib/internal/task-lifecycle.ts +5 -3
  175. package/lib/internal/task-operation-registry.ts +482 -0
  176. package/lib/internal/task-orchestration.ts +12 -0
  177. package/lib/internal/task-override.ts +15 -9
  178. package/lib/internal/task-qualification.ts +61 -0
  179. package/lib/internal/task-review.ts +6 -4
  180. package/lib/internal/task-short-id.ts +10 -1
  181. package/lib/internal/task-snapshot.ts +3 -1
  182. package/lib/internal/task-validate.ts +6 -2
  183. package/lib/internal/task-verify.ts +10 -7
  184. package/lib/internal/task-warning.ts +10 -4
  185. package/lib/platform/adapters.ts +3 -2
  186. package/lib/platform/change-request-git-evidence.ts +36 -9
  187. package/lib/platform/comment-safety.ts +250 -0
  188. package/lib/platform/completion-backfill.ts +9 -8
  189. package/lib/platform/context.ts +97 -134
  190. package/lib/platform/github-client.ts +2 -2
  191. package/lib/platform/github-provider.ts +1132 -0
  192. package/lib/platform/in-label-sync.ts +208 -0
  193. package/lib/platform/issue-comments.ts +255 -80
  194. package/lib/platform/issues.ts +344 -174
  195. package/lib/platform/metadata-labels.ts +5 -2
  196. package/lib/platform/none-provider.ts +35 -0
  197. package/lib/platform/pr-change-report.ts +639 -0
  198. package/lib/platform/pr-checks.ts +126 -106
  199. package/lib/platform/pr-review.ts +88 -85
  200. package/lib/platform/pr-summary.ts +581 -53
  201. package/lib/platform/provider-bridge.ts +82 -0
  202. package/lib/platform/provider-contract.ts +611 -0
  203. package/lib/platform/provider-loader.ts +307 -0
  204. package/lib/platform/provider-validation.ts +611 -0
  205. package/lib/platform/pull-request-metadata.ts +10 -7
  206. package/lib/platform/pull-requests.ts +781 -550
  207. package/lib/platform/release-notes.ts +76 -59
  208. package/lib/platform/releases.ts +77 -43
  209. package/lib/platform/repository-metadata.ts +453 -0
  210. package/lib/platform/resource-identity.ts +121 -0
  211. package/lib/platform/security-alerts.ts +191 -0
  212. package/lib/platform/task-identities.ts +40 -0
  213. package/lib/platform/types.ts +4 -2
  214. package/lib/platform/verification-required.ts +11 -13
  215. package/lib/platform/verification-sync.ts +128 -304
  216. package/lib/pr-review/evidence-grading.ts +25 -8
  217. package/lib/process-data/index.ts +7 -0
  218. package/lib/run/index.ts +62 -22
  219. package/lib/sandbox/commands/control-status.ts +26 -0
  220. package/lib/sandbox/commands/create.ts +46 -6
  221. package/lib/sandbox/commands/ls.ts +7 -0
  222. package/lib/sandbox/commands/rm.ts +1000 -87
  223. package/lib/sandbox/commands/show.ts +16 -0
  224. package/lib/sandbox/control/client.ts +203 -19
  225. package/lib/sandbox/control/completed-reentry.ts +98 -0
  226. package/lib/sandbox/control/container-identity.ts +27 -43
  227. package/lib/sandbox/control/executor.ts +180 -15
  228. package/lib/sandbox/control/lifecycle.ts +629 -17
  229. package/lib/sandbox/control/native-file-lock.ts +209 -0
  230. package/lib/sandbox/control/protocol.ts +118 -2
  231. package/lib/sandbox/control/server.ts +724 -34
  232. package/lib/sandbox/control/state.ts +257 -4
  233. package/lib/sandbox/control/task-view.ts +240 -0
  234. package/lib/sandbox/engines/authority.ts +365 -0
  235. package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
  236. package/lib/sandbox/index.ts +7 -0
  237. package/lib/sandbox/recovery.ts +21 -1
  238. package/lib/sandbox/workspace-view.ts +9 -3
  239. package/lib/sandbox/worktree-safety.ts +4 -1
  240. package/lib/server/index.ts +10 -0
  241. package/lib/server/protocol.ts +36 -1
  242. package/lib/task/activity-log.ts +8 -0
  243. package/lib/task/artifact-lifecycle.ts +70 -22
  244. package/lib/task/artifact-operations.ts +626 -0
  245. package/lib/task/artifact-repair-intent.ts +71 -0
  246. package/lib/task/artifact-schema.ts +192 -0
  247. package/lib/task/capabilities.ts +331 -0
  248. package/lib/task/commands/status.ts +38 -0
  249. package/lib/task/commit-operation.ts +12 -1
  250. package/lib/task/control-authority.ts +22 -9
  251. package/lib/task/create-service.ts +139 -14
  252. package/lib/task/create.ts +27 -0
  253. package/lib/task/current-contract.ts +6 -1
  254. package/lib/task/decision-details.ts +6 -2
  255. package/lib/task/events.ts +392 -16
  256. package/lib/task/finalization.ts +50 -14
  257. package/lib/task/human-override.ts +70 -46
  258. package/lib/task/index.ts +16 -3
  259. package/lib/task/invalidation-command.ts +86 -0
  260. package/lib/task/invalidation.ts +332 -0
  261. package/lib/task/ledger-intents.ts +35 -1
  262. package/lib/task/local-artifact-finalization.ts +432 -0
  263. package/lib/task/orchestration.ts +223 -133
  264. package/lib/task/pr-delivery-fact.ts +131 -148
  265. package/lib/task/qualification-audit.ts +599 -0
  266. package/lib/task/qualification-confirmation.ts +117 -0
  267. package/lib/task/qualification-intents.ts +150 -0
  268. package/lib/task/review-artifacts.ts +21 -22
  269. package/lib/task/review-finalization.ts +133 -4
  270. package/lib/task/review-fingerprint.ts +23 -2
  271. package/lib/task/rework-intent.ts +165 -0
  272. package/lib/task/sections.ts +6 -4
  273. package/lib/task/skill-scope.ts +24 -0
  274. package/lib/task/task-execution-lock.ts +23 -14
  275. package/lib/task/verification-config.ts +12 -0
  276. package/lib/task/verification-engine.ts +103 -17
  277. package/lib/task/verification.ts +4 -4
  278. package/lib/task/workflow-warning-intents.ts +1 -1
  279. package/lib/task/write.ts +19 -0
  280. package/lib/update.ts +1 -1
  281. package/lib/version.ts +15 -1
  282. package/package.json +12 -1
  283. package/templates/.agents/rules/README.en.md +3 -1
  284. package/templates/.agents/rules/README.zh-CN.md +3 -1
  285. package/templates/.agents/rules/decision-qualification.en.md +22 -0
  286. package/templates/.agents/rules/decision-qualification.zh-CN.md +22 -0
  287. package/templates/.agents/rules/evidence-reporting.en.md +28 -0
  288. package/templates/.agents/rules/evidence-reporting.zh-CN.md +28 -0
  289. package/templates/.agents/rules/issue-pr-commands.en.md +1 -1
  290. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
  291. package/templates/.agents/rules/issue-sync.en.md +2 -0
  292. package/templates/.agents/rules/issue-sync.zh-CN.md +2 -0
  293. package/templates/.agents/rules/label-milestone-setup.en.md +7 -7
  294. package/templates/.agents/rules/label-milestone-setup.zh-CN.md +7 -7
  295. package/templates/.agents/rules/local-artifact-repair.en.md +13 -2
  296. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +13 -2
  297. package/templates/.agents/rules/pr-sync.en.md +10 -4
  298. package/templates/.agents/rules/pr-sync.zh-CN.md +17 -4
  299. package/templates/.agents/rules/security-alerts.en.md +8 -8
  300. package/templates/.agents/rules/security-alerts.zh-CN.md +8 -8
  301. package/templates/.agents/rules/task-short-id.en.md +1 -4
  302. package/templates/.agents/rules/task-short-id.zh-CN.md +1 -3
  303. package/templates/.agents/skills/analyze-task/SKILL.en.md +28 -5
  304. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +29 -5
  305. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -12
  306. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -12
  307. package/templates/.agents/skills/check-task/SKILL.en.md +16 -37
  308. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -37
  309. package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
  310. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
  311. package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
  312. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
  313. package/templates/.agents/skills/code-task/SKILL.en.md +41 -9
  314. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +43 -11
  315. package/templates/.agents/skills/code-task/config/verify.en.json +6 -14
  316. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +6 -14
  317. package/templates/.agents/skills/code-task/reference/code-rules.en.md +5 -4
  318. package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +5 -4
  319. package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
  320. package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
  321. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +3 -1
  322. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +3 -1
  323. package/templates/.agents/skills/code-task/reference/report-template.en.md +42 -15
  324. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +39 -12
  325. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +2 -0
  326. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +2 -0
  327. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +3 -3
  328. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +3 -3
  329. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +10 -4
  330. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +10 -4
  331. package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +2 -0
  332. package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +2 -0
  333. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +4 -3
  334. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +4 -3
  335. package/templates/.agents/skills/complete-task/SKILL.en.md +26 -21
  336. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +25 -21
  337. package/templates/.agents/skills/create-pr/SKILL.en.md +7 -6
  338. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +7 -7
  339. package/templates/.agents/skills/create-pr/config/verify.json +1 -0
  340. package/templates/.agents/skills/create-pr/reference/change-report.en.md +16 -4
  341. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +16 -4
  342. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +5 -3
  343. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +5 -3
  344. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +1 -1
  345. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +1 -1
  346. package/templates/.agents/skills/create-pr/scripts/change-report.mjs +3 -0
  347. package/templates/.agents/skills/create-task/SKILL.en.md +8 -0
  348. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +7 -0
  349. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  350. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  351. package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
  352. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
  353. package/templates/.agents/skills/init-labels/SKILL.en.md +8 -8
  354. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +8 -8
  355. package/templates/.agents/skills/init-milestones/SKILL.en.md +9 -11
  356. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +9 -11
  357. package/templates/.agents/skills/plan-task/SKILL.en.md +27 -4
  358. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +26 -4
  359. package/templates/.agents/skills/plan-task/config/verify.en.json +4 -14
  360. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +4 -14
  361. package/templates/.agents/skills/review-analysis/SKILL.en.md +17 -4
  362. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +17 -4
  363. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -18
  364. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -18
  365. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +50 -23
  366. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +45 -18
  367. package/templates/.agents/skills/review-code/SKILL.en.md +18 -5
  368. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +18 -5
  369. package/templates/.agents/skills/review-code/config/verify.en.json +1 -23
  370. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -23
  371. package/templates/.agents/skills/review-code/reference/report-template.en.md +49 -22
  372. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +45 -18
  373. package/templates/.agents/skills/review-plan/SKILL.en.md +17 -4
  374. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +17 -4
  375. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -18
  376. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -18
  377. package/templates/.agents/skills/review-plan/reference/report-template.en.md +49 -22
  378. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +45 -18
  379. package/templates/.agents/skills/review-pr/SKILL.en.md +5 -1
  380. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +5 -1
  381. package/templates/.agents/skills/review-pr/reference/report-template.en.md +4 -3
  382. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +4 -3
  383. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +9 -3
  384. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +9 -3
  385. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +3 -1
  386. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +3 -1
  387. package/templates/.agents/skills/test/SKILL.en.md +13 -2
  388. package/templates/.agents/skills/test/SKILL.zh-CN.md +13 -2
  389. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +14 -0
  390. package/templates/.agents/skills/watch-pr/SKILL.en.md +2 -2
  391. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +2 -2
  392. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +6 -0
  393. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +6 -0
  394. package/templates/.agents/templates/task.en.md +24 -1
  395. package/templates/.agents/templates/task.zh-CN.md +24 -1
  396. package/templates/.github/workflows/pr-label.yml +7 -26
  397. package/templates/.agents/scripts/security-alerts.github.sh +0 -151
  398. package/templates/.agents/scripts/security-alerts.sh +0 -31
  399. package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +0 -146
  400. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +0 -32
  401. package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +0 -294
  402. package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +0 -6
@@ -0,0 +1,377 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { resolvePlatformProviderContext } from './context.js';
5
+ import { providerError, providerOperationContext, providerStatus } from './provider-bridge.js';
6
+ import { platformResult } from './types.js';
7
+ const COMMON_LABELS = [
8
+ { name: 'type: bug', color: 'DED6F9', description: 'A general bug' },
9
+ { name: 'type: enhancement', color: 'DED6F9', description: 'A general enhancement' },
10
+ { name: 'type: feature', color: 'DED6F9', description: 'A general feature' },
11
+ { name: 'type: documentation', color: 'DED6F9', description: 'A documentation task' },
12
+ { name: 'type: dependency-upgrade', color: 'DED6F9', description: 'A dependency upgrade' },
13
+ { name: 'type: task', color: 'DED6F9', description: 'A general task' },
14
+ { name: 'status: waiting-for-triage', color: 'FCF1C4', description: "An issue we've not yet triaged or decided on" },
15
+ { name: 'status: waiting-for-feedback', color: 'FCF1C4', description: 'We need additional information before we can continue' },
16
+ { name: 'status: feedback-provided', color: 'FCF1C4', description: 'Feedback has been provided' },
17
+ { name: 'status: feedback-reminder', color: 'FCF1C4', description: "We've sent a reminder that we need additional information before we can continue" },
18
+ { name: 'status: pending-design-work', color: 'FCF1C4', description: 'Needs design work before any code can be developed' },
19
+ { name: 'status: in-progress', color: 'FCF1C4', description: 'Work is actively being developed' },
20
+ { name: 'status: on-hold', color: 'FCF1C4', description: "We can't start working on this issue yet" },
21
+ { name: 'status: blocked', color: 'FCF1C4', description: "An issue that's blocked on an external project change" },
22
+ { name: 'status: declined', color: 'FCF1C4', description: "A suggestion or change that we don't feel we should currently apply" },
23
+ { name: 'status: duplicate', color: 'FCF1C4', description: 'A duplicate of another issue' },
24
+ { name: 'status: invalid', color: 'FCF1C4', description: "An issue that we don't feel is valid" },
25
+ { name: 'status: superseded', color: 'FCF1C4', description: 'An issue that has been superseded by another' },
26
+ { name: 'status: bulk-closed', color: 'FCF1C4', description: "An outdated, unresolved issue that's closed in bulk as part of a cleaning process" },
27
+ { name: 'status: ideal-for-contribution', color: 'FCF1C4', description: 'An issue that a contributor can help us with' },
28
+ { name: 'status: backported', color: 'FCF1C4', description: 'An issue that has been backported to maintenance branches' },
29
+ { name: 'status: waiting-for-internal-feedback', color: 'FCF1C4', description: 'An issue that needs input from a member or another team' },
30
+ { name: 'good first issue', color: 'F9D9E6', description: 'Good for newcomers' },
31
+ { name: 'help wanted', color: '008672', description: 'Extra attention is needed' },
32
+ { name: 'dependencies', color: '0366D6', description: 'Pull requests that update a dependency file' }
33
+ ];
34
+ function validIdentifiers(value, prerelease) {
35
+ if (!value)
36
+ return false;
37
+ return value.split('.').every((identifier) => /^[0-9A-Za-z-]+$/.test(identifier)
38
+ && (!prerelease || !/^\d+$/.test(identifier) || /^(0|[1-9]\d*)$/.test(identifier)));
39
+ }
40
+ function parseVersionTag(tag) {
41
+ if (!tag.startsWith('v'))
42
+ return null;
43
+ let version = tag.slice(1);
44
+ const plusAt = version.indexOf('+');
45
+ if (plusAt >= 0) {
46
+ const build = version.slice(plusAt + 1);
47
+ if (!validIdentifiers(build, false))
48
+ return null;
49
+ version = version.slice(0, plusAt);
50
+ }
51
+ let prerelease = '';
52
+ const dashAt = version.indexOf('-');
53
+ if (dashAt >= 0) {
54
+ prerelease = version.slice(dashAt + 1);
55
+ if (!validIdentifiers(prerelease, true))
56
+ return null;
57
+ version = version.slice(0, dashAt);
58
+ }
59
+ const core = version.split('.');
60
+ if (core.length !== 3 || !core.every((part) => /^(0|[1-9]\d*)$/.test(part)))
61
+ return null;
62
+ return { tag, major: core[0], minor: core[1], patch: core[2], prerelease };
63
+ }
64
+ function compareDecimal(left, right) {
65
+ if (left.length !== right.length)
66
+ return left.length > right.length ? 1 : -1;
67
+ if (left === right)
68
+ return 0;
69
+ return left > right ? 1 : -1;
70
+ }
71
+ function compareAscii(left, right) {
72
+ const alphabet = '+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
73
+ const limit = Math.min(left.length, right.length);
74
+ for (let index = 0; index < limit; index += 1) {
75
+ const leftRank = alphabet.indexOf(left[index]);
76
+ const rightRank = alphabet.indexOf(right[index]);
77
+ if (leftRank !== rightRank)
78
+ return leftRank > rightRank ? 1 : -1;
79
+ }
80
+ if (left.length === right.length)
81
+ return 0;
82
+ return left.length > right.length ? 1 : -1;
83
+ }
84
+ function comparePrerelease(left, right) {
85
+ if (!left || !right) {
86
+ if (left === right)
87
+ return 0;
88
+ return left ? -1 : 1;
89
+ }
90
+ const leftIds = left.split('.');
91
+ const rightIds = right.split('.');
92
+ const limit = Math.min(leftIds.length, rightIds.length);
93
+ for (let index = 0; index < limit; index += 1) {
94
+ const leftId = leftIds[index];
95
+ const rightId = rightIds[index];
96
+ const leftNumeric = /^\d+$/.test(leftId);
97
+ const rightNumeric = /^\d+$/.test(rightId);
98
+ const comparison = leftNumeric && rightNumeric
99
+ ? compareDecimal(leftId, rightId)
100
+ : leftNumeric !== rightNumeric
101
+ ? leftNumeric ? -1 : 1
102
+ : compareAscii(leftId, rightId);
103
+ if (comparison !== 0)
104
+ return comparison;
105
+ }
106
+ if (leftIds.length === rightIds.length)
107
+ return 0;
108
+ return leftIds.length > rightIds.length ? 1 : -1;
109
+ }
110
+ function compareVersions(left, right) {
111
+ for (const [leftPart, rightPart] of [
112
+ [left.major, right.major],
113
+ [left.minor, right.minor],
114
+ [left.patch, right.patch]
115
+ ]) {
116
+ const comparison = compareDecimal(leftPart, rightPart);
117
+ if (comparison !== 0)
118
+ return comparison;
119
+ }
120
+ const prerelease = comparePrerelease(left.prerelease, right.prerelease);
121
+ return prerelease !== 0 ? prerelease : compareAscii(left.tag, right.tag);
122
+ }
123
+ function incrementDecimal(value) {
124
+ const digits = value.split('');
125
+ let carry = 1;
126
+ for (let index = digits.length - 1; index >= 0 && carry; index -= 1) {
127
+ const next = Number(digits[index]) + carry;
128
+ digits[index] = String(next % 10);
129
+ carry = next === 10 ? 1 : 0;
130
+ }
131
+ return carry ? `1${digits.join('')}` : digits.join('');
132
+ }
133
+ function buildMilestonePlan(tags, history) {
134
+ const parsed = tags.flatMap((tag) => {
135
+ const version = parseVersionTag(tag);
136
+ return version ? [version] : [];
137
+ });
138
+ const selected = parsed.reduce((best, candidate) => !best || compareVersions(candidate, best) > 0 ? candidate : best, null);
139
+ const baseline = selected
140
+ ? { version: `${selected.major}.${selected.minor}.${selected.patch}`, source: `git tag ${selected.tag}` }
141
+ : { version: '0.1.0', source: 'compatibility default' };
142
+ const [major, minor, patch] = baseline.version.split('.');
143
+ const desired = [];
144
+ const titles = new Set();
145
+ const add = (title, description, state) => {
146
+ if (titles.has(title))
147
+ return;
148
+ titles.add(title);
149
+ desired.push({ title, description, state });
150
+ };
151
+ const line = `${major}.${minor}.x`;
152
+ const version = selected
153
+ ? `${major}.${minor}.${incrementDecimal(patch)}`
154
+ : baseline.version;
155
+ add('General Backlog', 'All unsorted backlogged tasks may be completed in a future version.', 'open');
156
+ add(line, `Issues that we want to resolve in ${major}.${minor} line.`, 'open');
157
+ add(version, `Issues that we want to release in v${version}.`, 'open');
158
+ if (patch === '0') {
159
+ const nextMinor = `${major}.${incrementDecimal(minor)}.0`;
160
+ const nextLine = `${major}.${incrementDecimal(minor)}.x`;
161
+ add(nextMinor, `Issues that we want to release in v${nextMinor}.`, 'open');
162
+ add(nextLine, `Issues that we want to resolve in ${major}.${incrementDecimal(minor)} line.`, 'open');
163
+ }
164
+ if (history) {
165
+ for (const historical of parsed) {
166
+ const historicalVersion = `${historical.major}.${historical.minor}.${historical.patch}`;
167
+ add(`${historical.major}.${historical.minor}.x`, `Issues that we want to resolve in ${historical.major}.${historical.minor} line.`, 'open');
168
+ add(historicalVersion, `Issues that we want to release in v${historicalVersion}.`, 'closed');
169
+ }
170
+ }
171
+ return { baseline, history, desired };
172
+ }
173
+ function buildLabelDefinitions(config) {
174
+ const labels = config && typeof config === 'object' && !Array.isArray(config)
175
+ ? config.labels
176
+ : undefined;
177
+ const mapping = labels && typeof labels === 'object' && !Array.isArray(labels)
178
+ ? labels.in
179
+ : undefined;
180
+ if (mapping === undefined)
181
+ return [...COMMON_LABELS];
182
+ if (!mapping || typeof mapping !== 'object' || Array.isArray(mapping))
183
+ throw new Error('labels.in must be an object');
184
+ const dynamic = Object.keys(mapping).sort().map((key) => {
185
+ if (!key || /[\r\n\t]/.test(key))
186
+ throw new Error('labels.in keys must be non-empty single-line values');
187
+ return { name: `in: ${key}`, color: 'BFD4F2', description: `Module label for ${key}` };
188
+ });
189
+ return [...COMMON_LABELS, ...dynamic];
190
+ }
191
+ function configAt(root) {
192
+ try {
193
+ return JSON.parse(fs.readFileSync(path.join(root, '.agents', '.airc.json'), 'utf8'));
194
+ }
195
+ catch {
196
+ return {};
197
+ }
198
+ }
199
+ function baseResult(status, context, extra = {}) {
200
+ return {
201
+ ...platformResult(status, {
202
+ platform: context.platform,
203
+ capabilities: context.capabilities,
204
+ operations: context.operations,
205
+ error: context.error
206
+ }),
207
+ ...extra
208
+ };
209
+ }
210
+ function unsupported(providerType, operation) {
211
+ return {
212
+ code: 'PLATFORM_CAPABILITY_UNSUPPORTED',
213
+ message: `Platform '${providerType}' does not provide ${operation}`,
214
+ retryable: false
215
+ };
216
+ }
217
+ function operationStatus(changed) {
218
+ return changed ? 'applied' : 'no-op';
219
+ }
220
+ function errorStatus(error) {
221
+ return error.code === 'PLATFORM_CAPABILITY_UNSUPPORTED' ? 'degraded' : providerStatus(error);
222
+ }
223
+ function initialLabelsResult(context, labels) {
224
+ return baseResult('degraded', context, {
225
+ operation: 'init-labels',
226
+ labels: {
227
+ commonCount: COMMON_LABELS.length,
228
+ inCount: labels.filter((item) => item.name.startsWith('in:')).length,
229
+ created: [], updated: [], removed: [], skipped: []
230
+ },
231
+ error: context.error || { code: 'PLATFORM_CAPABILITY_UNSUPPORTED', message: 'Label initialization is unavailable', retryable: false }
232
+ });
233
+ }
234
+ function initialMilestonesResult(context, history) {
235
+ return baseResult('degraded', context, {
236
+ operation: 'init-milestones',
237
+ milestones: { baseline: null, history, desired: [], created: [], skipped: [] },
238
+ error: context.error || { code: 'PLATFORM_CAPABILITY_UNSUPPORTED', message: 'Milestone initialization is unavailable', retryable: false }
239
+ });
240
+ }
241
+ function labelsFromReconciliation(initial, value) {
242
+ if (!value)
243
+ return initial.labels;
244
+ return {
245
+ ...initial.labels,
246
+ created: value.created,
247
+ updated: value.updated,
248
+ removed: value.removed,
249
+ skipped: value.skipped
250
+ };
251
+ }
252
+ function milestonesFromInitialization(initial, value) {
253
+ if (!value)
254
+ return initial.milestones;
255
+ return {
256
+ ...initial.milestones,
257
+ created: value.created,
258
+ skipped: value.skipped
259
+ };
260
+ }
261
+ function usableContext(loaded) {
262
+ return loaded.ok && Boolean(loaded.value.context.platform.repository);
263
+ }
264
+ async function initializeLabels(input = {}, options = {}) {
265
+ const loaded = await resolvePlatformProviderContext({ cwd: options.cwd, client: options.client, platformType: options.platformType });
266
+ const context = loaded.ok ? loaded.value.context : loaded.context;
267
+ let definitions;
268
+ try {
269
+ definitions = buildLabelDefinitions(loaded.ok ? configAt(loaded.value.repositoryRoot) : {});
270
+ }
271
+ catch (error) {
272
+ return {
273
+ ...initialLabelsResult(context, []),
274
+ status: 'failed',
275
+ error: { code: 'LABEL_CONFIG_INVALID', message: error instanceof Error ? error.message : String(error), retryable: false }
276
+ };
277
+ }
278
+ const initial = initialLabelsResult(context, definitions);
279
+ if (!usableContext(loaded))
280
+ return { ...initial, error: initial.error || context.error };
281
+ const operation = loaded.value.provider.repositoryMetadata?.reconcileLabels;
282
+ if (!operation)
283
+ return { ...initial, error: unsupported(loaded.value.provider.type, 'repositoryMetadata.reconcileLabels') };
284
+ const reconciled = await operation({
285
+ context: providerOperationContext(loaded.value),
286
+ desired: definitions,
287
+ cleanupStaleIn: input.cleanupStaleIn === true,
288
+ mutation: { idempotencyKey: 'labels:init' }
289
+ });
290
+ if (!reconciled.ok)
291
+ return {
292
+ ...initial,
293
+ status: errorStatus(reconciled.error),
294
+ changed: reconciled.value?.changed || false,
295
+ operations: [{ name: 'reconcile-labels', status: 'failed', reasonCode: reconciled.error.code }],
296
+ labels: labelsFromReconciliation(initial, reconciled.value),
297
+ error: providerError(reconciled.error, 'LABEL_INITIALIZATION_FAILED')
298
+ };
299
+ return {
300
+ ...initial,
301
+ status: operationStatus(reconciled.value.changed),
302
+ changed: reconciled.value.changed,
303
+ operations: [{ name: 'reconcile-labels', status: operationStatus(reconciled.value.changed), reasonCode: null }],
304
+ labels: {
305
+ commonCount: COMMON_LABELS.length,
306
+ inCount: definitions.length - COMMON_LABELS.length,
307
+ created: reconciled.value.created,
308
+ updated: reconciled.value.updated,
309
+ removed: reconciled.value.removed,
310
+ skipped: reconciled.value.skipped
311
+ },
312
+ error: null
313
+ };
314
+ }
315
+ function gitTags(cwd) {
316
+ const output = execFileSync('git', ['tag', '--list', 'v*'], { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
317
+ return output ? output.split(/\r?\n/).filter(Boolean) : [];
318
+ }
319
+ async function initializeMilestones(input = {}, options = {}) {
320
+ const history = input.history === true;
321
+ const loaded = await resolvePlatformProviderContext({ cwd: options.cwd, client: options.client, platformType: options.platformType });
322
+ const context = loaded.ok ? loaded.value.context : loaded.context;
323
+ const initial = initialMilestonesResult(context, history);
324
+ if (!usableContext(loaded))
325
+ return initial;
326
+ let plan;
327
+ try {
328
+ plan = buildMilestonePlan(gitTags(loaded.value.workingDirectory), history);
329
+ }
330
+ catch (error) {
331
+ return {
332
+ ...initial,
333
+ status: 'failed',
334
+ error: { code: 'MILESTONE_TAG_DISCOVERY_FAILED', message: error instanceof Error ? error.message : String(error), retryable: false }
335
+ };
336
+ }
337
+ const operation = loaded.value.provider.repositoryMetadata?.reconcileMilestones;
338
+ if (!operation)
339
+ return {
340
+ ...initial,
341
+ milestones: { ...initial.milestones, baseline: plan.baseline, history, desired: plan.desired.map((item) => item.title) },
342
+ error: unsupported(loaded.value.provider.type, 'repositoryMetadata.reconcileMilestones')
343
+ };
344
+ const reconciled = await operation({
345
+ context: providerOperationContext(loaded.value),
346
+ desired: plan.desired,
347
+ mutation: { idempotencyKey: `milestones:init:${plan.baseline.version}:${history}` }
348
+ });
349
+ if (!reconciled.ok)
350
+ return {
351
+ ...initial,
352
+ status: errorStatus(reconciled.error),
353
+ changed: reconciled.value?.changed || false,
354
+ operations: [{ name: 'reconcile-milestones', status: 'failed', reasonCode: reconciled.error.code }],
355
+ milestones: milestonesFromInitialization({
356
+ ...initial,
357
+ milestones: { ...initial.milestones, baseline: plan.baseline, history, desired: plan.desired.map((item) => item.title) }
358
+ }, reconciled.value),
359
+ error: providerError(reconciled.error, 'MILESTONE_INITIALIZATION_FAILED')
360
+ };
361
+ return {
362
+ ...initial,
363
+ status: operationStatus(reconciled.value.changed),
364
+ changed: reconciled.value.changed,
365
+ operations: [{ name: 'reconcile-milestones', status: operationStatus(reconciled.value.changed), reasonCode: null }],
366
+ milestones: {
367
+ baseline: plan.baseline,
368
+ history,
369
+ desired: plan.desired.map((item) => item.title),
370
+ created: reconciled.value.created,
371
+ skipped: reconciled.value.skipped
372
+ },
373
+ error: null
374
+ };
375
+ }
376
+ export { buildLabelDefinitions, buildMilestonePlan, initializeLabels, initializeMilestones };
377
+ //# sourceMappingURL=repository-metadata.js.map
@@ -0,0 +1,26 @@
1
+ type ResourceIdentityKind = 'id' | 'number' | 'key';
2
+ type ResourceIdentity = {
3
+ kind: 'id';
4
+ value: string;
5
+ } | {
6
+ kind: 'number';
7
+ value: number;
8
+ } | {
9
+ kind: 'key';
10
+ value: string;
11
+ };
12
+ type CanonicalResourceIdentity = ResourceIdentity;
13
+ type PlatformResourceKind = 'issue' | 'pull-request' | 'comment' | 'release';
14
+ type ProviderIdentityDeclaration = Partial<Record<PlatformResourceKind, ResourceIdentityKind>>;
15
+ declare function isResourceIdentity(value: unknown): value is CanonicalResourceIdentity;
16
+ declare function parseResourceIdentity(value: unknown, label?: string): CanonicalResourceIdentity;
17
+ declare function serializeResourceIdentity(identity: ResourceIdentity): string;
18
+ declare function resourceIdentityEquals(left: unknown, right: unknown): boolean;
19
+ declare function primaryIdentityKind(declaration: ProviderIdentityDeclaration | undefined, resourceKind: PlatformResourceKind): ResourceIdentityKind;
20
+ declare function parseResourceToken(token: string, resourceKind: PlatformResourceKind, declaration: ProviderIdentityDeclaration | undefined): ResourceIdentity;
21
+ declare function identityFromRemoteValue(value: unknown, resourceKind: PlatformResourceKind, declaration: ProviderIdentityDeclaration | undefined): ResourceIdentity;
22
+ declare function resourceIdentityNumber(identity: ResourceIdentity | null | undefined): number | null;
23
+ declare function resourceIdentityString(identity: ResourceIdentity | null | undefined): string | null;
24
+ declare function reviewMarker(identity: ResourceIdentity): string;
25
+ export { identityFromRemoteValue, isResourceIdentity, parseResourceIdentity, parseResourceToken, primaryIdentityKind, resourceIdentityEquals, resourceIdentityNumber, resourceIdentityString, reviewMarker, serializeResourceIdentity };
26
+ export type { CanonicalResourceIdentity, PlatformResourceKind, ProviderIdentityDeclaration, ResourceIdentity, ResourceIdentityKind };
@@ -0,0 +1,92 @@
1
+ function identityError(message) {
2
+ return Object.assign(new Error(`PLATFORM_IDENTITY_INVALID: ${message}`), {
3
+ code: 'PLATFORM_IDENTITY_INVALID'
4
+ });
5
+ }
6
+ function isResourceIdentity(value) {
7
+ if (!value || typeof value !== 'object' || Array.isArray(value))
8
+ return false;
9
+ const candidate = value;
10
+ if (Object.keys(candidate).length !== 2 || typeof candidate.kind !== 'string')
11
+ return false;
12
+ if (candidate.kind === 'number') {
13
+ return Number.isSafeInteger(candidate.value) && candidate.value > 0;
14
+ }
15
+ return (candidate.kind === 'id' || candidate.kind === 'key')
16
+ && typeof candidate.value === 'string'
17
+ && candidate.value.length > 0
18
+ && candidate.value.trim() === candidate.value;
19
+ }
20
+ function parseResourceIdentity(value, label = 'identity') {
21
+ if (!isResourceIdentity(value))
22
+ throw identityError(`${label} must contain exactly one valid kind/value pair`);
23
+ if (value.kind === 'number')
24
+ return { kind: 'number', value: value.value };
25
+ if (value.kind === 'id')
26
+ return { kind: 'id', value: value.value };
27
+ return { kind: 'key', value: value.value };
28
+ }
29
+ function serializeResourceIdentity(identity) {
30
+ return JSON.stringify(parseResourceIdentity(identity));
31
+ }
32
+ function resourceIdentityEquals(left, right) {
33
+ return isResourceIdentity(left) && isResourceIdentity(right)
34
+ && left.kind === right.kind && left.value === right.value;
35
+ }
36
+ function primaryIdentityKind(declaration, resourceKind) {
37
+ const kind = declaration?.[resourceKind];
38
+ if (kind !== 'id' && kind !== 'number' && kind !== 'key') {
39
+ throw identityError(`provider does not declare a primary identity for ${resourceKind}`);
40
+ }
41
+ return kind;
42
+ }
43
+ function parseResourceToken(token, resourceKind, declaration) {
44
+ if (typeof token !== 'string' || token.length === 0)
45
+ throw identityError('resource token must be a non-empty string');
46
+ const kind = primaryIdentityKind(declaration, resourceKind);
47
+ if (kind === 'number') {
48
+ if (!/^[1-9]\d*$/u.test(token))
49
+ throw identityError(`${resourceKind} token must be a positive safe integer`);
50
+ const value = Number(token);
51
+ if (!Number.isSafeInteger(value) || value <= 0)
52
+ throw identityError(`${resourceKind} token must be a positive safe integer`);
53
+ return { kind, value };
54
+ }
55
+ const value = token.trim();
56
+ if (!value)
57
+ throw identityError(`${resourceKind} token must not be empty`);
58
+ return { kind, value };
59
+ }
60
+ function identityFromRemoteValue(value, resourceKind, declaration) {
61
+ const kind = primaryIdentityKind(declaration, resourceKind);
62
+ if (isResourceIdentity(value)) {
63
+ if (value.kind !== kind)
64
+ throw identityError(`${resourceKind} response identity kind does not match provider declaration`);
65
+ return value;
66
+ }
67
+ if (kind === 'number') {
68
+ if (typeof value === 'number' && Number.isSafeInteger(value) && value > 0)
69
+ return { kind, value };
70
+ if (typeof value === 'string' && /^[1-9]\d*$/u.test(value))
71
+ return parseResourceToken(value, resourceKind, declaration);
72
+ throw identityError(`${resourceKind} response does not contain a valid number identity`);
73
+ }
74
+ if (typeof value !== 'string' || !value.trim())
75
+ throw identityError(`${resourceKind} response does not contain a valid string identity`);
76
+ return { kind, value: value.trim() };
77
+ }
78
+ function resourceIdentityNumber(identity) {
79
+ return identity?.kind === 'number' ? identity.value : null;
80
+ }
81
+ function resourceIdentityString(identity) {
82
+ return identity && (identity.kind === 'id' || identity.kind === 'key') ? identity.value : null;
83
+ }
84
+ function reviewMarker(identity) {
85
+ const parsed = parseResourceIdentity(identity);
86
+ if (parsed.kind === 'number')
87
+ return `pr${parsed.value}`;
88
+ const encoded = Buffer.from(serializeResourceIdentity(parsed), 'utf8').toString('base64url');
89
+ return `pr:${encoded}`;
90
+ }
91
+ export { identityFromRemoteValue, isResourceIdentity, parseResourceIdentity, parseResourceToken, primaryIdentityKind, resourceIdentityEquals, resourceIdentityNumber, resourceIdentityString, reviewMarker, serializeResourceIdentity };
92
+ //# sourceMappingURL=resource-identity.js.map
@@ -0,0 +1,155 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { resolvePlatformProviderContext } from './context.js';
4
+ import { providerError, providerOperationContext, providerStatus } from './provider-bridge.js';
5
+ import { platformResult } from './types.js';
6
+ function baseResult(operation, status, context, overrides = {}) {
7
+ return {
8
+ ...platformResult(status, {
9
+ platform: context.platform,
10
+ capabilities: context.capabilities,
11
+ operations: context.operations,
12
+ error: context.error,
13
+ changed: false
14
+ }),
15
+ operation,
16
+ alert: null,
17
+ data: null,
18
+ ...overrides
19
+ };
20
+ }
21
+ function unsupported(providerType) {
22
+ return {
23
+ code: 'PLATFORM_CAPABILITY_UNSUPPORTED',
24
+ message: `Platform '${providerType}' does not provide securityAlerts`,
25
+ retryable: false
26
+ };
27
+ }
28
+ function resultStatus(error) {
29
+ return error.code === 'PLATFORM_CAPABILITY_UNSUPPORTED' ? 'degraded' : providerStatus(error);
30
+ }
31
+ function validKind(value) {
32
+ return value === 'dependabot' || value === 'code-scanning';
33
+ }
34
+ function validNumber(value) {
35
+ return Number.isSafeInteger(value) && value > 0;
36
+ }
37
+ function unavailable(operation, context, error) {
38
+ const status = context.status === 'blocked' || context.status === 'failed' ? context.status : 'degraded';
39
+ return baseResult(operation, status, context, {
40
+ error: error || context.error || { code: 'PLATFORM_CAPABILITY_UNSUPPORTED', message: 'Security alert operations are unavailable', retryable: false }
41
+ });
42
+ }
43
+ async function readSecurityAlert(input, options = {}) {
44
+ if (!validKind(input.kind))
45
+ return baseResult('read', 'failed', platformResult('failed'), {
46
+ error: { code: 'SECURITY_KIND_INVALID', message: 'Alert kind must be dependabot or code-scanning', retryable: false }
47
+ });
48
+ if (!validNumber(input.number))
49
+ return baseResult('read', 'failed', platformResult('failed'), {
50
+ error: { code: 'SECURITY_NUMBER_INVALID', message: 'Alert number must be a positive integer', retryable: false }
51
+ });
52
+ const loaded = await resolvePlatformProviderContext({ cwd: options.cwd, client: options.client, platformType: options.platformType });
53
+ const context = loaded.ok ? loaded.value.context : loaded.context;
54
+ if (!loaded.ok || !context.platform.repository)
55
+ return unavailable('read', context);
56
+ const inspect = loaded.value.provider.securityAlerts?.inspect;
57
+ if (!inspect)
58
+ return unavailable('read', context, unsupported(loaded.value.provider.type));
59
+ const result = await inspect({ context: providerOperationContext(loaded.value), kind: input.kind, number: input.number });
60
+ if (!result.ok)
61
+ return {
62
+ ...baseResult('read', resultStatus(result.error), context),
63
+ error: providerError(result.error, 'SECURITY_ALERT_READ_FAILED')
64
+ };
65
+ return {
66
+ ...baseResult('read', 'applied', context, {
67
+ alert: result.value,
68
+ data: result.value.data,
69
+ operations: [{ name: 'inspect-alert', status: 'applied', reasonCode: null }]
70
+ }),
71
+ changed: false,
72
+ error: null
73
+ };
74
+ }
75
+ async function dismissSecurityAlert(input, options = {}) {
76
+ if (!validKind(input.kind))
77
+ return baseResult('dismiss', 'failed', platformResult('failed'), {
78
+ error: { code: 'SECURITY_KIND_INVALID', message: 'Alert kind must be dependabot or code-scanning', retryable: false }
79
+ });
80
+ if (!validNumber(input.number))
81
+ return baseResult('dismiss', 'failed', platformResult('failed'), {
82
+ error: { code: 'SECURITY_NUMBER_INVALID', message: 'Alert number must be a positive integer', retryable: false }
83
+ });
84
+ if (!input.reason || typeof input.comment !== 'string')
85
+ return baseResult('dismiss', 'failed', platformResult('failed'), {
86
+ error: { code: 'SECURITY_DISMISS_INPUT_INVALID', message: 'Dismissal reason and comment are required', retryable: false }
87
+ });
88
+ const loaded = await resolvePlatformProviderContext({ cwd: options.cwd, client: options.client, platformType: options.platformType });
89
+ const context = loaded.ok ? loaded.value.context : loaded.context;
90
+ if (!loaded.ok || !context.platform.repository)
91
+ return unavailable('dismiss', context);
92
+ const inspect = loaded.value.provider.securityAlerts?.inspect;
93
+ const dismiss = loaded.value.provider.securityAlerts?.dismiss;
94
+ if (!inspect || !dismiss)
95
+ return unavailable('dismiss', context, unsupported(loaded.value.provider.type));
96
+ const current = await inspect({ context: providerOperationContext(loaded.value), kind: input.kind, number: input.number });
97
+ if (!current.ok)
98
+ return {
99
+ ...baseResult('dismiss', resultStatus(current.error), context),
100
+ error: providerError(current.error, 'SECURITY_ALERT_READ_FAILED')
101
+ };
102
+ if (current.value.state === 'dismissed' || current.value.state === 'fixed')
103
+ return {
104
+ ...baseResult('dismiss', 'no-op', context, {
105
+ alert: current.value,
106
+ data: current.value.data,
107
+ operations: [{ name: 'inspect-alert', status: 'no-op', reasonCode: 'ALREADY_CLOSED' }]
108
+ }),
109
+ error: null
110
+ };
111
+ if (current.value.state !== 'open')
112
+ return {
113
+ ...baseResult('dismiss', 'failed', context, {
114
+ alert: current.value,
115
+ data: current.value.data,
116
+ operations: [{ name: 'inspect-alert', status: 'failed', reasonCode: 'INVALID_STATE' }]
117
+ }),
118
+ error: { code: 'SECURITY_RESPONSE_INVALID', message: 'The platform returned an alert without a valid state', retryable: false }
119
+ };
120
+ const changed = await dismiss({
121
+ context: providerOperationContext(loaded.value),
122
+ kind: input.kind,
123
+ number: input.number,
124
+ reason: input.reason,
125
+ comment: input.comment,
126
+ mutation: { idempotencyKey: `security-alert:dismiss:${input.kind}:${input.number}` }
127
+ });
128
+ if (!changed.ok)
129
+ return {
130
+ ...baseResult('dismiss', resultStatus(changed.error), context, {
131
+ alert: current.value,
132
+ data: current.value.data,
133
+ operations: [{ name: 'dismiss-alert', status: 'failed', reasonCode: null }]
134
+ }),
135
+ error: providerError(changed.error, 'SECURITY_ALERT_DISMISS_FAILED')
136
+ };
137
+ return {
138
+ ...baseResult('dismiss', changed.value.changed ? 'applied' : 'no-op', context, {
139
+ operations: [{ name: 'dismiss-alert', status: changed.value.changed ? 'applied' : 'no-op', reasonCode: null }]
140
+ }),
141
+ changed: changed.value.changed,
142
+ error: null
143
+ };
144
+ }
145
+ function readCommentFile(commentFile, cwd = process.cwd()) {
146
+ try {
147
+ const requested = path.resolve(cwd, commentFile);
148
+ return { ok: true, value: fs.readFileSync(requested, 'utf8') };
149
+ }
150
+ catch {
151
+ return { ok: false, error: { code: 'SECURITY_DISMISS_INPUT_INVALID', message: 'Dismissal comment file could not be read', retryable: false } };
152
+ }
153
+ }
154
+ export { dismissSecurityAlert, readCommentFile, readSecurityAlert };
155
+ //# sourceMappingURL=security-alerts.js.map