Allow DSP listing observations in Context enrichment
Summary
Adds a dsp_listings enrichment topic so the Context Engine can store DSP store listings (Apple Music first) as provider observations. They are not stored as canonical context_resources, identities or release IDs. claim_context_enrichment hard-codes its topic allowlist, so the API collector in the companion PR cannot save anything until this migration is applied.
20261010214300_context_dsp_listings.sql copies the current function body from 20260927090000_context_audio_source.sql unchanged except for one token: dsp_listings is added to the topic allowlist and to the "Provider lookup requires observation evidence" list. A diff that strips ,'dsp_listings' from the new file matches the base definition exactly.
Refs recoupable/app#2143 (child of epic recoupable/app#2116).
Merge sequencing
docs (no change) → this database PR → api recoupable/api#1025 (same branch claude/ctx-2143-dsp-listings) → app (no change).
- No dependency on open PRs. Open database PRs #89–#115 were checked: no migration timestamp collision, and none redefines
claim_context_enrichmentorcomplete_context_enrichment. - Ordering rule: this migration replaces the whole function body. Any later migration that redefines
claim_context_enrichment(for example one adding another provider topic) must keepdsp_listingsin both lists. The rule is stated in the migration header and intests/README.md. - Planner wiring (not in this slice): a planned DSP node will also need a node-to-topic mapping in
save_context_execution_outcome(20260924100000_context_release_track_execution.sql); without it the save raisesExecution evidence does not match node. The migration header andtests/README.mdname this second place.
Verification
- Ran on the current head (after the review follow-up commit
0be692a):LC_ALL=en_US.UTF-8 PATH=/opt/homebrew/opt/postgresql@17/bin:$PATH python3 -m unittest discover -s tests -p 'test_dsp_listings.py'→ 5 passed, 0 failed (PostgreSQL 17). The suite covers:- claim, then one saved result holding two storefronts with one versioned source each (
jpnot listed,uslisted), then reuse; interpretationandestimaterejected fordsp_listings;musicbrainz_recordingsandcatalog_valuationstill claim under their own rules;- near-miss and unregistered topics still raise
Invalid enrichment module; - the
context_resourcescount is unchanged across claim, save and reuse (the follow-up replaced a check that ignored every Spotify row), and no resource links or new subjects; - plus the inherited release-cases lifecycle test.
- claim, then one saved result holding two storefronts with one versioned source each (
- Ran on the first commit:
test_company_assessment.py→ 3 passed.test_release_cases.py→ 1 passed. The follow-up changes only the migration's header comment, so the function body is unchanged. - Migration check on the current head: after stripping
,'dsp_listings'and thebegin;/commit;wrapper, the function definition is identical to theclaim_context_enrichmentdefinition in20260927090000_context_audio_source.sql. - Ran (ad hoc, not committed): the existing
supabase/tests/context_provider_evidence.sql, seeded and run after the new migration → passed. - Red → green: with the migration body replaced by
select 1;,test_claim_save_and_reuse_storefront_scoped_listing_observationandtest_listing_topic_requires_observation_evidencefailed withERROR: Invalid enrichment module. Both pass with the migration. - CI: the new
.github/workflows/dsp-listings.ymlruns the suite on PostgreSQL 15 and 16. It mirrorsrelease-cases.ymlbut is a separate file, so sibling PRs editing that workflow won't conflict with this one. - Note: local macOS PostgreSQL 17 needs
LC_ALLset, or the postmaster refuses to start ("postmaster became multithreaded during startup"). - Not verified: hosted deployment, any hosted or production database (this migration has not been applied anywhere), live providers. Results are implemented and fixture-tested only.
Out of scope / known gaps
- No new tables, columns, constraints or
context_resources.providervalues. Listings stay incontext_results. - YouTube Music, music video, art track and uploader channel collection. YouTube Music store listings remain an open #2143 gap; #2131 covers single-video YouTube context, not store listings.
- No planner, dispatcher, HTTP, MCP or brief-recipe support (API side; not in this PR).
🤖 Generated with Claude Code