@ozzylabs/feedradar 0.1.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.ja.md +6 -3
  2. package/README.md +6 -3
  3. package/dist/agents/_boundary.d.ts +44 -0
  4. package/dist/agents/_boundary.d.ts.map +1 -1
  5. package/dist/agents/_boundary.js +80 -0
  6. package/dist/agents/_boundary.js.map +1 -1
  7. package/dist/cli/index.d.ts.map +1 -1
  8. package/dist/cli/index.js +2 -0
  9. package/dist/cli/index.js.map +1 -1
  10. package/dist/cli/init.d.ts +1 -1
  11. package/dist/cli/init.d.ts.map +1 -1
  12. package/dist/cli/init.js +10 -3
  13. package/dist/cli/init.js.map +1 -1
  14. package/dist/cli/routine/fire.d.ts +100 -0
  15. package/dist/cli/routine/fire.d.ts.map +1 -0
  16. package/dist/cli/routine/fire.js +196 -0
  17. package/dist/cli/routine/fire.js.map +1 -0
  18. package/dist/cli/routine/generate-pipeline.d.ts +100 -0
  19. package/dist/cli/routine/generate-pipeline.d.ts.map +1 -0
  20. package/dist/cli/routine/generate-pipeline.js +311 -0
  21. package/dist/cli/routine/generate-pipeline.js.map +1 -0
  22. package/dist/cli/routine/generate-watch.d.ts +174 -0
  23. package/dist/cli/routine/generate-watch.d.ts.map +1 -0
  24. package/dist/cli/routine/generate-watch.js +445 -0
  25. package/dist/cli/routine/generate-watch.js.map +1 -0
  26. package/dist/cli/routine.d.ts +32 -0
  27. package/dist/cli/routine.d.ts.map +1 -0
  28. package/dist/cli/routine.js +74 -0
  29. package/dist/cli/routine.js.map +1 -0
  30. package/dist/cli/triage.d.ts.map +1 -1
  31. package/dist/cli/triage.js +383 -78
  32. package/dist/cli/triage.js.map +1 -1
  33. package/dist/templates/agents/AGENTS.md +1 -1
  34. package/dist/templates/routines/pipeline.yaml.tmpl +231 -0
  35. package/dist/templates/routines/watch-daily.yaml +157 -0
  36. package/dist/templates/routines/watch.yaml.tmpl +151 -0
  37. package/package.json +1 -1
  38. package/dist/templates/routines/watch-daily.md +0 -42
