fluncle 0.256.0 → 0.258.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/fluncle.mjs +1266 -1124
  2. package/package.json +1 -1
package/bin/fluncle.mjs CHANGED
@@ -622,7 +622,7 @@ function parseVersion(version) {
622
622
  var currentVersion;
623
623
  var init_version = __esm(() => {
624
624
  init_output();
625
- currentVersion = "0.256.0".trim() ? "0.256.0".trim() : "0.1.0";
625
+ currentVersion = "0.258.0".trim() ? "0.258.0".trim() : "0.1.0";
626
626
  });
627
627
 
628
628
  // src/update-notifier.ts
@@ -2335,7 +2335,7 @@ function parseVersion2(version) {
2335
2335
  var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
2336
2336
  var init_version2 = __esm(() => {
2337
2337
  init_output();
2338
- currentVersion2 = "0.256.0".trim() ? "0.256.0".trim() : "0.1.0";
2338
+ currentVersion2 = "0.258.0".trim() ? "0.258.0".trim() : "0.1.0";
2339
2339
  });
2340
2340
 
2341
2341
  // ../../packages/registry/src/index.ts
@@ -3469,6 +3469,18 @@ var init_src = __esm(() => {
3469
3469
  title: "Freshness tap",
3470
3470
  weights: { status: "hidden" }
3471
3471
  },
3472
+ {
3473
+ exposedContent: [
3474
+ "checks pipeline yield against measured backlog and alerts the operator on sustained stalls"
3475
+ ],
3476
+ kind: "cron",
3477
+ name: "cron.pipeline-watch",
3478
+ operatorNotes: "Every 15m from a host calendar timer. Reads sweep markers and agent-tier status/worklist counters; alerts Discord on incident open, reminders, and recovery. Source: docs/agents/hermes/scripts/pipeline-watch.*.",
3479
+ probeConfig: { cadenceMs: 15 * MINUTE_MS, cronName: "fluncle-pipeline-watch", kind: "cron" },
3480
+ statusDescription: "watches for stalled track processing",
3481
+ title: "Track watch",
3482
+ weights: { status: "hidden" }
3483
+ },
3472
3484
  {
3473
3485
  command: "fluncle admin catalogue rank",
3474
3486
  exposedContent: [
@@ -3699,6 +3711,17 @@ var init_src = __esm(() => {
3699
3711
  title: "Label bios",
3700
3712
  weights: { status: "hidden" }
3701
3713
  },
3714
+ {
3715
+ command: "fluncle admin labels list --seed-state undecided",
3716
+ exposedContent: ["read the undecided crawl-seed pile and report whether a triage round is due"],
3717
+ kind: "cron",
3718
+ name: "cron.label-triage",
3719
+ operatorNotes: "daily. A PURE trigger — zero model tokens, one countless admin read and a sort. Fires only when 40+ NEVER-LOOKED labels have accumulated; stale ones ride along but never trigger a round. It cannot rule: recording a finding is record_label_triage (agent tier) and ruling is update_label (operator tier), which 403s the box token. The batched research leg is deliberately unwired until the gate proves it reports honestly. Source: docs/agents/hermes/scripts/{label-triage-sweep.ts,label-triage-sweep.sh}.",
3720
+ probeConfig: { cadenceMs: 24 * 60 * MINUTE_MS, cronName: "fluncle-label-triage", kind: "cron" },
3721
+ statusDescription: "reports when the label pile needs a round",
3722
+ title: "Label triage gate",
3723
+ weights: { status: "hidden" }
3724
+ },
3702
3725
  {
3703
3726
  command: "fluncle admin albums describe --queue",
3704
3727
  exposedContent: [
@@ -4428,6 +4451,7 @@ var SOURCE_LABELS;
4428
4451
  var init_admin_attention = __esm(() => {
4429
4452
  init_api();
4430
4453
  SOURCE_LABELS = {
4454
+ "anchor-failure": "anchor failure",
4431
4455
  "anchor-review": "version check",
4432
4456
  "artist-review": "artist links",
4433
4457
  "attach-cues": "cues",
@@ -10149,85 +10173,756 @@ var init_zod = __esm(() => {
10149
10173
  init_external();
10150
10174
  });
10151
10175
 
10152
- // ../../packages/contracts/src/orpc/admin-albums.ts
10153
- var DescribeAlbumBodySchema, describeAlbum, draftAlbumBio, AlbumBioWorkItemSchema, listAlbumsMissingBio, adminAlbumsContract;
10154
- var init_admin_albums = __esm(() => {
10176
+ // ../../packages/contracts/src/orpc/admin-catalogue.ts
10177
+ var CatalogueLensSchema, CapturePriorityReasonSchema, CatalogueMatchSchema, CatalogueTrackItemSchema, CatalogueSummarySchema, listCatalogueTracks, rankCatalogue, recordDemand, clearWrongAudio, requeueUnmatchedCaptures, requeueAnchor, requeueIsrcRecovery, flagWrongAudio, forceCapture, certifyTrack, setTrackDismissed, CaptureVerifyItemSchema, listUnverifiedCaptures, verifyCapture, CrawlPassSchema, CrawlPhaseInitializationSchema, MAX_CRAWL_PREPARE_LIMIT = 6, CrawlFetchPlanSchema, SuppliedCrawlBodySchema, MAX_CRAWL_COMMIT_BATCH, CRAWL_COMMIT_TOKEN_MAX_BYTES, CRAWL_COMMIT_BATCH_MAX_TOTAL_BYTES, CrawlCommitItemSchema, CrawlCommitReceiptSchema, CrawlPhaseCapabilitiesSchema, CrawlPhaseInputSchema, CrawlPhaseOutputSchema, CrawlStatusSchema, CrawlPipelineSummarySchema, crawlCatalogue, commitCrawlNodes, getCrawlStatus, ANCHOR_CANDIDATE_LIMIT = 100, ANCHOR_ARTIST_LIMIT = 20, ANCHOR_TEXT_MAX = 300, ANCHOR_ISRC_MAX = 64, ANCHOR_ID_MAX = 64, ANCHOR_URL_MAX = 2048, AnchorCandidateSchema, anchorTrack, recordAnchorFailure, DEEZER_CANDIDATE_LIMIT = 5, DEEZER_TEXT_MAX = 300, DEEZER_ISRC_MAX = 64, DEEZER_TRACK_ID_MAX = 32, DeezerIsrcCandidateSchema, resolveAnchor, resolveAnchorReview, setAnchorSearch, setAnchorApify, CaptureBudgetStateSchema, getCaptureBudget, setCaptureBudget, AnchorApifyBudgetSchema, getAnchorApifyBudget, setAnchorApifyBudget, SpotifyAnchorBreakerStateSchema, AnchorRungFlagsSchema, getSpotifyAnchorBreaker, resetSpotifyAnchorBreaker, AppleBreakerStateSchema, resetAppleBreaker, adminCatalogueContract;
10178
+ var init_admin_catalogue = __esm(() => {
10155
10179
  init_dist3();
10156
10180
  init_zod();
10157
- DescribeAlbumBodySchema = looseObject({
10158
- bio: unknown().optional(),
10159
- dryRun: unknown().optional(),
10160
- finalAttempt: boolean2().optional(),
10161
- promptVersion: number2().int().min(0).optional()
10162
- });
10163
- describeAlbum = oc.route({
10181
+ CatalogueLensSchema = _enum(["capture", "dismissed", "ear", "failed", "quarantine", "unmatched"]).meta({ id: "CatalogueLens" });
10182
+ CapturePriorityReasonSchema = object({
10183
+ kind: _enum(["artist", "label", "none", "seed-label", "skipped-label", "unauthorized"]),
10184
+ name: string2().nullable()
10185
+ }).meta({ id: "CapturePriorityReason" });
10186
+ CatalogueMatchSchema = object({
10187
+ artists: array(string2()),
10188
+ logId: string2().nullable(),
10189
+ title: string2(),
10190
+ trackId: string2()
10191
+ }).meta({ id: "CatalogueMatch" });
10192
+ CatalogueTrackItemSchema = object({
10193
+ albumImageUrl: string2().nullable(),
10194
+ appleMusicUrl: string2().nullable(),
10195
+ artists: array(string2()),
10196
+ bpm: number2().nullable(),
10197
+ capturePriority: number2().nullable(),
10198
+ captureReason: CapturePriorityReasonSchema.nullable(),
10199
+ captureStatus: string2().nullable(),
10200
+ captureVerification: string2().nullable(),
10201
+ dismissedAt: string2().nullable(),
10202
+ duplicateOf: CatalogueMatchSchema.nullable(),
10203
+ hasCapturedAudio: boolean2(),
10204
+ hasPreview: boolean2(),
10205
+ isrc: string2().nullable(),
10206
+ key: string2().nullable(),
10207
+ label: string2().nullable(),
10208
+ nearestFinding: CatalogueMatchSchema.nullable(),
10209
+ nearestFindingScore: number2().nullable(),
10210
+ rankedAt: string2().nullable(),
10211
+ releaseDate: string2().nullable(),
10212
+ sourceAudioAttemptedAt: string2().nullable().optional(),
10213
+ spotifyUrl: string2().nullable(),
10214
+ title: string2(),
10215
+ trackId: string2()
10216
+ }).meta({ id: "CatalogueTrackItem" });
10217
+ CatalogueSummarySchema = object({
10218
+ awaitingCapture: number2(),
10219
+ awaitingRank: number2(),
10220
+ dismissed: number2(),
10221
+ quarantined: number2(),
10222
+ ranked: number2(),
10223
+ total: number2()
10224
+ }).meta({ id: "CatalogueSummary" });
10225
+ listCatalogueTracks = oc.route({
10226
+ method: "GET",
10227
+ operationId: "listCatalogueTracks",
10228
+ path: "/admin/catalogue",
10229
+ summary: "The ranked catalogue: closest to a finding (`ear`), or next to capture (`capture`)",
10230
+ tags: ["Admin"]
10231
+ }).input(object({
10232
+ lens: CatalogueLensSchema.default("ear"),
10233
+ limit: number3().int().min(1).max(200).default(50)
10234
+ })).output(object({
10235
+ ok: literal(true),
10236
+ summary: CatalogueSummarySchema,
10237
+ tracks: array(CatalogueTrackItemSchema)
10238
+ }));
10239
+ rankCatalogue = oc.route({
10164
10240
  method: "POST",
10165
- operationId: "describeAlbum",
10166
- path: "/admin/albums/{slug}/bio",
10167
- summary: "Auto-author an album's voiced bio (fills an empty bio only)",
10241
+ operationId: "rankCatalogue",
10242
+ path: "/admin/catalogue/rank",
10243
+ summary: "One tick of the catalogue ranking sweep (nearest finding + capture priority)",
10168
10244
  tags: ["Admin"]
10169
- }).input(DescribeAlbumBodySchema.extend({ slug: string2() })).output(object({
10170
- bio: string2(),
10171
- dryRun: literal(true).optional(),
10172
- gateBypassed: literal(true).optional(),
10245
+ }).input(object({
10246
+ countRemaining: boolean3().default(false),
10247
+ limit: number3().int().min(1).max(1000).default(250)
10248
+ })).output(object({
10173
10249
  ok: literal(true),
10174
- skipped: boolean2().optional(),
10175
- slug: string2(),
10176
- voiceViolations: array(string2()).optional()
10250
+ summary: object({
10251
+ catalogueDuplicates: number2(),
10252
+ corpus: string2(),
10253
+ embeddedFindings: number2(),
10254
+ findings: number2(),
10255
+ prioritized: number2(),
10256
+ quarantined: number2(),
10257
+ remaining: number2(),
10258
+ scored: number2()
10259
+ }),
10260
+ telescope: union([
10261
+ object({ changed: boolean2(), ok: literal(true), size: number2() }),
10262
+ object({ ok: literal(false), reason: string2() })
10263
+ ]).optional()
10177
10264
  }));
10178
- draftAlbumBio = oc.route({
10179
- method: "GET",
10180
- operationId: "draftAlbumBio",
10181
- path: "/admin/albums/{slug}/bio-draft",
10182
- summary: "Assemble a ready-to-author bio prompt for an album (Worker-side grounding)",
10265
+ recordDemand = oc.route({
10266
+ method: "POST",
10267
+ operationId: "recordDemand",
10268
+ path: "/admin/catalogue/demand",
10269
+ summary: "One demand tick: reorder crawl/capture priority from Simple Analytics pageviews",
10183
10270
  tags: ["Admin"]
10184
- }).input(object({ slug: string2() })).output(object({
10185
- findingCount: number2(),
10186
- found: boolean2(),
10187
- hasFacts: boolean2(),
10188
- name: string2(),
10189
- prompt: string2(),
10190
- promptVersion: number2()
10271
+ }).input(object({})).output(object({
10272
+ ok: literal(true),
10273
+ summary: object({
10274
+ configured: boolean2(),
10275
+ demandedArtists: number2(),
10276
+ demandedLabels: number2(),
10277
+ frontierPromoted: number2(),
10278
+ pagesRead: number2(),
10279
+ totalPageviews: number2(),
10280
+ tracksScored: number2(),
10281
+ unknownSlugs: number2(),
10282
+ window: object({ end: string2(), start: string2() })
10283
+ })
10191
10284
  }));
10192
- AlbumBioWorkItemSchema = object({ id: string2(), name: string2(), slug: string2() }).meta({ id: "AlbumBioWorkItem" });
10193
- listAlbumsMissingBio = oc.route({
10285
+ clearWrongAudio = oc.route({
10286
+ method: "POST",
10287
+ operationId: "clearWrongAudio",
10288
+ path: "/admin/catalogue/wrong-audio/clear",
10289
+ summary: "Overrule the wrong-audio quarantine on one catalogue row (operator)",
10290
+ tags: ["Admin"]
10291
+ }).input(object({ trackId: string2().min(1) })).output(object({ cleared: boolean2(), ok: literal(true) }));
10292
+ requeueUnmatchedCaptures = oc.route({
10293
+ method: "POST",
10294
+ operationId: "requeueUnmatchedCaptures",
10295
+ path: "/admin/catalogue/captures/requeue-unmatched",
10296
+ summary: "Re-queue terminal-unmatched catalogue captures after a matcher improvement (operator)",
10297
+ tags: ["Admin"]
10298
+ }).input(object({})).output(object({ ok: literal(true), requeued: number2(), skippedVetoed: number2() }));
10299
+ requeueAnchor = oc.route({
10300
+ method: "POST",
10301
+ operationId: "requeueAnchor",
10302
+ path: "/admin/catalogue/anchor/requeue",
10303
+ summary: "Clear named rows' anchor re-ask backoff or terminal validation error (operator)",
10304
+ tags: ["Admin"]
10305
+ }).input(object({ trackIds: array(string2().min(1)).min(1).max(250) })).output(object({ ok: literal(true), requeued: number2() }));
10306
+ requeueIsrcRecovery = oc.route({
10307
+ method: "POST",
10308
+ operationId: "requeueIsrcRecovery",
10309
+ path: "/admin/catalogue/isrc-recovery/requeue",
10310
+ summary: "Clear Deezer-empty ISRC-recovery stamps from a named window (operator)",
10311
+ tags: ["Admin"]
10312
+ }).input(object({
10313
+ dryRun: boolean2().default(true),
10314
+ since: string2().regex(/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{1,3})?Z)?$/, "since must be an ISO date (2026-09-09) or instant (2026-09-09T00:00:00.000Z)")
10315
+ })).output(object({
10316
+ dryRun: boolean2(),
10317
+ matched: number2(),
10318
+ ok: literal(true),
10319
+ requeued: number2()
10320
+ }));
10321
+ flagWrongAudio = oc.route({
10322
+ method: "POST",
10323
+ operationId: "flagWrongAudio",
10324
+ path: "/admin/catalogue/wrong-audio/flag",
10325
+ summary: "Flag a finding's captured audio as the wrong recording (operator)",
10326
+ tags: ["Admin"]
10327
+ }).input(object({ trackId: string2().min(1) })).output(object({ flagged: boolean2(), ok: literal(true) }));
10328
+ forceCapture = oc.route({
10329
+ method: "POST",
10330
+ operationId: "forceCapture",
10331
+ path: "/admin/catalogue/force-capture",
10332
+ summary: "Overrule the duplicate veto on one catalogue row so it can be captured (operator)",
10333
+ tags: ["Admin"]
10334
+ }).input(object({ trackId: string2().min(1) })).output(object({ forced: boolean2(), ok: literal(true) }));
10335
+ certifyTrack = oc.route({
10336
+ method: "POST",
10337
+ operationId: "certifyTrack",
10338
+ path: "/admin/catalogue/certify",
10339
+ summary: "Certify an existing catalogue track in place — mint its finding (operator)",
10340
+ tags: ["Admin"]
10341
+ }).input(object({ note: string2().optional(), trackId: string2().min(1) })).output(object({ logId: string2(), ok: literal(true) }));
10342
+ setTrackDismissed = oc.route({
10343
+ method: "PUT",
10344
+ operationId: "setTrackDismissed",
10345
+ path: "/admin/catalogue/dismissed",
10346
+ summary: "Dismiss a catalogue track ('not for me') or restore it (operator)",
10347
+ tags: ["Admin"]
10348
+ }).input(object({ dismissed: boolean2(), trackId: string2().min(1) })).output(object({ changed: boolean2(), ok: literal(true) }));
10349
+ CaptureVerifyItemSchema = object({
10350
+ artists: array(string2()),
10351
+ certified: boolean2(),
10352
+ durationMs: number2(),
10353
+ isrc: string2().nullable(),
10354
+ logId: string2().nullable(),
10355
+ sourceAudioKey: string2(),
10356
+ title: string2(),
10357
+ trackId: string2()
10358
+ }).meta({ id: "CaptureVerifyItem" });
10359
+ listUnverifiedCaptures = oc.route({
10194
10360
  method: "GET",
10195
- operationId: "listAlbumsMissingBio",
10196
- path: "/admin/albums/bio-queue",
10197
- summary: "List albums with findings but no bio yet, oldest first (the bio worklist)",
10361
+ operationId: "listUnverifiedCaptures",
10362
+ path: "/admin/catalogue/captures/unverified",
10363
+ summary: "Captured rows not yet fingerprint-verified against their preview (the backfill worklist)",
10198
10364
  tags: ["Admin"]
10199
- }).input(object({ limit: string2().optional() })).output(object({ albums: array(AlbumBioWorkItemSchema), ok: literal(true) }));
10200
- adminAlbumsContract = {
10201
- describe_album: describeAlbum,
10202
- draft_album_bio: draftAlbumBio,
10203
- list_albums_missing_bio: listAlbumsMissingBio
10204
- };
10205
- });
10206
-
10207
- // ../../packages/contracts/src/orpc/admin-artifacts.ts
10208
- var ARTIFACT_CHANGE_API_MAX_LIMIT = 500, ARTIFACT_SNAPSHOT_API_MAX_LIMIT = 200, ARTIFACT_COMPACTION_API_MAX_LIMIT = 1000, ARTIFACT_SUPPORTED_CONTRACTS, ArtifactStreamSchema, ArtifactContractSchema, ConsumerIdSchema, DigestSchema, SequenceSchema, ArtifactRebuildCheckpointSchema, ArtifactConsumerStatusSchema, ArtifactChangeEventSchema, ArtifactSnapshotItemSchema, ArtifactSnapshotPageSchema, ArtifactChangePageSchema, ArtifactCompactionResultSchema, registerArtifactConsumer, getArtifactConsumer, listArtifactSnapshot, checkpointArtifactRebuild, activateArtifactConsumer, listArtifactChanges, acknowledgeArtifactChanges, inactivateArtifactConsumer, compactArtifactChanges, adminArtifactsContract;
10209
- var init_admin_artifacts = __esm(() => {
10210
- init_dist3();
10211
- init_zod();
10212
- ARTIFACT_SUPPORTED_CONTRACTS = [
10213
- { formatVersion: 1, stream: "device.album", streamVersion: 1 },
10214
- { formatVersion: 1, stream: "device.artist", streamVersion: 1 },
10215
- { formatVersion: 1, stream: "device.finding", streamVersion: 1 },
10216
- { formatVersion: 1, stream: "device.label", streamVersion: 1 },
10217
- { formatVersion: 1, stream: "device.track", streamVersion: 1 },
10218
- { formatVersion: 1, stream: "device.track-artist", streamVersion: 1 },
10219
- { formatVersion: 1, stream: "sonar.track", streamVersion: 1 }
10220
- ];
10221
- ArtifactStreamSchema = _enum([
10222
- "device.album",
10223
- "device.artist",
10224
- "device.finding",
10225
- "device.label",
10226
- "device.track",
10227
- "device.track-artist",
10228
- "sonar.track"
10229
- ]);
10230
- ArtifactContractSchema = strictObject({
10365
+ }).input(object({
10366
+ count: boolean3().default(false),
10367
+ limit: number3().int().min(1).max(200).default(50)
10368
+ })).output(object({
10369
+ ok: literal(true),
10370
+ queued: number2().optional(),
10371
+ tracks: array(CaptureVerifyItemSchema)
10372
+ }));
10373
+ verifyCapture = oc.route({
10374
+ method: "POST",
10375
+ operationId: "verifyCapture",
10376
+ path: "/admin/catalogue/captures/verify",
10377
+ summary: "Record a capture's fingerprint verdict against its preview, and route it",
10378
+ tags: ["Admin"]
10379
+ }).input(object({
10380
+ trackId: string2().min(1),
10381
+ verdict: _enum(["match", "mismatch", "no-preview"])
10382
+ })).output(object({
10383
+ action: _enum([
10384
+ "flagged-finding",
10385
+ "not-captured",
10386
+ "operator-verified",
10387
+ "preview-match",
10388
+ "quarantined-catalogue",
10389
+ "unverified"
10390
+ ]),
10391
+ ok: literal(true)
10392
+ }));
10393
+ CrawlPassSchema = object({
10394
+ artistsRearmed: number2().optional(),
10395
+ dryRun: boolean2(),
10396
+ expanded: number2(),
10397
+ failed: number2(),
10398
+ frontierPending: number2(),
10399
+ labelsDiscovered: array(string2()),
10400
+ maxHop: number2(),
10401
+ nodesEnqueued: number2(),
10402
+ rateLimited: boolean2(),
10403
+ releaseDetailsStored: number2().optional(),
10404
+ releasesRearmed: number2(),
10405
+ seeded: number2(),
10406
+ seedsRearmed: number2(),
10407
+ tracksAllowedIn: number2().optional(),
10408
+ tracksFound: number2(),
10409
+ tracksSkipped: number2(),
10410
+ tracksSkippedArtistRule: number2().optional(),
10411
+ tracksSkippedHeld: number2().optional(),
10412
+ tracksSkippedLabelGate: number2().optional(),
10413
+ tracksWritten: number2()
10414
+ }).meta({ id: "CrawlPass" });
10415
+ CrawlPhaseInitializationSchema = object({
10416
+ artistsRearmed: number2(),
10417
+ releasesRearmed: number2(),
10418
+ seeded: number2(),
10419
+ seedsRearmed: number2()
10420
+ });
10421
+ CrawlFetchPlanSchema = discriminatedUnion("kind", [
10422
+ object({ kind: literal("none") }),
10423
+ object({ kind: literal("single"), url: string2().max(2048) }),
10424
+ object({
10425
+ countField: literal("release-count"),
10426
+ kind: literal("tail"),
10427
+ pageSize: number2().int().positive(),
10428
+ pageUrlTemplate: string2().max(2048),
10429
+ probeUrl: string2().max(2048)
10430
+ })
10431
+ ]);
10432
+ SuppliedCrawlBodySchema = object({
10433
+ body: json().optional(),
10434
+ outcome: _enum(["body", "empty", "invalid", "oversize", "throttled"]),
10435
+ url: string2().max(2048)
10436
+ });
10437
+ MAX_CRAWL_COMMIT_BATCH = MAX_CRAWL_PREPARE_LIMIT;
10438
+ CRAWL_COMMIT_TOKEN_MAX_BYTES = 2 * 1024 * 1024;
10439
+ CRAWL_COMMIT_BATCH_MAX_TOTAL_BYTES = 8 * 1024 * 1024;
10440
+ CrawlCommitItemSchema = strictObject({
10441
+ commitToken: string2().max(CRAWL_COMMIT_TOKEN_MAX_BYTES),
10442
+ operationId: literal("catalogue.crawl"),
10443
+ operationKey: string2().max(128),
10444
+ requestDigest: string2().regex(/^[0-9a-f]{64}$/)
10445
+ });
10446
+ CrawlCommitReceiptSchema = object({
10447
+ elapsedMs: number2().int().min(0).optional(),
10448
+ error: string2().max(500).optional(),
10449
+ operationKey: string2().max(128),
10450
+ outcome: _enum([
10451
+ "committed",
10452
+ "conflict",
10453
+ "failed",
10454
+ "in-progress",
10455
+ "lookup-failed",
10456
+ "rejected",
10457
+ "safely-retryable"
10458
+ ]),
10459
+ replayed: boolean2(),
10460
+ result: json().optional(),
10461
+ resultIdentity: string2().optional(),
10462
+ state: _enum(["accepted", "committed", "rejected"]).optional()
10463
+ }).meta({ id: "CrawlCommitReceipt" });
10464
+ CrawlPhaseCapabilitiesSchema = strictObject({
10465
+ commitBatchLimit: number2().int().min(1).max(MAX_CRAWL_COMMIT_BATCH),
10466
+ commitBatchMaxTotalBytes: number2().int().min(1)
10467
+ });
10468
+ CrawlPhaseInputSchema = discriminatedUnion("phase", [
10469
+ object({ phase: literal("initialize") }),
10470
+ object({
10471
+ limit: number2().int().min(1).max(MAX_CRAWL_PREPARE_LIMIT).default(2),
10472
+ maxHop: number2().int().min(0).max(3).default(2),
10473
+ phase: literal("prepare"),
10474
+ sampleStorableRepair: boolean2().optional()
10475
+ }),
10476
+ object({
10477
+ phase: literal("fetch"),
10478
+ preparedToken: string2().max(2 * 1024 * 1024),
10479
+ supplied: array(SuppliedCrawlBodySchema).max(2).optional()
10480
+ }),
10481
+ object({
10482
+ commitToken: string2().max(2 * 1024 * 1024),
10483
+ operationId: literal("catalogue.crawl"),
10484
+ operationKey: string2().max(128),
10485
+ phase: literal("commit"),
10486
+ requestDigest: string2().regex(/^[0-9a-f]{64}$/)
10487
+ })
10488
+ ]);
10489
+ CrawlPhaseOutputSchema = discriminatedUnion("phase", [
10490
+ object({
10491
+ initialization: CrawlPhaseInitializationSchema,
10492
+ kind: _enum(["initialized", "unavailable"]),
10493
+ ok: literal(true),
10494
+ phase: literal("initialize")
10495
+ }),
10496
+ object({
10497
+ boxFetch: boolean2(),
10498
+ capabilities: CrawlPhaseCapabilitiesSchema.optional(),
10499
+ frontierPending: number2(),
10500
+ initialization: CrawlPhaseInitializationSchema,
10501
+ items: array(object({
10502
+ fetchPlan: CrawlFetchPlanSchema,
10503
+ nodeId: string2(),
10504
+ nodeKind: _enum(["artist", "label", "release"]).optional(),
10505
+ preparedToken: string2()
10506
+ })).max(MAX_CRAWL_PREPARE_LIMIT),
10507
+ kind: _enum(["drained", "prepared", "unavailable"]),
10508
+ ok: literal(true),
10509
+ phase: literal("prepare"),
10510
+ storableReady: boolean2().nullable().optional()
10511
+ }),
10512
+ object({
10513
+ commitToken: string2(),
10514
+ ok: literal(true),
10515
+ operationId: literal("catalogue.crawl"),
10516
+ operationKey: string2(),
10517
+ phase: literal("fetch"),
10518
+ rateLimited: boolean2().optional(),
10519
+ requestDigest: string2()
10520
+ }),
10521
+ object({
10522
+ ok: literal(true),
10523
+ phase: literal("commit"),
10524
+ receipt: object({
10525
+ outcome: _enum([
10526
+ "committed",
10527
+ "conflict",
10528
+ "in-progress",
10529
+ "lookup-failed",
10530
+ "rejected",
10531
+ "safely-retryable"
10532
+ ]),
10533
+ replayed: boolean2(),
10534
+ result: json().optional(),
10535
+ resultIdentity: string2().optional(),
10536
+ state: _enum(["accepted", "committed", "rejected"]).optional()
10537
+ })
10538
+ })
10539
+ ]);
10540
+ CrawlStatusSchema = object({
10541
+ anchorsPending: number2(),
10542
+ catalogueTracks: number2(),
10543
+ frontier: object({
10544
+ done: number2(),
10545
+ failed: number2(),
10546
+ pending: number2(),
10547
+ skipped: number2()
10548
+ }),
10549
+ frontierByKind: object({
10550
+ artist: number2(),
10551
+ label: number2(),
10552
+ release: number2()
10553
+ }),
10554
+ labelsUndecided: number2(),
10555
+ seedLabels: array(string2()),
10556
+ storablePending: number2(),
10557
+ undecidedLabelsQueued: number2(),
10558
+ unstorablePending: number2()
10559
+ }).meta({ id: "CrawlStatus" });
10560
+ CrawlPipelineSummarySchema = object({
10561
+ anchorsPending: number2(),
10562
+ frontier: object({ pending: number2() }),
10563
+ storablePending: number2(),
10564
+ summary: literal(true),
10565
+ unstorablePending: number2()
10566
+ }).meta({ id: "CrawlPipelineSummary" });
10567
+ crawlCatalogue = oc.route({
10568
+ inputStructure: "detailed",
10569
+ method: "POST",
10570
+ operationId: "crawlCatalogue",
10571
+ path: "/admin/catalogue/crawl",
10572
+ summary: "Run one bounded, resumable pass of the catalogue crawler",
10573
+ tags: ["Admin"]
10574
+ }).input(object({
10575
+ body: CrawlPhaseInputSchema.optional(),
10576
+ query: object({
10577
+ dryRun: string2().optional(),
10578
+ limit: string2().optional(),
10579
+ maxHop: string2().optional()
10580
+ })
10581
+ })).output(union([CrawlPassSchema.extend({ ok: literal(true) }), CrawlPhaseOutputSchema]));
10582
+ commitCrawlNodes = oc.route({
10583
+ method: "POST",
10584
+ operationId: "commitCrawlNodes",
10585
+ path: "/admin/catalogue/crawl/commits",
10586
+ summary: "Commit one claim's fetched crawl nodes in a single admitted phase",
10587
+ tags: ["Admin"]
10588
+ }).input(strictObject({
10589
+ items: array(CrawlCommitItemSchema).min(1).max(MAX_CRAWL_COMMIT_BATCH)
10590
+ })).output(strictObject({
10591
+ deferred: number2().int().min(0),
10592
+ ok: literal(true),
10593
+ receipts: array(CrawlCommitReceiptSchema).max(MAX_CRAWL_COMMIT_BATCH)
10594
+ }));
10595
+ getCrawlStatus = oc.route({
10596
+ method: "GET",
10597
+ operationId: "getCrawlStatus",
10598
+ path: "/admin/catalogue/crawl",
10599
+ summary: "The crawl frontier's state, the catalogue size, and the seed set",
10600
+ tags: ["Admin"]
10601
+ }).input(object({ summary: string2().optional() })).output(union([
10602
+ CrawlStatusSchema.extend({ ok: literal(true) }),
10603
+ CrawlPipelineSummarySchema.extend({ ok: literal(true) })
10604
+ ]));
10605
+ AnchorCandidateSchema = object({
10606
+ albumImageUrl: string2().max(ANCHOR_URL_MAX).nullish(),
10607
+ artists: array(object({
10608
+ id: string2().max(ANCHOR_ID_MAX).nullish(),
10609
+ name: string2().max(ANCHOR_TEXT_MAX)
10610
+ })).max(ANCHOR_ARTIST_LIMIT).default([]),
10611
+ durationMs: number2().nullish(),
10612
+ isrc: string2().max(ANCHOR_ISRC_MAX).nullish(),
10613
+ spotifyTrackId: string2().max(ANCHOR_ID_MAX).optional(),
10614
+ title: string2().max(ANCHOR_TEXT_MAX).default(""),
10615
+ uri: string2().max(ANCHOR_URL_MAX).optional(),
10616
+ url: string2().max(ANCHOR_URL_MAX).optional()
10617
+ }).refine((candidate) => Boolean(candidate.spotifyTrackId ?? candidate.uri ?? candidate.url), {
10618
+ error: "a candidate must carry a spotifyTrackId, uri, or url"
10619
+ }).meta({ id: "AnchorCandidate" });
10620
+ anchorTrack = oc.route({
10621
+ method: "POST",
10622
+ operationId: "anchorTrack",
10623
+ path: "/admin/catalogue/anchor",
10624
+ summary: "Verify box-supplied Spotify candidates against a catalogue row and write its anchor",
10625
+ tags: ["Admin"]
10626
+ }).input(object({
10627
+ candidates: array(AnchorCandidateSchema).max(ANCHOR_CANDIDATE_LIMIT).default([]),
10628
+ trackId: string2().min(1)
10629
+ })).output(object({
10630
+ anchored: boolean2(),
10631
+ ok: literal(true),
10632
+ verifiedBy: _enum(["isrc", "search", "search-subset"]).nullable()
10633
+ }));
10634
+ recordAnchorFailure = oc.route({
10635
+ method: "POST",
10636
+ operationId: "recordAnchorFailure",
10637
+ path: "/admin/catalogue/anchor/failure",
10638
+ summary: "Record a deterministic anchor candidate rejection",
10639
+ tags: ["Admin"]
10640
+ }).input(object({ status: union([literal(400), literal(422)]), trackId: string2().min(1) })).output(object({ attempts: number2().int(), ok: literal(true), terminal: boolean2() }));
10641
+ DeezerIsrcCandidateSchema = object({
10642
+ artistName: string2().max(DEEZER_TEXT_MAX),
10643
+ deezerTrackId: string2().max(DEEZER_TRACK_ID_MAX).optional(),
10644
+ durationMs: number2().positive().finite(),
10645
+ isrc: string2().max(DEEZER_ISRC_MAX),
10646
+ title: string2().max(DEEZER_TEXT_MAX)
10647
+ }).meta({ id: "DeezerIsrcCandidate" });
10648
+ resolveAnchor = oc.route({
10649
+ method: "POST",
10650
+ operationId: "resolveAnchor",
10651
+ path: "/admin/catalogue/anchor/resolve",
10652
+ summary: "Resolve a catalogue row's Spotify anchor from the free rungs (ListenBrainz + dark Spotify search)",
10653
+ tags: ["Admin"]
10654
+ }).input(object({
10655
+ deezerCandidates: array(DeezerIsrcCandidateSchema).max(DEEZER_CANDIDATE_LIMIT).optional(),
10656
+ spotifySearch: boolean2().optional(),
10657
+ trackId: string2().min(1)
10658
+ })).output(object({
10659
+ anchored: boolean2(),
10660
+ apifyBudgetRemaining: number2().int().nonnegative(),
10661
+ apifyEligible: boolean2(),
10662
+ apifyEnabled: boolean2(),
10663
+ apifyIneligibleReason: _enum(["apify_budget_spent", "awaiting_free_ask"]).nullable(),
10664
+ freeDurationMsOmitted: number2().int().nonnegative(),
10665
+ isrcRecoveredByDeezer: boolean2(),
10666
+ listenbrainzOutcome: _enum([
10667
+ "anchored",
10668
+ "empty-ids",
10669
+ "gate-rejected",
10670
+ "metadata-failed",
10671
+ "no-map",
10672
+ "no-mbid",
10673
+ "not-attempted",
10674
+ "request-failed",
10675
+ "yielded-on-breaker"
10676
+ ]),
10677
+ ok: literal(true),
10678
+ source: _enum(["listenbrainz", "spotify-isrc", "spotify-search"]).nullable(),
10679
+ spotifyIsrcAsked: boolean2(),
10680
+ spotifySearchDone: boolean2(),
10681
+ spotifySearchEnabled: boolean2(),
10682
+ spotifyThrottled: boolean2(),
10683
+ stamped: boolean2(),
10684
+ verifiedBy: _enum(["isrc", "search", "search-subset"]).nullable()
10685
+ }));
10686
+ resolveAnchorReview = oc.route({
10687
+ method: "POST",
10688
+ operationId: "resolveAnchorReview",
10689
+ path: "/admin/catalogue/anchor/reviews/{trackId}/resolve",
10690
+ summary: "Rule on a suspected version mismatch: anchor to the candidate, or dismiss (operator)",
10691
+ tags: ["Admin"]
10692
+ }).input(object({
10693
+ resolution: _enum(["accepted", "dismissed"]),
10694
+ trackId: string2().min(1)
10695
+ })).output(object({
10696
+ anchored: boolean2(),
10697
+ ok: literal(true),
10698
+ review: object({
10699
+ candidateTitle: string2(),
10700
+ spotifyTrackId: string2().optional()
10701
+ })
10702
+ }));
10703
+ setAnchorSearch = oc.route({
10704
+ method: "PUT",
10705
+ operationId: "setAnchorSearch",
10706
+ path: "/admin/catalogue/anchor/search",
10707
+ summary: "Flip the dark flag for the Spotify anchor-search rungs (operator)",
10708
+ tags: ["Admin"]
10709
+ }).input(object({ enabled: boolean2() })).output(object({ enabled: boolean2(), ok: literal(true) }));
10710
+ setAnchorApify = oc.route({
10711
+ method: "PUT",
10712
+ operationId: "setAnchorApify",
10713
+ path: "/admin/catalogue/anchor/apify",
10714
+ summary: "Flip the Apify anchor-fallback kill-flag — off = no-budget graceful state (operator)",
10715
+ tags: ["Admin"]
10716
+ }).input(object({ enabled: boolean2() })).output(object({ enabled: boolean2(), ok: literal(true), requeued: number2() }));
10717
+ CaptureBudgetStateSchema = object({
10718
+ budget: object({ dailyBytes: number2(), dailyTracks: number2() }),
10719
+ closedReason: _enum(["bytes_spent", "paused", "tracks_spent"]).nullable(),
10720
+ open: boolean2(),
10721
+ paused: boolean2(),
10722
+ remainingBytes: number2(),
10723
+ remainingTracks: number2(),
10724
+ spend: object({ bytes: number2(), tracks: number2() }),
10725
+ windowHours: number2()
10726
+ }).meta({ id: "CaptureBudgetState" });
10727
+ getCaptureBudget = oc.route({
10728
+ method: "GET",
10729
+ operationId: "getCaptureBudget",
10730
+ path: "/admin/catalogue/capture-budget",
10731
+ summary: "The catalogue capture budget: the switch, the caps, the 24h spend, what is left",
10732
+ tags: ["Admin"]
10733
+ }).input(object({})).output(CaptureBudgetStateSchema.extend({ ok: literal(true) }));
10734
+ setCaptureBudget = oc.route({
10735
+ method: "PUT",
10736
+ operationId: "setCaptureBudget",
10737
+ path: "/admin/catalogue/capture-budget",
10738
+ summary: "Set the catalogue capture budget / flip its kill switch (operator)",
10739
+ tags: ["Admin"]
10740
+ }).input(object({
10741
+ dailyBytes: number2().int().min(0).optional(),
10742
+ dailyTracks: number2().int().min(0).optional(),
10743
+ paused: boolean2().optional()
10744
+ })).output(CaptureBudgetStateSchema.extend({ ok: literal(true) }));
10745
+ AnchorApifyBudgetSchema = object({
10746
+ dailyRows: number2(),
10747
+ day: string2(),
10748
+ remainingRows: number2(),
10749
+ rowsSent: number2(),
10750
+ spent: boolean2()
10751
+ }).meta({ id: "AnchorApifyBudget" });
10752
+ getAnchorApifyBudget = oc.route({
10753
+ method: "GET",
10754
+ operationId: "getAnchorApifyBudget",
10755
+ path: "/admin/catalogue/anchor/apify-budget",
10756
+ summary: "The metered Apify anchor rung's daily row cap, today's spend, and what is left",
10757
+ tags: ["Admin"]
10758
+ }).input(object({})).output(AnchorApifyBudgetSchema.extend({ ok: literal(true) }));
10759
+ setAnchorApifyBudget = oc.route({
10760
+ method: "PUT",
10761
+ operationId: "setAnchorApifyBudget",
10762
+ path: "/admin/catalogue/anchor/apify-budget",
10763
+ summary: "Set the metered Apify anchor rung's daily row cap (operator)",
10764
+ tags: ["Admin"]
10765
+ }).input(object({ dailyRows: number2().int().min(0) })).output(AnchorApifyBudgetSchema.extend({ ok: literal(true) }));
10766
+ SpotifyAnchorBreakerStateSchema = object({
10767
+ cooldownRemainingMs: number2(),
10768
+ reason: string2().nullable(),
10769
+ throttlesInWindow: number2(),
10770
+ tripped: boolean2(),
10771
+ trippedAt: string2().nullable()
10772
+ }).meta({ id: "SpotifyAnchorBreakerState" });
10773
+ AnchorRungFlagsSchema = object({
10774
+ apifyBudget: AnchorApifyBudgetSchema,
10775
+ apifyEnabled: boolean2(),
10776
+ gateReason: _enum([
10777
+ "friday_window",
10778
+ "flag_off",
10779
+ "breaker_quota",
10780
+ "breaker_throttle",
10781
+ "shared_meter",
10782
+ "open"
10783
+ ]),
10784
+ nextEligibleAt: string2().nullable(),
10785
+ spotifySearchEnabled: boolean2()
10786
+ }).meta({ id: "AnchorRungFlags" });
10787
+ getSpotifyAnchorBreaker = oc.route({
10788
+ method: "GET",
10789
+ operationId: "getSpotifyAnchorBreaker",
10790
+ path: "/admin/catalogue/anchor/breaker",
10791
+ summary: "The Spotify anchor-search throttle breaker: tripped, why, how long left, and the rungs",
10792
+ tags: ["Admin"]
10793
+ }).input(object({})).output(SpotifyAnchorBreakerStateSchema.extend({ ok: literal(true), rungs: AnchorRungFlagsSchema }));
10794
+ resetSpotifyAnchorBreaker = oc.route({
10795
+ method: "POST",
10796
+ operationId: "resetSpotifyAnchorBreaker",
10797
+ path: "/admin/catalogue/anchor/breaker/reset",
10798
+ summary: "Clear the Spotify anchor-search throttle breaker (operator)",
10799
+ tags: ["Admin"]
10800
+ }).input(object({})).output(SpotifyAnchorBreakerStateSchema.extend({ ok: literal(true) }));
10801
+ AppleBreakerStateSchema = object({
10802
+ consecutiveAuthFailures: number2(),
10803
+ cooldownRemainingMs: number2(),
10804
+ tripped: boolean2(),
10805
+ trippedAt: string2().nullable()
10806
+ }).meta({ id: "AppleBreakerState" });
10807
+ resetAppleBreaker = oc.route({
10808
+ method: "POST",
10809
+ operationId: "resetAppleBreaker",
10810
+ path: "/admin/catalogue/apple-breaker/reset",
10811
+ summary: "Clear the Apple failure-regime breaker (operator)",
10812
+ tags: ["Admin"]
10813
+ }).input(object({})).output(AppleBreakerStateSchema.extend({ ok: literal(true) }));
10814
+ adminCatalogueContract = {
10815
+ anchor_track: anchorTrack,
10816
+ certify_track: certifyTrack,
10817
+ clear_wrong_audio: clearWrongAudio,
10818
+ commit_crawl_nodes: commitCrawlNodes,
10819
+ crawl_catalogue: crawlCatalogue,
10820
+ flag_wrong_audio: flagWrongAudio,
10821
+ force_capture: forceCapture,
10822
+ get_anchor_apify_budget: getAnchorApifyBudget,
10823
+ get_capture_budget: getCaptureBudget,
10824
+ get_crawl_status: getCrawlStatus,
10825
+ get_spotify_anchor_breaker: getSpotifyAnchorBreaker,
10826
+ list_catalogue_tracks: listCatalogueTracks,
10827
+ list_unverified_captures: listUnverifiedCaptures,
10828
+ rank_catalogue: rankCatalogue,
10829
+ record_anchor_failure: recordAnchorFailure,
10830
+ record_demand: recordDemand,
10831
+ requeue_anchor: requeueAnchor,
10832
+ requeue_isrc_recovery: requeueIsrcRecovery,
10833
+ requeue_unmatched_captures: requeueUnmatchedCaptures,
10834
+ reset_apple_breaker: resetAppleBreaker,
10835
+ reset_spotify_anchor_breaker: resetSpotifyAnchorBreaker,
10836
+ resolve_anchor: resolveAnchor,
10837
+ resolve_anchor_review: resolveAnchorReview,
10838
+ set_anchor_apify: setAnchorApify,
10839
+ set_anchor_apify_budget: setAnchorApifyBudget,
10840
+ set_anchor_search: setAnchorSearch,
10841
+ set_capture_budget: setCaptureBudget,
10842
+ set_track_dismissed: setTrackDismissed,
10843
+ verify_capture: verifyCapture
10844
+ };
10845
+ });
10846
+
10847
+ // ../../packages/contracts/src/orpc/admin-albums.ts
10848
+ var DescribeAlbumBodySchema, describeAlbum, draftAlbumBio, AlbumBioWorkItemSchema, listAlbumsMissingBio, adminAlbumsContract;
10849
+ var init_admin_albums = __esm(() => {
10850
+ init_dist3();
10851
+ init_zod();
10852
+ DescribeAlbumBodySchema = looseObject({
10853
+ bio: unknown().optional(),
10854
+ dryRun: unknown().optional(),
10855
+ finalAttempt: boolean2().optional(),
10856
+ promptVersion: number2().int().min(0).optional()
10857
+ });
10858
+ describeAlbum = oc.route({
10859
+ method: "POST",
10860
+ operationId: "describeAlbum",
10861
+ path: "/admin/albums/{slug}/bio",
10862
+ summary: "Auto-author an album's voiced bio (fills an empty bio only)",
10863
+ tags: ["Admin"]
10864
+ }).input(DescribeAlbumBodySchema.extend({ slug: string2() })).output(object({
10865
+ bio: string2(),
10866
+ dryRun: literal(true).optional(),
10867
+ gateBypassed: literal(true).optional(),
10868
+ ok: literal(true),
10869
+ skipped: boolean2().optional(),
10870
+ slug: string2(),
10871
+ voiceViolations: array(string2()).optional()
10872
+ }));
10873
+ draftAlbumBio = oc.route({
10874
+ method: "GET",
10875
+ operationId: "draftAlbumBio",
10876
+ path: "/admin/albums/{slug}/bio-draft",
10877
+ summary: "Assemble a ready-to-author bio prompt for an album (Worker-side grounding)",
10878
+ tags: ["Admin"]
10879
+ }).input(object({ slug: string2() })).output(object({
10880
+ findingCount: number2(),
10881
+ found: boolean2(),
10882
+ hasFacts: boolean2(),
10883
+ name: string2(),
10884
+ prompt: string2(),
10885
+ promptVersion: number2()
10886
+ }));
10887
+ AlbumBioWorkItemSchema = object({ id: string2(), name: string2(), slug: string2() }).meta({ id: "AlbumBioWorkItem" });
10888
+ listAlbumsMissingBio = oc.route({
10889
+ method: "GET",
10890
+ operationId: "listAlbumsMissingBio",
10891
+ path: "/admin/albums/bio-queue",
10892
+ summary: "List albums with findings but no bio yet, oldest first (the bio worklist)",
10893
+ tags: ["Admin"]
10894
+ }).input(object({ limit: string2().optional() })).output(object({ albums: array(AlbumBioWorkItemSchema), ok: literal(true) }));
10895
+ adminAlbumsContract = {
10896
+ describe_album: describeAlbum,
10897
+ draft_album_bio: draftAlbumBio,
10898
+ list_albums_missing_bio: listAlbumsMissingBio
10899
+ };
10900
+ });
10901
+
10902
+ // ../../packages/contracts/src/orpc/admin-artifacts.ts
10903
+ var ARTIFACT_CHANGE_API_MAX_LIMIT = 500, ARTIFACT_SNAPSHOT_API_MAX_LIMIT = 200, ARTIFACT_COMPACTION_API_MAX_LIMIT = 1000, ARTIFACT_SUPPORTED_CONTRACTS, ArtifactStreamSchema, ArtifactContractSchema, ConsumerIdSchema, DigestSchema, SequenceSchema, ArtifactRebuildCheckpointSchema, ArtifactConsumerStatusSchema, ArtifactChangeEventSchema, ArtifactSnapshotItemSchema, ArtifactSnapshotPageSchema, ArtifactChangePageSchema, ArtifactCompactionResultSchema, registerArtifactConsumer, getArtifactConsumer, listArtifactSnapshot, checkpointArtifactRebuild, activateArtifactConsumer, listArtifactChanges, acknowledgeArtifactChanges, inactivateArtifactConsumer, compactArtifactChanges, adminArtifactsContract;
10904
+ var init_admin_artifacts = __esm(() => {
10905
+ init_dist3();
10906
+ init_zod();
10907
+ ARTIFACT_SUPPORTED_CONTRACTS = [
10908
+ { formatVersion: 1, stream: "device.album", streamVersion: 1 },
10909
+ { formatVersion: 1, stream: "device.artist", streamVersion: 1 },
10910
+ { formatVersion: 1, stream: "device.finding", streamVersion: 1 },
10911
+ { formatVersion: 1, stream: "device.label", streamVersion: 1 },
10912
+ { formatVersion: 1, stream: "device.track", streamVersion: 1 },
10913
+ { formatVersion: 1, stream: "device.track-artist", streamVersion: 1 },
10914
+ { formatVersion: 1, stream: "sonar.track", streamVersion: 1 }
10915
+ ];
10916
+ ArtifactStreamSchema = _enum([
10917
+ "device.album",
10918
+ "device.artist",
10919
+ "device.finding",
10920
+ "device.label",
10921
+ "device.track",
10922
+ "device.track-artist",
10923
+ "sonar.track"
10924
+ ]);
10925
+ ArtifactContractSchema = strictObject({
10231
10926
  formatVersion: number2().int().positive(),
10232
10927
  stream: ArtifactStreamSchema,
10233
10928
  streamVersion: number2().int().positive()
@@ -10764,6 +11459,7 @@ var init_admin_attention2 = __esm(() => {
10764
11459
  init_dist3();
10765
11460
  init_zod();
10766
11461
  AttentionSourceSchema = _enum([
11462
+ "anchor-failure",
10767
11463
  "anchor-review",
10768
11464
  "artist-review",
10769
11465
  "attach-cues",
@@ -10899,458 +11595,125 @@ var init_admin_backfills = __esm(() => {
10899
11595
  context.addIssue({
10900
11596
  code: "custom",
10901
11597
  message: "Discogs label detail id must match its work id"
10902
- });
10903
- }
10904
- }).meta({ id: "DiscogsLabelCandidate" });
10905
- DiscogsLabelCandidateBatchSchema = array(DiscogsLabelCandidateSchema).max(DISCOGS_LABEL_WORK_LIMIT).superRefine((entries, context) => {
10906
- const slugs = new Set;
10907
- const base64Chars = entries.reduce((total, entry) => total + (entry.image?.bytesBase64.length ?? 0), 0);
10908
- if (base64Chars > MAX_LABEL_IMAGE_BASE64_CHARS * DISCOGS_LABEL_WORK_LIMIT) {
10909
- context.addIssue({
10910
- code: "custom",
10911
- message: "Discogs label-image candidate batch exceeds its decoded-image budget"
10912
- });
10913
- }
10914
- for (const entry of entries) {
10915
- if (slugs.has(entry.slug)) {
10916
- context.addIssue({
10917
- code: "custom",
10918
- message: "Discogs label candidate slugs must be unique"
10919
- });
10920
- return;
10921
- }
10922
- slugs.add(entry.slug);
10923
- }
10924
- });
10925
- DiscogsLabelWorkSchema = object({
10926
- discogsLabelId: DiscogsIdSchema,
10927
- slug: string2().min(1).max(DISCOGS_TEXT_MAX)
10928
- }).meta({ id: "DiscogsLabelWork" });
10929
- DiscogsResolvedSchema = object({
10930
- logId: string2(),
10931
- masterId: number2().optional(),
10932
- releaseId: number2(),
10933
- source: string2()
10934
- }).meta({ id: "DiscogsBackfillResolved" });
10935
- LastfmFailedSchema = object({
10936
- error: string2(),
10937
- logId: string2()
10938
- }).meta({ id: "LastfmBackfillFailed" });
10939
- AppleMusicResolvedSchema = object({
10940
- logId: string2(),
10941
- url: string2()
10942
- }).meta({ id: "AppleMusicBackfillResolved" });
10943
- AppleMusicFailedSchema = object({
10944
- error: string2(),
10945
- logId: string2()
10946
- }).meta({ id: "AppleMusicBackfillFailed" });
10947
- backfillDiscogs = oc.route({
10948
- inputStructure: "detailed",
10949
- method: "POST",
10950
- operationId: "backfillDiscogs",
10951
- path: "/admin/backfill/discogs",
10952
- summary: "Back-fill Discogs release ids over published findings (batched)",
10953
- tags: ["Admin"]
10954
- }).input(object({
10955
- body: object({
10956
- discogsCandidates: DiscogsReleaseCandidateBatchSchema.optional()
10957
- }).optional(),
10958
- query: object({
10959
- boxFetch: string2().optional(),
10960
- cursor: string2().optional(),
10961
- dryRun: string2().optional(),
10962
- limit: string2().optional()
10963
- })
10964
- })).output(object({
10965
- discogsWork: array(DiscogsReleaseWorkSchema).max(DISCOGS_RELEASE_WORK_LIMIT),
10966
- dryRun: boolean2(),
10967
- nextCursor: string2().nullable(),
10968
- ok: literal(true),
10969
- rateLimited: boolean2(),
10970
- rateLimitedBy: _enum(["discogs", "musicbrainz"]).nullable(),
10971
- resolved: array(DiscogsResolvedSchema),
10972
- resolvedCount: number2(),
10973
- skipped: array(string2()),
10974
- skippedCount: number2(),
10975
- unresolved: array(string2()),
10976
- unresolvedCount: number2()
10977
- }));
10978
- DiscogsFactsResolvedSchema = object({
10979
- catno: string2(),
10980
- slug: string2()
10981
- }).meta({ id: "DiscogsFactsResolved" });
10982
- DiscogsFactsFailedSchema = object({
10983
- error: string2(),
10984
- slug: string2()
10985
- }).meta({ id: "DiscogsFactsFailed" });
10986
- backfillDiscogsFacts = oc.route({
10987
- inputStructure: "detailed",
10988
- method: "POST",
10989
- operationId: "backfillDiscogsFacts",
10990
- path: "/admin/backfill/discogs-facts",
10991
- summary: "Back-fill album catalogue numbers + styles from already-resolved Discogs releases",
10992
- tags: ["Admin"]
10993
- }).input(object({
10994
- body: object({
10995
- discogsCandidates: DiscogsFactsCandidateBatchSchema.optional()
10996
- }).optional(),
10997
- query: object({
10998
- boxFetch: string2().optional(),
10999
- dryRun: string2().optional(),
11000
- limit: string2().optional()
11001
- })
11002
- })).output(object({
11003
- configured: boolean2(),
11004
- discogsWork: array(DiscogsFactsWorkSchema).max(DISCOGS_FACTS_WORK_LIMIT),
11005
- dryRun: boolean2(),
11006
- failed: array(DiscogsFactsFailedSchema),
11007
- failedCount: number2(),
11008
- none: array(string2()),
11009
- noneCount: number2(),
11010
- ok: literal(true),
11011
- rateLimited: boolean2(),
11012
- resolved: array(DiscogsFactsResolvedSchema),
11013
- resolvedCount: number2()
11014
- }));
11015
- backfillLastfm = oc.route({
11016
- inputStructure: "detailed",
11017
- method: "POST",
11018
- operationId: "backfillLastfm",
11019
- path: "/admin/backfill/lastfm",
11020
- summary: "Back-fill Last.fm loves over published findings (batched)",
11021
- tags: ["Admin"]
11022
- }).input(object({
11023
- query: object({
11024
- cursor: string2().optional(),
11025
- dryRun: string2().optional(),
11026
- limit: string2().optional()
11027
- })
11028
- })).output(object({
11029
- dryRun: boolean2(),
11030
- failed: array(LastfmFailedSchema),
11031
- failedCount: number2(),
11032
- loved: array(string2()),
11033
- lovedCount: number2(),
11034
- nextCursor: string2().nullable(),
11035
- ok: literal(true),
11036
- rateLimited: boolean2(),
11037
- skipped: array(string2()),
11038
- skippedCount: number2()
11039
- }));
11040
- backfillAppleMusic = oc.route({
11041
- inputStructure: "detailed",
11042
- method: "POST",
11043
- operationId: "backfillAppleMusic",
11044
- path: "/admin/backfill/apple-music",
11045
- summary: "Back-fill Apple Music URLs over published findings by exact ISRC (batched)",
11046
- tags: ["Admin"]
11047
- }).input(object({
11048
- query: object({
11049
- cursor: string2().optional(),
11050
- dryRun: string2().optional(),
11051
- limit: string2().optional()
11052
- })
11053
- })).output(object({
11054
- albumFactsWritten: number2(),
11055
- breakerTripped: boolean2(),
11056
- configured: boolean2(),
11057
- dryRun: boolean2(),
11058
- failed: array(AppleMusicFailedSchema),
11059
- failedCount: number2(),
11060
- nextCursor: string2().nullable(),
11061
- ok: literal(true),
11062
- rateLimited: boolean2(),
11063
- resolved: array(AppleMusicResolvedSchema),
11064
- resolvedCount: number2(),
11065
- skipped: array(string2()),
11066
- skippedCount: number2(),
11067
- unresolved: array(string2()),
11068
- unresolvedCount: number2()
11069
- }));
11070
- AppleCatalogueResolvedSchema = object({
11071
- trackId: string2(),
11072
- url: string2()
11073
- }).meta({ id: "AppleCatalogueResolved" });
11074
- AppleCatalogueFailedSchema = object({
11075
- error: string2(),
11076
- trackId: string2()
11077
- }).meta({ id: "AppleCatalogueFailed" });
11078
- backfillAppleCatalogue = oc.route({
11079
- inputStructure: "detailed",
11080
- method: "POST",
11081
- operationId: "backfillAppleCatalogue",
11082
- path: "/admin/backfill/apple-catalogue",
11083
- summary: "Back-fill Apple URLs + album facts over catalogue tracks by exact ISRC (batched)",
11084
- tags: ["Admin"]
11085
- }).input(object({
11086
- query: object({
11087
- dryRun: string2().optional(),
11088
- limit: string2().optional()
11089
- })
11090
- })).output(object({
11091
- albumFactsWritten: number2(),
11092
- breakerTripped: boolean2(),
11093
- configured: boolean2(),
11094
- dryRun: boolean2(),
11095
- failed: array(AppleCatalogueFailedSchema),
11096
- failedCount: number2(),
11097
- ok: literal(true),
11098
- rateLimited: boolean2(),
11099
- resolved: array(AppleCatalogueResolvedSchema),
11100
- resolvedCount: number2(),
11101
- unresolved: array(string2()),
11102
- unresolvedCount: number2()
11103
- }));
11104
- BeatportResolvedSchema = object({
11598
+ });
11599
+ }
11600
+ }).meta({ id: "DiscogsLabelCandidate" });
11601
+ DiscogsLabelCandidateBatchSchema = array(DiscogsLabelCandidateSchema).max(DISCOGS_LABEL_WORK_LIMIT).superRefine((entries, context) => {
11602
+ const slugs = new Set;
11603
+ const base64Chars = entries.reduce((total, entry) => total + (entry.image?.bytesBase64.length ?? 0), 0);
11604
+ if (base64Chars > MAX_LABEL_IMAGE_BASE64_CHARS * DISCOGS_LABEL_WORK_LIMIT) {
11605
+ context.addIssue({
11606
+ code: "custom",
11607
+ message: "Discogs label-image candidate batch exceeds its decoded-image budget"
11608
+ });
11609
+ }
11610
+ for (const entry of entries) {
11611
+ if (slugs.has(entry.slug)) {
11612
+ context.addIssue({
11613
+ code: "custom",
11614
+ message: "Discogs label candidate slugs must be unique"
11615
+ });
11616
+ return;
11617
+ }
11618
+ slugs.add(entry.slug);
11619
+ }
11620
+ });
11621
+ DiscogsLabelWorkSchema = object({
11622
+ discogsLabelId: DiscogsIdSchema,
11623
+ slug: string2().min(1).max(DISCOGS_TEXT_MAX)
11624
+ }).meta({ id: "DiscogsLabelWork" });
11625
+ DiscogsResolvedSchema = object({
11105
11626
  logId: string2(),
11106
- url: string2()
11107
- }).meta({ id: "BeatportResolved" });
11108
- BeatportFailedSchema = object({
11627
+ masterId: number2().optional(),
11628
+ releaseId: number2(),
11629
+ source: string2()
11630
+ }).meta({ id: "DiscogsBackfillResolved" });
11631
+ LastfmFailedSchema = object({
11109
11632
  error: string2(),
11110
11633
  logId: string2()
11111
- }).meta({ id: "BeatportFailed" });
11112
- BeatportCatalogueResolvedSchema = object({
11113
- trackId: string2(),
11634
+ }).meta({ id: "LastfmBackfillFailed" });
11635
+ AppleMusicResolvedSchema = object({
11636
+ logId: string2(),
11114
11637
  url: string2()
11115
- }).meta({ id: "BeatportCatalogueResolved" });
11116
- BeatportCatalogueFailedSchema = object({
11638
+ }).meta({ id: "AppleMusicBackfillResolved" });
11639
+ AppleMusicFailedSchema = object({
11117
11640
  error: string2(),
11118
- trackId: string2()
11119
- }).meta({ id: "BeatportCatalogueFailed" });
11120
- backfillBeatport = oc.route({
11641
+ logId: string2()
11642
+ }).meta({ id: "AppleMusicBackfillFailed" });
11643
+ backfillDiscogs = oc.route({
11121
11644
  inputStructure: "detailed",
11122
11645
  method: "POST",
11123
- operationId: "backfillBeatport",
11124
- path: "/admin/backfill/beatport",
11125
- summary: "Back-fill Beatport URLs over published findings by exact ISRC",
11646
+ operationId: "backfillDiscogs",
11647
+ path: "/admin/backfill/discogs",
11648
+ summary: "Back-fill Discogs release ids over published findings (batched)",
11126
11649
  tags: ["Admin"]
11127
11650
  }).input(object({
11651
+ body: object({
11652
+ discogsCandidates: DiscogsReleaseCandidateBatchSchema.optional()
11653
+ }).optional(),
11128
11654
  query: object({
11655
+ boxFetch: string2().optional(),
11129
11656
  cursor: string2().optional(),
11130
11657
  dryRun: string2().optional(),
11131
11658
  limit: string2().optional()
11132
11659
  })
11133
11660
  })).output(object({
11134
- catalogueFailed: array(BeatportCatalogueFailedSchema),
11135
- catalogueFailedCount: number2(),
11136
- catalogueResolved: array(BeatportCatalogueResolvedSchema),
11137
- catalogueResolvedCount: number2(),
11138
- catalogueUnresolved: array(string2()),
11139
- catalogueUnresolvedCount: number2(),
11140
- configured: boolean2(),
11661
+ discogsWork: array(DiscogsReleaseWorkSchema).max(DISCOGS_RELEASE_WORK_LIMIT),
11141
11662
  dryRun: boolean2(),
11142
- failed: array(BeatportFailedSchema),
11143
- failedCount: number2(),
11144
11663
  nextCursor: string2().nullable(),
11145
11664
  ok: literal(true),
11146
- resolved: array(BeatportResolvedSchema),
11665
+ rateLimited: boolean2(),
11666
+ rateLimitedBy: _enum(["discogs", "musicbrainz"]).nullable(),
11667
+ resolved: array(DiscogsResolvedSchema),
11147
11668
  resolvedCount: number2(),
11148
11669
  skipped: array(string2()),
11149
11670
  skippedCount: number2(),
11150
11671
  unresolved: array(string2()),
11151
11672
  unresolvedCount: number2()
11152
11673
  }));
11153
- DeezerResolvedSchema = object({
11154
- trackId: string2(),
11155
- url: string2()
11156
- }).meta({ id: "DeezerResolved" });
11157
- DeezerFailedSchema = object({
11158
- error: string2(),
11159
- trackId: string2()
11160
- }).meta({ id: "DeezerFailed" });
11161
- backfillDeezer = oc.route({
11162
- inputStructure: "detailed",
11163
- method: "POST",
11164
- operationId: "backfillDeezer",
11165
- path: "/admin/backfill/deezer",
11166
- summary: "Back-fill Deezer track ids over certified + catalogue rows by exact ISRC",
11167
- tags: ["Admin"]
11168
- }).input(object({
11169
- query: object({
11170
- dryRun: string2().optional(),
11171
- limit: string2().optional()
11172
- })
11173
- })).output(object({
11174
- dryRun: boolean2(),
11175
- failed: array(DeezerFailedSchema),
11176
- failedCount: number2(),
11177
- ok: literal(true),
11178
- rateLimited: boolean2(),
11179
- resolved: array(DeezerResolvedSchema),
11180
- resolvedCount: number2(),
11181
- unresolved: array(string2()),
11182
- unresolvedCount: number2(),
11183
- unvouchable: array(string2()),
11184
- unvouchableCount: number2()
11185
- }));
11186
- backfillLabelReleases = oc.route({
11187
- method: "POST",
11188
- operationId: "backfillLabelReleases",
11189
- path: "/admin/backfill/label-releases",
11190
- summary: "Tap Spotify's fresh releases for enabled seed labels into catalogue rows (bounded)",
11191
- tags: ["Admin"]
11192
- }).input(object({
11193
- dryRun: boolean2().default(false),
11194
- limit: number3().int().min(1).max(200).default(5)
11195
- })).output(object({
11196
- albumsMatched: number2(),
11197
- albumsSeen: number2(),
11198
- budgetPaused: boolean2(),
11199
- configured: boolean2(),
11200
- dryRun: boolean2(),
11201
- failedFetches: number2(),
11202
- failedLabels: array(string2()),
11203
- fetchCeilingHit: boolean2(),
11204
- labelSlugs: array(string2()),
11205
- labelsProbed: number2(),
11206
- newRows: number2(),
11207
- newTrackIds: array(string2()),
11208
- ok: literal(true),
11209
- rateLimited: boolean2(),
11210
- skippedKnown: number2(),
11211
- skippedUndated: number2(),
11212
- skippedUngrounded: number2(),
11213
- tracksSkippedArtistRule: number2().optional()
11214
- }));
11215
- LabelImagesBackfillFailedSchema = object({
11674
+ DiscogsFactsResolvedSchema = object({
11675
+ catno: string2(),
11676
+ slug: string2()
11677
+ }).meta({ id: "DiscogsFactsResolved" });
11678
+ DiscogsFactsFailedSchema = object({
11216
11679
  error: string2(),
11217
11680
  slug: string2()
11218
- }).meta({ id: "LabelImagesBackfillFailed" });
11219
- backfillLabelImages = oc.route({
11681
+ }).meta({ id: "DiscogsFactsFailed" });
11682
+ backfillDiscogsFacts = oc.route({
11220
11683
  inputStructure: "detailed",
11221
11684
  method: "POST",
11222
- operationId: "backfillLabelImages",
11223
- path: "/admin/backfill/label-images",
11224
- summary: "Resolve label logos (Discogs → Wikidata) into R2 for existing labels (batched)",
11685
+ operationId: "backfillDiscogsFacts",
11686
+ path: "/admin/backfill/discogs-facts",
11687
+ summary: "Back-fill album catalogue numbers + styles from already-resolved Discogs releases",
11225
11688
  tags: ["Admin"]
11226
11689
  }).input(object({
11227
11690
  body: object({
11228
- discogsCandidates: DiscogsLabelCandidateBatchSchema.optional()
11691
+ discogsCandidates: DiscogsFactsCandidateBatchSchema.optional()
11229
11692
  }).optional(),
11230
11693
  query: object({
11231
11694
  boxFetch: string2().optional(),
11232
- cursor: string2().optional(),
11233
- dryRun: string2().optional(),
11234
- limit: string2().optional()
11235
- })
11236
- })).output(object({
11237
- discogsWork: array(DiscogsLabelWorkSchema).max(DISCOGS_LABEL_WORK_LIMIT),
11238
- dryRun: boolean2(),
11239
- failed: array(LabelImagesBackfillFailedSchema),
11240
- failedCount: number2(),
11241
- nextCursor: string2().nullable(),
11242
- none: array(string2()),
11243
- noneCount: number2(),
11244
- ok: literal(true),
11245
- rateLimited: boolean2(),
11246
- resolved: array(string2()),
11247
- resolvedCount: number2()
11248
- }));
11249
- LabelLineageBackfillFailedSchema = object({
11250
- error: string2(),
11251
- slug: string2()
11252
- }).meta({ id: "LabelLineageBackfillFailed" });
11253
- backfillLabelLineage = oc.route({
11254
- inputStructure: "detailed",
11255
- method: "POST",
11256
- operationId: "backfillLabelLineage",
11257
- path: "/admin/backfill/label-lineage",
11258
- summary: "Resolve label lineage (founding date, place, parent imprint) from MusicBrainz (batched)",
11259
- tags: ["Admin"]
11260
- }).input(object({
11261
- query: object({
11262
- cursor: string2().optional(),
11263
- dryRun: string2().optional(),
11264
- limit: string2().optional()
11265
- })
11266
- })).output(object({
11267
- dryRun: boolean2(),
11268
- failed: array(LabelLineageBackfillFailedSchema),
11269
- failedCount: number2(),
11270
- nextCursor: string2().nullable(),
11271
- none: array(string2()),
11272
- noneCount: number2(),
11273
- ok: literal(true),
11274
- rateLimited: boolean2(),
11275
- resolved: array(string2()),
11276
- resolvedCount: number2(),
11277
- unmatchedParents: number2()
11278
- }));
11279
- CoverMastersFailedSchema = object({
11280
- error: string2(),
11281
- slug: string2()
11282
- }).meta({ id: "CoverMastersFailed" });
11283
- backfillCoverMasters = oc.route({
11284
- inputStructure: "detailed",
11285
- method: "POST",
11286
- operationId: "backfillCoverMasters",
11287
- path: "/admin/backfill/cover-masters",
11288
- summary: "Resolve owned ≤1200² cover masters (album/artist) into R2 (batched)",
11289
- tags: ["Admin"]
11290
- }).input(object({
11291
- query: object({
11292
- cursor: string2().optional(),
11293
- dryRun: string2().optional(),
11294
- kind: string2().optional(),
11295
- limit: string2().optional(),
11296
- retry: string2().optional()
11297
- })
11298
- })).output(object({
11299
- dryRun: boolean2(),
11300
- failed: array(CoverMastersFailedSchema),
11301
- failedCount: number2(),
11302
- kind: _enum(["album", "artist"]),
11303
- nextCursor: string2().nullable(),
11304
- none: array(string2()),
11305
- noneCount: number2(),
11306
- ok: literal(true),
11307
- rateLimited: boolean2(),
11308
- requeued: array(string2()).optional(),
11309
- requeuedCount: number2().optional(),
11310
- resolved: array(string2()),
11311
- resolvedCount: number2()
11312
- }));
11313
- RecordingMbidsFailedSchema = object({
11314
- error: string2(),
11315
- trackId: string2()
11316
- }).meta({ id: "RecordingMbidsBackfillFailed" });
11317
- backfillRecordingMbids = oc.route({
11318
- inputStructure: "detailed",
11319
- method: "POST",
11320
- operationId: "backfillRecordingMbids",
11321
- path: "/admin/backfill/recording-mbids",
11322
- summary: "Fill MusicBrainz recording MBIDs (crawler PK strip + ISRC resolve) over tracks (batched)",
11323
- tags: ["Admin"]
11324
- }).input(object({
11325
- query: object({
11326
- cursor: string2().optional(),
11327
11695
  dryRun: string2().optional(),
11328
- isrcRefreshLimit: string2().optional(),
11329
11696
  limit: string2().optional()
11330
11697
  })
11331
11698
  })).output(object({
11699
+ configured: boolean2(),
11700
+ discogsWork: array(DiscogsFactsWorkSchema).max(DISCOGS_FACTS_WORK_LIMIT),
11332
11701
  dryRun: boolean2(),
11333
- failed: array(RecordingMbidsFailedSchema),
11702
+ failed: array(DiscogsFactsFailedSchema),
11334
11703
  failedCount: number2(),
11335
- isrcRefreshMissed: array(string2()),
11336
- isrcRefreshMissedCount: number2(),
11337
- isrcRefreshed: array(string2()),
11338
- isrcRefreshedCount: number2(),
11339
- missed: array(string2()),
11340
- missedCount: number2(),
11341
- nextCursor: string2().nullable(),
11704
+ none: array(string2()),
11705
+ noneCount: number2(),
11342
11706
  ok: literal(true),
11343
- prefixStripped: number2(),
11344
11707
  rateLimited: boolean2(),
11345
- resolved: array(string2()),
11708
+ resolved: array(DiscogsFactsResolvedSchema),
11346
11709
  resolvedCount: number2()
11347
11710
  }));
11348
- backfillArtistEdges = oc.route({
11711
+ backfillLastfm = oc.route({
11349
11712
  inputStructure: "detailed",
11350
11713
  method: "POST",
11351
- operationId: "backfillArtistEdges",
11352
- path: "/admin/backfill/artist-edges",
11353
- summary: "Fold artists_json names onto existing artist identities → track_artists (batched)",
11714
+ operationId: "backfillLastfm",
11715
+ path: "/admin/backfill/lastfm",
11716
+ summary: "Back-fill Last.fm loves over published findings (batched)",
11354
11717
  tags: ["Admin"]
11355
11718
  }).input(object({
11356
11719
  query: object({
@@ -11360,25 +11723,22 @@ var init_admin_backfills = __esm(() => {
11360
11723
  })
11361
11724
  })).output(object({
11362
11725
  dryRun: boolean2(),
11363
- edgesWritten: number2(),
11364
- fullyMatched: array(string2()),
11365
- fullyMatchedCount: number2(),
11726
+ failed: array(LastfmFailedSchema),
11727
+ failedCount: number2(),
11728
+ loved: array(string2()),
11729
+ lovedCount: number2(),
11366
11730
  nextCursor: string2().nullable(),
11367
11731
  ok: literal(true),
11368
- partiallyMatched: array(string2()),
11369
- partiallyMatchedCount: number2(),
11370
- queueDepth: number2(),
11371
- scanned: number2(),
11372
- unmatchedNames: number2(),
11373
- zeroMatched: array(string2()),
11374
- zeroMatchedCount: number2()
11732
+ rateLimited: boolean2(),
11733
+ skipped: array(string2()),
11734
+ skippedCount: number2()
11375
11735
  }));
11376
- backfillArtistCredits = oc.route({
11736
+ backfillAppleMusic = oc.route({
11377
11737
  inputStructure: "detailed",
11378
11738
  method: "POST",
11379
- operationId: "backfillArtistCredits",
11380
- path: "/admin/backfill/artist-credits",
11381
- summary: "Mint identity-true artists from MusicBrainz credits for slice 0's zero-matched residual (batched)",
11739
+ operationId: "backfillAppleMusic",
11740
+ path: "/admin/backfill/apple-music",
11741
+ summary: "Back-fill Apple Music URLs over published findings by exact ISRC (batched)",
11382
11742
  tags: ["Admin"]
11383
11743
  }).input(object({
11384
11744
  query: object({
@@ -11387,699 +11747,395 @@ var init_admin_backfills = __esm(() => {
11387
11747
  limit: string2().optional()
11388
11748
  })
11389
11749
  })).output(object({
11390
- adoptedArtists: number2(),
11750
+ albumFactsWritten: number2(),
11751
+ breakerTripped: boolean2(),
11752
+ configured: boolean2(),
11391
11753
  dryRun: boolean2(),
11392
- edgesWritten: number2(),
11393
- matchedArtists: number2(),
11394
- mintedArtists: number2(),
11754
+ failed: array(AppleMusicFailedSchema),
11755
+ failedCount: number2(),
11395
11756
  nextCursor: string2().nullable(),
11396
11757
  ok: literal(true),
11397
11758
  rateLimited: boolean2(),
11398
- scanned: number2(),
11399
- skippedNoIdentity: number2()
11400
- }));
11401
- adminBackfillsContract = {
11402
- backfill_apple_catalogue: backfillAppleCatalogue,
11403
- backfill_apple_music: backfillAppleMusic,
11404
- backfill_artist_credits: backfillArtistCredits,
11405
- backfill_artist_edges: backfillArtistEdges,
11406
- backfill_beatport: backfillBeatport,
11407
- backfill_cover_masters: backfillCoverMasters,
11408
- backfill_deezer: backfillDeezer,
11409
- backfill_discogs: backfillDiscogs,
11410
- backfill_discogs_facts: backfillDiscogsFacts,
11411
- backfill_label_images: backfillLabelImages,
11412
- backfill_label_lineage: backfillLabelLineage,
11413
- backfill_label_releases: backfillLabelReleases,
11414
- backfill_lastfm: backfillLastfm,
11415
- backfill_recording_mbids: backfillRecordingMbids
11416
- };
11417
- });
11418
-
11419
- // ../../packages/contracts/src/orpc/admin-bios.ts
11420
- var BioEntityKindSchema, resolveBioReview, adminBiosContract;
11421
- var init_admin_bios = __esm(() => {
11422
- init_dist3();
11423
- init_zod();
11424
- BioEntityKindSchema = _enum(["album", "artist", "label"]).meta({ id: "BioEntityKind" });
11425
- resolveBioReview = oc.route({
11426
- method: "POST",
11427
- operationId: "resolveBioReview",
11428
- path: "/admin/bio-reviews/{kind}/{slug}/resolve",
11429
- summary: "Rule on a bio that landed past the voice gate: keep it or send it back (operator)",
11430
- tags: ["Admin"]
11431
- }).input(object({
11432
- kind: BioEntityKindSchema,
11433
- resolution: _enum(["keep", "rewrite"]),
11434
- slug: string2()
11435
- })).output(object({
11436
- kind: BioEntityKindSchema,
11437
- ok: literal(true),
11438
- resolution: _enum(["keep", "rewrite"]),
11439
- slug: string2()
11759
+ resolved: array(AppleMusicResolvedSchema),
11760
+ resolvedCount: number2(),
11761
+ skipped: array(string2()),
11762
+ skippedCount: number2(),
11763
+ unresolved: array(string2()),
11764
+ unresolvedCount: number2()
11440
11765
  }));
11441
- adminBiosContract = {
11442
- resolve_bio_review: resolveBioReview
11443
- };
11444
- });
11445
-
11446
- // ../../packages/contracts/src/orpc/admin-catalogue.ts
11447
- var CatalogueLensSchema, CapturePriorityReasonSchema, CatalogueMatchSchema, CatalogueTrackItemSchema, CatalogueSummarySchema, listCatalogueTracks, rankCatalogue, recordDemand, clearWrongAudio, requeueUnmatchedCaptures, requeueAnchor, requeueIsrcRecovery, flagWrongAudio, forceCapture, certifyTrack, setTrackDismissed, CaptureVerifyItemSchema, listUnverifiedCaptures, verifyCapture, CrawlPassSchema, CrawlPhaseInitializationSchema, MAX_CRAWL_PREPARE_LIMIT = 6, CrawlFetchPlanSchema, SuppliedCrawlBodySchema, MAX_CRAWL_COMMIT_BATCH, CRAWL_COMMIT_TOKEN_MAX_BYTES, CRAWL_COMMIT_BATCH_MAX_TOTAL_BYTES, CrawlCommitItemSchema, CrawlCommitReceiptSchema, CrawlPhaseCapabilitiesSchema, CrawlPhaseInputSchema, CrawlPhaseOutputSchema, CrawlStatusSchema, crawlCatalogue, commitCrawlNodes, getCrawlStatus, ANCHOR_CANDIDATE_LIMIT = 100, ANCHOR_ARTIST_LIMIT = 20, ANCHOR_TEXT_MAX = 300, ANCHOR_ISRC_MAX = 64, ANCHOR_ID_MAX = 64, ANCHOR_URL_MAX = 2048, AnchorCandidateSchema, anchorTrack, DEEZER_CANDIDATE_LIMIT = 5, DEEZER_TEXT_MAX = 300, DEEZER_ISRC_MAX = 64, DEEZER_TRACK_ID_MAX = 32, DeezerIsrcCandidateSchema, resolveAnchor, resolveAnchorReview, setAnchorSearch, setAnchorApify, CaptureBudgetStateSchema, getCaptureBudget, setCaptureBudget, AnchorApifyBudgetSchema, getAnchorApifyBudget, setAnchorApifyBudget, SpotifyAnchorBreakerStateSchema, AnchorRungFlagsSchema, getSpotifyAnchorBreaker, resetSpotifyAnchorBreaker, AppleBreakerStateSchema, resetAppleBreaker, adminCatalogueContract;
11448
- var init_admin_catalogue = __esm(() => {
11449
- init_dist3();
11450
- init_zod();
11451
- CatalogueLensSchema = _enum(["capture", "dismissed", "ear", "failed", "quarantine", "unmatched"]).meta({ id: "CatalogueLens" });
11452
- CapturePriorityReasonSchema = object({
11453
- kind: _enum(["artist", "label", "none", "seed-label", "skipped-label", "unauthorized"]),
11454
- name: string2().nullable()
11455
- }).meta({ id: "CapturePriorityReason" });
11456
- CatalogueMatchSchema = object({
11457
- artists: array(string2()),
11458
- logId: string2().nullable(),
11459
- title: string2(),
11460
- trackId: string2()
11461
- }).meta({ id: "CatalogueMatch" });
11462
- CatalogueTrackItemSchema = object({
11463
- albumImageUrl: string2().nullable(),
11464
- appleMusicUrl: string2().nullable(),
11465
- artists: array(string2()),
11466
- bpm: number2().nullable(),
11467
- capturePriority: number2().nullable(),
11468
- captureReason: CapturePriorityReasonSchema.nullable(),
11469
- captureStatus: string2().nullable(),
11470
- captureVerification: string2().nullable(),
11471
- dismissedAt: string2().nullable(),
11472
- duplicateOf: CatalogueMatchSchema.nullable(),
11473
- hasCapturedAudio: boolean2(),
11474
- hasPreview: boolean2(),
11475
- isrc: string2().nullable(),
11476
- key: string2().nullable(),
11477
- label: string2().nullable(),
11478
- nearestFinding: CatalogueMatchSchema.nullable(),
11479
- nearestFindingScore: number2().nullable(),
11480
- rankedAt: string2().nullable(),
11481
- releaseDate: string2().nullable(),
11482
- sourceAudioAttemptedAt: string2().nullable().optional(),
11483
- spotifyUrl: string2().nullable(),
11484
- title: string2(),
11766
+ AppleCatalogueResolvedSchema = object({
11767
+ trackId: string2(),
11768
+ url: string2()
11769
+ }).meta({ id: "AppleCatalogueResolved" });
11770
+ AppleCatalogueFailedSchema = object({
11771
+ error: string2(),
11485
11772
  trackId: string2()
11486
- }).meta({ id: "CatalogueTrackItem" });
11487
- CatalogueSummarySchema = object({
11488
- awaitingCapture: number2(),
11489
- awaitingRank: number2(),
11490
- dismissed: number2(),
11491
- quarantined: number2(),
11492
- ranked: number2(),
11493
- total: number2()
11494
- }).meta({ id: "CatalogueSummary" });
11495
- listCatalogueTracks = oc.route({
11496
- method: "GET",
11497
- operationId: "listCatalogueTracks",
11498
- path: "/admin/catalogue",
11499
- summary: "The ranked catalogue: closest to a finding (`ear`), or next to capture (`capture`)",
11500
- tags: ["Admin"]
11501
- }).input(object({
11502
- lens: CatalogueLensSchema.default("ear"),
11503
- limit: number3().int().min(1).max(200).default(50)
11504
- })).output(object({
11505
- ok: literal(true),
11506
- summary: CatalogueSummarySchema,
11507
- tracks: array(CatalogueTrackItemSchema)
11508
- }));
11509
- rankCatalogue = oc.route({
11773
+ }).meta({ id: "AppleCatalogueFailed" });
11774
+ backfillAppleCatalogue = oc.route({
11775
+ inputStructure: "detailed",
11510
11776
  method: "POST",
11511
- operationId: "rankCatalogue",
11512
- path: "/admin/catalogue/rank",
11513
- summary: "One tick of the catalogue ranking sweep (nearest finding + capture priority)",
11777
+ operationId: "backfillAppleCatalogue",
11778
+ path: "/admin/backfill/apple-catalogue",
11779
+ summary: "Back-fill Apple URLs + album facts over catalogue tracks by exact ISRC (batched)",
11514
11780
  tags: ["Admin"]
11515
11781
  }).input(object({
11516
- countRemaining: boolean3().default(false),
11517
- limit: number3().int().min(1).max(1000).default(250)
11782
+ query: object({
11783
+ dryRun: string2().optional(),
11784
+ limit: string2().optional()
11785
+ })
11518
11786
  })).output(object({
11787
+ albumFactsWritten: number2(),
11788
+ breakerTripped: boolean2(),
11789
+ configured: boolean2(),
11790
+ dryRun: boolean2(),
11791
+ failed: array(AppleCatalogueFailedSchema),
11792
+ failedCount: number2(),
11519
11793
  ok: literal(true),
11520
- summary: object({
11521
- catalogueDuplicates: number2(),
11522
- corpus: string2(),
11523
- embeddedFindings: number2(),
11524
- findings: number2(),
11525
- prioritized: number2(),
11526
- quarantined: number2(),
11527
- remaining: number2(),
11528
- scored: number2()
11529
- }),
11530
- telescope: union([
11531
- object({ changed: boolean2(), ok: literal(true), size: number2() }),
11532
- object({ ok: literal(false), reason: string2() })
11533
- ]).optional()
11534
- }));
11535
- recordDemand = oc.route({
11536
- method: "POST",
11537
- operationId: "recordDemand",
11538
- path: "/admin/catalogue/demand",
11539
- summary: "One demand tick: reorder crawl/capture priority from Simple Analytics pageviews",
11540
- tags: ["Admin"]
11541
- }).input(object({})).output(object({
11542
- ok: literal(true),
11543
- summary: object({
11544
- configured: boolean2(),
11545
- demandedArtists: number2(),
11546
- demandedLabels: number2(),
11547
- frontierPromoted: number2(),
11548
- pagesRead: number2(),
11549
- totalPageviews: number2(),
11550
- tracksScored: number2(),
11551
- unknownSlugs: number2(),
11552
- window: object({ end: string2(), start: string2() })
11553
- })
11794
+ rateLimited: boolean2(),
11795
+ resolved: array(AppleCatalogueResolvedSchema),
11796
+ resolvedCount: number2(),
11797
+ unresolved: array(string2()),
11798
+ unresolvedCount: number2()
11554
11799
  }));
11555
- clearWrongAudio = oc.route({
11556
- method: "POST",
11557
- operationId: "clearWrongAudio",
11558
- path: "/admin/catalogue/wrong-audio/clear",
11559
- summary: "Overrule the wrong-audio quarantine on one catalogue row (operator)",
11560
- tags: ["Admin"]
11561
- }).input(object({ trackId: string2().min(1) })).output(object({ cleared: boolean2(), ok: literal(true) }));
11562
- requeueUnmatchedCaptures = oc.route({
11563
- method: "POST",
11564
- operationId: "requeueUnmatchedCaptures",
11565
- path: "/admin/catalogue/captures/requeue-unmatched",
11566
- summary: "Re-queue terminal-unmatched catalogue captures after a matcher improvement (operator)",
11567
- tags: ["Admin"]
11568
- }).input(object({})).output(object({ ok: literal(true), requeued: number2(), skippedVetoed: number2() }));
11569
- requeueAnchor = oc.route({
11570
- method: "POST",
11571
- operationId: "requeueAnchor",
11572
- path: "/admin/catalogue/anchor/requeue",
11573
- summary: "Clear named rows' anchor re-ask backoff so the next tick retries them (operator)",
11574
- tags: ["Admin"]
11575
- }).input(object({ trackIds: array(string2().min(1)).min(1).max(250) })).output(object({ ok: literal(true), requeued: number2() }));
11576
- requeueIsrcRecovery = oc.route({
11800
+ BeatportResolvedSchema = object({
11801
+ logId: string2(),
11802
+ url: string2()
11803
+ }).meta({ id: "BeatportResolved" });
11804
+ BeatportFailedSchema = object({
11805
+ error: string2(),
11806
+ logId: string2()
11807
+ }).meta({ id: "BeatportFailed" });
11808
+ BeatportCatalogueResolvedSchema = object({
11809
+ trackId: string2(),
11810
+ url: string2()
11811
+ }).meta({ id: "BeatportCatalogueResolved" });
11812
+ BeatportCatalogueFailedSchema = object({
11813
+ error: string2(),
11814
+ trackId: string2()
11815
+ }).meta({ id: "BeatportCatalogueFailed" });
11816
+ backfillBeatport = oc.route({
11817
+ inputStructure: "detailed",
11577
11818
  method: "POST",
11578
- operationId: "requeueIsrcRecovery",
11579
- path: "/admin/catalogue/isrc-recovery/requeue",
11580
- summary: "Clear Deezer-empty ISRC-recovery stamps from a named window (operator)",
11819
+ operationId: "backfillBeatport",
11820
+ path: "/admin/backfill/beatport",
11821
+ summary: "Back-fill Beatport URLs over published findings by exact ISRC",
11581
11822
  tags: ["Admin"]
11582
11823
  }).input(object({
11583
- dryRun: boolean2().default(true),
11584
- since: string2().regex(/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{1,3})?Z)?$/, "since must be an ISO date (2026-09-09) or instant (2026-09-09T00:00:00.000Z)")
11824
+ query: object({
11825
+ cursor: string2().optional(),
11826
+ dryRun: string2().optional(),
11827
+ limit: string2().optional()
11828
+ })
11585
11829
  })).output(object({
11830
+ catalogueFailed: array(BeatportCatalogueFailedSchema),
11831
+ catalogueFailedCount: number2(),
11832
+ catalogueResolved: array(BeatportCatalogueResolvedSchema),
11833
+ catalogueResolvedCount: number2(),
11834
+ catalogueUnresolved: array(string2()),
11835
+ catalogueUnresolvedCount: number2(),
11836
+ configured: boolean2(),
11586
11837
  dryRun: boolean2(),
11587
- matched: number2(),
11838
+ failed: array(BeatportFailedSchema),
11839
+ failedCount: number2(),
11840
+ nextCursor: string2().nullable(),
11588
11841
  ok: literal(true),
11589
- requeued: number2()
11842
+ resolved: array(BeatportResolvedSchema),
11843
+ resolvedCount: number2(),
11844
+ skipped: array(string2()),
11845
+ skippedCount: number2(),
11846
+ unresolved: array(string2()),
11847
+ unresolvedCount: number2()
11590
11848
  }));
11591
- flagWrongAudio = oc.route({
11592
- method: "POST",
11593
- operationId: "flagWrongAudio",
11594
- path: "/admin/catalogue/wrong-audio/flag",
11595
- summary: "Flag a finding's captured audio as the wrong recording (operator)",
11596
- tags: ["Admin"]
11597
- }).input(object({ trackId: string2().min(1) })).output(object({ flagged: boolean2(), ok: literal(true) }));
11598
- forceCapture = oc.route({
11599
- method: "POST",
11600
- operationId: "forceCapture",
11601
- path: "/admin/catalogue/force-capture",
11602
- summary: "Overrule the duplicate veto on one catalogue row so it can be captured (operator)",
11603
- tags: ["Admin"]
11604
- }).input(object({ trackId: string2().min(1) })).output(object({ forced: boolean2(), ok: literal(true) }));
11605
- certifyTrack = oc.route({
11606
- method: "POST",
11607
- operationId: "certifyTrack",
11608
- path: "/admin/catalogue/certify",
11609
- summary: "Certify an existing catalogue track in place — mint its finding (operator)",
11610
- tags: ["Admin"]
11611
- }).input(object({ note: string2().optional(), trackId: string2().min(1) })).output(object({ logId: string2(), ok: literal(true) }));
11612
- setTrackDismissed = oc.route({
11613
- method: "PUT",
11614
- operationId: "setTrackDismissed",
11615
- path: "/admin/catalogue/dismissed",
11616
- summary: "Dismiss a catalogue track ('not for me') or restore it (operator)",
11617
- tags: ["Admin"]
11618
- }).input(object({ dismissed: boolean2(), trackId: string2().min(1) })).output(object({ changed: boolean2(), ok: literal(true) }));
11619
- CaptureVerifyItemSchema = object({
11620
- artists: array(string2()),
11621
- certified: boolean2(),
11622
- durationMs: number2(),
11623
- isrc: string2().nullable(),
11624
- logId: string2().nullable(),
11625
- sourceAudioKey: string2(),
11626
- title: string2(),
11849
+ DeezerResolvedSchema = object({
11850
+ trackId: string2(),
11851
+ url: string2()
11852
+ }).meta({ id: "DeezerResolved" });
11853
+ DeezerFailedSchema = object({
11854
+ error: string2(),
11627
11855
  trackId: string2()
11628
- }).meta({ id: "CaptureVerifyItem" });
11629
- listUnverifiedCaptures = oc.route({
11630
- method: "GET",
11631
- operationId: "listUnverifiedCaptures",
11632
- path: "/admin/catalogue/captures/unverified",
11633
- summary: "Captured rows not yet fingerprint-verified against their preview (the backfill worklist)",
11856
+ }).meta({ id: "DeezerFailed" });
11857
+ backfillDeezer = oc.route({
11858
+ inputStructure: "detailed",
11859
+ method: "POST",
11860
+ operationId: "backfillDeezer",
11861
+ path: "/admin/backfill/deezer",
11862
+ summary: "Back-fill Deezer track ids over certified + catalogue rows by exact ISRC",
11634
11863
  tags: ["Admin"]
11635
11864
  }).input(object({
11636
- count: boolean3().default(false),
11637
- limit: number3().int().min(1).max(200).default(50)
11865
+ query: object({
11866
+ dryRun: string2().optional(),
11867
+ limit: string2().optional()
11868
+ })
11638
11869
  })).output(object({
11870
+ dryRun: boolean2(),
11871
+ failed: array(DeezerFailedSchema),
11872
+ failedCount: number2(),
11639
11873
  ok: literal(true),
11640
- queued: number2().optional(),
11641
- tracks: array(CaptureVerifyItemSchema)
11874
+ rateLimited: boolean2(),
11875
+ resolved: array(DeezerResolvedSchema),
11876
+ resolvedCount: number2(),
11877
+ unresolved: array(string2()),
11878
+ unresolvedCount: number2(),
11879
+ unvouchable: array(string2()),
11880
+ unvouchableCount: number2()
11642
11881
  }));
11643
- verifyCapture = oc.route({
11882
+ backfillLabelReleases = oc.route({
11644
11883
  method: "POST",
11645
- operationId: "verifyCapture",
11646
- path: "/admin/catalogue/captures/verify",
11647
- summary: "Record a capture's fingerprint verdict against its preview, and route it",
11884
+ operationId: "backfillLabelReleases",
11885
+ path: "/admin/backfill/label-releases",
11886
+ summary: "Tap Spotify's fresh releases for enabled seed labels into catalogue rows (bounded)",
11648
11887
  tags: ["Admin"]
11649
11888
  }).input(object({
11650
- trackId: string2().min(1),
11651
- verdict: _enum(["match", "mismatch", "no-preview"])
11889
+ dryRun: boolean2().default(false),
11890
+ limit: number3().int().min(1).max(200).default(5)
11652
11891
  })).output(object({
11653
- action: _enum([
11654
- "flagged-finding",
11655
- "not-captured",
11656
- "operator-verified",
11657
- "preview-match",
11658
- "quarantined-catalogue",
11659
- "unverified"
11660
- ]),
11661
- ok: literal(true)
11662
- }));
11663
- CrawlPassSchema = object({
11664
- artistsRearmed: number2().optional(),
11892
+ albumsMatched: number2(),
11893
+ albumsSeen: number2(),
11894
+ budgetPaused: boolean2(),
11895
+ configured: boolean2(),
11665
11896
  dryRun: boolean2(),
11666
- expanded: number2(),
11667
- failed: number2(),
11668
- frontierPending: number2(),
11669
- labelsDiscovered: array(string2()),
11670
- maxHop: number2(),
11671
- nodesEnqueued: number2(),
11897
+ failedFetches: number2(),
11898
+ failedLabels: array(string2()),
11899
+ fetchCeilingHit: boolean2(),
11900
+ labelSlugs: array(string2()),
11901
+ labelsProbed: number2(),
11902
+ newRows: number2(),
11903
+ newTrackIds: array(string2()),
11904
+ ok: literal(true),
11672
11905
  rateLimited: boolean2(),
11673
- releasesRearmed: number2(),
11674
- seeded: number2(),
11675
- seedsRearmed: number2(),
11676
- tracksAllowedIn: number2().optional(),
11677
- tracksFound: number2(),
11678
- tracksSkipped: number2(),
11679
- tracksSkippedArtistRule: number2().optional(),
11680
- tracksSkippedHeld: number2().optional(),
11681
- tracksSkippedLabelGate: number2().optional(),
11682
- tracksWritten: number2()
11683
- }).meta({ id: "CrawlPass" });
11684
- CrawlPhaseInitializationSchema = object({
11685
- artistsRearmed: number2(),
11686
- releasesRearmed: number2(),
11687
- seeded: number2(),
11688
- seedsRearmed: number2()
11689
- });
11690
- CrawlFetchPlanSchema = discriminatedUnion("kind", [
11691
- object({ kind: literal("none") }),
11692
- object({ kind: literal("single"), url: string2().max(2048) }),
11693
- object({
11694
- countField: literal("release-count"),
11695
- kind: literal("tail"),
11696
- pageSize: number2().int().positive(),
11697
- pageUrlTemplate: string2().max(2048),
11698
- probeUrl: string2().max(2048)
11699
- })
11700
- ]);
11701
- SuppliedCrawlBodySchema = object({
11702
- body: json().optional(),
11703
- outcome: _enum(["body", "empty", "invalid", "oversize", "throttled"]),
11704
- url: string2().max(2048)
11705
- });
11706
- MAX_CRAWL_COMMIT_BATCH = MAX_CRAWL_PREPARE_LIMIT;
11707
- CRAWL_COMMIT_TOKEN_MAX_BYTES = 2 * 1024 * 1024;
11708
- CRAWL_COMMIT_BATCH_MAX_TOTAL_BYTES = 8 * 1024 * 1024;
11709
- CrawlCommitItemSchema = strictObject({
11710
- commitToken: string2().max(CRAWL_COMMIT_TOKEN_MAX_BYTES),
11711
- operationId: literal("catalogue.crawl"),
11712
- operationKey: string2().max(128),
11713
- requestDigest: string2().regex(/^[0-9a-f]{64}$/)
11714
- });
11715
- CrawlCommitReceiptSchema = object({
11716
- elapsedMs: number2().int().min(0).optional(),
11717
- error: string2().max(500).optional(),
11718
- operationKey: string2().max(128),
11719
- outcome: _enum([
11720
- "committed",
11721
- "conflict",
11722
- "failed",
11723
- "in-progress",
11724
- "lookup-failed",
11725
- "rejected",
11726
- "safely-retryable"
11727
- ]),
11728
- replayed: boolean2(),
11729
- result: json().optional(),
11730
- resultIdentity: string2().optional(),
11731
- state: _enum(["accepted", "committed", "rejected"]).optional()
11732
- }).meta({ id: "CrawlCommitReceipt" });
11733
- CrawlPhaseCapabilitiesSchema = strictObject({
11734
- commitBatchLimit: number2().int().min(1).max(MAX_CRAWL_COMMIT_BATCH),
11735
- commitBatchMaxTotalBytes: number2().int().min(1)
11736
- });
11737
- CrawlPhaseInputSchema = discriminatedUnion("phase", [
11738
- object({ phase: literal("initialize") }),
11739
- object({
11740
- limit: number2().int().min(1).max(MAX_CRAWL_PREPARE_LIMIT).default(2),
11741
- maxHop: number2().int().min(0).max(3).default(2),
11742
- phase: literal("prepare")
11743
- }),
11744
- object({
11745
- phase: literal("fetch"),
11746
- preparedToken: string2().max(2 * 1024 * 1024),
11747
- supplied: array(SuppliedCrawlBodySchema).max(2).optional()
11748
- }),
11749
- object({
11750
- commitToken: string2().max(2 * 1024 * 1024),
11751
- operationId: literal("catalogue.crawl"),
11752
- operationKey: string2().max(128),
11753
- phase: literal("commit"),
11754
- requestDigest: string2().regex(/^[0-9a-f]{64}$/)
11906
+ skippedKnown: number2(),
11907
+ skippedUndated: number2(),
11908
+ skippedUngrounded: number2(),
11909
+ tracksSkippedArtistRule: number2().optional()
11910
+ }));
11911
+ LabelImagesBackfillFailedSchema = object({
11912
+ error: string2(),
11913
+ slug: string2()
11914
+ }).meta({ id: "LabelImagesBackfillFailed" });
11915
+ backfillLabelImages = oc.route({
11916
+ inputStructure: "detailed",
11917
+ method: "POST",
11918
+ operationId: "backfillLabelImages",
11919
+ path: "/admin/backfill/label-images",
11920
+ summary: "Resolve label logos (Discogs → Wikidata) into R2 for existing labels (batched)",
11921
+ tags: ["Admin"]
11922
+ }).input(object({
11923
+ body: object({
11924
+ discogsCandidates: DiscogsLabelCandidateBatchSchema.optional()
11925
+ }).optional(),
11926
+ query: object({
11927
+ boxFetch: string2().optional(),
11928
+ cursor: string2().optional(),
11929
+ dryRun: string2().optional(),
11930
+ limit: string2().optional()
11755
11931
  })
11756
- ]);
11757
- CrawlPhaseOutputSchema = discriminatedUnion("phase", [
11758
- object({
11759
- initialization: CrawlPhaseInitializationSchema,
11760
- kind: _enum(["initialized", "unavailable"]),
11761
- ok: literal(true),
11762
- phase: literal("initialize")
11763
- }),
11764
- object({
11765
- boxFetch: boolean2(),
11766
- capabilities: CrawlPhaseCapabilitiesSchema.optional(),
11767
- frontierPending: number2(),
11768
- initialization: CrawlPhaseInitializationSchema,
11769
- items: array(object({
11770
- fetchPlan: CrawlFetchPlanSchema,
11771
- nodeId: string2(),
11772
- preparedToken: string2()
11773
- })).max(MAX_CRAWL_PREPARE_LIMIT),
11774
- kind: _enum(["drained", "prepared", "unavailable"]),
11775
- ok: literal(true),
11776
- phase: literal("prepare")
11777
- }),
11778
- object({
11779
- commitToken: string2(),
11780
- ok: literal(true),
11781
- operationId: literal("catalogue.crawl"),
11782
- operationKey: string2(),
11783
- phase: literal("fetch"),
11784
- rateLimited: boolean2().optional(),
11785
- requestDigest: string2()
11786
- }),
11787
- object({
11788
- ok: literal(true),
11789
- phase: literal("commit"),
11790
- receipt: object({
11791
- outcome: _enum([
11792
- "committed",
11793
- "conflict",
11794
- "in-progress",
11795
- "lookup-failed",
11796
- "rejected",
11797
- "safely-retryable"
11798
- ]),
11799
- replayed: boolean2(),
11800
- result: json().optional(),
11801
- resultIdentity: string2().optional(),
11802
- state: _enum(["accepted", "committed", "rejected"]).optional()
11803
- })
11932
+ })).output(object({
11933
+ discogsWork: array(DiscogsLabelWorkSchema).max(DISCOGS_LABEL_WORK_LIMIT),
11934
+ dryRun: boolean2(),
11935
+ failed: array(LabelImagesBackfillFailedSchema),
11936
+ failedCount: number2(),
11937
+ nextCursor: string2().nullable(),
11938
+ none: array(string2()),
11939
+ noneCount: number2(),
11940
+ ok: literal(true),
11941
+ rateLimited: boolean2(),
11942
+ resolved: array(string2()),
11943
+ resolvedCount: number2()
11944
+ }));
11945
+ LabelLineageBackfillFailedSchema = object({
11946
+ error: string2(),
11947
+ slug: string2()
11948
+ }).meta({ id: "LabelLineageBackfillFailed" });
11949
+ backfillLabelLineage = oc.route({
11950
+ inputStructure: "detailed",
11951
+ method: "POST",
11952
+ operationId: "backfillLabelLineage",
11953
+ path: "/admin/backfill/label-lineage",
11954
+ summary: "Resolve label lineage (founding date, place, parent imprint) from MusicBrainz (batched)",
11955
+ tags: ["Admin"]
11956
+ }).input(object({
11957
+ query: object({
11958
+ cursor: string2().optional(),
11959
+ dryRun: string2().optional(),
11960
+ limit: string2().optional()
11804
11961
  })
11805
- ]);
11806
- CrawlStatusSchema = object({
11807
- anchorsPending: number2(),
11808
- catalogueTracks: number2(),
11809
- frontier: object({
11810
- done: number2(),
11811
- failed: number2(),
11812
- pending: number2(),
11813
- skipped: number2()
11814
- }),
11815
- frontierByKind: object({
11816
- artist: number2(),
11817
- label: number2(),
11818
- release: number2()
11819
- }),
11820
- labelsUndecided: number2(),
11821
- seedLabels: array(string2()),
11822
- storablePending: number2(),
11823
- undecidedLabelsQueued: number2(),
11824
- unstorablePending: number2()
11825
- }).meta({ id: "CrawlStatus" });
11826
- crawlCatalogue = oc.route({
11962
+ })).output(object({
11963
+ dryRun: boolean2(),
11964
+ failed: array(LabelLineageBackfillFailedSchema),
11965
+ failedCount: number2(),
11966
+ nextCursor: string2().nullable(),
11967
+ none: array(string2()),
11968
+ noneCount: number2(),
11969
+ ok: literal(true),
11970
+ rateLimited: boolean2(),
11971
+ resolved: array(string2()),
11972
+ resolvedCount: number2(),
11973
+ unmatchedParents: number2()
11974
+ }));
11975
+ CoverMastersFailedSchema = object({
11976
+ error: string2(),
11977
+ slug: string2()
11978
+ }).meta({ id: "CoverMastersFailed" });
11979
+ backfillCoverMasters = oc.route({
11827
11980
  inputStructure: "detailed",
11828
11981
  method: "POST",
11829
- operationId: "crawlCatalogue",
11830
- path: "/admin/catalogue/crawl",
11831
- summary: "Run one bounded, resumable pass of the catalogue crawler",
11982
+ operationId: "backfillCoverMasters",
11983
+ path: "/admin/backfill/cover-masters",
11984
+ summary: "Resolve owned ≤1200² cover masters (album/artist) into R2 (batched)",
11832
11985
  tags: ["Admin"]
11833
11986
  }).input(object({
11834
- body: CrawlPhaseInputSchema.optional(),
11835
11987
  query: object({
11988
+ cursor: string2().optional(),
11836
11989
  dryRun: string2().optional(),
11990
+ kind: string2().optional(),
11837
11991
  limit: string2().optional(),
11838
- maxHop: string2().optional()
11992
+ retry: string2().optional()
11839
11993
  })
11840
- })).output(union([CrawlPassSchema.extend({ ok: literal(true) }), CrawlPhaseOutputSchema]));
11841
- commitCrawlNodes = oc.route({
11994
+ })).output(object({
11995
+ dryRun: boolean2(),
11996
+ failed: array(CoverMastersFailedSchema),
11997
+ failedCount: number2(),
11998
+ kind: _enum(["album", "artist"]),
11999
+ nextCursor: string2().nullable(),
12000
+ none: array(string2()),
12001
+ noneCount: number2(),
12002
+ ok: literal(true),
12003
+ rateLimited: boolean2(),
12004
+ requeued: array(string2()).optional(),
12005
+ requeuedCount: number2().optional(),
12006
+ resolved: array(string2()),
12007
+ resolvedCount: number2()
12008
+ }));
12009
+ RecordingMbidsFailedSchema = object({
12010
+ error: string2(),
12011
+ trackId: string2()
12012
+ }).meta({ id: "RecordingMbidsBackfillFailed" });
12013
+ backfillRecordingMbids = oc.route({
12014
+ inputStructure: "detailed",
11842
12015
  method: "POST",
11843
- operationId: "commitCrawlNodes",
11844
- path: "/admin/catalogue/crawl/commits",
11845
- summary: "Commit one claim's fetched crawl nodes in a single admitted phase",
12016
+ operationId: "backfillRecordingMbids",
12017
+ path: "/admin/backfill/recording-mbids",
12018
+ summary: "Fill MusicBrainz recording MBIDs (crawler PK strip + ISRC resolve) over tracks (batched)",
11846
12019
  tags: ["Admin"]
11847
- }).input(strictObject({
11848
- items: array(CrawlCommitItemSchema).min(1).max(MAX_CRAWL_COMMIT_BATCH)
11849
- })).output(strictObject({
11850
- deferred: number2().int().min(0),
12020
+ }).input(object({
12021
+ query: object({
12022
+ cursor: string2().optional(),
12023
+ dryRun: string2().optional(),
12024
+ isrcRefreshLimit: string2().optional(),
12025
+ limit: string2().optional()
12026
+ })
12027
+ })).output(object({
12028
+ dryRun: boolean2(),
12029
+ failed: array(RecordingMbidsFailedSchema),
12030
+ failedCount: number2(),
12031
+ isrcRefreshMissed: array(string2()),
12032
+ isrcRefreshMissedCount: number2(),
12033
+ isrcRefreshed: array(string2()),
12034
+ isrcRefreshedCount: number2(),
12035
+ missed: array(string2()),
12036
+ missedCount: number2(),
12037
+ nextCursor: string2().nullable(),
11851
12038
  ok: literal(true),
11852
- receipts: array(CrawlCommitReceiptSchema).max(MAX_CRAWL_COMMIT_BATCH)
12039
+ prefixStripped: number2(),
12040
+ rateLimited: boolean2(),
12041
+ resolved: array(string2()),
12042
+ resolvedCount: number2()
11853
12043
  }));
11854
- getCrawlStatus = oc.route({
11855
- method: "GET",
11856
- operationId: "getCrawlStatus",
11857
- path: "/admin/catalogue/crawl",
11858
- summary: "The crawl frontier's state, the catalogue size, and the seed set",
11859
- tags: ["Admin"]
11860
- }).input(object({})).output(CrawlStatusSchema.extend({ ok: literal(true) }));
11861
- AnchorCandidateSchema = object({
11862
- albumImageUrl: string2().max(ANCHOR_URL_MAX).nullish(),
11863
- artists: array(object({
11864
- id: string2().max(ANCHOR_ID_MAX).nullish(),
11865
- name: string2().max(ANCHOR_TEXT_MAX)
11866
- })).max(ANCHOR_ARTIST_LIMIT).default([]),
11867
- durationMs: number2().nullish(),
11868
- isrc: string2().max(ANCHOR_ISRC_MAX).nullish(),
11869
- spotifyTrackId: string2().max(ANCHOR_ID_MAX).optional(),
11870
- title: string2().max(ANCHOR_TEXT_MAX).default(""),
11871
- uri: string2().max(ANCHOR_URL_MAX).optional(),
11872
- url: string2().max(ANCHOR_URL_MAX).optional()
11873
- }).refine((candidate) => Boolean(candidate.spotifyTrackId ?? candidate.uri ?? candidate.url), {
11874
- error: "a candidate must carry a spotifyTrackId, uri, or url"
11875
- }).meta({ id: "AnchorCandidate" });
11876
- anchorTrack = oc.route({
12044
+ backfillArtistEdges = oc.route({
12045
+ inputStructure: "detailed",
11877
12046
  method: "POST",
11878
- operationId: "anchorTrack",
11879
- path: "/admin/catalogue/anchor",
11880
- summary: "Verify box-supplied Spotify candidates against a catalogue row and write its anchor",
12047
+ operationId: "backfillArtistEdges",
12048
+ path: "/admin/backfill/artist-edges",
12049
+ summary: "Fold artists_json names onto existing artist identities → track_artists (batched)",
11881
12050
  tags: ["Admin"]
11882
12051
  }).input(object({
11883
- candidates: array(AnchorCandidateSchema).max(ANCHOR_CANDIDATE_LIMIT).default([]),
11884
- trackId: string2().min(1)
12052
+ query: object({
12053
+ cursor: string2().optional(),
12054
+ dryRun: string2().optional(),
12055
+ limit: string2().optional()
12056
+ })
11885
12057
  })).output(object({
11886
- anchored: boolean2(),
12058
+ dryRun: boolean2(),
12059
+ edgesWritten: number2(),
12060
+ fullyMatched: array(string2()),
12061
+ fullyMatchedCount: number2(),
12062
+ nextCursor: string2().nullable(),
11887
12063
  ok: literal(true),
11888
- verifiedBy: _enum(["isrc", "search", "search-subset"]).nullable()
11889
- }));
11890
- DeezerIsrcCandidateSchema = object({
11891
- artistName: string2().max(DEEZER_TEXT_MAX),
11892
- deezerTrackId: string2().max(DEEZER_TRACK_ID_MAX).optional(),
11893
- durationMs: number2().positive().finite(),
11894
- isrc: string2().max(DEEZER_ISRC_MAX),
11895
- title: string2().max(DEEZER_TEXT_MAX)
11896
- }).meta({ id: "DeezerIsrcCandidate" });
11897
- resolveAnchor = oc.route({
12064
+ partiallyMatched: array(string2()),
12065
+ partiallyMatchedCount: number2(),
12066
+ queueDepth: number2(),
12067
+ scanned: number2(),
12068
+ unmatchedNames: number2(),
12069
+ zeroMatched: array(string2()),
12070
+ zeroMatchedCount: number2()
12071
+ }));
12072
+ backfillArtistCredits = oc.route({
12073
+ inputStructure: "detailed",
11898
12074
  method: "POST",
11899
- operationId: "resolveAnchor",
11900
- path: "/admin/catalogue/anchor/resolve",
11901
- summary: "Resolve a catalogue row's Spotify anchor from the free rungs (ListenBrainz + dark Spotify search)",
12075
+ operationId: "backfillArtistCredits",
12076
+ path: "/admin/backfill/artist-credits",
12077
+ summary: "Mint identity-true artists from MusicBrainz credits for slice 0's zero-matched residual (batched)",
11902
12078
  tags: ["Admin"]
11903
12079
  }).input(object({
11904
- deezerCandidates: array(DeezerIsrcCandidateSchema).max(DEEZER_CANDIDATE_LIMIT).optional(),
11905
- spotifySearch: boolean2().optional(),
11906
- trackId: string2().min(1)
12080
+ query: object({
12081
+ cursor: string2().optional(),
12082
+ dryRun: string2().optional(),
12083
+ limit: string2().optional()
12084
+ })
11907
12085
  })).output(object({
11908
- anchored: boolean2(),
11909
- apifyBudgetRemaining: number2().int().nonnegative(),
11910
- apifyEligible: boolean2(),
11911
- apifyEnabled: boolean2(),
11912
- apifyIneligibleReason: _enum(["apify_budget_spent", "awaiting_free_ask"]).nullable(),
11913
- freeDurationMsOmitted: number2().int().nonnegative(),
11914
- isrcRecoveredByDeezer: boolean2(),
11915
- listenbrainzOutcome: _enum([
11916
- "anchored",
11917
- "empty-ids",
11918
- "gate-rejected",
11919
- "metadata-failed",
11920
- "no-map",
11921
- "no-mbid",
11922
- "not-attempted",
11923
- "request-failed",
11924
- "yielded-on-breaker"
11925
- ]),
12086
+ adoptedArtists: number2(),
12087
+ dryRun: boolean2(),
12088
+ edgesWritten: number2(),
12089
+ matchedArtists: number2(),
12090
+ mintedArtists: number2(),
12091
+ nextCursor: string2().nullable(),
11926
12092
  ok: literal(true),
11927
- source: _enum(["listenbrainz", "spotify-isrc", "spotify-search"]).nullable(),
11928
- spotifyIsrcAsked: boolean2(),
11929
- spotifySearchDone: boolean2(),
11930
- spotifySearchEnabled: boolean2(),
11931
- spotifyThrottled: boolean2(),
11932
- stamped: boolean2(),
11933
- verifiedBy: _enum(["isrc", "search", "search-subset"]).nullable()
12093
+ rateLimited: boolean2(),
12094
+ scanned: number2(),
12095
+ skippedNoIdentity: number2()
11934
12096
  }));
11935
- resolveAnchorReview = oc.route({
12097
+ adminBackfillsContract = {
12098
+ backfill_apple_catalogue: backfillAppleCatalogue,
12099
+ backfill_apple_music: backfillAppleMusic,
12100
+ backfill_artist_credits: backfillArtistCredits,
12101
+ backfill_artist_edges: backfillArtistEdges,
12102
+ backfill_beatport: backfillBeatport,
12103
+ backfill_cover_masters: backfillCoverMasters,
12104
+ backfill_deezer: backfillDeezer,
12105
+ backfill_discogs: backfillDiscogs,
12106
+ backfill_discogs_facts: backfillDiscogsFacts,
12107
+ backfill_label_images: backfillLabelImages,
12108
+ backfill_label_lineage: backfillLabelLineage,
12109
+ backfill_label_releases: backfillLabelReleases,
12110
+ backfill_lastfm: backfillLastfm,
12111
+ backfill_recording_mbids: backfillRecordingMbids
12112
+ };
12113
+ });
12114
+
12115
+ // ../../packages/contracts/src/orpc/admin-bios.ts
12116
+ var BioEntityKindSchema, resolveBioReview, adminBiosContract;
12117
+ var init_admin_bios = __esm(() => {
12118
+ init_dist3();
12119
+ init_zod();
12120
+ BioEntityKindSchema = _enum(["album", "artist", "label"]).meta({ id: "BioEntityKind" });
12121
+ resolveBioReview = oc.route({
11936
12122
  method: "POST",
11937
- operationId: "resolveAnchorReview",
11938
- path: "/admin/catalogue/anchor/reviews/{trackId}/resolve",
11939
- summary: "Rule on a suspected version mismatch: anchor to the candidate, or dismiss (operator)",
12123
+ operationId: "resolveBioReview",
12124
+ path: "/admin/bio-reviews/{kind}/{slug}/resolve",
12125
+ summary: "Rule on a bio that landed past the voice gate: keep it or send it back (operator)",
11940
12126
  tags: ["Admin"]
11941
12127
  }).input(object({
11942
- resolution: _enum(["accepted", "dismissed"]),
11943
- trackId: string2().min(1)
12128
+ kind: BioEntityKindSchema,
12129
+ resolution: _enum(["keep", "rewrite"]),
12130
+ slug: string2()
11944
12131
  })).output(object({
11945
- anchored: boolean2(),
12132
+ kind: BioEntityKindSchema,
11946
12133
  ok: literal(true),
11947
- review: object({
11948
- candidateTitle: string2(),
11949
- spotifyTrackId: string2().optional()
11950
- })
12134
+ resolution: _enum(["keep", "rewrite"]),
12135
+ slug: string2()
11951
12136
  }));
11952
- setAnchorSearch = oc.route({
11953
- method: "PUT",
11954
- operationId: "setAnchorSearch",
11955
- path: "/admin/catalogue/anchor/search",
11956
- summary: "Flip the dark flag for the Spotify anchor-search rungs (operator)",
11957
- tags: ["Admin"]
11958
- }).input(object({ enabled: boolean2() })).output(object({ enabled: boolean2(), ok: literal(true) }));
11959
- setAnchorApify = oc.route({
11960
- method: "PUT",
11961
- operationId: "setAnchorApify",
11962
- path: "/admin/catalogue/anchor/apify",
11963
- summary: "Flip the Apify anchor-fallback kill-flag — off = no-budget graceful state (operator)",
11964
- tags: ["Admin"]
11965
- }).input(object({ enabled: boolean2() })).output(object({ enabled: boolean2(), ok: literal(true), requeued: number2() }));
11966
- CaptureBudgetStateSchema = object({
11967
- budget: object({ dailyBytes: number2(), dailyTracks: number2() }),
11968
- closedReason: _enum(["bytes_spent", "paused", "tracks_spent"]).nullable(),
11969
- open: boolean2(),
11970
- paused: boolean2(),
11971
- remainingBytes: number2(),
11972
- remainingTracks: number2(),
11973
- spend: object({ bytes: number2(), tracks: number2() }),
11974
- windowHours: number2()
11975
- }).meta({ id: "CaptureBudgetState" });
11976
- getCaptureBudget = oc.route({
11977
- method: "GET",
11978
- operationId: "getCaptureBudget",
11979
- path: "/admin/catalogue/capture-budget",
11980
- summary: "The catalogue capture budget: the switch, the caps, the 24h spend, what is left",
11981
- tags: ["Admin"]
11982
- }).input(object({})).output(CaptureBudgetStateSchema.extend({ ok: literal(true) }));
11983
- setCaptureBudget = oc.route({
11984
- method: "PUT",
11985
- operationId: "setCaptureBudget",
11986
- path: "/admin/catalogue/capture-budget",
11987
- summary: "Set the catalogue capture budget / flip its kill switch (operator)",
11988
- tags: ["Admin"]
11989
- }).input(object({
11990
- dailyBytes: number2().int().min(0).optional(),
11991
- dailyTracks: number2().int().min(0).optional(),
11992
- paused: boolean2().optional()
11993
- })).output(CaptureBudgetStateSchema.extend({ ok: literal(true) }));
11994
- AnchorApifyBudgetSchema = object({
11995
- dailyRows: number2(),
11996
- day: string2(),
11997
- remainingRows: number2(),
11998
- rowsSent: number2(),
11999
- spent: boolean2()
12000
- }).meta({ id: "AnchorApifyBudget" });
12001
- getAnchorApifyBudget = oc.route({
12002
- method: "GET",
12003
- operationId: "getAnchorApifyBudget",
12004
- path: "/admin/catalogue/anchor/apify-budget",
12005
- summary: "The metered Apify anchor rung's daily row cap, today's spend, and what is left",
12006
- tags: ["Admin"]
12007
- }).input(object({})).output(AnchorApifyBudgetSchema.extend({ ok: literal(true) }));
12008
- setAnchorApifyBudget = oc.route({
12009
- method: "PUT",
12010
- operationId: "setAnchorApifyBudget",
12011
- path: "/admin/catalogue/anchor/apify-budget",
12012
- summary: "Set the metered Apify anchor rung's daily row cap (operator)",
12013
- tags: ["Admin"]
12014
- }).input(object({ dailyRows: number2().int().min(0) })).output(AnchorApifyBudgetSchema.extend({ ok: literal(true) }));
12015
- SpotifyAnchorBreakerStateSchema = object({
12016
- cooldownRemainingMs: number2(),
12017
- reason: string2().nullable(),
12018
- throttlesInWindow: number2(),
12019
- tripped: boolean2(),
12020
- trippedAt: string2().nullable()
12021
- }).meta({ id: "SpotifyAnchorBreakerState" });
12022
- AnchorRungFlagsSchema = object({
12023
- apifyBudget: AnchorApifyBudgetSchema,
12024
- apifyEnabled: boolean2(),
12025
- spotifySearchEnabled: boolean2()
12026
- }).meta({ id: "AnchorRungFlags" });
12027
- getSpotifyAnchorBreaker = oc.route({
12028
- method: "GET",
12029
- operationId: "getSpotifyAnchorBreaker",
12030
- path: "/admin/catalogue/anchor/breaker",
12031
- summary: "The Spotify anchor-search throttle breaker: tripped, why, how long left, and the rungs",
12032
- tags: ["Admin"]
12033
- }).input(object({})).output(SpotifyAnchorBreakerStateSchema.extend({ ok: literal(true), rungs: AnchorRungFlagsSchema }));
12034
- resetSpotifyAnchorBreaker = oc.route({
12035
- method: "POST",
12036
- operationId: "resetSpotifyAnchorBreaker",
12037
- path: "/admin/catalogue/anchor/breaker/reset",
12038
- summary: "Clear the Spotify anchor-search throttle breaker (operator)",
12039
- tags: ["Admin"]
12040
- }).input(object({})).output(SpotifyAnchorBreakerStateSchema.extend({ ok: literal(true) }));
12041
- AppleBreakerStateSchema = object({
12042
- consecutiveAuthFailures: number2(),
12043
- cooldownRemainingMs: number2(),
12044
- tripped: boolean2(),
12045
- trippedAt: string2().nullable()
12046
- }).meta({ id: "AppleBreakerState" });
12047
- resetAppleBreaker = oc.route({
12048
- method: "POST",
12049
- operationId: "resetAppleBreaker",
12050
- path: "/admin/catalogue/apple-breaker/reset",
12051
- summary: "Clear the Apple failure-regime breaker (operator)",
12052
- tags: ["Admin"]
12053
- }).input(object({})).output(AppleBreakerStateSchema.extend({ ok: literal(true) }));
12054
- adminCatalogueContract = {
12055
- anchor_track: anchorTrack,
12056
- certify_track: certifyTrack,
12057
- clear_wrong_audio: clearWrongAudio,
12058
- commit_crawl_nodes: commitCrawlNodes,
12059
- crawl_catalogue: crawlCatalogue,
12060
- flag_wrong_audio: flagWrongAudio,
12061
- force_capture: forceCapture,
12062
- get_anchor_apify_budget: getAnchorApifyBudget,
12063
- get_capture_budget: getCaptureBudget,
12064
- get_crawl_status: getCrawlStatus,
12065
- get_spotify_anchor_breaker: getSpotifyAnchorBreaker,
12066
- list_catalogue_tracks: listCatalogueTracks,
12067
- list_unverified_captures: listUnverifiedCaptures,
12068
- rank_catalogue: rankCatalogue,
12069
- record_demand: recordDemand,
12070
- requeue_anchor: requeueAnchor,
12071
- requeue_isrc_recovery: requeueIsrcRecovery,
12072
- requeue_unmatched_captures: requeueUnmatchedCaptures,
12073
- reset_apple_breaker: resetAppleBreaker,
12074
- reset_spotify_anchor_breaker: resetSpotifyAnchorBreaker,
12075
- resolve_anchor: resolveAnchor,
12076
- resolve_anchor_review: resolveAnchorReview,
12077
- set_anchor_apify: setAnchorApify,
12078
- set_anchor_apify_budget: setAnchorApifyBudget,
12079
- set_anchor_search: setAnchorSearch,
12080
- set_capture_budget: setCaptureBudget,
12081
- set_track_dismissed: setTrackDismissed,
12082
- verify_capture: verifyCapture
12137
+ adminBiosContract = {
12138
+ resolve_bio_review: resolveBioReview
12083
12139
  };
12084
12140
  });
12085
12141
 
@@ -12751,6 +12807,7 @@ var init__shared = __esm(() => {
12751
12807
  postedToTelegram: boolean2(),
12752
12808
  previewUrl: string2().optional(),
12753
12809
  releaseDate: string2().optional(),
12810
+ similar: boolean2().optional(),
12754
12811
  sourceAudioFailures: number2().optional(),
12755
12812
  sourceAudioKey: string2().optional(),
12756
12813
  spotifyUrl: string2(),
@@ -13474,7 +13531,8 @@ var init_admin_hub_counts = __esm(() => {
13474
13531
  init_zod();
13475
13532
  HubCountsTableResultSchema = object({
13476
13533
  corrected: number2(),
13477
- deferred: number2()
13534
+ deferred: number2(),
13535
+ latestCorrected: number2()
13478
13536
  }).meta({ id: "HubCountsTableResult" });
13479
13537
  HubCountsReconcileCursorSchema = object({
13480
13538
  afterId: string2().min(1).max(512).nullable(),
@@ -13504,12 +13562,13 @@ var init_admin_hub_counts = __esm(() => {
13504
13562
  });
13505
13563
 
13506
13564
  // ../../packages/contracts/src/orpc/admin-labels.ts
13507
- var LabelSeedStateSchema, LabelAdminItemSchema, listLabelsAdmin, updateLabel, listLabelArtistRules, replaceLabelArtistRules, MergeLabelResultSchema, mergeLabel, MB_LABEL_MBID_PATTERN, MintLabelOutcomeSchema, LabelTakeOverResultSchema, mintLabel, LabelAliasSourceSchema, LabelAliasKindSchema, LabelAliasCandidateSchema, listLabelAliases, confirmLabelAlias, rejectLabelAlias, DescribeLabelBodySchema, describeLabel, draftLabelBio, LabelBioWorkItemSchema, listLabelsMissingBio, adminLabelsContract;
13565
+ var LabelSeedStateSchema, LabelTriageVerdictSchema, LabelAdminItemSchema, listLabelsAdmin, updateLabel, listLabelArtistRules, replaceLabelArtistRules, MergeLabelResultSchema, mergeLabel, MB_LABEL_MBID_PATTERN, MintLabelOutcomeSchema, LabelTakeOverResultSchema, mintLabel, LabelAliasSourceSchema, LabelAliasKindSchema, LabelAliasCandidateSchema, listLabelAliases, confirmLabelAlias, rejectLabelAlias, DescribeLabelBodySchema, describeLabel, draftLabelBio, LabelBioWorkItemSchema, listLabelsMissingBio, TriageRuleProposalSchema, RecordLabelTriageBodySchema, recordLabelTriage, adminLabelsContract;
13508
13566
  var init_admin_labels = __esm(() => {
13509
13567
  init_dist3();
13510
13568
  init_zod();
13511
13569
  init_admin_artist_rules();
13512
13570
  LabelSeedStateSchema = _enum(["disabled", "enabled", "undecided"]).meta({ id: "LabelSeedState" });
13571
+ LabelTriageVerdictSchema = _enum(["dnb", "dnb_partial", "not_dnb", "unclear"]).meta({ id: "LabelTriageVerdict" });
13513
13572
  LabelAdminItemSchema = object({
13514
13573
  createdAt: string2(),
13515
13574
  disambiguation: string2().nullable().optional(),
@@ -13524,6 +13583,9 @@ var init_admin_labels = __esm(() => {
13524
13583
  scopeChangedAt: string2().nullable().optional(),
13525
13584
  seedState: LabelSeedStateSchema,
13526
13585
  slug: string2(),
13586
+ triageCheckedAt: string2().nullable().optional(),
13587
+ triageReason: string2().nullable().optional(),
13588
+ triageVerdict: LabelTriageVerdictSchema.nullable().optional(),
13527
13589
  updatedAt: string2()
13528
13590
  }).meta({ id: "LabelAdminItem" });
13529
13591
  listLabelsAdmin = oc.route({
@@ -13703,6 +13765,38 @@ var init_admin_labels = __esm(() => {
13703
13765
  summary: "List labels with findings but no bio yet, oldest first (the bio worklist)",
13704
13766
  tags: ["Admin"]
13705
13767
  }).input(object({ limit: string2().optional() })).output(object({ labels: array(LabelBioWorkItemSchema), ok: literal(true) }));
13768
+ TriageRuleProposalSchema = object({
13769
+ artistMbid: string2(),
13770
+ artistName: string2(),
13771
+ evidence: string2().optional(),
13772
+ firstCreditCount: number2().int().min(0),
13773
+ verdict: _enum(["allow", "block"])
13774
+ });
13775
+ RecordLabelTriageBodySchema = object({
13776
+ censusSummary: string2().optional(),
13777
+ confidence: _enum(["high", "medium", "low"]),
13778
+ evidence: string2(),
13779
+ offLaneShare: number2().min(0).max(1).optional(),
13780
+ reason: string2().optional(),
13781
+ residualOffLaneShare: number2().min(0).max(1).optional(),
13782
+ roundId: string2(),
13783
+ rules: array(TriageRuleProposalSchema).optional(),
13784
+ verdict: LabelTriageVerdictSchema,
13785
+ verifyAgrees: boolean2().optional(),
13786
+ verifyEvidence: string2().optional()
13787
+ }).meta({ id: "RecordLabelTriageBody" });
13788
+ recordLabelTriage = oc.route({
13789
+ method: "POST",
13790
+ operationId: "recordLabelTriage",
13791
+ path: "/admin/labels/{slug}/triage",
13792
+ summary: "Record what a triage round found (stamps the cursor; never rules)",
13793
+ tags: ["Admin"]
13794
+ }).input(RecordLabelTriageBodySchema.extend({ slug: string2() })).output(object({
13795
+ droppedInertRules: number2().int(),
13796
+ ok: literal(true),
13797
+ superseded: boolean2(),
13798
+ triageCheckedAt: string2()
13799
+ }));
13706
13800
  adminLabelsContract = {
13707
13801
  confirm_label_alias: confirmLabelAlias,
13708
13802
  describe_label: describeLabel,
@@ -13713,6 +13807,7 @@ var init_admin_labels = __esm(() => {
13713
13807
  list_labels_missing_bio: listLabelsMissingBio,
13714
13808
  merge_label: mergeLabel,
13715
13809
  mint_label: mintLabel,
13810
+ record_label_triage: recordLabelTriage,
13716
13811
  reject_label_alias: rejectLabelAlias,
13717
13812
  replace_label_artist_rules: replaceLabelArtistRules,
13718
13813
  update_label: updateLabel
@@ -15295,15 +15390,18 @@ var init_admin_tracks = __esm(() => {
15295
15390
  summary: "The audio pipeline's worklist for one stage, in capture-priority order",
15296
15391
  tags: ["Admin"]
15297
15392
  }).input(object({
15393
+ age: string2().optional(),
15298
15394
  count: string2().optional(),
15299
15395
  debtAware: string2().optional(),
15300
15396
  kind: TrackWorkKindSchema,
15301
15397
  limit: number3().int().min(1).max(250).default(50),
15398
+ paidMode: _enum(["quota", "prior"]).optional(),
15302
15399
  scope: TrackWorkScopeSchema.default("all")
15303
15400
  })).output(object({
15304
15401
  capabilities: TrackWorkCapabilitiesSchema.optional(),
15305
15402
  debtPending: boolean2().optional(),
15306
15403
  ok: literal(true),
15404
+ oldestQueuedCaptureOver24h: boolean2().optional(),
15307
15405
  queued: number2().optional(),
15308
15406
  tracks: array(TrackWorkItemSchema)
15309
15407
  }));
@@ -16413,6 +16511,7 @@ var init_search2 = __esm(() => {
16413
16511
  bpmMin: number2().optional(),
16414
16512
  key: string2().optional(),
16415
16513
  label: string2().optional(),
16514
+ sound: string2().optional(),
16416
16515
  soundsLike: string2().optional(),
16417
16516
  soundsLikeArtists: array(string2()).max(6).optional(),
16418
16517
  text: string2().optional(),
@@ -16432,6 +16531,7 @@ var init_search2 = __esm(() => {
16432
16531
  logId: string2().optional(),
16433
16532
  previewable: boolean2().optional(),
16434
16533
  releaseDate: string2().optional(),
16534
+ similar: boolean2().optional(),
16435
16535
  spotifyUrl: string2().optional(),
16436
16536
  title: string2(),
16437
16537
  trackId: string2()
@@ -16694,6 +16794,7 @@ var init_tracks = __esm(() => {
16694
16794
  var contract, CONTRACT_OPERATION_NAMES, CONTRACT_OPERATION_ROUTES;
16695
16795
  var init_orpc = __esm(() => {
16696
16796
  init_dist3();
16797
+ init_admin_catalogue();
16697
16798
  init_admin_albums();
16698
16799
  init_admin_artifacts();
16699
16800
  init_admin_artist_rules();
@@ -19204,6 +19305,19 @@ async function mintLabelCommand(mbLabelId, seedState, takeOverSlug) {
19204
19305
  });
19205
19306
  return { label: response.label, outcome: response.outcome, takenOver: response.takenOver };
19206
19307
  }
19308
+ async function listLabelsAdminCommand(seedState) {
19309
+ const query = seedState === undefined ? "" : `?seedState=${encodeURIComponent(seedState)}`;
19310
+ const response = await adminApiGet(`/api/v1/admin/labels${query}`);
19311
+ return response.labels;
19312
+ }
19313
+ async function recordLabelTriageCommand(slug, payload) {
19314
+ const response = await adminApiPost(`/api/v1/admin/labels/${encodeURIComponent(slug.trim().toLowerCase())}/triage`, payload);
19315
+ return {
19316
+ droppedInertRules: response.droppedInertRules,
19317
+ superseded: response.superseded,
19318
+ triageCheckedAt: response.triageCheckedAt
19319
+ };
19320
+ }
19207
19321
  async function describeLabelCommand(slug, options) {
19208
19322
  return adminApiPost(`/api/v1/admin/labels/${encodeURIComponent(slug)}/bio`, buildBioBody2(options));
19209
19323
  }
@@ -23013,6 +23127,33 @@ JSON field reference:
23013
23127
  console.log(line);
23014
23128
  }
23015
23129
  });
23130
+ labels.command("list").description("List labels with their crawl-seed state and triage cursor").option("--seed-state <state>", "Only this state: enabled, disabled, or undecided").option("--json", "Print JSON", false).action(async (options) => {
23131
+ const seedState = options.seedState;
23132
+ if (seedState !== undefined && seedState !== "enabled" && seedState !== "disabled" && seedState !== "undecided") {
23133
+ throw new Error("Pass --seed-state enabled|disabled|undecided");
23134
+ }
23135
+ await Promise.resolve().then(() => init_admin_labels2());
23136
+ const labels = await listLabelsAdminCommand(seedState);
23137
+ if (options.json) {
23138
+ console.log(JSON.stringify({ labels }, null, 2));
23139
+ return;
23140
+ }
23141
+ for (const label of labels) {
23142
+ const looked = label.triageCheckedAt ? label.triageVerdict : "never looked";
23143
+ console.log(`${label.slug} ${label.seedState} ${looked ?? ""}`.trimEnd());
23144
+ }
23145
+ });
23146
+ labels.command("triage").description("Record what a triage round found for a label (agent; never rules)").argument("<slug>", "The label slug").requiredOption("--payload <file>", "JSON file holding the round's finding for this label").option("--json", "Print JSON", false).action(async (slug, options) => {
23147
+ const payload = JSON.parse(readFileSync6(options.payload, "utf8"));
23148
+ await Promise.resolve().then(() => init_admin_labels2());
23149
+ const result = await recordLabelTriageCommand(slug, payload);
23150
+ if (options.json) {
23151
+ console.log(JSON.stringify(result, null, 2));
23152
+ return;
23153
+ }
23154
+ const dropped = result.droppedInertRules > 0 ? ` \u2014 dropped ${result.droppedInertRules} inert` : "";
23155
+ console.log(`${slug} \u2192 ${payload.verdict}${dropped}${result.superseded ? " (superseded)" : ""}`);
23156
+ });
23016
23157
  labels.command("mint").description("Mint a label from its MusicBrainz MBID (operator; idempotent)").argument("<mbid>", "The MusicBrainz label MBID").option("--seed-state <state>", "Rule it on arrival: enabled, disabled, or undecided").option("--take-over <slug>", "Re-point this trackless row's identity onto the minted entity").option("--json", "Print JSON", false).action(async (mbid, options) => {
23017
23158
  const seedState = options.seedState;
23018
23159
  if (seedState !== undefined && seedState !== "enabled" && seedState !== "disabled" && seedState !== "undecided") {
@@ -26043,6 +26184,7 @@ var stringOptions = new Set([
26043
26184
  "--page-digest",
26044
26185
  "--page-limit",
26045
26186
  "--parent-id",
26187
+ "--payload",
26046
26188
  "--plate",
26047
26189
  "--plate-background",
26048
26190
  "--platform",