fluncle 0.218.0 → 0.220.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 +213 -16
- package/package.json +1 -1
package/bin/fluncle.mjs
CHANGED
|
@@ -610,7 +610,7 @@ function parseVersion(version) {
|
|
|
610
610
|
var currentVersion;
|
|
611
611
|
var init_version = __esm(() => {
|
|
612
612
|
init_output();
|
|
613
|
-
currentVersion = "0.
|
|
613
|
+
currentVersion = "0.220.0".trim() ? "0.220.0".trim() : "0.1.0";
|
|
614
614
|
});
|
|
615
615
|
|
|
616
616
|
// src/update-notifier.ts
|
|
@@ -2452,7 +2452,7 @@ function parseVersion2(version) {
|
|
|
2452
2452
|
var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
|
|
2453
2453
|
var init_version2 = __esm(() => {
|
|
2454
2454
|
init_output();
|
|
2455
|
-
currentVersion2 = "0.
|
|
2455
|
+
currentVersion2 = "0.220.0".trim() ? "0.220.0".trim() : "0.1.0";
|
|
2456
2456
|
});
|
|
2457
2457
|
|
|
2458
2458
|
// ../../packages/registry/src/index.ts
|
|
@@ -2779,7 +2779,7 @@ var init_src = __esm(() => {
|
|
|
2779
2779
|
},
|
|
2780
2780
|
{
|
|
2781
2781
|
exposedContent: [
|
|
2782
|
-
"the R2 media zone
|
|
2782
|
+
"the R2 media zone: each finding's video bundle and mixtape audio",
|
|
2783
2783
|
"the /cdn-cgi/media transform base (same zone, no cross-origin)"
|
|
2784
2784
|
],
|
|
2785
2785
|
kind: "subdomain",
|
|
@@ -2810,7 +2810,7 @@ var init_src = __esm(() => {
|
|
|
2810
2810
|
},
|
|
2811
2811
|
{
|
|
2812
2812
|
exposedContent: [
|
|
2813
|
-
"the Tor onion mirror of www.fluncle.com
|
|
2813
|
+
"the Tor onion mirror of www.fluncle.com: the archive, API, RSS, and MCP over Tor"
|
|
2814
2814
|
],
|
|
2815
2815
|
kind: "subdomain",
|
|
2816
2816
|
name: "subdomain.onion",
|
|
@@ -7016,15 +7016,48 @@ var init_admin_reach = __esm(() => {
|
|
|
7016
7016
|
var exports_admin_artists = {};
|
|
7017
7017
|
__export(exports_admin_artists, {
|
|
7018
7018
|
resolveArtistCommand: () => resolveArtistCommand,
|
|
7019
|
+
removeArtistRuleCommand: () => removeArtistRuleCommand,
|
|
7019
7020
|
rankArtistsCommand: () => rankArtistsCommand,
|
|
7020
7021
|
listArtistsCommand: () => listArtistsCommand,
|
|
7022
|
+
listArtistRulesCommand: () => listArtistRulesCommand,
|
|
7021
7023
|
draftArtistBioCommand: () => draftArtistBioCommand,
|
|
7022
7024
|
describeArtistCommand: () => describeArtistCommand,
|
|
7023
7025
|
buildBioBody: () => buildBioBody,
|
|
7024
7026
|
backfillArtistsCommand: () => backfillArtistsCommand,
|
|
7025
7027
|
backfillArtistImagesCommand: () => backfillArtistImagesCommand,
|
|
7026
|
-
artistsBioQueueCommand: () => artistsBioQueueCommand
|
|
7028
|
+
artistsBioQueueCommand: () => artistsBioQueueCommand,
|
|
7029
|
+
artistRuleInput: () => artistRuleInput,
|
|
7030
|
+
addArtistRuleCommand: () => addArtistRuleCommand
|
|
7027
7031
|
});
|
|
7032
|
+
function artistRuleInput(artistMbid, verdict, artistName) {
|
|
7033
|
+
const cleanMbid = artistMbid.trim();
|
|
7034
|
+
if (!MBID_PATTERN.test(cleanMbid)) {
|
|
7035
|
+
throw new Error("Artist MBID must be a MusicBrainz artist MBID");
|
|
7036
|
+
}
|
|
7037
|
+
if (verdict !== "allow" && verdict !== "block") {
|
|
7038
|
+
throw new Error("Pass --verdict allow|block");
|
|
7039
|
+
}
|
|
7040
|
+
const cleanName = artistName?.trim();
|
|
7041
|
+
if (artistName !== undefined && !cleanName) {
|
|
7042
|
+
throw new Error("--name must be a non-empty artist name");
|
|
7043
|
+
}
|
|
7044
|
+
return {
|
|
7045
|
+
artistMbid: cleanMbid.toLowerCase(),
|
|
7046
|
+
...cleanName ? { artistName: cleanName } : {},
|
|
7047
|
+
verdict
|
|
7048
|
+
};
|
|
7049
|
+
}
|
|
7050
|
+
async function listArtistRulesCommand() {
|
|
7051
|
+
const response = await adminApiGet("/api/v1/admin/artist-rules");
|
|
7052
|
+
return response.rules;
|
|
7053
|
+
}
|
|
7054
|
+
async function addArtistRuleCommand(input) {
|
|
7055
|
+
const response = await adminApiPost("/api/v1/admin/artist-rules", input);
|
|
7056
|
+
return response.rule;
|
|
7057
|
+
}
|
|
7058
|
+
async function removeArtistRuleCommand(id) {
|
|
7059
|
+
return adminApiDelete(`/api/v1/admin/artist-rules/${encodeURIComponent(id)}`);
|
|
7060
|
+
}
|
|
7028
7061
|
function buildBioBody(options) {
|
|
7029
7062
|
const body = { bio: options.bio };
|
|
7030
7063
|
if (options.dryRun) {
|
|
@@ -7077,8 +7110,10 @@ async function backfillArtistsCommand(limit, dryRun, cursor) {
|
|
|
7077
7110
|
}
|
|
7078
7111
|
return adminApiPost(`/api/v1/admin/backfill/artists?${params.toString()}`);
|
|
7079
7112
|
}
|
|
7113
|
+
var MBID_PATTERN;
|
|
7080
7114
|
var init_admin_artists = __esm(() => {
|
|
7081
7115
|
init_api();
|
|
7116
|
+
MBID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
7082
7117
|
});
|
|
7083
7118
|
|
|
7084
7119
|
// src/commands/admin-artists.ts
|
|
@@ -7103,24 +7138,88 @@ var init_admin_artists2 = __esm(() => {
|
|
|
7103
7138
|
var exports_admin_labels = {};
|
|
7104
7139
|
__export(exports_admin_labels, {
|
|
7105
7140
|
updateLabelCommand: () => updateLabelCommand,
|
|
7141
|
+
replaceLabelArtistRulesCommand: () => replaceLabelArtistRulesCommand,
|
|
7142
|
+
parseLabelArtistRulesJson: () => parseLabelArtistRulesJson,
|
|
7106
7143
|
mergeLabelCommand: () => mergeLabelCommand,
|
|
7144
|
+
listLabelArtistRulesCommand: () => listLabelArtistRulesCommand,
|
|
7107
7145
|
labelsBioQueueCommand: () => labelsBioQueueCommand,
|
|
7108
7146
|
draftLabelBioCommand: () => draftLabelBioCommand,
|
|
7109
7147
|
describeLabelCommand: () => describeLabelCommand,
|
|
7110
7148
|
backfillLabelLineageCommand: () => backfillLabelLineageCommand,
|
|
7111
7149
|
backfillLabelImagesCommand: () => backfillLabelImagesCommand
|
|
7112
7150
|
});
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7151
|
+
function requireArtistMbid(value, at) {
|
|
7152
|
+
if (typeof value !== "string" || !MBID_PATTERN2.test(value.trim())) {
|
|
7153
|
+
throw new Error(`${at}.artistMbid must be a MusicBrainz artist MBID`);
|
|
7154
|
+
}
|
|
7155
|
+
return value.trim().toLowerCase();
|
|
7156
|
+
}
|
|
7157
|
+
function requireArtistName(value, at) {
|
|
7158
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
7159
|
+
throw new Error(`${at}.artistName must be a non-empty string`);
|
|
7160
|
+
}
|
|
7161
|
+
return value.trim();
|
|
7162
|
+
}
|
|
7163
|
+
function requireArtistVerdict(value, at) {
|
|
7164
|
+
if (value === "allow" || value === "block") {
|
|
7165
|
+
return value;
|
|
7166
|
+
}
|
|
7167
|
+
throw new Error(`${at}.verdict must be 'allow' or 'block'`);
|
|
7116
7168
|
}
|
|
7117
|
-
|
|
7169
|
+
function parseLabelArtistRulesJson(source) {
|
|
7170
|
+
let parsed;
|
|
7171
|
+
try {
|
|
7172
|
+
parsed = JSON.parse(source);
|
|
7173
|
+
} catch {
|
|
7174
|
+
throw new Error("Rules file must contain valid JSON");
|
|
7175
|
+
}
|
|
7176
|
+
if (!Array.isArray(parsed)) {
|
|
7177
|
+
throw new Error("Rules file must contain a JSON array");
|
|
7178
|
+
}
|
|
7179
|
+
if (parsed.length > 100) {
|
|
7180
|
+
throw new Error("Rules file may contain at most 100 artist rules");
|
|
7181
|
+
}
|
|
7182
|
+
return parsed.map((entry, index) => {
|
|
7183
|
+
const at = `Rules file entry ${index + 1}`;
|
|
7184
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
|
|
7185
|
+
throw new Error(`${at} must be an object`);
|
|
7186
|
+
}
|
|
7187
|
+
const value = entry;
|
|
7188
|
+
return {
|
|
7189
|
+
artistMbid: requireArtistMbid(value.artistMbid, at),
|
|
7190
|
+
artistName: requireArtistName(value.artistName, at),
|
|
7191
|
+
verdict: requireArtistVerdict(value.verdict, at)
|
|
7192
|
+
};
|
|
7193
|
+
});
|
|
7194
|
+
}
|
|
7195
|
+
async function resolveLabel(slugOrId) {
|
|
7118
7196
|
const { labels } = await adminApiGet("/api/v1/admin/labels");
|
|
7119
7197
|
const match = labels.find((label) => label.slug === slugOrId || label.id === slugOrId);
|
|
7120
7198
|
if (!match) {
|
|
7121
7199
|
throw new Error(`No label with slug or id '${slugOrId}' — check \`fluncle labels\``);
|
|
7122
7200
|
}
|
|
7123
|
-
|
|
7201
|
+
return match;
|
|
7202
|
+
}
|
|
7203
|
+
async function listLabelArtistRulesCommand(slugOrId) {
|
|
7204
|
+
const label = await resolveLabel(slugOrId);
|
|
7205
|
+
const response = await adminApiGet(`/api/v1/admin/labels/${encodeURIComponent(label.id)}/artists`);
|
|
7206
|
+
return { label, rules: response.rules };
|
|
7207
|
+
}
|
|
7208
|
+
async function replaceLabelArtistRulesCommand(slugOrId, rules) {
|
|
7209
|
+
const label = await resolveLabel(slugOrId);
|
|
7210
|
+
const response = await adminApiPut(`/api/v1/admin/labels/${encodeURIComponent(label.id)}/artists`, { rules });
|
|
7211
|
+
return { label, rules: response.rules };
|
|
7212
|
+
}
|
|
7213
|
+
async function mergeLabelCommand(losingSlug, canonicalSlug) {
|
|
7214
|
+
const response = await adminApiPost(`/api/v1/admin/labels/${encodeURIComponent(losingSlug)}/merge`, { canonicalSlug });
|
|
7215
|
+
return response.result;
|
|
7216
|
+
}
|
|
7217
|
+
async function updateLabelCommand(slugOrId, seedState, rewalk = false) {
|
|
7218
|
+
const match = await resolveLabel(slugOrId);
|
|
7219
|
+
const response = await adminApiPatch(`/api/v1/admin/labels/${encodeURIComponent(match.id)}`, {
|
|
7220
|
+
...rewalk ? { rewalk: true } : {},
|
|
7221
|
+
...seedState === undefined ? {} : { seedState }
|
|
7222
|
+
});
|
|
7124
7223
|
return response.label;
|
|
7125
7224
|
}
|
|
7126
7225
|
async function describeLabelCommand(slug, options) {
|
|
@@ -7147,9 +7246,11 @@ async function backfillLabelLineageCommand(limit, dryRun, cursor) {
|
|
|
7147
7246
|
}
|
|
7148
7247
|
return adminApiPost(`/api/v1/admin/backfill/label-lineage?${params.toString()}`);
|
|
7149
7248
|
}
|
|
7249
|
+
var MBID_PATTERN2;
|
|
7150
7250
|
var init_admin_labels = __esm(() => {
|
|
7151
7251
|
init_api();
|
|
7152
7252
|
init_admin_artists2();
|
|
7253
|
+
MBID_PATTERN2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
7153
7254
|
});
|
|
7154
7255
|
|
|
7155
7256
|
// src/commands/admin-covers.ts
|
|
@@ -9678,6 +9779,38 @@ function toJsonFailure(error) {
|
|
|
9678
9779
|
init_util();
|
|
9679
9780
|
|
|
9680
9781
|
// src/cli.ts
|
|
9782
|
+
function labelUpdateLines(label, options) {
|
|
9783
|
+
const lines = [];
|
|
9784
|
+
if (options.seedState !== undefined) {
|
|
9785
|
+
lines.push(`${label.name} (${label.slug}) \u2192 ${label.seedState}.`);
|
|
9786
|
+
lines.push(label.seedState === "enabled" ? " The next crawl seeds from it and stores its releases." : " The next crawl will not seed from it; nothing already stored is touched.");
|
|
9787
|
+
}
|
|
9788
|
+
if (options.rewalk) {
|
|
9789
|
+
lines.push(`${label.name} (${label.slug}) \u2192 scoped re-walk armed.`);
|
|
9790
|
+
lines.push(" The next crawl rechecks its MusicBrainz releases.");
|
|
9791
|
+
}
|
|
9792
|
+
return lines;
|
|
9793
|
+
}
|
|
9794
|
+
var ARTIST_RULE_BOUNDARY = "Rules change what the next crawl takes. Everything already here stays.";
|
|
9795
|
+
function artistRuleWriteLine(prefix) {
|
|
9796
|
+
return `${prefix} \u2014 ${ARTIST_RULE_BOUNDARY.replace(/^R/, "r")}`;
|
|
9797
|
+
}
|
|
9798
|
+
function artistRuleLines(rules) {
|
|
9799
|
+
if (rules.length === 0) {
|
|
9800
|
+
return ["No artist rules."];
|
|
9801
|
+
}
|
|
9802
|
+
const rows = rules.map((rule) => [
|
|
9803
|
+
rule.id,
|
|
9804
|
+
rule.verdict,
|
|
9805
|
+
rule.resolvedName ?? rule.artistName,
|
|
9806
|
+
rule.resolvedMbid ?? rule.artistMbid,
|
|
9807
|
+
rule.artistSpotifyId ?? "unresolved"
|
|
9808
|
+
]);
|
|
9809
|
+
const headings = ["ID", "VERDICT", "ARTIST", "MUSICBRAINZ", "SPOTIFY"];
|
|
9810
|
+
const widths = headings.map((heading, index) => Math.max(heading.length, ...rows.map((row) => row[index]?.length ?? 0)));
|
|
9811
|
+
const line = (row) => row.map((value, index) => value.padEnd(widths[index] ?? value.length)).join(" ").trimEnd();
|
|
9812
|
+
return [line(headings), line(widths.map((width) => "-".repeat(width))), ...rows.map(line)];
|
|
9813
|
+
}
|
|
9681
9814
|
function createProgram() {
|
|
9682
9815
|
const program2 = configureCommand(new Command);
|
|
9683
9816
|
program2.name("fluncle").description(fluncleTagline.toLowerCase()).option("--env <local|production>", "Config profile to load (default: production)").showSuggestionAfterError(false).addHelpCommand("help [command]", "display help for command").hook("preAction", (_thisCommand, actionCommand) => {
|
|
@@ -10571,6 +10704,34 @@ JSON field reference:
|
|
|
10571
10704
|
const { rankArtistsCommand: rankArtistsCommand2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
|
|
10572
10705
|
await runArtistsRank(options, rankArtistsCommand2);
|
|
10573
10706
|
});
|
|
10707
|
+
artists.command("rule").description("Always or never take one MusicBrainz artist's records (operator)").argument("<artist-mbid>", "The MusicBrainz artist MBID").requiredOption("--verdict <verdict>", "The ruling: allow or block").option("--name <name>", "Artist name (optional; the server resolves it when omitted)").option("--json", "Print JSON", false).action(async (artistMbid, options) => {
|
|
10708
|
+
const { addArtistRuleCommand: addArtistRuleCommand2, artistRuleInput: artistRuleInput2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
|
|
10709
|
+
const rule = await addArtistRuleCommand2(artistRuleInput2(artistMbid, options.verdict, options.name));
|
|
10710
|
+
if (options.json) {
|
|
10711
|
+
printJson({ ok: true, rule });
|
|
10712
|
+
return;
|
|
10713
|
+
}
|
|
10714
|
+
console.log(artistRuleWriteLine(`Rule set for ${rule.resolvedName ?? rule.artistName}: ${rule.verdict.toUpperCase()}`));
|
|
10715
|
+
});
|
|
10716
|
+
artists.command("rules").description("List the global artist crawl rules").option("--json", "Print JSON", false).action(async (options) => {
|
|
10717
|
+
const { listArtistRulesCommand: listArtistRulesCommand2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
|
|
10718
|
+
const rules = await listArtistRulesCommand2();
|
|
10719
|
+
if (options.json) {
|
|
10720
|
+
printJson({ ok: true, rules });
|
|
10721
|
+
return;
|
|
10722
|
+
}
|
|
10723
|
+
console.log(artistRuleLines(rules).join(`
|
|
10724
|
+
`));
|
|
10725
|
+
});
|
|
10726
|
+
artists.command("unrule").description("Remove one global artist crawl rule (operator)").argument("<id>", "The artist rule id").option("--json", "Print JSON", false).action(async (id, options) => {
|
|
10727
|
+
const { removeArtistRuleCommand: removeArtistRuleCommand2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
|
|
10728
|
+
const result = await removeArtistRuleCommand2(id);
|
|
10729
|
+
if (options.json) {
|
|
10730
|
+
printJson(result);
|
|
10731
|
+
return;
|
|
10732
|
+
}
|
|
10733
|
+
console.log(artistRuleWriteLine(`Rule removed: ${id}`));
|
|
10734
|
+
});
|
|
10574
10735
|
artists.command("draft-bio").description("Assemble the Worker-grounded bio prompt for an artist (the sweep's trigger)").argument("<slug>").option("--json", "Print JSON", false).allowExcessArguments().action(async (slug, options) => {
|
|
10575
10736
|
const { draftArtistBioCommand: draftArtistBioCommand2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
|
|
10576
10737
|
await runEntityBioDraft("artist", slug, options, draftArtistBioCommand2);
|
|
@@ -10592,19 +10753,48 @@ JSON field reference:
|
|
|
10592
10753
|
const { draftLabelBioCommand: draftLabelBioCommand2 } = await Promise.resolve().then(() => (init_admin_labels(), exports_admin_labels));
|
|
10593
10754
|
await runEntityBioDraft("label", slug, options, draftLabelBioCommand2);
|
|
10594
10755
|
});
|
|
10595
|
-
labels.command("
|
|
10756
|
+
labels.command("artists").description("List or replace one label's artist crawl rules").argument("<slug>", "The label's slug (an exact lbl_\u2026 id also works)").option("--replace", "Replace the complete rule set from --rules-file", false).option("--rules-file <file>", "JSON array of { artistMbid, artistName, verdict } rules").option("--json", "Print JSON", false).action(async (slug, options) => {
|
|
10757
|
+
const {
|
|
10758
|
+
listLabelArtistRulesCommand: listLabelArtistRulesCommand2,
|
|
10759
|
+
parseLabelArtistRulesJson: parseLabelArtistRulesJson2,
|
|
10760
|
+
replaceLabelArtistRulesCommand: replaceLabelArtistRulesCommand2
|
|
10761
|
+
} = await Promise.resolve().then(() => (init_admin_labels(), exports_admin_labels));
|
|
10762
|
+
if (!options.replace && options.rulesFile !== undefined) {
|
|
10763
|
+
throw new Error("Pass --replace with --rules-file");
|
|
10764
|
+
}
|
|
10765
|
+
if (options.replace && options.rulesFile === undefined) {
|
|
10766
|
+
throw new Error("Pass --rules-file <json> with --replace");
|
|
10767
|
+
}
|
|
10768
|
+
const result = options.replace ? await replaceLabelArtistRulesCommand2(slug, parseLabelArtistRulesJson2(readFileSync7(options.rulesFile ?? "", "utf8"))) : await listLabelArtistRulesCommand2(slug);
|
|
10769
|
+
if (options.json) {
|
|
10770
|
+
printJson({ ok: true, rules: result.rules });
|
|
10771
|
+
return;
|
|
10772
|
+
}
|
|
10773
|
+
if (options.replace) {
|
|
10774
|
+
const noun = result.rules.length === 1 ? "rule" : "rules";
|
|
10775
|
+
console.log(artistRuleWriteLine(`${result.rules.length} ${noun} set`));
|
|
10776
|
+
return;
|
|
10777
|
+
}
|
|
10778
|
+
console.log(artistRuleLines(result.rules).join(`
|
|
10779
|
+
`));
|
|
10780
|
+
});
|
|
10781
|
+
labels.command("update").description("Rule on a label's crawl scope or arm a scoped re-walk (operator)").argument("<slug>", "The label's slug (an exact lbl_\u2026 id also works)").option("--seed-state <state>", "The ruling: enabled, disabled, or undecided").option("--rewalk", "Arm a scoped re-walk without changing the ruling", false).option("--json", "Print JSON", false).action(async (slug, options) => {
|
|
10596
10782
|
const seedState = options.seedState;
|
|
10597
|
-
if (seedState !== "enabled" && seedState !== "disabled" && seedState !== "undecided") {
|
|
10783
|
+
if (seedState !== undefined && seedState !== "enabled" && seedState !== "disabled" && seedState !== "undecided") {
|
|
10598
10784
|
throw new Error("Pass --seed-state enabled|disabled|undecided");
|
|
10599
10785
|
}
|
|
10786
|
+
if (seedState === undefined && !options.rewalk) {
|
|
10787
|
+
throw new Error("Pass --seed-state enabled|disabled|undecided or --rewalk");
|
|
10788
|
+
}
|
|
10600
10789
|
const { updateLabelCommand: updateLabelCommand2 } = await Promise.resolve().then(() => (init_admin_labels(), exports_admin_labels));
|
|
10601
|
-
const label = await updateLabelCommand2(slug, seedState);
|
|
10790
|
+
const label = await updateLabelCommand2(slug, seedState, options.rewalk);
|
|
10602
10791
|
if (options.json) {
|
|
10603
10792
|
printJson({ label, ok: true });
|
|
10604
10793
|
return;
|
|
10605
10794
|
}
|
|
10606
|
-
|
|
10607
|
-
|
|
10795
|
+
for (const line of labelUpdateLines(label, options)) {
|
|
10796
|
+
console.log(line);
|
|
10797
|
+
}
|
|
10608
10798
|
});
|
|
10609
10799
|
labels.command("merge").description("Merge a slug-split label into its canonical row (operator; re-points + redirects)").argument("<losingSlug>", "The duplicate label to fold away").argument("<canonicalSlug>", "The label to keep \u2014 everything re-points onto it").option("--json", "Print JSON", false).action(async (losingSlug, canonicalSlug, options) => {
|
|
10610
10800
|
const { mergeLabelCommand: mergeLabelCommand2 } = await Promise.resolve().then(() => (init_admin_labels(), exports_admin_labels));
|
|
@@ -10616,12 +10806,14 @@ JSON field reference:
|
|
|
10616
10806
|
const {
|
|
10617
10807
|
aliasWritten,
|
|
10618
10808
|
canonicalSlug: canon,
|
|
10809
|
+
droppedRules,
|
|
10619
10810
|
losingSlug: loser,
|
|
10620
10811
|
reconciled,
|
|
10621
10812
|
repointed
|
|
10622
10813
|
} = result;
|
|
10623
10814
|
console.log(`Merged ${loser} \u2192 ${canon}.`);
|
|
10624
10815
|
console.log(` Re-pointed: ${repointed.tracks} track(s), ${repointed.childLabels} sublabel(s), ${repointed.aliases} alias(es).`);
|
|
10816
|
+
console.log(` Dropped: ${droppedRules} loser-scoped artist rule(s).`);
|
|
10625
10817
|
console.log(reconciled.length > 0 ? ` Filled onto ${canon} (was empty): ${reconciled.join(", ")}.` : ` Nothing to fill \u2014 ${canon} already carried every fact.`);
|
|
10626
10818
|
console.log(` Seed state resolved to: ${result.seedState}.`);
|
|
10627
10819
|
console.log(` Alias written: "${aliasWritten.alias}" (${aliasWritten.aliasSlug}) \u2192 confirmed, so it can never re-mint.`);
|
|
@@ -13534,6 +13726,7 @@ var stringOptions = new Set([
|
|
|
13534
13726
|
"--mime",
|
|
13535
13727
|
"--min-phrase-words",
|
|
13536
13728
|
"--model",
|
|
13729
|
+
"--name",
|
|
13537
13730
|
"--note",
|
|
13538
13731
|
"--ok",
|
|
13539
13732
|
"--order",
|
|
@@ -13549,6 +13742,7 @@ var stringOptions = new Set([
|
|
|
13549
13742
|
"--reasoning",
|
|
13550
13743
|
"--recorded-at",
|
|
13551
13744
|
"--recording",
|
|
13745
|
+
"--rules-file",
|
|
13552
13746
|
"--render",
|
|
13553
13747
|
"--scene",
|
|
13554
13748
|
"--scheduled-for",
|
|
@@ -13615,5 +13809,8 @@ if (__require.main == __require.module) {
|
|
|
13615
13809
|
}
|
|
13616
13810
|
export {
|
|
13617
13811
|
parseTelemetryTimestamp,
|
|
13618
|
-
|
|
13812
|
+
labelUpdateLines,
|
|
13813
|
+
createProgram,
|
|
13814
|
+
artistRuleLines,
|
|
13815
|
+
ARTIST_RULE_BOUNDARY
|
|
13619
13816
|
};
|
package/package.json
CHANGED