feat(db,contracts): W5-C subscription units migration 0025, contracts and mapping

- subscription: status pending (TMDB not ready: searchable/evaluable, not completable),
  last_searched_at / next_search_at
- content_unit (season): episode_total ledger with source / lock / timestamp
- acquisition_plan: unit_keys (Slot × unit reservation) and file_selection; drop the
  one-in-flight-per-slot unique index (checked under slot row lock per unit instead)
- new tables slot_deferral, slot_unit (per-unit quality ledger), subscription_history
- contracts: SubscriptionParams, SubscriptionHistory, SlotDeferral, SlotUnit, SubscriptionProgress,
  EpisodeTotalSet, CandidateEvaluation pri/trace/unitKeys and decision deferred;
  endpoints subscriptions.search/progress/setEpisodeTotal and subscription-history
- mapping: evaluation messages via describeViolation, pri/trace passthrough

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-27 23:33:56 +08:00
1 parent d162d464c4
commit 1dd460d359
9 files changed
+405 -34

No files matched your search

+60 -1
View File
@@ -91,6 +91,7 @@ export type ContentUnitContentType =
| "unknown";
export type ContentUnitSegment = "full" | "upper" | "middle" | "lower" | "unknown";
export type ContentUnitStatus = "provisional" | "confirmed" | "retired";
export type ContentUnitEpisodeTotalSource = "tmdb" | "injected" | "manual" | "covered_floor" | "previous";
export type DecisionKind =
| "identity_ambiguous"
| "download_stalled"
@@ -209,7 +210,7 @@ export type SubscriptionMode = "once" | "continuous";
export type SubscriptionSeasonScope = "current_season" | "following_seasons";
export type SubscriptionOrigin = "user" | "agent" | "policy" | "import";
export type SubscriptionPriority = "immediate" | "tracking" | "new_work" | "upgrade";
export type SubscriptionStatus = "active" | "paused" | "completed" | "cancelled";
export type SubscriptionStatus = "active" | "paused" | "pending" | "completed" | "cancelled";
export type TaskStatus = "pending" | "running" | "waiting" | "succeeded" | "failed" | "cancelled" | "dead";
export type TasksOpLedgerStatus = "started" | "succeeded";
export type TitleAliasKind = "original" | "translated" | "short" | "site_title" | "romanized" | "other";
@@ -233,6 +234,8 @@ export interface AcquisitionPlanTable {
status_reason: string | null;
created_at: GeneratedTimestamptz;
updated_at: GeneratedTimestamptz;
unit_keys: Generated<string[]>;
file_selection: Json | null;
}
export interface AcquisitionSlotTable {
@@ -566,6 +569,10 @@ export interface ContentUnitTable {
field_locks: Generated<string[]>;
created_at: GeneratedTimestamptz;
updated_at: GeneratedTimestamptz;
episode_total: number | null;
episode_total_source: ContentUnitEpisodeTotalSource | null;
episode_total_locked: Generated<boolean>;
episode_total_at: Timestamptz | null;
}
export interface DecisionTable {
@@ -1143,6 +1150,29 @@ export interface SiteSnapshotTable {
updated_at: GeneratedTimestamptz;
}
export interface SlotDeferralTable {
id: Generated<string>;
slot_id: string;
source_release_id: string;
reason: string;
unit_keys: Generated<string[]>;
attempts: Generated<number>;
created_at: GeneratedTimestamptz;
updated_at: GeneratedTimestamptz;
}
export interface SlotUnitTable {
id: Generated<string>;
slot_id: string;
content_unit_id: string;
media_asset_id: string | null;
plan_id: string | null;
quality: Generated<Json>;
pri: number | null;
created_at: GeneratedTimestamptz;
updated_at: GeneratedTimestamptz;
}
export interface SourceReleaseTable {
id: Generated<string>;
site_id: string;
@@ -1201,6 +1231,23 @@ export interface SubscriptionTable {
created_by: string | null;
created_at: GeneratedTimestamptz;
updated_at: GeneratedTimestamptz;
last_searched_at: Timestamptz | null;
next_search_at: Timestamptz | null;
}
export interface SubscriptionHistoryTable {
id: Generated<string>;
subscription_id: string | null;
media_entity_id: string | null;
season_unit_id: string | null;
media_kind: string;
mode: string;
reason: string;
snapshot: Generated<Json>;
progress: Generated<Json>;
completed_at: GeneratedTimestamptz;
created_at: GeneratedTimestamptz;
updated_at: GeneratedTimestamptz;
}
export interface TaskTable {
@@ -1347,9 +1394,12 @@ export interface DB {
site: SiteTable;
site_account: SiteAccountTable;
site_snapshot: SiteSnapshotTable;
slot_deferral: SlotDeferralTable;
slot_unit: SlotUnitTable;
source_release: SourceReleaseTable;
sse_event: SseEventTable;
subscription: SubscriptionTable;
subscription_history: SubscriptionHistoryTable;
task: TaskTable;
tasks_fact: TasksFactTable;
tasks_op_ledger: TasksOpLedgerTable;
@@ -1517,6 +1567,12 @@ export type SiteAccountUpdate = Updateable<SiteAccountTable>;
export type SiteSnapshotRow = Selectable<SiteSnapshotTable>;
export type NewSiteSnapshot = Insertable<SiteSnapshotTable>;
export type SiteSnapshotUpdate = Updateable<SiteSnapshotTable>;
export type SlotDeferralRow = Selectable<SlotDeferralTable>;
export type NewSlotDeferral = Insertable<SlotDeferralTable>;
export type SlotDeferralUpdate = Updateable<SlotDeferralTable>;
export type SlotUnitRow = Selectable<SlotUnitTable>;
export type NewSlotUnit = Insertable<SlotUnitTable>;
export type SlotUnitUpdate = Updateable<SlotUnitTable>;
export type SourceReleaseRow = Selectable<SourceReleaseTable>;
export type NewSourceRelease = Insertable<SourceReleaseTable>;
export type SourceReleaseUpdate = Updateable<SourceReleaseTable>;
@@ -1526,6 +1582,9 @@ export type SseEventUpdate = Updateable<SseEventTable>;
export type SubscriptionRow = Selectable<SubscriptionTable>;
export type NewSubscription = Insertable<SubscriptionTable>;
export type SubscriptionUpdate = Updateable<SubscriptionTable>;
export type SubscriptionHistoryRow = Selectable<SubscriptionHistoryTable>;
export type NewSubscriptionHistory = Insertable<SubscriptionHistoryTable>;
export type SubscriptionHistoryUpdate = Updateable<SubscriptionHistoryTable>;
export type TaskRow = Selectable<TaskTable>;
export type NewTask = Insertable<TaskTable>;
export type TaskUpdate = Updateable<TaskTable>;