yt-briefing 0.11.1 → 0.12.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.
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: yt
3
- description: Briefing from the YouTube channels you follow — the engine sweeps each channel, filters videos in two stages (title, then transcript+content), and lazily yields one video to rate per call. This skill is a thin loop that shows the summary and collects the rating (via AskUserQuestion), which writes durable signal straight into the channel profile. Summaries and the rating question use the language chosen at onboarding.
3
+ description: Briefing from the YouTube channels you follow — the engine sweeps each channel, filters videos in two stages (title, then transcript+content), and lazily yields one video to rate per call. This skill is a thin loop that shows the summary and collects the rating (via AskUserQuestion), which writes durable signal straight into the channel profile. A third option, Research, breaks the loop to dig into the current video's content with the user (full transcript + their question). Summaries and the rating question use the language chosen at onboarding.
4
4
  ---
5
5
 
6
6
  ## How it works
7
7
 
8
- `src/yt-sweep.ts` is **the whole engine**: channel sweep, filters (title filter, then content filter on the transcript via the LLM API), and skip handling — all inside, lazy. The only state it does **not** write is the rating itself — that's `yt-rating.ts` in step D. This skill **does not run filters, read profiles, or format summaries** — it runs the script, pastes the summary, collects the rating.
8
+ `src/yt-sweep.ts` is **the whole engine**: channel sweep, filters (title filter, then content filter on the transcript via the LLM API), and skip handling — all inside, lazy. The only state it does **not** write is the rating itself — that's `yt-rating.ts` in step D. This skill **does not run filters, read profiles, or format summaries** — it runs the script, pastes the summary, collects the rating. The one exception is **Research mode** (below): an explicit user pick that ends the loop and opens the current video's content for discussion.
9
9
 
10
10
  `data/state.md` is the only persistent cursor. Session state — queue, pending, prefetch, background fill — lives in `data/.cache/` (rebuilt each run, never important to keep). Internals — lazy queue build, filters, summary format, LLM model, transcript fetching, prefetch, proxy — are in `README.md`, not here. No manual pre-flight: the engine self-invalidates a stale queue (new day or `--reset`).
11
11
 
@@ -34,22 +34,33 @@ while true:
34
34
  - **A.** Take `out.summary` (markdown) and `out.pending` (metadata).
35
35
  - **B.** In the same turn, as **your chat text** (NOT command output — the UI does not show it), paste `summary` **verbatim**: no paraphrase, no shortening, no comment, no "see above". The user must see it before the popup. _(If the user says "I don't see the summary" — you skipped B.)_
36
36
  - **C.** In the same message call `AskUserQuestion` — **1 call, 1 question** (everything in one step), phrased in `output_lang`:
37
- - The question (e.g. "Rating?") with two options whose descriptions explain: **OK** = neutral (no effect on the filter), **Weak** = worthless (teach the filter to skip such titles). The digits never appear in the popup — internally map to `--rating`: **OK → 1, Weak → 0**. There is **no positive rating** — keeping the channel is the implicit positive; you only down-rate noise (`0`) or steer with a comment.
38
- - **Other** is the comment / stop channel (no second question): the user types free text. If it equals `stop` (case-insensitive, trimmed) — or the popup is dismissed (✕) — **end the loop**. Otherwise it is a **comment**: **distill** the user's raw text into a clean, generalizable rule, and infer the rating — clearly negative → `0`, otherwise → `1`.
37
+ - The question (e.g. "Rating?") with three options whose descriptions explain: **OK** = neutral (no effect on the filter), **Weak** = worthless (teach the filter to skip such titles), **Research** = break the loop and dig into this video's content together. The digits never appear in the popup — internally map to `--rating`: **OK → 1, Weak → 0**; Research maps to no digit, it exits the loop (see Research mode). There is **no positive rating** — keeping the channel is the implicit positive; you only down-rate noise (`0`) or steer with a comment.
38
+ - **Other** is the comment / stop / research channel (no second question): the user types free text. If it equals `stop` (case-insensitive, trimmed) — or the popup is dismissed (✕) — **end the loop**. If it **starts with `?`**, the text after the `?` is a **research question** → Research mode. Otherwise it is a **comment**: **distill** the user's raw text into a clean, generalizable rule, and infer the rating — clearly negative → `0`, otherwise → `1`.
39
39
  - **D.** Act on the answer:
40
40
  - `stop` / dismissed → **end the loop** (state already on disk).
41
41
  - A rating option → `bun run src/yt-rating.ts --rating <1|0>`.
42
- - A comment (Other, not `stop`) → `bun run src/yt-rating.ts --rating <inferred 1|0> --comment "<distilled rule>"`.
42
+ - A comment (Other, not `stop`, not `?…`) → `bun run src/yt-rating.ts --rating <inferred 1|0> --comment "<distilled rule>"`.
43
+ - **Research** (the option, or a `?…` text) → **break the loop** and switch to **Research mode** below. Skip step E — no more sweep calls this session.
43
44
 
44
45
  In every non-stop case **pass only the rating (+ comment)**; the script reads channel/id/title/type from `data/.cache/pending.json`. The write is **immediate and durable — no consolidation**: `rating=0` appends to `## Skip titles` (title filter learns to skip such titles from the next run) and a comment appends the rule to `## Notes` (seen by both filters). A neutral `1` writes nothing — it only bumps the state cursor.
