@ozzylabs/feedradar 0.1.3 → 0.1.5

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 (144) hide show
  1. package/README.ja.md +31 -6
  2. package/README.md +31 -6
  3. package/dist/agents/claude-code.d.ts +12 -1
  4. package/dist/agents/claude-code.d.ts.map +1 -1
  5. package/dist/agents/claude-code.js +9 -5
  6. package/dist/agents/claude-code.js.map +1 -1
  7. package/dist/agents/codex-cli.d.ts +7 -1
  8. package/dist/agents/codex-cli.d.ts.map +1 -1
  9. package/dist/agents/codex-cli.js +9 -5
  10. package/dist/agents/codex-cli.js.map +1 -1
  11. package/dist/agents/copilot.d.ts +7 -1
  12. package/dist/agents/copilot.d.ts.map +1 -1
  13. package/dist/agents/copilot.js +9 -5
  14. package/dist/agents/copilot.js.map +1 -1
  15. package/dist/agents/gemini-cli.d.ts +7 -1
  16. package/dist/agents/gemini-cli.d.ts.map +1 -1
  17. package/dist/agents/gemini-cli.js +9 -5
  18. package/dist/agents/gemini-cli.js.map +1 -1
  19. package/dist/agents/index.d.ts +1 -1
  20. package/dist/agents/index.d.ts.map +1 -1
  21. package/dist/agents/types.d.ts +33 -0
  22. package/dist/agents/types.d.ts.map +1 -1
  23. package/dist/cli/_progress.d.ts +138 -0
  24. package/dist/cli/_progress.d.ts.map +1 -0
  25. package/dist/cli/_progress.js +176 -0
  26. package/dist/cli/_progress.js.map +1 -0
  27. package/dist/cli/doctor.d.ts +20 -0
  28. package/dist/cli/doctor.d.ts.map +1 -1
  29. package/dist/cli/doctor.js +291 -2
  30. package/dist/cli/doctor.js.map +1 -1
  31. package/dist/cli/index.d.ts.map +1 -1
  32. package/dist/cli/index.js +2 -0
  33. package/dist/cli/index.js.map +1 -1
  34. package/dist/cli/research.d.ts +18 -20
  35. package/dist/cli/research.d.ts.map +1 -1
  36. package/dist/cli/research.js +318 -203
  37. package/dist/cli/research.js.map +1 -1
  38. package/dist/cli/respawn.d.ts +53 -0
  39. package/dist/cli/respawn.d.ts.map +1 -0
  40. package/dist/cli/respawn.js +120 -0
  41. package/dist/cli/respawn.js.map +1 -0
  42. package/dist/cli/review.d.ts +7 -0
  43. package/dist/cli/review.d.ts.map +1 -1
  44. package/dist/cli/review.js +46 -1
  45. package/dist/cli/review.js.map +1 -1
  46. package/dist/cli/source.d.ts +23 -2
  47. package/dist/cli/source.d.ts.map +1 -1
  48. package/dist/cli/source.js +425 -7
  49. package/dist/cli/source.js.map +1 -1
  50. package/dist/cli/update.d.ts +7 -0
  51. package/dist/cli/update.d.ts.map +1 -1
  52. package/dist/cli/update.js +41 -1
  53. package/dist/cli/update.js.map +1 -1
  54. package/dist/cli/watch.d.ts.map +1 -1
  55. package/dist/cli/watch.js +65 -3
  56. package/dist/cli/watch.js.map +1 -1
  57. package/dist/cli/workflow/generate-combined.d.ts +100 -0
  58. package/dist/cli/workflow/generate-combined.d.ts.map +1 -0
  59. package/dist/cli/workflow/generate-combined.js +387 -0
  60. package/dist/cli/workflow/generate-combined.js.map +1 -0
  61. package/dist/cli/workflow/generate-watch.d.ts +142 -0
  62. package/dist/cli/workflow/generate-watch.d.ts.map +1 -0
  63. package/dist/cli/workflow/generate-watch.js +338 -0
  64. package/dist/cli/workflow/generate-watch.js.map +1 -0
  65. package/dist/cli/workflow.d.ts +29 -0
  66. package/dist/cli/workflow.d.ts.map +1 -0
  67. package/dist/cli/workflow.js +66 -0
  68. package/dist/cli/workflow.js.map +1 -0
  69. package/dist/core/feeds/_fetch.d.ts +103 -0
  70. package/dist/core/feeds/_fetch.d.ts.map +1 -0
  71. package/dist/core/feeds/_fetch.js +364 -0
  72. package/dist/core/feeds/_fetch.js.map +1 -0
  73. package/dist/core/feeds/_jsonpath.d.ts +57 -0
  74. package/dist/core/feeds/_jsonpath.d.ts.map +1 -0
  75. package/dist/core/feeds/_jsonpath.js +207 -0
  76. package/dist/core/feeds/_jsonpath.js.map +1 -0
  77. package/dist/core/feeds/github-api.d.ts.map +1 -1
  78. package/dist/core/feeds/github-api.js +2 -1
  79. package/dist/core/feeds/github-api.js.map +1 -1
  80. package/dist/core/feeds/html-js.d.ts +29 -0
  81. package/dist/core/feeds/html-js.d.ts.map +1 -1
  82. package/dist/core/feeds/html-js.js +86 -2
  83. package/dist/core/feeds/html-js.js.map +1 -1
  84. package/dist/core/feeds/html.d.ts.map +1 -1
  85. package/dist/core/feeds/html.js +2 -1
  86. package/dist/core/feeds/html.js.map +1 -1
  87. package/dist/core/feeds/index.d.ts +1 -1
  88. package/dist/core/feeds/index.d.ts.map +1 -1
  89. package/dist/core/feeds/index.js +4 -0
  90. package/dist/core/feeds/index.js.map +1 -1
  91. package/dist/core/feeds/json-api.d.ts +3 -0
  92. package/dist/core/feeds/json-api.d.ts.map +1 -0
  93. package/dist/core/feeds/json-api.js +723 -0
  94. package/dist/core/feeds/json-api.js.map +1 -0
  95. package/dist/core/feeds/json-feed.d.ts +11 -0
  96. package/dist/core/feeds/json-feed.d.ts.map +1 -0
  97. package/dist/core/feeds/json-feed.js +242 -0
  98. package/dist/core/feeds/json-feed.js.map +1 -0
  99. package/dist/core/feeds/npm-registry.d.ts.map +1 -1
  100. package/dist/core/feeds/npm-registry.js +2 -1
  101. package/dist/core/feeds/npm-registry.js.map +1 -1
  102. package/dist/core/feeds/rss.d.ts.map +1 -1
  103. package/dist/core/feeds/rss.js +2 -1
  104. package/dist/core/feeds/rss.js.map +1 -1
  105. package/dist/core/feeds/types.d.ts +123 -0
  106. package/dist/core/feeds/types.d.ts.map +1 -1
  107. package/dist/core/progress.d.ts +101 -0
  108. package/dist/core/progress.d.ts.map +1 -0
  109. package/dist/core/progress.js +212 -0
  110. package/dist/core/progress.js.map +1 -0
  111. package/dist/core/proxy.d.ts +87 -0
  112. package/dist/core/proxy.d.ts.map +1 -0
  113. package/dist/core/proxy.js +146 -0
  114. package/dist/core/proxy.js.map +1 -0
  115. package/dist/core/recipes.d.ts +138 -0
  116. package/dist/core/recipes.d.ts.map +1 -0
  117. package/dist/core/recipes.js +238 -0
  118. package/dist/core/recipes.js.map +1 -0
  119. package/dist/core/watcher.d.ts +61 -1
  120. package/dist/core/watcher.d.ts.map +1 -1
  121. package/dist/core/watcher.js +99 -2
  122. package/dist/core/watcher.js.map +1 -1
  123. package/dist/index.js +17 -4
  124. package/dist/index.js.map +1 -1
  125. package/dist/recipes/aws-whats-new.yaml +61 -0
  126. package/dist/recipes/dev-to.yaml +40 -0
  127. package/dist/schemas/index.d.ts +1 -0
  128. package/dist/schemas/index.d.ts.map +1 -1
  129. package/dist/schemas/index.js +1 -0
  130. package/dist/schemas/index.js.map +1 -1
  131. package/dist/schemas/recipe.d.ts +115 -0
  132. package/dist/schemas/recipe.d.ts.map +1 -0
  133. package/dist/schemas/recipe.js +54 -0
  134. package/dist/schemas/recipe.js.map +1 -0
  135. package/dist/schemas/source.d.ts +130 -0
  136. package/dist/schemas/source.d.ts.map +1 -1
  137. package/dist/schemas/source.js +130 -0
  138. package/dist/schemas/source.js.map +1 -1
  139. package/dist/templates/agents/AGENTS.md +31 -3
  140. package/dist/templates/feedradar.md +23 -8
  141. package/dist/templates/workflows/combined.template.yaml.tmpl +110 -0
  142. package/dist/templates/workflows/watch.template.yaml.tmpl +103 -0
  143. package/dist/templates/workflows/watch.yaml +5 -1
  144. package/package.json +2 -3
