fluncle 0.113.0 → 0.114.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 +44 -2
  2. package/package.json +1 -1
package/bin/fluncle.mjs CHANGED
@@ -557,7 +557,7 @@ function parseVersion(version) {
557
557
  var currentVersion;
558
558
  var init_version = __esm(() => {
559
559
  init_output();
560
- currentVersion = "0.113.0".trim() ? "0.113.0".trim() : "0.1.0";
560
+ currentVersion = "0.114.0".trim() ? "0.114.0".trim() : "0.1.0";
561
561
  });
562
562
 
563
563
  // src/update-notifier.ts
@@ -2209,7 +2209,7 @@ function parseVersion2(version) {
2209
2209
  var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
2210
2210
  var init_version2 = __esm(() => {
2211
2211
  init_output();
2212
- currentVersion2 = "0.113.0".trim() ? "0.113.0".trim() : "0.1.0";
2212
+ currentVersion2 = "0.114.0".trim() ? "0.114.0".trim() : "0.1.0";
2213
2213
  });
2214
2214
 
2215
2215
  // ../../packages/registry/src/index.ts
@@ -2265,6 +2265,18 @@ var init_src = __esm(() => {
2265
2265
  url: `${SITE}/mixtapes`,
2266
2266
  weights: { ssh: "secondary", web: "primary" }
2267
2267
  },
2268
+ {
2269
+ exposedContent: [
2270
+ "the mixability set-builder — chain a set from Fluncle's findings that mixes clean, share it as a link"
2271
+ ],
2272
+ kind: "web_route",
2273
+ name: "web.mix",
2274
+ operatorNotes: "ADMIN-GATED at launch (RFC mixability-engine, Decision 1): the full /mix set-builder ships behind admin auth until the archive clears the ~250-finding floor. Registered here as `pending` (dark to every public consumer — the dev-row, llms.txt, the sitemap, /status) so going public is one flip: remove `pending` + set a web weight + announce. The `list_mixable_tracks` API op already ships at its final public tier, so the flip needs no rebuild. No probeConfig — the admin gate 302s a bare GET to /admin/login, which would read as a false 'down'.",
2275
+ pending: true,
2276
+ route: "/mix",
2277
+ url: `${SITE}/mix`,
2278
+ weights: { web: "secondary" }
2279
+ },
2268
2280
  {
2269
2281
  exposedContent: [
2270
2282
  "the feed-first Stories surface — full-bleed findings",
@@ -3486,6 +3498,7 @@ __export(exports_admin_tracks, {
3486
3498
  queueCommand: () => queueCommand,
3487
3499
  observeQueueCommand: () => observeQueueCommand,
3488
3500
  noteQueueCommand: () => noteQueueCommand,
3501
+ mixableOrderCommand: () => mixableOrderCommand,
3489
3502
  listCommand: () => listCommand,
3490
3503
  enrichQueueCommand: () => enrichQueueCommand,
3491
3504
  embedQueueCommand: () => embedQueueCommand,
@@ -3665,6 +3678,13 @@ async function vehiclesCommand(limit) {
3665
3678
  vehicle: track.videoVehicle
3666
3679
  }));
3667
3680
  }
3681
+ async function mixableOrderCommand(logIds, seed) {
3682
+ const params = new URLSearchParams({ ids: logIds.join(",") });
3683
+ if (seed) {
3684
+ params.set("seed", seed);
3685
+ }
3686
+ return adminApiGet(`/api/admin/tracks/mixable-order?${params.toString()}`);
3687
+ }
3668
3688
  var pageSize3 = 48;
3669
3689
  var init_admin_tracks = __esm(() => {
3670
3690
  init_api();
@@ -7877,6 +7897,10 @@ function addAdminCommands(program2) {
7877
7897
  const { trackGetAdminCommand: trackGetAdminCommand2 } = await Promise.resolve().then(() => (init_track(), exports_track));
7878
7898
  await runTrackGetAdmin(idOrLogId, options, trackGetAdminCommand2);
7879
7899
  });
7900
+ adminTrack.command("mixable-order").description("Order findings into a smooth proposed mix (2\u201364 Log IDs)").argument("[logIds...]", "The findings to order, by Log ID").option("--seed <logId>", "Pin the first stop").option("--json", "Print JSON", false).allowExcessArguments().action(async (logIds, options) => {
7901
+ const { mixableOrderCommand: mixableOrderCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
7902
+ await runMixableOrder(logIds, options, mixableOrderCommand2);
7903
+ });
7880
7904
  adminTrack.command("update").description("Certify a track into the archive").argument("[trackId]").option("--analyzed-at <iso>", "Analysis-write ISO timestamp (BPM/key provenance)").option("--analyzed-from <class>", "Audio class BPM/key were analyzed from: full or preview").option("--bpm <number>", "Track BPM").option("--bpm-confidence <number>", "Analyzer confidence in the BPM (0..1)").option("--bpm-source <source>", "Where the BPM came from (analyzer bpmSource)").option("--embedding <json>", "MuQ audio embedding as a JSON array of 1024 floats").option("--embedding-file <file>", "Read the MuQ embedding JSON array from a file").option("--features <json>", "Audio feature JSON").option("--json", "Print JSON", false).option("--key <key>", "Musical key").option("--key-confidence <number>", "Analyzer confidence in the key (0..1)").option("--key-source <source>", "Where the key came from (analyzer keySource)").option("--note <text>", "Operator note").option("--status <status>", "Enrichment status").option("--video-url <url>", "Rendered video URL").allowExcessArguments().action(async (trackId, options) => {
7881
7905
  const { trackUpdateCommand: trackUpdateCommand3 } = await Promise.resolve().then(() => (init_track(), exports_track));
7882
7906
  await runTrackUpdate(trackId, options, trackUpdateCommand3);
@@ -8684,6 +8708,24 @@ async function runTrackGet(idOrLogId, options, trackGetCommand2) {
8684
8708
  console.log(`Log: ${t.logPageUrl}`);
8685
8709
  }
8686
8710
  }
8711
+ async function runMixableOrder(logIds, options, mixableOrderCommand2) {
8712
+ if (logIds.length < 2) {
8713
+ throw new Error("Give 2 or more Log IDs. Usage: fluncle admin tracks mixable-order <logId...> [--seed <logId>] [--json]");
8714
+ }
8715
+ const result = await mixableOrderCommand2(logIds, options.seed);
8716
+ if (options.json) {
8717
+ printJson(result);
8718
+ return;
8719
+ }
8720
+ console.log(`Proposed mix \u2014 a smooth chain (${result.algorithm}), not an energy-shaped set. Copy into Rekordbox as advisory.
8721
+ `);
8722
+ result.order.forEach((stop, index) => {
8723
+ const into = index === 0 ? "start" : stop.flagged ? "sparse join" : stop.transitionReason?.relationship.replace(/_/g, " ") ?? "\u2014";
8724
+ const meta = [stop.key, stop.bpm ? `${Math.round(stop.bpm)} bpm` : undefined].filter(Boolean).join(" \xB7 ");
8725
+ console.log(`${String(index + 1).padStart(2)}. ${stop.logId} ${stop.artists.join(", ")} \u2014 ${stop.title}`);
8726
+ console.log(` ${[into, meta].filter(Boolean).join(" \xB7 ")}`);
8727
+ });
8728
+ }
8687
8729
  async function runTrackGetAdmin(idOrLogId, options, trackGetAdminCommand2) {
8688
8730
  if (!idOrLogId) {
8689
8731
  throw new Error("Missing id. Usage: fluncle admin tracks get <track_id|log_id> [--json]");
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.113.0"
34
+ "version": "0.114.0"
35
35
  }