@fitlab-ai/agent-infra 0.9.14 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (354) hide show
  1. package/README.md +10 -0
  2. package/README.zh-CN.md +10 -0
  3. package/bin/internal-cli.sh +45 -0
  4. package/dist/bin/internal-cli.js +93 -30
  5. package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +165 -27
  6. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +9 -4
  7. package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +43 -3
  8. package/dist/lib/defaults.json +103 -103
  9. package/dist/lib/fs/durable-write.js +39 -0
  10. package/dist/lib/fs/file-lock.js +111 -0
  11. package/dist/lib/host-control/audit.js +19 -0
  12. package/dist/lib/host-control/client.js +142 -0
  13. package/dist/lib/host-control/command.js +49 -0
  14. package/dist/lib/host-control/path.js +160 -0
  15. package/dist/lib/host-control/secure-fs.js +140 -0
  16. package/dist/lib/host-control/server.js +159 -0
  17. package/dist/lib/host-control/service.js +112 -0
  18. package/dist/lib/init.js +11 -2
  19. package/dist/lib/internal/cli-route-inventory.js +4 -2
  20. package/dist/lib/internal/codex-lifecycle.js +6 -6
  21. package/dist/lib/internal/demo-promotion.js +322 -0
  22. package/dist/lib/internal/demo-transcript.js +454 -0
  23. package/dist/lib/internal/host-control.js +28 -0
  24. package/dist/lib/internal/manual-validation.js +331 -0
  25. package/dist/lib/internal/platform-pr.js +18 -4
  26. package/dist/lib/internal/release-workflow.js +63 -84
  27. package/dist/lib/internal/sandbox-control.js +149 -2
  28. package/dist/lib/internal/task-artifact.js +16 -263
  29. package/dist/lib/internal/task-create.js +6 -5
  30. package/dist/lib/internal/task-event.js +37 -37
  31. package/dist/lib/internal/task-lifecycle.js +2 -2
  32. package/dist/lib/internal/task-operation-registry.js +101 -4
  33. package/dist/lib/internal/task-review.js +11 -56
  34. package/dist/lib/internal/task-validate.js +30 -10
  35. package/dist/lib/owned-path.js +33 -0
  36. package/dist/lib/platform/check-status.js +11 -0
  37. package/dist/lib/platform/comment-safety.js +4 -1
  38. package/dist/lib/platform/completion-backfill.js +1 -1
  39. package/dist/lib/platform/github-data.js +241 -0
  40. package/dist/lib/platform/github-provider.js +15 -20
  41. package/dist/lib/platform/issue-comments.js +18 -12
  42. package/dist/lib/platform/issues.js +2 -180
  43. package/dist/lib/platform/pr-change-report.js +5 -4
  44. package/dist/lib/platform/pr-checks.js +12 -65
  45. package/dist/lib/platform/pr-summary.js +117 -33
  46. package/dist/lib/platform/pull-requests.js +5 -108
  47. package/dist/lib/platform/snapshots.js +2 -0
  48. package/dist/lib/platform/task-identities.js +2 -9
  49. package/dist/lib/platform/verification-sync.js +132 -143
  50. package/dist/lib/pr-review/evidence-grading.js +4 -8
  51. package/dist/lib/release/workflow.js +1 -1
  52. package/dist/lib/sandbox/commands/create.js +7 -2
  53. package/dist/lib/sandbox/commands/rm.js +19 -1511
  54. package/dist/lib/sandbox/control/audit.js +203 -0
  55. package/dist/lib/sandbox/control/client.js +93 -54
  56. package/dist/lib/sandbox/control/executor.js +129 -65
  57. package/dist/lib/sandbox/control/finalization-response.js +27 -0
  58. package/dist/lib/sandbox/control/identity-sentinel.js +107 -0
  59. package/dist/lib/sandbox/control/lifecycle.js +36 -2
  60. package/dist/lib/sandbox/control/native-file-lock.js +6 -98
  61. package/dist/lib/sandbox/control/protocol.js +55 -4
  62. package/dist/lib/sandbox/control/server.js +518 -127
  63. package/dist/lib/sandbox/control/state.js +64 -0
  64. package/dist/lib/sandbox/control/task-workflow.js +74 -0
  65. package/dist/lib/sandbox/control/workflow-executor.js +89 -0
  66. package/dist/lib/sandbox/index.js +1 -2
  67. package/dist/lib/sandbox/recovery.js +28 -4
  68. package/dist/lib/sandbox/removal.js +822 -0
  69. package/dist/lib/sandbox/task-cleanup.js +217 -0
  70. package/dist/lib/sandbox/workspace-identity.js +17 -1
  71. package/dist/lib/sandbox/workspace-view.js +13 -14
  72. package/dist/lib/task/activity-intent.js +2 -1
  73. package/dist/lib/task/activity-log.js +30 -24
  74. package/dist/lib/task/artifact-command.js +79 -0
  75. package/dist/lib/task/artifact-lifecycle.js +30 -28
  76. package/dist/lib/task/artifact-name.js +36 -0
  77. package/dist/lib/task/artifact-operations.js +29 -289
  78. package/dist/lib/task/artifact-receipts.js +3 -15
  79. package/dist/lib/task/artifact-recovery.js +430 -0
  80. package/dist/lib/task/artifact-repair-intent.js +134 -29
  81. package/dist/lib/task/artifact-schema.js +6 -14
  82. package/dist/lib/task/capabilities.js +12 -19
  83. package/dist/lib/task/codex-orchestration.js +71 -25
  84. package/dist/lib/task/commit-identity.js +28 -0
  85. package/dist/lib/task/commit-operation.js +33 -20
  86. package/dist/lib/task/control-authority.js +403 -6
  87. package/dist/lib/task/control-recovery.js +140 -0
  88. package/dist/lib/task/create-service.js +1 -8
  89. package/dist/lib/task/create.js +62 -9
  90. package/dist/lib/task/decision-details.js +2 -46
  91. package/dist/lib/task/delegation-receipts.js +64 -3
  92. package/dist/lib/task/events.js +275 -22
  93. package/dist/lib/task/finalization-state.js +9 -0
  94. package/dist/lib/task/human-override.js +8 -14
  95. package/dist/lib/task/implementation-inputs.js +3 -3
  96. package/dist/lib/task/intermediate-cleanup.js +441 -0
  97. package/dist/lib/task/invalidation.js +18 -65
  98. package/dist/lib/task/ledger-intents.js +7 -22
  99. package/dist/lib/task/ledger.js +1 -3
  100. package/dist/lib/task/lifecycle-recovery.js +549 -0
  101. package/dist/lib/task/lifecycle.js +31 -4
  102. package/dist/lib/task/local-artifact-finalization.js +197 -197
  103. package/dist/lib/task/manual-validation-completion.js +26 -0
  104. package/dist/lib/task/manual-validation-evidence.js +130 -0
  105. package/dist/lib/task/manual-validation-receipt.js +105 -0
  106. package/dist/lib/task/manual-validation-shared.js +40 -0
  107. package/dist/lib/task/manual-validation-transaction.js +243 -0
  108. package/dist/lib/task/markdown.js +47 -0
  109. package/dist/lib/task/orchestration.js +66 -19
  110. package/dist/lib/task/pr-delivery-fact.js +12 -56
  111. package/dist/lib/task/qualification-audit.js +20 -34
  112. package/dist/lib/task/recovery-warning.js +19 -0
  113. package/dist/lib/task/review-artifacts.js +2 -18
  114. package/dist/lib/task/review-command.js +26 -0
  115. package/dist/lib/task/review-finalization.js +175 -216
  116. package/dist/lib/task/review-fingerprint.js +2 -2
  117. package/dist/lib/task/sections.js +34 -56
  118. package/dist/lib/task/short-id.js +15 -7
  119. package/dist/lib/task/task-execution-lock.js +1 -1
  120. package/dist/lib/task/verification-engine.js +119 -337
  121. package/dist/lib/task/verification.js +1 -1
  122. package/dist/lib/task/workflow-command.js +16 -0
  123. package/dist/lib/task/workflow-warning-intents.js +0 -16
  124. package/dist/lib/task/workflow-warnings.js +28 -2
  125. package/dist/lib/update.js +2 -0
  126. package/dist/lib/version.js +1 -11
  127. package/dist/lifecycle-build-manifest.json +3 -3
  128. package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +223 -33
  129. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +10 -4
  130. package/lib/agent-clients/adapters/codex-lifecycle/store.ts +55 -3
  131. package/lib/fs/durable-write.ts +30 -0
  132. package/lib/fs/file-lock.ts +113 -0
  133. package/lib/host-control/audit.ts +22 -0
  134. package/lib/host-control/client.ts +172 -0
  135. package/lib/host-control/command.ts +60 -0
  136. package/lib/host-control/path.ts +167 -0
  137. package/lib/host-control/secure-fs.ts +135 -0
  138. package/lib/host-control/server.ts +180 -0
  139. package/lib/host-control/service.ts +133 -0
  140. package/lib/init.ts +15 -2
  141. package/lib/internal/cli-route-inventory.ts +4 -2
  142. package/lib/internal/codex-lifecycle.ts +6 -6
  143. package/lib/internal/demo-promotion.ts +354 -0
  144. package/lib/internal/demo-transcript.ts +419 -0
  145. package/lib/internal/host-control.ts +28 -0
  146. package/lib/internal/manual-validation.ts +315 -0
  147. package/lib/internal/platform-pr.ts +15 -4
  148. package/lib/internal/release-workflow.ts +74 -82
  149. package/lib/internal/sandbox-control.ts +162 -1
  150. package/lib/internal/task-artifact.ts +14 -217
  151. package/lib/internal/task-create.ts +5 -5
  152. package/lib/internal/task-event.ts +20 -11
  153. package/lib/internal/task-lifecycle.ts +4 -3
  154. package/lib/internal/task-operation-registry.ts +111 -4
  155. package/lib/internal/task-review.ts +9 -54
  156. package/lib/internal/task-validate.ts +26 -10
  157. package/lib/owned-path.ts +26 -0
  158. package/lib/platform/check-status.ts +9 -0
  159. package/lib/platform/comment-safety.ts +5 -0
  160. package/lib/platform/completion-backfill.ts +1 -1
  161. package/lib/platform/github-data.ts +322 -0
  162. package/lib/platform/github-provider.ts +15 -20
  163. package/lib/platform/issue-comments.ts +21 -14
  164. package/lib/platform/issues.ts +5 -246
  165. package/lib/platform/pr-change-report.ts +7 -5
  166. package/lib/platform/pr-checks.ts +13 -77
  167. package/lib/platform/pr-summary.ts +123 -35
  168. package/lib/platform/pull-requests.ts +6 -173
  169. package/lib/platform/snapshots.ts +53 -0
  170. package/lib/platform/task-identities.ts +3 -14
  171. package/lib/platform/verification-sync.ts +150 -156
  172. package/lib/pr-review/evidence-grading.ts +4 -9
  173. package/lib/release/workflow.ts +3 -3
  174. package/lib/sandbox/commands/create.ts +7 -6
  175. package/lib/sandbox/commands/rm.ts +21 -1895
  176. package/lib/sandbox/control/audit.ts +253 -0
  177. package/lib/sandbox/control/client.ts +109 -66
  178. package/lib/sandbox/control/executor.ts +134 -74
  179. package/lib/sandbox/control/finalization-response.ts +29 -0
  180. package/lib/sandbox/control/identity-sentinel.ts +137 -0
  181. package/lib/sandbox/control/lifecycle.ts +45 -3
  182. package/lib/sandbox/control/native-file-lock.ts +6 -107
  183. package/lib/sandbox/control/protocol.ts +80 -6
  184. package/lib/sandbox/control/server.ts +567 -132
  185. package/lib/sandbox/control/state.ts +86 -0
  186. package/lib/sandbox/control/task-workflow.ts +95 -0
  187. package/lib/sandbox/control/workflow-executor.ts +92 -0
  188. package/lib/sandbox/index.ts +1 -2
  189. package/lib/sandbox/recovery.ts +28 -5
  190. package/lib/sandbox/removal.ts +1142 -0
  191. package/lib/sandbox/task-cleanup.ts +209 -0
  192. package/lib/sandbox/workspace-identity.ts +19 -3
  193. package/lib/sandbox/workspace-view.ts +17 -15
  194. package/lib/task/activity-intent.ts +2 -2
  195. package/lib/task/activity-log.ts +27 -19
  196. package/lib/task/artifact-command.ts +85 -0
  197. package/lib/task/artifact-lifecycle.ts +31 -26
  198. package/lib/task/artifact-name.ts +55 -0
  199. package/lib/task/artifact-operations.ts +34 -310
  200. package/lib/task/artifact-receipts.ts +3 -14
  201. package/lib/task/artifact-recovery.ts +519 -0
  202. package/lib/task/artifact-repair-intent.ts +162 -33
  203. package/lib/task/artifact-schema.ts +5 -34
  204. package/lib/task/capabilities.ts +13 -22
  205. package/lib/task/codex-orchestration.ts +85 -24
  206. package/lib/task/commit-identity.ts +31 -0
  207. package/lib/task/commit-operation.ts +37 -20
  208. package/lib/task/control-authority.ts +540 -10
  209. package/lib/task/control-recovery.ts +186 -0
  210. package/lib/task/create-service.ts +1 -10
  211. package/lib/task/create.ts +63 -8
  212. package/lib/task/decision-details.ts +3 -71
  213. package/lib/task/delegation-receipts.ts +73 -2
  214. package/lib/task/events.ts +309 -24
  215. package/lib/task/finalization-state.ts +11 -0
  216. package/lib/task/human-override.ts +8 -16
  217. package/lib/task/implementation-inputs.ts +3 -3
  218. package/lib/task/intermediate-cleanup.ts +493 -0
  219. package/lib/task/invalidation.ts +18 -62
  220. package/lib/task/ledger-intents.ts +7 -24
  221. package/lib/task/ledger.ts +1 -3
  222. package/lib/task/lifecycle-recovery.ts +691 -0
  223. package/lib/task/lifecycle.ts +30 -5
  224. package/lib/task/local-artifact-finalization.ts +244 -234
  225. package/lib/task/manual-validation-completion.ts +40 -0
  226. package/lib/task/manual-validation-evidence.ts +209 -0
  227. package/lib/task/manual-validation-receipt.ts +156 -0
  228. package/lib/task/manual-validation-shared.ts +50 -0
  229. package/lib/task/manual-validation-transaction.ts +304 -0
  230. package/lib/task/markdown.ts +70 -0
  231. package/lib/task/orchestration.ts +84 -19
  232. package/lib/task/pr-delivery-fact.ts +15 -62
  233. package/lib/task/qualification-audit.ts +22 -33
  234. package/lib/task/recovery-warning.ts +21 -0
  235. package/lib/task/review-artifacts.ts +1 -20
  236. package/lib/task/review-command.ts +24 -0
  237. package/lib/task/review-finalization.ts +183 -292
  238. package/lib/task/review-fingerprint.ts +2 -2
  239. package/lib/task/sections.ts +33 -54
  240. package/lib/task/short-id.ts +27 -5
  241. package/lib/task/task-execution-lock.ts +1 -1
  242. package/lib/task/verification-engine.ts +113 -383
  243. package/lib/task/verification-types.ts +15 -0
  244. package/lib/task/verification.ts +1 -1
  245. package/lib/task/workflow-command.ts +17 -0
  246. package/lib/task/workflow-warning-intents.ts +0 -13
  247. package/lib/task/workflow-warnings.ts +21 -2
  248. package/lib/update.ts +6 -0
  249. package/lib/version.ts +1 -15
  250. package/package.json +6 -6
  251. package/templates/.agents/hooks/lifecycle-delegation.js +6 -6
  252. package/templates/.agents/rules/create-issue.en.md +1 -1
  253. package/templates/.agents/rules/create-issue.zh-CN.md +1 -1
  254. package/templates/.agents/rules/issue-sync.en.md +4 -2
  255. package/templates/.agents/rules/issue-sync.zh-CN.md +4 -3
  256. package/templates/.agents/rules/local-artifact-repair.en.md +46 -39
  257. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +43 -36
  258. package/templates/.agents/rules/testing-discipline.en.md +2 -0
  259. package/templates/.agents/rules/testing-discipline.zh-CN.md +2 -0
  260. package/templates/.agents/scripts/package.json +3 -0
  261. package/templates/.agents/skills/analyze-task/SKILL.en.md +6 -6
  262. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +6 -6
  263. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -1
  264. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -1
  265. package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
  266. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
  267. package/templates/.agents/skills/block-task/config/verify.json +1 -1
  268. package/templates/.agents/skills/cancel-task/SKILL.en.md +3 -3
  269. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +3 -3
  270. package/templates/.agents/skills/cancel-task/config/verify.json +1 -1
  271. package/templates/.agents/skills/code-task/SKILL.en.md +7 -7
  272. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +7 -7
  273. package/templates/.agents/skills/code-task/config/verify.en.json +1 -1
  274. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -1
  275. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +1 -1
  276. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +1 -1
  277. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +33 -21
  278. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +33 -21
  279. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
  280. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
  281. package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +2 -0
  282. package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +2 -0
  283. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +16 -7
  284. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +16 -7
  285. package/templates/.agents/skills/complete-task/SKILL.en.md +3 -3
  286. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +3 -3
  287. package/templates/.agents/skills/complete-task/config/verify.en.json +2 -2
  288. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +2 -2
  289. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +1 -1
  290. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +1 -1
  291. package/templates/.agents/skills/create-pr/SKILL.en.md +2 -2
  292. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +2 -2
  293. package/templates/.agents/skills/create-pr/config/verify.json +1 -1
  294. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +2 -2
  295. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +2 -2
  296. package/templates/.agents/skills/create-task/SKILL.en.md +5 -5
  297. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +5 -5
  298. package/templates/.agents/skills/create-task/config/verify.json +1 -1
  299. package/templates/.agents/skills/import-issue/SKILL.en.md +8 -8
  300. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +8 -8
  301. package/templates/.agents/skills/import-issue/config/verify.json +2 -2
  302. package/templates/.agents/skills/plan-task/SKILL.en.md +4 -4
  303. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +4 -4
  304. package/templates/.agents/skills/plan-task/config/verify.en.json +1 -1
  305. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -1
  306. package/templates/.agents/skills/release/SKILL.en.md +7 -3
  307. package/templates/.agents/skills/release/SKILL.zh-CN.md +7 -3
  308. package/templates/.agents/skills/restore-task/SKILL.en.md +2 -2
  309. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +2 -2
  310. package/templates/.agents/skills/restore-task/config/verify.json +1 -1
  311. package/templates/.agents/skills/review-analysis/SKILL.en.md +2 -2
  312. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +2 -2
  313. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -1
  314. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -1
  315. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +7 -7
  316. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +6 -6
  317. package/templates/.agents/skills/review-code/SKILL.en.md +2 -2
  318. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +2 -2
  319. package/templates/.agents/skills/review-code/config/verify.en.json +1 -1
  320. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -1
  321. package/templates/.agents/skills/review-code/reference/report-template.en.md +12 -12
  322. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +12 -12
  323. package/templates/.agents/skills/review-plan/SKILL.en.md +2 -2
  324. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +2 -2
  325. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -1
  326. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -1
  327. package/templates/.agents/skills/review-plan/reference/report-template.en.md +7 -7
  328. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +7 -7
  329. package/templates/.agents/skills/review-pr/config/verify.en.json +1 -1
  330. package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +1 -1
  331. package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +3 -3
  332. package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +3 -3
  333. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +20 -3
  334. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +20 -3
  335. package/templates/.agents/skills/run-manual-validation/config/verify.en.json +1 -1
  336. package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +1 -1
  337. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +4 -1
  338. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +4 -1
  339. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -0
  340. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -0
  341. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  342. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  343. package/templates/.agents/skills/test/SKILL.en.md +17 -6
  344. package/templates/.agents/skills/test/SKILL.zh-CN.md +17 -6
  345. package/templates/.agents/templates/task.en.md +1 -1
  346. package/templates/.agents/templates/task.zh-CN.md +1 -1
  347. package/templates/.claude/commands/import-issue.en.md +1 -1
  348. package/templates/.claude/commands/import-issue.zh-CN.md +1 -1
  349. package/templates/.claude/commands/restore-task.en.md +1 -1
  350. package/templates/.claude/commands/restore-task.zh-CN.md +1 -1
  351. package/templates/.claude/commands/run-manual-validation.en.md +1 -1
  352. package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
  353. package/dist/lib/platform/adapters.js +0 -56
  354. package/lib/platform/adapters.ts +0 -197
