Skip to content

fix(2.0.24): store slug (not numeric id) on patterns created from corrections#196

Open
ttlequals0 wants to merge 2 commits intomainfrom
claude/reference-test-server-api-yWzpV
Open

fix(2.0.24): store slug (not numeric id) on patterns created from corrections#196
ttlequals0 wants to merge 2 commits intomainfrom
claude/reference-test-server-api-yWzpV

Conversation

@ttlequals0
Copy link
Copy Markdown
Owner

@ttlequals0 ttlequals0 commented May 5, 2026

Summary

src/api/patterns.py writes str(podcast['id']) into ad_patterns.podcast_id on two correction paths:

  • submit_correction with correction_type=confirm and no existing pattern_id (src/api/patterns.py:445)
  • submit_correction with correction_type=adjust and no existing pattern_id (src/api/patterns.py:556)

Every other creation site stores the slug:

  • ad_detector.learn_from_detections -> text_pattern_matcher.create_pattern_from_ad(podcast_id=podcast_id) where the caller in main_app/processing.py:297 passes the slug
  • pattern_service verification-miss auto-create -> podcast_id=slug (src/pattern_service.py:784)

And the detection-side query is get_ad_patterns(podcast_id=podcast_slug) (src/ad_detector.py:1259), backed by ap.podcast_id = p.slug (src/database/patterns.py:17, plus the comment "podcast_id stores slugs since v0.1.194").

Net effect: a pattern auto-created from a user confirm or boundary adjustment is scoped to a value the matcher never queries with. The pattern is silently orphaned -- it will never match on subsequent episodes, so the system fails to learn from exactly the corrections users put the most thought into.

Fix

Both call sites now store the slug instead of the numeric id:

-podcast_id_str = str(podcast['id']) if podcast else None
+podcast_id_str = slug if podcast else None

The db.get_podcast_by_slug(slug) lookup is preserved so the existence guard still rejects creation when the slug doesn't resolve.

Version + tests (added)

  • version.py and openapi.yaml bumped to 2.0.24; CHANGELOG [Unreleased] rolled into [2.0.24] - 2026-05-05.
  • tests/unit/test_correction_pattern_scope.py (new): three tests pinning both correction paths and the find_pattern_by_text dedup lookup so they can't regress to writing the numeric id.

Migration note for existing data

Operators with patterns already created via the corrections UI will have rows where ad_patterns.podcast_id is a numeric string ("3", "7", ...) instead of a slug. These rows are inert -- detection can't find them. They can be repaired with a one-shot UPDATE that joins back to podcasts.id:

UPDATE ad_patterns
SET podcast_id = (SELECT slug FROM podcasts WHERE CAST(podcasts.id AS TEXT) = ad_patterns.podcast_id)
WHERE scope = 'podcast'
  AND podcast_id GLOB '[0-9]*'
  AND EXISTS (SELECT 1 FROM podcasts WHERE CAST(podcasts.id AS TEXT) = ad_patterns.podcast_id);

Not bundled in this PR -- the fix stops the bleeding; data repair is operator-driven and depends on whether the operator wants to keep, merge, or discard the orphaned rows.

Test plan

  • Unit tests added (3 cases) covering both write paths and the dedup lookup
  • After deploy: submit a confirm correction on an episode where no pattern_id is sent, then verify the new ad_patterns row has podcast_id equal to the slug
  • Re-process a later episode of the same podcast and confirm the new pattern is retrieved by get_ad_patterns(podcast_id=slug) and counted in last_matched_at
  • Existing learn_from_detections and verification-miss paths unchanged

claude and others added 2 commits May 5, 2026 19:11
src/api/patterns.py wrote str(podcast['id']) into ad_patterns.podcast_id
on the confirm and boundary_adjustment correction paths, while every
other creation site and the detection-side query
(get_ad_patterns(podcast_id=slug)) use the slug. Patterns created via a
user correction were scoped to a value the matcher never queries with,
so they were silently orphaned -- never retrieved during detection on
subsequent episodes. Use the slug at both call sites, matching the
ap.podcast_id = p.slug join the rest of the schema assumes.

https://claude.ai/code/session_01Cqt4uejLMshs1CQyBWNbQD
- Bump version.py and openapi.yaml to 2.0.24 (CLAUDE.md requires version
  update for behavioral changes).
- Replace [Unreleased] CHANGELOG section with [2.0.24] - 2026-05-05.
- Add tests/unit/test_correction_pattern_scope.py: pins both correction
  paths (confirm and adjust with no existing pattern_id) so they cannot
  regress to writing the numeric podcasts.id into ad_patterns.podcast_id.
  Also pins the find_pattern_by_text dedup lookup to use the slug.
@ttlequals0 ttlequals0 force-pushed the claude/reference-test-server-api-yWzpV branch from 16e0c34 to 39dd329 Compare May 5, 2026 23:17
@ttlequals0 ttlequals0 changed the title fix: store slug (not numeric id) on patterns created from corrections fix(2.0.24): store slug (not numeric id) on patterns created from corrections May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants