fluncle 0.173.0 → 0.174.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.
- package/bin/fluncle.mjs +103 -3
- package/package.json +1 -1
package/bin/fluncle.mjs
CHANGED
|
@@ -561,7 +561,7 @@ function parseVersion(version) {
|
|
|
561
561
|
var currentVersion;
|
|
562
562
|
var init_version = __esm(() => {
|
|
563
563
|
init_output();
|
|
564
|
-
currentVersion = "0.
|
|
564
|
+
currentVersion = "0.174.0".trim() ? "0.174.0".trim() : "0.1.0";
|
|
565
565
|
});
|
|
566
566
|
|
|
567
567
|
// src/update-notifier.ts
|
|
@@ -2259,7 +2259,7 @@ function parseVersion2(version) {
|
|
|
2259
2259
|
var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
|
|
2260
2260
|
var init_version2 = __esm(() => {
|
|
2261
2261
|
init_output();
|
|
2262
|
-
currentVersion2 = "0.
|
|
2262
|
+
currentVersion2 = "0.174.0".trim() ? "0.174.0".trim() : "0.1.0";
|
|
2263
2263
|
});
|
|
2264
2264
|
|
|
2265
2265
|
// ../../packages/registry/src/index.ts
|
|
@@ -2476,7 +2476,7 @@ var init_src = __esm(() => {
|
|
|
2476
2476
|
],
|
|
2477
2477
|
kind: "web_route",
|
|
2478
2478
|
name: "web.tracks",
|
|
2479
|
-
operatorNotes: "The top-level track index — the whole archive as one browse list, findings in full voice and the catalogue rows in the unlit register (DESIGN.md). Ordered by tracks.release_date (what came out), never findings.added_at (the Found Rule),
|
|
2479
|
+
operatorNotes: "The top-level track index — the whole archive as one browse list, findings in full voice and the catalogue rows in the unlit register (DESIGN.md). Ordered by tracks.release_date (what came out), never findings.added_at (the Found Rule), numbered-paginated (?page=N) over the tracks_release_date_idx btree with a quiet YEAR fast lane, so a crawler with no JS walks the whole list (lib/server/tracks-hub.ts). The filter params MIRROR the search vocabulary verbatim (yearMin/yearMax, bpmMin/bpmMax, key, label; galaxy is the one extension). The bare HUB is always indexable + in the sitemap, each page self-canonical; ANY filter param present flips it to noindex, and paged bare URLs stay out of the sitemap. The INDEX is always-200, so it is HTTP-probeable.",
|
|
2480
2480
|
probeConfig: { cadenceMs: PROBE_CADENCE_MS, kind: "http", timeoutMs: PROBE_TIMEOUT_MS },
|
|
2481
2481
|
route: "/tracks",
|
|
2482
2482
|
url: `${SITE}/tracks`,
|
|
@@ -3118,6 +3118,23 @@ var init_src = __esm(() => {
|
|
|
3118
3118
|
title: "Track crawler",
|
|
3119
3119
|
weights: { status: "hidden" }
|
|
3120
3120
|
},
|
|
3121
|
+
{
|
|
3122
|
+
command: "fluncle admin backfills apple-releases",
|
|
3123
|
+
exposedContent: [
|
|
3124
|
+
"tap Apple Music's latest releases for the operator's enabled seed labels → day-one uncertified catalogue rows"
|
|
3125
|
+
],
|
|
3126
|
+
kind: "cron",
|
|
3127
|
+
name: "cron.apple-releases",
|
|
3128
|
+
operatorNotes: "every 24h, run by a rave-02 HOST systemd timer (docs/agents/hermes/apple-releases-timer/). The MusicKit FRESHNESS TAP (D8): MusicBrainz WALKS the graph (cron.crawl) but lags a release ~2 weeks; Apple has it day one, so this taps each ENABLED seed label's latest releases and mints METADATA-ONLY catalogue rows (a `tracks` row with no `findings` row) with their real release dates — closing the /fresh lag cliff. It certifies nothing, publishes nothing, and never widens the graph (no new labels, no artist hops). Deduped against the MB crawl from both directions (ISRC + same-album title fold). Worker-paced (the three APPLE_MUSIC_* secrets live on the Worker); a NO-OP until they are provisioned. Zero LLM tokens. Source: docs/agents/hermes/scripts/apple-releases-sweep.*. See docs/catalogue-crawler.md.",
|
|
3129
|
+
probeConfig: {
|
|
3130
|
+
cadenceMs: 24 * 60 * MINUTE_MS,
|
|
3131
|
+
cronName: "fluncle-apple-releases",
|
|
3132
|
+
kind: "cron"
|
|
3133
|
+
},
|
|
3134
|
+
statusDescription: "taps day-one releases from the enabled labels",
|
|
3135
|
+
title: "Freshness tap",
|
|
3136
|
+
weights: { status: "hidden" }
|
|
3137
|
+
},
|
|
3121
3138
|
{
|
|
3122
3139
|
command: "fluncle admin catalogue rank",
|
|
3123
3140
|
exposedContent: [
|
|
@@ -4093,6 +4110,7 @@ __export(exports_admin_tracks, {
|
|
|
4093
4110
|
backfillRecordingMbidsCommand: () => backfillRecordingMbidsCommand,
|
|
4094
4111
|
backfillLastfmCommand: () => backfillLastfmCommand,
|
|
4095
4112
|
backfillDiscogsCommand: () => backfillDiscogsCommand,
|
|
4113
|
+
backfillAppleReleasesCommand: () => backfillAppleReleasesCommand,
|
|
4096
4114
|
backfillAppleMusicCommand: () => backfillAppleMusicCommand,
|
|
4097
4115
|
backfillAppleCatalogueCommand: () => backfillAppleCatalogueCommand
|
|
4098
4116
|
});
|
|
@@ -4278,6 +4296,10 @@ async function backfillAppleCatalogueCommand(limit, dryRun) {
|
|
|
4278
4296
|
const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
|
|
4279
4297
|
return adminApiPost(`/api/admin/backfill/apple-catalogue?${params.toString()}`);
|
|
4280
4298
|
}
|
|
4299
|
+
async function backfillAppleReleasesCommand(limit, dryRun) {
|
|
4300
|
+
const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
|
|
4301
|
+
return adminApiPost(`/api/admin/backfill/apple-releases?${params.toString()}`);
|
|
4302
|
+
}
|
|
4281
4303
|
async function backfillRecordingMbidsCommand(limit, dryRun, cursor) {
|
|
4282
4304
|
const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
|
|
4283
4305
|
if (cursor) {
|
|
@@ -9657,6 +9679,10 @@ function addAdminCommands(program2) {
|
|
|
9657
9679
|
const { backfillAppleCatalogueCommand: backfillAppleCatalogueCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
|
|
9658
9680
|
await runBackfillAppleCatalogue(options, backfillAppleCatalogueCommand2);
|
|
9659
9681
|
});
|
|
9682
|
+
backfill.command("apple-releases").description("Tap Apple's latest releases for enabled seed labels into catalogue rows").option("--dry-run", "Report the labels that would be probed without any Apple call", false).option("--limit <limit>", "Max enabled seed labels to probe per pass", "5").option("--json", "Print JSON", false).action(async (options) => {
|
|
9683
|
+
const { backfillAppleReleasesCommand: backfillAppleReleasesCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
|
|
9684
|
+
await runBackfillAppleReleases(options, backfillAppleReleasesCommand2);
|
|
9685
|
+
});
|
|
9660
9686
|
backfill.command("artists").description("Back-fill the artist entity (artists + track_artists) for existing findings").option("--dry-run", "Report which findings would be upserted without touching the DB", false).option("--limit <limit>", "Max findings to process", "50").option("--json", "Print JSON", false).action(async (options) => {
|
|
9661
9687
|
const { backfillArtistsCommand: backfillArtistsCommand2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
|
|
9662
9688
|
await runBackfillArtists(options, backfillArtistsCommand2);
|
|
@@ -10350,6 +10376,80 @@ async function runBackfillAppleCatalogue(options, backfillAppleCatalogueCommand2
|
|
|
10350
10376
|
process.exitCode = 1;
|
|
10351
10377
|
}
|
|
10352
10378
|
}
|
|
10379
|
+
async function runBackfillAppleReleases(options, backfillAppleReleasesCommand2) {
|
|
10380
|
+
const perPass = parseListLimit(options.limit);
|
|
10381
|
+
const newTrackIds = [];
|
|
10382
|
+
const resolvedLabels = [];
|
|
10383
|
+
const unresolvedLabels = [];
|
|
10384
|
+
let dryRun = options.dryRun;
|
|
10385
|
+
let throttled = false;
|
|
10386
|
+
let breakerTripped = false;
|
|
10387
|
+
let configured = true;
|
|
10388
|
+
let labelsProbed = 0;
|
|
10389
|
+
let albumsSeen = 0;
|
|
10390
|
+
let newRows = 0;
|
|
10391
|
+
let skippedKnown = 0;
|
|
10392
|
+
const MAX_PASSES = 100;
|
|
10393
|
+
for (let pass = 0;pass < MAX_PASSES; pass += 1) {
|
|
10394
|
+
const result = await backfillAppleReleasesCommand2(perPass, options.dryRun);
|
|
10395
|
+
dryRun = result.dryRun;
|
|
10396
|
+
configured = result.configured;
|
|
10397
|
+
labelsProbed += result.labelsProbed;
|
|
10398
|
+
albumsSeen += result.albumsSeen;
|
|
10399
|
+
newRows += result.newRows;
|
|
10400
|
+
skippedKnown += result.skippedKnown;
|
|
10401
|
+
newTrackIds.push(...result.newTrackIds);
|
|
10402
|
+
resolvedLabels.push(...result.resolvedLabels);
|
|
10403
|
+
unresolvedLabels.push(...result.unresolvedLabels);
|
|
10404
|
+
if (!options.json) {
|
|
10405
|
+
const verb2 = result.dryRun ? "would probe" : "probed";
|
|
10406
|
+
console.log(` \u2026${verb2} ${result.dryRun ? result.resolvedLabels.length : result.labelsProbed} label(s); ${result.newRows} new; ${result.skippedKnown} known; ${result.unresolvedLabels.length} unresolved`);
|
|
10407
|
+
}
|
|
10408
|
+
if (!result.configured) {
|
|
10409
|
+
break;
|
|
10410
|
+
}
|
|
10411
|
+
if (result.breakerTripped) {
|
|
10412
|
+
breakerTripped = true;
|
|
10413
|
+
break;
|
|
10414
|
+
}
|
|
10415
|
+
if (result.rateLimited) {
|
|
10416
|
+
throttled = true;
|
|
10417
|
+
break;
|
|
10418
|
+
}
|
|
10419
|
+
if (result.dryRun) {
|
|
10420
|
+
break;
|
|
10421
|
+
}
|
|
10422
|
+
if (result.labelsProbed === 0 && result.resolvedLabels.length === 0) {
|
|
10423
|
+
break;
|
|
10424
|
+
}
|
|
10425
|
+
}
|
|
10426
|
+
if (options.json) {
|
|
10427
|
+
printSweepJson({
|
|
10428
|
+
albumsSeen,
|
|
10429
|
+
breakerTripped,
|
|
10430
|
+
configured,
|
|
10431
|
+
dryRun,
|
|
10432
|
+
labelsProbed,
|
|
10433
|
+
newRows,
|
|
10434
|
+
newTrackIds,
|
|
10435
|
+
rateLimited: throttled,
|
|
10436
|
+
resolvedLabels,
|
|
10437
|
+
skippedKnown,
|
|
10438
|
+
unresolvedLabels
|
|
10439
|
+
}, 0);
|
|
10440
|
+
return;
|
|
10441
|
+
}
|
|
10442
|
+
if (!configured) {
|
|
10443
|
+
console.log("Apple releases tap is not configured (the Worker's MusicKit secrets are unset) \u2014 nothing probed.");
|
|
10444
|
+
return;
|
|
10445
|
+
}
|
|
10446
|
+
const verb = dryRun ? "Would probe" : "Probed";
|
|
10447
|
+
const probedCount = dryRun ? resolvedLabels.length : labelsProbed;
|
|
10448
|
+
console.log(`${verb} ${probedCount} enabled seed label(s); ${newRows} new catalogue row(s); ${skippedKnown} already known; ${resolvedLabels.length} resolved; ${unresolvedLabels.length} unresolved.`);
|
|
10449
|
+
for (const slug of unresolvedLabels) {
|
|
10450
|
+
console.log(` no exact Apple label match: ${slug}`);
|
|
10451
|
+
}
|
|
10452
|
+
}
|
|
10353
10453
|
async function runBackfillArtists(options, backfillArtistsCommand2) {
|
|
10354
10454
|
const limit = parseListLimit(options.limit);
|
|
10355
10455
|
const upserted = [];
|
package/package.json
CHANGED