fluncle 0.170.0 → 0.172.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 +52 -7
- 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.172.0".trim() ? "0.172.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.172.0".trim() ? "0.172.0".trim() : "0.1.0";
|
|
2263
2263
|
});
|
|
2264
2264
|
|
|
2265
2265
|
// ../../packages/registry/src/index.ts
|
|
@@ -3499,6 +3499,24 @@ var init_src = __esm(() => {
|
|
|
3499
3499
|
title: "Reach snapshot",
|
|
3500
3500
|
weights: { status: "secondary" }
|
|
3501
3501
|
},
|
|
3502
|
+
{
|
|
3503
|
+
command: "fluncle admin catalogue demand",
|
|
3504
|
+
exposedContent: [
|
|
3505
|
+
"nightly demand reorder — reads Simple Analytics pageviews for /artist + /label pages and reorders crawl/capture priority toward what real visitors looked at (--no-agent)"
|
|
3506
|
+
],
|
|
3507
|
+
kind: "cron",
|
|
3508
|
+
name: "cron.demand",
|
|
3509
|
+
operatorNotes: "04:40 Amsterdam daily (just after the 04:00 reach snapshot — both daily analytics reads in one window). A bare trigger (the reach/rank shape): fires the AGENT-tier record_demand op once — the WORKER reads Simple Analytics for the /artist/<slug> + /label/<slug> pageviews over the trailing 30 days and REWRITES two derived reorder columns, tracks.demand_score (the capture queue's within-tier secondary sort) and crawl_frontier.demand_rank (the frontier pick's within-hop tiebreak). RANK-ORDER ONLY: it reorders within a tier and never overrides the capture_priority veto (a ruled-out label is never resurrected); the seed-allowlist crawl gate is untouched. Clear-then-set, so a same-window re-run is idempotent. Unprovisioned (no SIMPLE_ANALYTICS_API_KEY) it returns configured:false and is a clean no-op. Zero LLM tokens; the box's agent token drives it and the SA key lives Worker-side (no new box secret). Source: docs/agents/hermes/scripts/demand-sweep.*. See docs/catalogue-crawler.md § Demand.",
|
|
3510
|
+
probeConfig: {
|
|
3511
|
+
cadenceMs: 24 * 60 * MINUTE_MS,
|
|
3512
|
+
cronName: "fluncle-demand",
|
|
3513
|
+
kind: "cron",
|
|
3514
|
+
schedule: { time: "04:40", tz: "Europe/Amsterdam" }
|
|
3515
|
+
},
|
|
3516
|
+
statusDescription: "leans the catalogue toward what visitors looked at",
|
|
3517
|
+
title: "Demand reorder",
|
|
3518
|
+
weights: { status: "hidden" }
|
|
3519
|
+
},
|
|
3502
3520
|
{
|
|
3503
3521
|
exposedContent: [
|
|
3504
3522
|
"daily catalogue-funnel snapshot — one row per UTC day of stage totals + queue depths + frontier counts behind /admin/funnel (--no-agent)"
|
|
@@ -6180,13 +6198,18 @@ __export(exports_admin_catalogue, {
|
|
|
6180
6198
|
clearWrongAudioCommand: () => clearWrongAudioCommand,
|
|
6181
6199
|
certifyTrackCommand: () => certifyTrackCommand,
|
|
6182
6200
|
catalogueRankCommand: () => catalogueRankCommand,
|
|
6183
|
-
catalogueListCommand: () => catalogueListCommand
|
|
6201
|
+
catalogueListCommand: () => catalogueListCommand,
|
|
6202
|
+
catalogueDemandCommand: () => catalogueDemandCommand
|
|
6184
6203
|
});
|
|
6185
6204
|
async function catalogueRankCommand(options) {
|
|
6186
6205
|
const limit = options.limit ? Number.parseInt(options.limit, 10) : undefined;
|
|
6187
6206
|
const response = await adminApiPost("/api/admin/catalogue/rank", limit ? { limit } : {});
|
|
6188
6207
|
return { summary: response.summary, telescope: response.telescope };
|
|
6189
6208
|
}
|
|
6209
|
+
async function catalogueDemandCommand() {
|
|
6210
|
+
const response = await adminApiPost("/api/admin/catalogue/demand", {});
|
|
6211
|
+
return response.summary;
|
|
6212
|
+
}
|
|
6190
6213
|
async function catalogueListCommand(options) {
|
|
6191
6214
|
const params = new URLSearchParams;
|
|
6192
6215
|
params.set("lens", options.lens && CATALOGUE_LENSES.has(options.lens) ? options.lens : "ear");
|
|
@@ -6389,11 +6412,14 @@ var exports_admin_covers = {};
|
|
|
6389
6412
|
__export(exports_admin_covers, {
|
|
6390
6413
|
backfillCoverMastersCommand: () => backfillCoverMastersCommand
|
|
6391
6414
|
});
|
|
6392
|
-
async function backfillCoverMastersCommand(kind, limit, dryRun, cursor) {
|
|
6415
|
+
async function backfillCoverMastersCommand(kind, limit, dryRun, cursor, retryNone = false) {
|
|
6393
6416
|
const params = new URLSearchParams({ dryRun: String(dryRun), kind, limit: String(limit) });
|
|
6394
6417
|
if (cursor) {
|
|
6395
6418
|
params.set("cursor", cursor);
|
|
6396
6419
|
}
|
|
6420
|
+
if (retryNone) {
|
|
6421
|
+
params.set("retry", "none");
|
|
6422
|
+
}
|
|
6397
6423
|
return adminApiPost(`/api/admin/backfill/cover-masters?${params.toString()}`);
|
|
6398
6424
|
}
|
|
6399
6425
|
var init_admin_covers = __esm(() => {
|
|
@@ -9467,6 +9493,19 @@ function addAdminCommands(program2) {
|
|
|
9467
9493
|
const { catalogueRankCommand: catalogueRankCommand2 } = await Promise.resolve().then(() => (init_admin_catalogue(), exports_admin_catalogue));
|
|
9468
9494
|
await runCatalogueRank(options, catalogueRankCommand2);
|
|
9469
9495
|
});
|
|
9496
|
+
catalogue.command("demand").description("Reorder crawl/capture priority from Simple Analytics pageviews (one tick)").option("--json", "Print JSON", false).action(async (options) => {
|
|
9497
|
+
const { catalogueDemandCommand: catalogueDemandCommand2 } = await Promise.resolve().then(() => (init_admin_catalogue(), exports_admin_catalogue));
|
|
9498
|
+
const summary = await catalogueDemandCommand2();
|
|
9499
|
+
if (options.json) {
|
|
9500
|
+
printJson({ ok: true, summary });
|
|
9501
|
+
return;
|
|
9502
|
+
}
|
|
9503
|
+
if (!summary.configured) {
|
|
9504
|
+
console.log("Simple Analytics is not configured \u2014 demand left untouched (a clean no-op).");
|
|
9505
|
+
return;
|
|
9506
|
+
}
|
|
9507
|
+
console.log(`Read ${summary.pagesRead} page(s) over ${summary.window.start}\u2026${summary.window.end}. Demanded ${summary.demandedArtists} artist(s) + ${summary.demandedLabels} label(s) (${summary.unknownSlugs} unknown skipped); scored ${summary.tracksScored} track(s), promoted ${summary.frontierPromoted} frontier node(s).`);
|
|
9508
|
+
});
|
|
9470
9509
|
catalogue.command("list").description("The ranked catalogue: closest to a finding (ear), next to capture, or wrong audio").option("--lens <lens>", "ear (default), capture, quarantine, unmatched, failed, or dismissed", "ear").option("--limit <limit>", "Rows (default 50, max 200)").option("--json", "Print JSON", false).action(async (options) => {
|
|
9471
9510
|
const { catalogueListCommand: catalogueListCommand2 } = await Promise.resolve().then(() => (init_admin_catalogue(), exports_admin_catalogue));
|
|
9472
9511
|
await runCatalogueList(options, catalogueListCommand2);
|
|
@@ -9632,7 +9671,7 @@ function addAdminCommands(program2) {
|
|
|
9632
9671
|
const { backfillRecordingMbidsCommand: backfillRecordingMbidsCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
|
|
9633
9672
|
await runBackfillRecordingMbids(options, backfillRecordingMbidsCommand2);
|
|
9634
9673
|
});
|
|
9635
|
-
backfill.command("cover-masters").description("Resolve owned \u22641200\xB2 cover masters (album/artist) into R2").option("--kind <kind>", "Which entity to drain: album | artist", "album").option("--dry-run", "Report the eligible worklist without any fetch or write", false).option("--limit <limit>", "Max entities to process", "50").option("--json", "Print JSON", false).action(async (options) => {
|
|
9674
|
+
backfill.command("cover-masters").description("Resolve owned \u22641200\xB2 cover masters (album/artist) into R2").option("--kind <kind>", "Which entity to drain: album | artist", "album").option("--dry-run", "Report the eligible worklist without any fetch or write", false).option("--retry-none", "First re-queue a bounded batch of terminal none rows to pending, then run the pass", false).option("--limit <limit>", "Max entities to process", "50").option("--json", "Print JSON", false).action(async (options) => {
|
|
9636
9675
|
const { backfillCoverMastersCommand: backfillCoverMastersCommand2 } = await Promise.resolve().then(() => (init_admin_covers(), exports_admin_covers));
|
|
9637
9676
|
await runBackfillCoverMasters(options, backfillCoverMastersCommand2);
|
|
9638
9677
|
});
|
|
@@ -10396,17 +10435,20 @@ async function runBackfillArtistImages(options, backfillArtistImagesCommand2) {
|
|
|
10396
10435
|
async function runBackfillCoverMasters(options, backfillCoverMastersCommand2) {
|
|
10397
10436
|
const limit = parseListLimit(options.limit);
|
|
10398
10437
|
const kind = options.kind === "artist" ? "artist" : "album";
|
|
10438
|
+
const retryNone = options.retryNone ?? false;
|
|
10399
10439
|
const resolved = [];
|
|
10400
10440
|
const none = [];
|
|
10441
|
+
const requeued = [];
|
|
10401
10442
|
const failed = [];
|
|
10402
10443
|
let cursor;
|
|
10403
10444
|
let dryRun = options.dryRun;
|
|
10404
10445
|
while (resolved.length + none.length + failed.length < limit) {
|
|
10405
10446
|
const remaining = limit - (resolved.length + none.length + failed.length);
|
|
10406
|
-
const result = await backfillCoverMastersCommand2(kind, remaining, options.dryRun, cursor);
|
|
10447
|
+
const result = await backfillCoverMastersCommand2(kind, remaining, options.dryRun, cursor, retryNone && cursor === undefined);
|
|
10407
10448
|
dryRun = result.dryRun;
|
|
10408
10449
|
resolved.push(...result.resolved);
|
|
10409
10450
|
none.push(...result.none);
|
|
10451
|
+
requeued.push(...result.requeued ?? []);
|
|
10410
10452
|
failed.push(...result.failed);
|
|
10411
10453
|
if (!options.json) {
|
|
10412
10454
|
const verb2 = result.dryRun ? "would resolve" : "resolved";
|
|
@@ -10427,6 +10469,8 @@ async function runBackfillCoverMasters(options, backfillCoverMastersCommand2) {
|
|
|
10427
10469
|
noneCount: none.length,
|
|
10428
10470
|
ok: true,
|
|
10429
10471
|
rateLimited: false,
|
|
10472
|
+
requeued,
|
|
10473
|
+
requeuedCount: requeued.length,
|
|
10430
10474
|
resolved,
|
|
10431
10475
|
resolvedCount: resolved.length
|
|
10432
10476
|
});
|
|
@@ -10436,7 +10480,8 @@ async function runBackfillCoverMasters(options, backfillCoverMastersCommand2) {
|
|
|
10436
10480
|
return;
|
|
10437
10481
|
}
|
|
10438
10482
|
const verb = dryRun ? "Would resolve" : "Resolved";
|
|
10439
|
-
|
|
10483
|
+
const requeuedNote = retryNone ? ` (${dryRun ? "would re-queue" : "re-queued"} ${requeued.length} from none)` : "";
|
|
10484
|
+
console.log(`${verb} ${resolved.length} ${kind} cover master(s); ${none.length} without a source; ${failed.length} failed${requeuedNote}.`);
|
|
10440
10485
|
for (const slug of resolved) {
|
|
10441
10486
|
console.log(` ${slug}`);
|
|
10442
10487
|
}
|
package/package.json
CHANGED