@ozzylabs/feedradar 0.1.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 (168) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +104 -0
  3. package/dist/agents/_boundary.d.ts +44 -0
  4. package/dist/agents/_boundary.d.ts.map +1 -0
  5. package/dist/agents/_boundary.js +59 -0
  6. package/dist/agents/_boundary.js.map +1 -0
  7. package/dist/agents/claude-code.d.ts +32 -0
  8. package/dist/agents/claude-code.d.ts.map +1 -0
  9. package/dist/agents/claude-code.js +256 -0
  10. package/dist/agents/claude-code.js.map +1 -0
  11. package/dist/agents/codex-cli.d.ts +31 -0
  12. package/dist/agents/codex-cli.d.ts.map +1 -0
  13. package/dist/agents/codex-cli.js +303 -0
  14. package/dist/agents/codex-cli.js.map +1 -0
  15. package/dist/agents/copilot.d.ts +29 -0
  16. package/dist/agents/copilot.d.ts.map +1 -0
  17. package/dist/agents/copilot.js +282 -0
  18. package/dist/agents/copilot.js.map +1 -0
  19. package/dist/agents/gemini-cli.d.ts +30 -0
  20. package/dist/agents/gemini-cli.d.ts.map +1 -0
  21. package/dist/agents/gemini-cli.js +316 -0
  22. package/dist/agents/gemini-cli.js.map +1 -0
  23. package/dist/agents/index.d.ts +12 -0
  24. package/dist/agents/index.d.ts.map +1 -0
  25. package/dist/agents/index.js +33 -0
  26. package/dist/agents/index.js.map +1 -0
  27. package/dist/agents/types.d.ts +103 -0
  28. package/dist/agents/types.d.ts.map +1 -0
  29. package/dist/agents/types.js +2 -0
  30. package/dist/agents/types.js.map +1 -0
  31. package/dist/claude-skills/dismiss/SKILL.md +41 -0
  32. package/dist/claude-skills/research/SKILL.md +45 -0
  33. package/dist/claude-skills/review/SKILL.md +45 -0
  34. package/dist/claude-skills/update/SKILL.md +49 -0
  35. package/dist/cli/dismiss.d.ts +28 -0
  36. package/dist/cli/dismiss.d.ts.map +1 -0
  37. package/dist/cli/dismiss.js +122 -0
  38. package/dist/cli/dismiss.js.map +1 -0
  39. package/dist/cli/index.d.ts +7 -0
  40. package/dist/cli/index.d.ts.map +1 -0
  41. package/dist/cli/index.js +64 -0
  42. package/dist/cli/index.js.map +1 -0
  43. package/dist/cli/init.d.ts +148 -0
  44. package/dist/cli/init.d.ts.map +1 -0
  45. package/dist/cli/init.js +578 -0
  46. package/dist/cli/init.js.map +1 -0
  47. package/dist/cli/research.d.ts +30 -0
  48. package/dist/cli/research.d.ts.map +1 -0
  49. package/dist/cli/research.js +313 -0
  50. package/dist/cli/research.js.map +1 -0
  51. package/dist/cli/review.d.ts +34 -0
  52. package/dist/cli/review.d.ts.map +1 -0
  53. package/dist/cli/review.js +418 -0
  54. package/dist/cli/review.js.map +1 -0
  55. package/dist/cli/source.d.ts +57 -0
  56. package/dist/cli/source.d.ts.map +1 -0
  57. package/dist/cli/source.js +511 -0
  58. package/dist/cli/source.js.map +1 -0
  59. package/dist/cli/update.d.ts +43 -0
  60. package/dist/cli/update.d.ts.map +1 -0
  61. package/dist/cli/update.js +429 -0
  62. package/dist/cli/update.js.map +1 -0
  63. package/dist/cli/watch.d.ts +22 -0
  64. package/dist/cli/watch.d.ts.map +1 -0
  65. package/dist/cli/watch.js +101 -0
  66. package/dist/cli/watch.js.map +1 -0
  67. package/dist/core/config.d.ts +60 -0
  68. package/dist/core/config.d.ts.map +1 -0
  69. package/dist/core/config.js +101 -0
  70. package/dist/core/config.js.map +1 -0
  71. package/dist/core/feeds/derive-id.d.ts +43 -0
  72. package/dist/core/feeds/derive-id.d.ts.map +1 -0
  73. package/dist/core/feeds/derive-id.js +66 -0
  74. package/dist/core/feeds/derive-id.js.map +1 -0
  75. package/dist/core/feeds/github-api.d.ts +69 -0
  76. package/dist/core/feeds/github-api.d.ts.map +1 -0
  77. package/dist/core/feeds/github-api.js +161 -0
  78. package/dist/core/feeds/github-api.js.map +1 -0
  79. package/dist/core/feeds/github-releases.d.ts +3 -0
  80. package/dist/core/feeds/github-releases.d.ts.map +1 -0
  81. package/dist/core/feeds/github-releases.js +85 -0
  82. package/dist/core/feeds/github-releases.js.map +1 -0
  83. package/dist/core/feeds/html.d.ts +10 -0
  84. package/dist/core/feeds/html.d.ts.map +1 -0
  85. package/dist/core/feeds/html.js +263 -0
  86. package/dist/core/feeds/html.js.map +1 -0
  87. package/dist/core/feeds/index.d.ts +5 -0
  88. package/dist/core/feeds/index.d.ts.map +1 -0
  89. package/dist/core/feeds/index.js +18 -0
  90. package/dist/core/feeds/index.js.map +1 -0
  91. package/dist/core/feeds/npm-registry.d.ts +36 -0
  92. package/dist/core/feeds/npm-registry.d.ts.map +1 -0
  93. package/dist/core/feeds/npm-registry.js +200 -0
  94. package/dist/core/feeds/npm-registry.js.map +1 -0
  95. package/dist/core/feeds/rss.d.ts +12 -0
  96. package/dist/core/feeds/rss.d.ts.map +1 -0
  97. package/dist/core/feeds/rss.js +222 -0
  98. package/dist/core/feeds/rss.js.map +1 -0
  99. package/dist/core/feeds/types.d.ts +45 -0
  100. package/dist/core/feeds/types.d.ts.map +1 -0
  101. package/dist/core/feeds/types.js +2 -0
  102. package/dist/core/feeds/types.js.map +1 -0
  103. package/dist/core/filter.d.ts +25 -0
  104. package/dist/core/filter.d.ts.map +1 -0
  105. package/dist/core/filter.js +123 -0
  106. package/dist/core/filter.js.map +1 -0
  107. package/dist/core/injection-detector.d.ts +57 -0
  108. package/dist/core/injection-detector.d.ts.map +1 -0
  109. package/dist/core/injection-detector.js +109 -0
  110. package/dist/core/injection-detector.js.map +1 -0
  111. package/dist/core/items.d.ts +20 -0
  112. package/dist/core/items.d.ts.map +1 -0
  113. package/dist/core/items.js +105 -0
  114. package/dist/core/items.js.map +1 -0
  115. package/dist/core/state.d.ts +12 -0
  116. package/dist/core/state.d.ts.map +1 -0
  117. package/dist/core/state.js +42 -0
  118. package/dist/core/state.js.map +1 -0
  119. package/dist/core/templates.d.ts +21 -0
  120. package/dist/core/templates.d.ts.map +1 -0
  121. package/dist/core/templates.js +52 -0
  122. package/dist/core/templates.js.map +1 -0
  123. package/dist/core/watcher.d.ts +72 -0
  124. package/dist/core/watcher.d.ts.map +1 -0
  125. package/dist/core/watcher.js +240 -0
  126. package/dist/core/watcher.js.map +1 -0
  127. package/dist/gemini-commands/dismiss.toml +2 -0
  128. package/dist/gemini-commands/research.toml +2 -0
  129. package/dist/gemini-commands/review.toml +2 -0
  130. package/dist/gemini-commands/update.toml +2 -0
  131. package/dist/index.d.ts +3 -0
  132. package/dist/index.d.ts.map +1 -0
  133. package/dist/index.js +8 -0
  134. package/dist/index.js.map +1 -0
  135. package/dist/schemas/config.d.ts +39 -0
  136. package/dist/schemas/config.d.ts.map +1 -0
  137. package/dist/schemas/config.js +23 -0
  138. package/dist/schemas/config.js.map +1 -0
  139. package/dist/schemas/index.d.ts +6 -0
  140. package/dist/schemas/index.d.ts.map +1 -0
  141. package/dist/schemas/index.js +6 -0
  142. package/dist/schemas/index.js.map +1 -0
  143. package/dist/schemas/item.d.ts +38 -0
  144. package/dist/schemas/item.d.ts.map +1 -0
  145. package/dist/schemas/item.js +34 -0
  146. package/dist/schemas/item.js.map +1 -0
  147. package/dist/schemas/research.d.ts +82 -0
  148. package/dist/schemas/research.d.ts.map +1 -0
  149. package/dist/schemas/research.js +45 -0
  150. package/dist/schemas/research.js.map +1 -0
  151. package/dist/schemas/source.d.ts +139 -0
  152. package/dist/schemas/source.d.ts.map +1 -0
  153. package/dist/schemas/source.js +127 -0
  154. package/dist/schemas/source.js.map +1 -0
  155. package/dist/schemas/state.d.ts +19 -0
  156. package/dist/schemas/state.d.ts.map +1 -0
  157. package/dist/schemas/state.js +12 -0
  158. package/dist/schemas/state.js.map +1 -0
  159. package/dist/skills/research/SKILL.md +156 -0
  160. package/dist/skills/review/SKILL.md +173 -0
  161. package/dist/skills/update/SKILL.md +200 -0
  162. package/dist/templates/agents/AGENTS.md +161 -0
  163. package/dist/templates/claude/CLAUDE.md +5 -0
  164. package/dist/templates/default.md +16 -0
  165. package/dist/templates/feedradar.md +165 -0
  166. package/dist/templates/routines/watch-daily.md +42 -0
  167. package/dist/templates/workflows/watch.yaml +70 -0
  168. package/package.json +73 -0
