11 Commits
Author SHA1 Message Date
ed d4e809ba63 conductor(track): close twitter_threads_extraction_20260705 — corpus extracted (VC8 complete) 2026-07-05 19:29:14 -04:00
ed 2c680e23e4 feat(twitter_threads): gallery-dl media download + inline media embeds in Markdown
download_media now shells out to gallery-dl (handles X.com auth/403/video->mp4) instead of urllib, returns the downloaded files, + media_files_for_post glob helper + --cookies CLI. render_markdown embeds images with ![](...) and videos with an HTML <video controls> tag (were plain links). extract_corpus uses the package download_media (one download path). Tests rewritten for the gallery-dl API. Corpus: 4 threads, 33 media (32 img embeds + 1 video), 0 missing.
2026-07-05 19:08:43 -04:00
ed 7e828cbd61 refactor(twitter_threads): consolidate corpus extraction into one script; gallery-dl downloads media
Replaced convert_cookies.py + run_corpus.py + dedupe_corpus.py (+ the scratch merge_corpus.py) with a single extract_corpus.py that: converts cookies, fetches each URL's full conversation, MERGES overlapping conversations into one thread (union of posts, no duplicate threads/media), downloads ALL media (images + video/mp4) via gallery-dl itself (plain urllib 403'd on pbs.twimg.com and never fetched videos), and renders. Result: 4 merged threads, 33 media files (incl mp4), 0 missing links. cookies_netscape.txt gitignored.
2026-07-05 18:50:55 -04:00
ed ae9cc1d494 feat(twitter_threads): full-thread extraction (conversations) + front-matter from target + corpus dedupe
fetch_thread_from_url now passes -o conversations=true (full threads, not single tweets), sorts posts chronologically, and sets root_post_id to the URL's target tweet. render_markdown builds front-matter from the target (root_post_id) post, not the earliest conversation tweet (fixes wrong @handle). Added dedupe_corpus.py: keeps deepest thread per conversation, deletes duplicates, keeps+marks unique branches (branch_of) + writes threads_index.json. 33 tests pass.
2026-07-05 18:38:43 -04:00
ed 53721a7796 fix(twitter_threads): align gallery-dl parser to live schema + add track extraction scripts
Live Task 5.3 validation against real gallery-dl output: (1) pass -o text-tweets=true so text-only tweets are returned (media-only default yielded []); (2) fix author name/nick swap (gallery-dl name=handle, nick=display). Added convert_cookies.py (JSON cookie export -> Netscape) + run_corpus.py (8-URL pipeline -> docs/twitter/) to the track dir. Extracted 8/8 threads. 33 tests still pass.
2026-07-05 18:28:40 -04:00
ed 0d7293d59e conductor(track): complete twitter_threads_extraction_20260705 + TRACK_COMPLETION report [state=completed]
All 5 phases done, 34 tests passing, VC1-VC7 pass. Task 5.3 (live 8-URL smoke) + 5.6 (user manual verification) deferred to user (network/cookies + merge decision).
2026-07-05 17:53:42 -04:00
ed 41656d6b7c conductor(plan): mark Phase 4 (fetch_thread.py) complete [06ff9299] 2026-07-05 17:36:37 -04:00
ed ea33a49f15 conductor(plan): mark Phase 3 (download_media.py) complete [f503eb5d] 2026-07-05 17:25:09 -04:00
ed 36de54a9e0 conductor(plan): mark Phase 2 (render_markdown.py) complete [ef98f6d1] 2026-07-05 17:17:52 -04:00
ed 0440be0288 conductor(plan): mark Phase 1 (scaffold + error types + dataclasses) complete [161d8da] 2026-07-05 17:08:31 -04:00
ed 0908f8fa28 conductor(track): init twitter_threads_extraction_20260705 — standalone Twitter/X thread extraction tooling
Scripts + workflow for extracting Twitter/X posts and threads into
Markdown with associated media. Mirrors the scripts/video_analysis/
pattern. Standalone requirement: zero imports from src/, conductor/,
or scripts.video_analysis — copy-pasteable to another repo with only
gallery-dl as the external dep.

5 modules: __init__.py, error_types.py (Result[T, ErrorInfo] +
ThreadData/PostData typed dataclasses), fetch_thread.py (gallery-dl
subprocess for URLs + html.parser fallback for local HTML),
download_media.py (stdlib urllib, idempotent), render_markdown.py
(YAML front-matter + per-post sections + ./media/ links).

Reference project: C:\projects\forth\bootslop — the corpus feeds
bootslop's scripts and reference-generation pipeline. Acceptance
corpus: 8 threads (@NOTimothyLottes x6 + @VPCOMPRESSB x2) extracted
to tests/artifacts/twitter_threads_corpus/. The ?s=20 quote-share
suffix on the @VPCOMPRESSB URLs must be stripped by fetch_thread.py
before acquisition (added to FR2 as URL normalization).

5 phases / 23 tasks. 8 verification criteria (VC1-VC8). TDD red-first
on the pure-function modules (render_markdown, types, media naming).
2026-07-05 16:50:05 -04:00