@@ -0,0 +1,241 @@
1
+ import { checkStatusBucket } from './check-status.js';
2
+ const ISSUE_FIELDS_QUERY = `query($owner:String!,$name:String!,$number:Int!){repository(owner:$owner,name:$name){issue(number:$number){id issueType{id name pinnedFields{__typename ... on IssueFieldSingleSelect{id name options{id name}} ... on IssueFieldDate{id name} ... on IssueFieldText{id name} ... on IssueFieldNumber{id name}}} issueFieldValues(first:50){nodes{__typename ... on IssueFieldSingleSelectValue{name optionId field{... on IssueFieldSingleSelect{id name}}} ... on IssueFieldDateValue{value field{... on IssueFieldDate{id name}}} ... on IssueFieldTextValue{value field{... on IssueFieldText{id name}}} ... on IssueFieldNumberValue{value field{... on IssueFieldNumber{id name}}}}}}}}`;
3
+ function normalizeIssue(remote, repository, fallbackNumber) {
4
+ const number = Number.isInteger(remote.number) && Number(remote.number) > 0
5
+ ? Number(remote.number)
6
+ : fallbackNumber;
7
+ if (!number || !Number.isSafeInteger(number) || remote.pull_request)
8
+ return null;
9
+ return {
10
+ repository,
11
+ number,
12
+ databaseId: Number.isInteger(remote.id) ? Number(remote.id) : null,
13
+ nodeId: remote.node_id || `issue-${number}`,
14
+ url: remote.html_url || `https://github.com/${repository}/issues/${number}`,
15
+ state: String(remote.state || '').toLowerCase() === 'closed' ? 'closed' : 'open',
16
+ title: remote.title || '',
17
+ body: remote.body || '',
18
+ labels: (remote.labels || []).map((label) => typeof label === 'string' ? label : label.name || '').filter(Boolean).sort(),
19
+ assignees: (remote.assignees || []).map((assignee) => assignee.login || '').filter(Boolean).sort(),
20
+ milestone: remote.milestone?.title || null,
21
+ issueType: remote.type?.name || null,
22
+ fields: {}
23
+ };
24
+ }
25
+ function fieldKind(value) {
26
+ if (value.__typename === 'IssueFieldSingleSelect' || value.__typename === 'IssueFieldSingleSelectValue')
27
+ return 'single-select';
28
+ if (value.__typename === 'IssueFieldDate' || value.__typename === 'IssueFieldDateValue')
29
+ return 'date';
30
+ if (value.__typename === 'IssueFieldText' || value.__typename === 'IssueFieldTextValue')
31
+ return 'text';
32
+ if (value.__typename === 'IssueFieldNumber' || value.__typename === 'IssueFieldNumberValue')
33
+ return 'number';
34
+ return null;
35
+ }
36
+ function normalizeFieldSchemas(value) {
37
+ if (!Array.isArray(value))
38
+ return [];
39
+ return value.flatMap((raw) => {
40
+ const item = raw;
41
+ const kind = fieldKind(item);
42
+ return item.id && item.name && kind ? [{
43
+ id: item.id,
44
+ name: item.name,
45
+ kind,
46
+ options: (item.options || []).flatMap((option) => option.id && option.name ? [{ id: option.id, name: option.name }] : [])
47
+ }] : [];
48
+ });
49
+ }
50
+ function normalizeCurrentFields(value) {
51
+ const issue = value?.data?.repository?.issue;
52
+ const type = issue?.issueType?.name ? {
53
+ id: issue.issueType.id || issue.issueType.name,
54
+ name: issue.issueType.name,
55
+ fields: normalizeFieldSchemas(issue.issueType.pinnedFields)
56
+ } : null;
57
+ const values = (issue?.issueFieldValues?.nodes || []).flatMap((raw) => {
58
+ const item = raw;
59
+ const kind = fieldKind(item);
60
+ const value = kind === 'single-select' ? item.name : item.value;
61
+ return item.field?.name && kind && value !== undefined
62
+ ? [{ id: item.field.id || item.field.name, name: item.field.name, kind, value: value ?? null }]
63
+ : [];
64
+ });
65
+ return { issueId: issue?.id || null, type, values };
66
+ }
67
+ function graphState(client, repository, issue, cwd) {
68
+ const [owner, name] = repository.split('/');
69
+ if (!owner || !name)
70
+ return null;
71
+ const current = client.json([
72
+ 'api', 'graphql', '-f', `query=${ISSUE_FIELDS_QUERY}`, '-F', `owner=${owner}`, '-F', `name=${name}`, '-F', `number=${issue}`
73
+ ], { cwd });
74
+ if (!current.ok)
75
+ return null;
76
+ return normalizeCurrentFields(current.value);
77
+ }
78
+ function fetchIssue(client, repository, issue, cwd) {
79
+ return client.json(['api', `repos/${repository}/issues/${issue}`], { cwd });
80
+ }
81
+ function inspectGitHubIssue(client, repository, issue, cwd) {
82
+ const fetched = fetchIssue(client, repository, issue, cwd);
83
+ if (!fetched.ok)
84
+ return fetched;
85
+ const snapshot = normalizeIssue(fetched.value, repository, issue);
86
+ return snapshot
87
+ ? { ok: true, value: snapshot }
88
+ : { ok: false, error: { code: 'ISSUE_IDENTITY_INVALID', message: 'Remote resource is not a valid Issue', retryable: false } };
89
+ }
90
+ const CLOSING_PULL_REQUESTS_QUERY = `query($owner:String!,$name:String!,$issue:Int!,$cursor:String){repository(owner:$owner,name:$name){issue(number:$issue){closedByPullRequestsReferences(first:100,after:$cursor){nodes{number id url state title body isDraft headRefName headRefOid headRepository{nameWithOwner} baseRefName baseRefOid baseRepository{nameWithOwner} mergedAt mergeCommit{oid} labels(first:100){nodes{name}} assignees(first:100){nodes{login}} milestone{title}} pageInfo{hasNextPage endCursor}}}}}`;
91
+ function normalizePullRequest(remote, repository) {
92
+ const number = Number(remote.number);
93
+ const headRepository = remote.head?.repo?.full_name;
94
+ const baseRepository = remote.base?.repo?.full_name;
95
+ if (!Number.isInteger(number) || number <= 0 || !remote.node_id || !remote.html_url ||
96
+ !remote.head?.ref || !remote.head.sha || !headRepository || !remote.base?.ref || !baseRepository)
97
+ return null;
98
+ const mergeabilityDetail = remote.mergeable_state?.trim().toLowerCase() || null;
99
+ const mergeability = remote.mergeable === false
100
+ ? { state: 'conflicting', detail: mergeabilityDetail }
101
+ : remote.mergeable === true && mergeabilityDetail !== 'dirty'
102
+ ? { state: 'mergeable', detail: mergeabilityDetail }
103
+ : { state: 'unknown', detail: mergeabilityDetail };
104
+ return {
105
+ repository,
106
+ number,
107
+ nodeId: remote.node_id,
108
+ url: remote.html_url,
109
+ state: remote.state === 'closed' ? 'closed' : 'open',
110
+ title: remote.title || '',
111
+ body: remote.body || '',
112
+ draft: Boolean(remote.draft),
113
+ head: { repository: headRepository, ref: remote.head.ref, sha: remote.head.sha },
114
+ base: { repository: baseRepository, ref: remote.base.ref, sha: remote.base.sha || '' },
115
+ mergedAt: remote.merged_at || null,
116
+ mergeCommitSha: remote.merge_commit_sha || null,
117
+ labels: (remote.labels || []).map((label) => typeof label === 'string' ? label : label.name || '').filter(Boolean).sort(),
118
+ assignees: (remote.assignees || []).map((assignee) => assignee.login || '').filter(Boolean).sort(),
119
+ milestone: remote.milestone?.title || null,
120
+ mergeability
121
+ };
122
+ }
123
+ function normalizeClosingPullRequest(node, repository) {
124
+ return normalizePullRequest({
125
+ number: node.number,
126
+ node_id: node.id,
127
+ html_url: node.url,
128
+ state: node.state === 'OPEN' ? 'open' : 'closed',
129
+ title: node.title,
130
+ body: node.body,
131
+ draft: node.isDraft,
132
+ head: { ref: node.headRefName, sha: node.headRefOid, repo: node.headRepository ? { full_name: node.headRepository.nameWithOwner } : null },
133
+ base: { ref: node.baseRefName, sha: node.baseRefOid, repo: node.baseRepository ? { full_name: node.baseRepository.nameWithOwner } : null },
134
+ merged_at: node.mergedAt,
135
+ merge_commit_sha: node.mergeCommit?.oid,
136
+ labels: node.labels?.nodes,
137
+ assignees: node.assignees?.nodes,
138
+ milestone: node.milestone
139
+ }, repository);
140
+ }
141
+ function inspectGitHubIssueClosingChangeRequests(client, repository, issueNumber, cwd) {
142
+ const [owner, name] = repository.split('/');
143
+ if (!owner || !name || !Number.isInteger(issueNumber) || issueNumber <= 0)
144
+ return {
145
+ ok: false,
146
+ error: { code: 'PR_IDENTITY_INVALID', message: 'Repository or Issue identity is invalid', retryable: false }
147
+ };
148
+ const candidates = [];
149
+ let cursor = null;
150
+ for (;;) {
151
+ const args = [
152
+ 'api', 'graphql', '-f', `query=${CLOSING_PULL_REQUESTS_QUERY}`,
153
+ '-F', `owner=${owner}`, '-F', `name=${name}`, '-F', `issue=${issueNumber}`
154
+ ];
155
+ if (cursor)
156
+ args.push('-F', `cursor=${cursor}`);
157
+ const response = client.json(args, { cwd });
158
+ if (!response.ok)
159
+ return response;
160
+ const connection = response.value?.data?.repository?.issue?.closedByPullRequestsReferences;
161
+ if (!connection || !Array.isArray(connection.nodes) || !connection.pageInfo)
162
+ return {
163
+ ok: false,
164
+ error: { code: 'PR_IDENTITY_INVALID', message: 'Closing pull request response is incomplete', retryable: false }
165
+ };
166
+ for (const node of connection.nodes) {
167
+ const normalized = normalizeClosingPullRequest(node, repository);
168
+ if (!normalized)
169
+ return {
170
+ ok: false,
171
+ error: { code: 'PR_IDENTITY_INVALID', message: 'Closing pull request identity is incomplete', retryable: false }
172
+ };
173
+ candidates.push(normalized);
174
+ }
175
+ if (!connection.pageInfo.hasNextPage)
176
+ return { ok: true, value: candidates };
177
+ if (!connection.pageInfo.endCursor || connection.pageInfo.endCursor === cursor)
178
+ return {
179
+ ok: false,
180
+ error: { code: 'PR_IDENTITY_INVALID', message: 'Closing pull request pagination cursor is invalid', retryable: false }
181
+ };
182
+ cursor = connection.pageInfo.endCursor;
183
+ }
184
+ }
185
+ function inspectGitHubPullRequest(client, repository, number, cwd) {
186
+ const fetched = client.json(['api', `repos/${repository}/pulls/${number}`], { cwd });
187
+ if (!fetched.ok)
188
+ return fetched;
189
+ const pullRequest = normalizePullRequest(fetched.value, repository);
190
+ return pullRequest
191
+ ? { ok: true, value: pullRequest }
192
+ : { ok: false, error: { code: 'PR_IDENTITY_INVALID', message: 'Remote resource is not a valid pull request', retryable: false } };
193
+ }
194
+ function normalizeGitHubChecks(value) {
195
+ if (!Array.isArray(value))
196
+ return [];
197
+ return value.flatMap((raw) => {
198
+ const item = raw;
199
+ const name = String(item.name || item.context || '');
200
+ return name ? [{
201
+ name,
202
+ status: checkStatusBucket(String(item.bucket || item.status || item.conclusion || item.state || '')),
203
+ conclusion: item.conclusion ? String(item.conclusion) : item.state ? String(item.state) : null,
204
+ detailsUrl: item.link ? String(item.link) : item.detailsUrl ? String(item.detailsUrl) : null
205
+ }] : [];
206
+ });
207
+ }
208
+ function inspectGitHubRequiredChecks(client, repository, number, cwd) {
209
+ const inspected = client.json([
210
+ 'pr', 'checks', String(number), '--repo', repository,
211
+ '--json', 'name,state,bucket,link,workflow,startedAt,completedAt'
212
+ ], { cwd });
213
+ return inspected.ok
214
+ ? { ok: true, value: normalizeGitHubChecks(inspected.value) }
215
+ : { ok: false, error: inspected.error };
216
+ }
217
+ function parseRunJobIdentity(detailsUrl) {
218
+ try {
219
+ const url = new URL(detailsUrl);
220
+ if (url.hostname !== 'github.com')
221
+ return null;
222
+ const match = url.pathname.match(/\/actions\/runs\/(\d+)(?:\/job\/(\d+))?/);
223
+ if (!match)
224
+ return null;
225
+ return { runId: Number(match[1]), jobId: match[2] ? Number(match[2]) : null };
226
+ }
227
+ catch {
228
+ return null;
229
+ }
230
+ }
231
+ function fetchCheckLogText(client, args, cwd) {
232
+ if (!client.text)
233
+ return { ok: false, error: { code: 'PLATFORM_CLIENT_TEXT_UNAVAILABLE', message: 'Platform client does not support text responses', retryable: false } };
234
+ const fetched = client.text(args, { cwd });
235
+ if (fetched.ok || args[0] !== 'api' || !/response contains terminal escape sequences/i.test(fetched.error.message)) {
236
+ return fetched;
237
+ }
238
+ return client.text([...args, '--allow-escape-sequences'], { cwd });
239
+ }
240
+ export { ISSUE_FIELDS_QUERY, graphState, inspectGitHubIssue, normalizePullRequest, inspectGitHubIssueClosingChangeRequests, inspectGitHubPullRequest, inspectGitHubRequiredChecks, parseRunJobIdentity, fetchCheckLogText };
241
+ //# sourceMappingURL=github-data.js.map
@@ -1,3 +1,4 @@
1
+ import { ISSUE_FIELDS_QUERY, graphState, inspectGitHubIssue, inspectGitHubPullRequest, inspectGitHubIssueClosingChangeRequests, inspectGitHubRequiredChecks, parseRunJobIdentity, fetchCheckLogText } from './github-data.js';
1
2
  import { execFileSync } from 'node:child_process';