@@ -0,0 +1,196 @@
1
+ /**
2
+ * `radar routine fire <trig_id>` — trigger a Claude Routine from the outside
3
+ * via the `/fire` API (ADR-0020 §「外部からの起動」; epic #277 / #282).
4
+ *
5
+ * The `/fire` endpoint creates a routine session and returns immediately — it
6
+ * does NOT wait for the session to finish. The optional `--text` body is a
7
+ * free-form string passed to the session as launch context; the API does not
8
+ * parse it. Each routine has its own per-routine bearer token, issued ONCE in
9
+ * the Web UI (shown a single time; Regenerate / Revoke from there). The token
10
+ * is read from the environment and is NEVER printed to logs.
11
+ */
12
+ /**
13
+ * Base URL of the Anthropic API. Exposed as a constant (not hardcoded inline)
14
+ * so the fire URL stays in one place and tests can assert against it.
15
+ */
16
+ export const ANTHROPIC_API_BASE = "https://api.anthropic.com";
17
+ /** Beta header gating the experimental Claude Code routines surface. */
18
+ export const ROUTINE_FIRE_BETA = "experimental-cc-routine-2026-04-01";
19
+ /** Anthropic API version pin (stable date-versioned API). */
20
+ export const ANTHROPIC_VERSION = "2023-06-01";
21
+ /** Default env var holding the per-routine `/fire` bearer token. */
22
+ export const DEFAULT_FIRE_TOKEN_ENV = "FEEDRADAR_ROUTINE_FIRE_TOKEN";
23
+ /**
24
+ * Routine ids issued by the Web UI carry a `trig_` prefix. We validate the
25
+ * shape before composing the URL so a typo'd id fails fast with a clear
26
+ * message instead of a 404 from the server.
27
+ */
28
+ export function isValidRoutineId(id) {
29
+ return /^trig_[A-Za-z0-9._-]+$/.test(id);
30
+ }
31
+ /**
32
+ * POST to `/v1/claude_code/routines/{trig_id}/fire`.
33
+ *
34
+ * The endpoint returns as soon as the session is created (it does not wait for
35
+ * completion). On a non-2xx status this throws with the status text; the token
36
+ * is never included in any error or log.
37
+ */
38
+ export async function fireRoutine(options) {
39
+ const { routineId, token, text } = options;
40
+ const apiBase = options.apiBase ?? ANTHROPIC_API_BASE;
41
+ const fetchImpl = options.fetch ?? globalThis.fetch;
42
+ if (!isValidRoutineId(routineId)) {
43
+ throw new Error(`invalid routine id '${routineId}' (expected a Web UI id starting with 'trig_')`);
44
+ }
45
+ if (token.trim().length === 0) {
46
+ throw new Error("missing per-routine fire token");
47
+ }
48
+ const url = `${apiBase}/v1/claude_code/routines/${routineId}/fire`;
49
+ const headers = {
50
+ authorization: `Bearer ${token}`,
51
+ "anthropic-version": ANTHROPIC_VERSION,
52
+ "anthropic-beta": ROUTINE_FIRE_BETA,
53
+ "content-type": "application/json",
54
+ };
55
+ // The `text` body is free-form launch context; the API does not parse it.
56
+ // Always send a JSON object so the content-type matches even when empty.
57
+ const body = JSON.stringify(text === undefined ? {} : { text });
58
+ const response = await fetchImpl(url, { method: "POST", headers, body });
59
+ // Read the body once regardless of status so error and success paths share
60
+ // the same parse and we can surface server detail without leaking the token.
61
+ let parsed;
62
+ try {
63
+ parsed = await response.json();
64
+ }
65
+ catch {
66
+ parsed = await response.text().catch(() => "");
67
+ }
68
+ if (!response.ok) {
69
+ const detail = typeof parsed === "string" && parsed.length > 0
70
+ ? `: ${parsed}`
71
+ : parsed && typeof parsed === "object"
72
+ ? `: ${JSON.stringify(parsed)}`
73
+ : "";
74
+ throw new Error(`fire failed (HTTP ${response.status} ${response.statusText})${detail}`);
75
+ }
76
+ return { status: response.status, body: parsed };
77
+ }
78
+ /**
79
+ * Parse `routine fire <trig_id> [--text <msg>] [--token-env <NAME>]`.
80
+ *
81
+ * The routine id is a positional argument (the first non-flag token). A
82
+ * `--token-env` override lets a user point at a differently-named env var when
83
+ * juggling multiple routines, but the value is ALWAYS read from the
84
+ * environment — never accepted as a CLI flag (which would leak into process
85
+ * listings / shell history).
86
+ */
87
+ export function parseFireRoutineArgs(args) {
88
+ let routineId;
89
+ let text;
90
+ let tokenEnv = DEFAULT_FIRE_TOKEN_ENV;
91
+ let help = false;
92
+ for (let i = 0; i < args.length; i++) {
93
+ const a = args[i];
94
+ if (a === "-h" || a === "--help") {
95
+ help = true;
96
+ continue;
97
+ }
98
+ if (a === "--text") {
99
+ const value = args[++i];
100
+ if (value === undefined)
101
+ throw new Error(`option ${a} requires a value`);
102
+ text = value;
103
+ continue;
104
+ }
105
+ if (a === "--token-env") {
106
+ const value = args[++i];
107
+ if (value === undefined)
108
+ throw new Error(`option ${a} requires a value`);
109
+ tokenEnv = value;
110
+ continue;
111
+ }
112
+ if (a === "--token") {
113
+ // Refuse a token on the command line: it would leak into `ps` output and
114
+ // shell history. Direct the user to the env-var path instead.
115
+ throw new Error("refusing --token on the command line (it leaks via process listing / shell history); " +
116
+ `set the token in the ${DEFAULT_FIRE_TOKEN_ENV} env var (or use --token-env <NAME>)`);
117
+ }
118
+ if (a?.startsWith("-")) {
119
+ throw new Error(`unknown option: ${a}`);
120
+ }
121
+ if (routineId !== undefined) {
122
+ throw new Error(`unexpected positional argument: ${a}`);
123
+ }
124
+ routineId = a;
125
+ }
126
+ return { routineId, text, tokenEnv, help };
127
+ }
128
+ export function printFireRoutineHelp(log) {
129
+ log("Usage: radar routine fire <trig_id> [options]");
130
+ log("");
131
+ log("Triggers a registered Claude Code Routine from the outside via the");
132
+ log("/fire API (ADR-0020). The call returns as soon as the routine session");
133
+ log("is created — it does NOT wait for the session to finish.");
134
+ log("");
135
+ log("Arguments:");
136
+ log(" <trig_id> Routine id from the Web UI (starts with 'trig_')");
137
+ log("");
138
+ log("Options:");
139
+ log(" --text <msg> Free-form launch context (request body `text`).");
140
+ log(" The API does not parse it; it is passed as-is.");
141
+ log(` --token-env <NAME> Env var holding the per-routine bearer token`);
142
+ log(` (default: ${DEFAULT_FIRE_TOKEN_ENV}).`);
143
+ log("");
144
+ log("The per-routine token is issued ONCE in the Web UI (Regenerate / Revoke");
145
+ log("there) and is read from the environment — it is never accepted as a flag");
146
+ log("and never printed.");
147
+ }
148
+ /**
149
+ * Entry point invoked by `runRoutine` when the user types
150
+ * `radar routine fire`. Reads the token from the environment (never a flag,
151
+ * never logged) and POSTs to `/fire`.
152
+ */
153
+ export async function runFireRoutine(args, io = {}, env = process.env, fetchImpl) {
154
+ const log = io.log ?? ((m) => console.log(m));
155
+ const error = io.error ?? ((m) => console.error(m));
156
+ let parsed;
157
+ try {
158
+ parsed = parseFireRoutineArgs(args);
159
+ }
160
+ catch (e) {
161
+ error(`routine fire: ${e instanceof Error ? e.message : String(e)}`);
162
+ return 2;
163
+ }
164
+ if (parsed.help) {
165
+ printFireRoutineHelp(log);
166
+ return 0;
167
+ }
168
+ if (!parsed.routineId) {
169
+ error("routine fire: missing <trig_id> argument (the routine id from the Web UI)");
170
+ printFireRoutineHelp(error);
171
+ return 2;
172
+ }
173
+ const token = env[parsed.tokenEnv];
174
+ if (!token || token.trim().length === 0) {
175
+ error(`routine fire: no token in ${parsed.tokenEnv}. ` +
176
+ `Issue a per-routine token in the Web UI and export it, e.g. ` +
177
+ `export ${parsed.tokenEnv}='...'`);
178
+ return 2;
179
+ }
180
+ try {
181
+ const result = await fireRoutine({
182
+ routineId: parsed.routineId,
183
+ token,
184
+ text: parsed.text,
185
+ fetch: fetchImpl,
186
+ });
187
+ log(`routine fire: triggered ${parsed.routineId} (HTTP ${result.status}).`);
188
+ log("The session was created — this call does not wait for it to finish.");
189
+ return 0;
190
+ }
191
+ catch (e) {
192
+ error(`routine fire: ${e instanceof Error ? e.message : String(e)}`);
193
+ return 1;
194
+ }
195
+ }
196
+ //# sourceMappingURL=fire.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fire.js","sourceRoot":"","sources":["../../../src/cli/routine/fire.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ import { type RoutineIO, type SupportedModel } from "./generate-watch.js";
2
+ /**
3
+ * `radar routine generate pipeline` (ADR-0020 D5 `pipeline`).
4
+ *
5
+ * Emits a Claude Routine YAML whose single session runs the FULL FeedRadar
6
+ * pipeline in sequence — `radar watch run` -> triage -> research -> review —
7
+ * processing items ONE AT A TIME via the self-session `--emit-payload` /
8
+ * `--commit` entrypoints (NOT `--batch`; ADR-0020 D2). The blast radius is
9
+ * bounded by CLI flags (`--max-items` / `--limit`), not the prompt's
10
+ * discretion (D3e), so a `--max-items` flag is the only structural addition
11
+ * over the `watch` generator.
12
+ *
13
+ * The cron / output-path / repository validators and the model roster are
14
+ * shared with `generate-watch.ts` rather than re-declared: routines enforce
15
+ * the identical 1-hour-minimum cron and `.claude/routines/*.yaml` output
16
+ * gate regardless of `<type>`, so a single source keeps the two in lockstep.
17
+ */
18
+ /**
19
+ * Default for `--max-items`: how many items one run may triage / research /
20
+ * review. Kept small so the routine's per-run blast radius stays bounded by a
21
+ * deterministic CLI cap (ADR-0020 D3e) rather than the prompt's discretion.
22
+ * Mirrors the conservative default of the GHA `combined-with-triage` cap.
23
+ */
24
+ export declare const PIPELINE_DEFAULT_MAX_ITEMS = 10;
25
+ /**
26
+ * Render the bundled `pipeline.yaml.tmpl` by substituting the `{{name}}` /
27
+ * `{{repository}}` / `{{cron}}` / `{{timezone}}` / `{{model}}` / `{{maxItems}}`
28
+ * placeholders.
29
+ *
30
+ * Literal `replace` (not a templating engine): the placeholders are simple
31
+ * tokens and we must not expand any other `{{...}}`-looking text in the body.
32
+ * Exported for unit testing in isolation.
33
+ */
34
+ export declare function renderPipelineRoutineTemplate(template: string, values: {
35
+ name: string;
36
+ repository: string;
37
+ cron: string;
38
+ timezone: string;
39
+ model: string;
40
+ maxItems: number;
41
+ networkAccessBlock: string;
42
+ }): string;
43
+ export interface GeneratePipelineRoutineOptions {
44
+ cwd: string;
45
+ name: string;
46
+ repository: string;
47
+ cron: string;
48
+ timezone: string;
49
+ model: SupportedModel;
50
+ maxItems: number;
51
+ output: string;
52
+ force: boolean;
53
+ /** Test seam: override the templates root location. */
54
+ templatesRoot?: string;
55
+ io?: RoutineIO;
56
+ }
57
+ export interface GeneratePipelineRoutineResult {
58
+ /** Relative path (from `cwd`) of the file that was written. */
59
+ outputPath: string;
60
+ }
61
+ /**
62
+ * Core implementation of `radar routine generate pipeline` (ADR-0020 D5
63
+ * `pipeline`).
64
+ *
65
+ * Validates the cron (5-field + 1-hour-minimum), output path, repository, and
66
+ * `--max-items` (>= 1), renders the bundled `pipeline.yaml.tmpl`, and writes it
67
+ * under `.claude/routines/`. The completion stdout tells the user how to paste
68
+ * the multi-line fields into the Web UI (yq extraction) and how to apply the
69
+ * schedule via `/schedule`, since Routines has no declarative apply API
70
+ * (ADR-0020 D1).
71
+ */
72
+ export declare function generatePipelineRoutine(options: GeneratePipelineRoutineOptions): Promise<GeneratePipelineRoutineResult>;
73
+ interface ParsedFlags {
74
+ name: string;
75
+ repository: string;
76
+ cron: string;
77
+ timezone: string;
78
+ model: SupportedModel;
79
+ maxItems: number;
80
+ output: string;
81
+ force: boolean;
82
+ help: boolean;
83
+ }
84
+ /**
85
+ * Parse `routine generate pipeline` flags.
86
+ *
87
+ * `--output` defaults to `.claude/routines/<name>.yaml`, so it is resolved
88
+ * AFTER the loop once `--name` is known (a `--output` flag, if given, wins).
89
+ */
90
+ export declare function parseGeneratePipelineRoutineArgs(args: string[]): ParsedFlags;
91
+ export declare function printGeneratePipelineRoutineHelp(log: (m: string) => void): void;
92
+ /**
93
+ * Entry point invoked by `runRoutine` (in `src/cli/routine.ts`) when the user
94
+ * types `radar routine generate pipeline`. Translates parsed flags into
95
+ * `generatePipelineRoutine` arguments and surfaces validation errors with the
96
+ * `routine generate pipeline:` prefix to match the rest of the CLI.
97
+ */
98
+ export declare function runGeneratePipelineRoutine(args: string[], io?: RoutineIO, cwd?: string): Promise<number>;
99
+ export {};
100
+ //# sourceMappingURL=generate-pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-pipeline.d.ts","sourceRoot":"","sources":["../../../src/cli/routine/generate-pipeline.ts"],"names":[],"mappings":"AAGA,OAAO,EAKL,KAAK,SAAS,EAGd,KAAK,cAAc,EACpB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;GAeG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAyB7C;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE;IACN,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,GACA,MAAM,CASR;AAED,MAAM,WAAW,8BAA8B;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,cAAc,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,EAAE,CAAC,EAAE,SAAS,CAAC;CAChB;AAED,MAAM,WAAW,6BAA6B;IAC5C,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,6BAA6B,CAAC,CAyFxC;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,cAAc,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,WAAW,CAyF5E;AAED,wBAAgB,gCAAgC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAyB/E;AAED;;;;;GAKG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,GAAE,SAAc,EAClB,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAkCjB"}
@@ -0,0 +1,311 @@
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
+ * Resolve the directory holding the bundled routine templates.
30
+ *
31
+ * Mirrors `resolveTemplatesRoot` in `generate-watch.ts`: the compiled CLI lives
32
+ * at `dist/cli/routine/generate-pipeline.js`, so the bundled templates sit at
33
+ * `../../templates` relative to this module. Tests run from source
34
+ * (`src/cli/routine/generate-pipeline.ts`), where the same relative path lands
35
+ * at `src/templates/`.
36
+ */
37
+ async function resolveTemplatesRoot() {
38
+ const here = dirname(fileURLToPath(import.meta.url));
39
+ return resolve(here, "..", "..", "templates");
40
+ }
41
+ async function pathExists(p) {
42
+ try {
43
+ await access(p);
44
+ return true;
45
+ }
46
+ catch {
47
+ return false;
48
+ }
49
+ }
50
+ /**
51
+ * Render the bundled `pipeline.yaml.tmpl` by substituting the `{{name}}` /
52
+ * `{{repository}}` / `{{cron}}` / `{{timezone}}` / `{{model}}` / `{{maxItems}}`
53
+ * placeholders.
54
+ *
55
+ * Literal `replace` (not a templating engine): the placeholders are simple
56
+ * tokens and we must not expand any other `{{...}}`-looking text in the body.
57
+ * Exported for unit testing in isolation.
58
+ */
59
+ export function renderPipelineRoutineTemplate(template, values) {
60
+ return template
61
+ .replace(/\{\{name\}\}/g, values.name)
62
+ .replace(/\{\{repository\}\}/g, values.repository)
63
+ .replace(/\{\{cron\}\}/g, values.cron)
64
+ .replace(/\{\{timezone\}\}/g, values.timezone)
65
+ .replace(/\{\{model\}\}/g, values.model)
66
+ .replace(/\{\{maxItems\}\}/g, String(values.maxItems))
67
+ .replace(/\{\{networkAccessBlock\}\}/g, values.networkAccessBlock);
68
+ }
69
+ /**
70
+ * Core implementation of `radar routine generate pipeline` (ADR-0020 D5
71
+ * `pipeline`).
72
+ *
73
+ * Validates the cron (5-field + 1-hour-minimum), output path, repository, and
74
+ * `--max-items` (>= 1), renders the bundled `pipeline.yaml.tmpl`, and writes it
75
+ * under `.claude/routines/`. The completion stdout tells the user how to paste
76
+ * the multi-line fields into the Web UI (yq extraction) and how to apply the
77
+ * schedule via `/schedule`, since Routines has no declarative apply API
78
+ * (ADR-0020 D1).
79
+ */
80
+ export async function generatePipelineRoutine(options) {
81
+ const { cwd, name, repository, cron, timezone, model, maxItems, output, force } = options;
82
+ const log = options.io?.log ?? ((m) => console.log(m));
83
+ const warn = options.io?.warn ?? ((m) => console.warn(m));
84
+ if (!isValidCron(cron)) {
85
+ throw new Error(`invalid --cron expression '${cron}' (expected 5-field POSIX cron, e.g. "0 * * * *")`);
86
+ }
87
+ if (isSubHourlyCron(cron)) {
88
+ throw new Error(`invalid --cron '${cron}': Claude Routines require a minimum interval of 1 hour ` +
89
+ `(use a fixed minute, e.g. "0 * * * *" hourly or "0 0 * * *" daily; ` +
90
+ `sub-hourly forms like "*/5 * * * *" or "0,30 * * * *" are rejected)`);
91
+ }
92
+ if (!Number.isInteger(maxItems) || maxItems < 1) {
93
+ throw new Error(`invalid --max-items '${maxItems}' (expected a positive integer)`);
94
+ }
95
+ if (!isSafeRoutinePath(output, cwd)) {
96
+ throw new Error(`invalid --output '${output}' (must be a relative path under .claude/routines/ ending in .yaml)`);
97
+ }
98
+ if (!/^[^/\s]+\/[^/\s]+$/.test(repository)) {
99
+ throw new Error(`invalid --repo '${repository}' (expected owner/repo)`);
100
+ }
101
+ const templatesRoot = options.templatesRoot ?? (await resolveTemplatesRoot());
102
+ const templatePath = join(templatesRoot, "routines", "pipeline.yaml.tmpl");
103
+ if (!(await pathExists(templatePath))) {
104
+ throw new Error(`bundled template not found: ${templatePath}`);
105
+ }
106
+ const template = await readFile(templatePath, "utf8");
107
+ const hosts = await collectSourceHosts(cwd, (m) => warn(`routine generate pipeline: ${m}`));
108
+ const rendered = renderPipelineRoutineTemplate(template, {
109
+ name,
110
+ repository,
111
+ cron,
112
+ timezone,
113
+ model,
114
+ maxItems,
115
+ networkAccessBlock: renderNetworkAccessBlock(hosts),
116
+ });
117
+ const destAbs = isAbsolute(output) ? output : join(cwd, output);
118
+ const destRel = isAbsolute(output) ? relative(cwd, output) : output;
119
+ if ((await pathExists(destAbs)) && !force) {
120
+ throw new Error(`output file already exists: ${destRel} (use --force to overwrite)`);
121
+ }
122
+ if ((await pathExists(destAbs)) && force) {
123
+ warn(`routine generate pipeline: overwriting existing file ${destRel}`);
124
+ }
125
+ await mkdir(dirname(destAbs), { recursive: true });
126
+ await writeFile(destAbs, rendered, "utf8");
127
+ log(`routine generate pipeline: wrote ${destRel}`);
128
+ log(`routine generate pipeline: name='${name}', repo='${repository}', cron='${cron}', model='${model}', max-items=${maxItems}`);
129
+ log("");
130
+ log("Routines has no declarative apply API — paste this routine into the Web UI by hand:");
131
+ log(" 1. Open https://claude.ai/code/routines and click New routine.");
132
+ log(" 2. Fill the form fields from the YAML (Name / Model / Repositories / Trigger / Permissions).");
133
+ log(" 3. For the multi-line Instructions and Setup script fields, extract them with yq:");
134
+ log(` yq -r '.instructions' ${destRel}`);
135
+ log(` yq -r '.environment.setup_script' ${destRel}`);
136
+ log(" 4. After registering, copy the issued routine_id (trig_xxxx) back into the YAML and set status: active.");
137
+ log("");
138
+ log("Or apply the schedule from the CLI with /schedule, e.g.:");
139
+ log(` /schedule create --name '${name}' --cron '${cron}' --repo '${repository}'`);
140
+ log("");
141
+ log("Single Claude session, no spawn (ADR-0020 D2): unlike the GHA combined-with-triage");
142
+ log("workflow, there is NO cross-agent review here — one Claude does every step.");
143
+ log(`Item caps are CLI-enforced (ADR-0020 D3e): triage --max-items ${maxItems} / items --limit ${maxItems}.`);
144
+ log("Output gate (ADR-0020 D3a): this routine writes to a claude/* branch / PR only — never main directly.");
145
+ return { outputPath: destRel };
146
+ }
147
+ /**
148
+ * Parse `routine generate pipeline` flags.
149
+ *
150
+ * `--output` defaults to `.claude/routines/<name>.yaml`, so it is resolved
151
+ * AFTER the loop once `--name` is known (a `--output` flag, if given, wins).
152
+ */
153
+ export function parseGeneratePipelineRoutineArgs(args) {
154
+ let name = "feedradar-pipeline";
155
+ let repository = "<owner>/<repo>";
156
+ let cron = "0 * * * *"; // hourly — the Routines minimum interval.
157
+ let timezone = "UTC";
158
+ let model = "claude-sonnet-4-6";
159
+ let maxItems = PIPELINE_DEFAULT_MAX_ITEMS;
160
+ let output;
161
+ let force = false;
162
+ let help = false;
163
+ for (let i = 0; i < args.length; i++) {
164
+ const a = args[i];
165
+ if (a === "-h" || a === "--help") {
166
+ help = true;
167
+ continue;
168
+ }
169
+ if (a === "--name") {
170
+ const value = args[++i];
171
+ if (value === undefined)
172
+ throw new Error(`option ${a} requires a value`);
173
+ name = value;
174
+ continue;
175
+ }
176
+ if (a === "--repo" || a === "--repository") {
177
+ const value = args[++i];
178
+ if (value === undefined)
179
+ throw new Error(`option ${a} requires a value`);
180
+ repository = value;
181
+ continue;
182
+ }
183
+ if (a === "--cron") {
184
+ const value = args[++i];
185
+ if (value === undefined)
186
+ throw new Error(`option ${a} requires a value`);
187
+ cron = value;
188
+ continue;
189
+ }
190
+ if (a === "--timezone" || a === "--tz") {
191
+ const value = args[++i];
192
+ if (value === undefined)
193
+ throw new Error(`option ${a} requires a value`);
194
+ timezone = value;
195
+ continue;
196
+ }
197
+ if (a === "--model") {
198
+ const value = args[++i];
199
+ if (value === undefined)
200
+ throw new Error(`option ${a} requires a value`);
201
+ if (!SUPPORTED_MODELS.includes(value)) {
202
+ throw new Error(`option --model expects one of: ${SUPPORTED_MODELS.join(" | ")}, got '${value}'`);
203
+ }
204
+ model = value;
205
+ continue;
206
+ }
207
+ if (a === "--max-items") {
208
+ const value = args[++i];
209
+ if (value === undefined)
210
+ throw new Error(`option ${a} requires a value`);
211
+ const n = Number(value);
212
+ if (!Number.isInteger(n) || n < 1) {
213
+ throw new Error(`option --max-items expects a positive integer, got '${value}'`);
214
+ }
215
+ maxItems = n;
216
+ continue;
217
+ }
218
+ if (a === "--output") {
219
+ const value = args[++i];
220
+ if (value === undefined)
221
+ throw new Error(`option ${a} requires a value`);
222
+ output = value;
223
+ continue;
224
+ }
225
+ if (a === "--force" || a === "-f") {
226
+ force = true;
227
+ continue;
228
+ }
229
+ if (a?.startsWith("--") || a?.startsWith("-")) {
230
+ throw new Error(`unknown option: ${a}`);
231
+ }
232
+ throw new Error(`unexpected positional argument: ${a}`);
233
+ }
234
+ return {
235
+ name,
236
+ repository,
237
+ cron,
238
+ timezone,
239
+ model,
240
+ maxItems,
241
+ output: output ?? join(".claude", "routines", `${name}.yaml`),
242
+ force,
243
+ help,
244
+ };
245
+ }
246
+ export function printGeneratePipelineRoutineHelp(log) {
247
+ log("Usage: radar routine generate pipeline [options]");
248
+ log("");
249
+ log("Generates a Claude Code Routine YAML whose single session runs the FULL");
250
+ log("pipeline — `radar watch run` -> triage -> research -> review — IN SEQUENCE,");
251
+ log("processing items ONE AT A TIME (ADR-0020 D5 `pipeline`). It does NOT spawn");
252
+ log("other agents (D2), so the cross-agent review of the GHA combined-with-triage");
253
+ log("workflow is NOT present. Per-run item count is bounded by CLI flags (D3e).");
254
+ log("");
255
+ log("Options:");
256
+ log(' --name <name> Routine name (default: "feedradar-pipeline")');
257
+ log(" Also the default output filename.");
258
+ log(" --repo <owner/repo> Target repository (default: <owner>/<repo>)");
259
+ log(' --cron <expression> 5-field cron, min interval 1 HOUR (default: "0 * * * *")');
260
+ log(' Sub-hourly (e.g. "*/5 * * * *") is rejected.');
261
+ log(' --timezone <tz> Schedule timezone (default: "UTC")');
262
+ log(` --model <name> ${SUPPORTED_MODELS.join(" | ")}`);
263
+ log(" (default: claude-sonnet-4-6)");
264
+ log(` --max-items N Hard cap on items triaged/researched/reviewed per run`);
265
+ log(` (default: ${PIPELINE_DEFAULT_MAX_ITEMS}). Drives triage --max-items and items --limit.`);
266
+ log(" --output <path> Output file under .claude/routines/");
267
+ log(" (default: .claude/routines/<name>.yaml)");
268
+ log(" --force, -f Overwrite existing output file");
269
+ }
270
+ /**
271
+ * Entry point invoked by `runRoutine` (in `src/cli/routine.ts`) when the user
272
+ * types `radar routine generate pipeline`. Translates parsed flags into
273
+ * `generatePipelineRoutine` arguments and surfaces validation errors with the
274
+ * `routine generate pipeline:` prefix to match the rest of the CLI.
275
+ */
276
+ export async function runGeneratePipelineRoutine(args, io = {}, cwd = process.cwd()) {
277
+ const log = io.log ?? ((m) => console.log(m));
278
+ const error = io.error ?? ((m) => console.error(m));
279
+ let parsed;
280
+ try {
281
+ parsed = parseGeneratePipelineRoutineArgs(args);
282
+ }
283
+ catch (e) {
284
+ error(`routine generate pipeline: ${e instanceof Error ? e.message : String(e)}`);
285
+ return 2;
286
+ }
287
+ if (parsed.help) {
288
+ printGeneratePipelineRoutineHelp(log);
289
+ return 0;
290
+ }
291
+ try {
292
+ await generatePipelineRoutine({
293
+ cwd,
294
+ name: parsed.name,
295
+ repository: parsed.repository,
296
+ cron: parsed.cron,
297
+ timezone: parsed.timezone,
298
+ model: parsed.model,
299
+ maxItems: parsed.maxItems,
300
+ output: parsed.output,
301
+ force: parsed.force,
302
+ io,
303
+ });
304
+ return 0;
305
+ }
306
+ catch (e) {
307
+ error(`routine generate pipeline: ${e instanceof Error ? e.message : String(e)}`);
308
+ return 1;
309
+ }
310
+ }
311
+ //# 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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"}