@@ -0,0 +1,511 @@
1
+ import { access, readdir, readFile, unlink, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
4
+ import { loadSourceState } from "../core/state.js";
5
+ import { SourceKindSchema, SourceSchema, SourceSelectorsSchema } from "../schemas/source.js";
6
+ async function pathExists(p) {
7
+ try {
8
+ await access(p);
9
+ return true;
10
+ }
11
+ catch {
12
+ return false;
13
+ }
14
+ }
15
+ function sourcesDir(cwd) {
16
+ return join(cwd, "sources");
17
+ }
18
+ function sourceFile(cwd, id) {
19
+ return join(sourcesDir(cwd), `${id}.yaml`);
20
+ }
21
+ function stateDir(cwd) {
22
+ return join(cwd, "state");
23
+ }
24
+ /**
25
+ * Validate a source id as a safe filename component.
26
+ *
27
+ * Rejecting path separators, leading dots, and shell-unsafe characters keeps
28
+ * `sources/<id>.yaml` from escaping the sources/ directory or producing
29
+ * surprising paths. The CLI is single-user but ids may flow from copy-pasted
30
+ * URLs or scripted inputs, so a conservative regex avoids footguns.
31
+ */
32
+ function isSafeSourceId(id) {
33
+ return /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(id) && !id.includes("..");
34
+ }
35
+ /** Split a comma-separated CLI argument into trimmed, non-empty tokens. */
36
+ function splitCsv(value) {
37
+ return value
38
+ .split(",")
39
+ .map((s) => s.trim())
40
+ .filter((s) => s.length > 0);
41
+ }
42
+ /**
43
+ * Parse `source add` flags.
44
+ *
45
+ * Throws on flags that require a value but receive none, or on unknown flags.
46
+ * Returning structured data keeps run() free of argument-parsing branches.
47
+ */
48
+ function parseAddArgs(args) {
49
+ const out = {};
50
+ for (let i = 0; i < args.length; i++) {
51
+ const a = args[i];
52
+ if (a === "-h" || a === "--help") {
53
+ out.help = true;
54
+ continue;
55
+ }
56
+ if (a === "--kind") {
57
+ out.kind = args[++i];
58
+ continue;
59
+ }
60
+ if (a === "--url") {
61
+ out.url = args[++i];
62
+ continue;
63
+ }
64
+ if (a === "--name") {
65
+ out.name = args[++i];
66
+ continue;
67
+ }
68
+ if (a === "--tags") {
69
+ out.tags = splitCsv(args[++i] ?? "");
70
+ continue;
71
+ }
72
+ if (a === "--keywords") {
73
+ out.keywords = splitCsv(args[++i] ?? "");
74
+ continue;
75
+ }
76
+ if (a === "--exclude-keywords") {
77
+ out.excludeKeywords = splitCsv(args[++i] ?? "");
78
+ continue;
79
+ }
80
+ if (a?.startsWith("--selector-")) {
81
+ // `--selector-<field> <css>` — e.g. `--selector-item "article.entry"`.
82
+ // Field validity (item / title / link / summary / publishedAt / body /
83
+ // tags) is enforced by SourceSelectorsSchema at parse time, so unknown
84
+ // fields surface as a normal validation error instead of being silently
85
+ // swallowed here.
86
+ const field = a.slice("--selector-".length);
87
+ if (!field)
88
+ throw new Error(`unknown option: ${a}`);
89
+ const value = args[++i];
90
+ if (value === undefined)
91
+ throw new Error(`option ${a} requires a value`);
92
+ out.selectors ??= {};
93
+ out.selectors[field] = value;
94
+ continue;
95
+ }
96
+ if (a?.startsWith("--")) {
97
+ throw new Error(`unknown option: ${a}`);
98
+ }
99
+ if (!out.id) {
100
+ out.id = a;
101
+ continue;
102
+ }
103
+ throw new Error(`unexpected positional argument: ${a}`);
104
+ }
105
+ return out;
106
+ }
107
+ function parseListArgs(args) {
108
+ const out = {};
109
+ for (const a of args) {
110
+ if (a === "-h" || a === "--help") {
111
+ out.help = true;
112
+ continue;
113
+ }
114
+ if (a === "--enabled-only") {
115
+ out.enabledOnly = true;
116
+ continue;
117
+ }
118
+ if (a === "-v" || a === "--verbose") {
119
+ out.verbose = true;
120
+ continue;
121
+ }
122
+ throw new Error(`unknown option: ${a}`);
123
+ }
124
+ return out;
125
+ }
126
+ function parseRemoveArgs(args) {
127
+ const out = {};
128
+ for (const a of args) {
129
+ if (a === "-h" || a === "--help") {
130
+ out.help = true;
131
+ continue;
132
+ }
133
+ if (a.startsWith("--")) {
134
+ throw new Error(`unknown option: ${a}`);
135
+ }
136
+ if (!out.id) {
137
+ out.id = a;
138
+ continue;
139
+ }
140
+ throw new Error(`unexpected positional argument: ${a}`);
141
+ }
142
+ return out;
143
+ }
144
+ function printAddHelp(log) {
145
+ log("Usage: radar source add <id> --kind <kind> --url <url> [options]");
146
+ log("");
147
+ log("Options:");
148
+ log(" --kind <kind> rss | html | github-releases | npm-registry");
149
+ log(" --url <url> fetch target URL");
150
+ log(" --name <name> display name (defaults to <id>)");
151
+ log(" --tags <a,b> comma-separated tags");
152
+ log(" --keywords <a,b> comma-separated include keywords");
153
+ log(" (required for useful output — empty = match nothing)");
154
+ log(" --exclude-keywords <a,b> comma-separated exclude keywords");
155
+ log(" --selector-<field> <css> CSS selector for kind=html (required: item, title, link)");
156
+ log(" optional: summary, publishedAt, body, tags");
157
+ }
158
+ function printListHelp(log) {
159
+ log("Usage: radar source list [--enabled-only] [-v|--verbose]");
160
+ log("");
161
+ log("Lists sources/*.yaml in tabular form: id / kind / url / tags.");
162
+ log("");
163
+ log("Options:");
164
+ log(" --enabled-only Reserved for forward compatibility (currently a no-op).");
165
+ log(" -v, --verbose Print a detailed block per source including keywords,");
166
+ log(" trustLevel, and lastFetchedAt (from state/<id>.yaml).");
167
+ }
168
+ function printRemoveHelp(log) {
169
+ log("Usage: radar source remove <id>");
170
+ log("");
171
+ log("Deletes sources/<id>.yaml. state/<id>.yaml and items/ are preserved.");
172
+ }
173
+ function printSourceHelp(log) {
174
+ log("Usage: radar source <add|list|remove> [...]");
175
+ log("");
176
+ log("Subcommands:");
177
+ log(" add <id> --kind <kind> --url <url> [...]");
178
+ log(" list [--enabled-only]");
179
+ log(" remove <id>");
180
+ }
181
+ /**
182
+ * Implementation of `source add`.
183
+ *
184
+ * Builds a Source object from CLI flags, validates it with the Zod schema, and
185
+ * writes `sources/<id>.yaml`. Refuses to overwrite an existing file (issue #12
186
+ * explicitly forbids `--force`-style escape hatches; YAML edits remain the
187
+ * supported workflow for mutation).
188
+ */
189
+ export async function addSource(args, options = {}) {
190
+ const cwd = options.cwd ?? process.cwd();
191
+ const log = options.io?.log ?? ((m) => console.log(m));
192
+ const warn = options.io?.warn ?? ((m) => console.warn(m));
193
+ const error = options.io?.error ?? ((m) => console.error(m));
194
+ let parsed;
195
+ try {
196
+ parsed = parseAddArgs(args);
197
+ }
198
+ catch (e) {
199
+ error(`source add: ${e instanceof Error ? e.message : String(e)}`);
200
+ return 2;
201
+ }
202
+ if (parsed.help) {
203
+ printAddHelp(log);
204
+ return 0;
205
+ }
206
+ if (!parsed.id) {
207
+ error("source add: missing <id>");
208
+ printAddHelp(error);
209
+ return 2;
210
+ }
211
+ if (!isSafeSourceId(parsed.id)) {
212
+ error(`source add: invalid <id> '${parsed.id}' (must match [A-Za-z0-9][A-Za-z0-9._-]*)`);
213
+ return 2;
214
+ }
215
+ if (!parsed.kind) {
216
+ error("source add: --kind is required");
217
+ return 2;
218
+ }
219
+ if (!parsed.url) {
220
+ error("source add: --url is required");
221
+ return 2;
222
+ }
223
+ const kindResult = SourceKindSchema.safeParse(parsed.kind);
224
+ if (!kindResult.success) {
225
+ error(`source add: invalid --kind '${parsed.kind}' (expected: rss | html | github-releases | npm-registry)`);
226
+ return 2;
227
+ }
228
+ // Compose the object before schema validation so url-format errors et al.
229
+ // surface through Zod (single source of truth for shape rules).
230
+ const candidate = {
231
+ id: parsed.id,
232
+ kind: kindResult.data,
233
+ url: parsed.url,
234
+ };
235
+ if (parsed.name)
236
+ candidate.name = parsed.name;
237
+ if (parsed.tags && parsed.tags.length > 0)
238
+ candidate.tags = parsed.tags;
239
+ if ((parsed.keywords && parsed.keywords.length > 0) ||
240
+ (parsed.excludeKeywords && parsed.excludeKeywords.length > 0)) {
241
+ const filters = {};
242
+ if (parsed.keywords && parsed.keywords.length > 0)
243
+ filters.keywords = parsed.keywords;
244
+ if (parsed.excludeKeywords && parsed.excludeKeywords.length > 0) {
245
+ filters.excludeKeywords = parsed.excludeKeywords;
246
+ }
247
+ candidate.filters = filters;
248
+ }
249
+ if (parsed.selectors) {
250
+ // Validate selector shape early so the user sees a single targeted error
251
+ // ("selectors.item: required") instead of the refinement-level "selectors
252
+ // is required when kind is 'html'" further down.
253
+ const selectorsResult = SourceSelectorsSchema.safeParse(parsed.selectors);
254
+ if (!selectorsResult.success) {
255
+ const issues = selectorsResult.error.issues.map((i) => `selectors.${i.path.join(".") || "<root>"}: ${i.message}`);
256
+ error(`source add: validation failed`);
257
+ for (const issue of issues) {
258
+ error(` - ${issue}`);
259
+ }
260
+ return 2;
261
+ }
262
+ candidate.selectors = selectorsResult.data;
263
+ }
264
+ const validated = SourceSchema.safeParse(candidate);
265
+ if (!validated.success) {
266
+ const issues = validated.error.issues.map((i) => `${i.path.join(".") || "<root>"}: ${i.message}`);
267
+ error(`source add: validation failed`);
268
+ for (const issue of issues) {
269
+ error(` - ${issue}`);
270
+ }
271
+ return 2;
272
+ }
273
+ const file = sourceFile(cwd, validated.data.id);
274
+ if (await pathExists(file)) {
275
+ error(`source add: '${validated.data.id}' already exists (sources/${validated.data.id}.yaml)`);
276
+ return 1;
277
+ }
278
+ await writeFile(file, stringifyYaml(validated.data), "utf8");
279
+ log(`source add: created sources/${validated.data.id}.yaml`);
280
+ // ADR-0006 / src/core/filter.ts treats an empty include-keyword list as
281
+ // "match nothing" (firehose guard). A source with no keywords is therefore
282
+ // valid YAML but inert — `watch run` will fetch it and drop every item
283
+ // before disk. Surface a hint here so the user is not left wondering why
284
+ // their feed appears silent later. We emit the hint as a non-fatal warning
285
+ // (stderr) so scripts that parse stdout are unaffected and the exit code
286
+ // stays 0.
287
+ if (validated.data.filters.keywords.length === 0) {
288
+ warn(`source add: warning — '${validated.data.id}' has no keywords; all fetched items will be filtered out. Edit sources/${validated.data.id}.yaml or re-add with --keywords to start ingesting.`);
289
+ }
290
+ return 0;
291
+ }
292
+ /**
293
+ * Load and validate a single `sources/<id>.yaml` file. Returns `null` and
294
+ * reports through `onError` when the file is malformed, so `list` can keep
295
+ * going across other entries.
296
+ */
297
+ async function readSourceFile(cwd, filename, onError) {
298
+ const file = join(sourcesDir(cwd), filename);
299
+ let raw;
300
+ try {
301
+ raw = await readFile(file, "utf8");
302
+ }
303
+ catch (e) {
304
+ onError(`source list: failed to read ${filename}: ${e instanceof Error ? e.message : String(e)}`);
305
+ return null;
306
+ }
307
+ let parsed;
308
+ try {
309
+ parsed = parseYaml(raw);
310
+ }
311
+ catch (e) {
312
+ onError(`source list: invalid YAML in ${filename}: ${e instanceof Error ? e.message : String(e)}`);
313
+ return null;
314
+ }
315
+ const result = SourceSchema.safeParse(parsed);
316
+ if (!result.success) {
317
+ onError(`source list: schema mismatch in ${filename}`);
318
+ return null;
319
+ }
320
+ return result.data;
321
+ }
322
+ /** Pad/truncate `value` to exactly `width` characters for table rendering. */
323
+ function pad(value, width) {
324
+ if (value.length >= width)
325
+ return value.slice(0, width);
326
+ return value + " ".repeat(width - value.length);
327
+ }
328
+ /**
329
+ * Implementation of `source list`.
330
+ *
331
+ * Renders a fixed-width table (id / kind / url / tags). When no sources exist
332
+ * we print a guidance message instead of an empty table so first-time users
333
+ * are nudged toward `source add`.
334
+ */
335
+ export async function listSources(args, options = {}) {
336
+ const cwd = options.cwd ?? process.cwd();
337
+ const log = options.io?.log ?? ((m) => console.log(m));
338
+ const error = options.io?.error ?? ((m) => console.error(m));
339
+ let parsed;
340
+ try {
341
+ parsed = parseListArgs(args);
342
+ }
343
+ catch (e) {
344
+ error(`source list: ${e instanceof Error ? e.message : String(e)}`);
345
+ return 2;
346
+ }
347
+ if (parsed.help) {
348
+ printListHelp(log);
349
+ return 0;
350
+ }
351
+ // --enabled-only is wired through for forward compatibility; the schema does
352
+ // not yet model an `enabled` field (see issue #13 for filter extensions), so
353
+ // for now we treat the flag as a no-op rather than an error to keep the CLI
354
+ // surface stable.
355
+ const dir = sourcesDir(cwd);
356
+ if (!(await pathExists(dir))) {
357
+ log("source list: no sources directory (run `radar init` first)");
358
+ return 0;
359
+ }
360
+ let entries;
361
+ try {
362
+ entries = await readdir(dir);
363
+ }
364
+ catch (e) {
365
+ error(`source list: failed to read sources/: ${e instanceof Error ? e.message : String(e)}`);
366
+ return 1;
367
+ }
368
+ const yamlFiles = entries.filter((f) => f.endsWith(".yaml")).sort();
369
+ if (yamlFiles.length === 0) {
370
+ log("source list: no sources defined (use `radar source add ...`)");
371
+ return 0;
372
+ }
373
+ const sources = [];
374
+ for (const filename of yamlFiles) {
375
+ const s = await readSourceFile(cwd, filename, error);
376
+ if (s)
377
+ sources.push(s);
378
+ }
379
+ if (sources.length === 0) {
380
+ // All entries were malformed; errors already printed by readSourceFile.
381
+ return 1;
382
+ }
383
+ if (parsed.verbose) {
384
+ // Verbose mode: emit a per-source block so we can include multi-line
385
+ // fields (keywords / trustLevel / lastFetchedAt) without breaking the
386
+ // 4-column table contract scripts may rely on. State is read lazily per
387
+ // source so a missing state file is rendered as "never" rather than
388
+ // surfacing as an error (state is created on first `watch run`).
389
+ for (let i = 0; i < sources.length; i++) {
390
+ const s = sources[i];
391
+ if (!s)
392
+ continue;
393
+ if (i > 0)
394
+ log("");
395
+ const lastFetchedAt = await readLastFetchedAt(cwd, s.id, error);
396
+ log(`${s.id}`);
397
+ log(` kind: ${s.kind}`);
398
+ log(` url: ${s.url}`);
399
+ log(` name: ${s.name ?? "-"}`);
400
+ log(` tags: ${s.tags.length > 0 ? s.tags.join(",") : "-"}`);
401
+ log(` keywords: ${s.filters.keywords.length > 0 ? s.filters.keywords.join(",") : "(none — items will be filtered out)"}`);
402
+ log(` excludeKeywords: ${s.filters.excludeKeywords.length > 0 ? s.filters.excludeKeywords.join(",") : "-"}`);
403
+ log(` trustLevel: ${s.trustLevel}`);
404
+ log(` lastFetchedAt: ${lastFetchedAt}`);
405
+ }
406
+ return 0;
407
+ }
408
+ const idWidth = Math.max(2, ...sources.map((s) => s.id.length));
409
+ const kindWidth = Math.max(4, ...sources.map((s) => s.kind.length));
410
+ const urlWidth = Math.max(3, ...sources.map((s) => s.url.length));
411
+ log(`${pad("ID", idWidth)} ${pad("KIND", kindWidth)} ${pad("URL", urlWidth)} TAGS`);
412
+ for (const s of sources) {
413
+ log(`${pad(s.id, idWidth)} ${pad(s.kind, kindWidth)} ${pad(s.url, urlWidth)} ${s.tags.join(",")}`);
414
+ }
415
+ return 0;
416
+ }
417
+ /**
418
+ * Best-effort read of `state/<id>.yaml`'s `lastFetchedAt`.
419
+ *
420
+ * Returns `"never"` when the state file does not exist or carries no
421
+ * `lastFetchedAt` (e.g. bootstrap-only state with no successful fetch yet),
422
+ * and `"unreadable"` for any other I/O or parse failure. Errors are surfaced
423
+ * via `onError` so the user sees them, but we never throw — `source list` is
424
+ * a read-only listing command and one broken state file should not prevent
425
+ * the rest from rendering.
426
+ */
427
+ async function readLastFetchedAt(cwd, sourceId, onError) {
428
+ try {
429
+ const state = await loadSourceState(stateDir(cwd), sourceId);
430
+ return state.lastFetchedAt ?? "never";
431
+ }
432
+ catch (e) {
433
+ onError(`source list: failed to read state/${sourceId}.yaml: ${e instanceof Error ? e.message : String(e)}`);
434
+ return "unreadable";
435
+ }
436
+ }
437
+ /**
438
+ * Implementation of `source remove`.
439
+ *
440
+ * Deletes `sources/<id>.yaml` only. Per user-guide.md and issue #12, this
441
+ * intentionally preserves `state/<id>.yaml` and any `items/` history so users
442
+ * never lose recorded research by toggling a source off.
443
+ */
444
+ export async function removeSource(args, options = {}) {
445
+ const cwd = options.cwd ?? process.cwd();
446
+ const log = options.io?.log ?? ((m) => console.log(m));
447
+ const error = options.io?.error ?? ((m) => console.error(m));
448
+ let parsed;
449
+ try {
450
+ parsed = parseRemoveArgs(args);
451
+ }
452
+ catch (e) {
453
+ error(`source remove: ${e instanceof Error ? e.message : String(e)}`);
454
+ return 2;
455
+ }
456
+ if (parsed.help) {
457
+ printRemoveHelp(log);
458
+ return 0;
459
+ }
460
+ if (!parsed.id) {
461
+ error("source remove: missing <id>");
462
+ printRemoveHelp(error);
463
+ return 2;
464
+ }
465
+ if (!isSafeSourceId(parsed.id)) {
466
+ error(`source remove: invalid <id> '${parsed.id}' (must match [A-Za-z0-9][A-Za-z0-9._-]*)`);
467
+ return 2;
468
+ }
469
+ const file = sourceFile(cwd, parsed.id);
470
+ if (!(await pathExists(file))) {
471
+ error(`source remove: '${parsed.id}' not found (sources/${parsed.id}.yaml)`);
472
+ return 1;
473
+ }
474
+ await unlink(file);
475
+ log(`source remove: deleted sources/${parsed.id}.yaml`);
476
+ return 0;
477
+ }
478
+ /**
479
+ * Top-level dispatcher for `radar source <subcommand>`.
480
+ *
481
+ * Sub-commands are kept as named functions (addSource/listSources/removeSource)
482
+ * so tests can call them directly with injected IO sinks without spawning the
483
+ * full CLI.
484
+ */
485
+ export async function runSource(args, options = {}) {
486
+ const log = options.io?.log ?? ((m) => console.log(m));
487
+ const error = options.io?.error ?? ((m) => console.error(m));
488
+ const [sub, ...rest] = args;
489
+ if (!sub || sub === "-h" || sub === "--help" || sub === "help") {
490
+ printSourceHelp(log);
491
+ return sub ? 0 : 2;
492
+ }
493
+ switch (sub) {
494
+ case "add":
495
+ return addSource(rest, options);
496
+ case "list":
497
+ return listSources(rest, options);
498
+ case "remove":
499
+ return removeSource(rest, options);
500
+ default:
501
+ error(`source: unknown subcommand '${sub}'`);
502
+ printSourceHelp(error);
503
+ return 2;
504
+ }
505
+ }
506
+ export const sourceCommand = {
507
+ name: "source",
508
+ summary: "Manage feed sources (add | list | remove)",
509
+ run: (args) => runSource(args),
510
+ };
511
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/cli/source.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { Command } from "./index.js";
2
+ /** Sinks for the update command's user-facing output. Tests inject capturing sinks. */
3
+ export interface UpdateIO {
4
+ log?: (message: string) => void;
5
+ warn?: (message: string) => void;
6
+ error?: (message: string) => void;
7
+ }
8
+ export interface UpdateCommandOptions {
9
+ cwd?: string;
10
+ io?: UpdateIO;
11
+ }
12
+ /**
13
+ * Implementation of `radar update <research-id>`.
14
+ *
15
+ * High-level flow (Phase 5, [#41](https://github.com/ozzy-labs/feedradar/issues/41)):
16
+ * 1. Parse + validate args (agent defaults to `claude-code`, template to `default`).
17
+ * 2. Resolve `research/<research-id>.md` and parse its frontmatter.
18
+ * 3. Compute the new id `<base>_v<n+1>` and refuse to overwrite an existing
19
+ * `research/<new-id>.md` (idempotent re-runs are user-facing errors).
20
+ * 4. Locate the linked items (read-only; their `status` is preserved per
21
+ * ADR-0008 / skill-design.md §8.4).
22
+ * 5. Reject `update` when any linked item is in `detected` / `dismissed`
23
+ * (no v1 research exists, or the user opted out of researching it).
24
+ * 6. Load `templates/<template-id>.md` (empty body when default is absent).
25
+ * 7. Invoke the adapter; the agent writes the new file at `outputPath`.
26
+ * 8. Re-read the new file, validate frontmatter against
27
+ * `ResearchFrontmatterSchema`, and assert v+1 invariants:
28
+ * - `id` matches the computed new id
29
+ * - `itemIds` / `templateId` / `createdAt` preserved from v(N)
30
+ * - `supersedes` equals the v(N) id
31
+ * - `reviewedAt` / `reviewedBy` are `null` (review state does NOT carry
32
+ * across versions per ADR-0003 / skill-design.md §8.3)
33
+ * 9. **No items.yaml mutation** — `update` is intentionally inert wrt item
34
+ * status. The v1 review event (if any) remains the authoritative record.
35
+ *
36
+ * Unlike `review`, `update` does not snapshot/restore: writing a new file is
37
+ * additive, so a failed adapter just leaves a missing / partial new file that
38
+ * the user can re-run after fixing the underlying issue. The predecessor file
39
+ * is never opened for writing.
40
+ */
41
+ export declare function runUpdate(args: string[], options?: UpdateCommandOptions): Promise<number>;
42
+ export declare const updateCommand: Command;
43
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/cli/update.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAkB1C,uFAAuF;AACvF,MAAM,WAAW,QAAQ;IACvB,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,oBAAoB;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,QAAQ,CAAC;CACf;AAuHD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,MAAM,CAAC,CAgSjB;AAED,eAAO,MAAM,aAAa,EAAE,OAI3B,CAAC"}