fluncle 0.234.0 → 0.235.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 +55 -13
  2. package/package.json +1 -1
package/bin/fluncle.mjs CHANGED
@@ -622,7 +622,7 @@ function parseVersion(version) {
622
622
  var currentVersion;
623
623
  var init_version = __esm(() => {
624
624
  init_output();
625
- currentVersion = "0.234.0".trim() ? "0.234.0".trim() : "0.1.0";
625
+ currentVersion = "0.235.0".trim() ? "0.235.0".trim() : "0.1.0";
626
626
  });
627
627
 
628
628
  // src/update-notifier.ts
@@ -2335,7 +2335,7 @@ function parseVersion2(version) {
2335
2335
  var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
2336
2336
  var init_version2 = __esm(() => {
2337
2337
  init_output();
2338
- currentVersion2 = "0.234.0".trim() ? "0.234.0".trim() : "0.1.0";
2338
+ currentVersion2 = "0.235.0".trim() ? "0.235.0".trim() : "0.1.0";
2339
2339
  });
2340
2340
 
2341
2341
  // ../../packages/registry/src/index.ts
@@ -3059,6 +3059,28 @@ var init_src = __esm(() => {
3059
3059
  url: `${SITE}/robots.txt`,
3060
3060
  weights: { web: "tertiary" }
3061
3061
  },
3062
+ {
3063
+ apiFormat: "text/plain",
3064
+ exposedContent: [
3065
+ "RFC 9116 security.txt — where to send a vulnerability report, in the one place a researcher looks first"
3066
+ ],
3067
+ kind: "discovery",
3068
+ name: "discovery.security-txt",
3069
+ operatorNotes: "A static file, apps/web/public/.well-known/security.txt. It carries an `Expires` field the RFC requires a responder to keep in the future — when it lapses, a reporter reads the contact as stale. No probeConfig, exactly like robots.txt and llms.txt: a static asset the Worker never computes.",
3070
+ route: "/.well-known/security.txt",
3071
+ url: `${SITE}/.well-known/security.txt`,
3072
+ weights: { web: "tertiary" }
3073
+ },
3074
+ {
3075
+ apiFormat: "text/plain",
3076
+ exposedContent: ["humans.txt — who made this, who is thanked, and what it is built with"],
3077
+ kind: "discovery",
3078
+ name: "discovery.humans",
3079
+ operatorNotes: "A static file, apps/web/public/humans.txt — the human counterpart to robots.txt. Machine-fetched by convention, never browsed, which is why it sits under `discovery` beside robots.txt rather than as a web route.",
3080
+ route: "/humans.txt",
3081
+ url: `${SITE}/humans.txt`,
3082
+ weights: { web: "tertiary" }
3083
+ },
3062
3084
  {
3063
3085
  apiFormat: "text/markdown",
3064
3086
  discoveryUrl: `${SITE}/.well-known/api-catalog`,
@@ -3875,7 +3897,7 @@ var init_src = __esm(() => {
3875
3897
  ],
3876
3898
  kind: "cron",
3877
3899
  name: "cron.reconcile-hub-counts",
3878
- operatorNotes: "04:10 Amsterdam (after the 04:00 reach snapshot, before the 04:40 demand tick), a rave-02 host systemd timer (docs/agents/hermes/reconcile-hub-counts-timer/). The SELF-HEALING BACKSTOP under keystone 2's maintained hub counts: they are moved as DELTAS by every edge-writing path (recompute-from-truth measured 27,400 ms at 150k hosted vs ~200 ms for the delta form), and a maintained counter drifts silently — a missed write path, a non-atomic bulk op, or an out-of-band write (the catalogue-prune skill deletes tracks straight out of the database). Keystone 2's own rollout proved it on day one: the deploy-window skew left 44 artists / 3 albums / 1 label wrong until a manual reconcile. A bare trigger (the funnel-snapshot shape): fires the AGENT-tier reconcile_hub_counts op once and the Worker runs two statements per table a grouped `UPDATE FROM ( GROUP BY fk)` guarded by a counts-DIFFER predicate (so rowsAffected IS the corrected-row count) plus a zero-truth pass for an entity whose last track vanished. The artists source is PINNED to `track_artists JOIN tracks` so orphaned edges never count. Idempotent; zero LLM tokens; no new secret. The corrected-row numbers are the operator's DRIFT AUDIT — journalctl -u fluncle-reconcile-hub-counts.service | grep AUDIT. Source: docs/agents/hermes/scripts/reconcile-hub-counts.*.",
3900
+ operatorNotes: "04:10 Amsterdam (after the 04:00 reach snapshot, before the 04:40 demand tick), a rave-02 host systemd timer (docs/agents/hermes/reconcile-hub-counts-timer/). The SELF-HEALING BACKSTOP under keystone 2's maintained hub counts: they are moved as DELTAS by every edge-writing path (recompute-from-truth measured 27,400 ms at 150k hosted vs ~200 ms for the delta form), and a maintained counter drifts silently — a missed write path, a non-atomic bulk op, or an out-of-band write (the catalogue-prune skill deletes tracks straight out of the database). Keystone 2's own rollout proved it on day one: the deploy-window skew left 44 artists / 3 albums / 1 label wrong until a manual reconcile. Walks the AGENT-tier reconcile_hub_counts op in bounded windows, one admitted database phase each: the Worker reads bounded keyset pages of entity rows beside their truth (never an aggregate inside a write transaction) and rewrites only disagreeing rows as compare-and-set point writes, so a concurrent maintained delta is never overwritten. The artists source is PINNED to `track_artists JOIN tracks` so orphaned edges never count. Idempotent; zero LLM tokens; no new secret. The corrected-row numbers are the operator's DRIFT AUDIT — journalctl -u fluncle-reconcile-hub-counts.service | grep AUDIT. Source: docs/agents/hermes/scripts/reconcile-hub-counts.*.",
3879
3901
  probeConfig: {
3880
3902
  cadenceMs: 24 * 60 * MINUTE_MS,
3881
3903
  cronName: "fluncle-reconcile-hub-counts",
@@ -10693,7 +10715,10 @@ var init_admin_artists = __esm(() => {
10693
10715
  path: "/admin/artists/rank",
10694
10716
  summary: "One tick of the similar-artists sweep (artist centroids + top-K edges)",
10695
10717
  tags: ["Admin"]
10696
- }).input(object({ limit: number3().int().min(1).max(1000).default(50) })).output(object({
10718
+ }).input(object({
10719
+ countRemaining: boolean3().default(false),
10720
+ limit: number3().int().min(1).max(1000).default(50)
10721
+ })).output(object({
10697
10722
  ok: literal(true),
10698
10723
  summary: object({
10699
10724
  centroidsComputed: number2(),
@@ -12282,7 +12307,8 @@ var init_admin_projections = __esm(() => {
12282
12307
  processed: CountSchema,
12283
12308
  scheduled: CountSchema,
12284
12309
  status: ProjectionStatusSchema.optional(),
12285
- target: ProjectionTargetSchema
12310
+ target: ProjectionTargetSchema,
12311
+ trackSourceMarkersPending: boolean2().optional()
12286
12312
  }));
12287
12313
  setProjectionCutover = oc.route({
12288
12314
  method: "PUT",
@@ -13226,7 +13252,7 @@ var init_admin_operation_receipts = __esm(() => {
13226
13252
  });
13227
13253
 
13228
13254
  // ../../packages/contracts/src/orpc/admin-health.ts
13229
- var HEALTH_SNAPSHOT_PRODUCER_MAX = 64, HEALTH_SNAPSHOT_PRODUCER_PATTERN, ServiceHealthStatusSchema, HealthCheckSchema, recordHealth, adminHealthContract;
13255
+ var HEALTH_SNAPSHOT_PRODUCER_MAX = 64, HEALTH_SNAPSHOT_PRODUCER_PATTERN, HEALTH_SNAPSHOT_CHECKS_MAX = 128, HEALTH_SNAPSHOT_SERVICE_MAX = 64, ServiceHealthStatusSchema, HealthCheckSchema, recordHealth, adminHealthContract;
13230
13256
  var init_admin_health = __esm(() => {
13231
13257
  init_dist3();
13232
13258
  init_zod();
@@ -13236,7 +13262,7 @@ var init_admin_health = __esm(() => {
13236
13262
  HealthCheckSchema = object({
13237
13263
  latencyMs: number2().int().nullable(),
13238
13264
  message: string2().nullable(),
13239
- service: string2().min(1),
13265
+ service: string2().min(1).max(HEALTH_SNAPSHOT_SERVICE_MAX),
13240
13266
  status: ServiceHealthStatusSchema,
13241
13267
  transitioned: boolean2()
13242
13268
  }).meta({ id: "HealthCheck" });
@@ -13248,7 +13274,7 @@ var init_admin_health = __esm(() => {
13248
13274
  tags: ["Admin"]
13249
13275
  }).input(object({
13250
13276
  at: string2().max(64).datetime({ offset: true }),
13251
- checks: array(HealthCheckSchema),
13277
+ checks: array(HealthCheckSchema).max(HEALTH_SNAPSHOT_CHECKS_MAX),
13252
13278
  operationKey: string2().min(1).max(OPERATION_RECEIPT_KEY_MAX).regex(OPERATION_RECEIPT_KEY_PATTERN).optional(),
13253
13279
  producer: string2().max(HEALTH_SNAPSHOT_PRODUCER_MAX).regex(HEALTH_SNAPSHOT_PRODUCER_PATTERN).optional(),
13254
13280
  requestDigest: string2().regex(OPERATION_RECEIPT_REQUEST_DIGEST_PATTERN).optional()
@@ -13263,24 +13289,34 @@ var init_admin_health = __esm(() => {
13263
13289
  });
13264
13290
 
13265
13291
  // ../../packages/contracts/src/orpc/admin-hub-counts.ts
13266
- var HubCountsTableResultSchema, reconcileHubCounts, adminHubCountsContract;
13292
+ var HubCountsTableResultSchema, HubCountsReconcileCursorSchema, reconcileHubCounts, adminHubCountsContract;
13267
13293
  var init_admin_hub_counts = __esm(() => {
13268
13294
  init_dist3();
13269
13295
  init_zod();
13270
13296
  HubCountsTableResultSchema = object({
13271
- corrected: number2()
13297
+ corrected: number2(),
13298
+ deferred: number2()
13272
13299
  }).meta({ id: "HubCountsTableResult" });
13300
+ HubCountsReconcileCursorSchema = object({
13301
+ afterId: string2().min(1).max(512).nullable(),
13302
+ table: _enum(["labels", "albums", "artists"])
13303
+ }).meta({ id: "HubCountsReconcileCursor" });
13273
13304
  reconcileHubCounts = oc.route({
13274
13305
  method: "POST",
13275
13306
  operationId: "reconcileHubCounts",
13276
13307
  path: "/admin/hub-counts/reconcile",
13277
13308
  summary: "Reconcile the maintained hub counts against truth and report the corrected rows",
13278
13309
  tags: ["Admin"]
13279
- }).input(object({})).output(object({
13310
+ }).input(object({
13311
+ cursor: HubCountsReconcileCursorSchema.optional(),
13312
+ pageLimit: number2().int().min(1).max(20).optional()
13313
+ })).output(object({
13280
13314
  albums: HubCountsTableResultSchema,
13281
13315
  artists: HubCountsTableResultSchema,
13282
13316
  labels: HubCountsTableResultSchema,
13317
+ next: HubCountsReconcileCursorSchema.nullable(),
13283
13318
  ok: literal(true),
13319
+ pages: number2(),
13284
13320
  tookMs: number2()
13285
13321
  }));
13286
13322
  adminHubCountsContract = {
@@ -18601,7 +18637,10 @@ async function resolveArtistCommand(artistId) {
18601
18637
  }
18602
18638
  async function rankArtistsCommand(options) {
18603
18639
  const limit = options.limit ? Number.parseInt(options.limit, 10) : undefined;
18604
- const response = await adminApiPost("/api/v1/admin/artists/rank", limit ? { limit } : {});
18640
+ const response = await adminApiPost("/api/v1/admin/artists/rank", {
18641
+ ...limit ? { limit } : {},
18642
+ ...options.countRemaining ? { countRemaining: true } : {}
18643
+ });
18605
18644
  return { summary: response.summary };
18606
18645
  }
18607
18646
  async function backfillArtistImagesCommand(limit, dryRun, cursor) {
@@ -24529,7 +24568,10 @@ async function runGalaxies(slug, options, commands) {
24529
24568
  }
24530
24569
  }
24531
24570
  async function runArtistsRank(options, rankArtistsCommand) {
24532
- const { summary } = await rankArtistsCommand({ limit: options.limit });
24571
+ const { summary } = await rankArtistsCommand({
24572
+ countRemaining: !options.json,
24573
+ limit: options.limit
24574
+ });
24533
24575
  if (options.json) {
24534
24576
  printJson({ ok: true, summary });
24535
24577
  return;
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.234.0"
34
+ "version": "0.235.0"
35
35
  }