fluncle 0.157.0 → 0.159.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 +104 -5
- 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.159.0".trim() ? "0.159.0".trim() : "0.1.0";
|
|
565
565
|
});
|
|
566
566
|
|
|
567
567
|
// src/update-notifier.ts
|
|
@@ -2189,7 +2189,7 @@ function parseVersion2(version) {
|
|
|
2189
2189
|
var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
|
|
2190
2190
|
var init_version2 = __esm(() => {
|
|
2191
2191
|
init_output();
|
|
2192
|
-
currentVersion2 = "0.
|
|
2192
|
+
currentVersion2 = "0.159.0".trim() ? "0.159.0".trim() : "0.1.0";
|
|
2193
2193
|
});
|
|
2194
2194
|
|
|
2195
2195
|
// ../../packages/registry/src/index.ts
|
|
@@ -2349,11 +2349,11 @@ var init_src = __esm(() => {
|
|
|
2349
2349
|
{
|
|
2350
2350
|
discoveryUrl: `${SITE}/llms.txt`,
|
|
2351
2351
|
exposedContent: [
|
|
2352
|
-
"/artist/:slug — one artist's page:
|
|
2352
|
+
"/artist/:slug — one artist's page: its findings, its identity links, and the rest of its catalogue"
|
|
2353
2353
|
],
|
|
2354
2354
|
kind: "web_route",
|
|
2355
2355
|
name: "web.artist",
|
|
2356
|
-
operatorNotes: "Slug is real-name kebab-case (e.g. /artist/dbridge). Read-only;
|
|
2356
|
+
operatorNotes: "Slug is real-name kebab-case (e.g. /artist/dbridge). Read-only; an artist earns a page on its CONTENT exactly as a label/album does — a row renders (a findings-free discovered artist included), a slug with no row 404s, and a page below the thin-content floor renders noindex + stays out of the sitemap (the ARTIST_INDEX_MIN_FINDINGS precedent). No probeConfig — the route is slug-parameterized, so there is no fixed URL to GET-probe.",
|
|
2357
2357
|
route: "/artist",
|
|
2358
2358
|
url: `${SITE}/artist`,
|
|
2359
2359
|
weights: { ssh: "secondary", web: "secondary" }
|
|
@@ -2380,7 +2380,7 @@ var init_src = __esm(() => {
|
|
|
2380
2380
|
],
|
|
2381
2381
|
kind: "web_route",
|
|
2382
2382
|
name: "web.albums",
|
|
2383
|
-
operatorNotes: "The album half of the graph, and the node that closes it: the album page carries the album → label edge (a link, plus `albumRelease.recordLabel` in its MusicAlbum JSON-LD). The INDEX is probeable (always 200); the slug page is not.
|
|
2383
|
+
operatorNotes: "The album half of the graph, and the node that closes it: the album page carries the album → label edge (a link, plus `albumRelease.recordLabel` in its MusicAlbum JSON-LD). The INDEX is probeable (always 200); the slug page is not. The `/albums` index stays archive-bounded (findings-joined), but a crawl-minted findings-free album is PUBLIC on its content — a row renders its page, a below-floor page renders noindex + stays out of the sitemap, like a discovered label (docs/album-entity.md).",
|
|
2384
2384
|
probeConfig: { cadenceMs: PROBE_CADENCE_MS, kind: "http", timeoutMs: PROBE_TIMEOUT_MS },
|
|
2385
2385
|
route: "/albums",
|
|
2386
2386
|
url: `${SITE}/albums`,
|
|
@@ -2969,6 +2969,23 @@ var init_src = __esm(() => {
|
|
|
2969
2969
|
title: "Track ranking",
|
|
2970
2970
|
weights: { status: "hidden" }
|
|
2971
2971
|
},
|
|
2972
|
+
{
|
|
2973
|
+
command: "fluncle admin frontier refresh",
|
|
2974
|
+
exposedContent: [
|
|
2975
|
+
"re-mirror every crew member's Fluncle's Frontier playlist from their current recommendations"
|
|
2976
|
+
],
|
|
2977
|
+
kind: "cron",
|
|
2978
|
+
name: "cron.frontier-refresh",
|
|
2979
|
+
operatorNotes: "weekly (Fri 07:00 Amsterdam), run by a rave-02 HOST systemd timer (docs/agents/hermes/frontier-refresh-timer/). E2, the public recommendation machine: every verified user can mint ONE public 'Fluncle's Frontier' playlist on Fluncle's OWN Spotify account (no per-user OAuth), holding THEIR recommendations (the E1 blend); this cron is the Discover-Weekly-style refresh that keeps each one current. The walk + the Spotify item replaces all happen inside the Worker; the sweep just fires one `fluncle admin frontier refresh`. It respects the DEFAULT-DENY `frontier.minting` kill switch (a closed switch touches nothing), skips playlists whose recommendation set is unchanged (a per-row URI-hash mirror guard), and creates no new public authority — every playlist it touches already exists, minted by its own owner. `refresh_frontier_playlists` is AGENT tier, so the box's existing agent-scoped token drives it: NO new secret. Zero LLM tokens. Source: docs/agents/hermes/scripts/frontier-refresh-sweep.*. See docs/the-ear.md § Fluncle's Frontier.",
|
|
2980
|
+
probeConfig: {
|
|
2981
|
+
cadenceMs: 7 * 24 * 60 * MINUTE_MS,
|
|
2982
|
+
cronName: "fluncle-frontier-refresh",
|
|
2983
|
+
kind: "cron"
|
|
2984
|
+
},
|
|
2985
|
+
statusDescription: "refreshes every crew member's Frontier playlist",
|
|
2986
|
+
title: "Frontier refresh",
|
|
2987
|
+
weights: { status: "hidden" }
|
|
2988
|
+
},
|
|
2972
2989
|
{
|
|
2973
2990
|
command: "fluncle admin backfills label-images",
|
|
2974
2991
|
exposedContent: [
|
|
@@ -3073,6 +3090,19 @@ var init_src = __esm(() => {
|
|
|
3073
3090
|
title: "Label bios",
|
|
3074
3091
|
weights: { status: "hidden" }
|
|
3075
3092
|
},
|
|
3093
|
+
{
|
|
3094
|
+
command: "fluncle admin albums describe --queue",
|
|
3095
|
+
exposedContent: [
|
|
3096
|
+
"auto-author the /album/<slug> voiced bio, fill-empty-only (hybrid: one claude -p call)"
|
|
3097
|
+
],
|
|
3098
|
+
kind: "cron",
|
|
3099
|
+
name: "cron.album-bio",
|
|
3100
|
+
operatorNotes: "every 30m. Hybrid --no-agent; one claude -p authors the paragraph, its grounding assembled WORKER-side (Firecrawl facts + the album's finding titles) via the draft-bio op. Never clobbers an operator bio. Live. Source: docs/agents/hermes/scripts/{entity-bio-sweep.ts,album-bio-sweep.sh}.",
|
|
3101
|
+
probeConfig: { cadenceMs: 30 * MINUTE_MS, cronName: "fluncle-album-bio", kind: "cron" },
|
|
3102
|
+
statusDescription: "writes each album's voiced bio",
|
|
3103
|
+
title: "Album bios",
|
|
3104
|
+
weights: { status: "hidden" }
|
|
3105
|
+
},
|
|
3076
3106
|
{
|
|
3077
3107
|
command: "fluncle admin submissions triage",
|
|
3078
3108
|
exposedContent: [
|
|
@@ -5871,6 +5901,19 @@ var init_admin_observations = __esm(() => {
|
|
|
5871
5901
|
init_api();
|
|
5872
5902
|
});
|
|
5873
5903
|
|
|
5904
|
+
// src/commands/admin-frontier.ts
|
|
5905
|
+
var exports_admin_frontier = {};
|
|
5906
|
+
__export(exports_admin_frontier, {
|
|
5907
|
+
frontierRefreshCommand: () => frontierRefreshCommand
|
|
5908
|
+
});
|
|
5909
|
+
async function frontierRefreshCommand(options) {
|
|
5910
|
+
const limit = options.limit ? Number.parseInt(options.limit, 10) : undefined;
|
|
5911
|
+
return adminApiPost("/api/admin/frontier-playlists/refresh", limit ? { limit } : {});
|
|
5912
|
+
}
|
|
5913
|
+
var init_admin_frontier = __esm(() => {
|
|
5914
|
+
init_api();
|
|
5915
|
+
});
|
|
5916
|
+
|
|
5874
5917
|
// src/commands/admin-catalogue.ts
|
|
5875
5918
|
var exports_admin_catalogue = {};
|
|
5876
5919
|
__export(exports_admin_catalogue, {
|
|
@@ -6092,6 +6135,28 @@ var init_admin_covers = __esm(() => {
|
|
|
6092
6135
|
init_api();
|
|
6093
6136
|
});
|
|
6094
6137
|
|
|
6138
|
+
// src/commands/admin-albums.ts
|
|
6139
|
+
var exports_admin_albums = {};
|
|
6140
|
+
__export(exports_admin_albums, {
|
|
6141
|
+
draftAlbumBioCommand: () => draftAlbumBioCommand,
|
|
6142
|
+
describeAlbumCommand: () => describeAlbumCommand,
|
|
6143
|
+
albumsBioQueueCommand: () => albumsBioQueueCommand
|
|
6144
|
+
});
|
|
6145
|
+
async function describeAlbumCommand(slug, options) {
|
|
6146
|
+
return adminApiPost(`/api/admin/albums/${encodeURIComponent(slug)}/bio`, buildBioBody2(options));
|
|
6147
|
+
}
|
|
6148
|
+
async function draftAlbumBioCommand(slug) {
|
|
6149
|
+
return adminApiGet(`/api/admin/albums/${encodeURIComponent(slug)}/bio-draft`);
|
|
6150
|
+
}
|
|
6151
|
+
async function albumsBioQueueCommand(limit) {
|
|
6152
|
+
const response = await adminApiGet(`/api/admin/albums/bio-queue?limit=${limit}`);
|
|
6153
|
+
return response.albums;
|
|
6154
|
+
}
|
|
6155
|
+
var init_admin_albums = __esm(() => {
|
|
6156
|
+
init_api();
|
|
6157
|
+
init_admin_artists2();
|
|
6158
|
+
});
|
|
6159
|
+
|
|
6095
6160
|
// src/commands/preview-migration.ts
|
|
6096
6161
|
var exports_preview_migration = {};
|
|
6097
6162
|
__export(exports_preview_migration, {
|
|
@@ -9076,6 +9141,23 @@ function addAdminCommands(program2) {
|
|
|
9076
9141
|
const { observationGateCommand: observationGateCommand2 } = await Promise.resolve().then(() => (init_admin_observations(), exports_admin_observations));
|
|
9077
9142
|
await runObservationGate(options, observationGateCommand2);
|
|
9078
9143
|
});
|
|
9144
|
+
const frontier = configureCommand(admin.command("frontier").description("The Frontier playlists (per-user recommendations)"));
|
|
9145
|
+
frontier.action(() => {
|
|
9146
|
+
frontier.outputHelp();
|
|
9147
|
+
});
|
|
9148
|
+
frontier.command("refresh").description("Re-mirror every crew member's Frontier playlist from their recommendations").option("--limit <limit>", "Playlists per tick (default 500)").option("--json", "Print JSON", false).action(async (options) => {
|
|
9149
|
+
const { frontierRefreshCommand: frontierRefreshCommand2 } = await Promise.resolve().then(() => (init_admin_frontier(), exports_admin_frontier));
|
|
9150
|
+
const summary = await frontierRefreshCommand2(options);
|
|
9151
|
+
if (options.json) {
|
|
9152
|
+
printJson(summary);
|
|
9153
|
+
return;
|
|
9154
|
+
}
|
|
9155
|
+
if (summary.switchOff) {
|
|
9156
|
+
console.log("Frontier minting is paused (the kill switch is closed). Nothing refreshed.");
|
|
9157
|
+
return;
|
|
9158
|
+
}
|
|
9159
|
+
console.log(`Walked ${summary.total} playlist(s): ${summary.refreshed} refreshed, ${summary.unchanged} unchanged, ${summary.minted} minted, ${summary.skipped} skipped, ${summary.failed} failed.`);
|
|
9160
|
+
});
|
|
9079
9161
|
const catalogue = configureCommand(admin.command("catalogue").description("The catalogue (uncertified tracks): the crawler + its ranking"));
|
|
9080
9162
|
catalogue.action(() => {
|
|
9081
9163
|
catalogue.outputHelp();
|
|
@@ -9284,6 +9366,23 @@ function addAdminCommands(program2) {
|
|
|
9284
9366
|
const { draftLabelBioCommand: draftLabelBioCommand2 } = await Promise.resolve().then(() => (init_admin_labels(), exports_admin_labels));
|
|
9285
9367
|
await runEntityBioDraft("label", slug, options, draftLabelBioCommand2);
|
|
9286
9368
|
});
|
|
9369
|
+
const albums = configureCommand(admin.command("albums").description("Album entity commands (the voiced bio)"));
|
|
9370
|
+
albums.action(() => {
|
|
9371
|
+
albums.outputHelp();
|
|
9372
|
+
});
|
|
9373
|
+
albums.command("describe").description("Author the voiced bio for an album (fills an empty bio only)").argument("[slug]").option("--queue", "Show the bio worklist (albums with findings but no bio), oldest first", false).option("--limit <limit>", "Number of albums to show with --queue", "50").option("--bio <text>", "The voice-gated bio paragraph").option("--bio-file <file>", "Read the bio from a file").option("--prompt-version <n>", "The prompt-registry version that authored the bio (the sweep sends this; it is the bio's provenance)").option("--dry-run", "Run the voice gate and report the verdict without storing anything", false).option("--json", "Print JSON", false).allowExcessArguments().action(async (slug, options) => {
|
|
9374
|
+
if (options.queue) {
|
|
9375
|
+
const { albumsBioQueueCommand: albumsBioQueueCommand2 } = await Promise.resolve().then(() => (init_admin_albums(), exports_admin_albums));
|
|
9376
|
+
await runEntityBioQueue("album", options, albumsBioQueueCommand2);
|
|
9377
|
+
return;
|
|
9378
|
+
}
|
|
9379
|
+
const { describeAlbumCommand: describeAlbumCommand2 } = await Promise.resolve().then(() => (init_admin_albums(), exports_admin_albums));
|
|
9380
|
+
await runEntityDescribe("album", slug, options, describeAlbumCommand2);
|
|
9381
|
+
});
|
|
9382
|
+
albums.command("draft-bio").description("Assemble the Worker-grounded bio prompt for an album (the sweep's trigger)").argument("<slug>").option("--json", "Print JSON", false).allowExcessArguments().action(async (slug, options) => {
|
|
9383
|
+
const { draftAlbumBioCommand: draftAlbumBioCommand2 } = await Promise.resolve().then(() => (init_admin_albums(), exports_admin_albums));
|
|
9384
|
+
await runEntityBioDraft("album", slug, options, draftAlbumBioCommand2);
|
|
9385
|
+
});
|
|
9287
9386
|
const migrations = configureCommand(admin.command("migrations").description("One-off operator data migrations"));
|
|
9288
9387
|
migrations.action(() => {
|
|
9289
9388
|
migrations.outputHelp();
|
package/package.json
CHANGED