@skill-map/cli 0.12.0 → 0.14.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/dist/cli/guide/sm-guide.md +688 -0
- package/dist/cli.js +745 -276
- package/dist/cli.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/kernel/index.js +2 -2
- package/dist/kernel/index.js.map +1 -1
- package/dist/ui/chunk-AVRC55YV.js +971 -0
- package/dist/ui/chunk-DOJURY6T.js +54 -0
- package/dist/ui/chunk-FWFBO7KA.js +37 -0
- package/dist/ui/chunk-G6SL4UFD.js +1 -0
- package/dist/ui/chunk-N2C45VIA.js +2 -0
- package/dist/ui/chunk-Q7L6LLAK.js +1 -0
- package/dist/ui/chunk-STE4Z72W.js +16 -0
- package/dist/ui/chunk-T5SUVDLE.js +2403 -0
- package/dist/ui/chunk-TEPC3SFH.js +819 -0
- package/dist/ui/chunk-VJAWM5V3.js +210 -0
- package/dist/ui/chunk-WFJRSBK6.js +38 -0
- package/dist/ui/chunk-ZF7H74JY.js +114 -0
- package/dist/ui/favicon-32x32.png +0 -0
- package/dist/ui/favicon.svg +14 -0
- package/dist/ui/index.html +27 -0
- package/dist/ui/main-TG4BEOVI.js +1 -0
- package/dist/ui/media/primeicons-4GST5W3O.woff2 +0 -0
- package/dist/ui/media/primeicons-DHQU4SEP.svg +345 -0
- package/dist/ui/media/primeicons-GEFHGEHP.ttf +0 -0
- package/dist/ui/media/primeicons-P53SE5CV.woff +0 -0
- package/dist/ui/media/primeicons-RSSEDYLY.eot +0 -0
- package/dist/ui/styles-TCK5JUQE.css +1 -0
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// cli/entry.ts
|
|
2
|
-
import { existsSync as
|
|
2
|
+
import { existsSync as existsSync20 } from "fs";
|
|
3
3
|
import { Builtins, Cli as Cli2 } from "clipanion";
|
|
4
4
|
|
|
5
5
|
// kernel/adapters/silent-logger.ts
|
|
@@ -50,7 +50,19 @@ function tx(template, vars = {}) {
|
|
|
50
50
|
|
|
51
51
|
// cli/i18n/entry.texts.ts
|
|
52
52
|
var ENTRY_TEXTS = {
|
|
53
|
-
bareNoProject: 'No skill-map project found in {{cwd}}.\nRun "sm init" to bootstrap one, or "sm --help" to see all commands.\n'
|
|
53
|
+
bareNoProject: 'No skill-map project found in {{cwd}}.\nRun "sm init" to bootstrap one, or "sm --help" to see all commands.\n',
|
|
54
|
+
parseErrorHeadline: "sm: {{message}}",
|
|
55
|
+
parseErrorUnknownOption: "unknown option '{{name}}'",
|
|
56
|
+
parseErrorUnknownOptionForVerb: "{{verb}}: unknown option '{{name}}'",
|
|
57
|
+
parseErrorUnknownCommand: "unknown command '{{name}}'",
|
|
58
|
+
parseErrorIncompleteCommand: "incomplete command '{{name}}'",
|
|
59
|
+
parseErrorSubcommandList: "Available subcommands: {{suggestions}}.",
|
|
60
|
+
parseErrorVerbUsage: "{{verb}}: {{message}}",
|
|
61
|
+
parseErrorMissingPositional: "{{verb}}: missing required positional argument(s) {{positionals}}",
|
|
62
|
+
parseErrorFlagSuggestion: "Did you mean '{{suggestion}}'?",
|
|
63
|
+
parseErrorVerbSuggestion: "Did you mean {{suggestions}}?",
|
|
64
|
+
parseErrorVerbHelpHint: "Run 'sm help {{verb}}' for usage.",
|
|
65
|
+
parseErrorFooter: "Run 'sm help' to see the full command list."
|
|
54
66
|
};
|
|
55
67
|
|
|
56
68
|
// kernel/ports/logger.ts
|
|
@@ -264,6 +276,174 @@ var ExitCode = {
|
|
|
264
276
|
NotFound: 5
|
|
265
277
|
};
|
|
266
278
|
|
|
279
|
+
// cli/util/edit-distance.ts
|
|
280
|
+
function editDistance(a, b, max) {
|
|
281
|
+
if (a === b) return 0;
|
|
282
|
+
if (Math.abs(a.length - b.length) > max) return max + 1;
|
|
283
|
+
const m = a.length;
|
|
284
|
+
const n = b.length;
|
|
285
|
+
if (m === 0) return n;
|
|
286
|
+
if (n === 0) return m;
|
|
287
|
+
let prev = Array.from({ length: n + 1 }, (_, i) => i);
|
|
288
|
+
let curr = new Array(n + 1);
|
|
289
|
+
for (let i = 1; i <= m; i++) {
|
|
290
|
+
const rowMin = fillEditRow({ a, b, i, prev, curr });
|
|
291
|
+
if (rowMin > max) return max + 1;
|
|
292
|
+
[prev, curr] = [curr, prev];
|
|
293
|
+
}
|
|
294
|
+
return prev[n];
|
|
295
|
+
}
|
|
296
|
+
function fillEditRow(args2) {
|
|
297
|
+
const { a, b, i, prev, curr } = args2;
|
|
298
|
+
curr[0] = i;
|
|
299
|
+
let rowMin = curr[0];
|
|
300
|
+
for (let j = 1; j < curr.length; j++) {
|
|
301
|
+
const cost = a.charCodeAt(i - 1) === b.charCodeAt(j - 1) ? 0 : 1;
|
|
302
|
+
const value = Math.min(curr[j - 1] + 1, prev[j] + 1, prev[j - 1] + cost);
|
|
303
|
+
curr[j] = value;
|
|
304
|
+
if (value < rowMin) rowMin = value;
|
|
305
|
+
}
|
|
306
|
+
return rowMin;
|
|
307
|
+
}
|
|
308
|
+
function closestMatches(target, candidates, options) {
|
|
309
|
+
const lcTarget = target.toLowerCase();
|
|
310
|
+
const ranked = [];
|
|
311
|
+
for (const c of candidates) {
|
|
312
|
+
const distance = editDistance(lcTarget, c.toLowerCase(), options.maxDistance);
|
|
313
|
+
if (distance <= options.maxDistance) ranked.push({ value: c, distance });
|
|
314
|
+
}
|
|
315
|
+
ranked.sort((a, b) => a.distance - b.distance || a.value.localeCompare(b.value));
|
|
316
|
+
return ranked.slice(0, options.topN).map((r) => r.value);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// cli/util/parse-error.ts
|
|
320
|
+
function isClipanionParseError(err) {
|
|
321
|
+
if (!err || typeof err !== "object") return false;
|
|
322
|
+
const e = err;
|
|
323
|
+
if (typeof e.name !== "string") return false;
|
|
324
|
+
if (!Array.isArray(e.input)) return false;
|
|
325
|
+
return e.name === "UnknownSyntaxError" || e.name === "AmbiguousSyntaxError";
|
|
326
|
+
}
|
|
327
|
+
function formatParseError(params) {
|
|
328
|
+
const { args: args2, verbPaths, error } = params;
|
|
329
|
+
const firstToken = args2[0] ?? "";
|
|
330
|
+
const offendingFlag = extractOffendingFlag(error.message);
|
|
331
|
+
if (offendingFlag !== null) {
|
|
332
|
+
const verbPrefix2 = matchedVerbPrefix(args2, verbPaths);
|
|
333
|
+
const suggestion2 = suggestFlag(offendingFlag);
|
|
334
|
+
const headline = verbPrefix2 ? tx(ENTRY_TEXTS.parseErrorUnknownOptionForVerb, { verb: verbPrefix2, name: offendingFlag }) : tx(ENTRY_TEXTS.parseErrorUnknownOption, { name: offendingFlag });
|
|
335
|
+
return renderError(headline, suggestion2);
|
|
336
|
+
}
|
|
337
|
+
if (firstToken === "") {
|
|
338
|
+
return renderError(error.message.trim(), null);
|
|
339
|
+
}
|
|
340
|
+
const verbPrefix = matchedVerbPrefix(args2, verbPaths);
|
|
341
|
+
if (verbPrefix) return formatVerbScopedError(verbPrefix, error.message);
|
|
342
|
+
const subcommands = subcommandsUnder(firstToken, verbPaths);
|
|
343
|
+
if (subcommands.length > 0) {
|
|
344
|
+
const headline = tx(ENTRY_TEXTS.parseErrorIncompleteCommand, { name: firstToken });
|
|
345
|
+
const suggestion2 = tx(ENTRY_TEXTS.parseErrorSubcommandList, {
|
|
346
|
+
suggestions: formatSuggestionList(subcommands)
|
|
347
|
+
});
|
|
348
|
+
return renderError(headline, suggestion2);
|
|
349
|
+
}
|
|
350
|
+
const candidates = closestVerbs(firstToken, verbPaths);
|
|
351
|
+
const suggestion = candidates.length > 0 ? tx(ENTRY_TEXTS.parseErrorVerbSuggestion, { suggestions: formatSuggestionList(candidates) }) : null;
|
|
352
|
+
return renderError(tx(ENTRY_TEXTS.parseErrorUnknownCommand, { name: firstToken }), suggestion);
|
|
353
|
+
}
|
|
354
|
+
function formatVerbScopedError(verbPrefix, errorMessage) {
|
|
355
|
+
const helpHint = tx(ENTRY_TEXTS.parseErrorVerbHelpHint, { verb: verbPrefix });
|
|
356
|
+
const missing = extractMissingPositionals(errorMessage);
|
|
357
|
+
if (missing !== null) {
|
|
358
|
+
const headline2 = tx(ENTRY_TEXTS.parseErrorMissingPositional, {
|
|
359
|
+
verb: verbPrefix,
|
|
360
|
+
positionals: missing
|
|
361
|
+
});
|
|
362
|
+
return renderError(headline2, helpHint);
|
|
363
|
+
}
|
|
364
|
+
const headline = tx(ENTRY_TEXTS.parseErrorVerbUsage, {
|
|
365
|
+
verb: verbPrefix,
|
|
366
|
+
message: firstLine(errorMessage)
|
|
367
|
+
});
|
|
368
|
+
return renderError(headline, helpHint);
|
|
369
|
+
}
|
|
370
|
+
function subcommandsUnder(namespace, verbPaths) {
|
|
371
|
+
const matches = verbPaths.filter((path) => path.length >= 2 && path[0] === namespace).map((path) => path.join(" ")).sort();
|
|
372
|
+
return matches.slice(0, 3);
|
|
373
|
+
}
|
|
374
|
+
function matchedVerbPrefix(args2, verbPaths) {
|
|
375
|
+
const leading = [];
|
|
376
|
+
for (const tok of args2) {
|
|
377
|
+
if (tok.startsWith("-")) break;
|
|
378
|
+
leading.push(tok);
|
|
379
|
+
}
|
|
380
|
+
if (leading.length === 0) return "";
|
|
381
|
+
let best = [];
|
|
382
|
+
for (const path of verbPaths) {
|
|
383
|
+
if (path.length > leading.length) continue;
|
|
384
|
+
const matches = path.every((tok, i) => leading[i] === tok);
|
|
385
|
+
if (matches && path.length > best.length) best = path;
|
|
386
|
+
}
|
|
387
|
+
return best.join(" ");
|
|
388
|
+
}
|
|
389
|
+
function renderError(headline, suggestion) {
|
|
390
|
+
const lines = [tx(ENTRY_TEXTS.parseErrorHeadline, { message: headline })];
|
|
391
|
+
if (suggestion) lines.push(suggestion);
|
|
392
|
+
lines.push(ENTRY_TEXTS.parseErrorFooter);
|
|
393
|
+
return lines.join("\n") + "\n";
|
|
394
|
+
}
|
|
395
|
+
function extractOffendingFlag(message) {
|
|
396
|
+
const match = /Unsupported option name \("([^"]+)"\)/.exec(message);
|
|
397
|
+
return match ? match[1] : null;
|
|
398
|
+
}
|
|
399
|
+
function extractMissingPositionals(message) {
|
|
400
|
+
if (!message.startsWith("Not enough positional arguments")) return null;
|
|
401
|
+
const hintLine = message.split("\n").map((l) => l.trim()).find((l) => l.startsWith("$"));
|
|
402
|
+
if (!hintLine) return "";
|
|
403
|
+
const names = [...hintLine.matchAll(/<([A-Za-z][A-Za-z0-9_-]*)>/g)].map((m) => `<${m[1]}>`);
|
|
404
|
+
return names.length > 0 ? names.join(" ") : "";
|
|
405
|
+
}
|
|
406
|
+
function firstLine(message) {
|
|
407
|
+
return message.split("\n")[0].trim();
|
|
408
|
+
}
|
|
409
|
+
function suggestFlag(token) {
|
|
410
|
+
if (!token.startsWith("-")) return null;
|
|
411
|
+
if (token.startsWith("--")) return null;
|
|
412
|
+
if (token.length <= 2) return null;
|
|
413
|
+
const longForm = "-" + token;
|
|
414
|
+
return tx(ENTRY_TEXTS.parseErrorFlagSuggestion, { suggestion: longForm });
|
|
415
|
+
}
|
|
416
|
+
function closestVerbs(typed, verbPaths) {
|
|
417
|
+
const target = typed.toLowerCase();
|
|
418
|
+
const distanceCap = target.length <= 4 ? 2 : 3;
|
|
419
|
+
const ranked = [];
|
|
420
|
+
for (const path of verbPaths) {
|
|
421
|
+
const verb = path.join(" ");
|
|
422
|
+
const head = path[0];
|
|
423
|
+
const distHead = editDistance(target, head.toLowerCase(), distanceCap);
|
|
424
|
+
const distFull = editDistance(target, verb.replace(/\s+/g, "").toLowerCase(), distanceCap);
|
|
425
|
+
const distance = Math.min(distHead, distFull);
|
|
426
|
+
if (distance <= distanceCap) ranked.push({ verb, distance });
|
|
427
|
+
}
|
|
428
|
+
ranked.sort((a, b) => a.distance - b.distance || a.verb.localeCompare(b.verb));
|
|
429
|
+
const seen = /* @__PURE__ */ new Set();
|
|
430
|
+
const out = [];
|
|
431
|
+
for (const { verb } of ranked) {
|
|
432
|
+
const head = verb.split(" ")[0];
|
|
433
|
+
if (seen.has(head)) continue;
|
|
434
|
+
seen.add(head);
|
|
435
|
+
out.push(verb);
|
|
436
|
+
if (out.length === 3) break;
|
|
437
|
+
}
|
|
438
|
+
return out;
|
|
439
|
+
}
|
|
440
|
+
function formatSuggestionList(items) {
|
|
441
|
+
const quoted = items.map((s) => `'${s}'`);
|
|
442
|
+
if (quoted.length <= 1) return quoted[0] ?? "";
|
|
443
|
+
if (quoted.length === 2) return `${quoted[0]} or ${quoted[1]}`;
|
|
444
|
+
return `${quoted.slice(0, -1).join(", ")}, or ${quoted[quoted.length - 1]}`;
|
|
445
|
+
}
|
|
446
|
+
|
|
267
447
|
// cli/util/runtime-context.ts
|
|
268
448
|
import { homedir } from "os";
|
|
269
449
|
function defaultRuntimeContext() {
|
|
@@ -839,7 +1019,7 @@ function normalizeTrigger(source) {
|
|
|
839
1019
|
|
|
840
1020
|
// built-in-plugins/extractors/slash/index.ts
|
|
841
1021
|
var ID2 = "slash";
|
|
842
|
-
var SLASH_RE = /(
|
|
1022
|
+
var SLASH_RE = /(?<![A-Za-z0-9_/.:?#])(\/[a-z0-9][a-z0-9_-]*(?::[a-z0-9][a-z0-9_-]*)?)/gi;
|
|
843
1023
|
var slashExtractor = {
|
|
844
1024
|
id: ID2,
|
|
845
1025
|
pluginId: "claude",
|
|
@@ -982,6 +1162,77 @@ function lineFor(lineStarts, offset) {
|
|
|
982
1162
|
return lo + 1;
|
|
983
1163
|
}
|
|
984
1164
|
|
|
1165
|
+
// built-in-plugins/extractors/markdown-link/index.ts
|
|
1166
|
+
import { posix as pathPosix } from "path";
|
|
1167
|
+
var ID5 = "markdown-link";
|
|
1168
|
+
var LINK_RE = /(?<!!)\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g;
|
|
1169
|
+
var URL_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;
|
|
1170
|
+
var markdownLinkExtractor = {
|
|
1171
|
+
id: ID5,
|
|
1172
|
+
pluginId: "core",
|
|
1173
|
+
kind: "extractor",
|
|
1174
|
+
version: "1.0.0",
|
|
1175
|
+
description: "Detects [text](path) markdown links and emits one references link per resolved file path.",
|
|
1176
|
+
stability: "stable",
|
|
1177
|
+
mode: "deterministic",
|
|
1178
|
+
emitsLinkKinds: ["references"],
|
|
1179
|
+
defaultConfidence: "high",
|
|
1180
|
+
scope: "body",
|
|
1181
|
+
extract(ctx) {
|
|
1182
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1183
|
+
const lineStarts = computeLineStarts2(ctx.body);
|
|
1184
|
+
const sourceDir = pathPosix.dirname(ctx.node.path);
|
|
1185
|
+
for (const match of ctx.body.matchAll(LINK_RE)) {
|
|
1186
|
+
const original = match[2];
|
|
1187
|
+
const resolved = resolveTarget(sourceDir, original);
|
|
1188
|
+
if (resolved === null) continue;
|
|
1189
|
+
if (seen.has(resolved)) continue;
|
|
1190
|
+
seen.add(resolved);
|
|
1191
|
+
const offset = match.index ?? 0;
|
|
1192
|
+
const link2 = {
|
|
1193
|
+
source: ctx.node.path,
|
|
1194
|
+
target: resolved,
|
|
1195
|
+
kind: "references",
|
|
1196
|
+
confidence: "high",
|
|
1197
|
+
sources: [ID5],
|
|
1198
|
+
trigger: {
|
|
1199
|
+
originalTrigger: original,
|
|
1200
|
+
normalizedTrigger: resolved
|
|
1201
|
+
},
|
|
1202
|
+
location: { line: lineFor2(lineStarts, offset) }
|
|
1203
|
+
};
|
|
1204
|
+
ctx.emitLink(link2);
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
};
|
|
1208
|
+
function resolveTarget(sourceDir, raw) {
|
|
1209
|
+
const noFragment = raw.split("#", 1)[0];
|
|
1210
|
+
const noQuery = noFragment.split("?", 1)[0];
|
|
1211
|
+
const trimmed = noQuery.trim();
|
|
1212
|
+
if (trimmed.length === 0) return null;
|
|
1213
|
+
if (URL_SCHEME_RE.test(trimmed)) return null;
|
|
1214
|
+
if (trimmed.startsWith("/")) return null;
|
|
1215
|
+
const joined = sourceDir === "." ? trimmed : `${sourceDir}/${trimmed}`;
|
|
1216
|
+
return pathPosix.normalize(joined);
|
|
1217
|
+
}
|
|
1218
|
+
function computeLineStarts2(body) {
|
|
1219
|
+
const starts = [0];
|
|
1220
|
+
for (let i = 0; i < body.length; i += 1) {
|
|
1221
|
+
if (body.charCodeAt(i) === 10) starts.push(i + 1);
|
|
1222
|
+
}
|
|
1223
|
+
return starts;
|
|
1224
|
+
}
|
|
1225
|
+
function lineFor2(lineStarts, offset) {
|
|
1226
|
+
let lo = 0;
|
|
1227
|
+
let hi = lineStarts.length - 1;
|
|
1228
|
+
while (lo < hi) {
|
|
1229
|
+
const mid = lo + hi + 1 >>> 1;
|
|
1230
|
+
if (lineStarts[mid] <= offset) lo = mid;
|
|
1231
|
+
else hi = mid - 1;
|
|
1232
|
+
}
|
|
1233
|
+
return lo + 1;
|
|
1234
|
+
}
|
|
1235
|
+
|
|
985
1236
|
// built-in-plugins/i18n/trigger-collision.texts.ts
|
|
986
1237
|
var TRIGGER_COLLISION_TEXTS = {
|
|
987
1238
|
/**
|
|
@@ -1008,14 +1259,14 @@ var TRIGGER_COLLISION_TEXTS = {
|
|
|
1008
1259
|
};
|
|
1009
1260
|
|
|
1010
1261
|
// built-in-plugins/rules/trigger-collision/index.ts
|
|
1011
|
-
var
|
|
1262
|
+
var ID6 = "trigger-collision";
|
|
1012
1263
|
var ADVERTISING_KINDS = /* @__PURE__ */ new Set([
|
|
1013
1264
|
"command",
|
|
1014
1265
|
"skill",
|
|
1015
1266
|
"agent"
|
|
1016
1267
|
]);
|
|
1017
1268
|
var triggerCollisionRule = {
|
|
1018
|
-
id:
|
|
1269
|
+
id: ID6,
|
|
1019
1270
|
pluginId: "core",
|
|
1020
1271
|
kind: "rule",
|
|
1021
1272
|
mode: "deterministic",
|
|
@@ -1115,7 +1366,7 @@ function analyzeTriggerBucket(normalized, claims) {
|
|
|
1115
1366
|
part: parts[0]
|
|
1116
1367
|
});
|
|
1117
1368
|
return {
|
|
1118
|
-
ruleId:
|
|
1369
|
+
ruleId: ID6,
|
|
1119
1370
|
severity: "error",
|
|
1120
1371
|
nodeIds,
|
|
1121
1372
|
message,
|
|
@@ -1134,9 +1385,9 @@ var BROKEN_REF_TEXTS = {
|
|
|
1134
1385
|
};
|
|
1135
1386
|
|
|
1136
1387
|
// built-in-plugins/rules/broken-ref/index.ts
|
|
1137
|
-
var
|
|
1388
|
+
var ID7 = "broken-ref";
|
|
1138
1389
|
var brokenRefRule = {
|
|
1139
|
-
id:
|
|
1390
|
+
id: ID7,
|
|
1140
1391
|
pluginId: "core",
|
|
1141
1392
|
kind: "rule",
|
|
1142
1393
|
version: "1.0.0",
|
|
@@ -1150,7 +1401,7 @@ var brokenRefRule = {
|
|
|
1150
1401
|
for (const link2 of ctx.links) {
|
|
1151
1402
|
if (isResolved(link2, byPath3, byNormalizedName)) continue;
|
|
1152
1403
|
issues.push({
|
|
1153
|
-
ruleId:
|
|
1404
|
+
ruleId: ID7,
|
|
1154
1405
|
severity: "warn",
|
|
1155
1406
|
nodeIds: [link2.source],
|
|
1156
1407
|
message: tx(BROKEN_REF_TEXTS.message, {
|
|
@@ -1198,9 +1449,9 @@ var SUPERSEDED_TEXTS = {
|
|
|
1198
1449
|
};
|
|
1199
1450
|
|
|
1200
1451
|
// built-in-plugins/rules/superseded/index.ts
|
|
1201
|
-
var
|
|
1452
|
+
var ID8 = "superseded";
|
|
1202
1453
|
var supersededRule = {
|
|
1203
|
-
id:
|
|
1454
|
+
id: ID8,
|
|
1204
1455
|
pluginId: "core",
|
|
1205
1456
|
kind: "rule",
|
|
1206
1457
|
version: "1.0.0",
|
|
@@ -1215,7 +1466,7 @@ var supersededRule = {
|
|
|
1215
1466
|
const supersededBy = meta["supersededBy"];
|
|
1216
1467
|
if (typeof supersededBy !== "string" || supersededBy.length === 0) continue;
|
|
1217
1468
|
issues.push({
|
|
1218
|
-
ruleId:
|
|
1469
|
+
ruleId: ID8,
|
|
1219
1470
|
severity: "info",
|
|
1220
1471
|
nodeIds: [node.path],
|
|
1221
1472
|
message: tx(SUPERSEDED_TEXTS.message, {
|
|
@@ -1236,9 +1487,9 @@ var LINK_CONFLICT_TEXTS = {
|
|
|
1236
1487
|
};
|
|
1237
1488
|
|
|
1238
1489
|
// built-in-plugins/rules/link-conflict/index.ts
|
|
1239
|
-
var
|
|
1490
|
+
var ID9 = "link-conflict";
|
|
1240
1491
|
var linkConflictRule = {
|
|
1241
|
-
id:
|
|
1492
|
+
id: ID9,
|
|
1242
1493
|
pluginId: "core",
|
|
1243
1494
|
kind: "rule",
|
|
1244
1495
|
version: "1.0.0",
|
|
@@ -1287,7 +1538,7 @@ var linkConflictRule = {
|
|
|
1287
1538
|
const [source, target] = key.split("\0");
|
|
1288
1539
|
const kindList = variants.map((v) => v.kind).join(" / ");
|
|
1289
1540
|
issues.push({
|
|
1290
|
-
ruleId:
|
|
1541
|
+
ruleId: ID9,
|
|
1291
1542
|
severity: "warn",
|
|
1292
1543
|
nodeIds: [source, target],
|
|
1293
1544
|
message: tx(LINK_CONFLICT_TEXTS.message, {
|
|
@@ -1333,10 +1584,10 @@ var ASCII_FORMATTER_TEXTS = {
|
|
|
1333
1584
|
};
|
|
1334
1585
|
|
|
1335
1586
|
// built-in-plugins/formatters/ascii/index.ts
|
|
1336
|
-
var
|
|
1587
|
+
var ID10 = "ascii";
|
|
1337
1588
|
var KIND_ORDER = ["agent", "command", "hook", "skill", "note"];
|
|
1338
1589
|
var asciiFormatter = {
|
|
1339
|
-
id:
|
|
1590
|
+
id: ID10,
|
|
1340
1591
|
pluginId: "core",
|
|
1341
1592
|
kind: "formatter",
|
|
1342
1593
|
version: "1.0.0",
|
|
@@ -1599,9 +1850,9 @@ var VALIDATE_ALL_TEXTS = {
|
|
|
1599
1850
|
};
|
|
1600
1851
|
|
|
1601
1852
|
// built-in-plugins/rules/validate-all/index.ts
|
|
1602
|
-
var
|
|
1853
|
+
var ID11 = "validate-all";
|
|
1603
1854
|
var validateAllRule = {
|
|
1604
|
-
id:
|
|
1855
|
+
id: ID11,
|
|
1605
1856
|
pluginId: "core",
|
|
1606
1857
|
kind: "rule",
|
|
1607
1858
|
version: "1.0.0",
|
|
@@ -1624,7 +1875,7 @@ function collectNodeFindings(v, node, out) {
|
|
|
1624
1875
|
const result = v.validate("node", toNodeForSchema(node));
|
|
1625
1876
|
if (result.ok) return;
|
|
1626
1877
|
out.push({
|
|
1627
|
-
ruleId:
|
|
1878
|
+
ruleId: ID11,
|
|
1628
1879
|
severity: "error",
|
|
1629
1880
|
nodeIds: [node.path],
|
|
1630
1881
|
message: tx(VALIDATE_ALL_TEXTS.nodeFailure, {
|
|
@@ -1638,7 +1889,7 @@ function collectLinkFindings(v, link2, out) {
|
|
|
1638
1889
|
const result = v.validate("link", toLinkForSchema(link2));
|
|
1639
1890
|
if (result.ok) return;
|
|
1640
1891
|
out.push({
|
|
1641
|
-
ruleId:
|
|
1892
|
+
ruleId: ID11,
|
|
1642
1893
|
severity: "error",
|
|
1643
1894
|
nodeIds: [link2.source],
|
|
1644
1895
|
message: tx(VALIDATE_ALL_TEXTS.linkFailure, {
|
|
@@ -1699,6 +1950,7 @@ var builtInBundles = [
|
|
|
1699
1950
|
granularity: "extension",
|
|
1700
1951
|
extensions: [
|
|
1701
1952
|
externalUrlCounterExtractor,
|
|
1953
|
+
markdownLinkExtractor,
|
|
1702
1954
|
triggerCollisionRule,
|
|
1703
1955
|
brokenRefRule,
|
|
1704
1956
|
supersededRule,
|
|
@@ -2706,7 +2958,7 @@ var AsyncMutex = class {
|
|
|
2706
2958
|
this.#locked = true;
|
|
2707
2959
|
return;
|
|
2708
2960
|
}
|
|
2709
|
-
await new Promise((
|
|
2961
|
+
await new Promise((resolve21) => this.#waiters.push(resolve21));
|
|
2710
2962
|
this.#locked = true;
|
|
2711
2963
|
}
|
|
2712
2964
|
unlock() {
|
|
@@ -3953,6 +4205,7 @@ async function loadNodeEnrichments(db, nodePath) {
|
|
|
3953
4205
|
}));
|
|
3954
4206
|
}
|
|
3955
4207
|
function parseJsonObject(s) {
|
|
4208
|
+
if (s === null || s === void 0) return {};
|
|
3956
4209
|
const parsed = JSON.parse(s);
|
|
3957
4210
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
3958
4211
|
return parsed;
|
|
@@ -3960,6 +4213,7 @@ function parseJsonObject(s) {
|
|
|
3960
4213
|
return {};
|
|
3961
4214
|
}
|
|
3962
4215
|
function parseJsonArray(s) {
|
|
4216
|
+
if (s === null || s === void 0) return [];
|
|
3963
4217
|
const parsed = JSON.parse(s);
|
|
3964
4218
|
return Array.isArray(parsed) ? parsed : [];
|
|
3965
4219
|
}
|
|
@@ -4970,6 +5224,7 @@ function formatErrorMessage(err) {
|
|
|
4970
5224
|
// cli/i18n/config.texts.ts
|
|
4971
5225
|
var CONFIG_TEXTS = {
|
|
4972
5226
|
unknownKey: "Unknown config key: {{key}}\n",
|
|
5227
|
+
unknownKeySuggestion: "Did you mean {{suggestions}}?\n",
|
|
4973
5228
|
valueWithLayer: "{{value}} (from {{layer}})\n",
|
|
4974
5229
|
invalidAfterSet: "Invalid config after set: {{errors}}\n",
|
|
4975
5230
|
setWritten: "{{key}} = {{value}} (wrote {{path}})\n",
|
|
@@ -4999,6 +5254,29 @@ function assertSafeSegments(segments, key) {
|
|
|
4999
5254
|
if (FORBIDDEN_SEGMENTS.has(seg)) throw new ForbiddenSegmentError(seg, key);
|
|
5000
5255
|
}
|
|
5001
5256
|
}
|
|
5257
|
+
function isPlainObject2(v) {
|
|
5258
|
+
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
5259
|
+
}
|
|
5260
|
+
function enumerateConfigPaths(obj, prefix = "") {
|
|
5261
|
+
if (!isPlainObject2(obj)) return prefix ? [prefix] : [];
|
|
5262
|
+
const out = [];
|
|
5263
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
5264
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
5265
|
+
if (isPlainObject2(value)) {
|
|
5266
|
+
out.push(...enumerateConfigPaths(value, path));
|
|
5267
|
+
} else {
|
|
5268
|
+
out.push(path);
|
|
5269
|
+
}
|
|
5270
|
+
}
|
|
5271
|
+
return out;
|
|
5272
|
+
}
|
|
5273
|
+
function suggestConfigKey(effective, typed) {
|
|
5274
|
+
const candidates = enumerateConfigPaths(effective);
|
|
5275
|
+
const matches = closestMatches(typed, candidates, { topN: 3, maxDistance: 3 });
|
|
5276
|
+
if (matches.length === 0) return null;
|
|
5277
|
+
const formatted = matches.map((m) => `'${m}'`).join(", ");
|
|
5278
|
+
return tx(CONFIG_TEXTS.unknownKeySuggestion, { suggestions: formatted });
|
|
5279
|
+
}
|
|
5002
5280
|
function getAtPath(obj, dotPath) {
|
|
5003
5281
|
const segments = dotPath.split(".").filter(Boolean);
|
|
5004
5282
|
assertSafeSegments(segments, dotPath);
|
|
@@ -5100,6 +5378,17 @@ function tryLoadConfig(opts, stderr) {
|
|
|
5100
5378
|
return { ok: false, exitCode: ExitCode.Error };
|
|
5101
5379
|
}
|
|
5102
5380
|
}
|
|
5381
|
+
function safeGetAtPath(effective, key, stderr) {
|
|
5382
|
+
try {
|
|
5383
|
+
return { ok: true, value: getAtPath(effective, key) };
|
|
5384
|
+
} catch (err) {
|
|
5385
|
+
if (err instanceof ForbiddenSegmentError) {
|
|
5386
|
+
stderr.write(tx(CONFIG_TEXTS.forbiddenKeySegment, { segment: err.segment, key: err.key }));
|
|
5387
|
+
return { ok: false, exitCode: ExitCode.Error };
|
|
5388
|
+
}
|
|
5389
|
+
throw err;
|
|
5390
|
+
}
|
|
5391
|
+
}
|
|
5103
5392
|
function* iterDotPaths(obj, prefix = "") {
|
|
5104
5393
|
if (obj === null || typeof obj !== "object" || Array.isArray(obj)) {
|
|
5105
5394
|
if (prefix) yield [prefix, obj];
|
|
@@ -5177,18 +5466,13 @@ var ConfigGetCommand = class extends SmCommand {
|
|
|
5177
5466
|
if (!result.ok) return result.exitCode;
|
|
5178
5467
|
const { effective, warnings } = result.loaded;
|
|
5179
5468
|
for (const w of warnings) this.context.stderr.write(w + "\n");
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
} catch (err) {
|
|
5184
|
-
if (err instanceof ForbiddenSegmentError) {
|
|
5185
|
-
this.context.stderr.write(tx(CONFIG_TEXTS.forbiddenKeySegment, { segment: err.segment, key: err.key }));
|
|
5186
|
-
return ExitCode.Error;
|
|
5187
|
-
}
|
|
5188
|
-
throw err;
|
|
5189
|
-
}
|
|
5469
|
+
const lookup = safeGetAtPath(effective, this.key, this.context.stderr);
|
|
5470
|
+
if (!lookup.ok) return lookup.exitCode;
|
|
5471
|
+
const { value } = lookup;
|
|
5190
5472
|
if (value === void 0) {
|
|
5191
5473
|
this.context.stderr.write(tx(CONFIG_TEXTS.unknownKey, { key: this.key }));
|
|
5474
|
+
const suggestion = suggestConfigKey(effective, this.key);
|
|
5475
|
+
if (suggestion !== null) this.context.stderr.write(suggestion);
|
|
5192
5476
|
return ExitCode.NotFound;
|
|
5193
5477
|
}
|
|
5194
5478
|
if (this.json) {
|
|
@@ -6051,9 +6335,9 @@ var DB_TEXTS = {
|
|
|
6051
6335
|
migrateKernelUpToDate: "kernel \xB7 Already up to date.\n",
|
|
6052
6336
|
migrateKernelApplied: "kernel \xB7 Applied {{count}} migration(s)\n",
|
|
6053
6337
|
migrateKernelAppliedWithBackup: "kernel \xB7 Applied {{count}} migration(s) \xB7 backup: {{backupPath}}\n",
|
|
6054
|
-
// --- shell
|
|
6338
|
+
// --- shell (system sqlite3 binary required for the interactive REPL) ---
|
|
6055
6339
|
shellSqlite3NotFound: "sqlite3 binary not found on PATH. Install it (macOS: brew install sqlite; Debian/Ubuntu: apt install sqlite3) or use `sm db dump` for read-only inspection.\n",
|
|
6056
|
-
|
|
6340
|
+
// --- dump (pure node:sqlite, no external binary) ----------------------
|
|
6057
6341
|
dumpInvalidTable: "--tables: refusing non-identifier name {{table}}. Table names must match [a-zA-Z_][a-zA-Z0-9_]*\n",
|
|
6058
6342
|
// --- plugin migration runner -----------------------------------------
|
|
6059
6343
|
pluginMigrateFailure: "plugin {{pluginId}} \xB7 {{reason}}\n",
|
|
@@ -6344,18 +6628,12 @@ var DbDumpCommand = class extends SmCommand {
|
|
|
6344
6628
|
static usage = Command5.Usage({
|
|
6345
6629
|
category: "Database",
|
|
6346
6630
|
description: "SQL dump to stdout.",
|
|
6347
|
-
details: "Read-only. Use --tables <names...> to limit the dump to specific tables."
|
|
6631
|
+
details: "Read-only. Pure node:sqlite \u2014 no external `sqlite3` binary required. Use --tables <names...> to limit the dump to specific tables."
|
|
6348
6632
|
});
|
|
6349
6633
|
tables = Option5.Array("--tables", { required: false });
|
|
6350
|
-
// CLI orchestrator: each branch (db existence, per-table identifier
|
|
6351
|
-
// gate, sqlite3-not-found fallback, exit-status passthrough) is a
|
|
6352
|
-
// single dispatcher decision. Splitting per branch scatters the gate
|
|
6353
|
-
// away from the value it gates.
|
|
6354
|
-
// eslint-disable-next-line complexity
|
|
6355
6634
|
async run() {
|
|
6356
6635
|
const path = resolveDbPath({ global: this.global, db: this.db, ...defaultRuntimeContext() });
|
|
6357
6636
|
if (!assertDbExists(path, this.context.stderr)) return ExitCode.NotFound;
|
|
6358
|
-
const args2 = ["-readonly", path, ".dump"];
|
|
6359
6637
|
if (this.tables && this.tables.length > 0) {
|
|
6360
6638
|
for (const t of this.tables) {
|
|
6361
6639
|
if (!SAFE_SQL_IDENTIFIER_RE.test(t)) {
|
|
@@ -6363,16 +6641,65 @@ var DbDumpCommand = class extends SmCommand {
|
|
|
6363
6641
|
return ExitCode.Error;
|
|
6364
6642
|
}
|
|
6365
6643
|
}
|
|
6366
|
-
args2.push(...this.tables);
|
|
6367
6644
|
}
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6645
|
+
try {
|
|
6646
|
+
dumpDatabaseToStream(path, this.context.stdout, this.tables ?? null);
|
|
6647
|
+
return ExitCode.Ok;
|
|
6648
|
+
} catch (err) {
|
|
6649
|
+
this.context.stderr.write(`sm db dump: ${err.message}
|
|
6650
|
+
`);
|
|
6371
6651
|
return ExitCode.Error;
|
|
6372
6652
|
}
|
|
6373
|
-
return result.status ?? 0;
|
|
6374
6653
|
}
|
|
6375
6654
|
};
|
|
6655
|
+
function dumpDatabaseToStream(dbPath, out, tables) {
|
|
6656
|
+
const db = new DatabaseSync4(dbPath, { readOnly: true });
|
|
6657
|
+
try {
|
|
6658
|
+
out.write("PRAGMA foreign_keys=OFF;\n");
|
|
6659
|
+
out.write("BEGIN TRANSACTION;\n");
|
|
6660
|
+
const objects = listSchemaObjects(db, tables);
|
|
6661
|
+
for (const obj of objects) {
|
|
6662
|
+
if (!obj.sql) continue;
|
|
6663
|
+
out.write(`${obj.sql};
|
|
6664
|
+
`);
|
|
6665
|
+
}
|
|
6666
|
+
for (const obj of objects) {
|
|
6667
|
+
if (obj.type !== "table") continue;
|
|
6668
|
+
writeTableData(db, out, obj.name);
|
|
6669
|
+
}
|
|
6670
|
+
out.write("COMMIT;\n");
|
|
6671
|
+
} finally {
|
|
6672
|
+
db.close();
|
|
6673
|
+
}
|
|
6674
|
+
}
|
|
6675
|
+
function listSchemaObjects(db, tables) {
|
|
6676
|
+
const baseQuery = "SELECT type, name, sql FROM sqlite_master WHERE type IN ('table','index','trigger','view') AND name NOT LIKE 'sqlite_%'";
|
|
6677
|
+
if (tables === null || tables.length === 0) {
|
|
6678
|
+
return db.prepare(`${baseQuery} ORDER BY rootpage`).all();
|
|
6679
|
+
}
|
|
6680
|
+
const placeholders = tables.map(() => "?").join(",");
|
|
6681
|
+
const sql4 = `${baseQuery} AND (name IN (${placeholders}) OR tbl_name IN (${placeholders})) ORDER BY rootpage`;
|
|
6682
|
+
return db.prepare(sql4).all(...tables, ...tables);
|
|
6683
|
+
}
|
|
6684
|
+
function writeTableData(db, out, tableName) {
|
|
6685
|
+
const quoted = `"${tableName.replace(/"/g, '""')}"`;
|
|
6686
|
+
for (const row of db.prepare(`SELECT * FROM ${quoted}`).iterate()) {
|
|
6687
|
+
const values = Object.values(row).map(formatSqlValue).join(",");
|
|
6688
|
+
out.write(`INSERT INTO ${quoted} VALUES(${values});
|
|
6689
|
+
`);
|
|
6690
|
+
}
|
|
6691
|
+
}
|
|
6692
|
+
function formatSqlNumber(value) {
|
|
6693
|
+
return Number.isFinite(value) ? String(value) : "NULL";
|
|
6694
|
+
}
|
|
6695
|
+
function formatSqlValue(value) {
|
|
6696
|
+
if (value === null || value === void 0) return "NULL";
|
|
6697
|
+
if (typeof value === "number") return formatSqlNumber(value);
|
|
6698
|
+
if (typeof value === "bigint") return value.toString();
|
|
6699
|
+
if (typeof value === "boolean") return value ? "1" : "0";
|
|
6700
|
+
if (value instanceof Uint8Array) return `X'${Buffer.from(value).toString("hex")}'`;
|
|
6701
|
+
return `'${String(value).replace(/'/g, "''")}'`;
|
|
6702
|
+
}
|
|
6376
6703
|
var DbMigrateCommand = class extends SmCommand {
|
|
6377
6704
|
static paths = [["db", "migrate"]];
|
|
6378
6705
|
static usage = Command5.Usage({
|
|
@@ -6762,18 +7089,19 @@ var ExportCommand = class extends SmCommand {
|
|
|
6762
7089
|
(POSIX glob \u2014 \`*\` matches a single segment, \`**\` matches across
|
|
6763
7090
|
segments).
|
|
6764
7091
|
|
|
6765
|
-
Pass an empty query (\`""\`)
|
|
7092
|
+
Pass an empty query (\`""\`) \u2014 or omit the argument entirely \u2014 to
|
|
7093
|
+
export every node.
|
|
6766
7094
|
|
|
6767
7095
|
Run \`sm scan\` first to populate the DB.
|
|
6768
7096
|
`,
|
|
6769
7097
|
examples: [
|
|
7098
|
+
["Whole graph (no query)", "$0 export --format md"],
|
|
6770
7099
|
["Every command node", '$0 export "kind=command" --format json'],
|
|
6771
7100
|
["Skills + agents with issues", '$0 export "kind=skill,agent has=issues" --format md'],
|
|
6772
|
-
["Files under a path glob", '$0 export "path=.claude/commands/**" --format json']
|
|
6773
|
-
["Whole graph as Markdown", '$0 export "" --format md']
|
|
7101
|
+
["Files under a path glob", '$0 export "path=.claude/commands/**" --format json']
|
|
6774
7102
|
]
|
|
6775
7103
|
});
|
|
6776
|
-
query = Option6.String({ required:
|
|
7104
|
+
query = Option6.String({ required: false });
|
|
6777
7105
|
format = Option6.String("--format", { required: false });
|
|
6778
7106
|
async run() {
|
|
6779
7107
|
const format = (this.format ?? "json").toLowerCase();
|
|
@@ -6798,7 +7126,7 @@ var ExportCommand = class extends SmCommand {
|
|
|
6798
7126
|
}
|
|
6799
7127
|
let parsedQuery;
|
|
6800
7128
|
try {
|
|
6801
|
-
parsedQuery = parseExportQuery(this.query);
|
|
7129
|
+
parsedQuery = parseExportQuery(this.query ?? "");
|
|
6802
7130
|
} catch (err) {
|
|
6803
7131
|
if (err instanceof ExportQueryError) {
|
|
6804
7132
|
this.context.stderr.write(tx(EXPORT_TEXTS.errorPrefix, { message: err.message }));
|
|
@@ -7025,16 +7353,108 @@ var GraphCommand = class extends SmCommand {
|
|
|
7025
7353
|
}
|
|
7026
7354
|
};
|
|
7027
7355
|
|
|
7356
|
+
// cli/commands/guide.ts
|
|
7357
|
+
import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
|
|
7358
|
+
import { writeFile } from "fs/promises";
|
|
7359
|
+
import { dirname as dirname9, join as join10, resolve as resolve13 } from "path";
|
|
7360
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
7361
|
+
import { Command as Command8, Option as Option8 } from "clipanion";
|
|
7362
|
+
|
|
7363
|
+
// cli/i18n/guide.texts.ts
|
|
7364
|
+
var GUIDE_TEXTS = {
|
|
7365
|
+
// Success — written to stdout after `<cwd>/sm-guide.md` is created.
|
|
7366
|
+
written: 'Listo. sm-guide.md creado en {{cwd}}. Abr\xED Claude Code ac\xE1 y decile "gu\xEDame" para arrancar la gu\xEDa interactiva.\n',
|
|
7367
|
+
// Refusal — `sm-guide.md` already exists and `--force` was not set.
|
|
7368
|
+
// Goes to stderr, exit code 2 (operational error per spec § Exit codes).
|
|
7369
|
+
alreadyExists: "sm guide: sm-guide.md ya existe en {{cwd}}. Us\xE1 `--force` para sobrescribir.\n",
|
|
7370
|
+
// I/O failure on write or on reading the bundled SKILL source.
|
|
7371
|
+
writeFailed: "sm guide: no se pudo escribir sm-guide.md: {{message}}\n",
|
|
7372
|
+
sourceMissing: "sm guide: no se pudo leer la gu\xEDa empaquetada (SKILL.md) desde la instalaci\xF3n. Reinstal\xE1 @skill-map/cli o report\xE1 el bug.\n"
|
|
7373
|
+
};
|
|
7374
|
+
|
|
7375
|
+
// cli/commands/guide.ts
|
|
7376
|
+
var SM_GUIDE_FILENAME = "sm-guide.md";
|
|
7377
|
+
var GuideCommand = class extends SmCommand {
|
|
7378
|
+
static paths = [["guide"]];
|
|
7379
|
+
static usage = Command8.Usage({
|
|
7380
|
+
category: "Setup",
|
|
7381
|
+
description: "Materialize the interactive tester guide (sm-guide.md) in the current directory.",
|
|
7382
|
+
details: `
|
|
7383
|
+
Drops the canonical SKILL.md content as ./sm-guide.md so a tester
|
|
7384
|
+
can open Claude Code in the cwd and trigger the sm-guide skill
|
|
7385
|
+
("gu\xEDame"). Top-level only \u2014 no subdirectory is created.
|
|
7386
|
+
|
|
7387
|
+
Does NOT require an initialized .skill-map/ project. Refuses to
|
|
7388
|
+
overwrite an existing sm-guide.md unless --force is passed.
|
|
7389
|
+
`,
|
|
7390
|
+
examples: [
|
|
7391
|
+
["Materialize the guide in the cwd", "$0 guide"],
|
|
7392
|
+
["Overwrite an existing sm-guide.md", "$0 guide --force"]
|
|
7393
|
+
]
|
|
7394
|
+
});
|
|
7395
|
+
force = Option8.Boolean("--force", false, {
|
|
7396
|
+
description: "Overwrite an existing sm-guide.md without prompting."
|
|
7397
|
+
});
|
|
7398
|
+
async run() {
|
|
7399
|
+
const ctx = defaultRuntimeContext();
|
|
7400
|
+
const target = join10(ctx.cwd, SM_GUIDE_FILENAME);
|
|
7401
|
+
if (await pathExists(target) && !this.force) {
|
|
7402
|
+
this.context.stderr.write(tx(GUIDE_TEXTS.alreadyExists, { cwd: ctx.cwd }));
|
|
7403
|
+
return ExitCode.Error;
|
|
7404
|
+
}
|
|
7405
|
+
let body;
|
|
7406
|
+
try {
|
|
7407
|
+
body = loadBundledGuideText();
|
|
7408
|
+
} catch {
|
|
7409
|
+
this.context.stderr.write(GUIDE_TEXTS.sourceMissing);
|
|
7410
|
+
return ExitCode.Error;
|
|
7411
|
+
}
|
|
7412
|
+
try {
|
|
7413
|
+
await writeFile(target, body);
|
|
7414
|
+
} catch (err) {
|
|
7415
|
+
this.context.stderr.write(
|
|
7416
|
+
tx(GUIDE_TEXTS.writeFailed, { message: formatErrorMessage(err) })
|
|
7417
|
+
);
|
|
7418
|
+
return ExitCode.Error;
|
|
7419
|
+
}
|
|
7420
|
+
this.context.stdout.write(tx(GUIDE_TEXTS.written, { cwd: ctx.cwd }));
|
|
7421
|
+
return ExitCode.Ok;
|
|
7422
|
+
}
|
|
7423
|
+
};
|
|
7424
|
+
var cachedGuide = null;
|
|
7425
|
+
function loadBundledGuideText() {
|
|
7426
|
+
if (cachedGuide !== null) return cachedGuide;
|
|
7427
|
+
cachedGuide = readGuideFromDisk();
|
|
7428
|
+
return cachedGuide;
|
|
7429
|
+
}
|
|
7430
|
+
function readGuideFromDisk() {
|
|
7431
|
+
const here = dirname9(fileURLToPath5(import.meta.url));
|
|
7432
|
+
const candidates = [
|
|
7433
|
+
// dev: src/cli/commands/ → repo-root .claude/skills/sm-guide/SKILL.md
|
|
7434
|
+
resolve13(here, "../../../.claude/skills/sm-guide/SKILL.md"),
|
|
7435
|
+
// bundled: dist/cli.js → dist/cli/guide/sm-guide.md (sibling)
|
|
7436
|
+
resolve13(here, "cli/guide/sm-guide.md"),
|
|
7437
|
+
// bundled fallback: any-depth → cli/guide/sm-guide.md
|
|
7438
|
+
resolve13(here, "../cli/guide/sm-guide.md")
|
|
7439
|
+
];
|
|
7440
|
+
for (const candidate of candidates) {
|
|
7441
|
+
if (existsSync12(candidate)) {
|
|
7442
|
+
return readFileSync10(candidate, "utf8");
|
|
7443
|
+
}
|
|
7444
|
+
}
|
|
7445
|
+
throw new Error(`SKILL.md not found in any candidate location (last tried: ${candidates[candidates.length - 1]})`);
|
|
7446
|
+
}
|
|
7447
|
+
|
|
7028
7448
|
// cli/commands/help.ts
|
|
7029
|
-
import { readFileSync as
|
|
7449
|
+
import { readFileSync as readFileSync11 } from "fs";
|
|
7030
7450
|
import { createRequire as createRequire4 } from "module";
|
|
7031
|
-
import { resolve as
|
|
7032
|
-
import { Command as
|
|
7451
|
+
import { resolve as resolve14 } from "path";
|
|
7452
|
+
import { Command as Command9, Option as Option9 } from "clipanion";
|
|
7033
7453
|
|
|
7034
7454
|
// package.json
|
|
7035
7455
|
var package_default = {
|
|
7036
7456
|
name: "@skill-map/cli",
|
|
7037
|
-
version: "0.
|
|
7457
|
+
version: "0.14.0",
|
|
7038
7458
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
7039
7459
|
license: "MIT",
|
|
7040
7460
|
type: "module",
|
|
@@ -7093,7 +7513,7 @@ var package_default = {
|
|
|
7093
7513
|
},
|
|
7094
7514
|
dependencies: {
|
|
7095
7515
|
"@hono/node-server": "2.0.1",
|
|
7096
|
-
"@skill-map/spec": "
|
|
7516
|
+
"@skill-map/spec": "0.14.1",
|
|
7097
7517
|
ajv: "8.18.0",
|
|
7098
7518
|
"ajv-formats": "3.0.1",
|
|
7099
7519
|
chokidar: "5.0.0",
|
|
@@ -7210,9 +7630,9 @@ var HELP_TEXTS = {
|
|
|
7210
7630
|
};
|
|
7211
7631
|
|
|
7212
7632
|
// cli/commands/help.ts
|
|
7213
|
-
var HelpCommand = class extends
|
|
7633
|
+
var HelpCommand = class extends Command9 {
|
|
7214
7634
|
static paths = [["help"]];
|
|
7215
|
-
static usage =
|
|
7635
|
+
static usage = Command9.Usage({
|
|
7216
7636
|
category: "Introspection",
|
|
7217
7637
|
description: "Self-describing introspection. --format human|md|json.",
|
|
7218
7638
|
details: `
|
|
@@ -7226,8 +7646,8 @@ var HelpCommand = class extends Command8 {
|
|
|
7226
7646
|
json \u2014 structured surface dump per spec/cli-contract.md.
|
|
7227
7647
|
`
|
|
7228
7648
|
});
|
|
7229
|
-
verbParts =
|
|
7230
|
-
format =
|
|
7649
|
+
verbParts = Option9.Rest({ required: 0 });
|
|
7650
|
+
format = Option9.String("--format", "human");
|
|
7231
7651
|
async execute() {
|
|
7232
7652
|
const format = normalizeFormat(this.format);
|
|
7233
7653
|
if (!format) {
|
|
@@ -7349,8 +7769,8 @@ function resolveSpecVersion() {
|
|
|
7349
7769
|
try {
|
|
7350
7770
|
const req = createRequire4(import.meta.url);
|
|
7351
7771
|
const indexPath = req.resolve("@skill-map/spec/index.json");
|
|
7352
|
-
const pkgPath =
|
|
7353
|
-
const pkg = JSON.parse(
|
|
7772
|
+
const pkgPath = resolve14(indexPath, "..", "package.json");
|
|
7773
|
+
const pkg = JSON.parse(readFileSync11(pkgPath, "utf8"));
|
|
7354
7774
|
return pkg.version;
|
|
7355
7775
|
} catch {
|
|
7356
7776
|
return "unknown";
|
|
@@ -7545,7 +7965,7 @@ function renderCompactOverview(verbs) {
|
|
|
7545
7965
|
lines.push(HELP_TEXTS.compactFooter);
|
|
7546
7966
|
return lines.join("\n") + "\n";
|
|
7547
7967
|
}
|
|
7548
|
-
var RootHelpCommand = class extends
|
|
7968
|
+
var RootHelpCommand = class extends Command9 {
|
|
7549
7969
|
static paths = [["-h"], ["--help"]];
|
|
7550
7970
|
async execute() {
|
|
7551
7971
|
const rawDefs = this.cli.definitions();
|
|
@@ -7601,13 +8021,13 @@ function registeredVerbPaths(cli2) {
|
|
|
7601
8021
|
}
|
|
7602
8022
|
|
|
7603
8023
|
// cli/commands/init.ts
|
|
7604
|
-
import { mkdir as mkdir2, readFile as readFile2, writeFile } from "fs/promises";
|
|
7605
|
-
import { join as
|
|
7606
|
-
import { Command as
|
|
8024
|
+
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
8025
|
+
import { join as join11 } from "path";
|
|
8026
|
+
import { Command as Command10, Option as Option10 } from "clipanion";
|
|
7607
8027
|
|
|
7608
8028
|
// kernel/orchestrator.ts
|
|
7609
8029
|
import { createHash } from "crypto";
|
|
7610
|
-
import { existsSync as
|
|
8030
|
+
import { existsSync as existsSync13, statSync as statSync3 } from "fs";
|
|
7611
8031
|
import { Tiktoken } from "js-tiktoken/lite";
|
|
7612
8032
|
import cl100k_base from "js-tiktoken/ranks/cl100k_base";
|
|
7613
8033
|
import yaml2 from "js-yaml";
|
|
@@ -7742,7 +8162,7 @@ function validateRoots(roots) {
|
|
|
7742
8162
|
throw new Error(ORCHESTRATOR_TEXTS.runScanRootEmptyArray);
|
|
7743
8163
|
}
|
|
7744
8164
|
for (const root of roots) {
|
|
7745
|
-
if (!
|
|
8165
|
+
if (!existsSync13(root) || !statSync3(root).isDirectory()) {
|
|
7746
8166
|
throw new Error(tx(ORCHESTRATOR_TEXTS.runScanRootMissing, { root }));
|
|
7747
8167
|
}
|
|
7748
8168
|
}
|
|
@@ -8518,10 +8938,10 @@ function recomputeExternalRefsCount(nodes, externalLinks, cachedPaths) {
|
|
|
8518
8938
|
}
|
|
8519
8939
|
|
|
8520
8940
|
// kernel/scan/watcher.ts
|
|
8521
|
-
import { resolve as
|
|
8941
|
+
import { resolve as resolve15, relative as relative4, sep as sep2 } from "path";
|
|
8522
8942
|
import chokidar from "chokidar";
|
|
8523
8943
|
function createChokidarWatcher(opts) {
|
|
8524
|
-
const absRoots = opts.roots.map((r) =>
|
|
8944
|
+
const absRoots = opts.roots.map((r) => resolve15(opts.cwd, r));
|
|
8525
8945
|
const ignoreFilter = opts.ignoreFilter;
|
|
8526
8946
|
const ignored = ignoreFilter ? (path) => {
|
|
8527
8947
|
const rel = relativePathFromRoots(path, absRoots);
|
|
@@ -8767,7 +9187,7 @@ function createCliProgressEmitter(stderr) {
|
|
|
8767
9187
|
// cli/commands/init.ts
|
|
8768
9188
|
var InitCommand = class extends SmCommand {
|
|
8769
9189
|
static paths = [["init"]];
|
|
8770
|
-
static usage =
|
|
9190
|
+
static usage = Command10.Usage({
|
|
8771
9191
|
category: "Setup",
|
|
8772
9192
|
description: "Bootstrap the current scope: scaffold .skill-map/, provision DB, run first scan.",
|
|
8773
9193
|
details: `
|
|
@@ -8791,16 +9211,16 @@ var InitCommand = class extends SmCommand {
|
|
|
8791
9211
|
["Preview what would be created", "$0 init --dry-run"]
|
|
8792
9212
|
]
|
|
8793
9213
|
});
|
|
8794
|
-
noScan =
|
|
9214
|
+
noScan = Option10.Boolean("--no-scan", false, {
|
|
8795
9215
|
description: "Skip the first scan after scaffolding."
|
|
8796
9216
|
});
|
|
8797
|
-
force =
|
|
9217
|
+
force = Option10.Boolean("--force", false, {
|
|
8798
9218
|
description: "Overwrite an existing settings.json / settings.local.json / .skill-mapignore."
|
|
8799
9219
|
});
|
|
8800
|
-
strict =
|
|
9220
|
+
strict = Option10.Boolean("--strict", false, {
|
|
8801
9221
|
description: "Strict mode: fail on any layered-loader warning AND promote frontmatter warnings to errors during the first scan. Same flag as sm scan / sm config."
|
|
8802
9222
|
});
|
|
8803
|
-
dryRun =
|
|
9223
|
+
dryRun = Option10.Boolean("-n,--dry-run", false, {
|
|
8804
9224
|
description: "Preview the scope provisioning without touching the filesystem or the DB. Honours --force for the would-overwrite preview. Skips the first scan unconditionally \u2014 dry-run never persists."
|
|
8805
9225
|
});
|
|
8806
9226
|
// CLI orchestrator: paths setup + dry-run branch (delegated to
|
|
@@ -8811,7 +9231,7 @@ var InitCommand = class extends SmCommand {
|
|
|
8811
9231
|
async run() {
|
|
8812
9232
|
const ctx = defaultRuntimeContext();
|
|
8813
9233
|
const scopeRoot = this.global ? ctx.homedir : ctx.cwd;
|
|
8814
|
-
const skillMapDir =
|
|
9234
|
+
const skillMapDir = join11(scopeRoot, SKILL_MAP_DIR);
|
|
8815
9235
|
const settingsPath = defaultSettingsPath(scopeRoot);
|
|
8816
9236
|
const localPath = defaultLocalSettingsPath(scopeRoot);
|
|
8817
9237
|
const ignorePath = defaultIgnoreFilePath(scopeRoot);
|
|
@@ -8835,17 +9255,17 @@ var InitCommand = class extends SmCommand {
|
|
|
8835
9255
|
return ExitCode.Ok;
|
|
8836
9256
|
}
|
|
8837
9257
|
await mkdir2(skillMapDir, { recursive: true });
|
|
8838
|
-
await
|
|
9258
|
+
await writeFile2(settingsPath, JSON.stringify({ schemaVersion: 1 }, null, 2) + "\n");
|
|
8839
9259
|
if (!await pathExists(localPath) || this.force) {
|
|
8840
|
-
await
|
|
9260
|
+
await writeFile2(localPath, "{}\n");
|
|
8841
9261
|
}
|
|
8842
9262
|
if (!await pathExists(ignorePath) || this.force) {
|
|
8843
|
-
await
|
|
9263
|
+
await writeFile2(ignorePath, loadBundledIgnoreText());
|
|
8844
9264
|
}
|
|
8845
9265
|
if (!this.global) {
|
|
8846
9266
|
const updated = await ensureGitignoreEntries(scopeRoot, GITIGNORE_ENTRIES);
|
|
8847
9267
|
if (updated) {
|
|
8848
|
-
const gitignorePath =
|
|
9268
|
+
const gitignorePath = join11(scopeRoot, ".gitignore");
|
|
8849
9269
|
this.context.stdout.write(
|
|
8850
9270
|
GITIGNORE_ENTRIES.length === 1 ? tx(INIT_TEXTS.gitignoreUpdatedSingular, { path: gitignorePath }) : tx(INIT_TEXTS.gitignoreUpdatedPlural, {
|
|
8851
9271
|
path: gitignorePath,
|
|
@@ -8884,7 +9304,7 @@ async function dryRunFileMessage(path) {
|
|
|
8884
9304
|
}
|
|
8885
9305
|
async function writeDryRunGitignorePlan(stdout, scopeRoot) {
|
|
8886
9306
|
const wouldAdd = await previewGitignoreEntries(scopeRoot, GITIGNORE_ENTRIES);
|
|
8887
|
-
const gitignorePath =
|
|
9307
|
+
const gitignorePath = join11(scopeRoot, ".gitignore");
|
|
8888
9308
|
if (wouldAdd.length === 0) {
|
|
8889
9309
|
stdout.write(tx(INIT_TEXTS.dryRunWouldLeaveGitignoreUnchanged, { path: gitignorePath }));
|
|
8890
9310
|
} else if (wouldAdd.length === 1) {
|
|
@@ -8959,7 +9379,7 @@ async function runFirstScan(scopeRoot, homedir2, dbPath, strict, stdout, stderr)
|
|
|
8959
9379
|
return hasErrors ? ExitCode.Issues : ExitCode.Ok;
|
|
8960
9380
|
}
|
|
8961
9381
|
async function previewGitignoreEntries(scopeRoot, entries) {
|
|
8962
|
-
const path =
|
|
9382
|
+
const path = join11(scopeRoot, ".gitignore");
|
|
8963
9383
|
const body = await pathExists(path) ? await readFile2(path, "utf8") : "";
|
|
8964
9384
|
const present = new Set(
|
|
8965
9385
|
body.split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"))
|
|
@@ -8967,7 +9387,7 @@ async function previewGitignoreEntries(scopeRoot, entries) {
|
|
|
8967
9387
|
return entries.filter((entry) => !present.has(entry));
|
|
8968
9388
|
}
|
|
8969
9389
|
async function ensureGitignoreEntries(scopeRoot, entries) {
|
|
8970
|
-
const path =
|
|
9390
|
+
const path = join11(scopeRoot, ".gitignore");
|
|
8971
9391
|
let body = "";
|
|
8972
9392
|
if (await pathExists(path)) {
|
|
8973
9393
|
body = await readFile2(path, "utf8");
|
|
@@ -8984,12 +9404,12 @@ async function ensureGitignoreEntries(scopeRoot, entries) {
|
|
|
8984
9404
|
present.add(entry);
|
|
8985
9405
|
changed = true;
|
|
8986
9406
|
}
|
|
8987
|
-
if (changed) await
|
|
9407
|
+
if (changed) await writeFile2(path, body);
|
|
8988
9408
|
return changed;
|
|
8989
9409
|
}
|
|
8990
9410
|
|
|
8991
9411
|
// cli/commands/history.ts
|
|
8992
|
-
import { Command as
|
|
9412
|
+
import { Command as Command11, Option as Option11 } from "clipanion";
|
|
8993
9413
|
|
|
8994
9414
|
// cli/i18n/option-validators.texts.ts
|
|
8995
9415
|
var OPTION_VALIDATORS_TEXTS = {
|
|
@@ -9078,7 +9498,7 @@ function parseStatuses(input, stderr) {
|
|
|
9078
9498
|
}
|
|
9079
9499
|
var HistoryCommand = class extends SmCommand {
|
|
9080
9500
|
static paths = [["history"]];
|
|
9081
|
-
static usage =
|
|
9501
|
+
static usage = Command11.Usage({
|
|
9082
9502
|
category: "History",
|
|
9083
9503
|
description: "Filter execution records. --json emits an array conforming to execution-record.schema.json.",
|
|
9084
9504
|
details: `
|
|
@@ -9098,12 +9518,12 @@ var HistoryCommand = class extends SmCommand {
|
|
|
9098
9518
|
["Machine-readable, scoped to one node", "$0 history -n skills/foo.md --json"]
|
|
9099
9519
|
]
|
|
9100
9520
|
});
|
|
9101
|
-
node =
|
|
9102
|
-
action =
|
|
9103
|
-
status =
|
|
9104
|
-
since =
|
|
9105
|
-
until =
|
|
9106
|
-
limit =
|
|
9521
|
+
node = Option11.String("-n", { required: false });
|
|
9522
|
+
action = Option11.String("--action", { required: false });
|
|
9523
|
+
status = Option11.String("--status", { required: false });
|
|
9524
|
+
since = Option11.String("--since", { required: false });
|
|
9525
|
+
until = Option11.String("--until", { required: false });
|
|
9526
|
+
limit = Option11.String("--limit", { required: false });
|
|
9107
9527
|
// CLI list verb: many optional filter flags (`--node`, `--action`,
|
|
9108
9528
|
// `--status`, `--since`, `--until`, `--limit`, `--json`, `--quiet`)
|
|
9109
9529
|
// each adding a guarded mutation to the filter or render path. Each
|
|
@@ -9151,7 +9571,7 @@ var HistoryCommand = class extends SmCommand {
|
|
|
9151
9571
|
};
|
|
9152
9572
|
var HistoryStatsCommand = class extends SmCommand {
|
|
9153
9573
|
static paths = [["history", "stats"]];
|
|
9154
|
-
static usage =
|
|
9574
|
+
static usage = Command11.Usage({
|
|
9155
9575
|
category: "History",
|
|
9156
9576
|
description: "Aggregate counts, tokens, periods, top nodes, and error rates over state_executions. --json conforms to history-stats.schema.json.",
|
|
9157
9577
|
details: `
|
|
@@ -9169,10 +9589,10 @@ var HistoryStatsCommand = class extends SmCommand {
|
|
|
9169
9589
|
["Top 5 nodes, JSON", "$0 history stats --top 5 --json"]
|
|
9170
9590
|
]
|
|
9171
9591
|
});
|
|
9172
|
-
since =
|
|
9173
|
-
until =
|
|
9174
|
-
period =
|
|
9175
|
-
top =
|
|
9592
|
+
since = Option11.String("--since", { required: false });
|
|
9593
|
+
until = Option11.String("--until", { required: false });
|
|
9594
|
+
period = Option11.String("--period", { required: false });
|
|
9595
|
+
top = Option11.String("--top", { required: false });
|
|
9176
9596
|
// CLI stats verb: range parsing + window flags + period flag + JSON
|
|
9177
9597
|
// branch + per-period iteration. Each branch is a single-purpose
|
|
9178
9598
|
// gate; the data work lives in `aggregateHistoryStats`.
|
|
@@ -9353,11 +9773,11 @@ function formatRow(...cols) {
|
|
|
9353
9773
|
|
|
9354
9774
|
// cli/commands/jobs.ts
|
|
9355
9775
|
import { unlink } from "fs/promises";
|
|
9356
|
-
import { Command as
|
|
9776
|
+
import { Command as Command12, Option as Option12 } from "clipanion";
|
|
9357
9777
|
|
|
9358
9778
|
// kernel/jobs/orphan-files.ts
|
|
9359
9779
|
import { readdirSync as readdirSync6, statSync as statSync4 } from "fs";
|
|
9360
|
-
import { join as
|
|
9780
|
+
import { join as join12, resolve as resolve16 } from "path";
|
|
9361
9781
|
function findOrphanJobFiles(jobsDir, referencedPaths) {
|
|
9362
9782
|
let entries;
|
|
9363
9783
|
try {
|
|
@@ -9372,7 +9792,7 @@ function findOrphanJobFiles(jobsDir, referencedPaths) {
|
|
|
9372
9792
|
const orphans = [];
|
|
9373
9793
|
for (const name of entries) {
|
|
9374
9794
|
if (!name.endsWith(".md")) continue;
|
|
9375
|
-
const abs =
|
|
9795
|
+
const abs = resolve16(join12(jobsDir, name));
|
|
9376
9796
|
if (!referencedPaths.has(abs)) orphans.push(abs);
|
|
9377
9797
|
}
|
|
9378
9798
|
orphans.sort();
|
|
@@ -9401,7 +9821,7 @@ var JOBS_TEXTS = {
|
|
|
9401
9821
|
// cli/commands/jobs.ts
|
|
9402
9822
|
var JobPruneCommand = class extends SmCommand {
|
|
9403
9823
|
static paths = [["job", "prune"]];
|
|
9404
|
-
static usage =
|
|
9824
|
+
static usage = Command12.Usage({
|
|
9405
9825
|
category: "Jobs",
|
|
9406
9826
|
description: "Retention GC for completed / failed jobs (per config policy). --orphan-files removes MD files with no DB row.",
|
|
9407
9827
|
details: `
|
|
@@ -9428,10 +9848,10 @@ var JobPruneCommand = class extends SmCommand {
|
|
|
9428
9848
|
["Preview without touching the DB", "$0 job prune --dry-run --json"]
|
|
9429
9849
|
]
|
|
9430
9850
|
});
|
|
9431
|
-
orphanFiles =
|
|
9851
|
+
orphanFiles = Option12.Boolean("--orphan-files", false, {
|
|
9432
9852
|
description: "Also remove MD files in .skill-map/jobs/ that have no matching state_jobs row."
|
|
9433
9853
|
});
|
|
9434
|
-
dryRun =
|
|
9854
|
+
dryRun = Option12.Boolean("-n,--dry-run", false, {
|
|
9435
9855
|
description: "Report what would be pruned without touching the DB or filesystem."
|
|
9436
9856
|
});
|
|
9437
9857
|
async run() {
|
|
@@ -9548,7 +9968,7 @@ function formatPolicy(seconds) {
|
|
|
9548
9968
|
}
|
|
9549
9969
|
|
|
9550
9970
|
// cli/commands/list.ts
|
|
9551
|
-
import { Command as
|
|
9971
|
+
import { Command as Command13, Option as Option13 } from "clipanion";
|
|
9552
9972
|
|
|
9553
9973
|
// cli/i18n/list.texts.ts
|
|
9554
9974
|
var LIST_TEXTS = {
|
|
@@ -9576,7 +9996,7 @@ var SORT_BY = {
|
|
|
9576
9996
|
var PATH_COL_WIDTH = 50;
|
|
9577
9997
|
var ListCommand = class extends SmCommand {
|
|
9578
9998
|
static paths = [["list"]];
|
|
9579
|
-
static usage =
|
|
9999
|
+
static usage = Command13.Usage({
|
|
9580
10000
|
category: "Browse",
|
|
9581
10001
|
description: "Tabular listing of nodes. --json emits an array conforming to node.schema.json.",
|
|
9582
10002
|
details: `
|
|
@@ -9597,10 +10017,10 @@ var ListCommand = class extends SmCommand {
|
|
|
9597
10017
|
["Only nodes with issues, machine-readable", "$0 list --issue --json"]
|
|
9598
10018
|
]
|
|
9599
10019
|
});
|
|
9600
|
-
kind =
|
|
9601
|
-
issue =
|
|
9602
|
-
sortBy =
|
|
9603
|
-
limit =
|
|
10020
|
+
kind = Option13.String("--kind", { required: false });
|
|
10021
|
+
issue = Option13.Boolean("--issue", false);
|
|
10022
|
+
sortBy = Option13.String("--sort-by", { required: false });
|
|
10023
|
+
limit = Option13.String("--limit", { required: false });
|
|
9604
10024
|
async run() {
|
|
9605
10025
|
let sortColumn = "path";
|
|
9606
10026
|
let sortDirection = "asc";
|
|
@@ -9702,7 +10122,7 @@ function formatRow2(path, kind, out, inCount, ext, issues, bytes) {
|
|
|
9702
10122
|
}
|
|
9703
10123
|
|
|
9704
10124
|
// cli/commands/orphans.ts
|
|
9705
|
-
import { Command as
|
|
10125
|
+
import { Command as Command14, Option as Option14 } from "clipanion";
|
|
9706
10126
|
|
|
9707
10127
|
// cli/i18n/orphans.texts.ts
|
|
9708
10128
|
var ORPHANS_TEXTS = {
|
|
@@ -9757,7 +10177,7 @@ function isStringArray(v) {
|
|
|
9757
10177
|
}
|
|
9758
10178
|
var OrphansCommand = class extends SmCommand {
|
|
9759
10179
|
static paths = [["orphans"]];
|
|
9760
|
-
static usage =
|
|
10180
|
+
static usage = Command14.Usage({
|
|
9761
10181
|
category: "Browse",
|
|
9762
10182
|
description: "List orphan / auto-rename issues from the last scan. --json emits an array conforming to issue.schema.json.",
|
|
9763
10183
|
details: `
|
|
@@ -9772,7 +10192,7 @@ var OrphansCommand = class extends SmCommand {
|
|
|
9772
10192
|
["Just the ambiguous ones, JSON", "$0 orphans --kind ambiguous --json"]
|
|
9773
10193
|
]
|
|
9774
10194
|
});
|
|
9775
|
-
kind =
|
|
10195
|
+
kind = Option14.String("--kind", { required: false });
|
|
9776
10196
|
async run() {
|
|
9777
10197
|
let ruleFilter = null;
|
|
9778
10198
|
if (this.kind !== void 0) {
|
|
@@ -9810,7 +10230,7 @@ var OrphansCommand = class extends SmCommand {
|
|
|
9810
10230
|
};
|
|
9811
10231
|
var OrphansReconcileCommand = class extends SmCommand {
|
|
9812
10232
|
static paths = [["orphans", "reconcile"]];
|
|
9813
|
-
static usage =
|
|
10233
|
+
static usage = Command14.Usage({
|
|
9814
10234
|
category: "Browse",
|
|
9815
10235
|
description: "Migrate state_* FKs from an orphan path to a live node, resolving the orphan issue.",
|
|
9816
10236
|
details: `
|
|
@@ -9826,9 +10246,9 @@ var OrphansReconcileCommand = class extends SmCommand {
|
|
|
9826
10246
|
["Reattach orphan history", "$0 orphans reconcile skills/old.md --to skills/new.md"]
|
|
9827
10247
|
]
|
|
9828
10248
|
});
|
|
9829
|
-
orphanPath =
|
|
9830
|
-
to =
|
|
9831
|
-
dryRun =
|
|
10249
|
+
orphanPath = Option14.String({ required: true });
|
|
10250
|
+
to = Option14.String("--to", { required: true });
|
|
10251
|
+
dryRun = Option14.Boolean("-n,--dry-run", false);
|
|
9832
10252
|
async run() {
|
|
9833
10253
|
const dbPath = resolveDbPath({ global: this.global, db: this.db, ...defaultRuntimeContext() });
|
|
9834
10254
|
if (!assertDbExists(dbPath, this.context.stderr)) return ExitCode.NotFound;
|
|
@@ -9898,7 +10318,7 @@ var OrphansReconcileCommand = class extends SmCommand {
|
|
|
9898
10318
|
};
|
|
9899
10319
|
var OrphansUndoRenameCommand = class extends SmCommand {
|
|
9900
10320
|
static paths = [["orphans", "undo-rename"]];
|
|
9901
|
-
static usage =
|
|
10321
|
+
static usage = Command14.Usage({
|
|
9902
10322
|
category: "Browse",
|
|
9903
10323
|
description: "Reverse a medium- or ambiguous-confidence auto-rename. Migrates state_* FKs back, emits a new orphan on the prior path.",
|
|
9904
10324
|
details: `
|
|
@@ -9918,10 +10338,10 @@ var OrphansUndoRenameCommand = class extends SmCommand {
|
|
|
9918
10338
|
["Undo an ambiguous, picking a candidate", "$0 orphans undo-rename skills/new.md --from skills/old-a.md"]
|
|
9919
10339
|
]
|
|
9920
10340
|
});
|
|
9921
|
-
newPath =
|
|
9922
|
-
from =
|
|
9923
|
-
force =
|
|
9924
|
-
dryRun =
|
|
10341
|
+
newPath = Option14.String({ required: true });
|
|
10342
|
+
from = Option14.String("--from", { required: false });
|
|
10343
|
+
force = Option14.Boolean("--force", false);
|
|
10344
|
+
dryRun = Option14.Boolean("-n,--dry-run", false);
|
|
9925
10345
|
async run() {
|
|
9926
10346
|
const dbPath = resolveDbPath({ global: this.global, db: this.db, ...defaultRuntimeContext() });
|
|
9927
10347
|
if (!assertDbExists(dbPath, this.context.stderr)) return ExitCode.NotFound;
|
|
@@ -10085,9 +10505,9 @@ var ORPHANS_COMMANDS = [
|
|
|
10085
10505
|
];
|
|
10086
10506
|
|
|
10087
10507
|
// cli/commands/plugins.ts
|
|
10088
|
-
import { existsSync as
|
|
10089
|
-
import { join as
|
|
10090
|
-
import { Command as
|
|
10508
|
+
import { existsSync as existsSync14 } from "fs";
|
|
10509
|
+
import { join as join13, resolve as resolve17 } from "path";
|
|
10510
|
+
import { Command as Command15, Option as Option15 } from "clipanion";
|
|
10091
10511
|
|
|
10092
10512
|
// cli/i18n/plugins.texts.ts
|
|
10093
10513
|
var PLUGINS_TEXTS = {
|
|
@@ -10163,7 +10583,7 @@ var PLUGINS_TEXTS = {
|
|
|
10163
10583
|
|
|
10164
10584
|
// cli/commands/plugins.ts
|
|
10165
10585
|
function resolveSearchPaths2(opts, cwd, homedir2) {
|
|
10166
|
-
if (opts.pluginDir) return [
|
|
10586
|
+
if (opts.pluginDir) return [resolve17(opts.pluginDir)];
|
|
10167
10587
|
const ctx = { cwd, homedir: homedir2 };
|
|
10168
10588
|
const project = defaultProjectPluginsDir(ctx);
|
|
10169
10589
|
const user = defaultUserPluginsDir(ctx);
|
|
@@ -10232,12 +10652,12 @@ function builtInRows(resolveEnabled) {
|
|
|
10232
10652
|
}
|
|
10233
10653
|
var PluginsListCommand = class extends SmCommand {
|
|
10234
10654
|
static paths = [["plugins", "list"]];
|
|
10235
|
-
static usage =
|
|
10655
|
+
static usage = Command15.Usage({
|
|
10236
10656
|
category: "Plugins",
|
|
10237
10657
|
description: "List discovered plugins and their load status.",
|
|
10238
10658
|
details: "Scans <scope>/.skill-map/plugins and ~/.skill-map/plugins (or --plugin-dir <path>). Built-in bundles (claude, core) are listed alongside user plugins."
|
|
10239
10659
|
});
|
|
10240
|
-
pluginDir =
|
|
10660
|
+
pluginDir = Option15.String("--plugin-dir", { required: false });
|
|
10241
10661
|
async run() {
|
|
10242
10662
|
const plugins = await loadAll({ global: this.global, pluginDir: this.pluginDir });
|
|
10243
10663
|
const resolveEnabled = await buildResolver(this.global);
|
|
@@ -10299,12 +10719,12 @@ function renderPluginRow(p) {
|
|
|
10299
10719
|
}
|
|
10300
10720
|
var PluginsShowCommand = class extends SmCommand {
|
|
10301
10721
|
static paths = [["plugins", "show"]];
|
|
10302
|
-
static usage =
|
|
10722
|
+
static usage = Command15.Usage({
|
|
10303
10723
|
category: "Plugins",
|
|
10304
10724
|
description: "Show a single plugin's manifest + loaded extensions."
|
|
10305
10725
|
});
|
|
10306
|
-
id =
|
|
10307
|
-
pluginDir =
|
|
10726
|
+
id = Option15.String({ required: true });
|
|
10727
|
+
pluginDir = Option15.String("--plugin-dir", { required: false });
|
|
10308
10728
|
async run() {
|
|
10309
10729
|
const plugins = await loadAll({ global: this.global, pluginDir: this.pluginDir });
|
|
10310
10730
|
const resolveEnabled = await buildResolver(this.global);
|
|
@@ -10481,7 +10901,7 @@ function appendUnknownKindWarnings(out, extractorQualifiedId, applicableKinds, k
|
|
|
10481
10901
|
}
|
|
10482
10902
|
function expandHome(p, homedir2) {
|
|
10483
10903
|
if (p === "~") return homedir2;
|
|
10484
|
-
if (p.startsWith("~/")) return
|
|
10904
|
+
if (p.startsWith("~/")) return join13(homedir2, p.slice(2));
|
|
10485
10905
|
return p;
|
|
10486
10906
|
}
|
|
10487
10907
|
function collectExplorationDirWarnings(plugins, homedir2) {
|
|
@@ -10490,7 +10910,7 @@ function collectExplorationDirWarnings(plugins, homedir2) {
|
|
|
10490
10910
|
const dir = instance["explorationDir"];
|
|
10491
10911
|
if (typeof dir !== "string" || dir.length === 0) return;
|
|
10492
10912
|
const resolved = expandHome(dir, homedir2);
|
|
10493
|
-
if (!
|
|
10913
|
+
if (!existsSync14(resolved)) {
|
|
10494
10914
|
out.push({
|
|
10495
10915
|
providerQualifiedId: qualifiedExtensionId(pluginId, id),
|
|
10496
10916
|
explorationDir: dir,
|
|
@@ -10502,12 +10922,12 @@ function collectExplorationDirWarnings(plugins, homedir2) {
|
|
|
10502
10922
|
}
|
|
10503
10923
|
var PluginsDoctorCommand = class extends SmCommand {
|
|
10504
10924
|
static paths = [["plugins", "doctor"]];
|
|
10505
|
-
static usage =
|
|
10925
|
+
static usage = Command15.Usage({
|
|
10506
10926
|
category: "Plugins",
|
|
10507
10927
|
description: "Run the full load pass and summarise by failure mode.",
|
|
10508
10928
|
details: "Exit code 0 when every plugin loads or is intentionally disabled; 1 when any plugin is in an error / incompat state."
|
|
10509
10929
|
});
|
|
10510
|
-
pluginDir =
|
|
10930
|
+
pluginDir = Option15.String("--plugin-dir", { required: false });
|
|
10511
10931
|
// Doctor verb: counts by status + applicableKinds warnings +
|
|
10512
10932
|
// explorationDir warnings + bad-plugins issues, each with its own
|
|
10513
10933
|
// gated render. Branching is intrinsic to the multi-section diagnostic
|
|
@@ -10673,8 +11093,8 @@ function resolveToggleTarget(id, catalogue, verb) {
|
|
|
10673
11093
|
return { key: bundle.id };
|
|
10674
11094
|
}
|
|
10675
11095
|
var TogglePluginsBase = class extends SmCommand {
|
|
10676
|
-
all =
|
|
10677
|
-
id =
|
|
11096
|
+
all = Option15.Boolean("--all", false);
|
|
11097
|
+
id = Option15.String({ required: false });
|
|
10678
11098
|
// eslint-disable-next-line complexity
|
|
10679
11099
|
async toggle(enabled) {
|
|
10680
11100
|
const verb = enabled ? "enable" : "disable";
|
|
@@ -10725,7 +11145,7 @@ var TogglePluginsBase = class extends SmCommand {
|
|
|
10725
11145
|
};
|
|
10726
11146
|
var PluginsEnableCommand = class extends TogglePluginsBase {
|
|
10727
11147
|
static paths = [["plugins", "enable"]];
|
|
10728
|
-
static usage =
|
|
11148
|
+
static usage = Command15.Usage({
|
|
10729
11149
|
category: "Plugins",
|
|
10730
11150
|
description: "Enable a plugin (or --all). Persists in config_plugins.",
|
|
10731
11151
|
details: `
|
|
@@ -10747,7 +11167,7 @@ var PluginsEnableCommand = class extends TogglePluginsBase {
|
|
|
10747
11167
|
};
|
|
10748
11168
|
var PluginsDisableCommand = class extends TogglePluginsBase {
|
|
10749
11169
|
static paths = [["plugins", "disable"]];
|
|
10750
|
-
static usage =
|
|
11170
|
+
static usage = Command15.Usage({
|
|
10751
11171
|
category: "Plugins",
|
|
10752
11172
|
description: "Disable a plugin (or --all). Persists in config_plugins; does not delete files.",
|
|
10753
11173
|
details: `
|
|
@@ -10783,8 +11203,8 @@ var PLUGIN_COMMANDS = [
|
|
|
10783
11203
|
|
|
10784
11204
|
// cli/commands/refresh.ts
|
|
10785
11205
|
import { readFile as readFile3 } from "fs/promises";
|
|
10786
|
-
import { resolve as
|
|
10787
|
-
import { Command as
|
|
11206
|
+
import { resolve as resolve19 } from "path";
|
|
11207
|
+
import { Command as Command16, Option as Option16 } from "clipanion";
|
|
10788
11208
|
|
|
10789
11209
|
// cli/i18n/refresh.texts.ts
|
|
10790
11210
|
var REFRESH_TEXTS = {
|
|
@@ -10813,12 +11233,12 @@ var REFRESH_TEXTS = {
|
|
|
10813
11233
|
};
|
|
10814
11234
|
|
|
10815
11235
|
// cli/util/path-guard.ts
|
|
10816
|
-
import { isAbsolute as isAbsolute3, resolve as
|
|
11236
|
+
import { isAbsolute as isAbsolute3, resolve as resolve18, sep as sep3 } from "path";
|
|
10817
11237
|
function assertContained2(cwd, rel) {
|
|
10818
11238
|
if (isAbsolute3(rel)) {
|
|
10819
11239
|
throw new Error(`node path is absolute, refusing to read: ${rel}`);
|
|
10820
11240
|
}
|
|
10821
|
-
const abs =
|
|
11241
|
+
const abs = resolve18(cwd, rel);
|
|
10822
11242
|
if (abs !== cwd && !abs.startsWith(cwd + sep3)) {
|
|
10823
11243
|
throw new Error(`node path escapes repo root: ${rel}`);
|
|
10824
11244
|
}
|
|
@@ -10827,7 +11247,7 @@ function assertContained2(cwd, rel) {
|
|
|
10827
11247
|
// cli/commands/refresh.ts
|
|
10828
11248
|
var RefreshCommand = class extends SmCommand {
|
|
10829
11249
|
static paths = [["refresh"]];
|
|
10830
|
-
static usage =
|
|
11250
|
+
static usage = Command16.Usage({
|
|
10831
11251
|
category: "Scan",
|
|
10832
11252
|
description: "Refresh enrichment rows: granular (single node) or batch (every stale row).",
|
|
10833
11253
|
details: `
|
|
@@ -10852,11 +11272,11 @@ var RefreshCommand = class extends SmCommand {
|
|
|
10852
11272
|
["Refresh every node with stale enrichments", "$0 refresh --stale"]
|
|
10853
11273
|
]
|
|
10854
11274
|
});
|
|
10855
|
-
nodePath =
|
|
10856
|
-
stale =
|
|
11275
|
+
nodePath = Option16.String({ name: "node", required: false });
|
|
11276
|
+
stale = Option16.Boolean("--stale", false, {
|
|
10857
11277
|
description: "Refresh every node whose probabilistic enrichment row is flagged stale=1."
|
|
10858
11278
|
});
|
|
10859
|
-
noPlugins =
|
|
11279
|
+
noPlugins = Option16.Boolean("--no-plugins", false, {
|
|
10860
11280
|
description: "Skip drop-in plugin discovery; use only the built-in extractor set."
|
|
10861
11281
|
});
|
|
10862
11282
|
// The remaining cyclomatic count comes from CLI ergonomics that don't
|
|
@@ -10992,7 +11412,7 @@ var RefreshCommand = class extends SmCommand {
|
|
|
10992
11412
|
let body;
|
|
10993
11413
|
try {
|
|
10994
11414
|
assertContained2(cwd, node.path);
|
|
10995
|
-
const raw = await readFile3(
|
|
11415
|
+
const raw = await readFile3(resolve19(cwd, node.path), "utf8");
|
|
10996
11416
|
body = stripFrontmatterFence(raw);
|
|
10997
11417
|
} catch (err) {
|
|
10998
11418
|
this.context.stderr.write(
|
|
@@ -11041,7 +11461,7 @@ function stripFrontmatterFence(text) {
|
|
|
11041
11461
|
var REFRESH_COMMANDS = [RefreshCommand];
|
|
11042
11462
|
|
|
11043
11463
|
// cli/commands/scan.ts
|
|
11044
|
-
import { Command as
|
|
11464
|
+
import { Command as Command18, Option as Option18 } from "clipanion";
|
|
11045
11465
|
|
|
11046
11466
|
// cli/i18n/scan.texts.ts
|
|
11047
11467
|
var SCAN_TEXTS = {
|
|
@@ -11233,7 +11653,7 @@ async function runEphemeralPath(opts, dbPath, strict, loadPrior, runScanWith) {
|
|
|
11233
11653
|
}
|
|
11234
11654
|
|
|
11235
11655
|
// cli/commands/watch.ts
|
|
11236
|
-
import { Command as
|
|
11656
|
+
import { Command as Command17, Option as Option17 } from "clipanion";
|
|
11237
11657
|
|
|
11238
11658
|
// cli/i18n/watch.texts.ts
|
|
11239
11659
|
var WATCH_TEXTS = {
|
|
@@ -11412,7 +11832,7 @@ async function runWatchLoop(opts) {
|
|
|
11412
11832
|
}
|
|
11413
11833
|
var WatchCommand = class extends SmCommand {
|
|
11414
11834
|
static paths = [["watch"]];
|
|
11415
|
-
static usage =
|
|
11835
|
+
static usage = Command17.Usage({
|
|
11416
11836
|
category: "Scan",
|
|
11417
11837
|
description: "Watch roots and run an incremental scan after each debounced batch of filesystem events.",
|
|
11418
11838
|
details: `
|
|
@@ -11436,17 +11856,17 @@ var WatchCommand = class extends SmCommand {
|
|
|
11436
11856
|
["Stream ScanResult per batch as ndjson", "$0 watch --json"]
|
|
11437
11857
|
]
|
|
11438
11858
|
});
|
|
11439
|
-
roots =
|
|
11440
|
-
noTokens =
|
|
11859
|
+
roots = Option17.Rest({ name: "roots" });
|
|
11860
|
+
noTokens = Option17.Boolean("--no-tokens", false, {
|
|
11441
11861
|
description: "Skip per-node token counts (cl100k_base BPE)."
|
|
11442
11862
|
});
|
|
11443
|
-
strict =
|
|
11863
|
+
strict = Option17.Boolean("--strict", false, {
|
|
11444
11864
|
description: "Promote frontmatter-validation findings from warn to error inside each batch. Does not change the watcher exit code."
|
|
11445
11865
|
});
|
|
11446
|
-
noPlugins =
|
|
11866
|
+
noPlugins = Option17.Boolean("--no-plugins", false, {
|
|
11447
11867
|
description: "Skip drop-in plugin discovery for the watcher session."
|
|
11448
11868
|
});
|
|
11449
|
-
maxConsecutiveFailures =
|
|
11869
|
+
maxConsecutiveFailures = Option17.String("--max-consecutive-failures", {
|
|
11450
11870
|
required: false,
|
|
11451
11871
|
description: "Shut down with exit 2 after N consecutive batch failures (default 5; 0 disables the breaker)."
|
|
11452
11872
|
});
|
|
@@ -11484,7 +11904,7 @@ function parseBreakerLimit(raw, stderr) {
|
|
|
11484
11904
|
// cli/commands/scan.ts
|
|
11485
11905
|
var ScanCommand = class extends SmCommand {
|
|
11486
11906
|
static paths = [["scan"]];
|
|
11487
|
-
static usage =
|
|
11907
|
+
static usage = Command18.Usage({
|
|
11488
11908
|
category: "Scan",
|
|
11489
11909
|
description: "Scan roots for markdown nodes, run extractors and rules.",
|
|
11490
11910
|
details: `
|
|
@@ -11513,29 +11933,29 @@ var ScanCommand = class extends SmCommand {
|
|
|
11513
11933
|
["What would the next incremental scan persist?", "$0 scan --changed -n --json"]
|
|
11514
11934
|
]
|
|
11515
11935
|
});
|
|
11516
|
-
roots =
|
|
11517
|
-
noBuiltIns =
|
|
11936
|
+
roots = Option18.Rest({ name: "roots" });
|
|
11937
|
+
noBuiltIns = Option18.Boolean("--no-built-ins", false, {
|
|
11518
11938
|
description: "Skip the built-in extension set. Yields a zero-filled ScanResult (kernel-empty-boot parity); skips DB persistence."
|
|
11519
11939
|
});
|
|
11520
|
-
noPlugins =
|
|
11940
|
+
noPlugins = Option18.Boolean("--no-plugins", false, {
|
|
11521
11941
|
description: "Skip drop-in plugin discovery. Only the built-in set runs. Combine with --no-built-ins for a fully empty pipeline."
|
|
11522
11942
|
});
|
|
11523
|
-
noTokens =
|
|
11943
|
+
noTokens = Option18.Boolean("--no-tokens", false, {
|
|
11524
11944
|
description: "Skip per-node token counts (cl100k_base BPE). Leaves node.tokens undefined; spec-valid since the field is optional."
|
|
11525
11945
|
});
|
|
11526
|
-
dryRun =
|
|
11946
|
+
dryRun = Option18.Boolean("-n,--dry-run", false, {
|
|
11527
11947
|
description: "Run the scan in memory and skip every DB write. Combined with --changed, still opens the DB read-side to load the prior snapshot."
|
|
11528
11948
|
});
|
|
11529
|
-
changed =
|
|
11949
|
+
changed = Option18.Boolean("--changed", false, {
|
|
11530
11950
|
description: "Incremental scan: reuse unchanged nodes from the persisted prior snapshot. Degrades to a full scan if no prior snapshot exists."
|
|
11531
11951
|
});
|
|
11532
|
-
allowEmpty =
|
|
11952
|
+
allowEmpty = Option18.Boolean("--allow-empty", false, {
|
|
11533
11953
|
description: "Allow a zero-result scan to wipe an already-populated DB (replace-all replace by zero rows). Off by default to avoid the typo-trap where an invalid root silently clears your data."
|
|
11534
11954
|
});
|
|
11535
|
-
strict =
|
|
11955
|
+
strict = Option18.Boolean("--strict", false, {
|
|
11536
11956
|
description: "Promote frontmatter-validation findings from warn to error (exit code 1 on any violation). Overrides scan.strict from config when both are set."
|
|
11537
11957
|
});
|
|
11538
|
-
watch =
|
|
11958
|
+
watch = Option18.Boolean("--watch", false, {
|
|
11539
11959
|
description: "Long-running mode: watch the roots and trigger an incremental scan after each debounced batch of filesystem events. Alias of `sm watch`."
|
|
11540
11960
|
});
|
|
11541
11961
|
async run() {
|
|
@@ -11633,11 +12053,11 @@ var ScanCommand = class extends SmCommand {
|
|
|
11633
12053
|
};
|
|
11634
12054
|
|
|
11635
12055
|
// cli/commands/scan-compare.ts
|
|
11636
|
-
import { existsSync as
|
|
11637
|
-
import { Command as
|
|
12056
|
+
import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
|
|
12057
|
+
import { Command as Command19, Option as Option19 } from "clipanion";
|
|
11638
12058
|
var ScanCompareCommand = class extends SmCommand {
|
|
11639
12059
|
static paths = [["scan", "compare-with"]];
|
|
11640
|
-
static usage =
|
|
12060
|
+
static usage = Command19.Usage({
|
|
11641
12061
|
category: "Scan",
|
|
11642
12062
|
description: "Run a fresh scan in memory and emit a delta against the saved ScanResult dump at <dump>. Read-only.",
|
|
11643
12063
|
details: `
|
|
@@ -11665,15 +12085,15 @@ var ScanCompareCommand = class extends SmCommand {
|
|
|
11665
12085
|
["JSON output for tooling", "$0 scan compare-with baseline.json --json"]
|
|
11666
12086
|
]
|
|
11667
12087
|
});
|
|
11668
|
-
dump =
|
|
11669
|
-
roots =
|
|
11670
|
-
noTokens =
|
|
12088
|
+
dump = Option19.String({ required: true });
|
|
12089
|
+
roots = Option19.Rest({ name: "roots" });
|
|
12090
|
+
noTokens = Option19.Boolean("--no-tokens", false, {
|
|
11671
12091
|
description: "Skip per-node token counts during the fresh scan."
|
|
11672
12092
|
});
|
|
11673
|
-
strict =
|
|
12093
|
+
strict = Option19.Boolean("--strict", false, {
|
|
11674
12094
|
description: "Promote layered-config warnings and frontmatter-validation findings from warn to error."
|
|
11675
12095
|
});
|
|
11676
|
-
noPlugins =
|
|
12096
|
+
noPlugins = Option19.Boolean("--no-plugins", false, {
|
|
11677
12097
|
description: "Skip drop-in plugin discovery."
|
|
11678
12098
|
});
|
|
11679
12099
|
// Cyclomatic count comes from CLI ergonomics: 3 distinct try/catch
|
|
@@ -11744,12 +12164,12 @@ var ScanCompareCommand = class extends SmCommand {
|
|
|
11744
12164
|
}
|
|
11745
12165
|
};
|
|
11746
12166
|
function loadAndValidateDump(path) {
|
|
11747
|
-
if (!
|
|
12167
|
+
if (!existsSync15(path)) {
|
|
11748
12168
|
throw new Error(tx(SCAN_TEXTS.compareDumpNotFound, { path }));
|
|
11749
12169
|
}
|
|
11750
12170
|
let raw;
|
|
11751
12171
|
try {
|
|
11752
|
-
raw =
|
|
12172
|
+
raw = readFileSync12(path, "utf8");
|
|
11753
12173
|
} catch (err) {
|
|
11754
12174
|
const message = formatErrorMessage(err);
|
|
11755
12175
|
throw new Error(tx(SCAN_TEXTS.compareDumpReadFailed, { path, message }), { cause: err });
|
|
@@ -11858,8 +12278,8 @@ function renderDeltaIssues(issues) {
|
|
|
11858
12278
|
|
|
11859
12279
|
// cli/commands/serve.ts
|
|
11860
12280
|
import { spawn } from "child_process";
|
|
11861
|
-
import { existsSync as
|
|
11862
|
-
import { Command as
|
|
12281
|
+
import { existsSync as existsSync19 } from "fs";
|
|
12282
|
+
import { Command as Command20, Option as Option20 } from "clipanion";
|
|
11863
12283
|
|
|
11864
12284
|
// server/index.ts
|
|
11865
12285
|
import { serve } from "@hono/node-server";
|
|
@@ -12040,7 +12460,7 @@ function contentTypeFor(format) {
|
|
|
12040
12460
|
}
|
|
12041
12461
|
|
|
12042
12462
|
// server/health.ts
|
|
12043
|
-
import { existsSync as
|
|
12463
|
+
import { existsSync as existsSync16 } from "fs";
|
|
12044
12464
|
var FALLBACK_SCHEMA_VERSION = "1";
|
|
12045
12465
|
function buildHealth(deps) {
|
|
12046
12466
|
return {
|
|
@@ -12049,7 +12469,7 @@ function buildHealth(deps) {
|
|
|
12049
12469
|
specVersion: deps.specVersion,
|
|
12050
12470
|
implVersion: VERSION,
|
|
12051
12471
|
scope: deps.scope,
|
|
12052
|
-
db:
|
|
12472
|
+
db: existsSync16(deps.dbPath) ? "present" : "missing"
|
|
12053
12473
|
};
|
|
12054
12474
|
}
|
|
12055
12475
|
async function resolveSpecVersion2() {
|
|
@@ -12489,9 +12909,9 @@ function emptyScanResult() {
|
|
|
12489
12909
|
}
|
|
12490
12910
|
|
|
12491
12911
|
// server/static.ts
|
|
12492
|
-
import { existsSync as
|
|
12912
|
+
import { existsSync as existsSync17 } from "fs";
|
|
12493
12913
|
import { readFile as readFile5 } from "fs/promises";
|
|
12494
|
-
import { extname, join as
|
|
12914
|
+
import { extname, join as join14 } from "path";
|
|
12495
12915
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
12496
12916
|
var INDEX_HTML = "index.html";
|
|
12497
12917
|
var PLACEHOLDER_HTML = `<!doctype html>
|
|
@@ -12509,7 +12929,7 @@ var PLACEHOLDER_HTML = `<!doctype html>
|
|
|
12509
12929
|
</head>
|
|
12510
12930
|
<body>
|
|
12511
12931
|
<h1>skill-map server is running</h1>
|
|
12512
|
-
<p>The UI bundle was not found.
|
|
12932
|
+
<p>The UI bundle was not found. If you installed <code>@skill-map/cli</code> from npm, this is a packaging bug \u2014 please report it. If you're developing in the monorepo, run <code>npm run build --workspace=ui</code> from the repo root and restart <code>sm serve</code> (or pass <code>--ui-dist <path></code> to point at a custom build).</p>
|
|
12513
12933
|
<p>The REST API is available at <code>/api/health</code>.</p>
|
|
12514
12934
|
</body>
|
|
12515
12935
|
</html>
|
|
@@ -12522,8 +12942,8 @@ function createSpaFallback(uiDist) {
|
|
|
12522
12942
|
return async (c, _next) => {
|
|
12523
12943
|
if (c.req.method !== "GET" && c.req.method !== "HEAD") return c.notFound();
|
|
12524
12944
|
if (uiDist === null) return htmlResponse(c, PLACEHOLDER_HTML);
|
|
12525
|
-
const indexPath =
|
|
12526
|
-
if (!
|
|
12945
|
+
const indexPath = join14(uiDist, INDEX_HTML);
|
|
12946
|
+
if (!existsSync17(indexPath)) return htmlResponse(c, PLACEHOLDER_HTML);
|
|
12527
12947
|
return fileResponse(c, indexPath);
|
|
12528
12948
|
};
|
|
12529
12949
|
}
|
|
@@ -13113,33 +13533,62 @@ function validateWatcherDebounce(value) {
|
|
|
13113
13533
|
}
|
|
13114
13534
|
|
|
13115
13535
|
// server/paths.ts
|
|
13116
|
-
import { existsSync as
|
|
13117
|
-
import { dirname as
|
|
13118
|
-
|
|
13536
|
+
import { existsSync as existsSync18, statSync as statSync5 } from "fs";
|
|
13537
|
+
import { dirname as dirname10, isAbsolute as isAbsolute5, join as join15, resolve as resolve20 } from "path";
|
|
13538
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
13539
|
+
var DEFAULT_UI_REL = join15("ui", "dist", "ui", "browser");
|
|
13540
|
+
var PACKAGE_UI_REL = "ui";
|
|
13119
13541
|
var INDEX_HTML2 = "index.html";
|
|
13120
13542
|
function resolveDefaultUiDist(ctx) {
|
|
13121
|
-
|
|
13122
|
-
|
|
13123
|
-
|
|
13124
|
-
if (isUiBundleDir(candidate)) return candidate;
|
|
13125
|
-
const parent = dirname9(current);
|
|
13126
|
-
if (parent === current) return null;
|
|
13127
|
-
current = parent;
|
|
13128
|
-
}
|
|
13129
|
-
return null;
|
|
13543
|
+
const bundled = resolvePackageBundledUi();
|
|
13544
|
+
if (bundled !== null) return bundled;
|
|
13545
|
+
return walkUpForUi(ctx.cwd);
|
|
13130
13546
|
}
|
|
13131
13547
|
function resolveExplicitUiDist(ctx, raw) {
|
|
13132
|
-
return isAbsolute5(raw) ? raw :
|
|
13548
|
+
return isAbsolute5(raw) ? raw : resolve20(ctx.cwd, raw);
|
|
13133
13549
|
}
|
|
13134
13550
|
function isUiBundleDir(path) {
|
|
13135
|
-
if (!
|
|
13551
|
+
if (!existsSync18(path)) return false;
|
|
13136
13552
|
try {
|
|
13137
13553
|
if (!statSync5(path).isDirectory()) return false;
|
|
13138
|
-
return
|
|
13554
|
+
return existsSync18(join15(path, INDEX_HTML2));
|
|
13139
13555
|
} catch {
|
|
13140
13556
|
return false;
|
|
13141
13557
|
}
|
|
13142
13558
|
}
|
|
13559
|
+
function resolvePackageBundledUi() {
|
|
13560
|
+
let here;
|
|
13561
|
+
try {
|
|
13562
|
+
here = dirname10(fileURLToPath6(import.meta.url));
|
|
13563
|
+
} catch {
|
|
13564
|
+
return null;
|
|
13565
|
+
}
|
|
13566
|
+
return resolvePackageBundledUiFrom(here);
|
|
13567
|
+
}
|
|
13568
|
+
function resolvePackageBundledUiFrom(here) {
|
|
13569
|
+
let current = here;
|
|
13570
|
+
for (let i = 0; i < 8; i++) {
|
|
13571
|
+
const candidate = join15(current, PACKAGE_UI_REL);
|
|
13572
|
+
if (isUiBundleDir(candidate)) return candidate;
|
|
13573
|
+
const distHere = join15(current, "dist", PACKAGE_UI_REL);
|
|
13574
|
+
if (isUiBundleDir(distHere)) return distHere;
|
|
13575
|
+
const parent = dirname10(current);
|
|
13576
|
+
if (parent === current) return null;
|
|
13577
|
+
current = parent;
|
|
13578
|
+
}
|
|
13579
|
+
return null;
|
|
13580
|
+
}
|
|
13581
|
+
function walkUpForUi(startDir) {
|
|
13582
|
+
let current = resolve20(startDir);
|
|
13583
|
+
for (let i = 0; i < 64; i++) {
|
|
13584
|
+
const candidate = join15(current, DEFAULT_UI_REL);
|
|
13585
|
+
if (isUiBundleDir(candidate)) return candidate;
|
|
13586
|
+
const parent = dirname10(current);
|
|
13587
|
+
if (parent === current) return null;
|
|
13588
|
+
current = parent;
|
|
13589
|
+
}
|
|
13590
|
+
return null;
|
|
13591
|
+
}
|
|
13143
13592
|
|
|
13144
13593
|
// server/index.ts
|
|
13145
13594
|
async function createServer(options, extra = {}) {
|
|
@@ -13294,7 +13743,7 @@ var SERVE_TEXTS = {
|
|
|
13294
13743
|
// cli/commands/serve.ts
|
|
13295
13744
|
var ServeCommand = class extends SmCommand {
|
|
13296
13745
|
static paths = [["serve"]];
|
|
13297
|
-
static usage =
|
|
13746
|
+
static usage = Command20.Usage({
|
|
13298
13747
|
category: "Setup",
|
|
13299
13748
|
description: "Start the Hono BFF (single-port: REST + WebSocket + SPA bundle).",
|
|
13300
13749
|
details: `
|
|
@@ -13319,22 +13768,22 @@ var ServeCommand = class extends SmCommand {
|
|
|
13319
13768
|
["Point at a pre-built UI bundle", "$0 serve --ui-dist ./ui/dist/browser"]
|
|
13320
13769
|
]
|
|
13321
13770
|
});
|
|
13322
|
-
port =
|
|
13771
|
+
port = Option20.String("--port", {
|
|
13323
13772
|
required: false,
|
|
13324
13773
|
description: "Listening port (default 4242). 0 = OS-assigned."
|
|
13325
13774
|
});
|
|
13326
|
-
host =
|
|
13775
|
+
host = Option20.String("--host", {
|
|
13327
13776
|
required: false,
|
|
13328
13777
|
description: "Listening host (default 127.0.0.1). Loopback-only enforced when --dev-cors is set."
|
|
13329
13778
|
});
|
|
13330
|
-
scope =
|
|
13779
|
+
scope = Option20.String("--scope", {
|
|
13331
13780
|
required: false,
|
|
13332
13781
|
description: "project | global. Alias for -g/--global. Default: project."
|
|
13333
13782
|
});
|
|
13334
|
-
noBuiltIns =
|
|
13783
|
+
noBuiltIns = Option20.Boolean("--no-built-ins", false, {
|
|
13335
13784
|
description: "Skip built-in plugin registration (parity with sm scan --no-built-ins)."
|
|
13336
13785
|
});
|
|
13337
|
-
noPlugins =
|
|
13786
|
+
noPlugins = Option20.Boolean("--no-plugins", false, {
|
|
13338
13787
|
description: "Skip drop-in plugin discovery."
|
|
13339
13788
|
});
|
|
13340
13789
|
// `Option.Boolean('--open', true)` — Clipanion's parser auto-derives
|
|
@@ -13344,24 +13793,24 @@ var ServeCommand = class extends SmCommand {
|
|
|
13344
13793
|
// two registrations for the same flag and rejects the invocation
|
|
13345
13794
|
// with "Ambiguous Syntax Error". Same convention shipped by every
|
|
13346
13795
|
// other `--no-...` flag in the CLI tree.
|
|
13347
|
-
open =
|
|
13796
|
+
open = Option20.Boolean("--open", true, {
|
|
13348
13797
|
description: "Auto-open the SPA in the user's default browser after listen. --no-open opts out."
|
|
13349
13798
|
});
|
|
13350
|
-
devCors =
|
|
13799
|
+
devCors = Option20.Boolean("--dev-cors", false, {
|
|
13351
13800
|
description: "Enable permissive CORS for the Angular dev-server proxy workflow."
|
|
13352
13801
|
});
|
|
13353
13802
|
// `--ui-dist` is intentionally undocumented in the Usage block above
|
|
13354
13803
|
// (the demo build pipeline + tests rely on it; everyday users never
|
|
13355
13804
|
// need it). Clipanion still exposes it on the parser; the Usage
|
|
13356
13805
|
// omission is the "hidden" contract per the 14.1 brief.
|
|
13357
|
-
uiDist =
|
|
13358
|
-
noWatcher =
|
|
13806
|
+
uiDist = Option20.String("--ui-dist", { required: false, hidden: true });
|
|
13807
|
+
noWatcher = Option20.Boolean("--no-watcher", false, {
|
|
13359
13808
|
description: "Disable the chokidar-fed scan-and-broadcast loop. Use only for CI / read-only deployments."
|
|
13360
13809
|
});
|
|
13361
13810
|
// `--watcher-debounce-ms` is undocumented sugar for advanced users
|
|
13362
13811
|
// who want to tighten / relax the watcher's batching window without
|
|
13363
13812
|
// editing settings.json. Hidden flag — the Usage block omits it.
|
|
13364
|
-
watcherDebounceMs =
|
|
13813
|
+
watcherDebounceMs = Option20.String("--watcher-debounce-ms", { required: false, hidden: true });
|
|
13365
13814
|
// Long-running daemon — `done in <…>` after a graceful shutdown is
|
|
13366
13815
|
// noise. Mirrors `sm watch`'s opt-out.
|
|
13367
13816
|
emitElapsed = false;
|
|
@@ -13389,7 +13838,7 @@ var ServeCommand = class extends SmCommand {
|
|
|
13389
13838
|
return ExitCode.Error;
|
|
13390
13839
|
}
|
|
13391
13840
|
const dbPath = resolveDbPath({ global: this.global, db: this.db, ...runtimeCtx });
|
|
13392
|
-
if (this.db !== void 0 && !
|
|
13841
|
+
if (this.db !== void 0 && !existsSync19(dbPath)) {
|
|
13393
13842
|
this.context.stderr.write(
|
|
13394
13843
|
tx(SERVE_TEXTS.dbNotFound, { path: sanitizeForTerminal(dbPath) })
|
|
13395
13844
|
);
|
|
@@ -13570,7 +14019,7 @@ function tryOpenBrowser(url, stderr) {
|
|
|
13570
14019
|
}
|
|
13571
14020
|
|
|
13572
14021
|
// cli/commands/show.ts
|
|
13573
|
-
import { Command as
|
|
14022
|
+
import { Command as Command21, Option as Option21 } from "clipanion";
|
|
13574
14023
|
|
|
13575
14024
|
// cli/i18n/show.texts.ts
|
|
13576
14025
|
var SHOW_TEXTS = {
|
|
@@ -13610,7 +14059,7 @@ var SHOW_TEXTS = {
|
|
|
13610
14059
|
// cli/commands/show.ts
|
|
13611
14060
|
var ShowCommand = class extends SmCommand {
|
|
13612
14061
|
static paths = [["show"]];
|
|
13613
|
-
static usage =
|
|
14062
|
+
static usage = Command21.Usage({
|
|
13614
14063
|
category: "Browse",
|
|
13615
14064
|
description: "Node detail: weight, frontmatter, links, issues.",
|
|
13616
14065
|
details: `
|
|
@@ -13626,7 +14075,7 @@ var ShowCommand = class extends SmCommand {
|
|
|
13626
14075
|
["Machine-readable detail", "$0 show .claude/agents/architect.md --json"]
|
|
13627
14076
|
]
|
|
13628
14077
|
});
|
|
13629
|
-
nodePath =
|
|
14078
|
+
nodePath = Option21.String({ required: true });
|
|
13630
14079
|
async run() {
|
|
13631
14080
|
const dbPath = resolveDbPath({ global: this.global, db: this.db, ...defaultRuntimeContext() });
|
|
13632
14081
|
if (!assertDbExists(dbPath, this.context.stderr)) return ExitCode.NotFound;
|
|
@@ -13775,7 +14224,7 @@ function rankConfidenceForGrouping(c) {
|
|
|
13775
14224
|
}
|
|
13776
14225
|
|
|
13777
14226
|
// cli/commands/stubs.ts
|
|
13778
|
-
import { Command as
|
|
14227
|
+
import { Command as Command22, Option as Option22 } from "clipanion";
|
|
13779
14228
|
|
|
13780
14229
|
// cli/i18n/stubs.texts.ts
|
|
13781
14230
|
var STUBS_TEXTS = {
|
|
@@ -13790,9 +14239,9 @@ function notImplemented(cmd, verb) {
|
|
|
13790
14239
|
cmd.context.stderr.write(tx(STUBS_TEXTS.notImplemented, { verb }));
|
|
13791
14240
|
return ExitCode.Error;
|
|
13792
14241
|
}
|
|
13793
|
-
var DoctorCommand = class extends
|
|
14242
|
+
var DoctorCommand = class extends Command22 {
|
|
13794
14243
|
static paths = [["doctor"]];
|
|
13795
|
-
static usage =
|
|
14244
|
+
static usage = Command22.Usage({
|
|
13796
14245
|
category: "Setup",
|
|
13797
14246
|
description: planned("Diagnostic report: DB integrity, pending migrations, orphan rows, plugin status, runner availability.")
|
|
13798
14247
|
});
|
|
@@ -13800,23 +14249,23 @@ var DoctorCommand = class extends Command21 {
|
|
|
13800
14249
|
return notImplemented(this, "doctor");
|
|
13801
14250
|
}
|
|
13802
14251
|
};
|
|
13803
|
-
var FindingsCommand = class extends
|
|
14252
|
+
var FindingsCommand = class extends Command22 {
|
|
13804
14253
|
static paths = [["findings"]];
|
|
13805
|
-
static usage =
|
|
14254
|
+
static usage = Command22.Usage({
|
|
13806
14255
|
category: "Browse",
|
|
13807
14256
|
description: planned("Probabilistic findings: injection, stale summaries, low confidence.")
|
|
13808
14257
|
});
|
|
13809
|
-
kind =
|
|
13810
|
-
since =
|
|
13811
|
-
threshold =
|
|
13812
|
-
json =
|
|
14258
|
+
kind = Option22.String("--kind", { required: false });
|
|
14259
|
+
since = Option22.String("--since", { required: false });
|
|
14260
|
+
threshold = Option22.String("--threshold", { required: false });
|
|
14261
|
+
json = Option22.Boolean("--json", false);
|
|
13813
14262
|
async execute() {
|
|
13814
14263
|
return notImplemented(this, "findings");
|
|
13815
14264
|
}
|
|
13816
14265
|
};
|
|
13817
|
-
var ActionsListCommand = class extends
|
|
14266
|
+
var ActionsListCommand = class extends Command22 {
|
|
13818
14267
|
static paths = [["actions", "list"]];
|
|
13819
|
-
static usage =
|
|
14268
|
+
static usage = Command22.Usage({
|
|
13820
14269
|
category: "Jobs",
|
|
13821
14270
|
description: planned("Registered action types (manifest view).")
|
|
13822
14271
|
});
|
|
@@ -13824,121 +14273,121 @@ var ActionsListCommand = class extends Command21 {
|
|
|
13824
14273
|
return notImplemented(this, "actions list");
|
|
13825
14274
|
}
|
|
13826
14275
|
};
|
|
13827
|
-
var ActionsShowCommand = class extends
|
|
14276
|
+
var ActionsShowCommand = class extends Command22 {
|
|
13828
14277
|
static paths = [["actions", "show"]];
|
|
13829
|
-
static usage =
|
|
14278
|
+
static usage = Command22.Usage({
|
|
13830
14279
|
category: "Jobs",
|
|
13831
14280
|
description: planned("Full action manifest, including preconditions and expected duration.")
|
|
13832
14281
|
});
|
|
13833
|
-
id =
|
|
14282
|
+
id = Option22.String({ required: true });
|
|
13834
14283
|
async execute() {
|
|
13835
14284
|
return notImplemented(this, "actions show");
|
|
13836
14285
|
}
|
|
13837
14286
|
};
|
|
13838
|
-
var JobSubmitCommand = class extends
|
|
14287
|
+
var JobSubmitCommand = class extends Command22 {
|
|
13839
14288
|
static paths = [["job", "submit"]];
|
|
13840
|
-
static usage =
|
|
14289
|
+
static usage = Command22.Usage({
|
|
13841
14290
|
category: "Jobs",
|
|
13842
14291
|
description: planned("Enqueue a single job or fan out to every matching node (--all).")
|
|
13843
14292
|
});
|
|
13844
|
-
action =
|
|
13845
|
-
node =
|
|
13846
|
-
all =
|
|
13847
|
-
run =
|
|
13848
|
-
force =
|
|
13849
|
-
ttl =
|
|
13850
|
-
priority =
|
|
14293
|
+
action = Option22.String({ required: true });
|
|
14294
|
+
node = Option22.String("-n", { required: false });
|
|
14295
|
+
all = Option22.Boolean("--all", false);
|
|
14296
|
+
run = Option22.Boolean("--run", false);
|
|
14297
|
+
force = Option22.Boolean("--force", false);
|
|
14298
|
+
ttl = Option22.String("--ttl", { required: false });
|
|
14299
|
+
priority = Option22.String("--priority", { required: false });
|
|
13851
14300
|
async execute() {
|
|
13852
14301
|
return notImplemented(this, "job submit");
|
|
13853
14302
|
}
|
|
13854
14303
|
};
|
|
13855
|
-
var JobListCommand = class extends
|
|
14304
|
+
var JobListCommand = class extends Command22 {
|
|
13856
14305
|
static paths = [["job", "list"]];
|
|
13857
|
-
static usage =
|
|
13858
|
-
status =
|
|
13859
|
-
action =
|
|
13860
|
-
node =
|
|
14306
|
+
static usage = Command22.Usage({ category: "Jobs", description: planned("List jobs.") });
|
|
14307
|
+
status = Option22.String("--status", { required: false });
|
|
14308
|
+
action = Option22.String("--action", { required: false });
|
|
14309
|
+
node = Option22.String("--node", { required: false });
|
|
13861
14310
|
async execute() {
|
|
13862
14311
|
return notImplemented(this, "job list");
|
|
13863
14312
|
}
|
|
13864
14313
|
};
|
|
13865
|
-
var JobShowCommand = class extends
|
|
14314
|
+
var JobShowCommand = class extends Command22 {
|
|
13866
14315
|
static paths = [["job", "show"]];
|
|
13867
|
-
static usage =
|
|
13868
|
-
id =
|
|
14316
|
+
static usage = Command22.Usage({ category: "Jobs", description: planned("Job detail: state, claim time, TTL, runner, content hash.") });
|
|
14317
|
+
id = Option22.String({ required: true });
|
|
13869
14318
|
async execute() {
|
|
13870
14319
|
return notImplemented(this, "job show");
|
|
13871
14320
|
}
|
|
13872
14321
|
};
|
|
13873
|
-
var JobPreviewCommand = class extends
|
|
14322
|
+
var JobPreviewCommand = class extends Command22 {
|
|
13874
14323
|
static paths = [["job", "preview"]];
|
|
13875
|
-
static usage =
|
|
13876
|
-
id =
|
|
14324
|
+
static usage = Command22.Usage({ category: "Jobs", description: planned("Render the job MD file without executing.") });
|
|
14325
|
+
id = Option22.String({ required: true });
|
|
13877
14326
|
async execute() {
|
|
13878
14327
|
return notImplemented(this, "job preview");
|
|
13879
14328
|
}
|
|
13880
14329
|
};
|
|
13881
|
-
var JobClaimCommand = class extends
|
|
14330
|
+
var JobClaimCommand = class extends Command22 {
|
|
13882
14331
|
static paths = [["job", "claim"]];
|
|
13883
|
-
static usage =
|
|
14332
|
+
static usage = Command22.Usage({
|
|
13884
14333
|
category: "Jobs",
|
|
13885
14334
|
description: planned("Atomic primitive: return next queued job id, mark it running.")
|
|
13886
14335
|
});
|
|
13887
|
-
filter =
|
|
14336
|
+
filter = Option22.String("--filter", { required: false });
|
|
13888
14337
|
async execute() {
|
|
13889
14338
|
return notImplemented(this, "job claim");
|
|
13890
14339
|
}
|
|
13891
14340
|
};
|
|
13892
|
-
var JobRunCommand = class extends
|
|
14341
|
+
var JobRunCommand = class extends Command22 {
|
|
13893
14342
|
static paths = [["job", "run"]];
|
|
13894
|
-
static usage =
|
|
14343
|
+
static usage = Command22.Usage({
|
|
13895
14344
|
category: "Jobs",
|
|
13896
14345
|
description: planned("Full CLI-runner loop: claim + spawn + record.")
|
|
13897
14346
|
});
|
|
13898
|
-
all =
|
|
13899
|
-
max =
|
|
14347
|
+
all = Option22.Boolean("--all", false);
|
|
14348
|
+
max = Option22.String("--max", { required: false });
|
|
13900
14349
|
async execute() {
|
|
13901
14350
|
return notImplemented(this, "job run");
|
|
13902
14351
|
}
|
|
13903
14352
|
};
|
|
13904
|
-
var JobStatusCommand = class extends
|
|
14353
|
+
var JobStatusCommand = class extends Command22 {
|
|
13905
14354
|
static paths = [["job", "status"]];
|
|
13906
|
-
static usage =
|
|
14355
|
+
static usage = Command22.Usage({
|
|
13907
14356
|
category: "Jobs",
|
|
13908
14357
|
description: planned("Counts (per status) or single-job status.")
|
|
13909
14358
|
});
|
|
13910
|
-
id =
|
|
14359
|
+
id = Option22.String({ required: false });
|
|
13911
14360
|
async execute() {
|
|
13912
14361
|
return notImplemented(this, "job status");
|
|
13913
14362
|
}
|
|
13914
14363
|
};
|
|
13915
|
-
var JobCancelCommand = class extends
|
|
14364
|
+
var JobCancelCommand = class extends Command22 {
|
|
13916
14365
|
static paths = [["job", "cancel"]];
|
|
13917
|
-
static usage =
|
|
14366
|
+
static usage = Command22.Usage({
|
|
13918
14367
|
category: "Jobs",
|
|
13919
14368
|
description: planned("Force a running job to failed with reason user-cancelled.")
|
|
13920
14369
|
});
|
|
13921
|
-
id =
|
|
13922
|
-
all =
|
|
14370
|
+
id = Option22.String({ required: false });
|
|
14371
|
+
all = Option22.Boolean("--all", false);
|
|
13923
14372
|
async execute() {
|
|
13924
14373
|
return notImplemented(this, "job cancel");
|
|
13925
14374
|
}
|
|
13926
14375
|
};
|
|
13927
|
-
var RecordCommand = class extends
|
|
14376
|
+
var RecordCommand = class extends Command22 {
|
|
13928
14377
|
static paths = [["record"]];
|
|
13929
|
-
static usage =
|
|
14378
|
+
static usage = Command22.Usage({
|
|
13930
14379
|
category: "Jobs",
|
|
13931
14380
|
description: planned("Close a running job with success or failure. Nonce is the sole credential.")
|
|
13932
14381
|
});
|
|
13933
|
-
id =
|
|
13934
|
-
nonce =
|
|
13935
|
-
status =
|
|
13936
|
-
report =
|
|
13937
|
-
tokensIn =
|
|
13938
|
-
tokensOut =
|
|
13939
|
-
durationMs =
|
|
13940
|
-
model =
|
|
13941
|
-
error =
|
|
14382
|
+
id = Option22.String("--id", { required: true });
|
|
14383
|
+
nonce = Option22.String("--nonce", { required: true });
|
|
14384
|
+
status = Option22.String("--status", { required: true });
|
|
14385
|
+
report = Option22.String("--report", { required: false });
|
|
14386
|
+
tokensIn = Option22.String("--tokens-in", { required: false });
|
|
14387
|
+
tokensOut = Option22.String("--tokens-out", { required: false });
|
|
14388
|
+
durationMs = Option22.String("--duration-ms", { required: false });
|
|
14389
|
+
model = Option22.String("--model", { required: false });
|
|
14390
|
+
error = Option22.String("--error", { required: false });
|
|
13942
14391
|
async execute() {
|
|
13943
14392
|
return notImplemented(this, "record");
|
|
13944
14393
|
}
|
|
@@ -13960,7 +14409,7 @@ var STUB_COMMANDS = [
|
|
|
13960
14409
|
];
|
|
13961
14410
|
|
|
13962
14411
|
// cli/commands/version.ts
|
|
13963
|
-
import { Command as
|
|
14412
|
+
import { Command as Command23 } from "clipanion";
|
|
13964
14413
|
|
|
13965
14414
|
// cli/i18n/version.texts.ts
|
|
13966
14415
|
var VERSION_TEXTS = {
|
|
@@ -13972,7 +14421,7 @@ var VERSION_TEXTS = {
|
|
|
13972
14421
|
// cli/commands/version.ts
|
|
13973
14422
|
var VersionCommand = class extends SmCommand {
|
|
13974
14423
|
static paths = [["version"]];
|
|
13975
|
-
static usage =
|
|
14424
|
+
static usage = Command23.Usage({
|
|
13976
14425
|
category: "Introspection",
|
|
13977
14426
|
description: "Print the CLI / kernel / spec / runtime / db-schema version matrix."
|
|
13978
14427
|
});
|
|
@@ -14042,6 +14491,7 @@ cli.register(Builtins.VersionCommand);
|
|
|
14042
14491
|
cli.register(RootHelpCommand);
|
|
14043
14492
|
cli.register(HelpCommand);
|
|
14044
14493
|
cli.register(InitCommand);
|
|
14494
|
+
cli.register(GuideCommand);
|
|
14045
14495
|
cli.register(ScanCommand);
|
|
14046
14496
|
cli.register(ScanCompareCommand);
|
|
14047
14497
|
cli.register(ServeCommand);
|
|
@@ -14072,6 +14522,25 @@ var logLevel = resolveLogLevel({
|
|
|
14072
14522
|
configureLogger(new Logger({ level: logLevel, stream: process.stderr }));
|
|
14073
14523
|
var bareArgs = args.length === 0 ? resolveBareDefault() : null;
|
|
14074
14524
|
var routedArgs = routeHelpArgs(bareArgs ?? args, cli);
|
|
14525
|
+
try {
|
|
14526
|
+
cli.process(routedArgs, {
|
|
14527
|
+
stdin: process.stdin,
|
|
14528
|
+
stdout: process.stdout,
|
|
14529
|
+
stderr: process.stderr
|
|
14530
|
+
});
|
|
14531
|
+
} catch (err) {
|
|
14532
|
+
if (isClipanionParseError(err)) {
|
|
14533
|
+
process.stderr.write(
|
|
14534
|
+
formatParseError({
|
|
14535
|
+
args: routedArgs,
|
|
14536
|
+
verbPaths: registeredVerbPaths(cli),
|
|
14537
|
+
error: err
|
|
14538
|
+
})
|
|
14539
|
+
);
|
|
14540
|
+
process.exit(ExitCode.Error);
|
|
14541
|
+
}
|
|
14542
|
+
throw err;
|
|
14543
|
+
}
|
|
14075
14544
|
var exitCode = await cli.run(routedArgs, {
|
|
14076
14545
|
stdin: process.stdin,
|
|
14077
14546
|
stdout: process.stdout,
|
|
@@ -14080,7 +14549,7 @@ var exitCode = await cli.run(routedArgs, {
|
|
|
14080
14549
|
process.exit(exitCode);
|
|
14081
14550
|
function resolveBareDefault() {
|
|
14082
14551
|
const ctx = defaultRuntimeContext();
|
|
14083
|
-
if (
|
|
14552
|
+
if (existsSync20(defaultProjectDbPath(ctx))) {
|
|
14084
14553
|
return ["serve"];
|
|
14085
14554
|
}
|
|
14086
14555
|
process.stderr.write(tx(ENTRY_TEXTS.bareNoProject, { cwd: ctx.cwd }));
|