@fitlab-ai/agent-infra 0.9.13 → 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 (280) hide show
  1. package/bin/cli.ts +26 -9
  2. package/dist/bin/cli.js +173 -157
  3. package/dist/bin/internal-cli.js +42 -21
  4. package/dist/lib/agent-client.js +5 -0
  5. package/dist/lib/internal/agent-client.js +5 -2
  6. package/dist/lib/internal/cli-route-inventory.js +152 -0
  7. package/dist/lib/internal/codex-lifecycle.js +9 -6
  8. package/dist/lib/internal/codex-sandbox-controller.js +8 -2
  9. package/dist/lib/internal/git-workflow.js +10 -6
  10. package/dist/lib/internal/platform-checks.js +16 -4
  11. package/dist/lib/internal/platform-comment.js +16 -4
  12. package/dist/lib/internal/platform-context.js +4 -1
  13. package/dist/lib/internal/platform-issue.js +12 -4
  14. package/dist/lib/internal/platform-metadata.js +88 -0
  15. package/dist/lib/internal/platform-pr-review.js +16 -3
  16. package/dist/lib/internal/platform-pr.js +24 -10
  17. package/dist/lib/internal/platform-release-notes.js +6 -3
  18. package/dist/lib/internal/platform-security.js +93 -0
  19. package/dist/lib/internal/pr-review-grade.js +14 -3
  20. package/dist/lib/internal/release-workflow.js +19 -5
  21. package/dist/lib/internal/sandbox-control.js +22 -5
  22. package/dist/lib/internal/task-activity.js +13 -4
  23. package/dist/lib/internal/task-artifact.js +186 -27
  24. package/dist/lib/internal/task-context.js +4 -1
  25. package/dist/lib/internal/task-create.js +48 -15
  26. package/dist/lib/internal/task-delivery.js +4 -1
  27. package/dist/lib/internal/task-event.js +4 -1
  28. package/dist/lib/internal/task-finalization.js +4 -1
  29. package/dist/lib/internal/task-invalidation.js +4 -1
  30. package/dist/lib/internal/task-ledger.js +12 -1
  31. package/dist/lib/internal/task-lifecycle.js +4 -1
  32. package/dist/lib/internal/task-operation-registry.js +421 -0
  33. package/dist/lib/internal/task-orchestration.js +12 -0
  34. package/dist/lib/internal/task-override.js +10 -3
  35. package/dist/lib/internal/task-qualification.js +90 -0
  36. package/dist/lib/internal/task-review.js +4 -1
  37. package/dist/lib/internal/task-short-id.js +11 -1
  38. package/dist/lib/internal/task-snapshot.js +4 -1
  39. package/dist/lib/internal/task-validate.js +7 -2
  40. package/dist/lib/internal/task-verify.js +5 -1
  41. package/dist/lib/internal/task-warning.js +8 -1
  42. package/dist/lib/platform/comment-safety.js +226 -0
  43. package/dist/lib/platform/github-provider.js +233 -6
  44. package/dist/lib/platform/issue-comments.js +146 -34
  45. package/dist/lib/platform/pr-change-report.js +6 -12
  46. package/dist/lib/platform/pr-summary.js +28 -7
  47. package/dist/lib/platform/provider-contract.d.ts +67 -1
  48. package/dist/lib/platform/provider-contract.js +6 -2
  49. package/dist/lib/platform/provider-validation.js +76 -3
  50. package/dist/lib/platform/pull-requests.js +115 -170
  51. package/dist/lib/platform/repository-metadata.js +377 -0
  52. package/dist/lib/platform/security-alerts.js +155 -0
  53. package/dist/lib/platform/verification-sync.js +33 -26
  54. package/dist/lib/process-data/index.js +7 -0
  55. package/dist/lib/run/index.js +5 -0
  56. package/dist/lib/sandbox/commands/control-status.js +22 -0
  57. package/dist/lib/sandbox/commands/create.js +32 -6
  58. package/dist/lib/sandbox/commands/ls.js +5 -0
  59. package/dist/lib/sandbox/commands/rm.js +827 -120
  60. package/dist/lib/sandbox/commands/show.js +16 -0
  61. package/dist/lib/sandbox/control/client.js +83 -9
  62. package/dist/lib/sandbox/control/completed-reentry.js +85 -0
  63. package/dist/lib/sandbox/control/container-identity.js +28 -31
  64. package/dist/lib/sandbox/control/executor.js +149 -14
  65. package/dist/lib/sandbox/control/lifecycle.js +621 -127
  66. package/dist/lib/sandbox/control/native-file-lock.js +177 -0
  67. package/dist/lib/sandbox/control/server.js +305 -35
  68. package/dist/lib/sandbox/control/state.js +5 -3
  69. package/dist/lib/sandbox/control/task-view.js +183 -0
  70. package/dist/lib/sandbox/engines/authority.js +289 -0
  71. package/dist/lib/sandbox/engines/docker-exact-discovery.js +97 -0
  72. package/dist/lib/sandbox/index.js +5 -0
  73. package/dist/lib/sandbox/recovery.js +21 -1
  74. package/dist/lib/sandbox/workspace-view.js +2 -1
  75. package/dist/lib/sandbox/worktree-safety.js +4 -1
  76. package/dist/lib/server/index.js +8 -0
  77. package/dist/lib/task/artifact-lifecycle.js +42 -13
  78. package/dist/lib/task/artifact-operations.js +520 -0
  79. package/dist/lib/task/artifact-repair-intent.js +59 -0
  80. package/dist/lib/task/artifact-schema.js +135 -0
  81. package/dist/lib/task/capabilities.js +72 -1
  82. package/dist/lib/task/control-authority.js +4 -0
  83. package/dist/lib/task/create-service.js +103 -4
  84. package/dist/lib/task/create.js +25 -0
  85. package/dist/lib/task/events.js +186 -67
  86. package/dist/lib/task/index.js +11 -3
  87. package/dist/lib/task/local-artifact-finalization.js +75 -150
  88. package/dist/lib/task/orchestration.js +192 -52
  89. package/dist/lib/task/qualification-audit.js +490 -0
  90. package/dist/lib/task/qualification-confirmation.js +109 -0
  91. package/dist/lib/task/qualification-intents.js +148 -0
  92. package/dist/lib/task/review-artifacts.js +22 -23
  93. package/dist/lib/task/review-finalization.js +121 -4
  94. package/dist/lib/task/sections.js +6 -4
  95. package/dist/lib/task/verification-config.js +11 -0
  96. package/dist/lib/task/verification-engine.js +54 -4
  97. package/dist/lifecycle-build-manifest.json +3 -3
  98. package/lib/agent-client.ts +9 -0
  99. package/lib/internal/agent-client.ts +4 -2
  100. package/lib/internal/cli-route-inventory.ts +140 -0
  101. package/lib/internal/codex-lifecycle.ts +8 -6
  102. package/lib/internal/codex-sandbox-controller.ts +7 -2
  103. package/lib/internal/git-workflow.ts +9 -6
  104. package/lib/internal/platform-checks.ts +12 -4
  105. package/lib/internal/platform-comment.ts +12 -4
  106. package/lib/internal/platform-context.ts +3 -1
  107. package/lib/internal/platform-issue.ts +11 -4
  108. package/lib/internal/platform-metadata.ts +70 -0
  109. package/lib/internal/platform-pr-review.ts +14 -3
  110. package/lib/internal/platform-pr.ts +23 -10
  111. package/lib/internal/platform-release-notes.ts +5 -3
  112. package/lib/internal/platform-security.ts +83 -0
  113. package/lib/internal/pr-review-grade.ts +10 -3
  114. package/lib/internal/release-workflow.ts +17 -5
  115. package/lib/internal/sandbox-control.ts +19 -5
  116. package/lib/internal/task-activity.ts +12 -4
  117. package/lib/internal/task-artifact.ts +164 -25
  118. package/lib/internal/task-context.ts +3 -1
  119. package/lib/internal/task-create.ts +76 -15
  120. package/lib/internal/task-delivery.ts +3 -1
  121. package/lib/internal/task-event.ts +3 -1
  122. package/lib/internal/task-finalization.ts +3 -1
  123. package/lib/internal/task-invalidation.ts +3 -1
  124. package/lib/internal/task-ledger.ts +11 -1
  125. package/lib/internal/task-lifecycle.ts +3 -1
  126. package/lib/internal/task-operation-registry.ts +482 -0
  127. package/lib/internal/task-orchestration.ts +12 -0
  128. package/lib/internal/task-override.ts +9 -3
  129. package/lib/internal/task-qualification.ts +61 -0
  130. package/lib/internal/task-review.ts +3 -1
  131. package/lib/internal/task-short-id.ts +10 -1
  132. package/lib/internal/task-snapshot.ts +3 -1
  133. package/lib/internal/task-validate.ts +6 -2
  134. package/lib/internal/task-verify.ts +4 -1
  135. package/lib/internal/task-warning.ts +7 -1
  136. package/lib/platform/comment-safety.ts +250 -0
  137. package/lib/platform/github-provider.ts +229 -7
  138. package/lib/platform/issue-comments.ts +160 -35
  139. package/lib/platform/pr-change-report.ts +6 -12
  140. package/lib/platform/pr-summary.ts +27 -6
  141. package/lib/platform/provider-contract.ts +78 -3
  142. package/lib/platform/provider-validation.ts +85 -3
  143. package/lib/platform/pull-requests.ts +126 -178
  144. package/lib/platform/repository-metadata.ts +453 -0
  145. package/lib/platform/security-alerts.ts +191 -0
  146. package/lib/platform/verification-sync.ts +32 -28
  147. package/lib/process-data/index.ts +7 -0
  148. package/lib/run/index.ts +5 -0
  149. package/lib/sandbox/commands/control-status.ts +26 -0
  150. package/lib/sandbox/commands/create.ts +46 -6
  151. package/lib/sandbox/commands/ls.ts +7 -0
  152. package/lib/sandbox/commands/rm.ts +1000 -87
  153. package/lib/sandbox/commands/show.ts +16 -0
  154. package/lib/sandbox/control/client.ts +103 -9
  155. package/lib/sandbox/control/completed-reentry.ts +98 -0
  156. package/lib/sandbox/control/container-identity.ts +27 -43
  157. package/lib/sandbox/control/executor.ts +177 -12
  158. package/lib/sandbox/control/lifecycle.ts +629 -17
  159. package/lib/sandbox/control/native-file-lock.ts +209 -0
  160. package/lib/sandbox/control/protocol.ts +5 -2
  161. package/lib/sandbox/control/server.ts +319 -37
  162. package/lib/sandbox/control/state.ts +6 -3
  163. package/lib/sandbox/control/task-view.ts +240 -0
  164. package/lib/sandbox/engines/authority.ts +365 -0
  165. package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
  166. package/lib/sandbox/index.ts +7 -0
  167. package/lib/sandbox/recovery.ts +21 -1
  168. package/lib/sandbox/workspace-view.ts +9 -3
  169. package/lib/sandbox/worktree-safety.ts +4 -1
  170. package/lib/server/index.ts +10 -0
  171. package/lib/task/artifact-lifecycle.ts +38 -16
  172. package/lib/task/artifact-operations.ts +626 -0
  173. package/lib/task/artifact-repair-intent.ts +71 -0
  174. package/lib/task/artifact-schema.ts +192 -0
  175. package/lib/task/capabilities.ts +70 -1
  176. package/lib/task/control-authority.ts +11 -1
  177. package/lib/task/create-service.ts +131 -6
  178. package/lib/task/create.ts +27 -0
  179. package/lib/task/events.ts +161 -65
  180. package/lib/task/index.ts +16 -3
  181. package/lib/task/local-artifact-finalization.ts +87 -218
  182. package/lib/task/orchestration.ts +172 -49
  183. package/lib/task/qualification-audit.ts +599 -0
  184. package/lib/task/qualification-confirmation.ts +117 -0
  185. package/lib/task/qualification-intents.ts +150 -0
  186. package/lib/task/review-artifacts.ts +21 -22
  187. package/lib/task/review-finalization.ts +133 -4
  188. package/lib/task/sections.ts +6 -4
  189. package/lib/task/verification-config.ts +12 -0
  190. package/lib/task/verification-engine.ts +55 -4
  191. package/package.json +6 -1
  192. package/templates/.agents/rules/README.en.md +2 -0
  193. package/templates/.agents/rules/README.zh-CN.md +2 -0
  194. package/templates/.agents/rules/decision-qualification.en.md +22 -0
  195. package/templates/.agents/rules/decision-qualification.zh-CN.md +22 -0
  196. package/templates/.agents/rules/evidence-reporting.en.md +28 -0
  197. package/templates/.agents/rules/evidence-reporting.zh-CN.md +28 -0
  198. package/templates/.agents/rules/label-milestone-setup.en.md +7 -7
  199. package/templates/.agents/rules/label-milestone-setup.zh-CN.md +7 -7
  200. package/templates/.agents/rules/local-artifact-repair.en.md +5 -1
  201. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +5 -1
  202. package/templates/.agents/rules/security-alerts.en.md +8 -8
  203. package/templates/.agents/rules/security-alerts.zh-CN.md +8 -8
  204. package/templates/.agents/skills/analyze-task/SKILL.en.md +15 -2
  205. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +19 -2
  206. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -12
  207. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -12
  208. package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
  209. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
  210. package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
  211. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
  212. package/templates/.agents/skills/code-task/SKILL.en.md +14 -1
  213. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +14 -1
  214. package/templates/.agents/skills/code-task/config/verify.en.json +5 -14
  215. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +5 -14
  216. package/templates/.agents/skills/code-task/reference/code-rules.en.md +5 -4
  217. package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +5 -4
  218. package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
  219. package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
  220. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +3 -1
  221. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +3 -1
  222. package/templates/.agents/skills/code-task/reference/report-template.en.md +42 -15
  223. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +39 -12
  224. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +5 -1
  225. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +5 -1
  226. package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +2 -0
  227. package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +2 -0
  228. package/templates/.agents/skills/complete-task/SKILL.en.md +9 -22
  229. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +9 -22
  230. package/templates/.agents/skills/create-task/SKILL.en.md +8 -0
  231. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +7 -0
  232. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  233. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  234. package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
  235. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
  236. package/templates/.agents/skills/init-labels/SKILL.en.md +8 -8
  237. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +8 -8
  238. package/templates/.agents/skills/init-milestones/SKILL.en.md +9 -11
  239. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +9 -11
  240. package/templates/.agents/skills/plan-task/SKILL.en.md +14 -1
  241. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +16 -1
  242. package/templates/.agents/skills/plan-task/config/verify.en.json +4 -14
  243. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +4 -14
  244. package/templates/.agents/skills/review-analysis/SKILL.en.md +14 -1
  245. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +14 -1
  246. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -18
  247. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -18
  248. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +50 -23
  249. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +45 -18
  250. package/templates/.agents/skills/review-code/SKILL.en.md +14 -1
  251. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +14 -1
  252. package/templates/.agents/skills/review-code/config/verify.en.json +1 -23
  253. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -23
  254. package/templates/.agents/skills/review-code/reference/report-template.en.md +49 -22
  255. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +45 -18
  256. package/templates/.agents/skills/review-plan/SKILL.en.md +14 -1
  257. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +14 -1
  258. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -18
  259. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -18
  260. package/templates/.agents/skills/review-plan/reference/report-template.en.md +49 -22
  261. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +45 -18
  262. package/templates/.agents/skills/review-pr/SKILL.en.md +5 -1
  263. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +5 -1
  264. package/templates/.agents/skills/review-pr/reference/report-template.en.md +4 -3
  265. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +4 -3
  266. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +5 -1
  267. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +5 -1
  268. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +3 -1
  269. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +3 -1
  270. package/templates/.agents/skills/test/SKILL.en.md +13 -2
  271. package/templates/.agents/skills/test/SKILL.zh-CN.md +13 -2
  272. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +14 -0
  273. package/templates/.agents/templates/task.en.md +6 -0
  274. package/templates/.agents/templates/task.zh-CN.md +6 -0
  275. package/templates/.agents/scripts/security-alerts.github.sh +0 -151
  276. package/templates/.agents/scripts/security-alerts.sh +0 -31
  277. package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +0 -146
  278. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +0 -32
  279. package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +0 -294
  280. package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +0 -6
