wip: estado de trabajo pendiente antes de la vista grid (suite 230 verde)

This commit is contained in:
urieljareth
2026-08-22 19:37:23 -06:00
parent 4f5a68b572
commit 8a59b39c98
103 changed files with 70954 additions and 1825 deletions
+44 -1
View File
@@ -1 +1,44 @@
{"0": "Webapp Frontend (JS)", "1": "Transcript Extraction & Parsing", "2": "Config & Discovery Pipeline", "3": "Store & Export Layer", "4": "CLI Command Layer", "5": "Platform Design & Proposals", "6": "Segments Search & Backfill", "7": "Store Platform Tests", "8": "Content Analysis", "9": "README & Config Docs", "10": "Server Start Script", "11": "Package Manifest", "12": "Server Stop Script", "13": "Webapp Package Init"}
{
"0": "Webapp Frontend (JS)",
"1": "Transcript Extraction & Parsing",
"2": "Config & Discovery Pipeline",
"3": "Store & Export Layer",
"4": "CLI Command Layer",
"5": "Platform Design & Proposals",
"6": "Segments Search & Backfill",
"7": "Store Platform Tests",
"8": "Content Analysis",
"9": "README & Config Docs",
"10": "Server Start Script",
"11": "Package Manifest",
"12": "Server Stop Script",
"13": "Webapp Package Init",
"14": "test_extract.py",
"15": "Auditoría · Cómo la extensión obtiene la transcripción / información de vídeos de YouTube",
"16": "api",
"17": "pipeline.py",
"18": "test_blocked_videos.py",
"19": "config.py",
"20": "setView",
"21": "Discovery-Only Scrape Design",
"22": "renderDashboardCharts",
"23": "Global Constraints",
"24": "Config",
"25": "init",
"26": "render.py",
"27": "loadChannels",
"28": "jobs.py",
"29": "Segment",
"30": "cookies.py",
"31": "discover.py",
"32": "export.py",
"33": "pipeline.py",
"34": "_channel_targets",
"35": "test_features.py",
"36": "VideoRow",
"37": "test_since_filter.py",
"38": ".reset_videos",
"39": "._connect",
"40": "re_render_cmd",
"41": "handleFiles"
}
+1 -1
View File
@@ -1 +1 @@
D:\yt-channel-scraper
.
@@ -0,0 +1,27 @@
{
"0": "Webapp Frontend (JS)",
"1": "Transcript Extraction & Parsing",
"2": "Config & Discovery Pipeline",
"3": "Store & Export Layer",
"4": "CLI Command Layer",
"5": "Platform Design & Proposals",
"6": "Segments Search & Backfill",
"7": "Store Platform Tests",
"8": "Content Analysis",
"9": "README & Config Docs",
"10": "Server Start Script",
"11": "Package Manifest",
"12": "Server Stop Script",
"13": "Webapp Package Init",
"14": "test_extract.py",
"15": "Auditoría · Cómo la extensión obtiene la transcripción / información de vídeos de YouTube",
"16": "api",
"17": "pipeline.py",
"18": "render.py",
"19": "config.py",
"20": "setView",
"21": "Discovery-Only Scrape Design",
"22": "renderDashboardCharts",
"23": "Global Constraints",
"24": "loadJobs"
}
+182
View File
@@ -0,0 +1,182 @@
# Graph Report - yt-channel-scraper (2026-07-31)
## Corpus Check
- 45 files · ~46,603 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 612 nodes · 1392 edges · 25 communities (22 shown, 3 thin omitted)
- Extraction: 91% EXTRACTED · 9% INFERRED · 0% AMBIGUOUS · INFERRED: 129 edges (avg confidence: 0.78)
- Token cost: 0 input · 0 output
## Graph Freshness
- Built from commit: `06497299`
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
- Run `graphify update .` after code changes (no API cost).
## Community Hubs (Navigation)
- Webapp Frontend (JS)
- Transcript Extraction & Parsing
- Config & Discovery Pipeline
- Store & Export Layer
- CLI Command Layer
- Platform Design & Proposals
- Segments Search & Backfill
- Store Platform Tests
- Content Analysis
- README & Config Docs
- Server Start Script
- Package Manifest
- Server Stop Script
- test_extract.py
- Auditoría · Cómo la extensión obtiene la transcripción / información de vídeos de YouTube
- api
- pipeline.py
- render.py
- config.py
- setView
- Discovery-Only Scrape Design
- renderDashboardCharts
- Global Constraints
- loadJobs
## God Nodes (most connected - your core abstractions)
1. `Store` - 96 edges
2. `api()` - 36 edges
3. `toast()` - 36 edges
4. `Config` - 34 edges
5. `Segment` - 32 edges
6. `JobManager` - 26 edges
7. `VideoRef` - 25 edges
8. `discover_incremental()` - 21 edges
9. `process_video()` - 19 edges
10. `subscribeJob()` - 18 edges
## Surprising Connections (you probably didn't know these)
- `test_config_languages_defaults_to_dict()` --calls--> `Config` [INFERRED]
tests/test_extract.py → src/yt_scraper/config.py
- `test_config_prefer_manual_defaults_true()` --calls--> `Config` [INFERRED]
tests/test_extract.py → src/yt_scraper/config.py
- `test_dashboard_aggregates()` --calls--> `Segment` [INFERRED]
tests/test_store_platform.py → src/yt_scraper/parse.py
- `test_store_and_search_segments()` --calls--> `Segment` [INFERRED]
tests/test_store_platform.py → src/yt_scraper/parse.py
- `test_store_segments_overwrites()` --calls--> `Segment` [INFERRED]
tests/test_store_platform.py → src/yt_scraper/parse.py
## Import Cycles
- None detected.
## Hyperedges (group relationships)
- **Workstream B webapp stack (FastAPI + Alpine SPA + subagent)** — opencode_agent_webapp_builder, opencode_goals_webapp_build, src_yt_scraper_webapp_static_index, docs_superpowers_specs_2026_07_26_platform_design_dark_command_center, docs_superpowers_specs_2026_07_26_platform_design_sse_job_runner [EXTRACTED 0.95]
- **FTS5 transcript search flow (proposal -> spec -> SPA view)** — opportunities_search_fts5, docs_superpowers_specs_2026_07_26_platform_design_transcript_fts5, src_yt_scraper_webapp_static_index [INFERRED 0.85]
- **Cookie auth chain (vault -> resolve_active_path -> scrape job)** — docs_superpowers_specs_2026_07_26_platform_design_cookie_vault_ux, docs_superpowers_specs_2026_07_26_platform_design_sse_job_runner, docs_superpowers_specs_2026_07_26_platform_design_cookies_bug_fix, src_yt_scraper_webapp_static_index [INFERRED 0.85]
## Communities (25 total, 3 thin omitted)
### Community 0 - "Webapp Frontend (JS)"
Cohesion: 0.07
Nodes (20): _armAutoHide(), closeClip(), closeJobWidget(), closeSidebar(), closeStats(), _disarmAutoHide(), downloadClipTxt(), downloadFile() (+12 more)
### Community 1 - "Transcript Extraction & Parsing"
Cohesion: 0.16
Nodes (17): merge_adjacent(), parse_auto_dump(), parse_json3(), parse_vtt(), Segment, _vtt_ts_to_seconds(), store(), test_export_json_csv() (+9 more)
### Community 2 - "Config & Discovery Pipeline"
Cohesion: 0.08
Nodes (34): Config, Path, deep_channel_avatar(), Robust avatar recovery via non-flat yt-dlp call on the channel root URL., _extract_handle(), _keep_ref(), Same shorts/live rules the store was populated under — see jobs._keep_ref., Discover + process pending videos for a channel, optionally on an interval. (+26 more)
### Community 3 - "Store & Export Layer"
Cohesion: 0.06
Nodes (43): Connection, Cursor, Environment, Row, auto_import_dir(), cookies_dir(), delete(), import_file() (+35 more)
### Community 4 - "CLI Command Layer"
Cohesion: 0.08
Nodes (37): analyze_cmd(), _apply_filters(), audio_cmd(), _channel_targets(), channels_add(), cli(), export_cmd(), _extract_handle() (+29 more)
### Community 5 - "Platform Design & Proposals"
Cohesion: 0.12
Nodes (20): Platform Implementation Plan, Platform Design Spec, Cookie drag-and-drop vault UX, cli.py cookies scope bug fix, Design language: dark data command center, Architecture: Monorepo in-package webapp (Approach A), Scope rule: No AI features, Single-threaded scrape job runner + SSE event bus (+12 more)
### Community 6 - "Segments Search & Backfill"
Cohesion: 0.10
Nodes (26): APIRouter, FastAPI, cache_thumbnail(), Thumbnail URL for a video: stored URL, else the canonical YouTube one derived fr, Download + cache a video's thumbnail to <thumbnails_dir>/<video_id>.jpg. Returns, thumbnail_url_for(), backfill_from_markdown(), parse_markdown() (+18 more)
### Community 7 - "Store Platform Tests"
Cohesion: 0.06
Nodes (44): Collection, _channel_root_url(), discover_channel(), discover_incremental(), _flatten_entries(), IncrementalDiscovery, _pick_channel_avatar(), Any (+36 more)
### Community 8 - "Content Analysis"
Cohesion: 0.27
Nodes (10): _iter_texts(), Path, Return [(YYYY-MM, count)] of months where `term` appears in transcripts., render_timeline_chart(), render_top_words_chart(), render_wordcloud(), term_timeline(), _tokenize() (+2 more)
### Community 10 - "Server Start Script"
Cohesion: 0.38
Nodes (3): Open-Browser(), Out-Line(), Show-State()
### Community 14 - "test_extract.py"
Cohesion: 0.08
Nodes (46): Response, parse_languages(), Any, Normalise legacy list / new dict / None into ``{lang: mode}``., _coerce_languages(), _download_subtitle(), extract_video(), _normalize_lang() (+38 more)
### Community 15 - "Auditoría · Cómo la extensión obtiene la transcripción / información de vídeos de YouTube"
Cohesion: 0.05
Nodes (41): Arquitectura, Comandos, Cookies, Cualquier petición HTTP a CDNs de YouTube va por `_yt_http.yt_get()`, Documentos de referencia, El Markdown es fuente de datos, no solo salida, Frontend, Idiomas: dict por-idioma con compatibilidad legacy (+33 more)
### Community 16 - "api"
Cohesion: 0.14
Nodes (34): activateCookie(), addChannel(), api(), checkAudio(), copyClip(), copyText(), downloadAudio(), downloadAudioOne() (+26 more)
### Community 17 - "pipeline.py"
Cohesion: 0.24
Nodes (15): align_chapters(), Chapter, chapters_from_info(), Section, _normalize_date(), process_video(), Regenerate .md for done videos that have stored segments. Returns count re-rende, Extract + parse + store + render a single video. Returns final status string. (+7 more)
### Community 18 - "render.py"
Cohesion: 0.20
Nodes (16): build_filename_stem(), format_timestamp(), _make_env(), Path, quote_yaml(), render_markdown(), to_json(), test_build_filename_stem() (+8 more)
### Community 19 - "config.py"
Cohesion: 0.27
Nodes (13): _build_config(), DelayConfig, load_config(), Incremental channel sync — how far back a routine re-scan looks. The /video, SyncConfig, YtDlpConfig, Tests for the YAML config loader. Focuses on the ``languages`` and ``prefer_man, test_load_legacy_languages_list() (+5 more)
### Community 20 - "setView"
Cohesion: 0.18
Nodes (14): checkHealth(), cycleSort(), destroyCharts(), hydrateURL(), init(), loadFolders(), loadFormat(), loadSearch() (+6 more)
### Community 21 - "Discovery-Only Scrape Design"
Cohesion: 0.22
Nodes (8): Architecture, Discovery-Only Scrape Design, Error Handling, Existing Context, Goal, Persistence and Results, Testing, UI
### Community 22 - "renderDashboardCharts"
Cohesion: 0.36
Nodes (9): axisOpts(), barOpts(), fmtMonth(), lineOpts(), loadAnalysis(), makeChart(), renderDashboardCharts(), renderTimelineChart() (+1 more)
### Community 23 - "Global Constraints"
Cohesion: 0.25
Nodes (7): Discovery-Only Scrape Implementation Plan, Global Constraints, Task 1: Make catalog insertion counts accurate, Task 2: Add discovery-only job execution, Task 3: Expose the discovery mode through the API, Task 4: Add one-channel and all-channel UI controls, Task 5: Final verification and review
### Community 24 - "loadJobs"
Cohesion: 0.29
Nodes (7): cancelScrape(), clearJobHistory(), closeStream(), deleteJob(), jobActionLabel(), jobIsTerminal(), loadJobs()
## Knowledge Gaps
- **57 isolated node(s):** `yt-channel-scraper`, `Qué es esto`, `Comandos`, `Orientación antes de leer código`, `Tres superficies, un solo pipeline` (+52 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **3 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **Why does `Store` connect `Store & Export Layer` to `Transcript Extraction & Parsing`, `Config & Discovery Pipeline`, `CLI Command Layer`, `Segments Search & Backfill`, `Store Platform Tests`, `Content Analysis`, `pipeline.py`?**
_High betweenness centrality (0.146) - this node is a cross-community bridge._
- **Why does `Segment` connect `Transcript Extraction & Parsing` to `CLI Command Layer`, `Segments Search & Backfill`, `Store Platform Tests`, `test_extract.py`, `pipeline.py`, `render.py`?**
_High betweenness centrality (0.035) - this node is a cross-community bridge._
- **Why does `VideoRef` connect `Store Platform Tests` to `Transcript Extraction & Parsing`, `Config & Discovery Pipeline`, `Store & Export Layer`, `CLI Command Layer`?**
_High betweenness centrality (0.027) - this node is a cross-community bridge._
- **Are the 12 inferred relationships involving `Store` (e.g. with `ParsedMarkdown` and `store()`) actually correct?**
_`Store` has 12 INFERRED edges - model-reasoned connections that need verification._
- **Are the 9 inferred relationships involving `Config` (e.g. with `test_config_languages_defaults_to_dict()` and `test_config_prefer_manual_defaults_true()`) actually correct?**
_`Config` has 9 INFERRED edges - model-reasoned connections that need verification._
- **Are the 17 inferred relationships involving `Segment` (e.g. with `Chapter` and `Section`) actually correct?**
_`Segment` has 17 INFERRED edges - model-reasoned connections that need verification._
- **What connects `yt-channel-scraper`, `Qué es esto`, `Comandos` to the rest of the system?**
_57 weakly-connected nodes found - possible documentation gaps or missing edges._
+12
View File
@@ -0,0 +1,12 @@
{
"runs": [
{
"date": "2026-07-27T05:54:56.822038+00:00",
"input_tokens": 11800,
"output_tokens": 4100,
"files": 37
}
],
"total_input_tokens": 11800,
"total_output_tokens": 4100
}
File diff suppressed because it is too large Load Diff
+237
View File
@@ -0,0 +1,237 @@
{
"pyproject.toml": {
"mtime": 1785126752.9759955,
"ast_hash": "f80dc007b3b67c7f7a78d9df01a81ead",
"semantic_hash": "f80dc007b3b67c7f7a78d9df01a81ead"
},
"scripts/start-server.ps1": {
"mtime": 1785132936.4055703,
"ast_hash": "7390a228e676bff301ae85c5a4e7449e",
"semantic_hash": ""
},
"scripts/stop-server.ps1": {
"mtime": 1785132762.2959402,
"ast_hash": "4a62db3fa3dca6b7109fcaadc1219226",
"semantic_hash": ""
},
"src/yt_scraper/__init__.py": {
"mtime": 1785120608.3336751,
"ast_hash": "4867131295172353fe6c2295851defc7",
"semantic_hash": "4867131295172353fe6c2295851defc7"
},
"src/yt_scraper/analysis.py": {
"mtime": 1785126463.1545029,
"ast_hash": "c28d08131e6594e1e7c6111ff01b2d37",
"semantic_hash": "c28d08131e6594e1e7c6111ff01b2d37"
},
"src/yt_scraper/chapters.py": {
"mtime": 1785120675.3308973,
"ast_hash": "1bf51b7c13486b9db9bcc3420fba2593",
"semantic_hash": "1bf51b7c13486b9db9bcc3420fba2593"
},
"src/yt_scraper/cli.py": {
"mtime": 1785555646.793181,
"ast_hash": "36369eb5843535426c93cb5e0e14343a",
"semantic_hash": ""
},
"src/yt_scraper/config.py": {
"mtime": 1785555391.6008003,
"ast_hash": "b7a36354f41dbbaa3e4bbc7b635be4a2",
"semantic_hash": ""
},
"src/yt_scraper/cookies.py": {
"mtime": 1785126417.4218228,
"ast_hash": "dd5ec44bb4c6e6375be80f21307fc73d",
"semantic_hash": "dd5ec44bb4c6e6375be80f21307fc73d"
},
"src/yt_scraper/discover.py": {
"mtime": 1785555427.3430922,
"ast_hash": "fce9799bd4076f35d4e5b4b1359b9782",
"semantic_hash": ""
},
"src/yt_scraper/export.py": {
"mtime": 1785126439.6829402,
"ast_hash": "f1cff31fb1004f08e997655f838e3a58",
"semantic_hash": "f1cff31fb1004f08e997655f838e3a58"
},
"src/yt_scraper/extract.py": {
"mtime": 1785134973.9585488,
"ast_hash": "a9cff81702b263b80f72087a14864d7a",
"semantic_hash": ""
},
"src/yt_scraper/monitor.py": {
"mtime": 1785555591.7611978,
"ast_hash": "e7948e61b74b84b246708518f02dbcae",
"semantic_hash": ""
},
"src/yt_scraper/parse.py": {
"mtime": 1785120665.3384771,
"ast_hash": "25354365ac1ab52f1561c97256573806",
"semantic_hash": "25354365ac1ab52f1561c97256573806"
},
"src/yt_scraper/pipeline.py": {
"mtime": 1785134990.2165341,
"ast_hash": "22d9c0d4630559f97ab68b652d9e1ef3",
"semantic_hash": ""
},
"src/yt_scraper/ratelimit.py": {
"mtime": 1785120650.3795395,
"ast_hash": "6082befe56d342fc43abd5299dd6c6ea",
"semantic_hash": "6082befe56d342fc43abd5299dd6c6ea"
},
"src/yt_scraper/render.py": {
"mtime": 1785120688.3247268,
"ast_hash": "ff83764f3a8c8874557993e11eab1f89",
"semantic_hash": "ff83764f3a8c8874557993e11eab1f89"
},
"src/yt_scraper/segments.py": {
"mtime": 1785128385.6652262,
"ast_hash": "09c7da35bc09a3f75fd0a627c0534746",
"semantic_hash": "09c7da35bc09a3f75fd0a627c0534746"
},
"src/yt_scraper/store.py": {
"mtime": 1785555451.541978,
"ast_hash": "1821f8382f14edc0fe16e27c947caa3b",
"semantic_hash": ""
},
"src/yt_scraper/webapp/__init__.py": {
"mtime": 1785126827.4957752,
"ast_hash": "d41d8cd98f00b204e9800998ecf8427e",
"semantic_hash": "d41d8cd98f00b204e9800998ecf8427e"
},
"src/yt_scraper/webapp/api.py": {
"mtime": 1785555568.718664,
"ast_hash": "be2bce8aacf98625a43edd840439a5a5",
"semantic_hash": ""
},
"src/yt_scraper/webapp/app.py": {
"mtime": 1785126888.8032887,
"ast_hash": "e0b1925b4318305dcf746d360373ff50",
"semantic_hash": "e0b1925b4318305dcf746d360373ff50"
},
"src/yt_scraper/webapp/jobs.py": {
"mtime": 1785555552.558772,
"ast_hash": "8ca8f21136d8a4564f49927821244344",
"semantic_hash": ""
},
"src/yt_scraper/webapp/static/app.js": {
"mtime": 1785555832.5020685,
"ast_hash": "6932efd1a6044e66d227a2fc93042187",
"semantic_hash": ""
},
"tests/test_chapters.py": {
"mtime": 1785120789.3300896,
"ast_hash": "6d5303fa86de8dc99af6ae2ee17da033",
"semantic_hash": "6d5303fa86de8dc99af6ae2ee17da033"
},
"tests/test_features.py": {
"mtime": 1785126709.65728,
"ast_hash": "21f9c44ce7cc1d618ece402ab7c2b057",
"semantic_hash": "21f9c44ce7cc1d618ece402ab7c2b057"
},
"tests/test_parse.py": {
"mtime": 1785120974.3283188,
"ast_hash": "57ce74ee10fe6f9a90126ec7d9fd96b0",
"semantic_hash": "57ce74ee10fe6f9a90126ec7d9fd96b0"
},
"tests/test_render.py": {
"mtime": 1785120806.3260238,
"ast_hash": "27125960e235813724fd669001faab59",
"semantic_hash": "27125960e235813724fd669001faab59"
},
"tests/test_store_platform.py": {
"mtime": 1785194588.4186954,
"ast_hash": "44069db75a444906fb5001880dedf180",
"semantic_hash": ""
},
".opencode/agent/webapp-builder.md": {
"mtime": 1785126783.7152567,
"ast_hash": "58e92641724400370d7823dce1e02ca3",
"semantic_hash": "58e92641724400370d7823dce1e02ca3"
},
".opencode/goals/webapp-build.md": {
"mtime": 1785126796.8402326,
"ast_hash": "478e7a2350ded2fd273cfdb0714d228d",
"semantic_hash": "478e7a2350ded2fd273cfdb0714d228d"
},
"OPPORTUNITIES.md": {
"mtime": 1785122706.3466253,
"ast_hash": "4af60e3106b394664fbf5b5c5f645804",
"semantic_hash": "4af60e3106b394664fbf5b5c5f645804"
},
"README.md": {
"mtime": 1785121499.3282604,
"ast_hash": "a0a8e6b62a991fce5d6c58171f80075e",
"semantic_hash": "a0a8e6b62a991fce5d6c58171f80075e"
},
"config.example.yaml": {
"mtime": 1785555848.8664799,
"ast_hash": "f65a5089bf286e47326e916ad19ca572",
"semantic_hash": ""
},
"docs/superpowers/plans/2026-07-26-platform-build.md": {
"mtime": 1785126240.4211702,
"ast_hash": "8097056ef23068f22c48151746de305b",
"semantic_hash": "8097056ef23068f22c48151746de305b"
},
"docs/superpowers/specs/2026-07-26-platform-design.md": {
"mtime": 1785126024.4879057,
"ast_hash": "9b85f02fd45c93cdabfd2e1c6d1e0c9e",
"semantic_hash": "9b85f02fd45c93cdabfd2e1c6d1e0c9e"
},
"src/yt_scraper/webapp/static/index.html": {
"mtime": 1785555838.550363,
"ast_hash": "372b8d77aae448ab1c478253782579ce",
"semantic_hash": ""
},
"src/yt_scraper/_yt_http.py": {
"mtime": 1785134945.1512043,
"ast_hash": "8af224580322df5aeeba10062592d961",
"semantic_hash": ""
},
"tests/test_config.py": {
"mtime": 1785135145.3334274,
"ast_hash": "5588a7ad8e1c866b1571a818d816f7a7",
"semantic_hash": ""
},
"tests/test_discover_incremental.py": {
"mtime": 1785555704.1061945,
"ast_hash": "e1c382a9b8f5c927a85d67814d3dbb09",
"semantic_hash": ""
},
"tests/test_extract.py": {
"mtime": 1785135157.3141267,
"ast_hash": "0bd7c2f3fb9f6bdfe855758b17e3bcf0",
"semantic_hash": ""
},
"tests/test_store_sync_watermark.py": {
"mtime": 1785555725.6495814,
"ast_hash": "9f9943f5b914078cee49bf4aaa060564",
"semantic_hash": ""
},
"tests/test_webapp_jobs.py": {
"mtime": 1785555746.4912646,
"ast_hash": "7688c701256ff0cdd2a7d78d7090c8b3",
"semantic_hash": ""
},
"CLAUDE.md": {
"mtime": 1785556046.8310063,
"ast_hash": "631eba15392019298d5fbfcce89c6611",
"semantic_hash": ""
},
"YOUTUBE-TRANSCRIPT-AUDIT.md": {
"mtime": 1785116715.5118847,
"ast_hash": "67c5b7e3b4661ca8c8a7280e63b13ba9",
"semantic_hash": ""
},
"docs/superpowers/plans/2026-07-27-discovery-only-scrape.md": {
"mtime": 1785192916.5353482,
"ast_hash": "3cf41d6331bd67e39ccd96b0e6138cf2",
"semantic_hash": ""
},
"docs/superpowers/specs/2026-07-27-discovery-only-scrape-design.md": {
"mtime": 1785192898.2889626,
"ast_hash": "529b39e9bd2adcafd17a2dc30263281c",
"semantic_hash": ""
}
}
@@ -0,0 +1,26 @@
{
"0": "Webapp Frontend (JS)",
"1": "Transcript Extraction & Parsing",
"2": "Config & Discovery Pipeline",
"3": "Store & Export Layer",
"4": "CLI Command Layer",
"5": "Platform Design & Proposals",
"6": "Segments Search & Backfill",
"7": "Store Platform Tests",
"8": "Content Analysis",
"9": "README & Config Docs",
"10": "Server Start Script",
"11": "Package Manifest",
"12": "Server Stop Script",
"13": "Webapp Package Init",
"14": "test_extract.py",
"15": "Auditoría · Cómo la extensión obtiene la transcripción / información de vídeos de YouTube",
"16": "api",
"17": "pipeline.py",
"20": "setView",
"21": "Discovery-Only Scrape Design",
"22": "renderDashboardCharts",
"23": "Global Constraints",
"25": "init",
"27": "loadChannels"
}
+177
View File
@@ -0,0 +1,177 @@
# Graph Report - yt-channel-scraper (2026-08-01)
## Corpus Check
- 48 files · ~51,184 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 669 nodes · 1538 edges · 24 communities (21 shown, 3 thin omitted)
- Extraction: 89% EXTRACTED · 11% INFERRED · 0% AMBIGUOUS · INFERRED: 162 edges (avg confidence: 0.78)
- Token cost: 0 input · 0 output
## Graph Freshness
- Built from commit: `06497299`
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
- Run `graphify update .` after code changes (no API cost).
## Community Hubs (Navigation)
- Webapp Frontend (JS)
- Transcript Extraction & Parsing
- Config & Discovery Pipeline
- Store & Export Layer
- CLI Command Layer
- Platform Design & Proposals
- Segments Search & Backfill
- Store Platform Tests
- Content Analysis
- README & Config Docs
- Server Start Script
- Package Manifest
- Server Stop Script
- test_extract.py
- Auditoría · Cómo la extensión obtiene la transcripción / información de vídeos de YouTube
- api
- pipeline.py
- setView
- Discovery-Only Scrape Design
- renderDashboardCharts
- Global Constraints
- init
- loadChannels
## God Nodes (most connected - your core abstractions)
1. `Store` - 101 edges
2. `VideoRef` - 42 edges
3. `api()` - 39 edges
4. `toast()` - 38 edges
5. `Config` - 36 edges
6. `Segment` - 32 edges
7. `JobManager` - 26 edges
8. `discover_incremental()` - 21 edges
9. `process_video()` - 19 edges
10. `reconcile_markdown()` - 19 edges
## Surprising Connections (you probably didn't know these)
- `seeded_store()` --calls--> `VideoRef` [INFERRED]
tests/test_store_platform.py → src/yt_scraper/store.py
- `test_upload_sort_uses_discovered_time_when_date_is_missing()` --calls--> `VideoRef` [INFERRED]
tests/test_store_platform.py → src/yt_scraper/store.py
- `test_upsert_videos_reports_only_new_rows()` --calls--> `VideoRef` [INFERRED]
tests/test_store_platform.py → src/yt_scraper/store.py
- `store()` --calls--> `Store` [INFERRED]
tests/test_store_platform.py → src/yt_scraper/store.py
- `test_migration_idempotent()` --calls--> `Store` [INFERRED]
tests/test_store_platform.py → src/yt_scraper/store.py
## Import Cycles
- None detected.
## Hyperedges (group relationships)
- **Workstream B webapp stack (FastAPI + Alpine SPA + subagent)** — opencode_agent_webapp_builder, opencode_goals_webapp_build, src_yt_scraper_webapp_static_index, docs_superpowers_specs_2026_07_26_platform_design_dark_command_center, docs_superpowers_specs_2026_07_26_platform_design_sse_job_runner [EXTRACTED 0.95]
- **FTS5 transcript search flow (proposal -> spec -> SPA view)** — opportunities_search_fts5, docs_superpowers_specs_2026_07_26_platform_design_transcript_fts5, src_yt_scraper_webapp_static_index [INFERRED 0.85]
- **Cookie auth chain (vault -> resolve_active_path -> scrape job)** — docs_superpowers_specs_2026_07_26_platform_design_cookie_vault_ux, docs_superpowers_specs_2026_07_26_platform_design_sse_job_runner, docs_superpowers_specs_2026_07_26_platform_design_cookies_bug_fix, src_yt_scraper_webapp_static_index [INFERRED 0.85]
## Communities (24 total, 3 thin omitted)
### Community 0 - "Webapp Frontend (JS)"
Cohesion: 0.06
Nodes (22): _armAutoHide(), cancelScrape(), closeClip(), closeJobWidget(), closeSidebar(), closeStats(), closeStream(), deleteJob() (+14 more)
### Community 1 - "Transcript Extraction & Parsing"
Cohesion: 0.27
Nodes (10): _iter_texts(), Path, Return [(YYYY-MM, count)] of months where `term` appears in transcripts., render_timeline_chart(), render_top_words_chart(), render_wordcloud(), term_timeline(), _tokenize() (+2 more)
### Community 2 - "Config & Discovery Pipeline"
Cohesion: 0.06
Nodes (46): _build_config(), Config, DelayConfig, load_config(), Path, Incremental channel sync — how far back a routine re-scan looks. The /video, SyncConfig, YtDlpConfig (+38 more)
### Community 3 - "Store & Export Layer"
Cohesion: 0.05
Nodes (46): Connection, Cursor, Environment, Row, auto_import_dir(), cookies_dir(), delete(), import_file() (+38 more)
### Community 4 - "CLI Command Layer"
Cohesion: 0.07
Nodes (44): analyze_cmd(), _apply_filters(), audio_cmd(), _channel_targets(), channels_add(), cli(), export_cmd(), _extract_handle() (+36 more)
### Community 5 - "Platform Design & Proposals"
Cohesion: 0.12
Nodes (20): Platform Implementation Plan, Platform Design Spec, Cookie drag-and-drop vault UX, cli.py cookies scope bug fix, Design language: dark data command center, Architecture: Monorepo in-package webapp (Approach A), Scope rule: No AI features, Single-threaded scrape job runner + SSE event bus (+12 more)
### Community 6 - "Segments Search & Backfill"
Cohesion: 0.09
Nodes (28): APIRouter, FastAPI, cache_channel_avatar(), cache_thumbnail(), Thumbnail URL for a video: stored URL, else the canonical YouTube one derived fr, Download + cache a video's thumbnail to <thumbnails_dir>/<video_id>.jpg. Returns, Download + cache a channel avatar to <avatars_dir>/<channel_id>.jpg. Returns Tru, thumbnail_url_for() (+20 more)
### Community 7 - "Store Platform Tests"
Cohesion: 0.13
Nodes (28): Collection, _channel_root_url(), deep_channel_avatar(), discover_channel(), discover_incremental(), _flatten_entries(), IncrementalDiscovery, _pick_channel_avatar() (+20 more)
### Community 8 - "Content Analysis"
Cohesion: 0.10
Nodes (41): Re-escanear data/markdown y hacer que la DB coincida con el disco., reconcile_cmd(), Make the DB agree with what is actually on disk. `backfill_from_markdown` f, reconcile_markdown(), VideoRef, Recovery paths: retryable statuses, recorded skip reasons, disk<->DB reconcile., The throttling message is the one that must stay retryable., The exact symptom the user reported: a .md exists but the row still shows a (+33 more)
### Community 10 - "Server Start Script"
Cohesion: 0.38
Nodes (3): Open-Browser(), Out-Line(), Show-State()
### Community 14 - "test_extract.py"
Cohesion: 0.07
Nodes (48): Response, parse_languages(), Any, Normalise legacy list / new dict / None into ``{lang: mode}``., _coerce_languages(), describe_missing_subtitle(), _download_subtitle(), extract_video() (+40 more)
### Community 15 - "Auditoría · Cómo la extensión obtiene la transcripción / información de vídeos de YouTube"
Cohesion: 0.04
Nodes (42): Arquitectura, Comandos, Cookies, Cualquier petición HTTP a CDNs de YouTube va por `_yt_http.yt_get()`, Documentos de referencia, El Markdown es fuente de datos, no solo salida, Estados terminales y frescura (la UI tiene que reflejar DB + disco), Frontend (+34 more)
### Community 16 - "api"
Cohesion: 0.15
Nodes (29): activateCookie(), api(), checkAudio(), clearJobHistory(), copyClip(), copyText(), downloadAudio(), downloadAudioOne() (+21 more)
### Community 17 - "pipeline.py"
Cohesion: 0.05
Nodes (56): align_chapters(), Chapter, chapters_from_info(), Section, merge_adjacent(), parse_auto_dump(), parse_json3(), parse_vtt() (+48 more)
### Community 20 - "setView"
Cohesion: 0.24
Nodes (10): cycleSort(), destroyCharts(), loadFolders(), loadFormat(), loadSearch(), loadVideos(), openChannel(), resetSearch() (+2 more)
### Community 21 - "Discovery-Only Scrape Design"
Cohesion: 0.22
Nodes (8): Architecture, Discovery-Only Scrape Design, Error Handling, Existing Context, Goal, Persistence and Results, Testing, UI
### Community 22 - "renderDashboardCharts"
Cohesion: 0.36
Nodes (9): axisOpts(), barOpts(), fmtMonth(), lineOpts(), loadAnalysis(), makeChart(), renderDashboardCharts(), renderTimelineChart() (+1 more)
### Community 23 - "Global Constraints"
Cohesion: 0.25
Nodes (7): Discovery-Only Scrape Implementation Plan, Global Constraints, Task 1: Make catalog insertion counts accurate, Task 2: Add discovery-only job execution, Task 3: Expose the discovery mode through the API, Task 4: Add one-channel and all-channel UI controls, Task 5: Final verification and review
### Community 25 - "init"
Cohesion: 0.20
Nodes (11): checkHealth(), hydrateURL(), init(), jobActive(), loadRetryable(), reconcile(), refreshLiveState(), resetVideos() (+3 more)
### Community 27 - "loadChannels"
Cohesion: 0.32
Nodes (8): addChannel(), downloadAvatarsScope(), loadChannelPending(), loadChannels(), loadDashboard(), removeChannel(), _setSyncResult(), syncChannels()
## Knowledge Gaps
- **58 isolated node(s):** `yt-channel-scraper`, `Qué es esto`, `Comandos`, `Orientación antes de leer código`, `Tres superficies, un solo pipeline` (+53 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **3 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **Why does `Store` connect `Store & Export Layer` to `Transcript Extraction & Parsing`, `Config & Discovery Pipeline`, `CLI Command Layer`, `Segments Search & Backfill`, `Content Analysis`, `pipeline.py`?**
_High betweenness centrality (0.151) - this node is a cross-community bridge._
- **Why does `VideoRef` connect `Content Analysis` to `Config & Discovery Pipeline`, `Store & Export Layer`, `CLI Command Layer`, `Store Platform Tests`, `pipeline.py`?**
_High betweenness centrality (0.048) - this node is a cross-community bridge._
- **Why does `Segment` connect `pipeline.py` to `CLI Command Layer`, `test_extract.py`, `Segments Search & Backfill`?**
_High betweenness centrality (0.032) - this node is a cross-community bridge._
- **Are the 13 inferred relationships involving `Store` (e.g. with `ParsedMarkdown` and `store()`) actually correct?**
_`Store` has 13 INFERRED edges - model-reasoned connections that need verification._
- **Are the 31 inferred relationships involving `VideoRef` (e.g. with `IncrementalDiscovery` and `store()`) actually correct?**
_`VideoRef` has 31 INFERRED edges - model-reasoned connections that need verification._
- **Are the 11 inferred relationships involving `Config` (e.g. with `test_config_languages_defaults_to_dict()` and `test_config_prefer_manual_defaults_true()`) actually correct?**
_`Config` has 11 INFERRED edges - model-reasoned connections that need verification._
- **What connects `yt-channel-scraper`, `Qué es esto`, `Comandos` to the rest of the system?**
_58 weakly-connected nodes found - possible documentation gaps or missing edges._
+12
View File
@@ -0,0 +1,12 @@
{
"runs": [
{
"date": "2026-07-27T05:54:56.822038+00:00",
"input_tokens": 11800,
"output_tokens": 4100,
"files": 37
}
],
"total_input_tokens": 11800,
"total_output_tokens": 4100
}
File diff suppressed because it is too large Load Diff
+252
View File
@@ -0,0 +1,252 @@
{
"pyproject.toml": {
"mtime": 1785126752.9759955,
"ast_hash": "f80dc007b3b67c7f7a78d9df01a81ead",
"semantic_hash": "f80dc007b3b67c7f7a78d9df01a81ead"
},
"scripts/start-server.ps1": {
"mtime": 1785132936.4055703,
"ast_hash": "7390a228e676bff301ae85c5a4e7449e",
"semantic_hash": ""
},
"scripts/stop-server.ps1": {
"mtime": 1785132762.2959402,
"ast_hash": "4a62db3fa3dca6b7109fcaadc1219226",
"semantic_hash": ""
},
"src/yt_scraper/__init__.py": {
"mtime": 1785120608.3336751,
"ast_hash": "4867131295172353fe6c2295851defc7",
"semantic_hash": "4867131295172353fe6c2295851defc7"
},
"src/yt_scraper/analysis.py": {
"mtime": 1785126463.1545029,
"ast_hash": "c28d08131e6594e1e7c6111ff01b2d37",
"semantic_hash": "c28d08131e6594e1e7c6111ff01b2d37"
},
"src/yt_scraper/chapters.py": {
"mtime": 1785120675.3308973,
"ast_hash": "1bf51b7c13486b9db9bcc3420fba2593",
"semantic_hash": "1bf51b7c13486b9db9bcc3420fba2593"
},
"src/yt_scraper/cli.py": {
"mtime": 1785561823.2458293,
"ast_hash": "100604834f369047b55641bd327333d0",
"semantic_hash": ""
},
"src/yt_scraper/config.py": {
"mtime": 1785561416.2574291,
"ast_hash": "712dddce27149cb3a5ceb34f78fac2fd",
"semantic_hash": ""
},
"src/yt_scraper/cookies.py": {
"mtime": 1785126417.4218228,
"ast_hash": "dd5ec44bb4c6e6375be80f21307fc73d",
"semantic_hash": "dd5ec44bb4c6e6375be80f21307fc73d"
},
"src/yt_scraper/discover.py": {
"mtime": 1785555427.3430922,
"ast_hash": "fce9799bd4076f35d4e5b4b1359b9782",
"semantic_hash": ""
},
"src/yt_scraper/export.py": {
"mtime": 1785126439.6829402,
"ast_hash": "f1cff31fb1004f08e997655f838e3a58",
"semantic_hash": "f1cff31fb1004f08e997655f838e3a58"
},
"src/yt_scraper/extract.py": {
"mtime": 1785561382.7161057,
"ast_hash": "a46b96123cfef40a10436e6e65b45d4b",
"semantic_hash": ""
},
"src/yt_scraper/monitor.py": {
"mtime": 1785555591.7611978,
"ast_hash": "e7948e61b74b84b246708518f02dbcae",
"semantic_hash": ""
},
"src/yt_scraper/parse.py": {
"mtime": 1785120665.3384771,
"ast_hash": "25354365ac1ab52f1561c97256573806",
"semantic_hash": "25354365ac1ab52f1561c97256573806"
},
"src/yt_scraper/pipeline.py": {
"mtime": 1785562085.460622,
"ast_hash": "7dae8872284b33015654fb356c008e67",
"semantic_hash": ""
},
"src/yt_scraper/ratelimit.py": {
"mtime": 1785120650.3795395,
"ast_hash": "6082befe56d342fc43abd5299dd6c6ea",
"semantic_hash": "6082befe56d342fc43abd5299dd6c6ea"
},
"src/yt_scraper/render.py": {
"mtime": 1785120688.3247268,
"ast_hash": "ff83764f3a8c8874557993e11eab1f89",
"semantic_hash": "ff83764f3a8c8874557993e11eab1f89"
},
"src/yt_scraper/segments.py": {
"mtime": 1785562183.2376134,
"ast_hash": "902d851e321b83c99d4cae30c1ae39fc",
"semantic_hash": ""
},
"src/yt_scraper/store.py": {
"mtime": 1785569257.9151454,
"ast_hash": "fffc4c7aa5265bd53cd7ca2856b453ef",
"semantic_hash": ""
},
"src/yt_scraper/webapp/__init__.py": {
"mtime": 1785126827.4957752,
"ast_hash": "d41d8cd98f00b204e9800998ecf8427e",
"semantic_hash": "d41d8cd98f00b204e9800998ecf8427e"
},
"src/yt_scraper/webapp/api.py": {
"mtime": 1785569267.6258545,
"ast_hash": "cadbcafc755f0e1daa574709bc54be84",
"semantic_hash": ""
},
"src/yt_scraper/webapp/app.py": {
"mtime": 1785562107.3107448,
"ast_hash": "80e375becb41e202f78239138252c5c8",
"semantic_hash": ""
},
"src/yt_scraper/webapp/jobs.py": {
"mtime": 1785556090.2023566,
"ast_hash": "45ba7f10b13b847c213f04441a5e741d",
"semantic_hash": ""
},
"src/yt_scraper/webapp/static/app.js": {
"mtime": 1785561992.7035935,
"ast_hash": "94250d573a31bf9bfb29cb54dc4c01e0",
"semantic_hash": ""
},
"tests/test_chapters.py": {
"mtime": 1785120789.3300896,
"ast_hash": "6d5303fa86de8dc99af6ae2ee17da033",
"semantic_hash": "6d5303fa86de8dc99af6ae2ee17da033"
},
"tests/test_features.py": {
"mtime": 1785126709.65728,
"ast_hash": "21f9c44ce7cc1d618ece402ab7c2b057",
"semantic_hash": "21f9c44ce7cc1d618ece402ab7c2b057"
},
"tests/test_parse.py": {
"mtime": 1785120974.3283188,
"ast_hash": "57ce74ee10fe6f9a90126ec7d9fd96b0",
"semantic_hash": "57ce74ee10fe6f9a90126ec7d9fd96b0"
},
"tests/test_render.py": {
"mtime": 1785120806.3260238,
"ast_hash": "27125960e235813724fd669001faab59",
"semantic_hash": "27125960e235813724fd669001faab59"
},
"tests/test_store_platform.py": {
"mtime": 1785194588.4186954,
"ast_hash": "44069db75a444906fb5001880dedf180",
"semantic_hash": ""
},
".opencode/agent/webapp-builder.md": {
"mtime": 1785126783.7152567,
"ast_hash": "58e92641724400370d7823dce1e02ca3",
"semantic_hash": "58e92641724400370d7823dce1e02ca3"
},
".opencode/goals/webapp-build.md": {
"mtime": 1785126796.8402326,
"ast_hash": "478e7a2350ded2fd273cfdb0714d228d",
"semantic_hash": "478e7a2350ded2fd273cfdb0714d228d"
},
"OPPORTUNITIES.md": {
"mtime": 1785122706.3466253,
"ast_hash": "4af60e3106b394664fbf5b5c5f645804",
"semantic_hash": "4af60e3106b394664fbf5b5c5f645804"
},
"README.md": {
"mtime": 1785121499.3282604,
"ast_hash": "a0a8e6b62a991fce5d6c58171f80075e",
"semantic_hash": "a0a8e6b62a991fce5d6c58171f80075e"
},
"config.example.yaml": {
"mtime": 1785561451.814817,
"ast_hash": "43661d5c00d05c922bcf884e8ac707c3",
"semantic_hash": ""
},
"docs/superpowers/plans/2026-07-26-platform-build.md": {
"mtime": 1785126240.4211702,
"ast_hash": "8097056ef23068f22c48151746de305b",
"semantic_hash": "8097056ef23068f22c48151746de305b"
},
"docs/superpowers/specs/2026-07-26-platform-design.md": {
"mtime": 1785126024.4879057,
"ast_hash": "9b85f02fd45c93cdabfd2e1c6d1e0c9e",
"semantic_hash": "9b85f02fd45c93cdabfd2e1c6d1e0c9e"
},
"src/yt_scraper/webapp/static/index.html": {
"mtime": 1785569275.8425553,
"ast_hash": "4f3d8f27f4f663c6f741be3db2312df3",
"semantic_hash": ""
},
"src/yt_scraper/_yt_http.py": {
"mtime": 1785134945.1512043,
"ast_hash": "8af224580322df5aeeba10062592d961",
"semantic_hash": ""
},
"tests/test_config.py": {
"mtime": 1785561477.3907576,
"ast_hash": "46f3eefb24bcf44535c17977ac175509",
"semantic_hash": ""
},
"tests/test_discover_incremental.py": {
"mtime": 1785555704.1061945,
"ast_hash": "e1c382a9b8f5c927a85d67814d3dbb09",
"semantic_hash": ""
},
"tests/test_extract.py": {
"mtime": 1785561483.422817,
"ast_hash": "9949ef4f6e7fe8cbdf12bc8d1dc71e3f",
"semantic_hash": ""
},
"tests/test_store_sync_watermark.py": {
"mtime": 1785555725.6495814,
"ast_hash": "9f9943f5b914078cee49bf4aaa060564",
"semantic_hash": ""
},
"tests/test_webapp_jobs.py": {
"mtime": 1785555746.4912646,
"ast_hash": "7688c701256ff0cdd2a7d78d7090c8b3",
"semantic_hash": ""
},
"CLAUDE.md": {
"mtime": 1785569349.167527,
"ast_hash": "a161232f286c0a4f674715f54b66fa76",
"semantic_hash": ""
},
"YOUTUBE-TRANSCRIPT-AUDIT.md": {
"mtime": 1785116715.5118847,
"ast_hash": "67c5b7e3b4661ca8c8a7280e63b13ba9",
"semantic_hash": ""
},
"docs/superpowers/plans/2026-07-27-discovery-only-scrape.md": {
"mtime": 1785192916.5353482,
"ast_hash": "3cf41d6331bd67e39ccd96b0e6138cf2",
"semantic_hash": ""
},
"docs/superpowers/specs/2026-07-27-discovery-only-scrape-design.md": {
"mtime": 1785192898.2889626,
"ast_hash": "529b39e9bd2adcafd17a2dc30263281c",
"semantic_hash": ""
},
"tests/test_recovery.py": {
"mtime": 1785569307.786051,
"ast_hash": "53f25aeda88cbf3755f45f2377970b62",
"semantic_hash": ""
},
"tests/test_since_filter.py": {
"mtime": 1785556104.7475204,
"ast_hash": "1d827c61156ab488e838dac91261624f",
"semantic_hash": ""
},
".claude/settings.json": {
"mtime": 1785569155.4443069,
"ast_hash": "dc072413449915d630bc773c9fb57dc7",
"semantic_hash": ""
}
}
+200 -56
View File
@@ -1,12 +1,18 @@
# Graph Report - . (2026-07-26)
# Graph Report - yt-channel-scraper (2026-08-01)
## Corpus Check
- Corpus is ~28,854 words - fits in a single context window. You may not need a graph.
- 49 files · ~52,574 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 392 nodes · 951 edges · 14 communities (12 shown, 2 thin omitted)
- Extraction: 93% EXTRACTED · 7% INFERRED · 0% AMBIGUOUS · INFERRED: 65 edges (avg confidence: 0.76)
- Token cost: 11,800 input · 4,100 output
- 696 nodes · 1591 edges · 42 communities (37 shown, 5 thin omitted)
- Extraction: 90% EXTRACTED · 10% INFERRED · 0% AMBIGUOUS · INFERRED: 163 edges (avg confidence: 0.78)
- Token cost: 0 input · 0 output
## Graph Freshness
- Built from commit: `06497299`
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
- Run `graphify update .` after code changes (no API cost).
## Community Hubs (Navigation)
- Webapp Frontend (JS)
@@ -19,31 +25,61 @@
- Store Platform Tests
- Content Analysis
- README & Config Docs
- Server Start Script
- Package Manifest
- Server Stop Script
- test_extract.py
- Auditoría · Cómo la extensión obtiene la transcripción / información de vídeos de YouTube
- api
- pipeline.py
- test_blocked_videos.py
- config.py
- setView
- Discovery-Only Scrape Design
- renderDashboardCharts
- Global Constraints
- Config
- init
- render.py
- loadChannels
- jobs.py
- Segment
- cookies.py
- discover.py
- export.py
- pipeline.py
- _channel_targets
- test_features.py
- VideoRow
- test_since_filter.py
- .reset_videos
- ._connect
- re_render_cmd
- handleFiles
## God Nodes (most connected - your core abstractions)
1. `Store` - 81 edges
2. `Segment` - 32 edges
3. `api()` - 31 edges
4. `toast()` - 29 edges
5. `Config` - 23 edges
6. `process_video()` - 19 edges
7. `JobManager` - 17 edges
8. `resolve_active_path()` - 13 edges
9. `discover_channel()` - 13 edges
10. `backfill_from_markdown()` - 13 edges
1. `Store` - 103 edges
2. `VideoRef` - 43 edges
3. `api()` - 39 edges
4. `toast()` - 38 edges
5. `Config` - 36 edges
6. `Segment` - 32 edges
7. `JobManager` - 26 edges
8. `discover_incremental()` - 21 edges
9. `process_video()` - 19 edges
10. `reconcile_markdown()` - 19 edges
## Surprising Connections (you probably didn't know these)
- `test_dashboard_aggregates()` --calls--> `Segment` [INFERRED]
tests/test_store_platform.py → src/yt_scraper/parse.py
- `test_store_and_search_segments()` --calls--> `Segment` [INFERRED]
tests/test_store_platform.py → src/yt_scraper/parse.py
- `test_store_segments_overwrites()` --calls--> `Segment` [INFERRED]
tests/test_store_platform.py → src/yt_scraper/parse.py
- `store()` --calls--> `Store` [INFERRED]
tests/test_store_platform.py → src/yt_scraper/store.py
- `test_migration_idempotent()` --calls--> `Store` [INFERRED]
tests/test_store_platform.py → src/yt_scraper/store.py
- `test_config_languages_defaults_to_dict()` --calls--> `Config` [INFERRED]
tests/test_extract.py → src/yt_scraper/config.py
- `test_config_prefer_manual_defaults_true()` --calls--> `Config` [INFERRED]
tests/test_extract.py → src/yt_scraper/config.py
- `test_export_json_csv()` --calls--> `Segment` [INFERRED]
tests/test_features.py → src/yt_scraper/parse.py
- `test_export_srt()` --calls--> `Segment` [INFERRED]
tests/test_features.py → src/yt_scraper/parse.py
- `test_term_timeline()` --calls--> `Segment` [INFERRED]
tests/test_features.py → src/yt_scraper/parse.py
## Import Cycles
- None detected.
@@ -53,63 +89,171 @@
- **FTS5 transcript search flow (proposal -> spec -> SPA view)** — opportunities_search_fts5, docs_superpowers_specs_2026_07_26_platform_design_transcript_fts5, src_yt_scraper_webapp_static_index [INFERRED 0.85]
- **Cookie auth chain (vault -> resolve_active_path -> scrape job)** — docs_superpowers_specs_2026_07_26_platform_design_cookie_vault_ux, docs_superpowers_specs_2026_07_26_platform_design_sse_job_runner, docs_superpowers_specs_2026_07_26_platform_design_cookies_bug_fix, src_yt_scraper_webapp_static_index [INFERRED 0.85]
## Communities (14 total, 2 thin omitted)
## Communities (42 total, 5 thin omitted)
### Community 0 - "Webapp Frontend (JS)"
Cohesion: 0.06
Nodes (59): activateCookie(), addChannel(), api(), axisOpts(), barOpts(), cancelScrape(), checkHealth(), closeStream() (+51 more)
Nodes (22): _armAutoHide(), blockLabel(), blockTitle(), cancelScrape(), closeClip(), closeJobWidget(), closeSidebar(), closeStats() (+14 more)
### Community 1 - "Transcript Extraction & Parsing"
Cohesion: 0.07
Nodes (57): Environment, align_chapters(), Chapter, chapters_from_info(), Section, _parse_tags(), Regenerar Markdown desde segmentos almacenados., re_render_cmd() (+49 more)
Cohesion: 0.27
Nodes (10): _iter_texts(), Path, Return [(YYYY-MM, count)] of months where `term` appears in transcripts., render_timeline_chart(), render_top_words_chart(), render_wordcloud(), term_timeline(), _tokenize() (+2 more)
### Community 2 - "Config & Discovery Pipeline"
Cohesion: 0.06
Nodes (40): APIRouter, FastAPI, _build_config(), Config, DelayConfig, load_config(), Any, Path (+32 more)
Cohesion: 0.17
Nodes (10): _clone_config(), _handle(), JobManager, _keep_ref(), Any, Single-worker scrape job runner with an in-memory event log per job (SSE-polled), Refresh the catalog without extracting or downloading video content., Refresh one channel's catalog. Incremental by default: only the newest (+2 more)
### Community 3 - "Store & Export Layer"
Cohesion: 0.07
Nodes (28): Connection, Cursor, Row, is_expired(), list_vault(), export_csv(), export_html(), export_json() (+20 more)
Cohesion: 0.10
Nodes (10): Cursor, _now_iso(), Any, Every video id already recorded for a channel — the boundary an incremen, Newest known upload date (YYYYMMDD) for a channel, or None., Refresh a channel's counters from what is actually stored. Incremental, Update only the fields explicitly passed. Preserves last_scraped and video_count, Set a video's status, optionally recording why. `no_subtitles` used to (+2 more)
### Community 4 - "CLI Command Layer"
Cohesion: 0.08
Nodes (41): analyze_cmd(), _apply_filters(), audio_cmd(), _channel_targets(), channels_add(), cli(), export_cmd(), _extract_handle() (+33 more)
Cohesion: 0.12
Nodes (24): channels_add(), cli(), _extract_handle(), _fmt_date(), _fmt_duration(), _known_channel_for(), main(), _order_pending() (+16 more)
### Community 5 - "Platform Design & Proposals"
Cohesion: 0.12
Nodes (20): Platform Implementation Plan, Platform Design Spec, Cookie drag-and-drop vault UX, cli.py cookies scope bug fix, Design language: dark data command center, Architecture: Monorepo in-package webapp (Approach A), Scope rule: No AI features, Single-threaded scrape job runner + SSE event bus (+12 more)
### Community 6 - "Segments Search & Backfill"
Cohesion: 0.26
Nodes (11): backfill_from_markdown(), parse_markdown(), ParsedMarkdown, Path, Parse all done .md files under md_root, populate segments/FTS/metadata. Idempote, search(), store_segments(), _strip_quotes() (+3 more)
Cohesion: 0.13
Nodes (17): APIRouter, FastAPI, cache_channel_avatar(), cache_thumbnail(), Thumbnail URL for a video: stored URL, else the canonical YouTube one derived fr, Download + cache a video's thumbnail to <thumbnails_dir>/<video_id>.jpg. Returns, Download + cache a channel avatar to <avatars_dir>/<channel_id>.jpg. Returns Tru, thumbnail_url_for() (+9 more)
### Community 7 - "Store Platform Tests"
Cohesion: 0.17
Nodes (5): store(), test_dashboard_aggregates(), test_migration_idempotent(), test_store_and_search_segments(), test_store_segments_overwrites()
Cohesion: 0.22
Nodes (18): Collection, discover_incremental(), IncrementalDiscovery, Fetch only the newest slice of a channel instead of paginating all of it. A, Outcome of a windowed channel sync., _fake_channel(), Windowed channel sync: only fetch what is newer than what we already have. The, Shorts the store never recorded must not keep the window widening. (+10 more)
### Community 8 - "Content Analysis"
Cohesion: 0.07
Nodes (52): Re-escanear data/markdown y hacer que la DB coincida con el disco., reconcile_cmd(), backfill_from_markdown(), parse_markdown(), ParsedMarkdown, Path, Parse all done .md files under md_root, populate segments/FTS/metadata. Idempote, Make the DB agree with what is actually on disk. `backfill_from_markdown` f (+44 more)
### Community 10 - "Server Start Script"
Cohesion: 0.38
Nodes (3): Open-Browser(), Out-Line(), Show-State()
### Community 14 - "test_extract.py"
Cohesion: 0.07
Nodes (50): Response, parse_languages(), Any, Normalise legacy list / new dict / None into ``{lang: mode}``., _coerce_languages(), describe_missing_subtitle(), _download_subtitle(), extract_video() (+42 more)
### Community 15 - "Auditoría · Cómo la extensión obtiene la transcripción / información de vídeos de YouTube"
Cohesion: 0.04
Nodes (42): Arquitectura, Comandos, Cookies, Cualquier petición HTTP a CDNs de YouTube va por `_yt_http.yt_get()`, Documentos de referencia, El Markdown es fuente de datos, no solo salida, Estados terminales y frescura (la UI tiene que reflejar DB + disco), Frontend (+34 more)
### Community 16 - "api"
Cohesion: 0.16
Nodes (29): activateCookie(), api(), checkAudio(), clearJobHistory(), copyClip(), copyText(), deleteJob(), downloadAudio() (+21 more)
### Community 17 - "pipeline.py"
Cohesion: 0.10
Nodes (19): merge_adjacent(), parse_auto_dump(), parse_json3(), parse_vtt(), _vtt_ts_to_seconds(), test_merge_adjacent(), test_parse_json3_basic(), test_parse_json3_invalid_json() (+11 more)
### Community 18 - "test_blocked_videos.py"
Cohesion: 0.23
Nodes (18): Members-only / gated videos: identified from discovery, labelled, and kept out o, Buying the membership must not leave the video permanently stranded., `unlisted` downloads perfectly well — mislabelling it would hide videos the, Rows burned into `error` before availability was captured must still be iden, Bulk runs must not spend requests on videos that cannot be fetched., _ref(), _store(), test_a_blocked_video_is_still_reachable_by_id() (+10 more)
### Community 19 - "config.py"
Cohesion: 0.24
Nodes (14): _build_config(), DelayConfig, load_config(), Incremental channel sync — how far back a routine re-scan looks. The /video, SyncConfig, YtDlpConfig, Tests for the YAML config loader. Focuses on the ``languages`` and ``prefer_man, The default must fall back to auto captions. A manual-only default silently (+6 more)
### Community 20 - "setView"
Cohesion: 0.24
Nodes (10): cycleSort(), destroyCharts(), loadFolders(), loadFormat(), loadSearch(), loadVideos(), openChannel(), resetSearch() (+2 more)
### Community 21 - "Discovery-Only Scrape Design"
Cohesion: 0.22
Nodes (8): Architecture, Discovery-Only Scrape Design, Error Handling, Existing Context, Goal, Persistence and Results, Testing, UI
### Community 22 - "renderDashboardCharts"
Cohesion: 0.36
Nodes (9): axisOpts(), barOpts(), fmtMonth(), lineOpts(), loadAnalysis(), makeChart(), renderDashboardCharts(), renderTimelineChart() (+1 more)
### Community 23 - "Global Constraints"
Cohesion: 0.25
Nodes (7): Discovery-Only Scrape Implementation Plan, Global Constraints, Task 1: Make catalog insertion counts accurate, Task 2: Add discovery-only job execution, Task 3: Expose the discovery mode through the API, Task 4: Add one-channel and all-channel UI controls, Task 5: Final verification and review
### Community 24 - "Config"
Cohesion: 0.23
Nodes (11): Config, Path, _catalog_channel(), The window is 30 wide but the channel has 200 videos — video_count must not, test_all_channel_discovery_continues_after_one_error(), test_audio_job_downloads_into_audio_directory(), test_audio_job_with_video_ids_uses_audio_runner(), test_batch_job_reports_videos_without_transcripts() (+3 more)
### Community 25 - "init"
Cohesion: 0.15
Nodes (18): addChannel(), checkHealth(), downloadAvatarsScope(), hydrateURL(), init(), jobActive(), loadChannelPending(), loadChannels() (+10 more)
### Community 26 - "render.py"
Cohesion: 0.25
Nodes (12): Environment, format_timestamp(), _make_env(), Path, quote_yaml(), render_markdown(), to_json(), test_format_timestamp_hours() (+4 more)
### Community 27 - "loadChannels"
Cohesion: 0.23
Nodes (8): Row, is_expired(), list_vault(), CookieRow, JobRow, _row_to_cookierow(), _row_to_jobrow(), _sanitize_fts()
### Community 28 - "jobs.py"
Cohesion: 0.23
Nodes (10): resolve_active_path(), _extract_handle(), _keep_ref(), Same shorts/live rules the store was populated under — see jobs._keep_ref., Discover + process pending videos for a channel, optionally on an interval., _run_once(), watch_loop(), polite_sleep() (+2 more)
### Community 29 - "Segment"
Cohesion: 0.37
Nodes (11): align_chapters(), Chapter, chapters_from_info(), Section, Segment, test_align_no_chapters(), test_align_pre_chapter_segments(), test_align_with_chapters() (+3 more)
### Community 30 - "cookies.py"
Cohesion: 0.35
Nodes (11): auto_import_dir(), cookies_dir(), delete(), import_file(), import_text(), parse_netscape(), parse_netscape_file(), Path (+3 more)
### Community 31 - "discover.py"
Cohesion: 0.27
Nodes (10): _iter_texts(), Path, Return [(YYYY-MM, count)] of months where `term` appears in transcripts., render_timeline_chart(), render_top_words_chart(), render_wordcloud(), term_timeline(), _tokenize() (+2 more)
Nodes (10): _channel_root_url(), deep_channel_avatar(), discover_channel(), _flatten_entries(), _pick_channel_avatar(), Any, Best-effort channel avatar URL from a yt-dlp channel info dict. Only source, Strip a tab suffix from a YouTube channel URL so yt-dlp extracts the channel (+2 more)
### Community 32 - "export.py"
Cohesion: 0.38
Nodes (10): export_csv(), export_html(), export_json(), export_srt(), export_srt_video(), Path, _segments_to_srt(), _srt_ts() (+2 more)
### Community 33 - "pipeline.py"
Cohesion: 0.29
Nodes (10): _normalize_date(), process_video(), Regenerate .md for done videos that have stored segments. Returns count re-rende, Extract + parse + store + render a single video. Returns final status string., re_render_videos(), _safe_dirname(), build_filename_stem(), test_build_filename_stem() (+2 more)
### Community 34 - "_channel_targets"
Cohesion: 0.20
Nodes (10): analyze_cmd(), audio_cmd(), _channel_targets(), export_cmd(), Devolver videos atascados en error/no_subtitles a 'pending' para reintentarlos., Export multi-formato., Descarga audio MP3 (requiere ffmpeg)., Analisis estadistico de contenido (frecuencia, timeline). (+2 more)
### Community 35 - "test_features.py"
Cohesion: 0.20
Nodes (5): store(), test_export_json_csv(), test_export_srt(), test_term_timeline(), test_word_frequency()
### Community 36 - "VideoRow"
Cohesion: 0.33
Nodes (4): Why this video can never be fetched, or None if it can. Prefers the dis, Pending videos, excluding ones discovery already told us we cannot fetch, _row_to_videorow(), VideoRow
### Community 37 - "test_since_filter.py"
Cohesion: 0.52
Nodes (6): _apply_filters(), `--since` / the scrape form's date filter must not eat undated entries. yt-dlp', _ref(), test_since_keeps_entries_with_no_upload_date(), test_since_still_drops_entries_that_are_provably_older(), test_without_since_nothing_is_dropped_on_date_grounds()
### Community 40 - "re_render_cmd"
Cohesion: 0.50
Nodes (4): _parse_tags(), Regenerar Markdown desde segmentos almacenados., re_render_cmd(), _safe_dirname()
### Community 41 - "handleFiles"
Cohesion: 0.67
Nodes (3): handleDrop(), handleFiles(), uploadCookies()
## Knowledge Gaps
- **10 isolated node(s):** `yt-channel-scraper`, `OPPORTUNITIES.md - extension audit`, `Design language: dark data command center`, `yt-dlp InnerTube mechanism (ANDROID/IOS/WEB clients)`, `Feature proposal: search (FTS5 transcript search)` (+5 more)
- **58 isolated node(s):** `yt-channel-scraper`, `Qué es esto`, `Comandos`, `Orientación antes de leer código`, `Tres superficies, un solo pipeline` (+53 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **2 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
- **5 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **Why does `Store` connect `Store & Export Layer` to `Transcript Extraction & Parsing`, `Config & Discovery Pipeline`, `CLI Command Layer`, `Segments Search & Backfill`, `Store Platform Tests`, `Content Analysis`?**
_High betweenness centrality (0.194) - this node is a cross-community bridge._
- **Why does `Segment` connect `Transcript Extraction & Parsing` to `CLI Command Layer`, `Segments Search & Backfill`, `Store Platform Tests`?**
_High betweenness centrality (0.057) - this node is a cross-community bridge._
- **Why does `Config` connect `Config & Discovery Pipeline` to `Transcript Extraction & Parsing`, `CLI Command Layer`?**
_High betweenness centrality (0.024) - this node is a cross-community bridge._
- **Are the 4 inferred relationships involving `Store` (e.g. with `ParsedMarkdown` and `store()`) actually correct?**
_`Store` has 4 INFERRED edges - model-reasoned connections that need verification._
- **Are the 17 inferred relationships involving `Segment` (e.g. with `Chapter` and `Section`) actually correct?**
_`Segment` has 17 INFERRED edges - model-reasoned connections that need verification._
- **What connects `yt-channel-scraper`, `OPPORTUNITIES.md - extension audit`, `Design language: dark data command center` to the rest of the system?**
_10 weakly-connected nodes found - possible documentation gaps or missing edges._
- **Should `Webapp Frontend (JS)` be split into smaller, more focused modules?**
_Cohesion score 0.062317429406037 - nodes in this community are weakly interconnected._
- **Why does `Store` connect `Store & Export Layer` to `export.py`, `Transcript Extraction & Parsing`, `pipeline.py`, `Config & Discovery Pipeline`, `CLI Command Layer`, `VideoRow`, `.reset_videos`, `._connect`, `Content Analysis`, `Segments Search & Backfill`, `test_features.py`, `pipeline.py`, `test_blocked_videos.py`, `Config`, `loadChannels`, `jobs.py`, `cookies.py`?**
_High betweenness centrality (0.162) - this node is a cross-community bridge._
- **Why does `VideoRef` connect `Content Analysis` to `Store & Export Layer`, `CLI Command Layer`, `test_features.py`, `test_since_filter.py`, `Store Platform Tests`, `pipeline.py`, `test_blocked_videos.py`, `Config`, `loadChannels`, `jobs.py`, `discover.py`?**
_High betweenness centrality (0.053) - this node is a cross-community bridge._
- **Why does `Segment` connect `Segment` to `pipeline.py`, `test_features.py`, `CLI Command Layer`, `re_render_cmd`, `Content Analysis`, `test_extract.py`, `pipeline.py`?**
_High betweenness centrality (0.031) - this node is a cross-community bridge._
- **Are the 14 inferred relationships involving `Store` (e.g. with `ParsedMarkdown` and `_store()`) actually correct?**
_`Store` has 14 INFERRED edges - model-reasoned connections that need verification._
- **Are the 31 inferred relationships involving `VideoRef` (e.g. with `IncrementalDiscovery` and `store()`) actually correct?**
_`VideoRef` has 31 INFERRED edges - model-reasoned connections that need verification._
- **Are the 11 inferred relationships involving `Config` (e.g. with `test_config_languages_defaults_to_dict()` and `test_config_prefer_manual_defaults_true()`) actually correct?**
_`Config` has 11 INFERRED edges - model-reasoned connections that need verification._
- **What connects `yt-channel-scraper`, `Qué es esto`, `Comandos` to the rest of the system?**
_58 weakly-connected nodes found - possible documentation gaps or missing edges._
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "d_yt_channel_scraper_scripts_stop_server_ps1", "label": "stop-server.ps1", "file_type": "code", "source_file": "scripts/stop-server.ps1", "source_location": "L1"}, {"id": "d_yt_channel_scraper_scripts_stop_server_out_line", "label": "Out-Line()", "file_type": "code", "source_file": "scripts/stop-server.ps1", "source_location": "L5"}, {"id": "d_yt_channel_scraper_scripts_stop_server_test_portopen", "label": "Test-PortOpen()", "file_type": "code", "source_file": "scripts/stop-server.ps1", "source_location": "L13"}, {"id": "d_yt_channel_scraper_scripts_stop_server_kill_portowner", "label": "Kill-PortOwner()", "file_type": "code", "source_file": "scripts/stop-server.ps1", "source_location": "L24"}], "edges": [{"source": "d_yt_channel_scraper_scripts_stop_server_ps1", "target": "d_yt_channel_scraper_scripts_stop_server_out_line", "relation": "contains", "confidence": "EXTRACTED", "source_file": "scripts/stop-server.ps1", "source_location": "L5", "weight": 1.0}, {"source": "d_yt_channel_scraper_scripts_stop_server_ps1", "target": "d_yt_channel_scraper_scripts_stop_server_test_portopen", "relation": "contains", "confidence": "EXTRACTED", "source_file": "scripts/stop-server.ps1", "source_location": "L13", "weight": 1.0}, {"source": "d_yt_channel_scraper_scripts_stop_server_ps1", "target": "d_yt_channel_scraper_scripts_stop_server_kill_portowner", "relation": "contains", "confidence": "EXTRACTED", "source_file": "scripts/stop-server.ps1", "source_location": "L24", "weight": 1.0}, {"source": "d_yt_channel_scraper_scripts_stop_server_kill_portowner", "target": "d_yt_channel_scraper_scripts_stop_server_out_line", "relation": "calls", "confidence": "EXTRACTED", "source_file": "scripts/stop-server.ps1", "source_location": "L27", "weight": 1.0}], "raw_calls": [{"caller_nid": "d_yt_channel_scraper_scripts_stop_server_out_line", "callee": "Write-Host", "is_member_call": false, "source_file": "scripts/stop-server.ps1", "source_location": "L6"}, {"caller_nid": "d_yt_channel_scraper_scripts_stop_server_out_line", "callee": "Write-Host", "is_member_call": false, "source_file": "scripts/stop-server.ps1", "source_location": "L7"}, {"caller_nid": "d_yt_channel_scraper_scripts_stop_server_test_portopen", "callee": "New-Object", "is_member_call": false, "source_file": "scripts/stop-server.ps1", "source_location": "L14"}, {"caller_nid": "d_yt_channel_scraper_scripts_stop_server_kill_portowner", "callee": "Get-NetTCPConnection", "is_member_call": false, "source_file": "scripts/stop-server.ps1", "source_location": "L25"}, {"caller_nid": "d_yt_channel_scraper_scripts_stop_server_kill_portowner", "callee": "ForEach-Object", "is_member_call": false, "source_file": "scripts/stop-server.ps1", "source_location": "L26"}, {"caller_nid": "d_yt_channel_scraper_scripts_stop_server_kill_portowner", "callee": "Stop-Process", "is_member_call": false, "source_file": "scripts/stop-server.ps1", "source_location": "L28"}]}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "d_yt_channel_scraper_src_yt_scraper_yt_http_py", "label": "_yt_http.py", "file_type": "code", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L1"}, {"id": "d_yt_channel_scraper_src_yt_scraper_yt_http_yt_headers", "label": "yt_headers()", "file_type": "code", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L33", "_callable": true}, {"id": "d_yt_channel_scraper_src_yt_scraper_yt_http_yt_get", "label": "yt_get()", "file_type": "code", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L40", "_callable": true}, {"id": "any", "label": "Any", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "D:\\yt-channel-scraper\\src\\yt_scraper\\_yt_http.py"}, {"id": "response", "label": "Response", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "D:\\yt-channel-scraper\\src\\yt_scraper\\_yt_http.py"}, {"id": "d_yt_channel_scraper_src_yt_scraper_yt_http_rationale_1", "label": "Shared HTTP helpers for talking to YouTube CDNs. Single source of truth for the", "file_type": "rationale", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L1"}, {"id": "d_yt_channel_scraper_src_yt_scraper_yt_http_rationale_34", "label": "Return a copy of the YouTube CDN headers merged with ``extra``.", "file_type": "rationale", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L34"}, {"id": "d_yt_channel_scraper_src_yt_scraper_yt_http_rationale_43", "label": "GET ``url`` with the shared YouTube CDN headers. Centralising this lets eve", "file_type": "rationale", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L43"}], "edges": [{"source": "d_yt_channel_scraper_src_yt_scraper_yt_http_py", "target": "typing", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L10", "weight": 1.0}, {"source": "d_yt_channel_scraper_src_yt_scraper_yt_http_py", "target": "requests", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L12", "weight": 1.0}, {"source": "d_yt_channel_scraper_src_yt_scraper_yt_http_py", "target": "d_yt_channel_scraper_src_yt_scraper_yt_http_yt_headers", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L33", "weight": 1.0}, {"source": "d_yt_channel_scraper_src_yt_scraper_yt_http_py", "target": "d_yt_channel_scraper_src_yt_scraper_yt_http_yt_get", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L40", "weight": 1.0}, {"source": "d_yt_channel_scraper_src_yt_scraper_yt_http_yt_get", "target": "any", "relation": "references", "context": "generic_arg", "confidence": "EXTRACTED", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L40", "weight": 1.0}, {"source": "d_yt_channel_scraper_src_yt_scraper_yt_http_yt_get", "target": "response", "relation": "references", "context": "return_type", "confidence": "EXTRACTED", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L40", "weight": 1.0}, {"source": "d_yt_channel_scraper_src_yt_scraper_yt_http_yt_get", "target": "d_yt_channel_scraper_src_yt_scraper_yt_http_yt_headers", "relation": "calls", "context": "call", "confidence": "EXTRACTED", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L49", "weight": 1.0}, {"source": "d_yt_channel_scraper_src_yt_scraper_yt_http_rationale_1", "target": "d_yt_channel_scraper_src_yt_scraper_yt_http_py", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L1", "weight": 1.0}, {"source": "d_yt_channel_scraper_src_yt_scraper_yt_http_rationale_34", "target": "d_yt_channel_scraper_src_yt_scraper_yt_http_yt_headers", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L34", "weight": 1.0}, {"source": "d_yt_channel_scraper_src_yt_scraper_yt_http_rationale_43", "target": "d_yt_channel_scraper_src_yt_scraper_yt_http_yt_get", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L43", "weight": 1.0}], "raw_calls": [{"caller_nid": "d_yt_channel_scraper_src_yt_scraper_yt_http_yt_headers", "callee": "_YT_HEADERS", "is_member_call": false, "indirect": true, "context": "argument", "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L37"}, {"caller_nid": "d_yt_channel_scraper_src_yt_scraper_yt_http_yt_get", "callee": "get", "is_member_call": true, "source_file": "src/yt_scraper/_yt_http.py", "source_location": "L49", "receiver": "requests"}]}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "d_yt_channel_scraper_scripts_start_server_ps1", "label": "start-server.ps1", "file_type": "code", "source_file": "scripts/start-server.ps1", "source_location": "L1"}, {"id": "d_yt_channel_scraper_scripts_start_server_out_line", "label": "Out-Line()", "file_type": "code", "source_file": "scripts/start-server.ps1", "source_location": "L10"}, {"id": "d_yt_channel_scraper_scripts_start_server_open_browser", "label": "Open-Browser()", "file_type": "code", "source_file": "scripts/start-server.ps1", "source_location": "L17"}, {"id": "d_yt_channel_scraper_scripts_start_server_test_portopen", "label": "Test-PortOpen()", "file_type": "code", "source_file": "scripts/start-server.ps1", "source_location": "L31"}, {"id": "d_yt_channel_scraper_scripts_start_server_get_serverhealth", "label": "Get-ServerHealth()", "file_type": "code", "source_file": "scripts/start-server.ps1", "source_location": "L42"}, {"id": "d_yt_channel_scraper_scripts_start_server_is_pidalive", "label": "Is-PidAlive()", "file_type": "code", "source_file": "scripts/start-server.ps1", "source_location": "L50"}, {"id": "d_yt_channel_scraper_scripts_start_server_show_state", "label": "Show-State()", "file_type": "code", "source_file": "scripts/start-server.ps1", "source_location": "L56"}], "edges": [{"source": "d_yt_channel_scraper_scripts_start_server_ps1", "target": "d_yt_channel_scraper_scripts_start_server_out_line", "relation": "contains", "confidence": "EXTRACTED", "source_file": "scripts/start-server.ps1", "source_location": "L10", "weight": 1.0}, {"source": "d_yt_channel_scraper_scripts_start_server_ps1", "target": "d_yt_channel_scraper_scripts_start_server_open_browser", "relation": "contains", "confidence": "EXTRACTED", "source_file": "scripts/start-server.ps1", "source_location": "L17", "weight": 1.0}, {"source": "d_yt_channel_scraper_scripts_start_server_ps1", "target": "d_yt_channel_scraper_scripts_start_server_test_portopen", "relation": "contains", "confidence": "EXTRACTED", "source_file": "scripts/start-server.ps1", "source_location": "L31", "weight": 1.0}, {"source": "d_yt_channel_scraper_scripts_start_server_ps1", "target": "d_yt_channel_scraper_scripts_start_server_get_serverhealth", "relation": "contains", "confidence": "EXTRACTED", "source_file": "scripts/start-server.ps1", "source_location": "L42", "weight": 1.0}, {"source": "d_yt_channel_scraper_scripts_start_server_ps1", "target": "d_yt_channel_scraper_scripts_start_server_is_pidalive", "relation": "contains", "confidence": "EXTRACTED", "source_file": "scripts/start-server.ps1", "source_location": "L50", "weight": 1.0}, {"source": "d_yt_channel_scraper_scripts_start_server_ps1", "target": "d_yt_channel_scraper_scripts_start_server_show_state", "relation": "contains", "confidence": "EXTRACTED", "source_file": "scripts/start-server.ps1", "source_location": "L56", "weight": 1.0}, {"source": "d_yt_channel_scraper_scripts_start_server_open_browser", "target": "d_yt_channel_scraper_scripts_start_server_out_line", "relation": "calls", "confidence": "EXTRACTED", "source_file": "scripts/start-server.ps1", "source_location": "L22", "weight": 1.0}, {"source": "d_yt_channel_scraper_scripts_start_server_show_state", "target": "d_yt_channel_scraper_scripts_start_server_out_line", "relation": "calls", "confidence": "EXTRACTED", "source_file": "scripts/start-server.ps1", "source_location": "L57", "weight": 1.0}], "raw_calls": [{"caller_nid": "d_yt_channel_scraper_scripts_start_server_out_line", "callee": "Write-Host", "is_member_call": false, "source_file": "scripts/start-server.ps1", "source_location": "L11"}, {"caller_nid": "d_yt_channel_scraper_scripts_start_server_out_line", "callee": "Write-Host", "is_member_call": false, "source_file": "scripts/start-server.ps1", "source_location": "L12"}, {"caller_nid": "d_yt_channel_scraper_scripts_start_server_open_browser", "callee": "Start-Process", "is_member_call": false, "source_file": "scripts/start-server.ps1", "source_location": "L19"}, {"caller_nid": "d_yt_channel_scraper_scripts_start_server_test_portopen", "callee": "New-Object", "is_member_call": false, "source_file": "scripts/start-server.ps1", "source_location": "L32"}, {"caller_nid": "d_yt_channel_scraper_scripts_start_server_get_serverhealth", "callee": "Invoke-WebRequest", "is_member_call": false, "source_file": "scripts/start-server.ps1", "source_location": "L44"}, {"caller_nid": "d_yt_channel_scraper_scripts_start_server_is_pidalive", "callee": "Get-Process", "is_member_call": false, "source_file": "scripts/start-server.ps1", "source_location": "L52"}, {"caller_nid": "d_yt_channel_scraper_scripts_start_server_show_state", "callee": "Get-Date", "is_member_call": false, "source_file": "scripts/start-server.ps1", "source_location": "L57"}]}
+1
View File
@@ -0,0 +1 @@
1787443350.5198534
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+12669 -1545
View File
File diff suppressed because it is too large Load Diff
+121 -51
View File
@@ -5,14 +5,14 @@
"semantic_hash": "f80dc007b3b67c7f7a78d9df01a81ead"
},
"scripts/start-server.ps1": {
"mtime": 1785130613.533591,
"ast_hash": "9baf397df6c14b7917ca59fbe6df61cc",
"semantic_hash": "9baf397df6c14b7917ca59fbe6df61cc"
"mtime": 1785132936.4055703,
"ast_hash": "7390a228e676bff301ae85c5a4e7449e",
"semantic_hash": ""
},
"scripts/stop-server.ps1": {
"mtime": 1785127403.2329483,
"ast_hash": "4398501c202a3eb624fb439f6d03fcf5",
"semantic_hash": "4398501c202a3eb624fb439f6d03fcf5"
"mtime": 1785132762.2959402,
"ast_hash": "4a62db3fa3dca6b7109fcaadc1219226",
"semantic_hash": ""
},
"src/yt_scraper/__init__.py": {
"mtime": 1785120608.3336751,
@@ -30,14 +30,14 @@
"semantic_hash": "1bf51b7c13486b9db9bcc3420fba2593"
},
"src/yt_scraper/cli.py": {
"mtime": 1785126572.0575886,
"ast_hash": "9734cedf7c1e045e1ab0e4a102860e29",
"semantic_hash": "9734cedf7c1e045e1ab0e4a102860e29"
"mtime": 1785561823.2458293,
"ast_hash": "100604834f369047b55641bd327333d0",
"semantic_hash": ""
},
"src/yt_scraper/config.py": {
"mtime": 1785120620.335521,
"ast_hash": "2f3c8f7768a942e12c0a9e41b54891be",
"semantic_hash": "2f3c8f7768a942e12c0a9e41b54891be"
"mtime": 1785561416.2574291,
"ast_hash": "712dddce27149cb3a5ceb34f78fac2fd",
"semantic_hash": ""
},
"src/yt_scraper/cookies.py": {
"mtime": 1785126417.4218228,
@@ -45,9 +45,9 @@
"semantic_hash": "dd5ec44bb4c6e6375be80f21307fc73d"
},
"src/yt_scraper/discover.py": {
"mtime": 1785120708.331971,
"ast_hash": "8db06d0b131575f709b55467eabdc2a9",
"semantic_hash": "8db06d0b131575f709b55467eabdc2a9"
"mtime": 1785569683.6527412,
"ast_hash": "6b626a24ae81406ea549e9989c9f5d5b",
"semantic_hash": ""
},
"src/yt_scraper/export.py": {
"mtime": 1785126439.6829402,
@@ -55,14 +55,14 @@
"semantic_hash": "f1cff31fb1004f08e997655f838e3a58"
},
"src/yt_scraper/extract.py": {
"mtime": 1785122183.7294595,
"ast_hash": "3e2179db2f7fd316d2b3acedee536086",
"semantic_hash": "3e2179db2f7fd316d2b3acedee536086"
"mtime": 1785561382.7161057,
"ast_hash": "a46b96123cfef40a10436e6e65b45d4b",
"semantic_hash": ""
},
"src/yt_scraper/monitor.py": {
"mtime": 1785126496.288271,
"ast_hash": "a64188f938dc4f8917335ef41d333ead",
"semantic_hash": "a64188f938dc4f8917335ef41d333ead"
"mtime": 1785555591.7611978,
"ast_hash": "e7948e61b74b84b246708518f02dbcae",
"semantic_hash": ""
},
"src/yt_scraper/parse.py": {
"mtime": 1785120665.3384771,
@@ -70,9 +70,9 @@
"semantic_hash": "25354365ac1ab52f1561c97256573806"
},
"src/yt_scraper/pipeline.py": {
"mtime": 1785131195.7311583,
"ast_hash": "ebce1b294140bf40f809848ef280c290",
"semantic_hash": "ebce1b294140bf40f809848ef280c290"
"mtime": 1785569737.341973,
"ast_hash": "4e22e69083b15c4b937fca406134539c",
"semantic_hash": ""
},
"src/yt_scraper/ratelimit.py": {
"mtime": 1785120650.3795395,
@@ -85,14 +85,14 @@
"semantic_hash": "ff83764f3a8c8874557993e11eab1f89"
},
"src/yt_scraper/segments.py": {
"mtime": 1785128385.6652262,
"ast_hash": "09c7da35bc09a3f75fd0a627c0534746",
"semantic_hash": "09c7da35bc09a3f75fd0a627c0534746"
"mtime": 1785562183.2376134,
"ast_hash": "902d851e321b83c99d4cae30c1ae39fc",
"semantic_hash": ""
},
"src/yt_scraper/store.py": {
"mtime": 1785131583.548138,
"ast_hash": "9a3d4286214aa54ae4ac4df2097b643d",
"semantic_hash": "9a3d4286214aa54ae4ac4df2097b643d"
"mtime": 1785569922.3510046,
"ast_hash": "ea9a69606929df7ff0508814f2733204",
"semantic_hash": ""
},
"src/yt_scraper/webapp/__init__.py": {
"mtime": 1785126827.4957752,
@@ -100,24 +100,24 @@
"semantic_hash": "d41d8cd98f00b204e9800998ecf8427e"
},
"src/yt_scraper/webapp/api.py": {
"mtime": 1785131595.9914868,
"ast_hash": "e64174f04d6eab0747b1d2a7c2a96a01",
"semantic_hash": "e64174f04d6eab0747b1d2a7c2a96a01"
"mtime": 1785569846.188889,
"ast_hash": "e63b87bc3804f92f9078cdf36d7181da",
"semantic_hash": ""
},
"src/yt_scraper/webapp/app.py": {
"mtime": 1785126888.8032887,
"ast_hash": "e0b1925b4318305dcf746d360373ff50",
"semantic_hash": "e0b1925b4318305dcf746d360373ff50"
"mtime": 1785562107.3107448,
"ast_hash": "80e375becb41e202f78239138252c5c8",
"semantic_hash": ""
},
"src/yt_scraper/webapp/jobs.py": {
"mtime": 1785131211.0397103,
"ast_hash": "8b6c80001ff8c95eaaa16f7b61d1f207",
"semantic_hash": "8b6c80001ff8c95eaaa16f7b61d1f207"
"mtime": 1785556090.2023566,
"ast_hash": "45ba7f10b13b847c213f04441a5e741d",
"semantic_hash": ""
},
"src/yt_scraper/webapp/static/app.js": {
"mtime": 1785131664.8792574,
"ast_hash": "f6b081fadc5884d379152abbd1e59700",
"semantic_hash": "f6b081fadc5884d379152abbd1e59700"
"mtime": 1785569873.551512,
"ast_hash": "0f4fc27cfdde0a10ef3c568774b199a2",
"semantic_hash": ""
},
"tests/test_chapters.py": {
"mtime": 1785120789.3300896,
@@ -140,9 +140,9 @@
"semantic_hash": "27125960e235813724fd669001faab59"
},
"tests/test_store_platform.py": {
"mtime": 1785126662.4772756,
"ast_hash": "bad13dcf37be7a414ffae8018c29e55b",
"semantic_hash": "bad13dcf37be7a414ffae8018c29e55b"
"mtime": 1785194588.4186954,
"ast_hash": "44069db75a444906fb5001880dedf180",
"semantic_hash": ""
},
".opencode/agent/webapp-builder.md": {
"mtime": 1785126783.7152567,
@@ -165,9 +165,9 @@
"semantic_hash": "a0a8e6b62a991fce5d6c58171f80075e"
},
"config.example.yaml": {
"mtime": 1785120602.4114335,
"ast_hash": "415b0fc8e71ecc305d21e9c3c08d585a",
"semantic_hash": "415b0fc8e71ecc305d21e9c3c08d585a"
"mtime": 1785561451.814817,
"ast_hash": "43661d5c00d05c922bcf884e8ac707c3",
"semantic_hash": ""
},
"docs/superpowers/plans/2026-07-26-platform-build.md": {
"mtime": 1785126240.4211702,
@@ -180,8 +180,78 @@
"semantic_hash": "9b85f02fd45c93cdabfd2e1c6d1e0c9e"
},
"src/yt_scraper/webapp/static/index.html": {
"mtime": 1785131695.7653384,
"ast_hash": "13591b7c8c662d8e7c2540f3032ae26d",
"semantic_hash": "13591b7c8c662d8e7c2540f3032ae26d"
"mtime": 1785570599.948749,
"ast_hash": "46b1cb57281f7683acc5b39714d74073",
"semantic_hash": ""
},
"src/yt_scraper/_yt_http.py": {
"mtime": 1785134945.1512043,
"ast_hash": "8af224580322df5aeeba10062592d961",
"semantic_hash": ""
},
"tests/test_config.py": {
"mtime": 1785561477.3907576,
"ast_hash": "46f3eefb24bcf44535c17977ac175509",
"semantic_hash": ""
},
"tests/test_discover_incremental.py": {
"mtime": 1785555704.1061945,
"ast_hash": "e1c382a9b8f5c927a85d67814d3dbb09",
"semantic_hash": ""
},
"tests/test_extract.py": {
"mtime": 1785561483.422817,
"ast_hash": "9949ef4f6e7fe8cbdf12bc8d1dc71e3f",
"semantic_hash": ""
},
"tests/test_store_sync_watermark.py": {
"mtime": 1785555725.6495814,
"ast_hash": "9f9943f5b914078cee49bf4aaa060564",
"semantic_hash": ""
},
"tests/test_webapp_jobs.py": {
"mtime": 1785555746.4912646,
"ast_hash": "7688c701256ff0cdd2a7d78d7090c8b3",
"semantic_hash": ""
},
"CLAUDE.md": {
"mtime": 1785570018.086969,
"ast_hash": "e478d29b66549d4a24cdd0f91ddfc2aa",
"semantic_hash": ""
},
"YOUTUBE-TRANSCRIPT-AUDIT.md": {
"mtime": 1785116715.5118847,
"ast_hash": "67c5b7e3b4661ca8c8a7280e63b13ba9",
"semantic_hash": ""
},
"docs/superpowers/plans/2026-07-27-discovery-only-scrape.md": {
"mtime": 1785192916.5353482,
"ast_hash": "3cf41d6331bd67e39ccd96b0e6138cf2",
"semantic_hash": ""
},
"docs/superpowers/specs/2026-07-27-discovery-only-scrape-design.md": {
"mtime": 1785192898.2889626,
"ast_hash": "529b39e9bd2adcafd17a2dc30263281c",
"semantic_hash": ""
},
"tests/test_recovery.py": {
"mtime": 1785569307.786051,
"ast_hash": "53f25aeda88cbf3755f45f2377970b62",
"semantic_hash": ""
},
"tests/test_since_filter.py": {
"mtime": 1785556104.7475204,
"ast_hash": "1d827c61156ab488e838dac91261624f",
"semantic_hash": ""
},
".claude/settings.json": {
"mtime": 1785569155.4443069,
"ast_hash": "dc072413449915d630bc773c9fb57dc7",
"semantic_hash": ""
},
"tests/test_blocked_videos.py": {
"mtime": 1785569898.4683661,
"ast_hash": "674b087c46f1ee8de0e650295f0cb8cd",
"semantic_hash": ""
}
}