@ozzylabs/feedradar 0.1.6 → 0.1.8

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 (106) hide show
  1. package/README.md +2 -1
  2. package/dist/agents/_boundary.d.ts +74 -1
  3. package/dist/agents/_boundary.d.ts.map +1 -1
  4. package/dist/agents/_boundary.js +152 -0
  5. package/dist/agents/_boundary.js.map +1 -1
  6. package/dist/claude-skills/dismiss/SKILL.md +18 -12
  7. package/dist/claude-skills/research/SKILL.md +21 -1
  8. package/dist/claude-skills/review/SKILL.md +23 -1
  9. package/dist/claude-skills/update/SKILL.md +24 -2
  10. package/dist/cli/_commit-path.d.ts +33 -0
  11. package/dist/cli/_commit-path.d.ts.map +1 -0
  12. package/dist/cli/_commit-path.js +43 -0
  13. package/dist/cli/_commit-path.js.map +1 -0
  14. package/dist/cli/dismiss.d.ts +38 -7
  15. package/dist/cli/dismiss.d.ts.map +1 -1
  16. package/dist/cli/dismiss.js +239 -54
  17. package/dist/cli/dismiss.js.map +1 -1
  18. package/dist/cli/index.d.ts.map +1 -1
  19. package/dist/cli/index.js +7 -1
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/cli/items.d.ts +44 -0
  22. package/dist/cli/items.d.ts.map +1 -0
  23. package/dist/cli/items.js +288 -0
  24. package/dist/cli/items.js.map +1 -0
  25. package/dist/cli/research.d.ts +21 -0
  26. package/dist/cli/research.d.ts.map +1 -1
  27. package/dist/cli/research.js +360 -54
  28. package/dist/cli/research.js.map +1 -1
  29. package/dist/cli/review.d.ts +23 -0
  30. package/dist/cli/review.d.ts.map +1 -1
  31. package/dist/cli/review.js +462 -2
  32. package/dist/cli/review.js.map +1 -1
  33. package/dist/cli/source.d.ts.map +1 -1
  34. package/dist/cli/source.js +18 -0
  35. package/dist/cli/source.js.map +1 -1
  36. package/dist/cli/triage.d.ts +136 -0
  37. package/dist/cli/triage.d.ts.map +1 -0
  38. package/dist/cli/triage.js +1110 -0
  39. package/dist/cli/triage.js.map +1 -0
  40. package/dist/cli/undismiss.d.ts +30 -0
  41. package/dist/cli/undismiss.d.ts.map +1 -0
  42. package/dist/cli/undismiss.js +133 -0
  43. package/dist/cli/undismiss.js.map +1 -0
  44. package/dist/cli/update.d.ts.map +1 -1
  45. package/dist/cli/update.js +429 -141
  46. package/dist/cli/update.js.map +1 -1
  47. package/dist/cli/workflow/generate-combined-with-triage.d.ts +163 -0
  48. package/dist/cli/workflow/generate-combined-with-triage.d.ts.map +1 -0
  49. package/dist/cli/workflow/generate-combined-with-triage.js +582 -0
  50. package/dist/cli/workflow/generate-combined-with-triage.js.map +1 -0
  51. package/dist/cli/workflow.d.ts +6 -5
  52. package/dist/cli/workflow.d.ts.map +1 -1
  53. package/dist/cli/workflow.js +13 -8
  54. package/dist/cli/workflow.js.map +1 -1
  55. package/dist/core/feeds/json-api.d.ts +5 -2
  56. package/dist/core/feeds/json-api.d.ts.map +1 -1
  57. package/dist/core/feeds/json-api.js +99 -13
  58. package/dist/core/feeds/json-api.js.map +1 -1
  59. package/dist/core/feeds/types.d.ts +26 -0
  60. package/dist/core/feeds/types.d.ts.map +1 -1
  61. package/dist/core/recipes.d.ts.map +1 -1
  62. package/dist/core/recipes.js +6 -0
  63. package/dist/core/recipes.js.map +1 -1
  64. package/dist/core/transitions.d.ts +30 -0
  65. package/dist/core/transitions.d.ts.map +1 -0
  66. package/dist/core/transitions.js +103 -0
  67. package/dist/core/transitions.js.map +1 -0
  68. package/dist/core/triage/adapter.d.ts +80 -0
  69. package/dist/core/triage/adapter.d.ts.map +1 -0
  70. package/dist/core/triage/adapter.js +128 -0
  71. package/dist/core/triage/adapter.js.map +1 -0
  72. package/dist/core/triage/index.d.ts +105 -0
  73. package/dist/core/triage/index.d.ts.map +1 -0
  74. package/dist/core/triage/index.js +246 -0
  75. package/dist/core/triage/index.js.map +1 -0
  76. package/dist/core/triage/prompt.d.ts +30 -0
  77. package/dist/core/triage/prompt.d.ts.map +1 -0
  78. package/dist/core/triage/prompt.js +157 -0
  79. package/dist/core/triage/prompt.js.map +1 -0
  80. package/dist/core/triage/response.d.ts +114 -0
  81. package/dist/core/triage/response.d.ts.map +1 -0
  82. package/dist/core/triage/response.js +188 -0
  83. package/dist/core/triage/response.js.map +1 -0
  84. package/dist/gemini-commands/research.toml +1 -1
  85. package/dist/gemini-commands/review.toml +1 -1
  86. package/dist/gemini-commands/update.toml +1 -1
  87. package/dist/recipes/aws-whats-new.yaml +36 -1
  88. package/dist/recipes/dev-to.yaml +24 -0
  89. package/dist/schemas/item.d.ts +151 -5
  90. package/dist/schemas/item.d.ts.map +1 -1
  91. package/dist/schemas/item.js +164 -4
  92. package/dist/schemas/item.js.map +1 -1
  93. package/dist/schemas/recipe.d.ts +11 -1
  94. package/dist/schemas/recipe.d.ts.map +1 -1
  95. package/dist/schemas/recipe.js +10 -1
  96. package/dist/schemas/recipe.js.map +1 -1
  97. package/dist/schemas/source.d.ts +65 -4
  98. package/dist/schemas/source.d.ts.map +1 -1
  99. package/dist/schemas/source.js +65 -3
  100. package/dist/schemas/source.js.map +1 -1
  101. package/dist/skills/research/SKILL.md +57 -1
  102. package/dist/skills/review/SKILL.md +65 -1
  103. package/dist/skills/update/SKILL.md +54 -1
  104. package/dist/templates/agents/AGENTS.md +30 -0
  105. package/dist/templates/workflows/combined-with-triage.template.yaml.tmpl +132 -0
  106. package/package.json +1 -1