@@ -14,6 +14,7 @@ import {
14
14
  import type { PullRequestResult } from '../platform/pull-requests.ts';
15
15
  import { reportWrite, summaryContext, syncPullRequestSummary } from '../platform/pr-summary.ts';
16
16
  import type { PlatformResult } from '../platform/types.ts';
17
+ import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.ts';
17
18
 
18
19
  const USAGE = `Usage: agent-infra-internal platform-pr inspect <task-ref> [--cwd <path>]
19
20
  agent-infra-internal platform-pr resolve-external <task-ref> --agent <agent> [--pr <token>] [--dry-run] [--cwd <path>]
@@ -67,10 +68,22 @@ function readFile(value: string, cwd: string): string {
67
68
  }
68
69
 
69
70
  async function platformPr(args: string[] = []): Promise<void> {
71
+ if (!ensureInternalHandlerRoute('platform-pr', args)) return;
70
72
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
71
73
  const operation = args[0];
72
- if (!operation || !['inspect', 'resolve-external', 'create', 'bind', 'skip', 'sync', 'sync-in-labels', 'summary-context', 'change-report', 'summary-sync'].includes(operation)) { fail('a valid operation is required'); return; }
73
- if (operation === 'sync-in-labels') {
74
+ if (!operation || ![
75
+ internalHandlerRoute('platform-pr', 'inspect', operation),
76
+ internalHandlerRoute('platform-pr', 'resolve-external', operation),
77
+ internalHandlerRoute('platform-pr', 'create', operation),
78
+ internalHandlerRoute('platform-pr', 'bind', operation),
79
+ internalHandlerRoute('platform-pr', 'skip', operation),
80
+ internalHandlerRoute('platform-pr', 'sync', operation),
81
+ internalHandlerRoute('platform-pr', 'sync-in-labels', operation),
82
+ internalHandlerRoute('platform-pr', 'summary-context', operation),
83
+ internalHandlerRoute('platform-pr', 'change-report', operation),
84
+ internalHandlerRoute('platform-pr', 'summary-sync', operation)
85
+ ].some(Boolean)) { fail('a valid operation is required'); return; }
86
+ if (internalHandlerRoute('platform-pr', 'sync-in-labels', operation)) {
74
87
  const parsed = parse(args, 1);
75
88
  if (parsed.error) { fail(parsed.error); return; }
76
89
  const values = parsed.values;
@@ -102,20 +115,20 @@ async function platformPr(args: string[] = []): Promise<void> {
102
115
  };
103
116
  const unexpected = Object.keys(values).find((name) => !allowed[operation]!.includes(name));
104
117
  if (unexpected) { fail(`${operation} does not accept --${unexpected}`); return; }
105
- if (operation === 'inspect') { finish(await inspectPlatformPullRequest(taskRef, { cwd })); return; }
106
- if (operation === 'summary-context') { finish(await summaryContext(taskRef, { cwd })); return; }
118
+ if (internalHandlerRoute('platform-pr', 'inspect', operation)) { finish(await inspectPlatformPullRequest(taskRef, { cwd })); return; }
119
+ if (internalHandlerRoute('platform-pr', 'summary-context', operation)) { finish(await summaryContext(taskRef, { cwd })); return; }
107
120
  if (typeof values.agent !== 'string' || !values.agent) { fail(`${operation} requires --agent`); return; }
108
121
  const agent = normalizeAgentToken(values.agent);
109
122
  if (!agent) { fail(`invalid --agent '${values.agent}': ${AGENT_USAGE_HINT}`); return; }
110
123
  values.agent = agent;
111
- if (operation === 'change-report') {
124
+ if (internalHandlerRoute('platform-pr', 'change-report', operation)) {
112
125
  if (typeof values.mechanicalFile !== 'string' || typeof values.precheckFile !== 'string') { fail('change-report requires --mechanical-file and --precheck-file'); return; }
113
126
  finish(await reportWrite(taskRef, {
114
127
  cwd, agent: values.agent, mechanicalFile: values.mechanicalFile, precheckFile: values.precheckFile, dryRun: values.dryRun === true
115
128
  }));
116
129
  return;
117
130
  }
118
- if (operation === 'skip') {
131
+ if (internalHandlerRoute('platform-pr', 'skip', operation)) {
119
132
  finish(await skipPlatformPullRequestFact(taskRef, { cwd, agent, dryRun: values.dryRun === true }));
120
133
  return;
121
134
  }
@@ -124,25 +137,25 @@ async function platformPr(args: string[] = []): Promise<void> {
124
137
  fail('--result must be pr_created, pr_reused, or no_op');
125
138
  return;
126
139
  }
127
- if (operation === 'resolve-external') {
140
+ if (internalHandlerRoute('platform-pr', 'resolve-external', operation)) {
128
141
  const pr = values.pr === undefined ? undefined : values.pr;
129
142
  if (pr !== undefined && (typeof pr !== 'string' || !pr)) { fail('resolve-external requires --pr <token>'); return; }
130
143
  finish(await resolveExternalPullRequest(taskRef, { cwd, agent: values.agent, pr, dryRun: values.dryRun === true }));
131
144
  return;
132
145
  }
133
- if (operation === 'bind') {
146
+ if (internalHandlerRoute('platform-pr', 'bind', operation)) {
134
147
  const pr = values.pr;
135
148
  if (typeof pr !== 'string' || !pr) { fail('bind requires --pr <token>'); return; }
136
149
  finish(await bindPlatformPullRequest(taskRef, { cwd, agent: values.agent, pr, dryRun: values.dryRun === true }));
137
150
  return;
138
151
  }
139
- if (operation === 'sync') {
152
+ if (internalHandlerRoute('platform-pr', 'sync', operation)) {
140
153
  if (values.metadata !== true && values.closingIssue !== true) { fail('sync requires --metadata or --closing-issue'); return; }
141
154
  if (!primaryResult) { fail('sync requires --result pr_created, pr_reused, or no_op'); return; }
142
155
  finish(await syncPlatformPullRequest(taskRef, { cwd, agent: values.agent, metadata: values.metadata === true, closingIssue: values.closingIssue === true, primaryResult: primaryResult as 'pr_created' | 'pr_reused' | 'no_op', dryRun: values.dryRun === true }));
143
156
  return;
144
157
  }
145
- if (operation === 'summary-sync') {
158
+ if (internalHandlerRoute('platform-pr', 'summary-sync', operation)) {
146
159
  if (typeof values.bodyFile !== 'string') { fail('summary-sync requires --body-file'); return; }
147
160
  if (typeof values.changeReportFile !== 'string') { fail('summary-sync requires --change-report-file'); return; }
148
161
  if (!primaryResult) { fail('summary-sync requires --result pr_created, pr_reused, or no_op'); return; }
@@ -2,6 +2,7 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
 
4
4
  import { publishReleaseNotes, releaseNoteContext, stageReleaseNotes } from '../platform/release-notes.ts';
5
+ import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.ts';
5
6
 
6
7
  type ParsedOptions = Readonly<{ values: ReadonlyMap<string, string>; switches: ReadonlySet<string> }>;
7
8
 
@@ -37,8 +38,9 @@ function finish(result: { status: string; [key: string]: unknown }): void {
37
38
  }
38
39
 
39
40
  async function platformReleaseNotes(args: string[] = []): Promise<void> {
41
+ if (!ensureInternalHandlerRoute('platform-release-notes', args)) return;
40
42
  const [action, ...rest] = args;
41
- if (action === 'context') {
43
+ if (internalHandlerRoute('platform-release-notes', 'context', action ?? '')) {
42
44
  const parsed = parseOptions(rest, ['--cwd', '--history-limit', '--from-tag', '--to-tag', '--branch']);
43
45
  if (!parsed) return finish(invalidInput('invalid context options'));
44
46
  const cwd = path.resolve(parsed.values.get('--cwd') || process.cwd());
@@ -51,7 +53,7 @@ async function platformReleaseNotes(args: string[] = []): Promise<void> {
51
53
  }, { cwd }));
52
54
  return;
53
55
  }
54
- if (action === 'stage') {
56
+ if (internalHandlerRoute('platform-release-notes', 'stage', action ?? '')) {
55
57
  const parsed = parseOptions(rest, ['--cwd', '--notes-file']);
56
58
  if (!parsed) return finish(invalidInput('invalid stage options'));
57
59
  const notesFile = parsed.values.get('--notes-file');
@@ -62,7 +64,7 @@ async function platformReleaseNotes(args: string[] = []): Promise<void> {
62
64
  ));
63
65
  return;
64
66
  }
65
- if (action === 'publish') {
67
+ if (internalHandlerRoute('platform-release-notes', 'publish', action ?? '')) {
66
68
  const parsed = parseOptions(
67
69
  rest,
68
70
  ['--cwd', '--notes-file', '--tag', '--title', '--expected-sha256'],
@@ -0,0 +1,83 @@
1
+ import path from 'node:path';
2
+
3
+ import { dismissSecurityAlert, readCommentFile, readSecurityAlert } from '../platform/security-alerts.ts';
4
+ import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.ts';
5
+
6
+ const USAGE = `Usage: agent-infra-internal platform-security read --kind <dependabot|code-scanning> --number <number> [--cwd <path>]
7
+ agent-infra-internal platform-security dismiss --kind <dependabot|code-scanning> --number <number> --reason <reason> --comment-file <path> [--cwd <path>]
8
+ `;
9
+
10
+ function fail(message: string): void {
11
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'SECURITY_INPUT_INVALID', message, retryable: false } })}\n`);
12
+ process.stderr.write(USAGE);
13
+ process.exitCode = 1;
14
+ }
15
+
16
+ function finish(result: { status: string; [key: string]: unknown }): void {
17
+ process.stdout.write(`${JSON.stringify(result)}\n`);
18
+ process.exitCode = result.status === 'blocked' ? 2 : result.status === 'failed' ? 1 : 0;
19
+ }
20
+
21
+ function parseOptions(args: string[]): { values: Map<string, string>; switches: Set<string> } | null {
22
+ const values = new Map<string, string>();
23
+ const switches = new Set<string>();
24
+ const valueFlags = new Set(['--cwd', '--kind', '--number', '--reason', '--comment-file']);
25
+ for (let index = 0; index < args.length; index += 1) {
26
+ const flag = args[index]!;
27
+ if (flag === '--help' || flag === '-h') return null;
28
+ if (!valueFlags.has(flag) || values.has(flag) || switches.has(flag)) return null;
29
+ const value = args[++index];
30
+ if (!value || value.startsWith('--')) return null;
31
+ values.set(flag, value);
32
+ }
33
+ return { values, switches };
34
+ }
35
+
36
+ function required(values: Map<string, string>, flag: string): string | null {
37
+ const value = values.get(flag);
38
+ return value && !value.startsWith('--') ? value : null;
39
+ }
40
+
41
+ async function platformSecurity(args: string[] = []): Promise<void> {
42
+ if (!ensureInternalHandlerRoute('platform-security', args)) return;
43
+ if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
44
+ const action = args[0];
45
+ if (!internalHandlerRoute('platform-security', 'read', action ?? '')
46
+ && !internalHandlerRoute('platform-security', 'dismiss', action ?? '')) {
47
+ fail('a valid operation is required');
48
+ return;
49
+ }
50
+ if (action !== 'read' && action !== 'dismiss') { fail('a valid operation is required'); return; }
51
+ const parsed = parseOptions(args.slice(1));
52
+ if (!parsed) { fail('invalid security alert options'); return; }
53
+ const kind = required(parsed.values, '--kind');
54
+ const numberRaw = required(parsed.values, '--number');
55
+ const cwd = path.resolve(required(parsed.values, '--cwd') || process.cwd());
56
+ if (!kind || !numberRaw) { fail(`${action} requires --kind and --number`); return; }
57
+ const number = Number(numberRaw);
58
+ if (!Number.isSafeInteger(number) || number <= 0) { fail('--number must be a positive integer'); return; }
59
+
60
+ if (action === 'read') {
61
+ if ([...parsed.values.keys()].some((flag) => !['--kind', '--number', '--cwd'].includes(flag))) {
62
+ fail('read does not accept dismissal options');
63
+ return;
64
+ }
65
+ finish(await readSecurityAlert({ kind: kind as 'dependabot' | 'code-scanning', number }, { cwd }));
66
+ return;
67
+ }
68
+
69
+ const reason = required(parsed.values, '--reason');
70
+ const commentFile = required(parsed.values, '--comment-file');
71
+ if (!reason || !commentFile) { fail('dismiss requires --reason and --comment-file'); return; }
72
+ const comment = readCommentFile(commentFile, cwd);
73
+ if (!comment.ok) {
74
+ finish({ status: 'failed', changed: false, error: comment.error });
75
+ return;
76
+ }
77
+ finish(await dismissSecurityAlert(
78
+ { kind: kind as 'dependabot' | 'code-scanning', number, reason, comment: comment.value },
79
+ { cwd }
80
+ ));
81
+ }
82
+
83
+ export { platformSecurity };
@@ -11,6 +11,7 @@ import {
11
11
  import type { DecisionRecord, HostResolution } from '../pr-review/evidence-grading.ts';
12
12
  import { inspectPlatformPullRequestByNumber } from '../platform/pull-requests.ts';
13
13
  import { verifyInProcess } from '../task/verification-engine.ts';
14
+ import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.ts';
14
15
 
15
16
  const USAGE = `Usage: agent-infra-internal pr-review-grade decide --input-file <path|-> [--cwd <path>]
16
17
  agent-infra-internal pr-review-grade resolve-host --pr <token> [--cwd <path>]
@@ -50,9 +51,14 @@ function readInput(value: string, cwd: string): string {
50
51
  }
51
52
 
52
53
  async function prReviewGrade(args: string[] = []): Promise<void> {
54
+ if (!ensureInternalHandlerRoute('pr-review-grade', args)) return;
53
55
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
54
56
  const operation = args[0];
55
- if (!operation || !['decide', 'resolve-host', 'verify-artifact'].includes(operation)) { fail('a valid operation is required'); return; }
57
+ if (!operation || ![
58
+ internalHandlerRoute('pr-review-grade', 'decide', operation),
59
+ internalHandlerRoute('pr-review-grade', 'resolve-host', operation),
60
+ internalHandlerRoute('pr-review-grade', 'verify-artifact', operation)
61
+ ].some(Boolean)) { fail('a valid operation is required'); return; }
56
62
  const parsed = parseFlags(args, 1);
57
63
  if (parsed.error) { fail(parsed.error); return; }
58
64
  const values = parsed.values;
@@ -65,7 +71,7 @@ async function prReviewGrade(args: string[] = []): Promise<void> {
65
71
  const unexpected = Object.keys(values).find((key) => !allowed[operation]!.includes(key));
66
72
  if (unexpected) { fail(`${operation} does not accept '--${unexpected}'`); return; }
67
73
 
68
- if (operation === 'decide') {
74
+ if (internalHandlerRoute('pr-review-grade', 'decide', operation)) {
69
75
  if (typeof values.inputFile !== 'string') { fail('decide requires --input-file'); return; }
70
76
  let input: unknown;
71
77
  try {
@@ -84,7 +90,7 @@ async function prReviewGrade(args: string[] = []): Promise<void> {
84
90
  return;
85
91
  }
86
92
 
87
- if (operation === 'resolve-host') {
93
+ if (internalHandlerRoute('pr-review-grade', 'resolve-host', operation)) {
88
94
  const pr = typeof values.pr === 'string' ? values.pr : '';
89
95
  if (!pr) { fail('resolve-host requires --pr <token>'); return; }
90
96
  const inspected = await inspectPlatformPullRequestByNumber(pr, { cwd });
@@ -109,6 +115,7 @@ async function prReviewGrade(args: string[] = []): Promise<void> {
109
115
  return;
110
116
  }
111
117
 
118
+ if (!internalHandlerRoute('pr-review-grade', 'verify-artifact', operation)) { fail('operation is not registered'); return; }
112
119
  if (typeof values.artifactFile !== 'string') { fail('verify-artifact requires --artifact-file'); return; }
113
120
  const artifactPath = path.resolve(cwd, values.artifactFile);
114
121
  let result: Record<string, unknown>;
@@ -9,6 +9,7 @@ import { inspectPlatformRelease, reconcileReleaseMilestones } from '../platform/
9
9
  import { inspectHomebrewChannel, inspectNpmChannel } from '../release/channels.ts';
10
10
  import { releaseSnapshot } from '../release/workflow.ts';
11
11
  import type { PostReleaseFacts, ReleaseFacts } from '../release/workflow.ts';
12
+ import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.ts';
12
13
 
13
14
  function command(cwd: string, executable: string, args: string[]) {
14
15
  return spawnSync(executable, args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
@@ -312,17 +313,24 @@ async function releaseWorkflow(args: string[] = []): Promise<void> {
312
313
  const version = String(rawVersion || '').replace(/^v/, '');
313
314
  const cwdIndex = rest.indexOf('--cwd');
314
315
  const cwd = path.resolve(cwdIndex >= 0 && rest[cwdIndex + 1] ? rest[cwdIndex + 1]! : process.cwd());
315
- if (!['inspect', 'prepare', 'publish', 'post-prepare', 'post-publish'].includes(action || '') || !semver.valid(version)) {
316
+ if (![
317
+ internalHandlerRoute('release-workflow', 'inspect', action || ''),
318
+ internalHandlerRoute('release-workflow', 'prepare', action || ''),
319
+ internalHandlerRoute('release-workflow', 'publish', action || ''),
320
+ internalHandlerRoute('release-workflow', 'post-prepare', action || ''),
321
+ internalHandlerRoute('release-workflow', 'post-publish', action || '')
322
+ ].some(Boolean) || !semver.valid(version)) {
316
323
  process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'RELEASE_INPUT_INVALID', message: 'Usage: release-workflow inspect|prepare|publish|post-prepare|post-publish <version>' } })}\n`);
