fluncle 0.148.0 → 0.150.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 +45 -8
  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.148.0".trim() ? "0.148.0".trim() : "0.1.0";
564
+ currentVersion = "0.150.0".trim() ? "0.150.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.148.0".trim() ? "0.148.0".trim() : "0.1.0";
2192
+ currentVersion2 = "0.150.0".trim() ? "0.150.0".trim() : "0.1.0";
2193
2193
  });
2194
2194
 
2195
2195
  // ../../packages/registry/src/index.ts
@@ -2312,6 +2312,18 @@ var init_src = __esm(() => {
2312
2312
  url: `${SITE}/status`,
2313
2313
  weights: { status: "primary", web: "secondary" }
2314
2314
  },
2315
+ {
2316
+ exposedContent: [
2317
+ "the public reach page — Fluncle's numbers across every platform over time (the crew aboard + how far the findings reached), grouped as audience/reach, no KPI hero"
2318
+ ],
2319
+ kind: "web_route",
2320
+ name: "web.reach",
2321
+ operatorNotes: "Reads the append-only platform_stats ledger via the public list_platform_stats op (a record_health noun-swap). Every number is already public on its own platform, so the read is anonymous. Loader-only, no react-query. The grouping taxonomy + per-platform display labels live in the PAGE, never the server (the rows stay raw).",
2322
+ probeConfig: { cadenceMs: PROBE_CADENCE_MS, kind: "http", timeoutMs: PROBE_TIMEOUT_MS },
2323
+ route: "/reach",
2324
+ url: `${SITE}/reach`,
2325
+ weights: { status: "secondary", web: "secondary" }
2326
+ },
2315
2327
  {
2316
2328
  exposedContent: ["the Galaxy game — the 8-bit fly-to-every-banger arcade front door"],
2317
2329
  kind: "web_route",
@@ -3165,6 +3177,22 @@ var init_src = __esm(() => {
3165
3177
  },
3166
3178
  weights: { status: "secondary" }
3167
3179
  },
3180
+ {
3181
+ command: "fluncle admin reach collect",
3182
+ exposedContent: [
3183
+ "daily snapshot of Fluncle's numbers across every platform (followers / subscribers / plays / stars) → one append-only row per (platform, metric) behind the public /reach page (--no-agent)"
3184
+ ],
3185
+ kind: "cron",
3186
+ name: "cron.reach",
3187
+ operatorNotes: "04:00 Amsterdam daily. A bare trigger (the catalogue-rank shape): fires the AGENT-tier record_platform_stats op once — the Worker fetches every Tier-1 platform best-effort and upserts one idempotent row per (platform, metric) keyed ${platform}:${metric}:${yyyy-mm-dd} (a same-day re-run lands inserted:0). Zero LLM tokens; the box's agent token drives it and every platform credential lives Worker-side (no new secret). Source: docs/agents/hermes/scripts/reach-sweep.*",
3188
+ probeConfig: {
3189
+ cadenceMs: 24 * 60 * MINUTE_MS,
3190
+ cronName: "fluncle-reach",
3191
+ kind: "cron",
3192
+ schedule: { time: "04:00", tz: "Europe/Amsterdam" }
3193
+ },
3194
+ weights: { status: "secondary" }
3195
+ },
3168
3196
  {
3169
3197
  exposedContent: [
3170
3198
  "nightly codebase audit — one domain/night on a 7-day rotation; opens a PR the reviewer merges (claude -p, subscription auth)"
@@ -3346,14 +3374,17 @@ async function trackVideoCommand(idOrLogId, files, onProgress, options = {}) {
3346
3374
  const presign = await adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/video/uploads`, { fields: present.map((spec) => spec.field) });
3347
3375
  const byField = new Map(presign.uploads.map((upload) => [upload.field, upload]));
3348
3376
  const urls = {};
3377
+ const STREAM_THRESHOLD_BYTES = 8 * 1024 * 1024;
3349
3378
  for (const spec of present) {
3350
3379
  const upload = byField.get(spec.field);
3351
3380
  if (!upload) {
3352
3381
  throw new CliError2("presign_missing", `Worker did not sign an upload for ${spec.field}`);
3353
3382
  }
3354
3383
  onProgress?.(`Uploading ${spec.field} → ${upload.key}`);
3384
+ const file = Bun.file(spec.path);
3385
+ const body = file.size > STREAM_THRESHOLD_BYTES ? file : await file.arrayBuffer();
3355
3386
  const response = await fetch(upload.url, {
3356
- body: Bun.file(spec.path),
3387
+ body,
3357
3388
  headers: { "Content-Type": upload.contentType },
3358
3389
  method: "PUT"
3359
3390
  });
@@ -3382,18 +3413,23 @@ async function trackVideoCommand(idOrLogId, files, onProgress, options = {}) {
3382
3413
  return { logId: finalize.logId, ok: true, trackId: finalize.trackId, urls };
3383
3414
  }
3384
3415
  async function readManifestFields(renderPath) {
3416
+ let result = {};
3385
3417
  try {
3386
3418
  const manifest = await Bun.file(renderPath).json();
3387
- const result = {};
3419
+ const parsed = {};
3388
3420
  for (const key of ["vehicle", "grain", "model", "reasoning", "register"]) {
3389
3421
  const value = manifest[key];
3390
3422
  if (typeof value === "string" && value.trim()) {
3391
- result[key] = value.trim().slice(0, 120);
3423
+ parsed[key] = value.trim().slice(0, 120);
3392
3424
  }
3393
3425
  }
3394
- return result;
3426
+ result = parsed;
3395
3427
  } catch {}
3396
- return {};
3428
+ const missing = DIVERSITY_LEDGER_FIELDS.filter((key) => !result[key]);
3429
+ if (missing.length > 0) {
3430
+ console.error(`[video] render.json is missing ${missing.join(", ")} — the finding ships without its diversity-ledger stamp(s); fix the render bundle's render.json`);
3431
+ }
3432
+ return result;
3397
3433
  }
3398
3434
  async function trackDraftCommand(idOrLogId, platform2) {
3399
3435
  return adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/social/${platform2}/draft`);
@@ -3509,7 +3545,7 @@ async function trackNoteCommand(idOrLogId, options) {
3509
3545
  }
3510
3546
  return adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/note`, body);
3511
3547
  }
3512
- var DEFAULT_VIDEO_MODEL = "anthropic/claude-opus-4-8", DEFAULT_VIDEO_REASONING = "high", FOUND_BASE = "https://found.fluncle.com", VIDEO_FIELDS, RERENDER_CONTRACT_FIELDS, RERENDER_ADVISORY_FIELDS, FOOTAGE_FIELDS, PLATE_FIELDS, NON_FILE_OPTIONS;
3548
+ var DEFAULT_VIDEO_MODEL = "anthropic/claude-opus-4-8", DEFAULT_VIDEO_REASONING = "high", FOUND_BASE = "https://found.fluncle.com", VIDEO_FIELDS, RERENDER_CONTRACT_FIELDS, RERENDER_ADVISORY_FIELDS, FOOTAGE_FIELDS, PLATE_FIELDS, NON_FILE_OPTIONS, DIVERSITY_LEDGER_FIELDS;
3513
3549
  var init_track = __esm(() => {
3514
3550
  init_api();
3515
3551
  init_output();
@@ -3550,6 +3586,7 @@ var init_track = __esm(() => {
3550
3586
  ];
3551
3587
  PLATE_FIELDS = ["plate", "plateBackground"];
3552
3588
  NON_FILE_OPTIONS = ["model", "reasoning"];
3589
+ DIVERSITY_LEDGER_FIELDS = ["vehicle", "grain", "register"];
3553
3590
  });
3554
3591
 
3555
3592
  // src/commands/admin-attention.ts
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.148.0"
34
+ "version": "0.150.0"
35
35
  }