45
46
  - **E.** Re-run `bun run src/yt-sweep.ts` **bare** (no `--reset` — resumes the same queue; only the loop's first call uses `--reset`). Its JSON becomes the next iteration's `out` — back to the top of the loop.
46
47
 
48
+ ## Research mode (break the loop and dig in)
49
+
50
+ The "don't shelve it" path: instead of the briefing landing on a to-do list, the user pulls it apart with you right now — e.g. the channel announces a new tool and the question is whether it beats what their project uses today. Entry: the **Research** option, or an Other text starting with `?`.
51
+
52
+ 1. **Commit first:** `bun run src/yt-rating.ts --rating 1` — engaging with a video is at least neutral, and the bump keeps it from reappearing on the next run. The rating loop is over: no step E, no further sweep calls.
53
+ 2. **Get the question.** A `?…` text (or any free text attached to the Research selection) IS the question. If Research was picked bare, ask in `output_lang` what they want to dig into.
54
+ 3. **Pull the full transcript** — the summary is too lossy to research from: `bun run src/yt-transcript.ts <videoId> --lang auto`, videoId from `out.pending` (or `data/.cache/pending.json`). The transcript arrives as the tool result — work from it there, never paste it into chat. Non-zero exit (`1` no subtitles / `2` IP-blocked / `3` tooling, reason on stderr) → tell the user and work from the summary instead.
55
+ 4. **Work the question with the user, grounded.** The transcript is the source for what the video *claims*; keep "the video claims X" separate from what you verify yourself. Use whatever tools the question needs — read the user's project when they ask "would this fit project xyz", search the web for docs / changelogs / pricing. It is a conversation, not a one-shot report: answer, then iterate until the user is done.
56
+ 5. **Closing.** `data/.cache/pending.json` is still on disk, so a verdict can still be recorded: turned out to be hype → `bun run src/yt-rating.ts --rating 0`; a durable channel preference surfaced → `--rating 1 --comment "<distilled rule>"` (the re-bump is a no-op). Mention that `/yt` resumes the queue where it left off — re-enter the rating loop (re-run the engine **bare**) only if the user asks.
57
+
47
58
  ## No consolidation
48
59
 
49
60
  There is no post-loop step. Each rating is **durable immediately**: `yt-rating.ts` writes `rating=0` straight to `## Skip titles` and a comment straight to `## Notes` (FIFO-capped, de-duplicated). `rating=1` only bumps the cursor. The title filter reads those sections live, so the signal takes effect on the very next sweep — nothing to flush, batch, or trigger.
50
61
 
51
62
  ## Rules
52
63
 
53
- - **Language:** question text, option descriptions, and loop messages follow `output_lang`; the two rating **labels** are `OK` / `Weak`. Summaries are written in `output_lang` by the content-filter prompt in the engine — not here.
54
- - **Transcripts:** never paste a raw transcript into chat; the summary is the artifact.
64
+ - **Language:** question text, option descriptions, and loop messages follow `output_lang`; the three option **labels** are `OK` / `Weak` / `Research`. Summaries are written in `output_lang` by the content-filter prompt in the engine — not here. Research mode converses in `output_lang` unless the user switches.
65
+ - **Transcripts:** never paste a raw transcript into chat; the summary is the artifact. In research mode, quote only the short passages you need.
55
66
  - **Resuming:** the skill can be re-run any time — `data/state.md` is the source of truth, so a re-run always skips what's already rated. A queue from a previous day self-invalidates; the loop's first call passes `--reset` to also force a **same-day** rebuild, catching videos published since that morning's queue.
package/README.md CHANGED
@@ -118,6 +118,16 @@ it to go deeper, lower it for a quicker pass:
118
118
  /yt-search @betterstack which terminal --top 5
119
119
  ```
120
120
 
121
+ ## Don't shelve it — research it
122
+
123
+ Tech channels announce something new every week, and the usual fate is "looks interesting" →
124
+ to-do list → never. So the rating popup has a third option next to OK/Weak: **Research**. Pick
125
+ it — or type `? your question` straight into the comment box — and the loop ends there: the
126
+ agent pulls that video's full transcript and works your question with you. Against your own
127
+ codebase if you ask "would this fit my project", against the web if the claims need checking —
128
+ a quick feedback loop instead of a shelf. The video is marked as seen, and the next `/yt`
129
+ resumes the queue right where you broke off.
130
+
121
131
  ## Run it
122
132
 
123
133
  Open your project in Claude Code or Cursor and run `/yt`. If it's not listed, start a fresh
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yt-briefing",
3
- "version": "0.11.1",
3
+ "version": "0.12.0",
4
4
  "description": "A self-learning YouTube briefing engine: it sweeps the channels you follow, filters noise in two stages (title, then transcript), summarizes the rest in your language, and adapts to your ratings — one video at a time.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -50,9 +50,10 @@
50
50
  "dotenv": "^16.6.1"
51
51
  },
52
52
  "devDependencies": {
53
+ "@socketsecurity/bun-security-scanner": "^1.1.2",
54
+ "@types/bun": "^1.3.14",
53
55
  "@types/node": "^22",
54
56
  "typescript": "^5.7",
55
- "@types/bun": "latest",
56
57
  "vitest": "^3"
57
58
  }
58
59
  }