@@ -0,0 +1,582 @@
1
+ import { access, mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { dirname, isAbsolute, join, normalize, relative, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { RESEARCH_BATCH_DEFAULT_MAX_ITEMS } from "../research.js";
5
+ import { SUPPORTED_AGENTS } from "./generate-watch.js";
6
+ /**
7
+ * `radar workflow generate combined-with-triage` (ADR-0018 §W5 / #241).
8
+ *
9
+ * Extends the `combined` generator with the LLM triage layer. The emitted
10
+ * workflow chains 5 steps in one job:
11
+ *
12
+ * watch run -> triage --apply -> research --batch (status=triaged_research)
13
+ * -> research --digest per triage-group -> review --batch (status=researched)
14
+ *
15
+ * Three distinct agents can be wired (triage / research / review) so the
16
+ * cheap-model channel handles triage while heavier models do the LoC-heavy
17
+ * research and the cross-agent review. The job-level `env:` block exposes
18
+ * every selected agent's API key once so each step inherits without
19
+ * per-step duplication (ADR-0014 D5 — API key auth only, never OAuth).
20
+ *
21
+ * A trailing `if: always()` notify step counts the `triaged_unsure` queue
22
+ * depth and (optionally) POSTs it to a Slack webhook so the human-review
23
+ * backlog cannot grow unnoticed. The notify step degrades silently when
24
+ * no webhook is configured.
25
+ */
26
+ /** Default watch cron — 06:00 UTC daily, matching the #241 example. */
27
+ const DEFAULT_WATCH_CRON = "0 6 * * *";
28
+ /**
29
+ * Output modes for the final pipeline step (#258).
30
+ *
31
+ * - `pr` (default): emit a `peter-evans/create-pull-request@v6` step so a
32
+ * human reviews the bot output before it lands on the default branch.
33
+ * - `direct-commit`: commit & push straight to the default branch (no PR
34
+ * gate), dropping `pull-requests: write` from `permissions:`. Mirrors the
35
+ * commit&push step the `watch` / `combined` generators already emit.
36
+ */
37
+ export const OUTPUT_MODES = ["pr", "direct-commit"];
38
+ /** Default output path under `.github/workflows/`. */
39
+ const DEFAULT_OUTPUT = join(".github", "workflows", "feedradar-daily.yaml");
40
+ /**
41
+ * Per-agent `env:` entries (single line each, no surrounding `env:` header).
42
+ *
43
+ * Used by `buildEnvBlock` to assemble a deduped job-level `env:` body that
44
+ * exposes every required secret across the three agent roles. Each line is
45
+ * 10-space indented so it sits under ` env:` (8 spaces, then 2-space
46
+ * map child indentation) when concatenated into the template.
47
+ *
48
+ * `claude-code` / `codex-cli` / `gemini-cli` each declare their API key.
49
+ * Every agent also gets `GITHUB_TOKEN` so the `github-releases` adapter
50
+ * lifts to the 5000 req/h ceiling; the watch step is the same one used in
51
+ * the `combined` generator, so the contract there carries over.
52
+ *
53
+ * `copilot` rides `secrets.GITHUB_TOKEN` natively (its CLI authenticates
54
+ * via the workflow's GH token), so it contributes no additional secret
55
+ * beyond the shared `GITHUB_TOKEN` line everybody gets.
56
+ */
57
+ const AGENT_ENV_LINES = {
58
+ "claude-code": [" ANTHROPIC_API_KEY: $" + "{{ secrets.ANTHROPIC_API_KEY }}"],
59
+ "codex-cli": [" OPENAI_API_KEY: $" + "{{ secrets.OPENAI_API_KEY }}"],
60
+ "gemini-cli": [" GEMINI_API_KEY: $" + "{{ secrets.GEMINI_API_KEY }}"],
61
+ copilot: [],
62
+ };
63
+ /** Always-present line: every step benefits from a higher GH rate limit. */
64
+ const SHARED_GITHUB_TOKEN_LINE = " GITHUB_TOKEN: $" + "{{ secrets.GITHUB_TOKEN }}";
65
+ /**
66
+ * Per-agent human-readable secret names surfaced after a successful
67
+ * generation. Mirrors `generate-combined.ts` so the experience is
68
+ * consistent across both generators.
69
+ */
70
+ const AGENT_SECRET_NAMES = {
71
+ "claude-code": ["ANTHROPIC_API_KEY"],
72
+ "codex-cli": ["OPENAI_API_KEY"],
73
+ "gemini-cli": ["GEMINI_API_KEY"],
74
+ copilot: [],
75
+ };
76
+ async function pathExists(p) {
77
+ try {
78
+ await access(p);
79
+ return true;
80
+ }
81
+ catch {
82
+ return false;
83
+ }
84
+ }
85
+ async function resolveTemplatesRoot() {
86
+ const here = dirname(fileURLToPath(import.meta.url));
87
+ return resolve(here, "..", "..", "templates");
88
+ }
89
+ /**
90
+ * Validate a 5-field POSIX cron expression. Same grammar check as
91
+ * `generate-combined.ts` / `generate-watch.ts`. Range bounds (e.g. month
92
+ * 1-12) are NOT enforced here; GitHub Actions rejects out-of-range
93
+ * expressions on workflow load.
94
+ */
95
+ export function isValidCron(expr) {
96
+ const trimmed = expr.trim();
97
+ if (trimmed.length === 0)
98
+ return false;
99
+ const fields = trimmed.split(/\s+/);
100
+ if (fields.length !== 5)
101
+ return false;
102
+ const tokenPattern = /^(?:\*|\d+(?:-\d+)?)(?:\/\d+)?$/;
103
+ for (const field of fields) {
104
+ if (field.length === 0)
105
+ return false;
106
+ const tokens = field.split(",");
107
+ for (const token of tokens) {
108
+ if (token.length === 0)
109
+ return false;
110
+ if (!tokenPattern.test(token))
111
+ return false;
112
+ }
113
+ }
114
+ return true;
115
+ }
116
+ /**
117
+ * Validate that the requested `--output` path lands under
118
+ * `.github/workflows/`. Mirrors `isSafeWorkflowPath` in `generate-watch.ts`
119
+ * — kept inline here so the two generators don't accidentally drift on
120
+ * the safety contract.
121
+ */
122
+ export function isSafeWorkflowPath(outputPath, cwd) {
123
+ if (isAbsolute(outputPath)) {
124
+ const allowedDir = resolve(cwd, ".github", "workflows");
125
+ const resolved = resolve(outputPath);
126
+ const rel = relative(allowedDir, resolved);
127
+ if (rel.startsWith("..") || isAbsolute(rel))
128
+ return false;
129
+ return /\.(ya?ml)$/i.test(resolved);
130
+ }
131
+ const normalized = normalize(outputPath);
132
+ if (normalized.split(/[\\/]/).includes(".."))
133
+ return false;
134
+ const required = `${join(".github", "workflows")}/`;
135
+ const unixified = normalized.replace(/\\/g, "/");
136
+ if (!unixified.startsWith(required.replace(/\\/g, "/")))
137
+ return false;
138
+ return /\.(ya?ml)$/i.test(unixified);
139
+ }
140
+ /**
141
+ * Validate `--max-items` as a positive integer (mirrors
142
+ * `parseMaxItems` in `src/cli/research.ts`).
143
+ */
144
+ export function isValidMaxItems(raw) {
145
+ if (!/^[0-9]+$/.test(raw))
146
+ return false;
147
+ const n = Number.parseInt(raw, 10);
148
+ return Number.isFinite(n) && n > 0;
149
+ }
150
+ /**
151
+ * Validate `--slack-webhook` shape. Required form: `secrets.<NAME>` (no
152
+ * leading `${{`, no trailing `}}`). The generator wraps the name into a
153
+ * proper GitHub Actions expression at render time so the user does not
154
+ * have to spell it out (and so we cannot accidentally double-wrap).
155
+ *
156
+ * Exported for unit testing.
157
+ */
158
+ export function isValidSlackWebhookRef(raw) {
159
+ return /^secrets\.[A-Z_][A-Z0-9_]*$/i.test(raw);
160
+ }
161
+ /**
162
+ * Build the deduped job-level `env:` body from the chosen triage /
163
+ * research / review agents. Lines are already 6-space indented (so they
164
+ * sit at ` env:` -> ` KEY: value` once the template inserts
165
+ * them at column 0 with `{{envBlock}}`).
166
+ *
167
+ * Order is deterministic (sorted) so generated workflows diff stably
168
+ * across regenerations. `GITHUB_TOKEN` is always last because shared
169
+ * lines come after agent-specific ones.
170
+ */
171
+ export function buildEnvBlock(triageAgent, researchAgent, reviewAgent) {
172
+ const lines = new Set();
173
+ for (const agent of [triageAgent, researchAgent, reviewAgent]) {
174
+ for (const line of AGENT_ENV_LINES[agent]) {
175
+ lines.add(line);
176
+ }
177
+ }
178
+ lines.add(SHARED_GITHUB_TOKEN_LINE);
179
+ return [...lines].sort().join("\n");
180
+ }
181
+ /**
182
+ * Convert a `--slack-webhook secrets.<NAME>` ref into the GitHub Actions
183
+ * expression literal the template needs. Returns an empty string when no
184
+ * webhook was supplied so the `[ -n "..." ]` guard in the rendered
185
+ * notify step short-circuits cleanly.
186
+ */
187
+ export function buildSlackWebhookExpr(raw) {
188
+ if (raw === undefined || raw.trim() === "")
189
+ return '""';
190
+ const trimmed = raw.trim();
191
+ // `secrets.X` -> `${{ secrets.X }}` (full Actions expression literal).
192
+ // biome-ignore lint/style/useTemplate: GitHub Actions expression literal — collapsing into a single template literal would re-trigger noTemplateCurlyInString
193
+ return "$" + `{{ ${trimmed} }}`;
194
+ }
195
+ /**
196
+ * Build the top-level `permissions:` block for the given output mode.
197
+ *
198
+ * - `pr` needs both `contents: write` (to create the branch/commit) and
199
+ * `pull-requests: write` (so `peter-evans/create-pull-request` can open
200
+ * the PR).
201
+ * - `direct-commit` pushes straight to the default branch, so it only needs
202
+ * `contents: write`; emitting `pull-requests: write` would be an unused —
203
+ * and misleading — grant (#258).
204
+ *
205
+ * Exported for unit testing.
206
+ */
207
+ export function buildPermissionsBlock(outputMode) {
208
+ if (outputMode === "direct-commit") {
209
+ return ["permissions:", " contents: write"].join("\n");
210
+ }
211
+ return ["permissions:", " contents: write", " pull-requests: write"].join("\n");
212
+ }
213
+ /**
214
+ * Build the final pipeline step for the given output mode.
215
+ *
216
+ * - `pr`: a `peter-evans/create-pull-request@v6` step that stages
217
+ * `items/ state/ research/` into a single PR per cron tick so a human can
218
+ * review the auto-generated content before it lands on main
219
+ * (ADR-0014 §X5 / ADR-0018 §W5).
220
+ * - `direct-commit`: a commit & push step modeled on the `watch` / `combined`
221
+ * generators — commit only when something changed, then push with a
222
+ * three-attempt `git pull --rebase --autostash` retry loop. No PR gate, so
223
+ * the comment warns against a PR-required branch protection on the default
224
+ * branch (#258).
225
+ *
226
+ * Both blocks are emitted with the same 6-space step indentation as the
227
+ * surrounding steps in the template (the placeholder sits at column 0 where a
228
+ * `- name:` step would normally start). Exported for unit testing.
229
+ */
230
+ export function buildFinalStep(outputMode) {
231
+ if (outputMode === "direct-commit") {
232
+ return [
233
+ " - name: Commit and push research output with retry",
234
+ " # direct-commit output mode (#258): push straight to the default",
235
+ " # branch instead of opening a PR. Commit only when items/ state/",
236
+ " # research/ actually changed, then retry the push up to 3 times with",
237
+ " # `git pull --rebase --autostash` between attempts (ADR-0014 D4),",
238
+ " # mirroring the watch / combined generators.",
239
+ " #",
240
+ " # NB: this mode pushes without a human review gate, so do NOT put a",
241
+ " # PR-required branch protection rule on the default branch — the bot",
242
+ " # commit would be rejected and every run would fail.",
243
+ " run: |",
244
+ " set -euo pipefail",
245
+ ' git config user.name "feedradar-bot"',
246
+ ' git config user.email "feedradar-bot@users.noreply.github.com"',
247
+ " git add items/ state/ research/",
248
+ " if git diff --cached --quiet; then",
249
+ ' echo "nothing staged; exiting cleanly"',
250
+ " exit 0",
251
+ " fi",
252
+ ' git commit -m "chore(feedradar): daily watch + triage + research $(date -u +%Y-%m-%d)"',
253
+ " for attempt in 1 2 3; do",
254
+ // The `${...}` tokens below are bash parameter expansions in the
255
+ // generated YAML, not JS template placeholders, so they are assembled
256
+ // by concatenation to keep biome's noTemplateCurlyInString quiet
257
+ // (same convention as the `${{ ... }}` Actions expressions above).
258
+ ' if git push origin "$' + '{GITHUB_REF_NAME}"; then',
259
+ ' echo "push succeeded on attempt $' + '{attempt}"',
260
+ " exit 0",
261
+ " fi",
262
+ ' echo "push failed (attempt $' + '{attempt}/3), rebasing..."',
263
+ ' git pull --rebase --autostash origin "$' + '{GITHUB_REF_NAME}"',
264
+ " done",
265
+ ' echo "push failed after 3 attempts" >&2',
266
+ " exit 1",
267
+ ].join("\n");
268
+ }
269
+ return [
270
+ " - name: Create PR with research output",
271
+ " # `peter-evans/create-pull-request@v6` stages items/ state/ research/",
272
+ " # into a single PR per cron tick. Human reviews the PR before",
273
+ " # research/ lands on main, giving an explicit gate on auto-generated",
274
+ " # content (ADR-0014 §X5 / ADR-0018 §W5).",
275
+ " uses: peter-evans/create-pull-request@v6",
276
+ " with:",
277
+ ' commit-message: "chore(feedradar): daily watch + triage + research"',
278
+ " # peter-evans/create-pull-request does not run shell on these",
279
+ " # fields, so `$(date ...)` would land literally in the PR title.",
280
+ " # Use the `github.run_id` expression to keep titles unique per run.",
281
+ ' title: "feedradar: daily triage + research (run $' + '{{ github.run_id }})"',
282
+ " body: |",
283
+ " Automated feedradar pipeline output. Review the research/ Markdown",
284
+ " before merging — generated content is untrusted (ADR-0009).",
285
+ " branch: feedradar/daily",
286
+ " base: $" + "{{ github.ref_name }}",
287
+ " delete-branch: true",
288
+ " add-paths: |",
289
+ " items/",
290
+ " state/",
291
+ " research/",
292
+ ].join("\n");
293
+ }
294
+ /**
295
+ * Render the bundled template by substituting `{{watchCron}}` /
296
+ * `{{maxItems}}` / `{{triageAgent}}` / `{{researchAgent}}` /
297
+ * `{{reviewAgent}}` / `{{envBlock}}` / `{{slackWebhookExpr}}` /
298
+ * `{{permissionsBlock}}` / `{{finalStep}}`.
299
+ */
300
+ export function renderCombinedWithTriageTemplate(template, values) {
301
+ return template
302
+ .replaceAll("{{watchCron}}", values.watchCron)
303
+ .replaceAll("{{maxItems}}", String(values.maxItems))
304
+ .replaceAll("{{triageAgent}}", values.triageAgent)
305
+ .replaceAll("{{researchAgent}}", values.researchAgent)
306
+ .replaceAll("{{reviewAgent}}", values.reviewAgent)
307
+ .replaceAll("{{envBlock}}", values.envBlock)
308
+ .replaceAll("{{slackWebhookExpr}}", values.slackWebhookExpr)
309
+ .replaceAll("{{permissionsBlock}}", values.permissionsBlock)
310
+ .replaceAll("{{finalStep}}", values.finalStep);
311
+ }
312
+ /**
313
+ * Core implementation of `radar workflow generate combined-with-triage`.
314
+ *
315
+ * Validates inputs, reads the bundled template, substitutes placeholders,
316
+ * and writes the result. The completion stdout enumerates every secret the
317
+ * user must register (across all three agent roles plus the optional
318
+ * Slack webhook) so they do not have to grep the YAML.
319
+ */
320
+ export async function generateCombinedWithTriage(options) {
321
+ const { cwd, watchCron, output, triageAgent, researchAgent, reviewAgent, maxItems, outputMode, force, } = options;
322
+ const log = options.io?.log ?? ((m) => console.log(m));
323
+ const warn = options.io?.warn ?? ((m) => console.warn(m));
324
+ if (!isValidCron(watchCron)) {
325
+ throw new Error(`invalid --watch-cron expression '${watchCron}' (expected 5-field POSIX cron, e.g. "0 6 * * *")`);
326
+ }
327
+ if (!isSafeWorkflowPath(output, cwd)) {
328
+ throw new Error(`invalid --output '${output}' (must be a relative path under .github/workflows/ ending in .yaml or .yml)`);
329
+ }
330
+ if (!Number.isInteger(maxItems) || maxItems <= 0) {
331
+ throw new Error(`invalid --max-items '${maxItems}' (must be a positive integer)`);
332
+ }
333
+ if (options.slackWebhook !== undefined && !isValidSlackWebhookRef(options.slackWebhook)) {
334
+ throw new Error(`invalid --slack-webhook '${options.slackWebhook}' (expected 'secrets.<NAME>', e.g. 'secrets.SLACK_WEBHOOK')`);
335
+ }
336
+ if (!OUTPUT_MODES.includes(outputMode)) {
337
+ throw new Error(`invalid --output-mode '${outputMode}' (expected one of: ${OUTPUT_MODES.join(" | ")})`);
338
+ }
339
+ const templatesRoot = options.templatesRoot ?? (await resolveTemplatesRoot());
340
+ const templatePath = join(templatesRoot, "workflows", "combined-with-triage.template.yaml.tmpl");
341
+ if (!(await pathExists(templatePath))) {
342
+ throw new Error(`bundled template not found: ${templatePath}`);
343
+ }
344
+ const template = await readFile(templatePath, "utf8");
345
+ const envBlock = buildEnvBlock(triageAgent, researchAgent, reviewAgent);
346
+ const slackWebhookExpr = buildSlackWebhookExpr(options.slackWebhook);
347
+ const permissionsBlock = buildPermissionsBlock(outputMode);
348
+ const finalStep = buildFinalStep(outputMode);
349
+ const rendered = renderCombinedWithTriageTemplate(template, {
350
+ watchCron,
351
+ maxItems,
352
+ triageAgent,
353
+ researchAgent,
354
+ reviewAgent,
355
+ envBlock,
356
+ slackWebhookExpr,
357
+ permissionsBlock,
358
+ finalStep,
359
+ });
360
+ const destAbs = isAbsolute(output) ? output : join(cwd, output);
361
+ const destRel = isAbsolute(output) ? relative(cwd, output) : output;
362
+ if ((await pathExists(destAbs)) && !force) {
363
+ throw new Error(`output file already exists: ${destRel} (use --force to overwrite)`);
364
+ }
365
+ if ((await pathExists(destAbs)) && force) {
366
+ warn(`workflow generate combined-with-triage: overwriting existing file ${destRel}`);
367
+ }
368
+ await mkdir(dirname(destAbs), { recursive: true });
369
+ await writeFile(destAbs, rendered, "utf8");
370
+ // Deduped secret list across all three agent roles + optional Slack.
371
+ const secrets = new Set();
372
+ for (const agent of [triageAgent, researchAgent, reviewAgent]) {
373
+ for (const s of AGENT_SECRET_NAMES[agent])
374
+ secrets.add(s);
375
+ }
376
+ if (options.slackWebhook !== undefined) {
377
+ // strip the `secrets.` prefix when surfacing to the user.
378
+ secrets.add(options.slackWebhook.replace(/^secrets\./, ""));
379
+ }
380
+ const sortedSecrets = [...secrets].sort();
381
+ log(`workflow generate combined-with-triage: wrote ${destRel}`);
382
+ log(` watch-cron: ${watchCron}`);
383
+ log(` triage-agent: ${triageAgent}`);
384
+ log(` research-agent: ${researchAgent}`);
385
+ log(` review-agent: ${reviewAgent}`);
386
+ log(` max-items: ${maxItems}`);
387
+ log(` output-mode: ${outputMode}`);
388
+ log(` slack-webhook: ${options.slackWebhook ?? "(none — notify step no-ops)"}`);
389
+ log("");
390
+ log("Required GitHub Actions secrets (Settings → Secrets and variables → Actions):");
391
+ if (sortedSecrets.length === 0) {
392
+ log(" (none — every selected agent rides the auto-provisioned GITHUB_TOKEN)");
393
+ }
394
+ else {
395
+ for (const s of sortedSecrets) {
396
+ log(` ${s}`);
397
+ }
398
+ }
399
+ log(" GITHUB_TOKEN (auto-provisioned, no setup needed)");
400
+ warn("workflow generate combined-with-triage: the --max-items cap is also enforced by `radar research --batch`; editing the YAML alone will not raise it");
401
+ return { outputPath: destRel, requiredSecrets: sortedSecrets };
402
+ }
403
+ /**
404
+ * Parse `workflow generate combined-with-triage` flags.
405
+ *
406
+ * Throws on missing values, unknown flags, unsupported agent choices, and
407
+ * malformed numeric / slack-webhook input so the caller can surface
408
+ * validation errors before any IO happens.
409
+ */
410
+ export function parseGenerateCombinedWithTriageArgs(args) {
411
+ let watchCron = DEFAULT_WATCH_CRON;
412
+ let output = DEFAULT_OUTPUT;
413
+ let triageAgent = "gemini-cli";
414
+ let researchAgent = "claude-code";
415
+ let reviewAgent = "codex-cli";
416
+ let maxItems = RESEARCH_BATCH_DEFAULT_MAX_ITEMS;
417
+ let slackWebhook;
418
+ let outputMode = "pr";
419
+ let force = false;
420
+ let help = false;
421
+ function parseAgentFlag(flag, value) {
422
+ if (value === undefined)
423
+ throw new Error(`option ${flag} requires a value`);
424
+ if (!SUPPORTED_AGENTS.includes(value)) {
425
+ throw new Error(`option ${flag} expects one of: ${SUPPORTED_AGENTS.join(" | ")}, got '${value}'`);
426
+ }
427
+ return value;
428
+ }
429
+ for (let i = 0; i < args.length; i++) {
430
+ const a = args[i];
431
+ if (a === "-h" || a === "--help") {
432
+ help = true;
433
+ continue;
434
+ }
435
+ if (a === "--watch-cron") {
436
+ const value = args[++i];
437
+ if (value === undefined)
438
+ throw new Error(`option ${a} requires a value`);
439
+ watchCron = value;
440
+ continue;
441
+ }
442
+ if (a === "--output") {
443
+ const value = args[++i];
444
+ if (value === undefined)
445
+ throw new Error(`option ${a} requires a value`);
446
+ output = value;
447
+ continue;
448
+ }
449
+ if (a === "--triage-agent") {
450
+ triageAgent = parseAgentFlag(a, args[++i]);
451
+ continue;
452
+ }
453
+ if (a === "--research-agent") {
454
+ researchAgent = parseAgentFlag(a, args[++i]);
455
+ continue;
456
+ }
457
+ if (a === "--review-agent") {
458
+ reviewAgent = parseAgentFlag(a, args[++i]);
459
+ continue;
460
+ }
461
+ if (a === "--max-items") {
462
+ const value = args[++i];
463
+ if (value === undefined)
464
+ throw new Error(`option ${a} requires a value`);
465
+ if (!isValidMaxItems(value)) {
466
+ throw new Error(`option --max-items expects a positive integer, got '${value}'`);
467
+ }
468
+ maxItems = Number.parseInt(value, 10);
469
+ continue;
470
+ }
471
+ if (a === "--slack-webhook") {
472
+ const value = args[++i];
473
+ if (value === undefined)
474
+ throw new Error(`option ${a} requires a value`);
475
+ if (!isValidSlackWebhookRef(value)) {
476
+ throw new Error(`option --slack-webhook expects 'secrets.<NAME>', got '${value}'`);
477
+ }
478
+ slackWebhook = value;
479
+ continue;
480
+ }
481
+ if (a === "--output-mode") {
482
+ const value = args[++i];
483
+ if (value === undefined)
484
+ throw new Error(`option ${a} requires a value`);
485
+ if (!OUTPUT_MODES.includes(value)) {
486
+ throw new Error(`option --output-mode expects one of: ${OUTPUT_MODES.join(" | ")}, got '${value}'`);
487
+ }
488
+ outputMode = value;
489
+ continue;
490
+ }
491
+ if (a === "--force" || a === "-f") {
492
+ force = true;
493
+ continue;
494
+ }
495
+ if (a?.startsWith("--") || a?.startsWith("-")) {
496
+ throw new Error(`unknown option: ${a}`);
497
+ }
498
+ throw new Error(`unexpected positional argument: ${a}`);
499
+ }
500
+ return {
501
+ watchCron,
502
+ output,
503
+ triageAgent,
504
+ researchAgent,
505
+ reviewAgent,
506
+ maxItems,
507
+ slackWebhook,
508
+ outputMode,
509
+ force,
510
+ help,
511
+ };
512
+ }
513
+ export function printGenerateCombinedWithTriageHelp(log) {
514
+ log("Usage: radar workflow generate combined-with-triage [options]");
515
+ log("");
516
+ log("Generates a GitHub Actions workflow that chains `radar watch run` ->");
517
+ log("`radar triage --apply` -> `radar research --batch --status triaged_research` ->");
518
+ log("per-group `radar research --digest` -> `radar review --batch` in one job");
519
+ log("(ADR-0018 §W5).");
520
+ log("");
521
+ log("Options:");
522
+ log(` --watch-cron <expression> 5-field cron expression (default: "${DEFAULT_WATCH_CRON}")`);
523
+ log(" --output <path> Output file under .github/workflows/");
524
+ log(` (default: ${DEFAULT_OUTPUT})`);
525
+ log(" --triage-agent <name> claude-code | codex-cli | gemini-cli | copilot (default: gemini-cli)");
526
+ log(" --research-agent <name> claude-code | codex-cli | gemini-cli | copilot (default: claude-code)");
527
+ log(" --review-agent <name> claude-code | codex-cli | gemini-cli | copilot (default: codex-cli)");
528
+ log(` --max-items N Hard cap on research --batch per run (default: ${RESEARCH_BATCH_DEFAULT_MAX_ITEMS})`);
529
+ log(" --slack-webhook <ref> Secret reference (e.g. secrets.SLACK_WEBHOOK) for the");
530
+ log(" triaged_unsure-queue alert (optional)");
531
+ log(" --output-mode <mode> pr | direct-commit (default: pr). 'pr' opens a");
532
+ log(" review PR; 'direct-commit' commits & pushes straight");
533
+ log(" to the default branch (drops pull-requests: write)");
534
+ log(" --force, -f Overwrite existing output file");
535
+ log("");
536
+ log("Required secrets (Settings → Secrets and variables → Actions):");
537
+ log(" ANTHROPIC_API_KEY when any role uses --agent claude-code");
538
+ log(" OPENAI_API_KEY when any role uses --agent codex-cli");
539
+ log(" GEMINI_API_KEY when any role uses --agent gemini-cli (default for triage)");
540
+ log(" GITHUB_TOKEN auto-provisioned (no manual setup needed)");
541
+ }
542
+ /**
543
+ * Entry point invoked by `runWorkflow` when the user types
544
+ * `radar workflow generate combined-with-triage`.
545
+ */
546
+ export async function runGenerateCombinedWithTriage(args, io = {}, cwd = process.cwd()) {
547
+ const log = io.log ?? ((m) => console.log(m));
548
+ const error = io.error ?? ((m) => console.error(m));
549
+ let parsed;
550
+ try {
551
+ parsed = parseGenerateCombinedWithTriageArgs(args);
552
+ }
553
+ catch (e) {
554
+ error(`workflow generate combined-with-triage: ${e instanceof Error ? e.message : String(e)}`);
555
+ return 2;
556
+ }
557
+ if (parsed.help) {
558
+ printGenerateCombinedWithTriageHelp(log);
559
+ return 0;
560
+ }
561
+ try {
562
+ await generateCombinedWithTriage({
563
+ cwd,
564
+ watchCron: parsed.watchCron,
565
+ output: parsed.output,
566
+ triageAgent: parsed.triageAgent,
567
+ researchAgent: parsed.researchAgent,
568
+ reviewAgent: parsed.reviewAgent,
569
+ maxItems: parsed.maxItems,
570
+ slackWebhook: parsed.slackWebhook,
571
+ outputMode: parsed.outputMode,
572
+ force: parsed.force,
573
+ io,
574
+ });
575
+ return 0;
576
+ }
577
+ catch (e) {
578
+ error(`workflow generate combined-with-triage: ${e instanceof Error ? e.message : String(e)}`);
579
+ return 1;
580
+ }
581
+ }
582
+ //# sourceMappingURL=generate-combined-with-triage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-combined-with-triage.js","sourceRoot":"","sources":["../../../src/cli/workflow/generate-combined-with-triage.ts"],"names":[],"mappings":"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"}
@@ -17,12 +17,13 @@ export interface WorkflowCommandOptions {
17
17
  /**
18
18
  * Dispatcher for `radar workflow <subcommand>`.
19
19
  *
20
- * Today the supported subcommands are `generate watch` (#188) and
21
- * `generate combined` (this issue, #189). Additional `<type>` values
22
- * (`research` / `review` per #191) will land as new branches in the
23
- * `generate` switch without changing the surface.
20
+ * Supported subcommands: `generate watch` (#188), `generate combined`
21
+ * (#189), and `generate combined-with-triage` (#241 / ADR-0018 §W5).
22
+ * Additional `<type>` values (`research` / `review` per #191) will land
23
+ * as new branches in the `generate` switch without changing the surface.
24
24
  *
25
- * See ADR-0014 (workflow generate sub-command) for the full design rationale.
25
+ * See ADR-0014 (workflow generate sub-command) and ADR-0018 (LLM-based
26
+ * triage extension) for the full design rationale.
26
27
  */
27
28
  export declare function runWorkflow(args: string[], options?: WorkflowCommandOptions): Promise<number>;
28
29
  export declare const workflowCommand: Command;
@@ -1 +1 @@
1
- {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/cli/workflow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAI1C;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,sBAAsB;IACrC,qEAAqE;IACrE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,UAAU,CAAC;CACjB;AAsBD;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,MAAM,CAAC,CAiCjB;AAED,eAAO,MAAM,eAAe,EAAE,OAI7B,CAAC"}
1
+ {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/cli/workflow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAK1C;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,sBAAsB;IACrC,qEAAqE;IACrE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,UAAU,CAAC;CACjB;AA6BD;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,MAAM,CAAC,CAmCjB;AAED,eAAO,MAAM,eAAe,EAAE,OAI7B,CAAC"}