@ozzylabs/feedradar 0.1.9 → 0.2.1
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.
- package/README.ja.md +6 -3
- package/README.md +6 -3
- package/dist/agents/_boundary.d.ts +44 -0
- package/dist/agents/_boundary.d.ts.map +1 -1
- package/dist/agents/_boundary.js +80 -0
- package/dist/agents/_boundary.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init.d.ts +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +10 -3
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/routine/fire.d.ts +100 -0
- package/dist/cli/routine/fire.d.ts.map +1 -0
- package/dist/cli/routine/fire.js +196 -0
- package/dist/cli/routine/fire.js.map +1 -0
- package/dist/cli/routine/generate-pipeline.d.ts +162 -0
- package/dist/cli/routine/generate-pipeline.d.ts.map +1 -0
- package/dist/cli/routine/generate-pipeline.js +480 -0
- package/dist/cli/routine/generate-pipeline.js.map +1 -0
- package/dist/cli/routine/generate-watch.d.ts +174 -0
- package/dist/cli/routine/generate-watch.d.ts.map +1 -0
- package/dist/cli/routine/generate-watch.js +450 -0
- package/dist/cli/routine/generate-watch.js.map +1 -0
- package/dist/cli/routine.d.ts +32 -0
- package/dist/cli/routine.d.ts.map +1 -0
- package/dist/cli/routine.js +74 -0
- package/dist/cli/routine.js.map +1 -0
- package/dist/cli/triage.d.ts.map +1 -1
- package/dist/cli/triage.js +383 -78
- package/dist/cli/triage.js.map +1 -1
- package/dist/templates/agents/AGENTS.md +1 -1
- package/dist/templates/routines/pipeline.yaml.tmpl +222 -0
- package/dist/templates/routines/watch-daily.yaml +157 -0
- package/dist/templates/routines/watch.yaml.tmpl +151 -0
- package/package.json +1 -1
- package/dist/templates/routines/watch-daily.md +0 -42
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { collectSourceHosts, isSafeRoutinePath, isSubHourlyCron, isValidCron, renderNetworkAccessBlock, SUPPORTED_MODELS, } from "./generate-watch.js";
|
|
5
|
+
/**
|
|
6
|
+
* `radar routine generate pipeline` (ADR-0020 D5 `pipeline`).
|
|
7
|
+
*
|
|
8
|
+
* Emits a Claude Routine YAML whose single session runs the FULL FeedRadar
|
|
9
|
+
* pipeline in sequence — `radar watch run` -> triage -> research -> review —
|
|
10
|
+
* processing items ONE AT A TIME via the self-session `--emit-payload` /
|
|
11
|
+
* `--commit` entrypoints (NOT `--batch`; ADR-0020 D2). The blast radius is
|
|
12
|
+
* bounded by CLI flags (`--max-items` / `--limit`), not the prompt's
|
|
13
|
+
* discretion (D3e), so a `--max-items` flag is the only structural addition
|
|
14
|
+
* over the `watch` generator.
|
|
15
|
+
*
|
|
16
|
+
* The cron / output-path / repository validators and the model roster are
|
|
17
|
+
* shared with `generate-watch.ts` rather than re-declared: routines enforce
|
|
18
|
+
* the identical 1-hour-minimum cron and `.claude/routines/*.yaml` output
|
|
19
|
+
* gate regardless of `<type>`, so a single source keeps the two in lockstep.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Default for `--max-items`: how many items one run may triage / research /
|
|
23
|
+
* review. Kept small so the routine's per-run blast radius stays bounded by a
|
|
24
|
+
* deterministic CLI cap (ADR-0020 D3e) rather than the prompt's discretion.
|
|
25
|
+
* Mirrors the conservative default of the GHA `combined-with-triage` cap.
|
|
26
|
+
*/
|
|
27
|
+
export const PIPELINE_DEFAULT_MAX_ITEMS = 10;
|
|
28
|
+
/**
|
|
29
|
+
* Landing / output modes for the pipeline routine's step-6 commit (#301).
|
|
30
|
+
*
|
|
31
|
+
* Symmetric with the GHA `combined-with-triage --output-mode pr|direct-commit`
|
|
32
|
+
* (#258), but the names differ because the mechanics differ:
|
|
33
|
+
*
|
|
34
|
+
* - `pr` (default): open a `claude/pipeline/...` branch + PR and STOP. A human
|
|
35
|
+
* reviews and merges. This is the ADR-0020 D3a safe default — no unreviewed
|
|
36
|
+
* routine output reaches the default branch.
|
|
37
|
+
* - `auto-merge`: open the same `claude/pipeline/...` PR, then immediately
|
|
38
|
+
* `gh pr merge --squash` it so the output lands on `main`. Distinct from the
|
|
39
|
+
* GHA `direct-commit` (which pushes to main with NO PR at all); here a PR is
|
|
40
|
+
* always created first. Opt-in because the step-5 self-review makes the PR
|
|
41
|
+
* review-complete (ADR-0020 D3a opt-in auto-merge).
|
|
42
|
+
*
|
|
43
|
+
* NB: `--auto` (vs immediate `--squash`) is intentionally NOT used — on a repo
|
|
44
|
+
* with no required checks `gh pr merge --auto` never merges, so the routine
|
|
45
|
+
* uses an immediate squash merge instead (#301).
|
|
46
|
+
*/
|
|
47
|
+
export const OUTPUT_MODES = ["pr", "auto-merge"];
|
|
48
|
+
/**
|
|
49
|
+
* Build the instructions step-6 commit/landing block for the given output mode.
|
|
50
|
+
*
|
|
51
|
+
* - `pr`: open a `claude/pipeline/...` branch + PR and stop (the current,
|
|
52
|
+
* pre-#301 behavior).
|
|
53
|
+
* - `auto-merge`: the same branch + PR, then `git switch main` and
|
|
54
|
+
* `gh pr merge "${BRANCH}" --squash --delete-branch` so the output lands on
|
|
55
|
+
* `main`. Switching to `main` before `--delete-branch` keeps the merge
|
|
56
|
+
* robust; the merge is fail-soft (`|| true`) so a transient failure leaves
|
|
57
|
+
* the PR open rather than aborting the routine.
|
|
58
|
+
*
|
|
59
|
+
* Emitted with the same 5-space body indentation as the surrounding numbered
|
|
60
|
+
* step (the placeholder sits where the step body starts). Exported for unit
|
|
61
|
+
* testing (mirrors the GHA generator's `buildFinalStep`).
|
|
62
|
+
*/
|
|
63
|
+
export function buildPipelineLandingStep(mode) {
|
|
64
|
+
// The `${...}` / `$(...)` tokens below are bash expansions in the GENERATED
|
|
65
|
+
// YAML, not JS template placeholders, so they are assembled by concatenation
|
|
66
|
+
// to keep biome's noTemplateCurlyInString quiet (same convention as the GHA
|
|
67
|
+
// `generate-combined-with-triage.ts` builders).
|
|
68
|
+
const BR = "$" + "{BRANCH}";
|
|
69
|
+
const DATE_BRANCH = "$" + "(date -u +%Y%m%d-%H%M)";
|
|
70
|
+
const DATE_COMMIT = "$" + "(date -u +%Y-%m-%d)";
|
|
71
|
+
const common = [
|
|
72
|
+
` BRANCH="claude/pipeline/${DATE_BRANCH}"`,
|
|
73
|
+
` git switch -c "${BR}"`,
|
|
74
|
+
" git add items/ state/ research/",
|
|
75
|
+
` git commit -m "chore(pipeline): triage/research/review ${DATE_COMMIT}"`,
|
|
76
|
+
` git push -u origin "${BR}"`,
|
|
77
|
+
` gh pr create --fill --base main --head "${BR}" || true`,
|
|
78
|
+
];
|
|
79
|
+
if (mode === "auto-merge") {
|
|
80
|
+
return [
|
|
81
|
+
" 6. If `items/`, `state/`, or `research/` changed, commit them to a `claude/*`",
|
|
82
|
+
" branch, open a pull request, then squash-merge it to `main` (auto-merge is",
|
|
83
|
+
" opt-in here — the step-5 review makes the PR review-complete):",
|
|
84
|
+
"",
|
|
85
|
+
" ```bash",
|
|
86
|
+
" if ! git diff --quiet items/ state/ research/; then",
|
|
87
|
+
...common,
|
|
88
|
+
" # Switch off the head branch before --delete-branch so the merge is",
|
|
89
|
+
" # robust, then squash-merge immediately (NOT --auto: on a repo with no",
|
|
90
|
+
" # required checks --auto never merges). Fail-soft so a transient merge",
|
|
91
|
+
" # failure leaves the PR open rather than aborting the run.",
|
|
92
|
+
" git switch main",
|
|
93
|
+
` gh pr merge "${BR}" --squash --delete-branch || true`,
|
|
94
|
+
" fi",
|
|
95
|
+
" ```",
|
|
96
|
+
].join("\n");
|
|
97
|
+
}
|
|
98
|
+
return [
|
|
99
|
+
" 6. If `items/`, `state/`, or `research/` changed, commit them to a `claude/*`",
|
|
100
|
+
" branch and open a pull request (do NOT push to `main`):",
|
|
101
|
+
"",
|
|
102
|
+
" ```bash",
|
|
103
|
+
" if ! git diff --quiet items/ state/ research/; then",
|
|
104
|
+
...common,
|
|
105
|
+
" fi",
|
|
106
|
+
" ```",
|
|
107
|
+
].join("\n");
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Build the hard-constraints output-gate bullet for the given output mode.
|
|
111
|
+
*
|
|
112
|
+
* - `pr`: the current "do NOT push to main; claude/* branch + PR only"
|
|
113
|
+
* constraint (ADR-0020 D3a, no auto-merge).
|
|
114
|
+
* - `auto-merge`: flips the constraint to say auto-merge is intentional — the
|
|
115
|
+
* routine opens a `claude/pipeline/...` PR then squash-merges it, and the
|
|
116
|
+
* step-5 review is what makes the PR review-complete (ADR-0020 D3a opt-in
|
|
117
|
+
* auto-merge).
|
|
118
|
+
*
|
|
119
|
+
* Exported for unit testing (mirrors the GHA generator's exported builders).
|
|
120
|
+
*/
|
|
121
|
+
export function buildOutputGateConstraint(mode) {
|
|
122
|
+
if (mode === "auto-merge") {
|
|
123
|
+
return [
|
|
124
|
+
" - Auto-merge is intentional here: this routine opens a `claude/pipeline/...`",
|
|
125
|
+
" PR then squash-merges it to `main`. The step-5 review makes the PR",
|
|
126
|
+
" review-complete (ADR-0020 D3a opt-in auto-merge).",
|
|
127
|
+
].join("\n");
|
|
128
|
+
}
|
|
129
|
+
return [
|
|
130
|
+
" - Do NOT push to `main` directly. Always use a `claude/pipeline/...` branch",
|
|
131
|
+
" and a PR (ADR-0020 D3a output gate; no auto-merge).",
|
|
132
|
+
].join("\n");
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Build the `notes:` output-gate sentence for the given output mode. Mirrors
|
|
136
|
+
* `buildOutputGateConstraint` but phrased for the ops `notes` block.
|
|
137
|
+
*/
|
|
138
|
+
export function buildOutputGateNote(mode) {
|
|
139
|
+
if (mode === "auto-merge") {
|
|
140
|
+
return [
|
|
141
|
+
" Output is committed to a `claude/*` branch / PR, then squash-merged to main",
|
|
142
|
+
" (auto-merge is opt-in; the step-5 review makes the PR review-complete —",
|
|
143
|
+
" ADR-0020 D3a). Single Claude session, no spawn (D2): the cross-agent review",
|
|
144
|
+
" of the GHA pipeline is NOT present here.",
|
|
145
|
+
].join("\n");
|
|
146
|
+
}
|
|
147
|
+
return [
|
|
148
|
+
" Output is committed to a `claude/*` branch / PR only (never main directly;",
|
|
149
|
+
" ADR-0020 D3a). Single Claude session, no spawn (D2): the cross-agent review",
|
|
150
|
+
" of the GHA pipeline is NOT present here.",
|
|
151
|
+
].join("\n");
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Resolve the directory holding the bundled routine templates.
|
|
155
|
+
*
|
|
156
|
+
* Mirrors `resolveTemplatesRoot` in `generate-watch.ts`: the compiled CLI lives
|
|
157
|
+
* at `dist/cli/routine/generate-pipeline.js`, so the bundled templates sit at
|
|
158
|
+
* `../../templates` relative to this module. Tests run from source
|
|
159
|
+
* (`src/cli/routine/generate-pipeline.ts`), where the same relative path lands
|
|
160
|
+
* at `src/templates/`.
|
|
161
|
+
*/
|
|
162
|
+
async function resolveTemplatesRoot() {
|
|
163
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
164
|
+
return resolve(here, "..", "..", "templates");
|
|
165
|
+
}
|
|
166
|
+
async function pathExists(p) {
|
|
167
|
+
try {
|
|
168
|
+
await access(p);
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Render the bundled `pipeline.yaml.tmpl` by substituting the `{{name}}` /
|
|
177
|
+
* `{{repository}}` / `{{cron}}` / `{{timezone}}` / `{{model}}` / `{{maxItems}}`
|
|
178
|
+
* placeholders.
|
|
179
|
+
*
|
|
180
|
+
* Literal `replace` (not a templating engine): the placeholders are simple
|
|
181
|
+
* tokens and we must not expand any other `{{...}}`-looking text in the body.
|
|
182
|
+
* Exported for unit testing in isolation.
|
|
183
|
+
*/
|
|
184
|
+
export function renderPipelineRoutineTemplate(template, values) {
|
|
185
|
+
return template
|
|
186
|
+
.replace(/\{\{name\}\}/g, values.name)
|
|
187
|
+
.replace(/\{\{repository\}\}/g, values.repository)
|
|
188
|
+
.replace(/\{\{cron\}\}/g, values.cron)
|
|
189
|
+
.replace(/\{\{timezone\}\}/g, values.timezone)
|
|
190
|
+
.replace(/\{\{model\}\}/g, values.model)
|
|
191
|
+
.replace(/\{\{maxItems\}\}/g, String(values.maxItems))
|
|
192
|
+
.replace(/\{\{networkAccessBlock\}\}/g, values.networkAccessBlock)
|
|
193
|
+
.replace(/\{\{landingStep\}\}/g, values.landingStep)
|
|
194
|
+
.replace(/\{\{outputGateConstraint\}\}/g, values.outputGateConstraint)
|
|
195
|
+
.replace(/\{\{outputGateNote\}\}/g, values.outputGateNote)
|
|
196
|
+
.replace(/\{\{allowUnrestrictedGitPush\}\}/g, String(values.allowUnrestrictedGitPush));
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Core implementation of `radar routine generate pipeline` (ADR-0020 D5
|
|
200
|
+
* `pipeline`).
|
|
201
|
+
*
|
|
202
|
+
* Validates the cron (5-field + 1-hour-minimum), output path, repository, and
|
|
203
|
+
* `--max-items` (>= 1), renders the bundled `pipeline.yaml.tmpl`, and writes it
|
|
204
|
+
* under `.claude/routines/`. The completion stdout tells the user how to paste
|
|
205
|
+
* the multi-line fields into the Web UI (yq extraction) and how to apply the
|
|
206
|
+
* schedule via `/schedule`, since Routines has no declarative apply API
|
|
207
|
+
* (ADR-0020 D1).
|
|
208
|
+
*/
|
|
209
|
+
export async function generatePipelineRoutine(options) {
|
|
210
|
+
const { cwd, name, repository, cron, timezone, model, maxItems, outputMode, output, force } = options;
|
|
211
|
+
const log = options.io?.log ?? ((m) => console.log(m));
|
|
212
|
+
const warn = options.io?.warn ?? ((m) => console.warn(m));
|
|
213
|
+
if (!OUTPUT_MODES.includes(outputMode)) {
|
|
214
|
+
throw new Error(`invalid --output-mode '${outputMode}' (expected one of: ${OUTPUT_MODES.join(" | ")})`);
|
|
215
|
+
}
|
|
216
|
+
if (!isValidCron(cron)) {
|
|
217
|
+
throw new Error(`invalid --cron expression '${cron}' (expected 5-field POSIX cron, e.g. "0 * * * *")`);
|
|
218
|
+
}
|
|
219
|
+
if (isSubHourlyCron(cron)) {
|
|
220
|
+
throw new Error(`invalid --cron '${cron}': Claude Routines require a minimum interval of 1 hour ` +
|
|
221
|
+
`(use a fixed minute, e.g. "0 * * * *" hourly or "0 0 * * *" daily; ` +
|
|
222
|
+
`sub-hourly forms like "*/5 * * * *" or "0,30 * * * *" are rejected)`);
|
|
223
|
+
}
|
|
224
|
+
if (!Number.isInteger(maxItems) || maxItems < 1) {
|
|
225
|
+
throw new Error(`invalid --max-items '${maxItems}' (expected a positive integer)`);
|
|
226
|
+
}
|
|
227
|
+
if (!isSafeRoutinePath(output, cwd)) {
|
|
228
|
+
throw new Error(`invalid --output '${output}' (must be a relative path under .claude/routines/ ending in .yaml)`);
|
|
229
|
+
}
|
|
230
|
+
if (!/^[^/\s]+\/[^/\s]+$/.test(repository)) {
|
|
231
|
+
throw new Error(`invalid --repo '${repository}' (expected owner/repo)`);
|
|
232
|
+
}
|
|
233
|
+
const templatesRoot = options.templatesRoot ?? (await resolveTemplatesRoot());
|
|
234
|
+
const templatePath = join(templatesRoot, "routines", "pipeline.yaml.tmpl");
|
|
235
|
+
if (!(await pathExists(templatePath))) {
|
|
236
|
+
throw new Error(`bundled template not found: ${templatePath}`);
|
|
237
|
+
}
|
|
238
|
+
const template = await readFile(templatePath, "utf8");
|
|
239
|
+
const hosts = await collectSourceHosts(cwd, (m) => warn(`routine generate pipeline: ${m}`));
|
|
240
|
+
const rendered = renderPipelineRoutineTemplate(template, {
|
|
241
|
+
name,
|
|
242
|
+
repository,
|
|
243
|
+
cron,
|
|
244
|
+
timezone,
|
|
245
|
+
model,
|
|
246
|
+
maxItems,
|
|
247
|
+
networkAccessBlock: renderNetworkAccessBlock(hosts),
|
|
248
|
+
landingStep: buildPipelineLandingStep(outputMode),
|
|
249
|
+
outputGateConstraint: buildOutputGateConstraint(outputMode),
|
|
250
|
+
outputGateNote: buildOutputGateNote(outputMode),
|
|
251
|
+
allowUnrestrictedGitPush: outputMode === "auto-merge",
|
|
252
|
+
});
|
|
253
|
+
const destAbs = isAbsolute(output) ? output : join(cwd, output);
|
|
254
|
+
const destRel = isAbsolute(output) ? relative(cwd, output) : output;
|
|
255
|
+
if ((await pathExists(destAbs)) && !force) {
|
|
256
|
+
throw new Error(`output file already exists: ${destRel} (use --force to overwrite)`);
|
|
257
|
+
}
|
|
258
|
+
if ((await pathExists(destAbs)) && force) {
|
|
259
|
+
warn(`routine generate pipeline: overwriting existing file ${destRel}`);
|
|
260
|
+
}
|
|
261
|
+
await mkdir(dirname(destAbs), { recursive: true });
|
|
262
|
+
await writeFile(destAbs, rendered, "utf8");
|
|
263
|
+
log(`routine generate pipeline: wrote ${destRel}`);
|
|
264
|
+
log(`routine generate pipeline: name='${name}', repo='${repository}', cron='${cron}', model='${model}', max-items=${maxItems}, output-mode='${outputMode}'`);
|
|
265
|
+
if (outputMode === "auto-merge") {
|
|
266
|
+
warn("routine generate pipeline: --output-mode auto-merge sets " +
|
|
267
|
+
"`allow_unrestricted_git_push: true`, but that is NECESSARY, NOT SUFFICIENT — " +
|
|
268
|
+
"you must ALSO turn ON the Web UI 'Allow unrestricted branch pushes' toggle " +
|
|
269
|
+
"(the RemoteTrigger API does not accept this field). Note that unattended AI " +
|
|
270
|
+
"output then lands on the default branch with NO human review.");
|
|
271
|
+
}
|
|
272
|
+
log("");
|
|
273
|
+
log("Routines has no declarative apply API — paste this routine into the Web UI by hand:");
|
|
274
|
+
log(" 1. Open https://claude.ai/code/routines and click New routine.");
|
|
275
|
+
log(" 2. Fill the form fields from the YAML (Name / Model / Repositories / Trigger / Permissions).");
|
|
276
|
+
log(" 3. For the multi-line Instructions and Setup script fields, extract them with yq:");
|
|
277
|
+
log(` yq -r '.instructions' ${destRel}`);
|
|
278
|
+
log(` yq -r '.environment.setup_script' ${destRel}`);
|
|
279
|
+
log(" 4. After registering, copy the issued routine_id (trig_xxxx) back into the YAML and set status: active.");
|
|
280
|
+
log("");
|
|
281
|
+
log("Note on /schedule (Claude Code): it is conversational — `/schedule <description>`");
|
|
282
|
+
log("to create one, plus `list` / `update` / `run` subcommands. There is no flag-based");
|
|
283
|
+
log("form (no `--name` / `--cron` / `--repo` arguments). It also cannot ingest this YAML");
|
|
284
|
+
log("verbatim, so for the long Instructions field the Web UI paste flow above (yq");
|
|
285
|
+
log("extraction) is the practical path. Finally, the unrestricted-git-push permission an");
|
|
286
|
+
log("auto-merge routine needs is set only via the Web UI 'Allow unrestricted branch");
|
|
287
|
+
log("pushes' toggle — /schedule cannot configure it.");
|
|
288
|
+
log("");
|
|
289
|
+
log("Single Claude session, no spawn (ADR-0020 D2): unlike the GHA combined-with-triage");
|
|
290
|
+
log("workflow, there is NO cross-agent review here — one Claude does every step.");
|
|
291
|
+
log(`Item caps are CLI-enforced (ADR-0020 D3e): triage --max-items ${maxItems} / items --limit ${maxItems}.`);
|
|
292
|
+
if (outputMode === "auto-merge") {
|
|
293
|
+
log("Output gate (ADR-0020 D3a): this routine opens a claude/* PR then squash-merges it to main (review-complete via step 5).");
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
log("Output gate (ADR-0020 D3a): this routine writes to a claude/* branch / PR only — never main directly.");
|
|
297
|
+
}
|
|
298
|
+
return { outputPath: destRel };
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Parse `routine generate pipeline` flags.
|
|
302
|
+
*
|
|
303
|
+
* `--output` defaults to `.claude/routines/<name>.yaml`, so it is resolved
|
|
304
|
+
* AFTER the loop once `--name` is known (a `--output` flag, if given, wins).
|
|
305
|
+
*/
|
|
306
|
+
export function parseGeneratePipelineRoutineArgs(args) {
|
|
307
|
+
let name = "feedradar-pipeline";
|
|
308
|
+
let repository = "<owner>/<repo>";
|
|
309
|
+
let cron = "0 * * * *"; // hourly — the Routines minimum interval.
|
|
310
|
+
let timezone = "UTC";
|
|
311
|
+
let model = "claude-sonnet-4-6";
|
|
312
|
+
let maxItems = PIPELINE_DEFAULT_MAX_ITEMS;
|
|
313
|
+
let outputMode = "pr";
|
|
314
|
+
let output;
|
|
315
|
+
let force = false;
|
|
316
|
+
let help = false;
|
|
317
|
+
for (let i = 0; i < args.length; i++) {
|
|
318
|
+
const a = args[i];
|
|
319
|
+
if (a === "-h" || a === "--help") {
|
|
320
|
+
help = true;
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
if (a === "--name") {
|
|
324
|
+
const value = args[++i];
|
|
325
|
+
if (value === undefined)
|
|
326
|
+
throw new Error(`option ${a} requires a value`);
|
|
327
|
+
name = value;
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
if (a === "--repo" || a === "--repository") {
|
|
331
|
+
const value = args[++i];
|
|
332
|
+
if (value === undefined)
|
|
333
|
+
throw new Error(`option ${a} requires a value`);
|
|
334
|
+
repository = value;
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
if (a === "--cron") {
|
|
338
|
+
const value = args[++i];
|
|
339
|
+
if (value === undefined)
|
|
340
|
+
throw new Error(`option ${a} requires a value`);
|
|
341
|
+
cron = value;
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
if (a === "--timezone" || a === "--tz") {
|
|
345
|
+
const value = args[++i];
|
|
346
|
+
if (value === undefined)
|
|
347
|
+
throw new Error(`option ${a} requires a value`);
|
|
348
|
+
timezone = value;
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
if (a === "--model") {
|
|
352
|
+
const value = args[++i];
|
|
353
|
+
if (value === undefined)
|
|
354
|
+
throw new Error(`option ${a} requires a value`);
|
|
355
|
+
if (!SUPPORTED_MODELS.includes(value)) {
|
|
356
|
+
throw new Error(`option --model expects one of: ${SUPPORTED_MODELS.join(" | ")}, got '${value}'`);
|
|
357
|
+
}
|
|
358
|
+
model = value;
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
if (a === "--max-items") {
|
|
362
|
+
const value = args[++i];
|
|
363
|
+
if (value === undefined)
|
|
364
|
+
throw new Error(`option ${a} requires a value`);
|
|
365
|
+
const n = Number(value);
|
|
366
|
+
if (!Number.isInteger(n) || n < 1) {
|
|
367
|
+
throw new Error(`option --max-items expects a positive integer, got '${value}'`);
|
|
368
|
+
}
|
|
369
|
+
maxItems = n;
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
if (a === "--output-mode") {
|
|
373
|
+
const value = args[++i];
|
|
374
|
+
if (value === undefined)
|
|
375
|
+
throw new Error(`option ${a} requires a value`);
|
|
376
|
+
if (!OUTPUT_MODES.includes(value)) {
|
|
377
|
+
throw new Error(`option --output-mode expects one of: ${OUTPUT_MODES.join(" | ")}, got '${value}'`);
|
|
378
|
+
}
|
|
379
|
+
outputMode = value;
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
if (a === "--output") {
|
|
383
|
+
const value = args[++i];
|
|
384
|
+
if (value === undefined)
|
|
385
|
+
throw new Error(`option ${a} requires a value`);
|
|
386
|
+
output = value;
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
if (a === "--force" || a === "-f") {
|
|
390
|
+
force = true;
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
if (a?.startsWith("--") || a?.startsWith("-")) {
|
|
394
|
+
throw new Error(`unknown option: ${a}`);
|
|
395
|
+
}
|
|
396
|
+
throw new Error(`unexpected positional argument: ${a}`);
|
|
397
|
+
}
|
|
398
|
+
return {
|
|
399
|
+
name,
|
|
400
|
+
repository,
|
|
401
|
+
cron,
|
|
402
|
+
timezone,
|
|
403
|
+
model,
|
|
404
|
+
maxItems,
|
|
405
|
+
outputMode,
|
|
406
|
+
output: output ?? join(".claude", "routines", `${name}.yaml`),
|
|
407
|
+
force,
|
|
408
|
+
help,
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
export function printGeneratePipelineRoutineHelp(log) {
|
|
412
|
+
log("Usage: radar routine generate pipeline [options]");
|
|
413
|
+
log("");
|
|
414
|
+
log("Generates a Claude Code Routine YAML whose single session runs the FULL");
|
|
415
|
+
log("pipeline — `radar watch run` -> triage -> research -> review — IN SEQUENCE,");
|
|
416
|
+
log("processing items ONE AT A TIME (ADR-0020 D5 `pipeline`). It does NOT spawn");
|
|
417
|
+
log("other agents (D2), so the cross-agent review of the GHA combined-with-triage");
|
|
418
|
+
log("workflow is NOT present. Per-run item count is bounded by CLI flags (D3e).");
|
|
419
|
+
log("");
|
|
420
|
+
log("Options:");
|
|
421
|
+
log(' --name <name> Routine name (default: "feedradar-pipeline")');
|
|
422
|
+
log(" Also the default output filename.");
|
|
423
|
+
log(" --repo <owner/repo> Target repository (default: <owner>/<repo>)");
|
|
424
|
+
log(' --cron <expression> 5-field cron, min interval 1 HOUR (default: "0 * * * *")');
|
|
425
|
+
log(' Sub-hourly (e.g. "*/5 * * * *") is rejected.');
|
|
426
|
+
log(' --timezone <tz> Schedule timezone (default: "UTC")');
|
|
427
|
+
log(` --model <name> ${SUPPORTED_MODELS.join(" | ")}`);
|
|
428
|
+
log(" (default: claude-sonnet-4-6)");
|
|
429
|
+
log(` --max-items N Hard cap on items triaged/researched/reviewed per run`);
|
|
430
|
+
log(` (default: ${PIPELINE_DEFAULT_MAX_ITEMS}). Drives triage --max-items and items --limit.`);
|
|
431
|
+
log(" --output-mode <mode> pr | auto-merge (default: pr). 'auto-merge' squash-merges");
|
|
432
|
+
log(" the routine's own PR to main (requires the Web UI 'Allow");
|
|
433
|
+
log(" unrestricted branch pushes' toggle).");
|
|
434
|
+
log(" --output <path> Output file under .claude/routines/");
|
|
435
|
+
log(" (default: .claude/routines/<name>.yaml)");
|
|
436
|
+
log(" --force, -f Overwrite existing output file");
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Entry point invoked by `runRoutine` (in `src/cli/routine.ts`) when the user
|
|
440
|
+
* types `radar routine generate pipeline`. Translates parsed flags into
|
|
441
|
+
* `generatePipelineRoutine` arguments and surfaces validation errors with the
|
|
442
|
+
* `routine generate pipeline:` prefix to match the rest of the CLI.
|
|
443
|
+
*/
|
|
444
|
+
export async function runGeneratePipelineRoutine(args, io = {}, cwd = process.cwd()) {
|
|
445
|
+
const log = io.log ?? ((m) => console.log(m));
|
|
446
|
+
const error = io.error ?? ((m) => console.error(m));
|
|
447
|
+
let parsed;
|
|
448
|
+
try {
|
|
449
|
+
parsed = parseGeneratePipelineRoutineArgs(args);
|
|
450
|
+
}
|
|
451
|
+
catch (e) {
|
|
452
|
+
error(`routine generate pipeline: ${e instanceof Error ? e.message : String(e)}`);
|
|
453
|
+
return 2;
|
|
454
|
+
}
|
|
455
|
+
if (parsed.help) {
|
|
456
|
+
printGeneratePipelineRoutineHelp(log);
|
|
457
|
+
return 0;
|
|
458
|
+
}
|
|
459
|
+
try {
|
|
460
|
+
await generatePipelineRoutine({
|
|
461
|
+
cwd,
|
|
462
|
+
name: parsed.name,
|
|
463
|
+
repository: parsed.repository,
|
|
464
|
+
cron: parsed.cron,
|
|
465
|
+
timezone: parsed.timezone,
|
|
466
|
+
model: parsed.model,
|
|
467
|
+
maxItems: parsed.maxItems,
|
|
468
|
+
outputMode: parsed.outputMode,
|
|
469
|
+
output: parsed.output,
|
|
470
|
+
force: parsed.force,
|
|
471
|
+
io,
|
|
472
|
+
});
|
|
473
|
+
return 0;
|
|
474
|
+
}
|
|
475
|
+
catch (e) {
|
|
476
|
+
error(`routine generate pipeline: ${e instanceof Error ? e.message : String(e)}`);
|
|
477
|
+
return 1;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
//# sourceMappingURL=generate-pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-pipeline.js","sourceRoot":"","sources":["../../../src/cli/routine/generate-pipeline.ts"],"names":[],"mappings":"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"}
|