chore(repo): datos privados fuera de git + line-endings normalizados

- .gitignore: data/* (canales, BD, markdown, media), cookies/ (sesiones de YouTube),
  config.yaml real (usar config.example.yaml), graphify-out/, .superpowers/, .env,
  venvs, estado local de agentes
- untrack de graphify-out (102 archivos de cache regenerable), config.yaml y
  .claude/settings.json (estado de maquina local); los archivos se conservan en disco
- .gitattributes: LF en todo el texto, CRLF solo para .bat/.ps1, binarios marcados
  (fin de los warnings LF/CRLF en cada diff)
- data/.gitkeep documenta el proposito del directorio
This commit is contained in:
urieljareth
2026-09-10 00:32:55 -06:00
parent 450aee216d
commit c693b20e19
107 changed files with 70 additions and 76620 deletions
-7
View File
@@ -1,7 +0,0 @@
{
"permissions": {
"allow": [
"PowerShell(python \"C:\\\\Users\\\\URIELJ~1\\\\AppData\\\\Local\\\\Temp\\\\claude\\\\d--yt-channel-scraper\\\\22447059-a4b2-482a-92ce-78bd6f3f9010\\\\scratchpad\\\\probe_failing.py\")"
]
}
}
+33
View File
@@ -0,0 +1,33 @@
# Normalizar todo el texto a LF en el repo (checkout nativo por OS controlado abajo)
* text=auto eol=lf
# Extensiones con LF forzado
*.py text eol=lf
*.js text eol=lf
*.css text eol=lf
*.html text eol=lf
*.md text eol=lf
*.yaml text eol=lf
*.yml text eol=lf
*.toml text eol=lf
*.json text eol=lf
*.sh text eol=lf
*.j2 text eol=lf
*.bat text eol=crlf
*.ps1 text eol=crlf
.gitattributes text eol=lf
.gitignore text eol=lf
Makefile text eol=lf
# Binarios
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.db binary
*.mp3 binary
*.mp4 binary
*.webm binary
*.woff binary
*.woff2 binary
+35 -4
View File
@@ -1,3 +1,4 @@
# --- Python ---
__pycache__/ __pycache__/
*.py[cod] *.py[cod]
*.egg-info/ *.egg-info/
@@ -7,14 +8,44 @@ dist/
.pytest_cache/ .pytest_cache/
.coverage .coverage
htmlcov/ htmlcov/
data/
cookies/ # --- Entornos virtuales ---
.run/
.venv/ .venv/
.venv-*/
venv/ venv/
# --- Datos del usuario: NUNCA versionar (canal(es), contenido scrapeado, BD, media) ---
data/*
!data/.gitkeep
# --- Cookies de sesión de YouTube: sensibles, nunca versionar ---
cookies/
*.cookies.txt
cookies.txt
# --- Config real del usuario (usar config.example.yaml como plantilla) ---
config.yaml
.env
.env.*
# --- Estado de runtime del servidor ---
.run/
*.log *.log
# opencode runtime state (keep agent/ + goal definitions, exclude loop/session state) # --- Salida regenerable de herramientas de análisis (graphify) ---
graphify-out/
# --- Estado local de agentes IA ---
.superpowers/
.claude/
.opencode/goals/state.json
.opencode/goals/state.json .opencode/goals/state.json
.opencode/goals/state.json.ledger.jsonl .opencode/goals/state.json.ledger.jsonl
.opencode/opencode-loop/ .opencode/opencode-loop/
.opencode/node_modules/
# --- macOS / editors ---
.DS_Store
Thumbs.db
.idea/
.vscode/
-67
View File
@@ -1,67 +0,0 @@
channel_url: "https://www.youtube.com/@Nostal-Vlad/videos"
languages:
es: any
es-419: any
en: any
prefer_manual: true
include_shorts: false
include_live: true
min_duration_sec: 30
# --------------------------------------------------------------------------
# Ritmo contra YouTube.
#
# El unico techo publicado que existe es el de la wiki de yt-dlp: una sesion
# sin cuenta aguanta ~300 videos/hora (~1000 peticiones/hora) antes del muro
# de bot. Google no documenta limites para acceso sin API, asi que ese numero
# es la referencia menos mala. Los valores de abajo apuntan deliberadamente
# por debajo.
#
# Cuentas: un video cuesta 3 peticiones a youtube.com
# 1. la pagina /watch
# 2. la llamada InnerTube /youtubei/v1/player (separada de la anterior por
# sleep_subrequests)
# 3. /api/timedtext, la transcripcion
# (la miniatura va a i.ytimg.com, que es CDN estatico y no cuenta contra esto)
#
# Esas 3 son irreducibles: se midio si se podia bajar de ahi restringiendo
# player_client o saltando la pagina /watch, y no se puede. Con solo
# web_safari, o con player_skip=webpage, yt-dlp devuelve CERO pistas de
# subtitulos y pierde duration/channel_id/tags. El default de yt-dlp
# (android_vr + web_safari, 2 peticiones) ya es el optimo. No re-litigar.
#
# Medido con estos valores: 12.4 s/video => ~870 peticiones/hora, ~290
# videos/hora. Por debajo del techo, con margen.
#
# Si vas con prisa y aceptas el riesgo, baja delay.min/max_seconds y
# min_request_interval. Si aun asi te topas con el muro, subelos:
# min_request_interval es el unico ajuste que aplica a la vez a los jobs y
# a los /api/tools/*, que corren fuera del JobManager.
# --------------------------------------------------------------------------
delay:
min_seconds: 5.0
max_seconds: 10.0
backoff_base: 2.0 # tras un rate-limit: min(2 * 2**n + jitter, cap)
backoff_cap: 60.0
throttle_threshold: 3 # 3 rate-limits seguidos y el job para
min_request_interval: 2.5
audio_rate_limit: 0
yt_dlp:
retries: 10
sleep_subrequests: 3.0 # -> sleep_interval_requests de yt-dlp
extractor_retries: 3
socket_timeout: 30.0
sync:
incremental: true
window: 30
max_window: 300
overlap: 3
database_path: "data/state.db"
output_dir: "data/markdown"
template_path: "templates/video.md.j2"
filename_template: "{upload_date}_{slug}"
+2
View File
@@ -0,0 +1,2 @@
# data/ contiene la BD SQLite, notas markdown, miniaturas, audio y video de los canales.
# Todo su contenido es privado y esta ignorado por git (ver .gitignore).
-44
View File
@@ -1,44 +0,0 @@
{
"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
View File
@@ -1 +0,0 @@
C:\Users\Uriel Jareth\AppData\Local\Programs\Python\Python312\python.exe
-1
View File
@@ -1 +0,0 @@
.
@@ -1,27 +0,0 @@
{
"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
@@ -1,182 +0,0 @@
# 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
@@ -1,12 +0,0 @@
{
"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
@@ -1,237 +0,0 @@
{
"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": ""
}
}
@@ -1,26 +0,0 @@
{
"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
@@ -1,177 +0,0 @@
# 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
@@ -1,12 +0,0 @@
{
"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
@@ -1,252 +0,0 @@
{
"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": ""
}
}
-259
View File
@@ -1,259 +0,0 @@
# Graph Report - yt-channel-scraper (2026-08-01)
## Corpus Check
- 49 files · ~52,574 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 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)
- 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
- 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` - 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_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.
## 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 (42 total, 5 thin omitted)
### Community 0 - "Webapp Frontend (JS)"
Cohesion: 0.06
Nodes (22): _armAutoHide(), blockLabel(), blockTitle(), cancelScrape(), closeClip(), closeJobWidget(), closeSidebar(), closeStats() (+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.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.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.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.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.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): _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
- **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.
- **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 `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
@@ -1 +0,0 @@
{"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_open_browser", "label": "Open-Browser()", "file_type": "code", "source_file": "scripts/start-server.ps1", "source_location": "L6"}], "edges": [{"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": "L6", "weight": 1.0}], "raw_calls": [{"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": "L9"}, {"caller_nid": "d_yt_channel_scraper_scripts_start_server_open_browser", "callee": "Write-Host", "is_member_call": false, "source_file": "scripts/start-server.ps1", "source_location": "L18"}, {"caller_nid": "d_yt_channel_scraper_scripts_start_server_open_browser", "callee": "Write-Host", "is_member_call": false, "source_file": "scripts/start-server.ps1", "source_location": "L19"}]}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
{"nodes": [{"id": "d_yt_channel_scraper_src_yt_scraper_ratelimit_py", "label": "ratelimit.py", "file_type": "code", "source_file": "src/yt_scraper/ratelimit.py", "source_location": "L1"}, {"id": "d_yt_channel_scraper_src_yt_scraper_ratelimit_polite_sleep", "label": "polite_sleep()", "file_type": "code", "source_file": "src/yt_scraper/ratelimit.py", "source_location": "L7", "_callable": true}, {"id": "d_yt_channel_scraper_src_yt_scraper_ratelimit_backoff_sleep", "label": "backoff_sleep()", "file_type": "code", "source_file": "src/yt_scraper/ratelimit.py", "source_location": "L12", "_callable": true}], "edges": [{"source": "d_yt_channel_scraper_src_yt_scraper_ratelimit_py", "target": "random", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/yt_scraper/ratelimit.py", "source_location": "L3", "weight": 1.0}, {"source": "d_yt_channel_scraper_src_yt_scraper_ratelimit_py", "target": "time", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/yt_scraper/ratelimit.py", "source_location": "L4", "weight": 1.0}, {"source": "d_yt_channel_scraper_src_yt_scraper_ratelimit_py", "target": "d_yt_channel_scraper_src_yt_scraper_ratelimit_polite_sleep", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/yt_scraper/ratelimit.py", "source_location": "L7", "weight": 1.0}, {"source": "d_yt_channel_scraper_src_yt_scraper_ratelimit_py", "target": "d_yt_channel_scraper_src_yt_scraper_ratelimit_backoff_sleep", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/yt_scraper/ratelimit.py", "source_location": "L12", "weight": 1.0}], "raw_calls": [{"caller_nid": "d_yt_channel_scraper_src_yt_scraper_ratelimit_polite_sleep", "callee": "uniform", "is_member_call": true, "source_file": "src/yt_scraper/ratelimit.py", "source_location": "L8", "receiver": "random"}, {"caller_nid": "d_yt_channel_scraper_src_yt_scraper_ratelimit_polite_sleep", "callee": "sleep", "is_member_call": true, "source_file": "src/yt_scraper/ratelimit.py", "source_location": "L9", "receiver": "time"}, {"caller_nid": "d_yt_channel_scraper_src_yt_scraper_ratelimit_backoff_sleep", "callee": "uniform", "is_member_call": true, "source_file": "src/yt_scraper/ratelimit.py", "source_location": "L13", "receiver": "random"}, {"caller_nid": "d_yt_channel_scraper_src_yt_scraper_ratelimit_backoff_sleep", "callee": "sleep", "is_member_call": true, "source_file": "src/yt_scraper/ratelimit.py", "source_location": "L14", "receiver": "time"}]}
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
@@ -1 +0,0 @@
{"nodes": [{"id": "d_yt_channel_scraper_src_yt_scraper_webapp_init_py", "label": "__init__.py", "file_type": "code", "source_file": "src/yt_scraper/webapp/__init__.py", "source_location": "L1"}], "edges": [], "raw_calls": []}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
{"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
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
@@ -1 +0,0 @@
{"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
@@ -1 +0,0 @@
{"nodes": [{"id": "d_yt_channel_scraper_src_yt_scraper_init_py", "label": "__init__.py", "file_type": "code", "source_file": "src/yt_scraper/__init__.py", "source_location": "L1"}], "edges": [], "raw_calls": []}
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
@@ -1 +0,0 @@
{"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"}], "edges": [], "raw_calls": []}
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
@@ -1 +0,0 @@
{"nodes": [{"id": "pkg_yt_channel_scraper", "label": "yt-channel-scraper", "file_type": "code", "type": "package", "ecosystem": "python", "source_file": "pyproject.toml", "source_location": "L1", "version": "0.1.0"}], "edges": [{"source": "pkg_yt_channel_scraper", "target": "pkg_yt_dlp", "relation": "depends_on", "context": "dependency", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "pyproject.toml", "source_location": "L1", "weight": 1.0}, {"source": "pkg_yt_channel_scraper", "target": "pkg_click", "relation": "depends_on", "context": "dependency", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "pyproject.toml", "source_location": "L1", "weight": 1.0}, {"source": "pkg_yt_channel_scraper", "target": "pkg_rich", "relation": "depends_on", "context": "dependency", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "pyproject.toml", "source_location": "L1", "weight": 1.0}, {"source": "pkg_yt_channel_scraper", "target": "pkg_jinja2", "relation": "depends_on", "context": "dependency", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "pyproject.toml", "source_location": "L1", "weight": 1.0}, {"source": "pkg_yt_channel_scraper", "target": "pkg_pyyaml", "relation": "depends_on", "context": "dependency", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "pyproject.toml", "source_location": "L1", "weight": 1.0}, {"source": "pkg_yt_channel_scraper", "target": "pkg_python_slugify", "relation": "depends_on", "context": "dependency", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "pyproject.toml", "source_location": "L1", "weight": 1.0}, {"source": "pkg_yt_channel_scraper", "target": "pkg_requests", "relation": "depends_on", "context": "dependency", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "pyproject.toml", "source_location": "L1", "weight": 1.0}]}
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
@@ -1 +0,0 @@
{"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
@@ -1 +0,0 @@
1787443350.5198534
@@ -1 +0,0 @@
{"nodes": [{"id": "src_yt_scraper_webapp_static_index", "label": "SPA shell (index.html)", "file_type": "document", "source_file": "src/yt_scraper/webapp/static/index.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "src_yt_scraper_webapp_static_index", "target": "docs_superpowers_specs_2026_07_26_platform_design_dark_command_center", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "src/yt_scraper/webapp/static/index.html", "source_location": null, "weight": 1.0}, {"source": "src_yt_scraper_webapp_static_index", "target": "docs_superpowers_specs_2026_07_26_platform_design_cookie_vault_ux", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "src/yt_scraper/webapp/static/index.html", "source_location": "Cookies view dropzone", "weight": 1.0}], "hyperedges": []}
@@ -1 +0,0 @@
{"nodes": [{"id": "opencode_agent_webapp_builder", "label": "webapp-builder agent definition", "file_type": "document", "source_file": ".opencode/agent/webapp-builder.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "opencode_agent_webapp_builder_store_data_layer", "label": "Store API surface (data layer the webapp reuses)", "file_type": "concept", "source_file": ".opencode/agent/webapp-builder.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Agent must REUSE not duplicate: Store(db_path), cookies.py, segments.py, analysis.py, export.py, pipeline.process_video, config.Config. Active cookie (cookies.resolve_active_path) MUST be passed as cookies_file to every scrape job."}], "edges": [{"source": "opencode_agent_webapp_builder", "target": "docs_superpowers_specs_2026_07_26_platform_design", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": ".opencode/agent/webapp-builder.md", "source_location": "last line", "weight": 1.0}, {"source": "opencode_agent_webapp_builder", "target": "docs_superpowers_plans_2026_07_26_platform_build", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": ".opencode/agent/webapp-builder.md", "source_location": "last line", "weight": 1.0}, {"source": "opencode_agent_webapp_builder", "target": "opencode_agent_webapp_builder_store_data_layer", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": ".opencode/agent/webapp-builder.md", "source_location": "What already exists section", "weight": 1.0}, {"source": "opencode_agent_webapp_builder", "target": "src_yt_scraper_webapp_static_index", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": ".opencode/agent/webapp-builder.md", "source_location": null, "weight": 1.0}], "hyperedges": [{"id": "webapp_stack_b", "label": "Workstream B webapp stack (FastAPI + Alpine SPA + subagent)", "nodes": ["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"], "relation": "participate_in", "confidence": "EXTRACTED", "confidence_score": 0.95, "source_file": ".opencode/agent/webapp-builder.md"}]}
@@ -1 +0,0 @@
{"nodes": [{"id": "opencode_goals_webapp_build", "label": "Sub-goal: Build the local webapp (Workstream B)", "file_type": "document", "source_file": ".opencode/goals/webapp-build.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "opencode_goals_webapp_build", "target": "opencode_agent_webapp_builder", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": ".opencode/goals/webapp-build.md", "source_location": "Owner agent line", "weight": 1.0}, {"source": "opencode_goals_webapp_build", "target": "docs_superpowers_specs_2026_07_26_platform_design", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": ".opencode/goals/webapp-build.md", "source_location": "Spec line", "weight": 1.0}], "hyperedges": []}
@@ -1 +0,0 @@
{"nodes": [{"id": "docs_superpowers_plans_2026_07_26_platform_build", "label": "Platform Implementation Plan", "file_type": "document", "source_file": "docs/superpowers/plans/2026-07-26-platform-build.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "docs_superpowers_plans_2026_07_26_platform_build", "target": "docs_superpowers_specs_2026_07_26_platform_design", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/superpowers/plans/2026-07-26-platform-build.md", "source_location": "Spec line", "weight": 1.0}], "hyperedges": []}
@@ -1 +0,0 @@
{"nodes": [{"id": "readme", "label": "yt-channel-scraper README", "file_type": "document", "source_file": "README.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "readme_yt_dlp_innertube", "label": "yt-dlp InnerTube mechanism (ANDROID/IOS/WEB clients)", "file_type": "concept", "source_file": "README.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "readme", "target": "config_example", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "README.md", "source_location": "Configuraci\u00f3n section", "weight": 1.0}, {"source": "readme", "target": "readme_yt_dlp_innertube", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "README.md", "source_location": "header", "weight": 1.0}], "hyperedges": []}
@@ -1 +0,0 @@
{"nodes": [{"id": "opportunities", "label": "OPPORTUNITIES.md - extension audit", "file_type": "document", "source_file": "OPPORTUNITIES.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "opportunities_search_fts5", "label": "Feature proposal: search (FTS5 transcript search)", "file_type": "concept", "source_file": "OPPORTUNITIES.md", "source_location": "Tier 1 #1", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "opportunities_llm_summaries", "label": "Feature proposal: LLM summaries per video", "file_type": "concept", "source_file": "OPPORTUNITIES.md", "source_location": "Tier 3 #12", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "opportunities_rag_qa", "label": "Feature proposal: Q&A / RAG over channel", "file_type": "concept", "source_file": "OPPORTUNITIES.md", "source_location": "Tier 3 #13", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "opportunities_export_formats", "label": "Feature proposal: multi-format export (json/csv/srt/html)", "file_type": "concept", "source_file": "OPPORTUNITIES.md", "source_location": "Tier 1 #3", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "opportunities_analysis_wordcloud", "label": "Feature proposal: content analysis (wordcloud/top-words/timeline)", "file_type": "concept", "source_file": "OPPORTUNITIES.md", "source_location": "Tier 2 #9", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "opportunities_watch_mode", "label": "Feature proposal: watch mode (periodic discovery)", "file_type": "concept", "source_file": "OPPORTUNITIES.md", "source_location": "Tier 2 #8", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "opportunities_search_fts5", "target": "docs_superpowers_specs_2026_07_26_platform_design_transcript_fts5", "relation": "semantically_similar_to", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "OPPORTUNITIES.md", "source_location": null, "weight": 1.0}, {"source": "opportunities_export_formats", "target": "opencode_agent_webapp_builder_store_data_layer", "relation": "semantically_similar_to", "confidence": "INFERRED", "confidence_score": 0.65, "source_file": "OPPORTUNITIES.md", "source_location": null, "weight": 1.0}, {"source": "opportunities_watch_mode", "target": "docs_superpowers_specs_2026_07_26_platform_design_sse_job_runner", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.65, "source_file": "OPPORTUNITIES.md", "source_location": null, "weight": 1.0}, {"source": "opportunities_analysis_wordcloud", "target": "opencode_agent_webapp_builder_store_data_layer", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.65, "source_file": "OPPORTUNITIES.md", "source_location": null, "weight": 1.0}], "hyperedges": []}

Some files were not shown because too many files have changed in this diff Show More