317
324
  process.exitCode = 1; return;
318
325
  }
326
+ if (!ensureInternalHandlerRoute('release-workflow', args)) return;
319
327
  const before = releaseSnapshot(version, await inspectFacts(cwd, version));
320
- if (action === 'inspect') { process.stdout.write(`${JSON.stringify({ status: 'no-op', changed: false, snapshot: before, error: null })}\n`); return; }
328
+ if (internalHandlerRoute('release-workflow', 'inspect', action || '')) { process.stdout.write(`${JSON.stringify({ status: 'no-op', changed: false, snapshot: before, error: null })}\n`); return; }
321
329
  if (before.facts.localTagConflict) {
322
330
  process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, snapshot: before, error: { code: 'GIT_TAG_CONFLICT', message: `Tag v${version} is not reachable from HEAD` } })}\n`);
323
331
  process.exitCode = 1; return;
324
332
  }
325
- if (action === 'prepare') {
333
+ if (internalHandlerRoute('release-workflow', 'prepare', action || '')) {
326
334
  if (before.phase !== 'unprepared') {
327
335
  const milestones = await reconcileReleaseMilestones(version, { cwd });
328
336
  process.stdout.write(`${JSON.stringify({ ...milestones, snapshot: before })}\n`);
@@ -352,14 +360,14 @@ async function releaseWorkflow(args: string[] = []): Promise<void> {
352
360
  process.stdout.write(`${JSON.stringify({ status, changed: true, snapshot, operations: milestones?.operations ?? [], error: tagged.status !== 0 ? { code: 'GIT_TAG_FAILED', message: String(tagged.stderr) } : milestones?.error ?? null })}\n`);
353
361
  process.exitCode = failed ? 1 : blocked ? 2 : 0; return;
354
362
  }
355
- if (action === 'publish') {
363
+ if (internalHandlerRoute('release-workflow', 'publish', action || '')) {
356
364
  if (!before.facts.localTag || !['prepared', 'partially-published'].includes(before.phase)) { process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, snapshot: before, error: { code: 'RELEASE_PHASE_INVALID', message: `Cannot publish from ${before.phase}` } })}\n`); process.exitCode = 1; return; }
