- metadata.enrich (propose, low, replay safe): normalized-title cache (kv_cache
region enrich, 7 days) -> daily budget -> web.search (title + 短剧 / 电视剧 平台,
second query limited to whitelist via site:) -> web.fetch of up to 3 relevant
whitelisted pages (registered site domains never read, redirects out of the
whitelist dropped) -> upstream model extraction with rule fallback -> server-side
evidence check (rule_confirmed / multi_evidence / needs_review). Suggestion only.
- POST /identity-pool/{id}/enrich (suggest) and /enrich/apply (console session):
provisional entity or same-title merge, season/episode units, field-level
metadata with source web/agent + evidence, aliases, release assignment.
Poster proxy GET /img/enrich/{id} (og:image from whitelisted pages only).
- Auto-enrich once per pool entry when subscription/rule lookups find nothing on
TMDB (identity.autoEnrich, off by default); identity.enrichDailyBudget,
identity.enrichDomains settings; web.fetch now returns og:image.
- Pool sheet "元数据补全" section; entity detail shows evidence links.
- Migration 0049_enrichment (metadata_enrichment, metadata_field.evidence, source
web). Requires image rebuild / api + worker restart to take effect.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
RSS/list releases that match no subscription or local work no longer hit
TMDB or open a pending item; they go to the identity pool as `unmatched`.
TMDB is queried only on a local alias hit, a published new-title rule whose
prefilter passes, manual/Agent retry, search results, or when the new
setting identity.eagerTmdbLookup (default off) is on. Mirrors MoviePilot:
torrents are recognised only when matched to a subscription or searched,
and recognition failures are logged, not alerted.
- Pending items only for related releases (ambiguous after lookup, or
related to a local work but unresolved); same source + normalized title
merge into one decision ("来源「X」的 N 条资源待识别"), resolve/dismiss
applies to the whole group, members detach as they get resolved.
- Pool governance: unmatched reviews capped (daily, 3x), title_alias
insert trigger wakes similar entries, stale unmatched entries archived
after identity.poolArchiveDays (30); review idempotency keys include the
due time.
- Migration 0047_identity_pool: reason/outcome `unmatched`,
identity_candidate.normalized_title (+trgm index), wake trigger, and
cleanup of open identity_unresolved items with no related work
(dismissed, resolution=moved_to_pool).
- Inbox: group by type + work/source with collapse, hide info-only items
by default (minSeverity=warning), badge counts warning+ only; pool sheet
gets manual TMDB/local-work assign and dismiss; settings card for the
new identity settings.
- Runbook docs/runbook/identity.md.
Requires rebuild/restart (migration runs on start).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- glossary: 10 punctuation rules (full-width in Chinese, CJK/Latin spacing,
full-width parens around Chinese, single ellipsis, 「」 quotes, period rules)
- scripts/check-copy-punctuation.mjs: checks string literals, templates and JSX
text (not comments, types, keys, match/compare strings); --fix, --strict,
--by-file; wired into deno task ci as check:copy in warn mode
- --fix applied to web, server and contracts; files other lanes were editing
(subscriptions, sites, browser, agent, auth/account, inventory) left for them
- tests updated for the changed messages
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- U4: form save failures toast the first problem and scroll/focus the first
invalid field (policy draft, settings cards, resource drawers, subscription
form) via lib/form-errors.
- U5: FormField keeps 8px between a hint and the next label.
- U6: file manager status bar keeps free space left-aligned, clear of the
Agent button.
- U13: move/copy dialog stops "target is the source folder / inside the
source" before requesting a preview (transferTargetProblem + tests).
- U14: account popover uses the solid float material.
- U15/U16: inbox tile hint shortened; TMDB assign dialog uses the shared
Select and labelled fields (type, TMDB ID, note).
- Copy: "TMDB 已保存" spacing, API Key block no longer repeats the section
title, whole-day intervals read "每 7 天", "最高级别:提示",
"延后:已有计划在途", failed records show "未生成目标路径", upstream model
column "默认模型".
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Found in v0.2 visual QA (docs/plan/09-visual-qa.md):
- actor strings (admin_session:<uuid>, user:<uuid>, system) -> 管理员/系统/API Key
in policy revisions, subscriptions, inbox, trash, business tasks, organize detail
- cache volume without key shows the downloader name instead of instance:<uuid>
- download timeline/plan: task and organize statuses, plan purpose, priority and
status reason localized; audit gets labels for capability/files/site/feed actions
- organize record reason uses conflict detail (没有可入库的主视频) instead of
blocked:no_main_video; slot/candidate reasons drop inflight:<uuid>
- identity decision summary no longer shows no_viable_candidate
- upstream test: 'Connection error.' classified as network, with a Chinese hint
- new policy draft prefills key default (placeholder looked like a value)
- dialog/sheet close sr-only text in Chinese
Co-Authored-By: Claude Opus 5.5 <[email protected]>
no_match resources (and lookup failures after auto-review gives up) now
open a decision in the inbox with options to set a TMDB ID, pick a local
work, or dismiss; ambiguous decisions get the same manual options.
Resolve accepts identity {tmdb | mediaEntityId} and assigns with a manual
lock. The inbox option dialog collects the TMDB type/ID or searches local
works; the identity pool links each pending item to its inbox filter.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- subscription sheet: 立即搜索, active-search times, 追更进度 (per-season total with source/lock,
per-episode state chips, in-flight/deferred counts) and set/lock season episode total
- labels for subscription pending and candidate decision deferred
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- library list (kind/status/search, cursor paging) and detail: paths and roots, external identity
mapping with lock, field-level metadata sources and locks, slot cards with rejection reasons,
content units (provisional flag), downloads with verification; remap/lock/refresh/merge actions
- subscriptions: list/create/update, slot rules editor (hard/soft/upgrade/completion),
policy revision draft -> preview -> publish (grant warning) -> rollback
- preferences: tag CRUD, disable/enable, suppression records and lift, history timeline
- inbox: grouped by entity and kind, evidence/suggestion/impact/preview, resolve options, SSE refresh
- identity: pool assign/dismiss/retry, external identity revisions and lock, title alias management
- all responses validated against contracts zod schemas
Co-Authored-By: Claude Opus 5.5 <[email protected]>