// AUTO-GENERATED from armada/tide-table/models.py — DO NOT EDIT.
// Regenerate: python3 tools/gen_ts_types.py  (DRY data layer, #42)

export type AgreeLevel = 'empty' | 'unparsed' | 'no-claim' | 'agree' | 'partial' | 'conflict' | 'divergent'

export type LinkKind = 'profile' | 'release' | 'track' | 'playlist' | 'video' | 'embed'

export type PatternScope = 'unique' | 'repeated' | 'shared'

export type Platform = 'bandcamp' | 'spotify' | 'soundcloud' | 'youtube' | 'deezer' | 'apple_music' | 'instagram'

export type ReleaseKind = 'album' | 'ep' | 'single' | 'live'

export type Source = 'user' | 'ear' | 'file' | 'web' | 'derived'

export type Variant = 'stream' | 'club'

/** A↔C: how well the site's claimed ingredients match the actual score. */
export interface AgreeResult {
  level: AgreeLevel
  precision?: number | null
  jaccard?: number | null
  score_only?: string[]
  metadata_only?: string[]
  shared?: string[]
}

export interface CatalogStats {
  tracks_total: number
  score_present: number
  score_parsed: number
  with_metadata: number
  ac_agree: number
  ac_partial: number
  ac_conflict: number
  ac_divergent: number
  ac_unparsed: number
  ac_no_claim: number
  ac_empty: number
  alias_fragmented: number
  recorded: number
  unrecorded: number
  with_eda: number
  takes_total: number
  takes_with_eda: number
  gigs_total: number
}

/** A raw corner-C ingredient (the site's claim) — ground truth for the drawer. */
export interface Ingredient {
  type?: string
  code?: string
  description?: string
  gig?: string
}

export interface LoudTrace {
  trace: number[]
  stepS: number
}

export interface MasterInfo {
  file: string
  I?: number | null
  LRA?: number | null
  TP?: number | null
}

/** One orbit's lane in a take: label DERIVED from the .tidal sound, family VALIDATED by audio (centroid), activity = RMS dB per bin. (#40) */
export interface OrbitActivity {
  orbit: string
  label: string
  group: string
  sound?: string
  centroid?: number | null
  activity: number[]
}

/** One normalized mini-notation phrase — 'a thing' we can name and track. */
export interface PatternEntry {
  id: string
  norm: string
  n_tokens: number
  n_tracks: number
  n_total: number
  scope: PatternScope
  occurrences?: PatternOccurrence[]
}

export interface PatternOccurrence {
  track: string
  name?: string
  orbit?: number | null
  count?: number
  raw?: string
}

/** One URL on one platform, with provenance. The atom of the presence graph. */
export interface PresenceLink {
  platform: Platform
  url: string
  kind?: LinkKind
  label?: string
  ext_id?: string
  embed_url?: string
  prov?: Provenance | null
}

/** Where a value came from, so it can be trusted and corrected. */
export interface Provenance {
  source: Source
  locator?: string
  as_of: string
  note?: string
}

/** An album/EP/single/live release and its per-platform links. */
export interface Release {
  slug: string
  title: string
  kind?: ReleaseKind
  gig?: string | null
  year?: number | null
  links?: PresenceLink[]
  tracks?: ReleaseTrack[]
}

/** A track as it appears on a release, with any per-platform DIRECT links. `track` is the canonical catalog id (.tidal path) when known — the join key. */
export interface ReleaseTrack {
  title: string
  track?: string | null
  position?: number | null
  links?: PresenceLink[]
}

export interface RoleGroup {
  key: string
  label: string
  color: string
  glyph: string
}

export interface Take {
  id: string
  label: string
  gig: string
  date: string
  tidal?: string | null
  dur: number
  binS: number
  masters: Record<Variant, MasterInfo>
  loud: Record<Variant, LoudTrace>
  orbits: OrbitActivity[]
}

/** Corner B candidate: a take this track plausibly lives in (date-join, L0). */
export interface TakeRef {
  take: string
  type: string
  via: string
  method: string
  is_set: boolean
  eda?: string | null
  audio?: string | null
}

/** Corner C facts for one gig appearance (site tracklist, a pointer). */
export interface TrackMeta {
  gig: string
  date?: string
  bpm?: number | null
  style?: string | null
  dur?: number | null
}

export interface TrackNeighbor {
  track: string
  name?: string
  similarity: number
  shared_patterns?: string[]
}

export interface TrackPatternSig {
  track: string
  name?: string
  n_phrases: number
  n_shared: number
  neighbors?: TrackNeighbor[]
}

/** One track (identity = its .tidal path), reconciled across the three corners. */
export interface TrackRow {
  track: string
  names?: string[]
  name: string
  gigs?: string[]
  metas?: TrackMeta[]
  score_present: boolean
  n_orbits: number
  score?: Record<string, string>
  score_sounds?: string[]
  source?: string | null
  claimed_sounds?: string[]
  ingredients?: Ingredient[]
  ac: AgreeResult
  takes?: TakeRef[]
  n_takes: number
  n_takes_eda: number
  recorded: boolean
  alias_siblings?: string[]
}

export interface PlayerData {
  track: string
  calibration: string
  activeDb: number
  litFloorDb?: number
  roleGroups: RoleGroup[]
  note?: string
  takes: Take[]
}

export interface Note {
  id: string
  takeId: string
  t: number
  text: string
}

export interface CatalogView {
  schema: string
  as_of: string
  stats: CatalogStats
  tracks?: TrackRow[]
}

export interface PatternRegistry {
  schema: string
  as_of: string
  n_tracks: number
  n_patterns: number
  n_shared: number
  n_repeated: number
  patterns?: PatternEntry[]
  tracks?: TrackPatternSig[]
}

/** The whole distribution truth: artist profiles + releases. Generated artifact presence.json (built from presence.authored.yaml, validated on emit). */
export interface Presence {
  schema?: string
  artist?: string
  as_of: string
  profiles?: PresenceLink[]
  releases?: Release[]
}