@@ -5,6 +5,8 @@ export const SourceKindSchema = z.enum([
5
5
  "html-js",
6
6
  "github-releases",
7
7
  "npm-registry",
8
+ "json-feed",
9
+ "json-api",
8
10
  ]);
9
11
  /**
10
12
  * Match modes for keyword evaluation (ADR-0006).
@@ -93,6 +95,114 @@ export const SourceJsOptionsSchema = z.object({
93
95
  timeout: z.number().int().positive().default(30000),
94
96
  userAgent: z.string().optional(),
95
97
  });
98
+ /**
99
+ * HTTP options for `kind: json-api` sources (ADR-0012 §D2).
100
+ *
101
+ * Phase 1 supports GET only. `headers` accepts arbitrary key/value pairs and
102
+ * supports `${VAR}` env-var interpolation (resolved by the adapter, never
103
+ * persisted to log / frontmatter — see ADR-0012 §D5c).
104
+ *
105
+ * The schema deliberately does not validate header values against env names —
106
+ * the adapter handles unresolved `${VAR}` placeholders by omitting the header
107
+ * (degraded fetch). This lets public APIs work without env wiring while
108
+ * authenticated APIs fail-fast with a 401/403 at runtime.
109
+ */
110
+ export const SourceHttpOptionsSchema = z.object({
111
+ method: z.literal("GET").default("GET"),
112
+ headers: z.record(z.string(), z.string()).default({}),
113
+ });
114
+ /**
115
+ * Pagination configuration for `kind: json-api` sources (ADR-0012 §D2).
116
+ *
117
+ * Five wire formats are supported:
118
+ *
119
+ * page — `?page=K&pageSize=N` (e.g. AWS What's New, dev.to)
120
+ * offset — `?offset=K&limit=N`
121
+ * cursor — `?after=<cursorValue>` with `nextCursor` extracted via JSONPath
122
+ * link-header — `Link: <...>; rel="next"` HTTP header
123
+ * token — `?pageToken=<opaque>` opaque continuation token
124
+ * none — single request, no pagination
125
+ *
126
+ * `maxPages` is a hard cap to prevent runaway loops / DoS on misconfigured
127
+ * recipes. The default (20) matches a conservative bound for normal-mode
128
+ * fetching; `--backfill` can override via `--max-pages` to walk further.
129
+ *
130
+ * `nextCursorPath` / `totalPath` are JSONPath-lite expressions resolved against
131
+ * the parsed response body. `totalPath` is consulted in backfill mode to
132
+ * compute an upper bound on pages and short-circuit early when the total is
133
+ * known.
134
+ */
135
+ export const SourcePaginationSchema = z.object({
136
+ type: z.enum(["page", "offset", "cursor", "link-header", "token", "none"]),
137
+ /**
138
+ * Query parameter name for the page / offset / token (e.g. `page`, `offset`,
139
+ * `after`, `pageToken`). Required for `page` / `offset` / `cursor` / `token`;
140
+ * ignored for `link-header` / `none`.
141
+ */
142
+ param: z.string().min(1).optional(),
143
+ /** Initial value (e.g. 0 for offset, 1 for page-number, undefined for cursor/token). */
144
+ start: z.number().int().optional(),
145
+ /** Items per page (e.g. 100 for AWS, 30 for dev.to). */
146
+ pageSize: z.number().int().positive().optional(),
147
+ /** Query parameter name for the page-size value. Defaults to `pageSize` when present. */
148
+ pageSizeParam: z.string().min(1).optional(),
149
+ /** JSONPath-lite to the next-cursor / next-token value in the response body. */
150
+ nextCursorPath: z.string().min(1).optional(),
151
+ /** JSONPath-lite to the total-count value in the response body (backfill-mode early-stop hint). */
152
+ totalPath: z.string().min(1).optional(),
153
+ /** Hard cap on pages traversed. Default 20 (normal mode); `--max-pages` overrides in backfill. */
154
+ maxPages: z.number().int().positive().default(20),
155
+ });
156
+ /**
157
+ * Selector ruleset for `kind: json-api` sources (ADR-0012 §D2).
158
+ *
159
+ * Every selector is a JSONPath-lite expression (`src/core/feeds/_jsonpath.ts`).
160
+ *
161
+ * Every field is optional. When omitted the adapter falls back to a default
162
+ * selector chain per field (#174 / ADR-0012 §D2 defaults). For "simple"
163
+ * page-based APIs (dev.to, JSON Feed-shaped) the recipe can therefore omit
164
+ * `jsonSelectors` entirely (or use just `{}`) and rely on:
165
+ *
166
+ * items — `$.items[*] || $.data[*] || $.results[*] || $.posts[*] || $.entries[*] || $[*]`
167
+ * title — `$.title || $.name || $.headline`
168
+ * link — `$.url || $.link || $.permalink || $.html_url`
169
+ * publishedAt — `$.publishedAt || $.published_at || $.date || $.created_at || $.pubDate`
170
+ * summary — `$.summary || $.description || $.excerpt || $.body`
171
+ *
172
+ * - `publisherId` has no fallback chain (stable id derivation falls through
173
+ * to `link` URL by default; see `derive-id.ts`).
174
+ * - `body` / `tags` have no fallback chain (rarely needed for normalization).
175
+ * - `linkBase` resolves relative `link` values against an explicit base URL
176
+ * (defaults to `source.url`). See field-level docstring for details (#204).
177
+ *
178
+ * Note that selectors are evaluated against each item element (already
179
+ * dereferenced via `items`), so paths inside this schema commonly use `$` as
180
+ * the per-item root (e.g. `$.title`, `$.created_at`).
181
+ */
182
+ export const SourceJsonApiSelectorsSchema = z.object({
183
+ items: z.string().min(1).optional(),
184
+ title: z.string().min(1).optional(),
185
+ link: z.string().min(1).optional(),
186
+ publisherId: z.string().min(1).optional(),
187
+ summary: z.string().min(1).optional(),
188
+ publishedAt: z.string().min(1).optional(),
189
+ body: z.string().min(1).optional(),
190
+ tags: z.string().min(1).optional(),
191
+ /**
192
+ * Base URL used to resolve relative `link` values returned by the API
193
+ * (#204). Many APIs (e.g. AWS What's New) return `headlineUrl` as a path
194
+ * like `/about-aws/whats-new/.../` instead of a full URL, which causes
195
+ * every item to be silently dropped at `ItemSchema` validation. When
196
+ * `linkBase` is set, the adapter resolves relative `link` values against
197
+ * it (`new URL(raw, linkBase)`); when omitted, `source.url` is used as
198
+ * the base, mirroring how the html adapter resolves `<a href="/...">`.
199
+ * Absolute links pass through untouched in either case.
200
+ *
201
+ * Must be a fully-qualified http(s) URL — invalid bases would silently
202
+ * mis-resolve, so we fail-fast at schema parse time.
203
+ */
204
+ linkBase: z.string().url().optional(),
205
+ });
96
206
  /**
97
207
  * Validate `Source.url` per kind.
98
208
  *
@@ -137,6 +247,13 @@ export const SourceSchema = z
137
247
  // existing source YAMLs (and `kind: html` ones) parse unchanged; the
138
248
  // adapter applies defaults when the field is omitted entirely.
139
249
  js: SourceJsOptionsSchema.optional(),
250
+ // `http` / `pagination` / `jsonSelectors` are consulted only by the
251
+ // `json-api` adapter (ADR-0012). Marked optional so existing source YAMLs
252
+ // and other kinds parse unchanged. The `jsonSelectors` name disambiguates
253
+ // from the css-selector `selectors` field that html / html-js use.
254
+ http: SourceHttpOptionsSchema.optional(),
255
+ pagination: SourcePaginationSchema.optional(),
256
+ jsonSelectors: SourceJsonApiSelectorsSchema.optional(),
140
257
  // `trustLevel` defaults to `"untrusted"` so existing source YAMLs (which
141
258
  // omit the field entirely) keep their current treatment. Per ADR-0009 M4
142
259
  // this is schema-only; policy branches that read `trustLevel` arrive in a
@@ -158,5 +275,18 @@ export const SourceSchema = z
158
275
  message: `selectors is required when kind is '${value.kind}'`,
159
276
  });
160
277
  }
278
+ if (value.kind === "json-api") {
279
+ // `jsonSelectors` is now optional — when omitted the adapter relies on
280
+ // its default selector chain (ADR-0012 §D2 / #174). Most "simple"
281
+ // page-based APIs work with just `pagination` set; complex shapes
282
+ // (AWS What's New, nested fields) still need explicit selectors.
283
+ if (value.pagination === undefined) {
284
+ ctx.addIssue({
285
+ code: "custom",
286
+ path: ["pagination"],
287
+ message: "pagination is required when kind is 'json-api'",
288
+ });
289
+ }
290
+ }
161
291
  });
162
292
  //# sourceMappingURL=source.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/schemas/source.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/schemas/source.ts"],"names":[],"mappings":"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"}
@@ -48,22 +48,50 @@ radar init --with-actions # .github/workflows/watch.yaml を生成
48
48
  radar init --force # 既存ファイルを上書き
49
49
 
50
50
  # 監視対象の管理
51
- radar source add <id> --kind <rss|html|html-js|github-releases|npm-registry> --url <url> [options]
51
+ radar source add <id> --kind <rss|html|html-js|github-releases|npm-registry|json-feed|json-api> --url <url> [options]
52
52
  radar source list
53
+ radar source recipes # バンドル recipe を一覧表示 (ADR-0012)
54
+ radar source add <id> --recipe <name> [--keywords ... --tags ... --name ...] # recipe ベースで 1 行追加
53
55
  radar source test <id> [--limit N] [--show-content] # state/items を書き換えず取得 + フィルタを試す
54
56
  radar source remove <id>
55
57
 
58
+ # JSON API recipe を pagination 付きで追加(ADR-0012)
59
+ radar source add aws-whats-new --kind json-api \
60
+ --url "https://aws.amazon.com/api/dirs/items/search?item.directoryId=whats-new&size=100&page=0" \
61
+ --keywords "Bedrock,Claude" \
62
+ --pagination-strategy page --page-size 100 --max-pages 200
63
+
64
+ # 同じことを bundled recipe で 1 行で
65
+ radar source add aws-watch --recipe aws-whats-new --keywords "Bedrock,Claude"
66
+
67
+ # JSON Feed (1.0 / 1.1) は URL のみで動く zero-config
68
+ radar source add example-microblog --kind json-feed \
69
+ --url https://example.micro.blog/feed.json \
70
+ --keywords "release"
71
+
56
72
  # 監視実行 (新着検出 → items/*.yaml に detected で書く)
57
73
  radar watch run
58
74
 
75
+ # 過去全履歴の一括取り込み (kind: json-api / github-releases / npm-registry)
76
+ radar watch run --source aws-whats-new --backfill --max-pages 200
77
+
59
78
  # 検出済み item に対する操作
60
- radar research <item-id> --agent <agent> # 調査レポートを生成 (status: detected -> researched)
79
+ radar research <item-id> --agent <agent> [--verbose] # 調査レポートを生成 (status: detected -> researched)。--verbose で agent stdout を直接見る (ADR-0015)
61
80
  radar research --digest <item-id> <item-id> ... [--agent <agent>] # 複数 item を 1 digest にまとめる (ADR-0011)
81
+ radar research --batch [--max-items N] [--filter-tags <list>] [--agent <agent>] # detected を一括 research (ADR-0014 D3a、--max-items 既定 10)
62
82
  radar review <research-id> --agent <agent> # 既存レポートをレビュー (status: researched -> reviewed)
63
83
  radar update <research-id> --agent <agent> # v+1 を生成 (item status は変えない)
64
84
  radar dismiss <item-id> # LLM 不要、item を dismissed に
85
+
86
+ # GitHub Actions workflow の後追い生成 (ADR-0014)
87
+ radar workflow generate watch [--cron "<expr>"] [--agent <agent>] [--output <path>]
88
+ radar workflow generate combined [--watch-cron "<expr>"] [--max-items N] [--filter-tags <list>] [--agent <agent>] [--output <path>]
65
89
  ```
66
90
 
91
+ > **自動 research のコスト管理 (重要)**: `radar workflow generate combined` は watch → 自動 research を連鎖する workflow を生成し、`--max-items N` (既定 10) のハードキャップを YAML literal + CLI default の **二重防御**で焼き込む (ADR-0014 D3a)。`--max-items 100` のように大きい値を渡す前に必ず agent provider の billing alert を設定すること。暴走に気付いたら GitHub UI から workflow を `Disable workflow` で即停止する。詳細は `docs/user-guide.md` の「[`radar workflow generate`](https://github.com/ozzy-labs/feedradar/blob/main/docs/user-guide.md#radar-workflow-generate)」を参照。
92
+ >
93
+ > **進捗表示 (ADR-0015)**: `research` / `review` / `update` / `watch run --backfill` / html-js fetch / `source test` は stderr に phase markers + spinner + 副次メトリクス (`stdout` / `output` / `page x/N`) を出力する。`--verbose` で agent stdout を pass-through(デバッグ・「フリーズに見える」時の第一手)、`--quiet` または `RADAR_NO_PROGRESS=1` で完全に黙らせる。詳細は `docs/user-guide.md` の「[進捗表示 / verbose / quiet](https://github.com/ozzy-labs/feedradar/blob/main/docs/user-guide.md#進捗表示--verbose--quiet)」を参照。
94
+
67
95
  `<agent>` の値: `claude-code` / `codex-cli` / `gemini-cli` / `copilot`
68
96
 
69
97
  ## 利用可能な slash commands (4 agent 共通)
@@ -145,7 +173,7 @@ agent の選択は CLI が強制せず、ユーザー判断です。
145
173
 
146
174
  ## セキュリティ警告 (untrusted external content)
147
175
 
148
- `radar` が fetch する外部 feed (RSS / HTML / HTML (JS rendered, `kind: html-js`) / GitHub Releases / npm registry) のコンテンツは **untrusted** として扱われます ([ADR-0009](https://github.com/ozzy-labs/feedradar/blob/main/docs/adr/0009-untrusted-external-content-handling.md))。攻撃者が feed 内容に prompt injection を仕込む可能性があるため:
176
+ `radar` が fetch する外部 feed (RSS / HTML / HTML (JS rendered, `kind: html-js`) / GitHub Releases / npm registry / JSON Feed / JSON API) のコンテンツは **untrusted** として扱われます ([ADR-0009](https://github.com/ozzy-labs/feedradar/blob/main/docs/adr/0009-untrusted-external-content-handling.md))。攻撃者が feed 内容に prompt injection を仕込む可能性があるため:
149
177
 
150
178
  - agent に渡すコンテンツは boundary marker で囲まれ、procedure 本体と分離される
151
179
  - `sources/<id>.yaml` の `trustLevel` で `"trusted" | "untrusted"` を per-source で指定可能 (既定 `"untrusted"`)
@@ -24,7 +24,7 @@ radar watch run
24
24
  # (c) あとは AI エージェントに頼む (次セクション)
25
25
  ```
26
26
 
27
- `source add` と `watch run` は scheduler 連携を想定して CLI のままです。`--with-actions` / `--with-routines` を付けて init すれば、GitHub Actions / Claude Routines で定期実行する雛形が出ます。
27
+ `source add` と `watch run` は scheduler 連携を想定して CLI のままです。`--with-actions` / `--with-routines` を付けて init すれば、GitHub Actions / Claude Routines で定期実行する雛形が出ます。後から workflow を追加 / cadence 切替 / watch + 自動 research の連鎖が必要になったら `radar workflow generate watch | combined` で後追い生成できます ([ADR-0014](https://github.com/ozzy-labs/feedradar/blob/main/docs/adr/0014-workflow-generate-and-auto-research-safety.md))。
28
28
 
29
29
  ## 主要操作: エージェントに頼む
30
30
 
@@ -111,19 +111,34 @@ slash で直接呼ぶなら:
111
111
  エージェントを起動しない自動化文脈では CLI を直接呼びます。`radar <subcommand> --help` で全コマンドのヘルプが出ます。
112
112
 
113
113
  ```bash
114
- radar source add <id> --kind <rss|html|html-js|github-releases|npm-registry> --url <url> [options]
114
+ radar source add <id> --kind <rss|html|html-js|github-releases|npm-registry|json-feed|json-api> --url <url> [options]
115
+ radar source add <id> --recipe <name> [--keywords ... --tags ... --name ...] # バンドル recipe で 1 行追加 (ADR-0012)
115
116
  radar source list
117
+ radar source recipes # バンドル recipe を一覧表示
116
118
  radar source test <id> [--limit N] [--show-content]
117
119
  radar source remove <id>
118
- radar watch run [--source <id>] [--bootstrap]
119
- radar research <item-id> --agent <agent>
120
+ radar watch run [--source <id>] [--bootstrap | --backfill [--max-pages N]] [-v|--verbose | -q|--quiet]
121
+ radar research <item-id> --agent <agent> [--verbose | --quiet] # 進捗表示・stdout pass-through は --verbose で有効化 (ADR-0015)
120
122
  radar research --digest <item-id> <item-id> ... [--agent <agent>] # 複数 item を 1 digest にまとめる (ADR-0011)
121
- radar review <research-id> --agent <agent>
122
- radar update <research-id> --agent <agent>
123
+ radar review <research-id> --agent <agent> [--verbose | --quiet]
124
+ radar update <research-id> --agent <agent> [--verbose | --quiet]
123
125
  radar dismiss <item-id>
126
+ radar research --batch [--max-items N] [--filter-tags <list>] [--agent <agent>] [--verbose | --quiet] # detected を一括 research (ADR-0014)
127
+ radar workflow generate watch [--cron "<expr>"] [--agent <agent>] [--output <path>] # GitHub Actions watch 雛形を後追い生成 (ADR-0014)
128
+ radar workflow generate combined [--watch-cron "<expr>"] [--max-items N] [--filter-tags <list>] [--agent <agent>] [--output <path>] # watch + 自動 research を --max-items ハードキャップ付きで生成 (ADR-0014)
124
129
  ```
125
130
 
126
- 定期実行の雛形 (GitHub Actions / Claude Routines) `radar init --with-actions` / `--with-routines` で生成できます。
131
+ JSON API は recipe ベースで、`kind: json-api` を選んで `pagination` を YAML に書く([ADR-0012](https://github.com/ozzy-labs/feedradar/blob/main/docs/adr/0012-json-api-adapter-and-recipe-strategy.md))。JSON Feed 1.0 / 1.1 標準に準拠したサイトは URL だけで動く zero-config kind (`kind: json-feed`)。過去の全件取り込みは `radar watch run --backfill` を使う (kind: json-api / github-releases / npm-registry 対応)。
132
+
133
+ 長時間実行コマンド (`research` / `review` / `update` / `watch run --backfill` / html-js fetch / `source test`) は stderr に phase markers + spinner + 副次メトリクス (`stdout` / `output` / `page x/N`) を表示します([ADR-0015](https://github.com/ozzy-labs/feedradar/blob/main/docs/adr/0015-progress-reporting-ux.md))。挙動切替は env > flag > TTY auto-detect の優先順:
134
+
135
+ - `--verbose`(または `-v`): agent CLI / Playwright の stdout/stderr を pass-through。デバッグや「フリーズに見える」ときの第一手
136
+ - `--quiet`(または `-q`): reporter を完全に黙らせ、CLI の従来 1 行ログだけ残す
137
+ - `RADAR_NO_PROGRESS=1`(env): 上記より強い escape hatch。CI script で flag を消さずに reporter だけ off にしたいケース向け
138
+
139
+ 詳細・トラブルシュート(`Agent running [mm:ss]` で動いていないように見える時の対処等)は [docs/user-guide.md → 進捗表示 / verbose / quiet](https://github.com/ozzy-labs/feedradar/blob/main/docs/user-guide.md#進捗表示--verbose--quiet) を参照。
140
+
141
+ 定期実行の雛形 (GitHub Actions / Claude Routines) は `radar init --with-actions` / `--with-routines` で初回 bootstrap として生成できます。後追いで cadence 切替 / 複数 workflow 共存 / `combined` (watch + 自動 research) を追加したい場合は `radar workflow generate <type>` ([ADR-0014](https://github.com/ozzy-labs/feedradar/blob/main/docs/adr/0014-workflow-generate-and-auto-research-safety.md)) を使います。`combined` は `--max-items` ハードキャップを YAML literal + CLI default の二重防御で焼き込むため、暴走 feed (publisher 側 bug / `--backfill` 事故) による LLM cost 爆発を設計レベルで遮断します。
127
142
 
128
143
  ## このディレクトリのレイアウト
129
144
 
@@ -154,7 +169,7 @@ radar dismiss <item-id>
154
169
 
155
170
  ## セキュリティ警告
156
171
 
157
- FeedRadar が fetch する外部 feed (RSS / HTML / HTML (JS rendered, `kind: html-js`) / GitHub Releases / npm registry) は **untrusted** として扱われます ([ADR-0009](https://github.com/ozzy-labs/feedradar/blob/main/docs/adr/0009-untrusted-external-content-handling.md))。攻撃者が feed 内容に prompt injection を仕込む可能性があるため:
172
+ FeedRadar が fetch する外部 feed (RSS / HTML / HTML (JS rendered, `kind: html-js`) / GitHub Releases / npm registry / JSON Feed / JSON API) は **untrusted** として扱われます ([ADR-0009](https://github.com/ozzy-labs/feedradar/blob/main/docs/adr/0009-untrusted-external-content-handling.md))。攻撃者が feed 内容に prompt injection を仕込む可能性があるため:
158
173
 
159
174
  - 信頼できる公式 source のみ登録するのが第一の防御線
160
175
  - `sources/<id>.yaml` の `trustLevel: trusted` で個別 opt-in 可 (既定 `untrusted`)
@@ -0,0 +1,110 @@
1
+ # `radar workflow generate combined` template (ADR-0014 D2 / D3 / D4 / D5).
2
+ #
3
+ # Chains `radar watch run` -> "skip if no new items" guard -> `radar research
4
+ # --batch` -> `git commit/push --rebase` retry inside a single job so the
5
+ # detection-to-research delay collapses to one cron tick instead of two
6
+ # stacked workflows.
7
+ #
8
+ # Placeholders rendered by `src/cli/workflow/generate-combined.ts`:
9
+ # {{cron}} — schedule cron expression (default "0 0 * * *")
10
+ # {{maxItems}} — `--max-items` hard cap (ADR-0014 D3a; default 10)
11
+ # {{filterTags}} — `--filter-tags` arg as a single CLI literal (empty when
12
+ # filtering is off so the line collapses to bare `--batch`)
13
+ # {{agent}} — agent id literal (claude-code|codex-cli|gemini-cli|copilot)
14
+ # {{secretsBlock}} — agent-specific `env:` body (no shared default; the
15
+ # CLI generator selects one of four prebuilt fragments,
16
+ # never injecting OAuth tokens per ADR-0014 D5)
17
+ #
18
+ # Hard-cap rationale: this YAML embeds `--max-items {{maxItems}}` as a literal
19
+ # so a workflow audit shows the cap without needing to re-read CLI source.
20
+ # The CLI re-enforces the cap (`RESEARCH_BATCH_DEFAULT_MAX_ITEMS` in
21
+ # `src/cli/research.ts`) so even hand-edited YAML cannot blow it inside one
22
+ # invocation (ADR-0014 D3a 二重防御).
23
+
24
+ name: feedradar-combined
25
+
26
+ on:
27
+ schedule:
28
+ - cron: "{{cron}}"
29
+ workflow_dispatch: {}
30
+
31
+ permissions:
32
+ contents: write
33
+
34
+ concurrency:
35
+ # Type-scoped concurrency group: watch-only and combined workflows must not
36
+ # serialize each other (different cadence, different scope), so each type
37
+ # has its own `feedradar-<type>-${{ github.ref }}` group.
38
+ group: feedradar-combined-${{ github.ref }}
39
+ cancel-in-progress: false
40
+
41
+ jobs:
42
+ combined:
43
+ runs-on: ubuntu-latest
44
+ timeout-minutes: 30
45
+ steps:
46
+ - name: Checkout workspace
47
+ uses: actions/checkout@v4
48
+ with:
49
+ fetch-depth: 0
50
+ persist-credentials: true
51
+
52
+ - name: Set up Node.js
53
+ uses: actions/setup-node@v4
54
+ with:
55
+ node-version: "22.21"
56
+
57
+ - name: Install FeedRadar
58
+ run: npm install -g @ozzylabs/feedradar
59
+
60
+ - name: Run watch
61
+ env:
62
+ {{secretsBlock}}
63
+ run: radar watch run
64
+
65
+ - name: Skip research when no new items
66
+ id: detect_changes
67
+ # ADR-0014: skip the research step entirely when `watch run` produced
68
+ # no new items. Otherwise a runaway-detection cap would still burn a
69
+ # full `radar research --batch` invocation (template load, item walk)
70
+ # on a fresh-empty queue.
71
+ run: |
72
+ if [ -z "$(git status --porcelain items/)" ]; then
73
+ echo "no new items in items/; skipping research step"
74
+ echo "has_changes=false" >> "$GITHUB_OUTPUT"
75
+ else
76
+ echo "has_changes=true" >> "$GITHUB_OUTPUT"
77
+ fi
78
+
79
+ - name: Run research on detected items (capped at {{maxItems}}, agent={{agent}})
80
+ if: steps.detect_changes.outputs.has_changes == 'true'
81
+ env:
82
+ {{secretsBlock}}
83
+ # `--batch` walks items/ for status=detected, applies the filter-tags
84
+ # allow-list, and stops once `--max-items` reports are written. The CLI
85
+ # re-enforces the cap so a hand-edited YAML cannot exceed it.
86
+ run: radar research --batch --status detected --max-items {{maxItems}}{{filterTags}} --agent {{agent}}
87
+
88
+ - name: Commit and push with retry
89
+ if: steps.detect_changes.outputs.has_changes == 'true'
90
+ # ADR-0014 D4: three-attempt push with `git pull --rebase --autostash`
91
+ # between failures. Tuned for two concurrent feedradar workflows (e.g.
92
+ # watch-hourly + combined-weekly) racing on items/ / state/ / research/.
93
+ run: |
94
+ git config user.name "feedradar-bot"
95
+ git config user.email "feedradar-bot@users.noreply.github.com"
96
+ git add items/ state/ research/
97
+ if git diff --cached --quiet; then
98
+ echo "nothing staged; exiting cleanly"
99
+ exit 0
100
+ fi
101
+ git commit -m "chore(feedradar): combined watch + research $(date -u +%Y-%m-%d)"
102
+ for attempt in 1 2 3; do
103
+ if git push origin "${GITHUB_REF_NAME}"; then
104
+ exit 0
105
+ fi
106
+ echo "push failed (attempt ${attempt}/3), rebasing..."
107
+ git pull --rebase --autostash origin "${GITHUB_REF_NAME}"
108
+ done
109
+ echo "push failed after 3 attempts" >&2
110
+ exit 1
@@ -0,0 +1,103 @@
1
+ # GitHub Actions scaffold generated by `radar workflow generate watch`.
2
+ # Edit the cron schedule, sources, and commit message to match your workflow.
3
+ # Auth policy: API key only (ADR-0004 / ADR-0014). The Claude Code OAuth token
4
+ # is forbidden for unattended workflows per Anthropic's usage policy.
5
+ #
6
+ # This template is the placeholder-driven, post-init regeneration variant of
7
+ # `src/templates/workflows/watch.yaml`. The latter is emitted by
8
+ # `radar init --with-actions` for first-time workspace bootstrap and is
9
+ # preserved verbatim for backward compatibility (ADR-0014 D1). Differences:
10
+ #
11
+ # - Cron schedule, output path, and agent secret name are substituted by
12
+ # `generate-watch.ts` from CLI flags before the file is written.
13
+ # - `concurrency.group` is scoped to `feedradar-watch-` so multiple workflow
14
+ # types (watch / combined) can run side by side without cancelling each
15
+ # other; ADR-0014 D4 push-conflict mitigation pairs with the rebase retry
16
+ # below.
17
+ # - `Commit and push with retry` step has up to 3 `git pull --rebase`
18
+ # retries to recover from concurrent cron pushes (ADR-0014 D4).
19
+
20
+ name: feedradar-watch
21
+
22
+ on:
23
+ schedule:
24
+ - cron: "{{cron}}"
25
+ workflow_dispatch: {}
26
+
27
+ permissions:
28
+ # Required to commit detected items / state back to the workspace branch.
29
+ contents: write
30
+
31
+ concurrency:
32
+ # Per-type group so `watch` and `combined` workflows don't cancel each other.
33
+ # Same-type concurrent firings still serialize via this group.
34
+ group: feedradar-watch-${{ github.ref }}
35
+ cancel-in-progress: false
36
+
37
+ jobs:
38
+ watch:
39
+ runs-on: ubuntu-latest
40
+ timeout-minutes: 15
41
+ steps:
42
+ - name: Checkout workspace
43
+ uses: actions/checkout@v4
44
+ with:
45
+ # Need history so we can rebase on top of concurrent pushes.
46
+ fetch-depth: 0
47
+ persist-credentials: true
48
+
49
+ - name: Set up Node.js
50
+ uses: actions/setup-node@v4
51
+ with:
52
+ # Node 22.21+ (or 24.5+) is required so radar can auto-detect
53
+ # HTTPS_PROXY / HTTP_PROXY and respawn with --use-env-proxy.
54
+ node-version: "22.21"
55
+
56
+ - name: Install FeedRadar
57
+ # Pin to a release once you've decided on a version; this scaffold
58
+ # installs the latest published build.
59
+ run: npm install -g @ozzylabs/feedradar
60
+
61
+ - name: Run watch
62
+ env:
63
+ # Authenticate against the agent API per ADR-0004 / ADR-0014 D5.
64
+ # The secret name below follows the per-agent convention; see the
65
+ # post-generation stdout for the exact secret you must add.
66
+ {{agentEnvKey}}: ${{ secrets.{{agentEnvKey}} }}
67
+ # Raises GitHub REST API rate limit from 60 → 5000 req/h for the
68
+ # github-releases adapter (ADR-0002 / Phase 3).
69
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
70
+ run: radar watch run
71
+
72
+ - name: Commit and push with retry
73
+ # Persist updates to items/ and state/ so the next scheduled run can
74
+ # diff against the previous lastSeenIds. Routines / Actions both
75
+ # fresh-clone, so state must live in git.
76
+ #
77
+ # Push conflict mitigation (ADR-0014 D4): if another workflow (e.g.
78
+ # combined.yaml) pushed concurrently, `git push` fails with
79
+ # non-fast-forward. We retry up to 3 times, rebasing on each attempt;
80
+ # autostash keeps any unindexed bot-side changes safe across the
81
+ # rebase. 4+ attempts indicate a structural problem (branch
82
+ # protection, token failure, true merge conflict) so we fail fast
83
+ # instead of retrying further.
84
+ run: |
85
+ set -euo pipefail
86
+ git config user.name "github-actions[bot]"
87
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
88
+ if git diff --quiet items/ state/; then
89
+ echo "no changes detected; skipping commit"
90
+ exit 0
91
+ fi
92
+ git add items/ state/
93
+ git commit -m "chore(watch): detected items $(date -u +%Y-%m-%d)"
94
+ for attempt in 1 2 3; do
95
+ if git push origin "${GITHUB_REF_NAME}"; then
96
+ echo "push succeeded on attempt ${attempt}"
97
+ exit 0
98
+ fi
99
+ echo "push failed (attempt ${attempt}/3), rebasing..."
100
+ git pull --rebase --autostash origin "${GITHUB_REF_NAME}"
101
+ done
102
+ echo "push failed after 3 attempts" >&2
103
+ exit 1
@@ -36,7 +36,11 @@ jobs:
36
36
  - name: Set up Node.js
37
37
  uses: actions/setup-node@v4
38
38
  with:
39
- node-version: "22"
39
+ # Node 22.21+ (or 24.5+) is required so radar can auto-detect
40
+ # HTTPS_PROXY / HTTP_PROXY and respawn with --use-env-proxy.
41
+ # Older 22.x lacks the flag and `radar` runs without proxy
42
+ # support even when HTTPS_PROXY is set.
43
+ node-version: "22.21"
40
44
 
41
45
  - name: Install FeedRadar
42
46
  # Pin to a release once you've decided on a version; this scaffold
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ozzylabs/feedradar",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Multi-agent CLI that watches blogs and release feeds, then turns keyword hits into Markdown research reports",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -8,7 +8,6 @@
8
8
  },
9
9
  "files": [
10
10
  "dist",
11
- "dist/skills",
12
11
  "LICENSE",
13
12
  "README.md"
14
13
  ],
@@ -78,6 +77,6 @@
78
77
  ],
79
78
  "author": "ozzy-labs",
80
79
  "engines": {
81
- "node": ">=22"
80
+ "node": ">=22.21.0 || >=24.5.0"
82
81
  }
83
82
  }