feat(channels): suggest your own tags for untagged channels from your tagging pattern (E8·S4)

Learn, per user tag, which auto TOPIC tags are characteristic of the channels
you've tagged it, then suggest that tag for still-untagged subscribed channels
whose topics cover enough of the profile. Language auto-tags are excluded from
the signal — near-universal within a language, they flooded every channel.

New GET /api/tags/suggestions (read-only, deterministic) backed by
app/sync/tagsuggest.py. Surfaced in the Channel Manager as dashed "ghost" chips
in the tags cell — one tap accepts (reuses the attach-tag endpoint), × dismisses
for the session — plus a header badge and a bulk "Accept N confident" (the
full-profile matches) behind a confirm. No silent writes (D4 = suggest-and-confirm).

Also reflow a pre-existing prettier drift in dateFilter.ts from E8·S2.
This commit is contained in:
2026-08-26 02:18:34 +02:00
parent fbb961b5b7
commit 549aae67cc
12 changed files with 566 additions and 8 deletions
+13 -1
View File
@@ -54,7 +54,19 @@
"createFailed": "Could not create the tag.",
"noTag": "No tag",
"moreCount_one": "{{count}} more tag",
"moreCount_other": "{{count}} more tags"
"moreCount_other": "{{count}} more tags",
"suggestedHint": "Suggested from your tagging pattern ({{pct}}% match) — click to add",
"acceptSuggestion": "Add suggested tag {{name}}",
"dismissSuggestion": "Dismiss suggestion",
"suggestionsHint": "Tags suggested for your untagged channels, learned from how you've tagged similar ones. Click a ghost chip to add it, or × to dismiss.",
"suggestionsCount_one": "{{count}} suggestion",
"suggestionsCount_other": "{{count}} suggestions",
"acceptAllHigh_one": "Accept {{count}} confident",
"acceptAllHigh_other": "Accept {{count}} confident",
"acceptAllTitle": "Accept suggested tags",
"acceptAllConfirm_one": "Add the {{count}} high-confidence suggested tag to its channel?",
"acceptAllConfirm_other": "Add the {{count}} high-confidence suggested tags to their channels?",
"acceptAllConfirmCta": "Accept all"
},
"loading": "Loading channels…",
"empty": "No channels.",
+13 -1
View File
@@ -54,7 +54,19 @@
"createFailed": "A címke létrehozása nem sikerült.",
"noTag": "Nincs címke",
"moreCount_one": "még {{count}} címke",
"moreCount_other": "még {{count}} címke"
"moreCount_other": "még {{count}} címke",
"suggestedHint": "A címkézési mintád alapján javasolt ({{pct}}% egyezés) — kattints a hozzáadáshoz",
"acceptSuggestion": "{{name}} javasolt címke hozzáadása",
"dismissSuggestion": "Javaslat elvetése",
"suggestionsHint": "A címkézetlen csatornáidhoz javasolt címkék, abból tanulva, hogyan címkézted a hasonlókat. Kattints egy szellem-chipre a hozzáadáshoz, vagy ×-re az elvetéshez.",
"suggestionsCount_one": "{{count}} javaslat",
"suggestionsCount_other": "{{count}} javaslat",
"acceptAllHigh_one": "{{count}} biztos elfogadása",
"acceptAllHigh_other": "{{count}} biztos elfogadása",
"acceptAllTitle": "Javasolt címkék elfogadása",
"acceptAllConfirm_one": "Hozzáadod a(z) {{count}} nagy magabiztosságú javasolt címkét a csatornájához?",
"acceptAllConfirm_other": "Hozzáadod a(z) {{count}} nagy magabiztosságú javasolt címkét a csatornáikhoz?",
"acceptAllConfirmCta": "Mind elfogadása"
},
"loading": "Csatornák betöltése…",
"empty": "Nincsenek csatornák.",