357
365
  const branch = git(cwd, ['branch', '--show-current']) || '';
358
366
  const refs = [...(!before.facts.remoteBranch ? [branch] : []), ...(!before.facts.remoteTag ? [`refs/tags/v${version}`] : [])];
359
367
  const result = pushGitRefs({ cwd, remote: 'origin', refs });
360
368
  process.stdout.write(`${JSON.stringify({ ...result, snapshot: releaseSnapshot(version, await inspectFacts(cwd, version)) })}\n`); process.exitCode = result.status === 'failed' ? 1 : result.status === 'degraded' ? 2 : 0; return;
361
369
  }
362
- if (action === 'post-publish') {
370
+ if (internalHandlerRoute('release-workflow', 'post-publish', action || '')) {
363
371
  const expectedValues = optionValues(rest, '--expected-sha256');
364
372
  if (expectedValues.length !== 1 || !/^sha256:[0-9a-f]{64}$/.test(expectedValues[0]!)) {
365
373
  process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, snapshot: before, error: { code: 'RELEASE_INPUT_INVALID', message: 'post-publish requires one --expected-sha256 sha256:<64 hex>' } })}\n`);
@@ -394,6 +402,10 @@ async function releaseWorkflow(args: string[] = []): Promise<void> {
394
402
  process.exitCode = blocked ? 2 : 1; return;
395
403
  }
396
404
 
405
+ if (!internalHandlerRoute('release-workflow', 'post-prepare', action || '')) {
406
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, snapshot: before, error: { code: 'RELEASE_INPUT_INVALID', message: 'release-workflow action is not registered' } })}\n`);
407
+ process.exitCode = 1; return;
408
+ }
397
409
  if (before.phase === 'complete') {
398
410
  process.stdout.write(`${JSON.stringify({ status: 'no-op', changed: false, snapshot: before, error: null })}\n`);
399
411
  return;
@@ -12,6 +12,8 @@ import {
12
12
  controllerProofFromContext,
13
13
  verifyCodexSandboxControllerContextWithWarnings
14
14
  } from '../agent-clients/adapters/codex-lifecycle/sandbox-controller.ts';
15
+ import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.ts';
16
+ import { parseTaskCreateResult, taskCreateExitCode } from '../task/create-service.ts';
15
17
 
16
18
  function isCanonicalCodexPrepare(args: readonly string[]): boolean {
17
19
  if (args[1] !== 'prepare') return false;
@@ -45,6 +47,17 @@ function writeClientError(error: SandboxControlClientError): void {
45
47
  if (error.requestId) process.stderr.write(`SANDBOX_CONTROL_REQUEST_ID: ${error.requestId}\n`);
46
48
  }
47
49
 
50
+ function recoveredExitCode(response: Awaited<ReturnType<typeof recoverSandboxControl>>): number {
51
+ if (response.phase !== 'completed') return response.exitCode ?? 1;
52
+ try {
53
+ const result = parseTaskCreateResult(JSON.parse(response.stdout));
54
+ if (result.control?.requestId === response.id) return taskCreateExitCode(result);
55
+ } catch {
56
+ // Other control families use their own result envelopes.
57
+ }
58
+ return response.exitCode ?? 1;
59
+ }
60
+
48
61
  function sandboxFinalizationClient(args: string[]): void {
49
62
  if (args.length !== 4 || !args[0] || args[1] !== 'complete' || args[2] !== '--agent' || !args[3]) {
50
63
  const error = { code: 'TASK_FINALIZATION_PAYLOAD_INVALID', message: 'task ref, complete intent, and --agent are required', retryable: false };
@@ -87,8 +100,9 @@ function sandboxFinalizationClient(args: string[]): void {
87
100
  }
88
101
 
89
102
  async function sandboxControl(args: string[]): Promise<void> {
103
+ if (!ensureInternalHandlerRoute('sandbox-control', args)) return;
90
104
  const [operation, ...rest] = args;
91
- if (operation === 'serve') {
105
+ if (internalHandlerRoute('sandbox-control', 'serve', operation ?? '')) {
92
106
  const manifestIndex = rest.indexOf('--manifest');
93
107
  const manifest = manifestIndex >= 0 ? rest[manifestIndex + 1] : undefined;
94
108
  if (!manifest) throw new Error('sandbox-control serve requires --manifest');
@@ -104,7 +118,7 @@ async function sandboxControl(args: string[]): Promise<void> {
104
118
  }
105
119
  return;
106
120
  }
107
- if (operation === 'execute') {
121
+ if (internalHandlerRoute('sandbox-control', 'execute', operation ?? '')) {
108
122
  const requestIndex = rest.indexOf('--request');
109
123
  const nonceIndex = rest.indexOf('--nonce');
110
124
  const request = requestIndex >= 0 ? rest[requestIndex + 1] : undefined;
@@ -113,7 +127,7 @@ async function sandboxControl(args: string[]): Promise<void> {
113
127
  await runSandboxControlExecutor(request, nonce);
114
128
  return;
115
129
  }
116
- if (operation === 'recover') {
130
+ if (internalHandlerRoute('sandbox-control', 'recover', operation ?? '')) {
117
131
  if (rest.length !== 1 || !rest[0]) throw new Error('sandbox-control recover requires <request-id>');
118
132
  let response;
119
133
  try {
@@ -128,10 +142,10 @@ async function sandboxControl(args: string[]): Promise<void> {
128
142
  process.stderr.write(response.stderr);
129
143
  process.exitCode = response.phase === 'rejected'
130
144
  ? response.error?.retryable ? 75 : 1
131
- : response.exitCode ?? 1;
145
+ : recoveredExitCode(response);
132
146
  return;
133
147
  }
134
- if (operation === 'client') {
148
+ if (internalHandlerRoute('sandbox-control', 'client', operation ?? '')) {
135
149
  const [family = '', ...commandArgs] = rest;
136
150
  if (family === 'task-finalization') {
137
151
  sandboxFinalizationClient(commandArgs);
@@ -9,6 +9,7 @@ import type {
9
9
  import { consumeHumanOverride, failureId, overrideDryRunConflict } from '../task/human-override.ts';
10
10
  import { resolveTaskRef } from '../task/resolve-ref.ts';
11
11
  import { TaskExecutionLockError, withTaskExecutionLock } from '../task/task-execution-lock.ts';
12
+ import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.ts';
12
13
 
13
14
  const USAGE = `Usage: agent-infra-internal task-activity <task-ref> pr-review-inspect
14
15
  agent-infra-internal task-activity <task-ref> pr-review-start --agent <agent> --artifact <canonical.md> --head <40hex> [--dry-run]
@@ -44,9 +45,16 @@ function usageFailure(message: string): void {
44
45
  }
45
46
 
46
47
  async function taskActivity(args: string[] = []): Promise<void> {
48
+ if (!ensureInternalHandlerRoute('task-activity', args)) return;
47
49
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
48
50
  const [taskRef, kind] = args;
49
- if (!taskRef || taskRef.startsWith('--') || !kind || !OPERATIONS.has(kind)) {
51
+ if (!taskRef || taskRef.startsWith('--') || !kind || !OPERATIONS.has(kind)
52
+ || ![
53
+ internalHandlerRoute('task-activity', 'pr-review-inspect', kind),
54
+ internalHandlerRoute('task-activity', 'pr-review-start', kind),
55
+ internalHandlerRoute('task-activity', 'pr-review-complete', kind),
56
+ internalHandlerRoute('task-activity', 'pr-review-terminate', kind)
57
+ ].some(Boolean)) {
50
58
  usageFailure('task ref and a supported PR review intent are required');
51
59
  return;
52
60
  }
@@ -72,7 +80,7 @@ async function taskActivity(args: string[] = []): Promise<void> {
72
80
  const allowed = ALLOWED[kind]!;
73
81
  const unexpected = Object.keys(values).find((key) => !allowed.has(key));
74
82
  if (unexpected) { usageFailure(`${kind} does not accept '${unexpected}'`); return; }
75
- if (kind === 'pr-review-inspect') {
83
+ if (internalHandlerRoute('task-activity', 'pr-review-inspect', kind)) {
76
84
  const result = inspectPrReviewActivity(values as PrReviewInspectIntent);
77
85
  process.stdout.write(`${JSON.stringify(result)}\n`);
78
86
  if (result.status === 'failed') process.exitCode = 1;
@@ -81,9 +89,9 @@ async function taskActivity(args: string[] = []): Promise<void> {
81
89
  for (const key of COMMON) {
82
90
  if (values[key] === undefined) { usageFailure(`${kind} requires '${key}'`); return; }
83
91
  }
84
- const operationRequired = kind === 'pr-review-complete'
92
+ const operationRequired = internalHandlerRoute('task-activity', 'pr-review-complete', kind)
85
93
  ? ['verdict', 'blockers', 'major', 'minor']
86
- : kind === 'pr-review-terminate' ? ['outcome', 'reason'] : [];
94
+ : internalHandlerRoute('task-activity', 'pr-review-terminate', kind) ? ['outcome', 'reason'] : [];
87
95
  for (const key of operationRequired) {
88
96
  if (values[key] === undefined) { usageFailure(`${kind} requires '${key}'`); return; }
89
97
  }