fluncle 0.144.0 → 0.146.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.
- package/bin/fluncle.mjs +63 -4
- 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.
|
|
564
|
+
currentVersion = "0.146.0".trim() ? "0.146.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.
|
|
2192
|
+
currentVersion2 = "0.146.0".trim() ? "0.146.0".trim() : "0.1.0";
|
|
2193
2193
|
});
|
|
2194
2194
|
|
|
2195
2195
|
// ../../packages/registry/src/index.ts
|
|
@@ -2783,7 +2783,7 @@ var init_src = __esm(() => {
|
|
|
2783
2783
|
{
|
|
2784
2784
|
command: "ssh rave.fluncle.com",
|
|
2785
2785
|
exposedContent: [
|
|
2786
|
-
"the rave terminal TUI: Latest bangers, Mixtape archive, Submit, Subscribe, Install CLI, About",
|
|
2786
|
+
"the rave terminal TUI: Latest bangers, Artist archive, Sonic galaxies, Mixtape archive, Random banger, Submit, Subscribe, Install CLI, System status, About",
|
|
2787
2787
|
"deep-register one-shots: `ssh rave.fluncle.com latest|random`"
|
|
2788
2788
|
],
|
|
2789
2789
|
kind: "ssh",
|
|
@@ -2980,6 +2980,17 @@ var init_src = __esm(() => {
|
|
|
2980
2980
|
probeConfig: { cadenceMs: 5 * MINUTE_MS, cronName: "fluncle-capture", kind: "cron" },
|
|
2981
2981
|
weights: { status: "hidden" }
|
|
2982
2982
|
},
|
|
2983
|
+
{
|
|
2984
|
+
command: "fluncle admin catalogue verify --queue",
|
|
2985
|
+
exposedContent: [
|
|
2986
|
+
"fingerprint-check each captured song against its official preview → the wrong-audio verdict"
|
|
2987
|
+
],
|
|
2988
|
+
kind: "cron",
|
|
2989
|
+
name: "cron.verify-captures",
|
|
2990
|
+
operatorNotes: "every 30m, run by a rave-02 HOST systemd timer (docs/agents/hermes/verify-captures-timer/). The HISTORIC half of the capture verification gate (docs/the-ear.md § Wrong audio): the capture sweep verifies every NEW download at ingest, and this sweep walks every capture that landed before the gate existed and gives each the same Chromaprint check against the track's ISRC-resolved official preview. The box only MEASURES (fpcalc + the sliding-window match) and reports a plain verdict; the Worker ROUTES it — match/no-preview stamp `capture_verification`, a CATALOGUE mismatch quarantines for re-capture, a FINDING mismatch only raises the `capture-suspect` /admin attention item (a machine never rewinds a public finding; the operator rules with flag_wrong_audio). Resumable by construction (a stamped row leaves the worklist); degrades honestly without fpcalc (pre-rebake: `fpcalc_missing`, nothing stamped). Zero LLM tokens. Source: docs/agents/hermes/scripts/verify-captures.* + fingerprint-match.ts. See docs/the-ear.md.",
|
|
2991
|
+
probeConfig: { cadenceMs: 30 * MINUTE_MS, cronName: "fluncle-verify-captures", kind: "cron" },
|
|
2992
|
+
weights: { status: "hidden" }
|
|
2993
|
+
},
|
|
2983
2994
|
{
|
|
2984
2995
|
command: "fluncle admin tracks context --queue",
|
|
2985
2996
|
exposedContent: [
|
|
@@ -3572,6 +3583,7 @@ var init_admin_attention = __esm(() => {
|
|
|
3572
3583
|
SOURCE_LABELS = {
|
|
3573
3584
|
"artist-review": "artist links",
|
|
3574
3585
|
"attach-cues": "cues",
|
|
3586
|
+
"capture-suspect": "capture check",
|
|
3575
3587
|
distribute: "distribute",
|
|
3576
3588
|
"drip-empty": "clip drip",
|
|
3577
3589
|
"label-review": "label",
|
|
@@ -5715,7 +5727,9 @@ var init_admin_notes = __esm(() => {
|
|
|
5715
5727
|
// src/commands/admin-catalogue.ts
|
|
5716
5728
|
var exports_admin_catalogue = {};
|
|
5717
5729
|
__export(exports_admin_catalogue, {
|
|
5730
|
+
verifyCaptureCommand: () => verifyCaptureCommand,
|
|
5718
5731
|
setTrackDismissedCommand: () => setTrackDismissedCommand,
|
|
5732
|
+
listUnverifiedCapturesCommand: () => listUnverifiedCapturesCommand,
|
|
5719
5733
|
flagWrongAudioCommand: () => flagWrongAudioCommand,
|
|
5720
5734
|
crawlStatusCommand: () => crawlStatusCommand,
|
|
5721
5735
|
crawlCatalogueCommand: () => crawlCatalogueCommand,
|
|
@@ -5759,6 +5773,19 @@ async function setTrackDismissedCommand(trackId, dismissed) {
|
|
|
5759
5773
|
trackId
|
|
5760
5774
|
});
|
|
5761
5775
|
}
|
|
5776
|
+
async function listUnverifiedCapturesCommand(options) {
|
|
5777
|
+
const params = new URLSearchParams;
|
|
5778
|
+
if (options.limit) {
|
|
5779
|
+
params.set("limit", options.limit);
|
|
5780
|
+
}
|
|
5781
|
+
return adminApiGet(`/api/admin/catalogue/captures/unverified?${params.toString()}`);
|
|
5782
|
+
}
|
|
5783
|
+
async function verifyCaptureCommand(trackId, verdict) {
|
|
5784
|
+
return adminApiPost("/api/admin/catalogue/captures/verify", {
|
|
5785
|
+
trackId,
|
|
5786
|
+
verdict
|
|
5787
|
+
});
|
|
5788
|
+
}
|
|
5762
5789
|
async function crawlCatalogueCommand(limit, maxHop, dryRun) {
|
|
5763
5790
|
const params = new URLSearchParams({ limit: String(limit), maxHop: String(maxHop) });
|
|
5764
5791
|
if (dryRun) {
|
|
@@ -8843,6 +8870,37 @@ function addAdminCommands(program2) {
|
|
|
8843
8870
|
}
|
|
8844
8871
|
console.log(flagged ? `Flagged ${trackId}. Its vector is out of the ranking and a fresh capture is queued (the bad bytes are hash-rejected).` : `${trackId} is not a captured finding \u2014 nothing to flag.`);
|
|
8845
8872
|
});
|
|
8873
|
+
catalogue.command("verify").description("Capture verification: the unverified worklist (--queue), or record one verdict").argument("[trackId]", "The track whose capture verdict to record (omit with --queue)").option("--queue", "List captured rows not yet verified against their preview", false).option("--verdict <verdict>", "The fingerprint verdict: match | mismatch | no-preview").option("--limit <limit>", "Worklist rows (default 50, max 200)").option("--json", "Print JSON", false).action(async (trackId, options) => {
|
|
8874
|
+
const { listUnverifiedCapturesCommand: listUnverifiedCapturesCommand2, verifyCaptureCommand: verifyCaptureCommand2 } = await Promise.resolve().then(() => (init_admin_catalogue(), exports_admin_catalogue));
|
|
8875
|
+
if (options.queue) {
|
|
8876
|
+
const { tracks } = await listUnverifiedCapturesCommand2(options.limit ? { limit: options.limit } : {});
|
|
8877
|
+
if (options.json) {
|
|
8878
|
+
printJson({ ok: true, tracks });
|
|
8879
|
+
return;
|
|
8880
|
+
}
|
|
8881
|
+
if (tracks.length === 0) {
|
|
8882
|
+
console.log("Every capture is verified. Nothing to check.");
|
|
8883
|
+
return;
|
|
8884
|
+
}
|
|
8885
|
+
for (const track of tracks) {
|
|
8886
|
+
console.log(`${track.logId ?? `${track.trackId} \xB7 catalogue`} \u2014 ${track.artists.join(", ")} \u2014 ${track.title}`);
|
|
8887
|
+
}
|
|
8888
|
+
return;
|
|
8889
|
+
}
|
|
8890
|
+
if (!trackId) {
|
|
8891
|
+
throw new Error("Pass a trackId with --verdict, or --queue for the worklist.");
|
|
8892
|
+
}
|
|
8893
|
+
const verdict = options.verdict;
|
|
8894
|
+
if (verdict !== "match" && verdict !== "mismatch" && verdict !== "no-preview") {
|
|
8895
|
+
throw new Error("--verdict must be match, mismatch, or no-preview.");
|
|
8896
|
+
}
|
|
8897
|
+
const { action } = await verifyCaptureCommand2(trackId, verdict);
|
|
8898
|
+
if (options.json) {
|
|
8899
|
+
printJson({ action, ok: true });
|
|
8900
|
+
return;
|
|
8901
|
+
}
|
|
8902
|
+
console.log(`Recorded. ${trackId} \u2192 ${action}.`);
|
|
8903
|
+
});
|
|
8846
8904
|
catalogue.command("certify").description("Certify an existing catalogue track in place \u2014 mint its finding (operator)").argument("<trackId>", "The catalogue track id to log").option("--note <note>", "An optional editorial note to mint onto the finding").option("--json", "Print JSON", false).action(async (trackId, options) => {
|
|
8847
8905
|
const { certifyTrackCommand: certifyTrackCommand2 } = await Promise.resolve().then(() => (init_admin_catalogue(), exports_admin_catalogue));
|
|
8848
8906
|
const { logId } = await certifyTrackCommand2(trackId, options.note);
|
|
@@ -10523,7 +10581,8 @@ async function runCatalogueRank(options, catalogueRankCommand2) {
|
|
|
10523
10581
|
return;
|
|
10524
10582
|
}
|
|
10525
10583
|
const quarantine = summary.quarantined > 0 ? ` Quarantined ${summary.quarantined} as wrong audio.` : "";
|
|
10526
|
-
|
|
10584
|
+
const deduped = summary.catalogueDuplicates > 0 ? ` Marked ${summary.catalogueDuplicates} as catalogue duplicates.` : "";
|
|
10585
|
+
console.log(`Ranked ${summary.scored} against ${summary.embeddedFindings} embedded findings; prioritized ${summary.prioritized} for capture.${quarantine}${deduped} ${summary.remaining} still stale.`);
|
|
10527
10586
|
}
|
|
10528
10587
|
async function runCatalogueList(options, catalogueListCommand2) {
|
|
10529
10588
|
const { summary, tracks } = await catalogueListCommand2({
|
package/package.json
CHANGED