Per sub-project-2 plan Task 9 / spec §6.4. Three keyless first-ship fetchers
parse documented JSON APIs via an injected HttpClient; license/attribution go
through tools.licensing; NASA third-party + IA no-license cases are flagged in
notes for review. musopen/fma/freesound are explicit deferred stubs raising
NotImplementedError; freesound documents FREESOUND_API_TOKEN (secret, env-only).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per sub-project-2 plan Task 8 / spec §6. ingest_candidate dedupes, downloads,
mechanically tags, drafts coordinates, builds a proposed Record and appends it;
ingest_search loops over fetcher hits. All boundaries (download/prober/color_fn)
injectable, so the pipeline is fully hermetic.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per sub-project-2 plan Task 7 / spec §7. HeuristicProposer seeds the brain plane
from archive priors and the mood plane from title/description keyword nudges,
clamps to 0..4, and emits a one-line rationale. Deterministic, no I/O, no ML
(honors design §11) — only a DRAFT a human reviews.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per sub-project-2 plan Task 6 / spec §5.3. normalize_license maps CC URLs /
identifiers and public-domain markers to the LICENSES vocab, builds non-empty
attribution for cc_by/cc_by_nc, and rejects unmappable licenses at ingest.
librivox_license() helper returns public_domain.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per sub-project-2 plan Task 5 / spec §5.2. ffmpeg-only dominant color (no image
library), opt-in by design; extract_frame for review previews. Runners injectable
so the unit suite never shells out.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per sub-project-2 plan Task 4 / spec §5.1. derive_tags(Probe) -> Tags with the
attached_pic cover-art guard so an art-bearing audio file stays mode=audio.
Duration falls back to the longest stream when format.duration is absent, and
rounds half-up so 12.5s -> 13s (Python's round() would give 12 via banker's
rounding) to match the spec's stated behavior.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per sub-project-2 plan Task 3 / spec §5.1. Parses ffprobe JSON into a Probe
(streams + format); subprocess runner injectable so tests never shell out.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per sub-project-2 plan Task 2 / spec §3. Purely additive to hef.catalog;
no existing symbol changes. validate_catalog runs per-record validate() then
asserts id uniqueness; index_by_id gives by-id lookup the player also wants.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per sub-project-2 plan Task 1. Adds tools/ to setuptools packages,
gitignores media/, and a minimal injectable urllib HTTP client.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>