fluncle 0.270.0 → 0.271.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 +4 -114
  2. package/package.json +1 -1
package/bin/fluncle.mjs CHANGED
@@ -651,7 +651,7 @@ function parseVersion(version) {
651
651
  var currentVersion;
652
652
  var init_version = __esm(() => {
653
653
  init_output();
654
- currentVersion = "0.270.0".trim() ? "0.270.0".trim() : "0.1.0";
654
+ currentVersion = "0.271.0".trim() ? "0.271.0".trim() : "0.1.0";
655
655
  });
656
656
 
657
657
  // src/update-notifier.ts
@@ -2363,7 +2363,7 @@ function parseVersion2(version) {
2363
2363
  var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
2364
2364
  var init_version2 = __esm(() => {
2365
2365
  init_output();
2366
- currentVersion2 = "0.270.0".trim() ? "0.270.0".trim() : "0.1.0";
2366
+ currentVersion2 = "0.271.0".trim() ? "0.271.0".trim() : "0.1.0";
2367
2367
  });
2368
2368
 
2369
2369
  // ../../packages/registry/src/index.ts
@@ -3481,23 +3481,6 @@ var init_src = __esm(() => {
3481
3481
  title: "Track crawler",
3482
3482
  weights: { status: "hidden" }
3483
3483
  },
3484
- {
3485
- exposedContent: [
3486
- "tap day-one fresh releases for the operator's enabled seed labels → uncertified catalogue rows"
3487
- ],
3488
- kind: "cron",
3489
- name: "cron.label-releases",
3490
- operatorNotes: "every 15 minutes from 03:00 through 08:45 UTC, run by a Hermes host systemd timer (docs/agents/hermes/label-releases-timer/). The FRESHNESS TAP (D8): MusicBrainz WALKS the graph (cron.crawl) but lags a release ~2 weeks; Spotify has it day one, so this mints METADATA-ONLY catalogue rows (a `tracks` row with no `findings` row) for each ENABLED seed label's fresh releases with their real dates — closing the /fresh lag cliff. The WORKER does all of it (`backfill_label_releases`, agent tier): it searches the official Spotify API (`label:\"<name>\" tag:new`), reads each hit as a SINGLE `GET /albums/{id}` then `GET /tracks/{id}` (the batch endpoints are 403 at our tier), and mints. The box sweep is a thin HTTP TRIGGER that POSTs bounded passes with the agent token — no vendor token, no CLI dependency (a pinned box CLI missing a flag broke an earlier run). The gate, both required: artist-grounding (an album's Spotify artist already in `artists.spotify_artist_id` — the PRIMARY anchor that stops cross-genre homonym junk) AND an EXACT fold-match of the seed name in the ℗/© copyright; an album with no release_date is dropped outright (/fresh could never show it). BUDGET: the tap shares the official app's per-app window with the user-facing paths, so it paces itself against the shared call meter and stops at a FRACTION of the window (its own ceiling) — user write paths get the window, the tap takes only slack. Hitting that ceiling ends the pass cleanly and the durable per-label cadence stamps resume it next tick. It certifies nothing, publishes nothing, never widens the graph (no new labels, no artist hops). Deduped against the MB crawl from both directions (Spotify id/uri/ISRC + same-album title fold). No vendor spend and zero LLM tokens. Source: docs/agents/hermes/scripts/label-releases-sweep.*. See docs/catalogue-crawler.md.",
3491
- probeConfig: {
3492
- cadenceMs: 24 * 60 * MINUTE_MS,
3493
- cronName: "fluncle-label-releases",
3494
- kind: "cron",
3495
- schedule: { time: "03:00", tz: "UTC" }
3496
- },
3497
- statusDescription: "taps day-one releases from the enabled labels",
3498
- title: "Freshness tap",
3499
- weights: { status: "hidden" }
3500
- },
3501
3484
  {
3502
3485
  exposedContent: [
3503
3486
  "checks pipeline yield against measured backlog and alerts the operator on sustained stalls"
@@ -10257,7 +10240,7 @@ var init_zod = __esm(() => {
10257
10240
  });
10258
10241
 
10259
10242
  // ../../packages/contracts/src/orpc/admin-catalogue.ts
10260
- 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, PipelineWatchBoundedCountSchema, getPipeline, 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, AnchorResolveResultSchema, AnchorCommitResultSchema, prepareAnchor, AnchorPhaseBatchItemFailureSchema, prepareAnchorBatch, resolveAnchorCandidate, commitAnchor, commitAnchorBatch, getAnchorReceipt, getAnchorPaidToken, cancelAnchorPaidResult, resolveAnchorPaidResult, resolveAnchor, ReleaseLinkResultSchema, ReleaseLinkProbeSchema, resolveAnchorReleaseProbe, commitAnchorRelease, resolveAnchorReview, CrawlHoldReasonSchema, CrawlHoldStateSchema, CrawlHoldSchema, listCrawlHolds, resolveCrawlHold, setAnchorSearch, setAnchorApify, CaptureBudgetStateSchema, getCaptureBudget, setCaptureBudget, AnchorApifyBudgetSchema, getAnchorApifyBudget, setAnchorApifyBudget, SpotifyAnchorBreakerStateSchema, AnchorRungFlagsSchema, getSpotifyAnchorBreaker, setSpotifyConsumerBudget, LabelReleasesBudgetSchema, getLabelReleasesBudget, setLabelReleasesBudget, resetSpotifyAnchorBreaker, AppleBreakerStateSchema, resetAppleBreaker, adminCatalogueContract;
10243
+ 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, PipelineWatchBoundedCountSchema, getPipeline, 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, AnchorResolveResultSchema, AnchorCommitResultSchema, prepareAnchor, AnchorPhaseBatchItemFailureSchema, prepareAnchorBatch, resolveAnchorCandidate, commitAnchor, commitAnchorBatch, getAnchorReceipt, getAnchorPaidToken, cancelAnchorPaidResult, resolveAnchorPaidResult, resolveAnchor, ReleaseLinkResultSchema, ReleaseLinkProbeSchema, resolveAnchorReleaseProbe, commitAnchorRelease, resolveAnchorReview, CrawlHoldReasonSchema, CrawlHoldStateSchema, CrawlHoldSchema, listCrawlHolds, resolveCrawlHold, setAnchorSearch, setAnchorApify, CaptureBudgetStateSchema, getCaptureBudget, setCaptureBudget, AnchorApifyBudgetSchema, getAnchorApifyBudget, setAnchorApifyBudget, SpotifyAnchorBreakerStateSchema, AnchorRungFlagsSchema, getSpotifyAnchorBreaker, setSpotifyConsumerBudget, resetSpotifyAnchorBreaker, AppleBreakerStateSchema, resetAppleBreaker, adminCatalogueContract;
10261
10244
  var init_admin_catalogue = __esm(() => {
10262
10245
  init_dist3();
10263
10246
  init_zod();
@@ -11160,25 +11143,6 @@ var init_admin_catalogue = __esm(() => {
11160
11143
  consumer: _enum(["anchor", "artist_images", "public_search"]),
11161
11144
  dailyBudget: number2().int().min(0).max(1e6)
11162
11145
  })).output(object({ ok: literal(true) }));
11163
- LabelReleasesBudgetSchema = object({
11164
- callsSpent: number2().int().nonnegative(),
11165
- dailyBudget: number2().int().nonnegative(),
11166
- spotifyDailyCalls: number2().int().nonnegative()
11167
- });
11168
- getLabelReleasesBudget = oc.route({
11169
- method: "GET",
11170
- operationId: "getLabelReleasesBudget",
11171
- path: "/admin/catalogue/label-releases-budget",
11172
- summary: "Read the label releases tap daily budget and Spotify usage",
11173
- tags: ["Admin"]
11174
- }).input(object({})).output(LabelReleasesBudgetSchema.extend({ ok: literal(true) }));
11175
- setLabelReleasesBudget = oc.route({
11176
- method: "PUT",
11177
- operationId: "setLabelReleasesBudget",
11178
- path: "/admin/catalogue/label-releases-budget",
11179
- summary: "Set the label releases tap daily budget (operator)",
11180
- tags: ["Admin"]
11181
- }).input(object({ dailyBudget: number2().int().min(0).max(1e6) })).output(LabelReleasesBudgetSchema.extend({ ok: literal(true) }));
11182
11146
  resetSpotifyAnchorBreaker = oc.route({
11183
11147
  method: "POST",
11184
11148
  operationId: "resetSpotifyAnchorBreaker",
@@ -11216,7 +11180,6 @@ var init_admin_catalogue = __esm(() => {
11216
11180
  get_anchor_receipt: getAnchorReceipt,
11217
11181
  get_capture_budget: getCaptureBudget,
11218
11182
  get_crawl_status: getCrawlStatus,
11219
- get_label_releases_budget: getLabelReleasesBudget,
11220
11183
  get_pipeline: getPipeline,
11221
11184
  get_spotify_anchor_breaker: getSpotifyAnchorBreaker,
11222
11185
  list_catalogue_tracks: listCatalogueTracks,
@@ -11242,7 +11205,6 @@ var init_admin_catalogue = __esm(() => {
11242
11205
  set_anchor_apify_budget: setAnchorApifyBudget,
11243
11206
  set_anchor_search: setAnchorSearch,
11244
11207
  set_capture_budget: setCaptureBudget,
11245
- set_label_releases_budget: setLabelReleasesBudget,
11246
11208
  set_spotify_consumer_budget: setSpotifyConsumerBudget,
11247
11209
  set_track_dismissed: setTrackDismissed,
11248
11210
  verify_capture: verifyCapture
@@ -11970,7 +11932,7 @@ var init_admin_attention2 = __esm(() => {
11970
11932
  });
11971
11933
 
11972
11934
  // ../../packages/contracts/src/orpc/admin-backfills.ts
11973
- var DISCOGS_RELEASE_WORK_LIMIT = 3, DISCOGS_SEARCH_QUERY_LIMIT = 3, DISCOGS_RELEASES_PER_TRACK_LIMIT = 12, DISCOGS_FACTS_WORK_LIMIT = 25, DISCOGS_LABEL_WORK_LIMIT = 4, DISCOGS_ID_MAX, DISCOGS_TEXT_MAX = 500, DISCOGS_URI_MAX = 2048, DISCOGS_QUERY_MAX = 2048, DISCOGS_ARTIST_LIMIT = 20, DISCOGS_LABEL_LIMIT = 20, DISCOGS_STYLE_LIMIT = 50, DISCOGS_FORMAT_LIMIT = 20, DISCOGS_TRACKLIST_LIMIT = 500, DISCOGS_LABEL_DETAIL_IMAGE_LIMIT = 20, MAX_LABEL_IMAGE_BYTES = 5000000, MAX_LABEL_IMAGE_BASE64_CHARS, DiscogsIdSchema, DiscogsTextSchema, DiscogsReleaseEvidenceSchema, DiscogsReleaseCandidateSchema, DiscogsReleaseCandidateBatchSchema, DiscogsReleaseWorkSchema, DiscogsFactsWorkSchema, DiscogsFactsCandidateSchema, DiscogsFactsCandidateBatchSchema, DiscogsLabelDetailImageSchema, DiscogsLabelImageBytesSchema, DiscogsLabelCandidateSchema, DiscogsLabelCandidateBatchSchema, DiscogsLabelWorkSchema, DiscogsResolvedSchema, LastfmFailedSchema, AppleMusicResolvedSchema, AppleMusicFailedSchema, backfillDiscogs, DiscogsFactsResolvedSchema, DiscogsFactsFailedSchema, backfillDiscogsFacts, backfillLastfm, backfillAppleMusic, AppleCatalogueResolvedSchema, AppleCatalogueFailedSchema, backfillAppleCatalogue, BeatportResolvedSchema, BeatportFailedSchema, BeatportCatalogueResolvedSchema, BeatportCatalogueFailedSchema, backfillBeatport, DeezerResolvedSchema, DeezerFailedSchema, backfillDeezer, backfillLabelReleases, LabelImagesBackfillFailedSchema, backfillLabelImages, LabelLineageBackfillFailedSchema, backfillLabelLineage, CoverMastersFailedSchema, backfillCoverMasters, RecordingMbidsFailedSchema, backfillRecordingMbids, backfillArtistEdges, backfillArtistCredits, adminBackfillsContract;
11935
+ var DISCOGS_RELEASE_WORK_LIMIT = 3, DISCOGS_SEARCH_QUERY_LIMIT = 3, DISCOGS_RELEASES_PER_TRACK_LIMIT = 12, DISCOGS_FACTS_WORK_LIMIT = 25, DISCOGS_LABEL_WORK_LIMIT = 4, DISCOGS_ID_MAX, DISCOGS_TEXT_MAX = 500, DISCOGS_URI_MAX = 2048, DISCOGS_QUERY_MAX = 2048, DISCOGS_ARTIST_LIMIT = 20, DISCOGS_LABEL_LIMIT = 20, DISCOGS_STYLE_LIMIT = 50, DISCOGS_FORMAT_LIMIT = 20, DISCOGS_TRACKLIST_LIMIT = 500, DISCOGS_LABEL_DETAIL_IMAGE_LIMIT = 20, MAX_LABEL_IMAGE_BYTES = 5000000, MAX_LABEL_IMAGE_BASE64_CHARS, DiscogsIdSchema, DiscogsTextSchema, DiscogsReleaseEvidenceSchema, DiscogsReleaseCandidateSchema, DiscogsReleaseCandidateBatchSchema, DiscogsReleaseWorkSchema, DiscogsFactsWorkSchema, DiscogsFactsCandidateSchema, DiscogsFactsCandidateBatchSchema, DiscogsLabelDetailImageSchema, DiscogsLabelImageBytesSchema, DiscogsLabelCandidateSchema, DiscogsLabelCandidateBatchSchema, DiscogsLabelWorkSchema, DiscogsResolvedSchema, LastfmFailedSchema, AppleMusicResolvedSchema, AppleMusicFailedSchema, backfillDiscogs, DiscogsFactsResolvedSchema, DiscogsFactsFailedSchema, backfillDiscogsFacts, backfillLastfm, backfillAppleMusic, AppleCatalogueResolvedSchema, AppleCatalogueFailedSchema, backfillAppleCatalogue, BeatportResolvedSchema, BeatportFailedSchema, BeatportCatalogueResolvedSchema, BeatportCatalogueFailedSchema, backfillBeatport, DeezerResolvedSchema, DeezerFailedSchema, backfillDeezer, LabelImagesBackfillFailedSchema, backfillLabelImages, LabelLineageBackfillFailedSchema, backfillLabelLineage, CoverMastersFailedSchema, backfillCoverMasters, RecordingMbidsFailedSchema, backfillRecordingMbids, backfillArtistEdges, backfillArtistCredits, adminBackfillsContract;
11974
11936
  var init_admin_backfills = __esm(() => {
11975
11937
  init_dist3();
11976
11938
  init_zod();
@@ -12341,48 +12303,6 @@ var init_admin_backfills = __esm(() => {
12341
12303
  unvouchable: array(string2()),
12342
12304
  unvouchableCount: number2()
12343
12305
  }));
12344
- backfillLabelReleases = oc.route({
12345
- method: "POST",
12346
- operationId: "backfillLabelReleases",
12347
- path: "/admin/backfill/label-releases",
12348
- summary: "Tap Spotify's fresh releases for enabled seed labels into catalogue rows (bounded)",
12349
- tags: ["Admin"]
12350
- }).input(object({
12351
- dryRun: boolean2().default(false),
12352
- limit: number3().int().min(1).max(200).default(5)
12353
- })).output(object({
12354
- albumsMatched: number2(),
12355
- albumsSeen: number2(),
12356
- blockedReason: _enum([
12357
- "spotify_breaker",
12358
- "spotify_budget",
12359
- "spotify_budget_spent",
12360
- "spotify_quota",
12361
- "spotify_throttle"
12362
- ]).nullable(),
12363
- budgetPaused: boolean2(),
12364
- configured: boolean2(),
12365
- dryRun: boolean2(),
12366
- failedFetches: number2(),
12367
- failedLabels: array(string2()),
12368
- fetchCeilingHit: boolean2(),
12369
- labelSlugs: array(string2()),
12370
- labelsDue: number2(),
12371
- labelsProbed: number2(),
12372
- neverChecked: number2(),
12373
- newRows: number2(),
12374
- newTrackIds: array(string2()),
12375
- ok: literal(true),
12376
- quotaExceeded: boolean2(),
12377
- rateLimited: boolean2(),
12378
- retryAfterMs: number2(),
12379
- skippedKnown: number2(),
12380
- skippedUndated: number2(),
12381
- skippedUngrounded: number2(),
12382
- tapDailyBudget: number2().int(),
12383
- tapDailyCallsSpent: number2().int(),
12384
- tracksSkippedArtistRule: number2().optional()
12385
- }));
12386
12306
  LabelImagesBackfillFailedSchema = object({
12387
12307
  error: string2(),
12388
12308
  slug: string2()
@@ -12581,7 +12501,6 @@ var init_admin_backfills = __esm(() => {
12581
12501
  backfill_discogs_facts: backfillDiscogsFacts,
12582
12502
  backfill_label_images: backfillLabelImages,
12583
12503
  backfill_label_lineage: backfillLabelLineage,
12584
- backfill_label_releases: backfillLabelReleases,
12585
12504
  backfill_lastfm: backfillLastfm,
12586
12505
  backfill_recording_mbids: backfillRecordingMbids
12587
12506
  };
@@ -20054,12 +19973,6 @@ async function setSpotifyConsumerBudgetCommand(consumer, dailyBudget) {
20054
19973
  dailyBudget
20055
19974
  });
20056
19975
  }
20057
- async function labelReleasesBudgetCommand() {
20058
- return adminApiGet("/api/v1/admin/catalogue/label-releases-budget");
20059
- }
20060
- async function setLabelReleasesBudgetCommand(dailyBudget) {
20061
- return adminApiPut("/api/v1/admin/catalogue/label-releases-budget", { dailyBudget });
20062
- }
20063
19976
  async function anchorApifyBudgetCommand() {
20064
19977
  return adminApiGet("/api/v1/admin/catalogue/anchor/apify-budget");
20065
19978
  }
@@ -24822,29 +24735,6 @@ JSON field reference:
24822
24735
  console.log(`Settled ${paidCleared} pending paid receipt(s); recorded spend remains charged.`);
24823
24736
  }
24824
24737
  });
24825
- const labelReleasesBudget = catalogue.command("label-releases-budget").description("Read or set the label releases tap daily Spotify call budget");
24826
- labelReleasesBudget.option("--json", "Print JSON", false).action(async (options) => {
24827
- await Promise.resolve().then(() => init_admin_catalogue2());
24828
- const state = await labelReleasesBudgetCommand();
24829
- if (options.json) {
24830
- printJson({ ...state, ok: true });
24831
- return;
24832
- }
24833
- console.log(`LABEL RELEASES BUDGET \u2014 ${state.callsSpent}/${state.dailyBudget} tap calls today \xB7 ${state.spotifyDailyCalls} Spotify calls total`);
24834
- });
24835
- labelReleasesBudget.command("set").requiredOption("--calls <count>", "Daily tap Spotify call budget").option("--json", "Print JSON", false).action(async (options) => {
24836
- await Promise.resolve().then(() => init_admin_catalogue2());
24837
- const calls = Number(options.calls);
24838
- if (!Number.isSafeInteger(calls) || calls < 0 || calls > 1e6) {
24839
- throw new Error("--calls must be an integer from 0 to 1000000");
24840
- }
24841
- const state = await setLabelReleasesBudgetCommand(calls);
24842
- if (options.json) {
24843
- printJson({ ...state, ok: true });
24844
- return;
24845
- }
24846
- console.log(`LABEL RELEASES BUDGET \u2014 ${state.callsSpent}/${state.dailyBudget} tap calls today \xB7 ${state.spotifyDailyCalls} Spotify calls total`);
24847
- });
24848
24738
  const spotifyBudget = catalogue.command("spotify-consumer-budget").description("Read or set Spotify daily call budgets by consumer");
24849
24739
  const showSpotifyConsumerBudget = async (options) => {
24850
24740
  await Promise.resolve().then(() => init_admin_catalogue2());
package/package.json CHANGED
@@ -31,5 +31,5 @@
31
31
  "url": "git+https://github.com/mauricekleine/fluncle.git"
32
32
  },
33
33
  "type": "module",
34
- "version": "0.270.0"
34
+ "version": "0.271.0"
35
35
  }