fluncle 0.128.0 → 0.129.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 +107 -2
  2. 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.128.0".trim() ? "0.128.0".trim() : "0.1.0";
564
+ currentVersion = "0.129.0".trim() ? "0.129.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.128.0".trim() ? "0.128.0".trim() : "0.1.0";
2192
+ currentVersion2 = "0.129.0".trim() ? "0.129.0".trim() : "0.1.0";
2193
2193
  });
2194
2194
 
2195
2195
  // ../../packages/registry/src/index.ts
@@ -2346,6 +2346,34 @@ var init_src = __esm(() => {
2346
2346
  url: `${SITE}/artist`,
2347
2347
  weights: { ssh: "secondary", web: "secondary" }
2348
2348
  },
2349
+ {
2350
+ discoveryUrl: `${SITE}/llms.txt`,
2351
+ exposedContent: [
2352
+ "/labels — every record label Fluncle has found a banger on",
2353
+ "/label/:slug — one label: its findings, the artists on it, and the rest of its catalogue"
2354
+ ],
2355
+ kind: "web_route",
2356
+ name: "web.labels",
2357
+ operatorNotes: "The label half of the graph (log ↔ artist ↔ label ↔ album). The INDEX is probeable (always 200); the slug page is not, so the probe targets /labels. A label below the renderable-track floor renders noindex + stays out of the sitemap (the ARTIST_INDEX_MIN_FINDINGS precedent). The page is BLIND to the label's crawl seed_state — that is crawl scope, never storage (docs/label-entity.md); the operator's ruling station is /admin/labels.",
2358
+ probeConfig: { cadenceMs: PROBE_CADENCE_MS, kind: "http", timeoutMs: PROBE_TIMEOUT_MS },
2359
+ route: "/labels",
2360
+ url: `${SITE}/labels`,
2361
+ weights: { web: "secondary" }
2362
+ },
2363
+ {
2364
+ discoveryUrl: `${SITE}/llms.txt`,
2365
+ exposedContent: [
2366
+ "/albums — every record Fluncle has found a banger on",
2367
+ "/album/:slug — one record: its findings, its artists, its label, and the rest of its tracklist"
2368
+ ],
2369
+ kind: "web_route",
2370
+ name: "web.albums",
2371
+ 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. Bounded by the archive, not the catalogue — an album earns a page by carrying a finding (docs/album-entity.md).",
2372
+ probeConfig: { cadenceMs: PROBE_CADENCE_MS, kind: "http", timeoutMs: PROBE_TIMEOUT_MS },
2373
+ route: "/albums",
2374
+ url: `${SITE}/albums`,
2375
+ weights: { web: "secondary" }
2376
+ },
2349
2377
  {
2350
2378
  exposedContent: [
2351
2379
  "/galaxies — the browse-by-feel lens: the archive grouped into operator-named sonic galaxies (k-means over the MuQ audio embedding space)",
@@ -2982,6 +3010,17 @@ var init_src = __esm(() => {
2982
3010
  probeConfig: { cadenceMs: 20 * MINUTE_MS, cronName: "fluncle-clip-drip", kind: "cron" },
2983
3011
  weights: { status: "hidden" }
2984
3012
  },
3013
+ {
3014
+ command: "fluncle admin publish pause",
3015
+ exposedContent: [
3016
+ "advance one freshly-rendered finding into the publish push — YouTube Short + TikTok inbox draft (--no-agent, Worker HTTP)"
3017
+ ],
3018
+ kind: "cron",
3019
+ name: "cron.publish-advance",
3020
+ operatorNotes: "every 30m. Pure HTTP trigger, zero LLM tokens. The last autonomy gap: render finishes → this pushes, with no operator beat between. Admin tier (needs the Worker's Postiz key, which the box never sees — the box only triggers; the `drip_clips` / `capture_post_urls` precedent). SHIPS DARK: the Worker's kill switch is DEFAULT-DENY (only an explicit `false` in the `publish_advance_paused` setting runs it), so the timer ticks and posts nothing until `fluncle admin publish resume`. The Worker reads the switch FIRST, then advances at most ONE ready finding — both masters finalized, 15m settled, the whole bundle served on R2, the (track, platform) row CLAIMED atomically before any Postiz call, a rolling-24h cap of 6 pushes. A failed push is left `failed` for the operator and never auto-retried. Source: docs/agents/hermes/scripts/publish-advance-sweep.sh. Probed on /status as cron.publish-advance.",
3021
+ probeConfig: { cadenceMs: 30 * MINUTE_MS, cronName: "fluncle-publish-advance", kind: "cron" },
3022
+ weights: { status: "hidden" }
3023
+ },
2985
3024
  {
2986
3025
  command: "fluncle admin tracks queue",
2987
3026
  exposedContent: [
@@ -4097,6 +4136,23 @@ var init_mixtape_youtube2 = __esm(() => {
4097
4136
  init_output();
4098
4137
  });
4099
4138
 
4139
+ // src/commands/publish.ts
4140
+ var exports_publish = {};
4141
+ __export(exports_publish, {
4142
+ publishAdvancePauseCommand: () => publishAdvancePauseCommand,
4143
+ publishAdvanceCommand: () => publishAdvanceCommand
4144
+ });
4145
+ async function publishAdvanceCommand() {
4146
+ return adminApiPost("/api/admin/social/publish/advance", {});
4147
+ }
4148
+ async function publishAdvancePauseCommand(paused) {
4149
+ const response = await adminApiPut("/api/admin/social/publish/advance/state", { paused });
4150
+ return response.paused;
4151
+ }
4152
+ var init_publish = __esm(() => {
4153
+ init_api();
4154
+ });
4155
+
4100
4156
  // ../../packages/contracts/src/util/multipart.ts
4101
4157
  function planMultipart(contentLength, partSize = DEFAULT_PART_SIZE) {
4102
4158
  if (!Number.isInteger(contentLength) || contentLength <= 0) {
@@ -8065,6 +8121,22 @@ function addAdminCommands(program2) {
8065
8121
  const { mixtapeResyncCommand: mixtapeResyncCommand2 } = await Promise.resolve().then(() => (init_mixtapes(), exports_mixtapes));
8066
8122
  await runMixtapeResync(idOrLogId, options, mixtapeResyncCommand2);
8067
8123
  });
8124
+ const adminPublish = configureCommand(admin.command("publish").description("Render \u2192 publish auto-advance commands"));
8125
+ adminPublish.action(() => {
8126
+ adminPublish.outputHelp();
8127
+ });
8128
+ adminPublish.command("advance").description("Run one tick of the render \u2192 publish auto-advance (kill-switch aware)").option("--json", "Print JSON", false).allowExcessArguments().action(async (options) => {
8129
+ const { publishAdvanceCommand: publishAdvanceCommand2 } = await Promise.resolve().then(() => (init_publish(), exports_publish));
8130
+ await runPublishAdvance(options, publishAdvanceCommand2);
8131
+ });
8132
+ adminPublish.command("pause").description("Pause the render \u2192 publish auto-advance, the kill switch (operator)").option("--json", "Print JSON", false).allowExcessArguments().action(async (options) => {
8133
+ const { publishAdvancePauseCommand: publishAdvancePauseCommand2 } = await Promise.resolve().then(() => (init_publish(), exports_publish));
8134
+ await runPublishAdvancePause(true, options, publishAdvancePauseCommand2);
8135
+ });
8136
+ adminPublish.command("resume").description("Resume the render \u2192 publish auto-advance, clear the kill switch (operator)").option("--json", "Print JSON", false).allowExcessArguments().action(async (options) => {
8137
+ const { publishAdvancePauseCommand: publishAdvancePauseCommand2 } = await Promise.resolve().then(() => (init_publish(), exports_publish));
8138
+ await runPublishAdvancePause(false, options, publishAdvancePauseCommand2);
8139
+ });
8068
8140
  const adminClips = configureCommand(admin.command("clips").description("Mixtape clip (Fluncle Studio) commands"));
8069
8141
  adminClips.action(() => {
8070
8142
  adminClips.outputHelp();
@@ -9116,6 +9188,39 @@ async function runClipsDripPause(paused, options, clipDripPauseCommand2) {
9116
9188
  }
9117
9189
  console.log(result ? "The drip-feed is paused." : "The drip-feed is running.");
9118
9190
  }
9191
+ async function runPublishAdvance(options, publishAdvanceCommand2) {
9192
+ const result = await publishAdvanceCommand2();
9193
+ if (options.json) {
9194
+ printJson(result);
9195
+ return;
9196
+ }
9197
+ if (result.paused) {
9198
+ console.log("Auto-advance is paused \u2014 nothing pushed.");
9199
+ return;
9200
+ }
9201
+ if (result.pushed.length === 0 && result.held.length === 0 && result.failed.length === 0) {
9202
+ console.log("Nothing ready to advance.");
9203
+ return;
9204
+ }
9205
+ for (const push of result.pushed) {
9206
+ console.log(`Pushed ${push.logId} to ${push.platform} (${push.status}).`);
9207
+ }
9208
+ for (const held of result.held) {
9209
+ const detail = held.missing?.length ? ` (${held.missing.join(", ")})` : "";
9210
+ console.log(`Held ${held.platform} for ${held.trackId}: ${held.reason}${detail}.`);
9211
+ }
9212
+ for (const failure of result.failed) {
9213
+ console.log(`Failed ${failure.platform} for ${failure.trackId} \u2014 left for the operator.`);
9214
+ }
9215
+ }
9216
+ async function runPublishAdvancePause(paused, options, publishAdvancePauseCommand2) {
9217
+ const result = await publishAdvancePauseCommand2(paused);
9218
+ if (options.json) {
9219
+ printJson({ ok: true, paused: result });
9220
+ return;
9221
+ }
9222
+ console.log(result ? "The publish auto-advance is paused." : "The publish auto-advance is running.");
9223
+ }
9119
9224
  async function runMixtapeGet(idOrLogId, options, mixtapeGetCommand2) {
9120
9225
  if (!idOrLogId) {
9121
9226
  throw new Error("Missing mixtape id or log id. Usage: fluncle admin mixtapes get <id|logId>");
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.128.0"
34
+ "version": "0.129.0"
35
35
  }