2
3
  import fs from 'node:fs';
3
4
  import os from 'node:os';
@@ -8,7 +9,6 @@ import { resourceIdentityNumber, resourceIdentityString } from './resource-ident
8
9
  import { extractPullRequestFileNames, syncLabelDelta } from './in-label-sync.js';
9
10
  const CURRENT_USER_QUERY = 'query { viewer { login } }';
10
11
  const ISSUE_TYPES_QUERY = `query($owner:String!){organization(login:$owner){issueTypes(first:20){nodes{id name pinnedFields{__typename ... on IssueFieldSingleSelect{id name options{id name}} ... on IssueFieldDate{id name} ... on IssueFieldText{id name} ... on IssueFieldNumber{id name}}}}}}`;
11
- const ISSUE_FIELDS_QUERY = `query($owner:String!,$name:String!,$number:Int!){repository(owner:$owner,name:$name){issue(number:$number){id issueType{id name pinnedFields{__typename ... on IssueFieldSingleSelect{id name options{id name}} ... on IssueFieldDate{id name} ... on IssueFieldText{id name} ... on IssueFieldNumber{id name}}} issueFieldValues(first:50){nodes{__typename ... on IssueFieldSingleSelectValue{name optionId field{... on IssueFieldSingleSelect{id name}}} ... on IssueFieldDateValue{value field{... on IssueFieldDate{id name}}} ... on IssueFieldTextValue{value field{... on IssueFieldText{id name}}} ... on IssueFieldNumberValue{value field{... on IssueFieldNumber{id name}}}}}}}}`;
12
12
  const CLOSING_ISSUES_QUERY = 'query($owner:String!,$name:String!,$number:Int!,$cursor:String){repository(owner:$owner,name:$name){pullRequest(number:$number){closingIssuesReferences(first:100,after:$cursor){nodes{number} pageInfo{hasNextPage endCursor}}}}}';
