fluncle 0.257.0 → 0.258.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 +95 -4
  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.257.0".trim() ? "0.257.0".trim() : "0.1.0";
625
+ currentVersion = "0.258.0".trim() ? "0.258.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.257.0".trim() ? "0.257.0".trim() : "0.1.0";
2338
+ currentVersion2 = "0.258.0".trim() ? "0.258.0".trim() : "0.1.0";
2339
2339
  });
2340
2340
 
2341
2341
  // ../../packages/registry/src/index.ts
@@ -3711,6 +3711,17 @@ var init_src = __esm(() => {
3711
3711
  title: "Label bios",
3712
3712
  weights: { status: "hidden" }
3713
3713
  },
3714
+ {
3715
+ command: "fluncle admin labels list --seed-state undecided",
3716
+ exposedContent: ["read the undecided crawl-seed pile and report whether a triage round is due"],
3717
+ kind: "cron",
3718
+ name: "cron.label-triage",
3719
+ operatorNotes: "daily. A PURE trigger — zero model tokens, one countless admin read and a sort. Fires only when 40+ NEVER-LOOKED labels have accumulated; stale ones ride along but never trigger a round. It cannot rule: recording a finding is record_label_triage (agent tier) and ruling is update_label (operator tier), which 403s the box token. The batched research leg is deliberately unwired until the gate proves it reports honestly. Source: docs/agents/hermes/scripts/{label-triage-sweep.ts,label-triage-sweep.sh}.",
3720
+ probeConfig: { cadenceMs: 24 * 60 * MINUTE_MS, cronName: "fluncle-label-triage", kind: "cron" },
3721
+ statusDescription: "reports when the label pile needs a round",
3722
+ title: "Label triage gate",
3723
+ weights: { status: "hidden" }
3724
+ },
3714
3725
  {
3715
3726
  command: "fluncle admin albums describe --queue",
3716
3727
  exposedContent: [
@@ -12796,6 +12807,7 @@ var init__shared = __esm(() => {
12796
12807
  postedToTelegram: boolean2(),
12797
12808
  previewUrl: string2().optional(),
12798
12809
  releaseDate: string2().optional(),
12810
+ similar: boolean2().optional(),
12799
12811
  sourceAudioFailures: number2().optional(),
12800
12812
  sourceAudioKey: string2().optional(),
12801
12813
  spotifyUrl: string2(),
@@ -13519,7 +13531,8 @@ var init_admin_hub_counts = __esm(() => {
13519
13531
  init_zod();
13520
13532
  HubCountsTableResultSchema = object({
13521
13533
  corrected: number2(),
13522
- deferred: number2()
13534
+ deferred: number2(),
13535
+ latestCorrected: number2()
13523
13536
  }).meta({ id: "HubCountsTableResult" });
13524
13537
  HubCountsReconcileCursorSchema = object({
13525
13538
  afterId: string2().min(1).max(512).nullable(),
@@ -13549,12 +13562,13 @@ var init_admin_hub_counts = __esm(() => {
13549
13562
  });
13550
13563
 
13551
13564
  // ../../packages/contracts/src/orpc/admin-labels.ts
13552
- var LabelSeedStateSchema, LabelAdminItemSchema, listLabelsAdmin, updateLabel, listLabelArtistRules, replaceLabelArtistRules, MergeLabelResultSchema, mergeLabel, MB_LABEL_MBID_PATTERN, MintLabelOutcomeSchema, LabelTakeOverResultSchema, mintLabel, LabelAliasSourceSchema, LabelAliasKindSchema, LabelAliasCandidateSchema, listLabelAliases, confirmLabelAlias, rejectLabelAlias, DescribeLabelBodySchema, describeLabel, draftLabelBio, LabelBioWorkItemSchema, listLabelsMissingBio, adminLabelsContract;
13565
+ var LabelSeedStateSchema, LabelTriageVerdictSchema, LabelAdminItemSchema, listLabelsAdmin, updateLabel, listLabelArtistRules, replaceLabelArtistRules, MergeLabelResultSchema, mergeLabel, MB_LABEL_MBID_PATTERN, MintLabelOutcomeSchema, LabelTakeOverResultSchema, mintLabel, LabelAliasSourceSchema, LabelAliasKindSchema, LabelAliasCandidateSchema, listLabelAliases, confirmLabelAlias, rejectLabelAlias, DescribeLabelBodySchema, describeLabel, draftLabelBio, LabelBioWorkItemSchema, listLabelsMissingBio, TriageRuleProposalSchema, RecordLabelTriageBodySchema, recordLabelTriage, adminLabelsContract;
13553
13566
  var init_admin_labels = __esm(() => {
13554
13567
  init_dist3();
13555
13568
  init_zod();
13556
13569
  init_admin_artist_rules();
13557
13570
  LabelSeedStateSchema = _enum(["disabled", "enabled", "undecided"]).meta({ id: "LabelSeedState" });
13571
+ LabelTriageVerdictSchema = _enum(["dnb", "dnb_partial", "not_dnb", "unclear"]).meta({ id: "LabelTriageVerdict" });
13558
13572
  LabelAdminItemSchema = object({
13559
13573
  createdAt: string2(),
13560
13574
  disambiguation: string2().nullable().optional(),
@@ -13569,6 +13583,9 @@ var init_admin_labels = __esm(() => {
13569
13583
  scopeChangedAt: string2().nullable().optional(),
13570
13584
  seedState: LabelSeedStateSchema,
13571
13585
  slug: string2(),
13586
+ triageCheckedAt: string2().nullable().optional(),
13587
+ triageReason: string2().nullable().optional(),
13588
+ triageVerdict: LabelTriageVerdictSchema.nullable().optional(),
13572
13589
  updatedAt: string2()
13573
13590
  }).meta({ id: "LabelAdminItem" });
13574
13591
  listLabelsAdmin = oc.route({
@@ -13748,6 +13765,38 @@ var init_admin_labels = __esm(() => {
13748
13765
  summary: "List labels with findings but no bio yet, oldest first (the bio worklist)",
13749
13766
  tags: ["Admin"]
13750
13767
  }).input(object({ limit: string2().optional() })).output(object({ labels: array(LabelBioWorkItemSchema), ok: literal(true) }));
13768
+ TriageRuleProposalSchema = object({
13769
+ artistMbid: string2(),
13770
+ artistName: string2(),
13771
+ evidence: string2().optional(),
13772
+ firstCreditCount: number2().int().min(0),
13773
+ verdict: _enum(["allow", "block"])
13774
+ });
13775
+ RecordLabelTriageBodySchema = object({
13776
+ censusSummary: string2().optional(),
13777
+ confidence: _enum(["high", "medium", "low"]),
13778
+ evidence: string2(),
13779
+ offLaneShare: number2().min(0).max(1).optional(),
13780
+ reason: string2().optional(),
13781
+ residualOffLaneShare: number2().min(0).max(1).optional(),
13782
+ roundId: string2(),
13783
+ rules: array(TriageRuleProposalSchema).optional(),
13784
+ verdict: LabelTriageVerdictSchema,
13785
+ verifyAgrees: boolean2().optional(),
13786
+ verifyEvidence: string2().optional()
13787
+ }).meta({ id: "RecordLabelTriageBody" });
13788
+ recordLabelTriage = oc.route({
13789
+ method: "POST",
13790
+ operationId: "recordLabelTriage",
13791
+ path: "/admin/labels/{slug}/triage",
13792
+ summary: "Record what a triage round found (stamps the cursor; never rules)",
13793
+ tags: ["Admin"]
13794
+ }).input(RecordLabelTriageBodySchema.extend({ slug: string2() })).output(object({
13795
+ droppedInertRules: number2().int(),
13796
+ ok: literal(true),
13797
+ superseded: boolean2(),
13798
+ triageCheckedAt: string2()
13799
+ }));
13751
13800
  adminLabelsContract = {
13752
13801
  confirm_label_alias: confirmLabelAlias,
13753
13802
  describe_label: describeLabel,
@@ -13758,6 +13807,7 @@ var init_admin_labels = __esm(() => {
13758
13807
  list_labels_missing_bio: listLabelsMissingBio,
13759
13808
  merge_label: mergeLabel,
13760
13809
  mint_label: mintLabel,
13810
+ record_label_triage: recordLabelTriage,
13761
13811
  reject_label_alias: rejectLabelAlias,
13762
13812
  replace_label_artist_rules: replaceLabelArtistRules,
13763
13813
  update_label: updateLabel
@@ -19255,6 +19305,19 @@ async function mintLabelCommand(mbLabelId, seedState, takeOverSlug) {
19255
19305
  });
19256
19306
  return { label: response.label, outcome: response.outcome, takenOver: response.takenOver };
19257
19307
  }
19308
+ async function listLabelsAdminCommand(seedState) {
19309
+ const query = seedState === undefined ? "" : `?seedState=${encodeURIComponent(seedState)}`;
19310
+ const response = await adminApiGet(`/api/v1/admin/labels${query}`);
19311
+ return response.labels;
19312
+ }
19313
+ async function recordLabelTriageCommand(slug, payload) {
19314
+ const response = await adminApiPost(`/api/v1/admin/labels/${encodeURIComponent(slug.trim().toLowerCase())}/triage`, payload);
19315
+ return {
19316
+ droppedInertRules: response.droppedInertRules,
19317
+ superseded: response.superseded,
19318
+ triageCheckedAt: response.triageCheckedAt
19319
+ };
19320
+ }
19258
19321
  async function describeLabelCommand(slug, options) {
19259
19322
  return adminApiPost(`/api/v1/admin/labels/${encodeURIComponent(slug)}/bio`, buildBioBody2(options));
19260
19323
  }
@@ -23064,6 +23127,33 @@ JSON field reference:
23064
23127
  console.log(line);
23065
23128
  }
23066
23129
  });
23130
+ labels.command("list").description("List labels with their crawl-seed state and triage cursor").option("--seed-state <state>", "Only this state: enabled, disabled, or undecided").option("--json", "Print JSON", false).action(async (options) => {
23131
+ const seedState = options.seedState;
23132
+ if (seedState !== undefined && seedState !== "enabled" && seedState !== "disabled" && seedState !== "undecided") {
23133
+ throw new Error("Pass --seed-state enabled|disabled|undecided");
23134
+ }
23135
+ await Promise.resolve().then(() => init_admin_labels2());
23136
+ const labels = await listLabelsAdminCommand(seedState);
23137
+ if (options.json) {
23138
+ console.log(JSON.stringify({ labels }, null, 2));
23139
+ return;
23140
+ }
23141
+ for (const label of labels) {
23142
+ const looked = label.triageCheckedAt ? label.triageVerdict : "never looked";
23143
+ console.log(`${label.slug} ${label.seedState} ${looked ?? ""}`.trimEnd());
23144
+ }
23145
+ });
23146
+ labels.command("triage").description("Record what a triage round found for a label (agent; never rules)").argument("<slug>", "The label slug").requiredOption("--payload <file>", "JSON file holding the round's finding for this label").option("--json", "Print JSON", false).action(async (slug, options) => {
23147
+ const payload = JSON.parse(readFileSync6(options.payload, "utf8"));
23148
+ await Promise.resolve().then(() => init_admin_labels2());
23149
+ const result = await recordLabelTriageCommand(slug, payload);
23150
+ if (options.json) {
23151
+ console.log(JSON.stringify(result, null, 2));
23152
+ return;
23153
+ }
23154
+ const dropped = result.droppedInertRules > 0 ? ` \u2014 dropped ${result.droppedInertRules} inert` : "";
23155
+ console.log(`${slug} \u2192 ${payload.verdict}${dropped}${result.superseded ? " (superseded)" : ""}`);
23156
+ });
23067
23157
  labels.command("mint").description("Mint a label from its MusicBrainz MBID (operator; idempotent)").argument("<mbid>", "The MusicBrainz label MBID").option("--seed-state <state>", "Rule it on arrival: enabled, disabled, or undecided").option("--take-over <slug>", "Re-point this trackless row's identity onto the minted entity").option("--json", "Print JSON", false).action(async (mbid, options) => {
23068
23158
  const seedState = options.seedState;
23069
23159
  if (seedState !== undefined && seedState !== "enabled" && seedState !== "disabled" && seedState !== "undecided") {
@@ -26094,6 +26184,7 @@ var stringOptions = new Set([
26094
26184
  "--page-digest",
26095
26185
  "--page-limit",
26096
26186
  "--parent-id",
26187
+ "--payload",
26097
26188
  "--plate",
26098
26189
  "--plate-background",
26099
26190
  "--platform",
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.257.0"
34
+ "version": "0.258.0"
35
35
  }