13
13
  function parseGitHubRemote(remote) {
14
14
  const trimmed = remote.trim().replace(/\.git$/, '');
@@ -399,11 +399,10 @@ function createGitHubOperations(client) {
399
399
  const number = resourceIdentityNumber(target);
400
400
  if (!number)
401
401
  return invalid('ISSUE_NUMBER_INVALID', 'Issue number must be positive');
402
- const module = await import('./issues.js');
403
- const fetched = module.inspectGitHubIssue(client, repository(context), number, context.workingDirectory);
402
+ const fetched = inspectGitHubIssue(client, repository(context), number, context.workingDirectory);
404
403
  if (!fetched.ok)
405
404
  return fetched;
406
- const graph = module.graphState(client, repository(context), number, context.workingDirectory);
405
+ const graph = graphState(client, repository(context), number, context.workingDirectory);
407
406
  return { ok: true, value: issueSnapshot(fetched.value, graph || undefined) };
408
407
  },
409
408
  async create({ context, desired }) {
@@ -606,8 +605,7 @@ function createGitHubOperations(client) {
606
605
  const number = resourceIdentityNumber(target);
607
606
  if (!number)
608
607
  return invalid('PR_NUMBER_INVALID', 'Pull request number must be positive');
609
- const module = await import('./pull-requests.js');
610
- const fetched = module.inspectGitHubPullRequest(client, repository(context), number, context.workingDirectory);
608
+ const fetched = inspectGitHubPullRequest(client, repository(context), number, context.workingDirectory);
611
609
  if (!fetched.ok)
612
610
  return fetched;
613
611
  return { ok: true, value: changeRequestSnapshot(fetched.value) };
@@ -671,8 +669,7 @@ function createGitHubOperations(client) {
671
669
  const number = resourceIdentityNumber(issue);
672
670
  if (!number)
673
671
  return invalid('ISSUE_NUMBER_INVALID', 'Issue number must be positive');
674
- const module = await import('./pull-requests.js');
675
- const fetched = module.inspectGitHubIssueClosingChangeRequests(client, repository(context), number, context.workingDirectory);
672
+ const fetched = inspectGitHubIssueClosingChangeRequests(client, repository(context), number, context.workingDirectory);
676
673
  if (!fetched.ok)
677
674
  return fetched;
678
675
  return { ok: true, value: fetched.value.map(changeRequestSnapshot) };
@@ -756,8 +753,7 @@ function createGitHubOperations(client) {
756
753
  const number = resourceIdentityNumber(target);
757
754
  if (!number)
758
755
  return invalid('PR_NUMBER_INVALID', 'Pull request number must be positive');
759
- const module = await import('./github-provider.js');
760
- return module.resolveGitHubChangeRequestGitEvidence({
756
+ return resolveGitHubChangeRequestGitEvidence({
761
757
  cwd: context.workingDirectory,
762
758
  repository: repository(context),
763
759
  number,
@@ -771,18 +767,13 @@ function createGitHubOperations(client) {
771
767
  const number = resourceIdentityNumber(changeRequest);
772
768
  if (!number)
773
769
  return invalid('PR_NUMBER_INVALID', 'Pull request number must be positive');
774
- const module = await import('./pr-checks.js');
775
- const fetched = module.inspectGitHubRequiredChecks(client, repository(context), number, context.workingDirectory);
776
- if (!fetched.ok)
777
- return fetched;
778
- return { ok: true, value: fetched.value.map((check) => ({ name: check.name, status: check.bucket, conclusion: check.conclusion, detailsUrl: check.detailsUrl })) };
770
+ return inspectGitHubRequiredChecks(client, repository(context), number, context.workingDirectory);
779
771
  },
780
772
  async resolveRun({ context, changeRequest, checkName, detailsUrl }) {
781
773
  const number = resourceIdentityNumber(changeRequest);
782
774
  if (!number)
783
775
  return invalid('PR_NUMBER_INVALID', 'Pull request number must be positive');
784
- const module = await import('./pr-checks.js');
785
- const direct = detailsUrl ? module.parseRunJobIdentity(detailsUrl) : null;
776
+ const direct = detailsUrl ? parseRunJobIdentity(detailsUrl) : null;
786
777
  if (direct) {
787
778
  const run = client.json(['api', `repos/${repository(context)}/actions/runs/${direct.runId}`], { cwd: context.workingDirectory });
788
779
  if (!run.ok)
@@ -798,11 +789,10 @@ function createGitHubOperations(client) {
798
789
  : invalid('CHECK_RUN_NOT_FOUND', 'Check run was not found');
799
790
  },
800
791
  async fetchLogs({ context, runId, jobId }) {
801
- const module = await import('./pr-checks.js');
802
792
  const args = jobId
803
793
  ? ['api', `repos/${repository(context)}/actions/jobs/${jobId}/logs`]
804
794
  : ['run', 'view', runId, '--repo', repository(context), '--log-failed'];
805
- const fetched = module.fetchCheckLogText(client, args, context.workingDirectory);
795
+ const fetched = fetchCheckLogText(client, args, context.workingDirectory);
806
796
  if (!fetched.ok)
807
797
  return fetched;
808
798
  return { ok: true, value: { runId, jobId, text: fetched.value || '' } };
@@ -883,7 +873,12 @@ function createGitHubOperations(client) {
883
873
  }
884
874
  continue;
885
875
  }
886
- const response = client.json(['api', '--method', 'POST', `repos/${repository(context)}/milestones`, '-f', `title=${item.title}`, '-f', `description=${item.description}`], { cwd: context.workingDirectory });
876
+ const response = client.json([
877
+ 'api', '--method', 'POST', `repos/${repository(context)}/milestones`,
878
+ '-f', `title=${item.title}`,
879
+ '-f', `description=${item.description}`,
880
+ '-f', `state=${item.state}`
881
+ ], { cwd: context.workingDirectory });
887
882
  if (!response.ok)
888
883
  return response;
889
884
  created.push(item.title);
@@ -7,7 +7,7 @@ import { platformResult } from './types.js';
7
7
  import { providerError, providerOperationContext, providerStatus, providerResourceToken, unsupportedProviderOperation } from './provider-bridge.js';
8
8
  import { resourceIdentityNumber } from './resource-identity.js';
9
9
  import { taskIssueIdentity, taskIssueIdentityError } from './task-identities.js';
10
- import { CONTROL_MARKER_PATTERN, escapeHtmlText, fenceRanges, renderSafeCodeFence, sanitizeMarkdownDocument } from './comment-safety.js';
10
+ import { canonicalizeCommentBody, escapeHtmlText, fenceRanges, renderSafeCodeFence } from './comment-safety.js';
11
11
  function providerCommentId(id, provider) {
12
12
  return provider.identity?.comment === 'number' && /^\d+$/.test(id) ? Number(id) : id;
13
13
  }
@@ -18,6 +18,7 @@ const MARKERS = {
18
18
  summary: (taskId) => `<!-- sync-issue:${taskId}:summary -->`,
19
19
  cancel: (taskId) => `<!-- sync-issue:${taskId}:cancel -->`
20
20
  };
21
+ const COMMENT_BYTE_LIMIT = 60_000;
21
22
  const ARTIFACT_TITLES = {
22
23
  analysis: '需求分析',
23
24
  'review-analysis': '需求分析审查',
@@ -32,6 +33,9 @@ const ARTIFACT_TITLES = {
32
33
  function normalizeCommentContent(content) {
33
34
  return content.replace(/\r\n/g, '\n').replace(/\n+$/, '\n');
34
35
  }
36
+ function isTaskCommentTooLarge(content) {
37
+ return Buffer.byteLength(content, 'utf8') > COMMENT_BYTE_LIMIT;
38
+ }
35
39
  function splitFrontmatter(content) {
36
40
  const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
37
41
  if (!match)
@@ -39,7 +43,7 @@ function splitFrontmatter(content) {
39
43
  return { frontmatter: match[1], body: content.slice(match[0].length).replace(/^\r?\n/, '') };
40
44
  }
41
45
  function sanitizeCommentBody(value, label) {
42
- const result = sanitizeMarkdownDocument(value, { reservedMarkers: [CONTROL_MARKER_PATTERN] });
46
+ const result = canonicalizeCommentBody(value);
43
47
  if (!result.ok)
44
48
  throw new Error(`${result.error.code}: ${label}: ${result.error.message} at offset ${result.error.offset}`);
45
49
  return result.value;
@@ -219,7 +223,7 @@ function buildArtifactChunk(taskId, stem, title, agent, content, part, total, ch
219
223
  return { marker, body, content, part, total };
220
224
  }
221
225
  function chunkArtifactComment(input) {
222
- const byteLimit = input.byteLimit || 60_000;
226
+ const byteLimit = input.byteLimit || COMMENT_BYTE_LIMIT;
223
227
  const identity = artifactIdentity(input.artifact);
224
228
  const safeBody = sanitizeCommentBody(input.body, 'artifact body');
225
229
  const single = buildArtifactChunk(input.taskId, identity.stem, identity.title, input.agent, safeBody, 1, 1, false, Boolean(input.backfill));
@@ -257,11 +261,6 @@ function flattenComments(value) {
257
261
  const flattened = value.flatMap((entry) => Array.isArray(entry) ? entry : [entry]);
258
262
  return flattened.filter((entry) => Boolean(entry && typeof entry === 'object' && (typeof entry.id === 'number' || typeof entry.id === 'string') && typeof entry.body === 'string'));
259
263
  }
260
- function issueNumberFromTask(content) {
261
- const value = parseTaskFrontmatter(content).issue_number;
262
- const number = Number(value);
263
- return Number.isInteger(number) && number > 0 ? number : null;
264
- }
265
264
  function listRemoteComments(client, repo, issue, cwd) {
266
265
  const result = client.json([
267
266
  'api', '--paginate', '--slurp', `repos/${repo}/issues/${issue}/comments?per_page=100`
@@ -374,14 +373,21 @@ async function syncPlatformComment(taskRef, options) {
374
373
  const taskContent = fs.readFileSync(resolved.taskMdPath, 'utf8');
375
374
  let issueIdentityFromTask;
376
375
  try {
377
- issueIdentityFromTask = taskIssueIdentity(parseTaskFrontmatter(taskContent), undefined, options.runtimeVersion);
376
+ issueIdentityFromTask = taskIssueIdentity(parseTaskFrontmatter(taskContent));
378
377
  }
379
378
  catch (error) {
380
379
  return platformResult('failed', { error: { ...taskIssueIdentityError(error), retryable: false } });
381
380
  }
382
381
  if (!issueIdentityFromTask) {
383
382
  return platformResult('no-op', {
384
- error: { code: 'ISSUE_NOT_LINKED', message: 'Task has no valid issue_number', retryable: false }
383
+ error: { code: 'ISSUE_NOT_LINKED', message: 'Task has no valid platform issue identity', retryable: false }
384
+ });
385
+ }
386
+ if (options.kind === 'task' && isTaskCommentTooLarge(taskContent)) {
387
+ return platformResult('no-op', {
388
+ resource: { kind: 'issue', number: resourceIdentityNumber(issueIdentityFromTask), identity: issueIdentityFromTask },
389
+ operations: [{ name: `comment:${MARKERS.task(resolved.taskId)}`, status: 'skipped', reasonCode: 'COMMENT_PAYLOAD_TOO_LARGE' }],
390
+ error: null
385
391
  });
386
392
  }
387
393
  let desired;
@@ -541,7 +547,7 @@ async function checkPlatformCommentOwner(taskRef, options = {}) {
541
547
  const content = fs.readFileSync(resolved.taskMdPath, 'utf8');
542
548
  let issueIdentity;
543
549
  try {
544
- issueIdentity = taskIssueIdentity(parseTaskFrontmatter(content), undefined, options.runtimeVersion);
550
+ issueIdentity = taskIssueIdentity(parseTaskFrontmatter(content));
545
551
  }
546
552
  catch (error) {
547
553
  return platformResult('failed', { error: { ...taskIssueIdentityError(error), retryable: false } });
@@ -572,5 +578,5 @@ async function checkPlatformCommentOwner(taskRef, options = {}) {
572
578
  }
573
579
  return platformResult('no-op', { ...contextFields(context), resource: { kind: 'issue', number: resourceIdentityNumber(issueIdentity), identity: issueIdentity }, error: null });
574
580
  }
575
- export { MARKERS, chunkArtifactComment, findMarkerComments, listRemoteComments, checkPlatformCommentOwner, listPlatformComments, normalizeCommentContent, renderTaskComment, syncPlatformComment, validateRelatedMarkerSet, writeComment };
581
+ export { COMMENT_BYTE_LIMIT, MARKERS, chunkArtifactComment, findMarkerComments, listRemoteComments, checkPlatformCommentOwner, listPlatformComments, normalizeCommentContent, renderTaskComment, isTaskCommentTooLarge, syncPlatformComment, validateRelatedMarkerSet, writeComment };
576
582
  //# sourceMappingURL=issue-comments.js.map
@@ -14,8 +14,6 @@ import { labelDelta, planInLabelUpdate, syncLabelDelta, validateInLabelMapping,
14
14
  import { providerError, providerOperationContext, providerStatus, providerResourceIdentity, providerResourceToken, unsupportedProviderOperation } from './provider-bridge.js';
15
15
  import { resourceIdentityEquals, resourceIdentityNumber, resourceIdentityString, serializeResourceIdentity } from './resource-identity.js';
16
16
  import { taskIssueIdentity, taskIssueIdentityError } from './task-identities.js';
17
- const ISSUE_TYPES_QUERY = `query($owner:String!){organization(login:$owner){issueTypes(first:20){nodes{id name pinnedFields{__typename ... on IssueFieldSingleSelect{id name options{id name}} ... on IssueFieldDate{id name} ... on IssueFieldText{id name} ... on IssueFieldNumber{id name}}}}}}`;
18
- const ISSUE_FIELDS_QUERY = `query($owner:String!,$name:String!,$number:Int!){repository(owner:$owner,name:$name){issue(number:$number){id issueType{id name pinnedFields{__typename ... on IssueFieldSingleSelect{id name options{id name}} ... on IssueFieldDate{id name} ... on IssueFieldText{id name} ... on IssueFieldNumber{id name}}} issueFieldValues(first:50){nodes{__typename ... on IssueFieldSingleSelectValue{name optionId field{... on IssueFieldSingleSelect{id name}}} ... on IssueFieldDateValue{value field{... on IssueFieldDate{id name}}} ... on IssueFieldTextValue{value field{... on IssueFieldText{id name}}} ... on IssueFieldNumberValue{value field{... on IssueFieldNumber{id name}}}}}}}}`;
19
17
  function result(status, taskId, issueNumber, overrides = {}) {
20
18
  return {
21
19
  ...platformResult(status),
@@ -34,7 +32,7 @@ async function resolvedContext(taskRef, options) {
34
32
  const frontmatter = parseTaskFrontmatter(content);
35
33
  let issueIdentity;
36
34
  try {
37
- issueIdentity = taskIssueIdentity(frontmatter, undefined, options.runtimeVersion);
35
+ issueIdentity = taskIssueIdentity(frontmatter);
38
36
  }
39
37
  catch (error) {
40
38
  return { ok: false, output: result('failed', resolved.taskId, null, { error: { ...taskIssueIdentityError(error), retryable: false } }) };
@@ -133,115 +131,6 @@ async function inspectExternalIssue(base, issueIdentity) {
133
131
  error: null
134
132
  });
135
133
  }
136
- function normalizeIssue(remote, repository, fallbackNumber) {
137
- const number = Number.isInteger(remote.number) && Number(remote.number) > 0
138
- ? Number(remote.number)
139
- : fallbackNumber;
140
- if (!number || !Number.isSafeInteger(number) || remote.pull_request)
141
- return null;
142
- return {
143
- repository,
144
- number,
145
- databaseId: Number.isInteger(remote.id) ? Number(remote.id) : null,
146
- nodeId: remote.node_id || `issue-${number}`,
147
- url: remote.html_url || `https://github.com/${repository}/issues/${number}`,
148
- state: String(remote.state || '').toLowerCase() === 'closed' ? 'closed' : 'open',
149
- title: remote.title || '',
150
- body: remote.body || '',
151
- labels: (remote.labels || []).map((label) => typeof label === 'string' ? label : label.name || '').filter(Boolean).sort(),
152
- assignees: (remote.assignees || []).map((assignee) => assignee.login || '').filter(Boolean).sort(),
153
- milestone: remote.milestone?.title || null,
154
- issueType: remote.type?.name || null,
155
- fields: {}
156
- };
157
- }
158
- function fieldKind(value) {
159
- if (value.__typename === 'IssueFieldSingleSelect' || value.__typename === 'IssueFieldSingleSelectValue')
160
- return 'single-select';
161
- if (value.__typename === 'IssueFieldDate' || value.__typename === 'IssueFieldDateValue')
162
- return 'date';
163
- if (value.__typename === 'IssueFieldText' || value.__typename === 'IssueFieldTextValue')
164
- return 'text';
165
- if (value.__typename === 'IssueFieldNumber' || value.__typename === 'IssueFieldNumberValue')
166
- return 'number';
167
- return null;
168
- }
169
- function normalizeFieldSchemas(value) {
170
- if (!Array.isArray(value))
171
- return [];
172
- return value.flatMap((raw) => {
173
- const item = raw;
174
- const kind = fieldKind(item);
175
- return item.id && item.name && kind ? [{
176
- id: item.id,
177
- name: item.name,
178
- kind,
179
- options: (item.options || []).flatMap((option) => option.id && option.name ? [{ id: option.id, name: option.name }] : [])
180
- }] : [];
181
- });
182
- }
183
- function normalizeIssueTypes(value) {
184
- const nodes = value?.data?.organization?.issueTypes?.nodes;
185
- return (nodes || []).flatMap((raw) => {
186
- const item = raw;
187
- return item.id && item.name ? [{ id: item.id, name: item.name, fields: normalizeFieldSchemas(item.pinnedFields) }] : [];
188
- });
189
- }
190
- function normalizeCurrentFields(value) {
191
- const issue = value?.data?.repository?.issue;
192
- const type = issue?.issueType?.name ? {
193
- id: issue.issueType.id || issue.issueType.name,
194
- name: issue.issueType.name,
195
- fields: normalizeFieldSchemas(issue.issueType.pinnedFields)
196
- } : null;
197
- const values = (issue?.issueFieldValues?.nodes || []).flatMap((raw) => {
198
- const item = raw;
199
- const kind = fieldKind(item);
200
- const value = kind === 'single-select' ? item.name : item.value;
201
- return item.field?.name && kind && value !== undefined
202
- ? [{ id: item.field.id || item.field.name, name: item.field.name, kind, value: value ?? null }]
203
- : [];
204
- });
205
- return { issueId: issue?.id || null, type, values };
206
- }
207
- function graphState(client, repository, issue, cwd) {
208
- const [owner, name] = repository.split('/');
209
- if (!owner || !name)
210
- return null;
211
- const current = client.json([
212
- 'api', 'graphql', '-f', `query=${ISSUE_FIELDS_QUERY}`, '-F', `owner=${owner}`, '-F', `name=${name}`, '-F', `number=${issue}`
213
- ], { cwd });
214
- if (!current.ok)
215
- return null;
216
- return normalizeCurrentFields(current.value);
217
- }
218
- function fetchIssue(client, repository, issue, cwd) {
219
- return client.json(['api', `repos/${repository}/issues/${issue}`], { cwd });
220
- }
221
- function inspectGitHubIssue(client, repository, issue, cwd) {
222
- const fetched = fetchIssue(client, repository, issue, cwd);
223
- if (!fetched.ok)
224
- return fetched;
225
- const snapshot = normalizeIssue(fetched.value, repository, issue);
226
- return snapshot
227
- ? { ok: true, value: snapshot }
228
- : { ok: false, error: { code: 'ISSUE_IDENTITY_INVALID', message: 'Remote resource is not a valid Issue', retryable: false } };
229
- }
230
- function inspectGitHubIssueMetadata(client, repository, issue, cwd) {
231
- const fetched = fetchIssue(client, repository, issue, cwd);
232
- if (!fetched.ok)
233
- return fetched;
234
- const remote = fetched.value;
235
- return {
236
- ok: true,
237
- value: {
238
- state: String(remote.state || '').toLowerCase() === 'closed' ? 'closed' : 'open',
239
- labels: (remote.labels || []).map((label) => typeof label === 'string' ? label : label.name || '').filter(Boolean).sort(),
240
- body: remote.body || '',
241
- milestone: remote.milestone?.title || null
242
- }
243
- };
244
- }
245
134
  async function inspectPlatformIssue(taskRef, options = {}) {
246
135
  const base = await resolvedContext(taskRef, options);
247
136
  if (!base.ok)
@@ -450,12 +339,6 @@ function requirementsFromTask(content) {
450
339
  checked: match[1].toLowerCase() === 'x', text: match[2]
451
340
  }));
452
341
  }
453
- function flattenPages(value) {
454
- return Array.isArray(value) ? value.flatMap((item) => Array.isArray(item) ? item : [item]) : [];
455
- }
456
- function listNames(value) {
457
- return flattenPages(value).map((item) => typeof item === 'string' ? item : String(item.name || '')).filter(Boolean);
458
- }
459
342
  function milestoneBasis(repoRoot, current) {
460
343
  if (!current || !/^\d+\.\d+\.x$/.test(current))
461
344
  return current;
@@ -552,67 +435,6 @@ function desiredFieldValues(frontmatter, fields) {
552
435
  }
553
436
  return desired;
554
437
  }
555
- function planGraphMetadata(client, repository, issue, cwd, frontmatter, options, capabilities) {
556
- if (!options.issueType && !options.fields)
557
- return { operations: [], issueId: null };
558
- if (!capabilities.push)
559
- return {
560
- operations: [
561
- ...(options.issueType ? [{ name: 'issue-type', status: 'skipped', reasonCode: 'PUSH_REQUIRED' }] : []),
562
- ...(options.fields ? [{ name: 'fields', status: 'skipped', reasonCode: 'PUSH_REQUIRED' }] : [])
563
- ], issueId: null
564
- };
565
- const [owner] = repository.split('/');
566
- const typesResult = client.json(['api', 'graphql', '-f', `query=${ISSUE_TYPES_QUERY}`, '-F', `owner=${owner}`], { cwd });
567
- if (!typesResult.ok)
568
- return { operations: [{ name: 'issue-schema', status: 'failed', reasonCode: typesResult.error.code }], issueId: null };
569
- const types = normalizeIssueTypes(typesResult.value);
570
- if (types.length === 0)
571
- return {
572
- operations: [
573
- ...(options.issueType ? [{ name: 'issue-type', status: 'skipped', reasonCode: 'ISSUE_TYPES_UNSUPPORTED' }] : []),
574
- ...(options.fields ? [{ name: 'fields', status: 'skipped', reasonCode: 'ISSUE_TYPES_UNSUPPORTED' }] : [])
575
- ], issueId: null
576
- };
577
- const current = graphState(client, repository, issue, cwd);
578
- if (!current?.issueId)
579
- return { operations: [{ name: 'issue-schema', status: 'failed', reasonCode: 'ISSUE_GRAPH_IDENTITY_INVALID' }], issueId: null };
580
- const target = types.find((type) => type.name === desiredIssueType(frontmatter.type || ''));
581
- if (!target)
582
- return { operations: [{ name: 'issue-type', status: 'failed', reasonCode: 'ISSUE_TYPE_NOT_FOUND' }], issueId: current.issueId };
583
- const operations = [];
584
- if (options.issueType)
585
- operations.push(current.type?.id === target.id
586
- ? { name: 'issue-type', status: 'no-op', reasonCode: null }
587
- : { name: 'issue-type', status: 'planned', reasonCode: null, value: { issueTypeId: target.id } });
588
- if (options.fields) {
589
- const desired = desiredFieldValues(frontmatter, target.fields);
590
- const inputs = desired.filter((field) => current.values.find((value) => value.name === field.name)?.value !== field.value).map((field) => field.input);
591
- if (current.type?.id !== target.id) {
592
- const targetNames = new Set(target.fields.map((field) => field.name));
593
- for (const old of current.values)
594
- if (!targetNames.has(old.name))
595
- inputs.push({ fieldId: old.id, delete: true });
596
- }
597
- operations.push(inputs.length === 0
598
- ? { name: 'fields', status: 'no-op', reasonCode: null }
599
- : { name: 'fields', status: 'planned', reasonCode: null, value: inputs });
600
- }
601
- return { operations, issueId: current.issueId };
602
- }
603
- function executeGraphOperation(client, cwd, issueId, operation) {
604
- if (operation.name === 'issue-type') {
605
- const query = 'mutation($issueId:ID!,$issueTypeId:ID){updateIssueIssueType(input:{issueId:$issueId,issueTypeId:$issueTypeId}){issue{id}}}';
606
- const typeId = operation.value.issueTypeId;
607
- return client.json(['api', 'graphql', '--input', '-'], {
608
- cwd, method: 'POST', input: JSON.stringify({ query, variables: { issueId, issueTypeId: typeId } })
609
- });
610
- }
611
- const query = 'mutation($issueId:ID!,$issueFields:[IssueFieldCreateOrUpdateInput!]!){setIssueFieldValue(input:{issueId:$issueId,issueFields:$issueFields}){issue{id}}}';
612
- return client.json(['api', 'graphql', '--input', '-'], {
613
- cwd, method: 'POST', input: JSON.stringify({ query, variables: { issueId, issueFields: operation.value } })
614
- });
615
- }
616
438
  async function syncPlatformIssue(taskRef, options) {
617
439
  const base = await resolvedContext(taskRef, options);
618
440
  if (!base.ok)
@@ -761,5 +583,5 @@ async function syncPlatformIssue(taskRef, options) {
761
583
  operations: plan.operations.map((operation) => operation.status === 'planned' ? { ...operation, status: 'applied' } : operation), error: null
762
584
  });
763
585
  }
764
- export { bindPlatformIssue, createPlatformIssue, graphState, inspectGitHubIssue, inspectGitHubIssueMetadata, inspectPlatformIssue, normalizeIssue, requirementSectionAnchors, syncPlatformIssue };
586
+ export { bindPlatformIssue, createPlatformIssue, inspectPlatformIssue, requirementSectionAnchors, syncPlatformIssue };
765
587
  //# sourceMappingURL=issues.js.map