@skill-map/cli 0.13.0 → 0.14.1
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 +798 -0
- package/dist/cli.js +752 -332
- 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-NUUSKOAE.js → chunk-AVRC55YV.js} +1 -1
- package/dist/ui/{chunk-MFQFSZZ5.js → chunk-DOJURY6T.js} +1 -1
- package/dist/ui/{chunk-J3FDTSKA.js → chunk-G6SL4UFD.js} +1 -1
- package/dist/ui/{chunk-VYSE3ZFQ.js → chunk-T5SUVDLE.js} +12 -12
- package/dist/ui/{chunk-SKGGJQY3.js → chunk-TEPC3SFH.js} +2 -2
- package/dist/ui/chunk-VJAWM5V3.js +210 -0
- package/dist/ui/{chunk-6EW3JAB6.js → chunk-WFJRSBK6.js} +2 -2
- package/dist/ui/{chunk-ZTVMUEY2.js → chunk-ZF7H74JY.js} +1 -1
- package/dist/ui/favicon-32x32.png +0 -0
- package/dist/ui/favicon.svg +14 -0
- package/dist/ui/index.html +10 -2
- package/dist/ui/main-TG4BEOVI.js +1 -0
- package/package.json +2 -2
- package/dist/ui/chunk-RN7YDIJP.js +0 -210
- package/dist/ui/favicon.ico +0 -0
- package/dist/ui/main-7S2SK7UD.js +0 -1
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
|
|
@@ -58,6 +58,7 @@ var ENTRY_TEXTS = {
|
|
|
58
58
|
parseErrorIncompleteCommand: "incomplete command '{{name}}'",
|
|
59
59
|
parseErrorSubcommandList: "Available subcommands: {{suggestions}}.",
|
|
60
60
|
parseErrorVerbUsage: "{{verb}}: {{message}}",
|
|
61
|
+
parseErrorMissingPositional: "{{verb}}: missing required positional argument(s) {{positionals}}",
|
|
61
62
|
parseErrorFlagSuggestion: "Did you mean '{{suggestion}}'?",
|
|
62
63
|
parseErrorVerbSuggestion: "Did you mean {{suggestions}}?",
|
|
63
64
|
parseErrorVerbHelpHint: "Run 'sm help {{verb}}' for usage.",
|
|
@@ -275,6 +276,46 @@ var ExitCode = {
|
|
|
275
276
|
NotFound: 5
|
|
276
277
|
};
|
|
277
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
|
+
|
|
278
319
|
// cli/util/parse-error.ts
|
|
279
320
|
function isClipanionParseError(err) {
|
|
280
321
|
if (!err || typeof err !== "object") return false;
|
|
@@ -297,10 +338,7 @@ function formatParseError(params) {
|
|
|
297
338
|
return renderError(error.message.trim(), null);
|
|
298
339
|
}
|
|
299
340
|
const verbPrefix = matchedVerbPrefix(args2, verbPaths);
|
|
300
|
-
if (verbPrefix)
|
|
301
|
-
const headline = tx(ENTRY_TEXTS.parseErrorVerbUsage, { verb: verbPrefix, message: error.message.trim() });
|
|
302
|
-
return renderError(headline, tx(ENTRY_TEXTS.parseErrorVerbHelpHint, { verb: verbPrefix }));
|
|
303
|
-
}
|
|
341
|
+
if (verbPrefix) return formatVerbScopedError(verbPrefix, error.message);
|
|
304
342
|
const subcommands = subcommandsUnder(firstToken, verbPaths);
|
|
305
343
|
if (subcommands.length > 0) {
|
|
306
344
|
const headline = tx(ENTRY_TEXTS.parseErrorIncompleteCommand, { name: firstToken });
|
|
@@ -313,6 +351,22 @@ function formatParseError(params) {
|
|
|
313
351
|
const suggestion = candidates.length > 0 ? tx(ENTRY_TEXTS.parseErrorVerbSuggestion, { suggestions: formatSuggestionList(candidates) }) : null;
|
|
314
352
|
return renderError(tx(ENTRY_TEXTS.parseErrorUnknownCommand, { name: firstToken }), suggestion);
|
|
315
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
|
+
}
|
|
316
370
|
function subcommandsUnder(namespace, verbPaths) {
|
|
317
371
|
const matches = verbPaths.filter((path) => path.length >= 2 && path[0] === namespace).map((path) => path.join(" ")).sort();
|
|
318
372
|
return matches.slice(0, 3);
|
|
@@ -342,6 +396,16 @@ function extractOffendingFlag(message) {
|
|
|
342
396
|
const match = /Unsupported option name \("([^"]+)"\)/.exec(message);
|
|
343
397
|
return match ? match[1] : null;
|
|
344
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
|
+
}
|
|
345
409
|
function suggestFlag(token) {
|
|
346
410
|
if (!token.startsWith("-")) return null;
|
|
347
411
|
if (token.startsWith("--")) return null;
|
|
@@ -349,34 +413,6 @@ function suggestFlag(token) {
|
|
|
349
413
|
const longForm = "-" + token;
|
|
350
414
|
return tx(ENTRY_TEXTS.parseErrorFlagSuggestion, { suggestion: longForm });
|
|
351
415
|
}
|
|
352
|
-
function editDistance(a, b, max) {
|
|
353
|
-
if (a === b) return 0;
|
|
354
|
-
if (Math.abs(a.length - b.length) > max) return max + 1;
|
|
355
|
-
const m = a.length;
|
|
356
|
-
const n = b.length;
|
|
357
|
-
if (m === 0) return n;
|
|
358
|
-
if (n === 0) return m;
|
|
359
|
-
let prev = Array.from({ length: n + 1 }, (_, i) => i);
|
|
360
|
-
let curr = new Array(n + 1);
|
|
361
|
-
for (let i = 1; i <= m; i++) {
|
|
362
|
-
const rowMin = fillEditRow({ a, b, i, prev, curr });
|
|
363
|
-
if (rowMin > max) return max + 1;
|
|
364
|
-
[prev, curr] = [curr, prev];
|
|
365
|
-
}
|
|
366
|
-
return prev[n];
|
|
367
|
-
}
|
|
368
|
-
function fillEditRow(args2) {
|
|
369
|
-
const { a, b, i, prev, curr } = args2;
|
|
370
|
-
curr[0] = i;
|
|
371
|
-
let rowMin = curr[0];
|
|
372
|
-
for (let j = 1; j < curr.length; j++) {
|
|
373
|
-
const cost = a.charCodeAt(i - 1) === b.charCodeAt(j - 1) ? 0 : 1;
|
|
374
|
-
const value = Math.min(curr[j - 1] + 1, prev[j] + 1, prev[j - 1] + cost);
|
|
375
|
-
curr[j] = value;
|
|
376
|
-
if (value < rowMin) rowMin = value;
|
|
377
|
-
}
|
|
378
|
-
return rowMin;
|
|
379
|
-
}
|
|
380
416
|
function closestVerbs(typed, verbPaths) {
|
|
381
417
|
const target = typed.toLowerCase();
|
|
382
418
|
const distanceCap = target.length <= 4 ? 2 : 3;
|
|
@@ -983,7 +1019,7 @@ function normalizeTrigger(source) {
|
|
|
983
1019
|
|
|
984
1020
|
// built-in-plugins/extractors/slash/index.ts
|
|
985
1021
|
var ID2 = "slash";
|
|
986
|
-
var SLASH_RE = /(
|
|
1022
|
+
var SLASH_RE = /(?<![A-Za-z0-9_/.:?#])(\/[a-z0-9][a-z0-9_-]*(?::[a-z0-9][a-z0-9_-]*)?)/gi;
|
|
987
1023
|
var slashExtractor = {
|
|
988
1024
|
id: ID2,
|
|
989
1025
|
pluginId: "claude",
|
|
@@ -1126,6 +1162,77 @@ function lineFor(lineStarts, offset) {
|
|
|
1126
1162
|
return lo + 1;
|
|
1127
1163
|
}
|
|
1128
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
|
+
|
|
1129
1236
|
// built-in-plugins/i18n/trigger-collision.texts.ts
|
|
1130
1237
|
var TRIGGER_COLLISION_TEXTS = {
|
|
1131
1238
|
/**
|
|
@@ -1152,14 +1259,14 @@ var TRIGGER_COLLISION_TEXTS = {
|
|
|
1152
1259
|
};
|
|
1153
1260
|
|
|
1154
1261
|
// built-in-plugins/rules/trigger-collision/index.ts
|
|
1155
|
-
var
|
|
1262
|
+
var ID6 = "trigger-collision";
|
|
1156
1263
|
var ADVERTISING_KINDS = /* @__PURE__ */ new Set([
|
|
1157
1264
|
"command",
|
|
1158
1265
|
"skill",
|
|
1159
1266
|
"agent"
|
|
1160
1267
|
]);
|
|
1161
1268
|
var triggerCollisionRule = {
|
|
1162
|
-
id:
|
|
1269
|
+
id: ID6,
|
|
1163
1270
|
pluginId: "core",
|
|
1164
1271
|
kind: "rule",
|
|
1165
1272
|
mode: "deterministic",
|
|
@@ -1259,7 +1366,7 @@ function analyzeTriggerBucket(normalized, claims) {
|
|
|
1259
1366
|
part: parts[0]
|
|
1260
1367
|
});
|
|
1261
1368
|
return {
|
|
1262
|
-
ruleId:
|
|
1369
|
+
ruleId: ID6,
|
|
1263
1370
|
severity: "error",
|
|
1264
1371
|
nodeIds,
|
|
1265
1372
|
message,
|
|
@@ -1278,9 +1385,9 @@ var BROKEN_REF_TEXTS = {
|
|
|
1278
1385
|
};
|
|
1279
1386
|
|
|
1280
1387
|
// built-in-plugins/rules/broken-ref/index.ts
|
|
1281
|
-
var
|
|
1388
|
+
var ID7 = "broken-ref";
|
|
1282
1389
|
var brokenRefRule = {
|
|
1283
|
-
id:
|
|
1390
|
+
id: ID7,
|
|
1284
1391
|
pluginId: "core",
|
|
1285
1392
|
kind: "rule",
|
|
1286
1393
|
version: "1.0.0",
|
|
@@ -1294,7 +1401,7 @@ var brokenRefRule = {
|
|
|
1294
1401
|
for (const link2 of ctx.links) {
|
|
1295
1402
|
if (isResolved(link2, byPath3, byNormalizedName)) continue;
|
|
1296
1403
|
issues.push({
|
|
1297
|
-
ruleId:
|
|
1404
|
+
ruleId: ID7,
|
|
1298
1405
|
severity: "warn",
|
|
1299
1406
|
nodeIds: [link2.source],
|
|
1300
1407
|
message: tx(BROKEN_REF_TEXTS.message, {
|
|
@@ -1342,9 +1449,9 @@ var SUPERSEDED_TEXTS = {
|
|
|
1342
1449
|
};
|
|
1343
1450
|
|
|
1344
1451
|
// built-in-plugins/rules/superseded/index.ts
|
|
1345
|
-
var
|
|
1452
|
+
var ID8 = "superseded";
|
|
1346
1453
|
var supersededRule = {
|
|
1347
|
-
id:
|
|
1454
|
+
id: ID8,
|
|
1348
1455
|
pluginId: "core",
|
|
1349
1456
|
kind: "rule",
|
|
1350
1457
|
version: "1.0.0",
|
|
@@ -1359,7 +1466,7 @@ var supersededRule = {
|
|
|
1359
1466
|
const supersededBy = meta["supersededBy"];
|
|
1360
1467
|
if (typeof supersededBy !== "string" || supersededBy.length === 0) continue;
|
|
1361
1468
|
issues.push({
|
|
1362
|
-
ruleId:
|
|
1469
|
+
ruleId: ID8,
|
|
1363
1470
|
severity: "info",
|
|
1364
1471
|
nodeIds: [node.path],
|
|
1365
1472
|
message: tx(SUPERSEDED_TEXTS.message, {
|
|
@@ -1380,9 +1487,9 @@ var LINK_CONFLICT_TEXTS = {
|
|
|
1380
1487
|
};
|
|
1381
1488
|
|
|
1382
1489
|
// built-in-plugins/rules/link-conflict/index.ts
|
|
1383
|
-
var
|
|
1490
|
+
var ID9 = "link-conflict";
|
|
1384
1491
|
var linkConflictRule = {
|
|
1385
|
-
id:
|
|
1492
|
+
id: ID9,
|
|
1386
1493
|
pluginId: "core",
|
|
1387
1494
|
kind: "rule",
|
|
1388
1495
|
version: "1.0.0",
|
|
@@ -1431,7 +1538,7 @@ var linkConflictRule = {
|
|
|
1431
1538
|
const [source, target] = key.split("\0");
|
|
1432
1539
|
const kindList = variants.map((v) => v.kind).join(" / ");
|
|
1433
1540
|
issues.push({
|
|
1434
|
-
ruleId:
|
|
1541
|
+
ruleId: ID9,
|
|
1435
1542
|
severity: "warn",
|
|
1436
1543
|
nodeIds: [source, target],
|
|
1437
1544
|
message: tx(LINK_CONFLICT_TEXTS.message, {
|
|
@@ -1477,10 +1584,10 @@ var ASCII_FORMATTER_TEXTS = {
|
|
|
1477
1584
|
};
|
|
1478
1585
|
|
|
1479
1586
|
// built-in-plugins/formatters/ascii/index.ts
|
|
1480
|
-
var
|
|
1587
|
+
var ID10 = "ascii";
|
|
1481
1588
|
var KIND_ORDER = ["agent", "command", "hook", "skill", "note"];
|
|
1482
1589
|
var asciiFormatter = {
|
|
1483
|
-
id:
|
|
1590
|
+
id: ID10,
|
|
1484
1591
|
pluginId: "core",
|
|
1485
1592
|
kind: "formatter",
|
|
1486
1593
|
version: "1.0.0",
|
|
@@ -1743,9 +1850,9 @@ var VALIDATE_ALL_TEXTS = {
|
|
|
1743
1850
|
};
|
|
1744
1851
|
|
|
1745
1852
|
// built-in-plugins/rules/validate-all/index.ts
|
|
1746
|
-
var
|
|
1853
|
+
var ID11 = "validate-all";
|
|
1747
1854
|
var validateAllRule = {
|
|
1748
|
-
id:
|
|
1855
|
+
id: ID11,
|
|
1749
1856
|
pluginId: "core",
|
|
1750
1857
|
kind: "rule",
|
|
1751
1858
|
version: "1.0.0",
|
|
@@ -1768,7 +1875,7 @@ function collectNodeFindings(v, node, out) {
|
|
|
1768
1875
|
const result = v.validate("node", toNodeForSchema(node));
|
|
1769
1876
|
if (result.ok) return;
|
|
1770
1877
|
out.push({
|
|
1771
|
-
ruleId:
|
|
1878
|
+
ruleId: ID11,
|
|
1772
1879
|
severity: "error",
|
|
1773
1880
|
nodeIds: [node.path],
|
|
1774
1881
|
message: tx(VALIDATE_ALL_TEXTS.nodeFailure, {
|
|
@@ -1782,7 +1889,7 @@ function collectLinkFindings(v, link2, out) {
|
|
|
1782
1889
|
const result = v.validate("link", toLinkForSchema(link2));
|
|
1783
1890
|
if (result.ok) return;
|
|
1784
1891
|
out.push({
|
|
1785
|
-
ruleId:
|
|
1892
|
+
ruleId: ID11,
|
|
1786
1893
|
severity: "error",
|
|
1787
1894
|
nodeIds: [link2.source],
|
|
1788
1895
|
message: tx(VALIDATE_ALL_TEXTS.linkFailure, {
|
|
@@ -1843,6 +1950,7 @@ var builtInBundles = [
|
|
|
1843
1950
|
granularity: "extension",
|
|
1844
1951
|
extensions: [
|
|
1845
1952
|
externalUrlCounterExtractor,
|
|
1953
|
+
markdownLinkExtractor,
|
|
1846
1954
|
triggerCollisionRule,
|
|
1847
1955
|
brokenRefRule,
|
|
1848
1956
|
supersededRule,
|
|
@@ -2850,7 +2958,7 @@ var AsyncMutex = class {
|
|
|
2850
2958
|
this.#locked = true;
|
|
2851
2959
|
return;
|
|
2852
2960
|
}
|
|
2853
|
-
await new Promise((
|
|
2961
|
+
await new Promise((resolve21) => this.#waiters.push(resolve21));
|
|
2854
2962
|
this.#locked = true;
|
|
2855
2963
|
}
|
|
2856
2964
|
unlock() {
|
|
@@ -4097,6 +4205,7 @@ async function loadNodeEnrichments(db, nodePath) {
|
|
|
4097
4205
|
}));
|
|
4098
4206
|
}
|
|
4099
4207
|
function parseJsonObject(s) {
|
|
4208
|
+
if (s === null || s === void 0) return {};
|
|
4100
4209
|
const parsed = JSON.parse(s);
|
|
4101
4210
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
4102
4211
|
return parsed;
|
|
@@ -4104,6 +4213,7 @@ function parseJsonObject(s) {
|
|
|
4104
4213
|
return {};
|
|
4105
4214
|
}
|
|
4106
4215
|
function parseJsonArray(s) {
|
|
4216
|
+
if (s === null || s === void 0) return [];
|
|
4107
4217
|
const parsed = JSON.parse(s);
|
|
4108
4218
|
return Array.isArray(parsed) ? parsed : [];
|
|
4109
4219
|
}
|
|
@@ -5114,6 +5224,7 @@ function formatErrorMessage(err) {
|
|
|
5114
5224
|
// cli/i18n/config.texts.ts
|
|
5115
5225
|
var CONFIG_TEXTS = {
|
|
5116
5226
|
unknownKey: "Unknown config key: {{key}}\n",
|
|
5227
|
+
unknownKeySuggestion: "Did you mean {{suggestions}}?\n",
|
|
5117
5228
|
valueWithLayer: "{{value}} (from {{layer}})\n",
|
|
5118
5229
|
invalidAfterSet: "Invalid config after set: {{errors}}\n",
|
|
5119
5230
|
setWritten: "{{key}} = {{value}} (wrote {{path}})\n",
|
|
@@ -5143,6 +5254,29 @@ function assertSafeSegments(segments, key) {
|
|
|
5143
5254
|
if (FORBIDDEN_SEGMENTS.has(seg)) throw new ForbiddenSegmentError(seg, key);
|
|
5144
5255
|
}
|
|
5145
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
|
+
}
|
|
5146
5280
|
function getAtPath(obj, dotPath) {
|
|
5147
5281
|
const segments = dotPath.split(".").filter(Boolean);
|
|
5148
5282
|
assertSafeSegments(segments, dotPath);
|
|
@@ -5244,6 +5378,17 @@ function tryLoadConfig(opts, stderr) {
|
|
|
5244
5378
|
return { ok: false, exitCode: ExitCode.Error };
|
|
5245
5379
|
}
|
|
5246
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
|
+
}
|
|
5247
5392
|
function* iterDotPaths(obj, prefix = "") {
|
|
5248
5393
|
if (obj === null || typeof obj !== "object" || Array.isArray(obj)) {
|
|
5249
5394
|
if (prefix) yield [prefix, obj];
|
|
@@ -5321,18 +5466,13 @@ var ConfigGetCommand = class extends SmCommand {
|
|
|
5321
5466
|
if (!result.ok) return result.exitCode;
|
|
5322
5467
|
const { effective, warnings } = result.loaded;
|
|
5323
5468
|
for (const w of warnings) this.context.stderr.write(w + "\n");
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
} catch (err) {
|
|
5328
|
-
if (err instanceof ForbiddenSegmentError) {
|
|
5329
|
-
this.context.stderr.write(tx(CONFIG_TEXTS.forbiddenKeySegment, { segment: err.segment, key: err.key }));
|
|
5330
|
-
return ExitCode.Error;
|
|
5331
|
-
}
|
|
5332
|
-
throw err;
|
|
5333
|
-
}
|
|
5469
|
+
const lookup = safeGetAtPath(effective, this.key, this.context.stderr);
|
|
5470
|
+
if (!lookup.ok) return lookup.exitCode;
|
|
5471
|
+
const { value } = lookup;
|
|
5334
5472
|
if (value === void 0) {
|
|
5335
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);
|
|
5336
5476
|
return ExitCode.NotFound;
|
|
5337
5477
|
}
|
|
5338
5478
|
if (this.json) {
|
|
@@ -6195,9 +6335,9 @@ var DB_TEXTS = {
|
|
|
6195
6335
|
migrateKernelUpToDate: "kernel \xB7 Already up to date.\n",
|
|
6196
6336
|
migrateKernelApplied: "kernel \xB7 Applied {{count}} migration(s)\n",
|
|
6197
6337
|
migrateKernelAppliedWithBackup: "kernel \xB7 Applied {{count}} migration(s) \xB7 backup: {{backupPath}}\n",
|
|
6198
|
-
// --- shell
|
|
6338
|
+
// --- shell (system sqlite3 binary required for the interactive REPL) ---
|
|
6199
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",
|
|
6200
|
-
|
|
6340
|
+
// --- dump (pure node:sqlite, no external binary) ----------------------
|
|
6201
6341
|
dumpInvalidTable: "--tables: refusing non-identifier name {{table}}. Table names must match [a-zA-Z_][a-zA-Z0-9_]*\n",
|
|
6202
6342
|
// --- plugin migration runner -----------------------------------------
|
|
6203
6343
|
pluginMigrateFailure: "plugin {{pluginId}} \xB7 {{reason}}\n",
|
|
@@ -6488,18 +6628,12 @@ var DbDumpCommand = class extends SmCommand {
|
|
|
6488
6628
|
static usage = Command5.Usage({
|
|
6489
6629
|
category: "Database",
|
|
6490
6630
|
description: "SQL dump to stdout.",
|
|
6491
|
-
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."
|
|
6492
6632
|
});
|
|
6493
6633
|
tables = Option5.Array("--tables", { required: false });
|
|
6494
|
-
// CLI orchestrator: each branch (db existence, per-table identifier
|
|
6495
|
-
// gate, sqlite3-not-found fallback, exit-status passthrough) is a
|
|
6496
|
-
// single dispatcher decision. Splitting per branch scatters the gate
|
|
6497
|
-
// away from the value it gates.
|
|
6498
|
-
// eslint-disable-next-line complexity
|
|
6499
6634
|
async run() {
|
|
6500
6635
|
const path = resolveDbPath({ global: this.global, db: this.db, ...defaultRuntimeContext() });
|
|
6501
6636
|
if (!assertDbExists(path, this.context.stderr)) return ExitCode.NotFound;
|
|
6502
|
-
const args2 = ["-readonly", path, ".dump"];
|
|
6503
6637
|
if (this.tables && this.tables.length > 0) {
|
|
6504
6638
|
for (const t of this.tables) {
|
|
6505
6639
|
if (!SAFE_SQL_IDENTIFIER_RE.test(t)) {
|
|
@@ -6507,16 +6641,65 @@ var DbDumpCommand = class extends SmCommand {
|
|
|
6507
6641
|
return ExitCode.Error;
|
|
6508
6642
|
}
|
|
6509
6643
|
}
|
|
6510
|
-
args2.push(...this.tables);
|
|
6511
6644
|
}
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
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
|
+
`);
|
|
6515
6651
|
return ExitCode.Error;
|
|
6516
6652
|
}
|
|
6517
|
-
return result.status ?? 0;
|
|
6518
6653
|
}
|
|
6519
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
|
+
}
|
|
6520
6703
|
var DbMigrateCommand = class extends SmCommand {
|
|
6521
6704
|
static paths = [["db", "migrate"]];
|
|
6522
6705
|
static usage = Command5.Usage({
|
|
@@ -6906,18 +7089,19 @@ var ExportCommand = class extends SmCommand {
|
|
|
6906
7089
|
(POSIX glob \u2014 \`*\` matches a single segment, \`**\` matches across
|
|
6907
7090
|
segments).
|
|
6908
7091
|
|
|
6909
|
-
Pass an empty query (\`""\`)
|
|
7092
|
+
Pass an empty query (\`""\`) \u2014 or omit the argument entirely \u2014 to
|
|
7093
|
+
export every node.
|
|
6910
7094
|
|
|
6911
7095
|
Run \`sm scan\` first to populate the DB.
|
|
6912
7096
|
`,
|
|
6913
7097
|
examples: [
|
|
7098
|
+
["Whole graph (no query)", "$0 export --format md"],
|
|
6914
7099
|
["Every command node", '$0 export "kind=command" --format json'],
|
|
6915
7100
|
["Skills + agents with issues", '$0 export "kind=skill,agent has=issues" --format md'],
|
|
6916
|
-
["Files under a path glob", '$0 export "path=.claude/commands/**" --format json']
|
|
6917
|
-
["Whole graph as Markdown", '$0 export "" --format md']
|
|
7101
|
+
["Files under a path glob", '$0 export "path=.claude/commands/**" --format json']
|
|
6918
7102
|
]
|
|
6919
7103
|
});
|
|
6920
|
-
query = Option6.String({ required:
|
|
7104
|
+
query = Option6.String({ required: false });
|
|
6921
7105
|
format = Option6.String("--format", { required: false });
|
|
6922
7106
|
async run() {
|
|
6923
7107
|
const format = (this.format ?? "json").toLowerCase();
|
|
@@ -6942,7 +7126,7 @@ var ExportCommand = class extends SmCommand {
|
|
|
6942
7126
|
}
|
|
6943
7127
|
let parsedQuery;
|
|
6944
7128
|
try {
|
|
6945
|
-
parsedQuery = parseExportQuery(this.query);
|
|
7129
|
+
parsedQuery = parseExportQuery(this.query ?? "");
|
|
6946
7130
|
} catch (err) {
|
|
6947
7131
|
if (err instanceof ExportQueryError) {
|
|
6948
7132
|
this.context.stderr.write(tx(EXPORT_TEXTS.errorPrefix, { message: err.message }));
|
|
@@ -7169,16 +7353,109 @@ var GraphCommand = class extends SmCommand {
|
|
|
7169
7353
|
}
|
|
7170
7354
|
};
|
|
7171
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 "ejecut\xE1 @sm-guide.md" 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 load the file as a skill by
|
|
7385
|
+
typing "ejecut\xE1 @sm-guide.md". Top-level only \u2014 no subdirectory
|
|
7386
|
+
is created.
|
|
7387
|
+
|
|
7388
|
+
Does NOT require an initialized .skill-map/ project. Refuses to
|
|
7389
|
+
overwrite an existing sm-guide.md unless --force is passed.
|
|
7390
|
+
`,
|
|
7391
|
+
examples: [
|
|
7392
|
+
["Materialize the guide in the cwd", "$0 guide"],
|
|
7393
|
+
["Overwrite an existing sm-guide.md", "$0 guide --force"]
|
|
7394
|
+
]
|
|
7395
|
+
});
|
|
7396
|
+
force = Option8.Boolean("--force", false, {
|
|
7397
|
+
description: "Overwrite an existing sm-guide.md without prompting."
|
|
7398
|
+
});
|
|
7399
|
+
async run() {
|
|
7400
|
+
const ctx = defaultRuntimeContext();
|
|
7401
|
+
const target = join10(ctx.cwd, SM_GUIDE_FILENAME);
|
|
7402
|
+
if (await pathExists(target) && !this.force) {
|
|
7403
|
+
this.context.stderr.write(tx(GUIDE_TEXTS.alreadyExists, { cwd: ctx.cwd }));
|
|
7404
|
+
return ExitCode.Error;
|
|
7405
|
+
}
|
|
7406
|
+
let body;
|
|
7407
|
+
try {
|
|
7408
|
+
body = loadBundledGuideText();
|
|
7409
|
+
} catch {
|
|
7410
|
+
this.context.stderr.write(GUIDE_TEXTS.sourceMissing);
|
|
7411
|
+
return ExitCode.Error;
|
|
7412
|
+
}
|
|
7413
|
+
try {
|
|
7414
|
+
await writeFile(target, body);
|
|
7415
|
+
} catch (err) {
|
|
7416
|
+
this.context.stderr.write(
|
|
7417
|
+
tx(GUIDE_TEXTS.writeFailed, { message: formatErrorMessage(err) })
|
|
7418
|
+
);
|
|
7419
|
+
return ExitCode.Error;
|
|
7420
|
+
}
|
|
7421
|
+
this.context.stdout.write(tx(GUIDE_TEXTS.written, { cwd: ctx.cwd }));
|
|
7422
|
+
return ExitCode.Ok;
|
|
7423
|
+
}
|
|
7424
|
+
};
|
|
7425
|
+
var cachedGuide = null;
|
|
7426
|
+
function loadBundledGuideText() {
|
|
7427
|
+
if (cachedGuide !== null) return cachedGuide;
|
|
7428
|
+
cachedGuide = readGuideFromDisk();
|
|
7429
|
+
return cachedGuide;
|
|
7430
|
+
}
|
|
7431
|
+
function readGuideFromDisk() {
|
|
7432
|
+
const here = dirname9(fileURLToPath5(import.meta.url));
|
|
7433
|
+
const candidates = [
|
|
7434
|
+
// dev: src/cli/commands/ → repo-root .claude/skills/sm-guide/SKILL.md
|
|
7435
|
+
resolve13(here, "../../../.claude/skills/sm-guide/SKILL.md"),
|
|
7436
|
+
// bundled: dist/cli.js → dist/cli/guide/sm-guide.md (sibling)
|
|
7437
|
+
resolve13(here, "cli/guide/sm-guide.md"),
|
|
7438
|
+
// bundled fallback: any-depth → cli/guide/sm-guide.md
|
|
7439
|
+
resolve13(here, "../cli/guide/sm-guide.md")
|
|
7440
|
+
];
|
|
7441
|
+
for (const candidate of candidates) {
|
|
7442
|
+
if (existsSync12(candidate)) {
|
|
7443
|
+
return readFileSync10(candidate, "utf8");
|
|
7444
|
+
}
|
|
7445
|
+
}
|
|
7446
|
+
throw new Error(`SKILL.md not found in any candidate location (last tried: ${candidates[candidates.length - 1]})`);
|
|
7447
|
+
}
|
|
7448
|
+
|
|
7172
7449
|
// cli/commands/help.ts
|
|
7173
|
-
import { readFileSync as
|
|
7450
|
+
import { readFileSync as readFileSync11 } from "fs";
|
|
7174
7451
|
import { createRequire as createRequire4 } from "module";
|
|
7175
|
-
import { resolve as
|
|
7176
|
-
import { Command as
|
|
7452
|
+
import { resolve as resolve14 } from "path";
|
|
7453
|
+
import { Command as Command9, Option as Option9 } from "clipanion";
|
|
7177
7454
|
|
|
7178
7455
|
// package.json
|
|
7179
7456
|
var package_default = {
|
|
7180
7457
|
name: "@skill-map/cli",
|
|
7181
|
-
version: "0.
|
|
7458
|
+
version: "0.14.1",
|
|
7182
7459
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
7183
7460
|
license: "MIT",
|
|
7184
7461
|
type: "module",
|
|
@@ -7237,7 +7514,7 @@ var package_default = {
|
|
|
7237
7514
|
},
|
|
7238
7515
|
dependencies: {
|
|
7239
7516
|
"@hono/node-server": "2.0.1",
|
|
7240
|
-
"@skill-map/spec": "
|
|
7517
|
+
"@skill-map/spec": "0.14.1",
|
|
7241
7518
|
ajv: "8.18.0",
|
|
7242
7519
|
"ajv-formats": "3.0.1",
|
|
7243
7520
|
chokidar: "5.0.0",
|
|
@@ -7354,9 +7631,9 @@ var HELP_TEXTS = {
|
|
|
7354
7631
|
};
|
|
7355
7632
|
|
|
7356
7633
|
// cli/commands/help.ts
|
|
7357
|
-
var HelpCommand = class extends
|
|
7634
|
+
var HelpCommand = class extends Command9 {
|
|
7358
7635
|
static paths = [["help"]];
|
|
7359
|
-
static usage =
|
|
7636
|
+
static usage = Command9.Usage({
|
|
7360
7637
|
category: "Introspection",
|
|
7361
7638
|
description: "Self-describing introspection. --format human|md|json.",
|
|
7362
7639
|
details: `
|
|
@@ -7370,8 +7647,8 @@ var HelpCommand = class extends Command8 {
|
|
|
7370
7647
|
json \u2014 structured surface dump per spec/cli-contract.md.
|
|
7371
7648
|
`
|
|
7372
7649
|
});
|
|
7373
|
-
verbParts =
|
|
7374
|
-
format =
|
|
7650
|
+
verbParts = Option9.Rest({ required: 0 });
|
|
7651
|
+
format = Option9.String("--format", "human");
|
|
7375
7652
|
async execute() {
|
|
7376
7653
|
const format = normalizeFormat(this.format);
|
|
7377
7654
|
if (!format) {
|
|
@@ -7493,8 +7770,8 @@ function resolveSpecVersion() {
|
|
|
7493
7770
|
try {
|
|
7494
7771
|
const req = createRequire4(import.meta.url);
|
|
7495
7772
|
const indexPath = req.resolve("@skill-map/spec/index.json");
|
|
7496
|
-
const pkgPath =
|
|
7497
|
-
const pkg = JSON.parse(
|
|
7773
|
+
const pkgPath = resolve14(indexPath, "..", "package.json");
|
|
7774
|
+
const pkg = JSON.parse(readFileSync11(pkgPath, "utf8"));
|
|
7498
7775
|
return pkg.version;
|
|
7499
7776
|
} catch {
|
|
7500
7777
|
return "unknown";
|
|
@@ -7689,7 +7966,7 @@ function renderCompactOverview(verbs) {
|
|
|
7689
7966
|
lines.push(HELP_TEXTS.compactFooter);
|
|
7690
7967
|
return lines.join("\n") + "\n";
|
|
7691
7968
|
}
|
|
7692
|
-
var RootHelpCommand = class extends
|
|
7969
|
+
var RootHelpCommand = class extends Command9 {
|
|
7693
7970
|
static paths = [["-h"], ["--help"]];
|
|
7694
7971
|
async execute() {
|
|
7695
7972
|
const rawDefs = this.cli.definitions();
|
|
@@ -7745,13 +8022,13 @@ function registeredVerbPaths(cli2) {
|
|
|
7745
8022
|
}
|
|
7746
8023
|
|
|
7747
8024
|
// cli/commands/init.ts
|
|
7748
|
-
import { mkdir as mkdir2, readFile as readFile2, writeFile } from "fs/promises";
|
|
7749
|
-
import { join as
|
|
7750
|
-
import { Command as
|
|
8025
|
+
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
8026
|
+
import { join as join11 } from "path";
|
|
8027
|
+
import { Command as Command10, Option as Option10 } from "clipanion";
|
|
7751
8028
|
|
|
7752
8029
|
// kernel/orchestrator.ts
|
|
7753
8030
|
import { createHash } from "crypto";
|
|
7754
|
-
import { existsSync as
|
|
8031
|
+
import { existsSync as existsSync13, statSync as statSync3 } from "fs";
|
|
7755
8032
|
import { Tiktoken } from "js-tiktoken/lite";
|
|
7756
8033
|
import cl100k_base from "js-tiktoken/ranks/cl100k_base";
|
|
7757
8034
|
import yaml2 from "js-yaml";
|
|
@@ -7886,7 +8163,7 @@ function validateRoots(roots) {
|
|
|
7886
8163
|
throw new Error(ORCHESTRATOR_TEXTS.runScanRootEmptyArray);
|
|
7887
8164
|
}
|
|
7888
8165
|
for (const root of roots) {
|
|
7889
|
-
if (!
|
|
8166
|
+
if (!existsSync13(root) || !statSync3(root).isDirectory()) {
|
|
7890
8167
|
throw new Error(tx(ORCHESTRATOR_TEXTS.runScanRootMissing, { root }));
|
|
7891
8168
|
}
|
|
7892
8169
|
}
|
|
@@ -8662,10 +8939,10 @@ function recomputeExternalRefsCount(nodes, externalLinks, cachedPaths) {
|
|
|
8662
8939
|
}
|
|
8663
8940
|
|
|
8664
8941
|
// kernel/scan/watcher.ts
|
|
8665
|
-
import { resolve as
|
|
8942
|
+
import { resolve as resolve15, relative as relative4, sep as sep2 } from "path";
|
|
8666
8943
|
import chokidar from "chokidar";
|
|
8667
8944
|
function createChokidarWatcher(opts) {
|
|
8668
|
-
const absRoots = opts.roots.map((r) =>
|
|
8945
|
+
const absRoots = opts.roots.map((r) => resolve15(opts.cwd, r));
|
|
8669
8946
|
const ignoreFilter = opts.ignoreFilter;
|
|
8670
8947
|
const ignored = ignoreFilter ? (path) => {
|
|
8671
8948
|
const rel = relativePathFromRoots(path, absRoots);
|
|
@@ -8911,7 +9188,7 @@ function createCliProgressEmitter(stderr) {
|
|
|
8911
9188
|
// cli/commands/init.ts
|
|
8912
9189
|
var InitCommand = class extends SmCommand {
|
|
8913
9190
|
static paths = [["init"]];
|
|
8914
|
-
static usage =
|
|
9191
|
+
static usage = Command10.Usage({
|
|
8915
9192
|
category: "Setup",
|
|
8916
9193
|
description: "Bootstrap the current scope: scaffold .skill-map/, provision DB, run first scan.",
|
|
8917
9194
|
details: `
|
|
@@ -8935,16 +9212,16 @@ var InitCommand = class extends SmCommand {
|
|
|
8935
9212
|
["Preview what would be created", "$0 init --dry-run"]
|
|
8936
9213
|
]
|
|
8937
9214
|
});
|
|
8938
|
-
noScan =
|
|
9215
|
+
noScan = Option10.Boolean("--no-scan", false, {
|
|
8939
9216
|
description: "Skip the first scan after scaffolding."
|
|
8940
9217
|
});
|
|
8941
|
-
force =
|
|
9218
|
+
force = Option10.Boolean("--force", false, {
|
|
8942
9219
|
description: "Overwrite an existing settings.json / settings.local.json / .skill-mapignore."
|
|
8943
9220
|
});
|
|
8944
|
-
strict =
|
|
9221
|
+
strict = Option10.Boolean("--strict", false, {
|
|
8945
9222
|
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."
|
|
8946
9223
|
});
|
|
8947
|
-
dryRun =
|
|
9224
|
+
dryRun = Option10.Boolean("-n,--dry-run", false, {
|
|
8948
9225
|
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."
|
|
8949
9226
|
});
|
|
8950
9227
|
// CLI orchestrator: paths setup + dry-run branch (delegated to
|
|
@@ -8955,7 +9232,7 @@ var InitCommand = class extends SmCommand {
|
|
|
8955
9232
|
async run() {
|
|
8956
9233
|
const ctx = defaultRuntimeContext();
|
|
8957
9234
|
const scopeRoot = this.global ? ctx.homedir : ctx.cwd;
|
|
8958
|
-
const skillMapDir =
|
|
9235
|
+
const skillMapDir = join11(scopeRoot, SKILL_MAP_DIR);
|
|
8959
9236
|
const settingsPath = defaultSettingsPath(scopeRoot);
|
|
8960
9237
|
const localPath = defaultLocalSettingsPath(scopeRoot);
|
|
8961
9238
|
const ignorePath = defaultIgnoreFilePath(scopeRoot);
|
|
@@ -8979,17 +9256,17 @@ var InitCommand = class extends SmCommand {
|
|
|
8979
9256
|
return ExitCode.Ok;
|
|
8980
9257
|
}
|
|
8981
9258
|
await mkdir2(skillMapDir, { recursive: true });
|
|
8982
|
-
await
|
|
9259
|
+
await writeFile2(settingsPath, JSON.stringify({ schemaVersion: 1 }, null, 2) + "\n");
|
|
8983
9260
|
if (!await pathExists(localPath) || this.force) {
|
|
8984
|
-
await
|
|
9261
|
+
await writeFile2(localPath, "{}\n");
|
|
8985
9262
|
}
|
|
8986
9263
|
if (!await pathExists(ignorePath) || this.force) {
|
|
8987
|
-
await
|
|
9264
|
+
await writeFile2(ignorePath, loadBundledIgnoreText());
|
|
8988
9265
|
}
|
|
8989
9266
|
if (!this.global) {
|
|
8990
9267
|
const updated = await ensureGitignoreEntries(scopeRoot, GITIGNORE_ENTRIES);
|
|
8991
9268
|
if (updated) {
|
|
8992
|
-
const gitignorePath =
|
|
9269
|
+
const gitignorePath = join11(scopeRoot, ".gitignore");
|
|
8993
9270
|
this.context.stdout.write(
|
|
8994
9271
|
GITIGNORE_ENTRIES.length === 1 ? tx(INIT_TEXTS.gitignoreUpdatedSingular, { path: gitignorePath }) : tx(INIT_TEXTS.gitignoreUpdatedPlural, {
|
|
8995
9272
|
path: gitignorePath,
|
|
@@ -9028,7 +9305,7 @@ async function dryRunFileMessage(path) {
|
|
|
9028
9305
|
}
|
|
9029
9306
|
async function writeDryRunGitignorePlan(stdout, scopeRoot) {
|
|
9030
9307
|
const wouldAdd = await previewGitignoreEntries(scopeRoot, GITIGNORE_ENTRIES);
|
|
9031
|
-
const gitignorePath =
|
|
9308
|
+
const gitignorePath = join11(scopeRoot, ".gitignore");
|
|
9032
9309
|
if (wouldAdd.length === 0) {
|
|
9033
9310
|
stdout.write(tx(INIT_TEXTS.dryRunWouldLeaveGitignoreUnchanged, { path: gitignorePath }));
|
|
9034
9311
|
} else if (wouldAdd.length === 1) {
|
|
@@ -9048,13 +9325,13 @@ async function writeDryRunGitignorePlan(stdout, scopeRoot) {
|
|
|
9048
9325
|
);
|
|
9049
9326
|
}
|
|
9050
9327
|
}
|
|
9051
|
-
async function runFirstScan(scopeRoot,
|
|
9328
|
+
async function runFirstScan(scopeRoot, homedir3, dbPath, strict, stdout, stderr) {
|
|
9052
9329
|
stdout.write(INIT_TEXTS.runningFirstScan);
|
|
9053
9330
|
const kernel = createKernel();
|
|
9054
9331
|
for (const manifest of listBuiltIns()) kernel.registry.register(manifest);
|
|
9055
9332
|
let cfg;
|
|
9056
9333
|
try {
|
|
9057
|
-
cfg = loadConfig({ scope: "project", cwd: scopeRoot, homedir:
|
|
9334
|
+
cfg = loadConfig({ scope: "project", cwd: scopeRoot, homedir: homedir3, strict }).effective;
|
|
9058
9335
|
} catch (err) {
|
|
9059
9336
|
const message = formatErrorMessage(err);
|
|
9060
9337
|
stderr.write(tx(INIT_TEXTS.configLoadFailure, { message }));
|
|
@@ -9103,7 +9380,7 @@ async function runFirstScan(scopeRoot, homedir2, dbPath, strict, stdout, stderr)
|
|
|
9103
9380
|
return hasErrors ? ExitCode.Issues : ExitCode.Ok;
|
|
9104
9381
|
}
|
|
9105
9382
|
async function previewGitignoreEntries(scopeRoot, entries) {
|
|
9106
|
-
const path =
|
|
9383
|
+
const path = join11(scopeRoot, ".gitignore");
|
|
9107
9384
|
const body = await pathExists(path) ? await readFile2(path, "utf8") : "";
|
|
9108
9385
|
const present = new Set(
|
|
9109
9386
|
body.split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"))
|
|
@@ -9111,7 +9388,7 @@ async function previewGitignoreEntries(scopeRoot, entries) {
|
|
|
9111
9388
|
return entries.filter((entry) => !present.has(entry));
|
|
9112
9389
|
}
|
|
9113
9390
|
async function ensureGitignoreEntries(scopeRoot, entries) {
|
|
9114
|
-
const path =
|
|
9391
|
+
const path = join11(scopeRoot, ".gitignore");
|
|
9115
9392
|
let body = "";
|
|
9116
9393
|
if (await pathExists(path)) {
|
|
9117
9394
|
body = await readFile2(path, "utf8");
|
|
@@ -9128,12 +9405,12 @@ async function ensureGitignoreEntries(scopeRoot, entries) {
|
|
|
9128
9405
|
present.add(entry);
|
|
9129
9406
|
changed = true;
|
|
9130
9407
|
}
|
|
9131
|
-
if (changed) await
|
|
9408
|
+
if (changed) await writeFile2(path, body);
|
|
9132
9409
|
return changed;
|
|
9133
9410
|
}
|
|
9134
9411
|
|
|
9135
9412
|
// cli/commands/history.ts
|
|
9136
|
-
import { Command as
|
|
9413
|
+
import { Command as Command11, Option as Option11 } from "clipanion";
|
|
9137
9414
|
|
|
9138
9415
|
// cli/i18n/option-validators.texts.ts
|
|
9139
9416
|
var OPTION_VALIDATORS_TEXTS = {
|
|
@@ -9222,7 +9499,7 @@ function parseStatuses(input, stderr) {
|
|
|
9222
9499
|
}
|
|
9223
9500
|
var HistoryCommand = class extends SmCommand {
|
|
9224
9501
|
static paths = [["history"]];
|
|
9225
|
-
static usage =
|
|
9502
|
+
static usage = Command11.Usage({
|
|
9226
9503
|
category: "History",
|
|
9227
9504
|
description: "Filter execution records. --json emits an array conforming to execution-record.schema.json.",
|
|
9228
9505
|
details: `
|
|
@@ -9242,12 +9519,12 @@ var HistoryCommand = class extends SmCommand {
|
|
|
9242
9519
|
["Machine-readable, scoped to one node", "$0 history -n skills/foo.md --json"]
|
|
9243
9520
|
]
|
|
9244
9521
|
});
|
|
9245
|
-
node =
|
|
9246
|
-
action =
|
|
9247
|
-
status =
|
|
9248
|
-
since =
|
|
9249
|
-
until =
|
|
9250
|
-
limit =
|
|
9522
|
+
node = Option11.String("-n", { required: false });
|
|
9523
|
+
action = Option11.String("--action", { required: false });
|
|
9524
|
+
status = Option11.String("--status", { required: false });
|
|
9525
|
+
since = Option11.String("--since", { required: false });
|
|
9526
|
+
until = Option11.String("--until", { required: false });
|
|
9527
|
+
limit = Option11.String("--limit", { required: false });
|
|
9251
9528
|
// CLI list verb: many optional filter flags (`--node`, `--action`,
|
|
9252
9529
|
// `--status`, `--since`, `--until`, `--limit`, `--json`, `--quiet`)
|
|
9253
9530
|
// each adding a guarded mutation to the filter or render path. Each
|
|
@@ -9295,7 +9572,7 @@ var HistoryCommand = class extends SmCommand {
|
|
|
9295
9572
|
};
|
|
9296
9573
|
var HistoryStatsCommand = class extends SmCommand {
|
|
9297
9574
|
static paths = [["history", "stats"]];
|
|
9298
|
-
static usage =
|
|
9575
|
+
static usage = Command11.Usage({
|
|
9299
9576
|
category: "History",
|
|
9300
9577
|
description: "Aggregate counts, tokens, periods, top nodes, and error rates over state_executions. --json conforms to history-stats.schema.json.",
|
|
9301
9578
|
details: `
|
|
@@ -9313,10 +9590,10 @@ var HistoryStatsCommand = class extends SmCommand {
|
|
|
9313
9590
|
["Top 5 nodes, JSON", "$0 history stats --top 5 --json"]
|
|
9314
9591
|
]
|
|
9315
9592
|
});
|
|
9316
|
-
since =
|
|
9317
|
-
until =
|
|
9318
|
-
period =
|
|
9319
|
-
top =
|
|
9593
|
+
since = Option11.String("--since", { required: false });
|
|
9594
|
+
until = Option11.String("--until", { required: false });
|
|
9595
|
+
period = Option11.String("--period", { required: false });
|
|
9596
|
+
top = Option11.String("--top", { required: false });
|
|
9320
9597
|
// CLI stats verb: range parsing + window flags + period flag + JSON
|
|
9321
9598
|
// branch + per-period iteration. Each branch is a single-purpose
|
|
9322
9599
|
// gate; the data work lives in `aggregateHistoryStats`.
|
|
@@ -9497,11 +9774,11 @@ function formatRow(...cols) {
|
|
|
9497
9774
|
|
|
9498
9775
|
// cli/commands/jobs.ts
|
|
9499
9776
|
import { unlink } from "fs/promises";
|
|
9500
|
-
import { Command as
|
|
9777
|
+
import { Command as Command12, Option as Option12 } from "clipanion";
|
|
9501
9778
|
|
|
9502
9779
|
// kernel/jobs/orphan-files.ts
|
|
9503
9780
|
import { readdirSync as readdirSync6, statSync as statSync4 } from "fs";
|
|
9504
|
-
import { join as
|
|
9781
|
+
import { join as join12, resolve as resolve16 } from "path";
|
|
9505
9782
|
function findOrphanJobFiles(jobsDir, referencedPaths) {
|
|
9506
9783
|
let entries;
|
|
9507
9784
|
try {
|
|
@@ -9516,7 +9793,7 @@ function findOrphanJobFiles(jobsDir, referencedPaths) {
|
|
|
9516
9793
|
const orphans = [];
|
|
9517
9794
|
for (const name of entries) {
|
|
9518
9795
|
if (!name.endsWith(".md")) continue;
|
|
9519
|
-
const abs =
|
|
9796
|
+
const abs = resolve16(join12(jobsDir, name));
|
|
9520
9797
|
if (!referencedPaths.has(abs)) orphans.push(abs);
|
|
9521
9798
|
}
|
|
9522
9799
|
orphans.sort();
|
|
@@ -9545,7 +9822,7 @@ var JOBS_TEXTS = {
|
|
|
9545
9822
|
// cli/commands/jobs.ts
|
|
9546
9823
|
var JobPruneCommand = class extends SmCommand {
|
|
9547
9824
|
static paths = [["job", "prune"]];
|
|
9548
|
-
static usage =
|
|
9825
|
+
static usage = Command12.Usage({
|
|
9549
9826
|
category: "Jobs",
|
|
9550
9827
|
description: "Retention GC for completed / failed jobs (per config policy). --orphan-files removes MD files with no DB row.",
|
|
9551
9828
|
details: `
|
|
@@ -9572,10 +9849,10 @@ var JobPruneCommand = class extends SmCommand {
|
|
|
9572
9849
|
["Preview without touching the DB", "$0 job prune --dry-run --json"]
|
|
9573
9850
|
]
|
|
9574
9851
|
});
|
|
9575
|
-
orphanFiles =
|
|
9852
|
+
orphanFiles = Option12.Boolean("--orphan-files", false, {
|
|
9576
9853
|
description: "Also remove MD files in .skill-map/jobs/ that have no matching state_jobs row."
|
|
9577
9854
|
});
|
|
9578
|
-
dryRun =
|
|
9855
|
+
dryRun = Option12.Boolean("-n,--dry-run", false, {
|
|
9579
9856
|
description: "Report what would be pruned without touching the DB or filesystem."
|
|
9580
9857
|
});
|
|
9581
9858
|
async run() {
|
|
@@ -9692,7 +9969,7 @@ function formatPolicy(seconds) {
|
|
|
9692
9969
|
}
|
|
9693
9970
|
|
|
9694
9971
|
// cli/commands/list.ts
|
|
9695
|
-
import { Command as
|
|
9972
|
+
import { Command as Command13, Option as Option13 } from "clipanion";
|
|
9696
9973
|
|
|
9697
9974
|
// cli/i18n/list.texts.ts
|
|
9698
9975
|
var LIST_TEXTS = {
|
|
@@ -9720,7 +9997,7 @@ var SORT_BY = {
|
|
|
9720
9997
|
var PATH_COL_WIDTH = 50;
|
|
9721
9998
|
var ListCommand = class extends SmCommand {
|
|
9722
9999
|
static paths = [["list"]];
|
|
9723
|
-
static usage =
|
|
10000
|
+
static usage = Command13.Usage({
|
|
9724
10001
|
category: "Browse",
|
|
9725
10002
|
description: "Tabular listing of nodes. --json emits an array conforming to node.schema.json.",
|
|
9726
10003
|
details: `
|
|
@@ -9741,10 +10018,10 @@ var ListCommand = class extends SmCommand {
|
|
|
9741
10018
|
["Only nodes with issues, machine-readable", "$0 list --issue --json"]
|
|
9742
10019
|
]
|
|
9743
10020
|
});
|
|
9744
|
-
kind =
|
|
9745
|
-
issue =
|
|
9746
|
-
sortBy =
|
|
9747
|
-
limit =
|
|
10021
|
+
kind = Option13.String("--kind", { required: false });
|
|
10022
|
+
issue = Option13.Boolean("--issue", false);
|
|
10023
|
+
sortBy = Option13.String("--sort-by", { required: false });
|
|
10024
|
+
limit = Option13.String("--limit", { required: false });
|
|
9748
10025
|
async run() {
|
|
9749
10026
|
let sortColumn = "path";
|
|
9750
10027
|
let sortDirection = "asc";
|
|
@@ -9846,7 +10123,7 @@ function formatRow2(path, kind, out, inCount, ext, issues, bytes) {
|
|
|
9846
10123
|
}
|
|
9847
10124
|
|
|
9848
10125
|
// cli/commands/orphans.ts
|
|
9849
|
-
import { Command as
|
|
10126
|
+
import { Command as Command14, Option as Option14 } from "clipanion";
|
|
9850
10127
|
|
|
9851
10128
|
// cli/i18n/orphans.texts.ts
|
|
9852
10129
|
var ORPHANS_TEXTS = {
|
|
@@ -9901,7 +10178,7 @@ function isStringArray(v) {
|
|
|
9901
10178
|
}
|
|
9902
10179
|
var OrphansCommand = class extends SmCommand {
|
|
9903
10180
|
static paths = [["orphans"]];
|
|
9904
|
-
static usage =
|
|
10181
|
+
static usage = Command14.Usage({
|
|
9905
10182
|
category: "Browse",
|
|
9906
10183
|
description: "List orphan / auto-rename issues from the last scan. --json emits an array conforming to issue.schema.json.",
|
|
9907
10184
|
details: `
|
|
@@ -9916,7 +10193,7 @@ var OrphansCommand = class extends SmCommand {
|
|
|
9916
10193
|
["Just the ambiguous ones, JSON", "$0 orphans --kind ambiguous --json"]
|
|
9917
10194
|
]
|
|
9918
10195
|
});
|
|
9919
|
-
kind =
|
|
10196
|
+
kind = Option14.String("--kind", { required: false });
|
|
9920
10197
|
async run() {
|
|
9921
10198
|
let ruleFilter = null;
|
|
9922
10199
|
if (this.kind !== void 0) {
|
|
@@ -9954,7 +10231,7 @@ var OrphansCommand = class extends SmCommand {
|
|
|
9954
10231
|
};
|
|
9955
10232
|
var OrphansReconcileCommand = class extends SmCommand {
|
|
9956
10233
|
static paths = [["orphans", "reconcile"]];
|
|
9957
|
-
static usage =
|
|
10234
|
+
static usage = Command14.Usage({
|
|
9958
10235
|
category: "Browse",
|
|
9959
10236
|
description: "Migrate state_* FKs from an orphan path to a live node, resolving the orphan issue.",
|
|
9960
10237
|
details: `
|
|
@@ -9970,9 +10247,9 @@ var OrphansReconcileCommand = class extends SmCommand {
|
|
|
9970
10247
|
["Reattach orphan history", "$0 orphans reconcile skills/old.md --to skills/new.md"]
|
|
9971
10248
|
]
|
|
9972
10249
|
});
|
|
9973
|
-
orphanPath =
|
|
9974
|
-
to =
|
|
9975
|
-
dryRun =
|
|
10250
|
+
orphanPath = Option14.String({ required: true });
|
|
10251
|
+
to = Option14.String("--to", { required: true });
|
|
10252
|
+
dryRun = Option14.Boolean("-n,--dry-run", false);
|
|
9976
10253
|
async run() {
|
|
9977
10254
|
const dbPath = resolveDbPath({ global: this.global, db: this.db, ...defaultRuntimeContext() });
|
|
9978
10255
|
if (!assertDbExists(dbPath, this.context.stderr)) return ExitCode.NotFound;
|
|
@@ -10042,7 +10319,7 @@ var OrphansReconcileCommand = class extends SmCommand {
|
|
|
10042
10319
|
};
|
|
10043
10320
|
var OrphansUndoRenameCommand = class extends SmCommand {
|
|
10044
10321
|
static paths = [["orphans", "undo-rename"]];
|
|
10045
|
-
static usage =
|
|
10322
|
+
static usage = Command14.Usage({
|
|
10046
10323
|
category: "Browse",
|
|
10047
10324
|
description: "Reverse a medium- or ambiguous-confidence auto-rename. Migrates state_* FKs back, emits a new orphan on the prior path.",
|
|
10048
10325
|
details: `
|
|
@@ -10062,10 +10339,10 @@ var OrphansUndoRenameCommand = class extends SmCommand {
|
|
|
10062
10339
|
["Undo an ambiguous, picking a candidate", "$0 orphans undo-rename skills/new.md --from skills/old-a.md"]
|
|
10063
10340
|
]
|
|
10064
10341
|
});
|
|
10065
|
-
newPath =
|
|
10066
|
-
from =
|
|
10067
|
-
force =
|
|
10068
|
-
dryRun =
|
|
10342
|
+
newPath = Option14.String({ required: true });
|
|
10343
|
+
from = Option14.String("--from", { required: false });
|
|
10344
|
+
force = Option14.Boolean("--force", false);
|
|
10345
|
+
dryRun = Option14.Boolean("-n,--dry-run", false);
|
|
10069
10346
|
async run() {
|
|
10070
10347
|
const dbPath = resolveDbPath({ global: this.global, db: this.db, ...defaultRuntimeContext() });
|
|
10071
10348
|
if (!assertDbExists(dbPath, this.context.stderr)) return ExitCode.NotFound;
|
|
@@ -10229,9 +10506,9 @@ var ORPHANS_COMMANDS = [
|
|
|
10229
10506
|
];
|
|
10230
10507
|
|
|
10231
10508
|
// cli/commands/plugins.ts
|
|
10232
|
-
import { existsSync as
|
|
10233
|
-
import { join as
|
|
10234
|
-
import { Command as
|
|
10509
|
+
import { existsSync as existsSync14 } from "fs";
|
|
10510
|
+
import { join as join13, resolve as resolve17 } from "path";
|
|
10511
|
+
import { Command as Command15, Option as Option15 } from "clipanion";
|
|
10235
10512
|
|
|
10236
10513
|
// cli/i18n/plugins.texts.ts
|
|
10237
10514
|
var PLUGINS_TEXTS = {
|
|
@@ -10306,9 +10583,9 @@ var PLUGINS_TEXTS = {
|
|
|
10306
10583
|
};
|
|
10307
10584
|
|
|
10308
10585
|
// cli/commands/plugins.ts
|
|
10309
|
-
function resolveSearchPaths2(opts, cwd,
|
|
10310
|
-
if (opts.pluginDir) return [
|
|
10311
|
-
const ctx = { cwd, homedir:
|
|
10586
|
+
function resolveSearchPaths2(opts, cwd, homedir3) {
|
|
10587
|
+
if (opts.pluginDir) return [resolve17(opts.pluginDir)];
|
|
10588
|
+
const ctx = { cwd, homedir: homedir3 };
|
|
10312
10589
|
const project = defaultProjectPluginsDir(ctx);
|
|
10313
10590
|
const user = defaultUserPluginsDir(ctx);
|
|
10314
10591
|
return opts.global ? [user] : [project, user];
|
|
@@ -10376,12 +10653,12 @@ function builtInRows(resolveEnabled) {
|
|
|
10376
10653
|
}
|
|
10377
10654
|
var PluginsListCommand = class extends SmCommand {
|
|
10378
10655
|
static paths = [["plugins", "list"]];
|
|
10379
|
-
static usage =
|
|
10656
|
+
static usage = Command15.Usage({
|
|
10380
10657
|
category: "Plugins",
|
|
10381
10658
|
description: "List discovered plugins and their load status.",
|
|
10382
10659
|
details: "Scans <scope>/.skill-map/plugins and ~/.skill-map/plugins (or --plugin-dir <path>). Built-in bundles (claude, core) are listed alongside user plugins."
|
|
10383
10660
|
});
|
|
10384
|
-
pluginDir =
|
|
10661
|
+
pluginDir = Option15.String("--plugin-dir", { required: false });
|
|
10385
10662
|
async run() {
|
|
10386
10663
|
const plugins = await loadAll({ global: this.global, pluginDir: this.pluginDir });
|
|
10387
10664
|
const resolveEnabled = await buildResolver(this.global);
|
|
@@ -10443,12 +10720,12 @@ function renderPluginRow(p) {
|
|
|
10443
10720
|
}
|
|
10444
10721
|
var PluginsShowCommand = class extends SmCommand {
|
|
10445
10722
|
static paths = [["plugins", "show"]];
|
|
10446
|
-
static usage =
|
|
10723
|
+
static usage = Command15.Usage({
|
|
10447
10724
|
category: "Plugins",
|
|
10448
10725
|
description: "Show a single plugin's manifest + loaded extensions."
|
|
10449
10726
|
});
|
|
10450
|
-
id =
|
|
10451
|
-
pluginDir =
|
|
10727
|
+
id = Option15.String({ required: true });
|
|
10728
|
+
pluginDir = Option15.String("--plugin-dir", { required: false });
|
|
10452
10729
|
async run() {
|
|
10453
10730
|
const plugins = await loadAll({ global: this.global, pluginDir: this.pluginDir });
|
|
10454
10731
|
const resolveEnabled = await buildResolver(this.global);
|
|
@@ -10623,18 +10900,18 @@ function appendUnknownKindWarnings(out, extractorQualifiedId, applicableKinds, k
|
|
|
10623
10900
|
if (!knownKinds.has(k)) out.push({ extractorQualifiedId, unknownKind: k });
|
|
10624
10901
|
}
|
|
10625
10902
|
}
|
|
10626
|
-
function expandHome(p,
|
|
10627
|
-
if (p === "~") return
|
|
10628
|
-
if (p.startsWith("~/")) return
|
|
10903
|
+
function expandHome(p, homedir3) {
|
|
10904
|
+
if (p === "~") return homedir3;
|
|
10905
|
+
if (p.startsWith("~/")) return join13(homedir3, p.slice(2));
|
|
10629
10906
|
return p;
|
|
10630
10907
|
}
|
|
10631
|
-
function collectExplorationDirWarnings(plugins,
|
|
10908
|
+
function collectExplorationDirWarnings(plugins, homedir3) {
|
|
10632
10909
|
const out = [];
|
|
10633
10910
|
forEachProviderInstance(plugins, ({ id, pluginId, instance }) => {
|
|
10634
10911
|
const dir = instance["explorationDir"];
|
|
10635
10912
|
if (typeof dir !== "string" || dir.length === 0) return;
|
|
10636
|
-
const resolved = expandHome(dir,
|
|
10637
|
-
if (!
|
|
10913
|
+
const resolved = expandHome(dir, homedir3);
|
|
10914
|
+
if (!existsSync14(resolved)) {
|
|
10638
10915
|
out.push({
|
|
10639
10916
|
providerQualifiedId: qualifiedExtensionId(pluginId, id),
|
|
10640
10917
|
explorationDir: dir,
|
|
@@ -10646,12 +10923,12 @@ function collectExplorationDirWarnings(plugins, homedir2) {
|
|
|
10646
10923
|
}
|
|
10647
10924
|
var PluginsDoctorCommand = class extends SmCommand {
|
|
10648
10925
|
static paths = [["plugins", "doctor"]];
|
|
10649
|
-
static usage =
|
|
10926
|
+
static usage = Command15.Usage({
|
|
10650
10927
|
category: "Plugins",
|
|
10651
10928
|
description: "Run the full load pass and summarise by failure mode.",
|
|
10652
10929
|
details: "Exit code 0 when every plugin loads or is intentionally disabled; 1 when any plugin is in an error / incompat state."
|
|
10653
10930
|
});
|
|
10654
|
-
pluginDir =
|
|
10931
|
+
pluginDir = Option15.String("--plugin-dir", { required: false });
|
|
10655
10932
|
// Doctor verb: counts by status + applicableKinds warnings +
|
|
10656
10933
|
// explorationDir warnings + bad-plugins issues, each with its own
|
|
10657
10934
|
// gated render. Branching is intrinsic to the multi-section diagnostic
|
|
@@ -10817,8 +11094,8 @@ function resolveToggleTarget(id, catalogue, verb) {
|
|
|
10817
11094
|
return { key: bundle.id };
|
|
10818
11095
|
}
|
|
10819
11096
|
var TogglePluginsBase = class extends SmCommand {
|
|
10820
|
-
all =
|
|
10821
|
-
id =
|
|
11097
|
+
all = Option15.Boolean("--all", false);
|
|
11098
|
+
id = Option15.String({ required: false });
|
|
10822
11099
|
// eslint-disable-next-line complexity
|
|
10823
11100
|
async toggle(enabled) {
|
|
10824
11101
|
const verb = enabled ? "enable" : "disable";
|
|
@@ -10869,7 +11146,7 @@ var TogglePluginsBase = class extends SmCommand {
|
|
|
10869
11146
|
};
|
|
10870
11147
|
var PluginsEnableCommand = class extends TogglePluginsBase {
|
|
10871
11148
|
static paths = [["plugins", "enable"]];
|
|
10872
|
-
static usage =
|
|
11149
|
+
static usage = Command15.Usage({
|
|
10873
11150
|
category: "Plugins",
|
|
10874
11151
|
description: "Enable a plugin (or --all). Persists in config_plugins.",
|
|
10875
11152
|
details: `
|
|
@@ -10891,7 +11168,7 @@ var PluginsEnableCommand = class extends TogglePluginsBase {
|
|
|
10891
11168
|
};
|
|
10892
11169
|
var PluginsDisableCommand = class extends TogglePluginsBase {
|
|
10893
11170
|
static paths = [["plugins", "disable"]];
|
|
10894
|
-
static usage =
|
|
11171
|
+
static usage = Command15.Usage({
|
|
10895
11172
|
category: "Plugins",
|
|
10896
11173
|
description: "Disable a plugin (or --all). Persists in config_plugins; does not delete files.",
|
|
10897
11174
|
details: `
|
|
@@ -10927,8 +11204,8 @@ var PLUGIN_COMMANDS = [
|
|
|
10927
11204
|
|
|
10928
11205
|
// cli/commands/refresh.ts
|
|
10929
11206
|
import { readFile as readFile3 } from "fs/promises";
|
|
10930
|
-
import { resolve as
|
|
10931
|
-
import { Command as
|
|
11207
|
+
import { resolve as resolve19 } from "path";
|
|
11208
|
+
import { Command as Command16, Option as Option16 } from "clipanion";
|
|
10932
11209
|
|
|
10933
11210
|
// cli/i18n/refresh.texts.ts
|
|
10934
11211
|
var REFRESH_TEXTS = {
|
|
@@ -10957,12 +11234,12 @@ var REFRESH_TEXTS = {
|
|
|
10957
11234
|
};
|
|
10958
11235
|
|
|
10959
11236
|
// cli/util/path-guard.ts
|
|
10960
|
-
import { isAbsolute as isAbsolute3, resolve as
|
|
11237
|
+
import { isAbsolute as isAbsolute3, resolve as resolve18, sep as sep3 } from "path";
|
|
10961
11238
|
function assertContained2(cwd, rel) {
|
|
10962
11239
|
if (isAbsolute3(rel)) {
|
|
10963
11240
|
throw new Error(`node path is absolute, refusing to read: ${rel}`);
|
|
10964
11241
|
}
|
|
10965
|
-
const abs =
|
|
11242
|
+
const abs = resolve18(cwd, rel);
|
|
10966
11243
|
if (abs !== cwd && !abs.startsWith(cwd + sep3)) {
|
|
10967
11244
|
throw new Error(`node path escapes repo root: ${rel}`);
|
|
10968
11245
|
}
|
|
@@ -10971,7 +11248,7 @@ function assertContained2(cwd, rel) {
|
|
|
10971
11248
|
// cli/commands/refresh.ts
|
|
10972
11249
|
var RefreshCommand = class extends SmCommand {
|
|
10973
11250
|
static paths = [["refresh"]];
|
|
10974
|
-
static usage =
|
|
11251
|
+
static usage = Command16.Usage({
|
|
10975
11252
|
category: "Scan",
|
|
10976
11253
|
description: "Refresh enrichment rows: granular (single node) or batch (every stale row).",
|
|
10977
11254
|
details: `
|
|
@@ -10996,11 +11273,11 @@ var RefreshCommand = class extends SmCommand {
|
|
|
10996
11273
|
["Refresh every node with stale enrichments", "$0 refresh --stale"]
|
|
10997
11274
|
]
|
|
10998
11275
|
});
|
|
10999
|
-
nodePath =
|
|
11000
|
-
stale =
|
|
11276
|
+
nodePath = Option16.String({ name: "node", required: false });
|
|
11277
|
+
stale = Option16.Boolean("--stale", false, {
|
|
11001
11278
|
description: "Refresh every node whose probabilistic enrichment row is flagged stale=1."
|
|
11002
11279
|
});
|
|
11003
|
-
noPlugins =
|
|
11280
|
+
noPlugins = Option16.Boolean("--no-plugins", false, {
|
|
11004
11281
|
description: "Skip drop-in plugin discovery; use only the built-in extractor set."
|
|
11005
11282
|
});
|
|
11006
11283
|
// The remaining cyclomatic count comes from CLI ergonomics that don't
|
|
@@ -11136,7 +11413,7 @@ var RefreshCommand = class extends SmCommand {
|
|
|
11136
11413
|
let body;
|
|
11137
11414
|
try {
|
|
11138
11415
|
assertContained2(cwd, node.path);
|
|
11139
|
-
const raw = await readFile3(
|
|
11416
|
+
const raw = await readFile3(resolve19(cwd, node.path), "utf8");
|
|
11140
11417
|
body = stripFrontmatterFence(raw);
|
|
11141
11418
|
} catch (err) {
|
|
11142
11419
|
this.context.stderr.write(
|
|
@@ -11185,7 +11462,7 @@ function stripFrontmatterFence(text) {
|
|
|
11185
11462
|
var REFRESH_COMMANDS = [RefreshCommand];
|
|
11186
11463
|
|
|
11187
11464
|
// cli/commands/scan.ts
|
|
11188
|
-
import { Command as
|
|
11465
|
+
import { Command as Command18, Option as Option18 } from "clipanion";
|
|
11189
11466
|
|
|
11190
11467
|
// cli/i18n/scan.texts.ts
|
|
11191
11468
|
var SCAN_TEXTS = {
|
|
@@ -11377,7 +11654,7 @@ async function runEphemeralPath(opts, dbPath, strict, loadPrior, runScanWith) {
|
|
|
11377
11654
|
}
|
|
11378
11655
|
|
|
11379
11656
|
// cli/commands/watch.ts
|
|
11380
|
-
import { Command as
|
|
11657
|
+
import { Command as Command17, Option as Option17 } from "clipanion";
|
|
11381
11658
|
|
|
11382
11659
|
// cli/i18n/watch.texts.ts
|
|
11383
11660
|
var WATCH_TEXTS = {
|
|
@@ -11556,7 +11833,7 @@ async function runWatchLoop(opts) {
|
|
|
11556
11833
|
}
|
|
11557
11834
|
var WatchCommand = class extends SmCommand {
|
|
11558
11835
|
static paths = [["watch"]];
|
|
11559
|
-
static usage =
|
|
11836
|
+
static usage = Command17.Usage({
|
|
11560
11837
|
category: "Scan",
|
|
11561
11838
|
description: "Watch roots and run an incremental scan after each debounced batch of filesystem events.",
|
|
11562
11839
|
details: `
|
|
@@ -11580,17 +11857,17 @@ var WatchCommand = class extends SmCommand {
|
|
|
11580
11857
|
["Stream ScanResult per batch as ndjson", "$0 watch --json"]
|
|
11581
11858
|
]
|
|
11582
11859
|
});
|
|
11583
|
-
roots =
|
|
11584
|
-
noTokens =
|
|
11860
|
+
roots = Option17.Rest({ name: "roots" });
|
|
11861
|
+
noTokens = Option17.Boolean("--no-tokens", false, {
|
|
11585
11862
|
description: "Skip per-node token counts (cl100k_base BPE)."
|
|
11586
11863
|
});
|
|
11587
|
-
strict =
|
|
11864
|
+
strict = Option17.Boolean("--strict", false, {
|
|
11588
11865
|
description: "Promote frontmatter-validation findings from warn to error inside each batch. Does not change the watcher exit code."
|
|
11589
11866
|
});
|
|
11590
|
-
noPlugins =
|
|
11867
|
+
noPlugins = Option17.Boolean("--no-plugins", false, {
|
|
11591
11868
|
description: "Skip drop-in plugin discovery for the watcher session."
|
|
11592
11869
|
});
|
|
11593
|
-
maxConsecutiveFailures =
|
|
11870
|
+
maxConsecutiveFailures = Option17.String("--max-consecutive-failures", {
|
|
11594
11871
|
required: false,
|
|
11595
11872
|
description: "Shut down with exit 2 after N consecutive batch failures (default 5; 0 disables the breaker)."
|
|
11596
11873
|
});
|
|
@@ -11628,7 +11905,7 @@ function parseBreakerLimit(raw, stderr) {
|
|
|
11628
11905
|
// cli/commands/scan.ts
|
|
11629
11906
|
var ScanCommand = class extends SmCommand {
|
|
11630
11907
|
static paths = [["scan"]];
|
|
11631
|
-
static usage =
|
|
11908
|
+
static usage = Command18.Usage({
|
|
11632
11909
|
category: "Scan",
|
|
11633
11910
|
description: "Scan roots for markdown nodes, run extractors and rules.",
|
|
11634
11911
|
details: `
|
|
@@ -11657,29 +11934,29 @@ var ScanCommand = class extends SmCommand {
|
|
|
11657
11934
|
["What would the next incremental scan persist?", "$0 scan --changed -n --json"]
|
|
11658
11935
|
]
|
|
11659
11936
|
});
|
|
11660
|
-
roots =
|
|
11661
|
-
noBuiltIns =
|
|
11937
|
+
roots = Option18.Rest({ name: "roots" });
|
|
11938
|
+
noBuiltIns = Option18.Boolean("--no-built-ins", false, {
|
|
11662
11939
|
description: "Skip the built-in extension set. Yields a zero-filled ScanResult (kernel-empty-boot parity); skips DB persistence."
|
|
11663
11940
|
});
|
|
11664
|
-
noPlugins =
|
|
11941
|
+
noPlugins = Option18.Boolean("--no-plugins", false, {
|
|
11665
11942
|
description: "Skip drop-in plugin discovery. Only the built-in set runs. Combine with --no-built-ins for a fully empty pipeline."
|
|
11666
11943
|
});
|
|
11667
|
-
noTokens =
|
|
11944
|
+
noTokens = Option18.Boolean("--no-tokens", false, {
|
|
11668
11945
|
description: "Skip per-node token counts (cl100k_base BPE). Leaves node.tokens undefined; spec-valid since the field is optional."
|
|
11669
11946
|
});
|
|
11670
|
-
dryRun =
|
|
11947
|
+
dryRun = Option18.Boolean("-n,--dry-run", false, {
|
|
11671
11948
|
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."
|
|
11672
11949
|
});
|
|
11673
|
-
changed =
|
|
11950
|
+
changed = Option18.Boolean("--changed", false, {
|
|
11674
11951
|
description: "Incremental scan: reuse unchanged nodes from the persisted prior snapshot. Degrades to a full scan if no prior snapshot exists."
|
|
11675
11952
|
});
|
|
11676
|
-
allowEmpty =
|
|
11953
|
+
allowEmpty = Option18.Boolean("--allow-empty", false, {
|
|
11677
11954
|
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."
|
|
11678
11955
|
});
|
|
11679
|
-
strict =
|
|
11956
|
+
strict = Option18.Boolean("--strict", false, {
|
|
11680
11957
|
description: "Promote frontmatter-validation findings from warn to error (exit code 1 on any violation). Overrides scan.strict from config when both are set."
|
|
11681
11958
|
});
|
|
11682
|
-
watch =
|
|
11959
|
+
watch = Option18.Boolean("--watch", false, {
|
|
11683
11960
|
description: "Long-running mode: watch the roots and trigger an incremental scan after each debounced batch of filesystem events. Alias of `sm watch`."
|
|
11684
11961
|
});
|
|
11685
11962
|
async run() {
|
|
@@ -11777,11 +12054,11 @@ var ScanCommand = class extends SmCommand {
|
|
|
11777
12054
|
};
|
|
11778
12055
|
|
|
11779
12056
|
// cli/commands/scan-compare.ts
|
|
11780
|
-
import { existsSync as
|
|
11781
|
-
import { Command as
|
|
12057
|
+
import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
|
|
12058
|
+
import { Command as Command19, Option as Option19 } from "clipanion";
|
|
11782
12059
|
var ScanCompareCommand = class extends SmCommand {
|
|
11783
12060
|
static paths = [["scan", "compare-with"]];
|
|
11784
|
-
static usage =
|
|
12061
|
+
static usage = Command19.Usage({
|
|
11785
12062
|
category: "Scan",
|
|
11786
12063
|
description: "Run a fresh scan in memory and emit a delta against the saved ScanResult dump at <dump>. Read-only.",
|
|
11787
12064
|
details: `
|
|
@@ -11809,15 +12086,15 @@ var ScanCompareCommand = class extends SmCommand {
|
|
|
11809
12086
|
["JSON output for tooling", "$0 scan compare-with baseline.json --json"]
|
|
11810
12087
|
]
|
|
11811
12088
|
});
|
|
11812
|
-
dump =
|
|
11813
|
-
roots =
|
|
11814
|
-
noTokens =
|
|
12089
|
+
dump = Option19.String({ required: true });
|
|
12090
|
+
roots = Option19.Rest({ name: "roots" });
|
|
12091
|
+
noTokens = Option19.Boolean("--no-tokens", false, {
|
|
11815
12092
|
description: "Skip per-node token counts during the fresh scan."
|
|
11816
12093
|
});
|
|
11817
|
-
strict =
|
|
12094
|
+
strict = Option19.Boolean("--strict", false, {
|
|
11818
12095
|
description: "Promote layered-config warnings and frontmatter-validation findings from warn to error."
|
|
11819
12096
|
});
|
|
11820
|
-
noPlugins =
|
|
12097
|
+
noPlugins = Option19.Boolean("--no-plugins", false, {
|
|
11821
12098
|
description: "Skip drop-in plugin discovery."
|
|
11822
12099
|
});
|
|
11823
12100
|
// Cyclomatic count comes from CLI ergonomics: 3 distinct try/catch
|
|
@@ -11888,12 +12165,12 @@ var ScanCompareCommand = class extends SmCommand {
|
|
|
11888
12165
|
}
|
|
11889
12166
|
};
|
|
11890
12167
|
function loadAndValidateDump(path) {
|
|
11891
|
-
if (!
|
|
12168
|
+
if (!existsSync15(path)) {
|
|
11892
12169
|
throw new Error(tx(SCAN_TEXTS.compareDumpNotFound, { path }));
|
|
11893
12170
|
}
|
|
11894
12171
|
let raw;
|
|
11895
12172
|
try {
|
|
11896
|
-
raw =
|
|
12173
|
+
raw = readFileSync12(path, "utf8");
|
|
11897
12174
|
} catch (err) {
|
|
11898
12175
|
const message = formatErrorMessage(err);
|
|
11899
12176
|
throw new Error(tx(SCAN_TEXTS.compareDumpReadFailed, { path, message }), { cause: err });
|
|
@@ -12002,8 +12279,8 @@ function renderDeltaIssues(issues) {
|
|
|
12002
12279
|
|
|
12003
12280
|
// cli/commands/serve.ts
|
|
12004
12281
|
import { spawn } from "child_process";
|
|
12005
|
-
import { existsSync as
|
|
12006
|
-
import { Command as
|
|
12282
|
+
import { existsSync as existsSync19 } from "fs";
|
|
12283
|
+
import { Command as Command20, Option as Option20 } from "clipanion";
|
|
12007
12284
|
|
|
12008
12285
|
// server/index.ts
|
|
12009
12286
|
import { serve } from "@hono/node-server";
|
|
@@ -12184,7 +12461,7 @@ function contentTypeFor(format) {
|
|
|
12184
12461
|
}
|
|
12185
12462
|
|
|
12186
12463
|
// server/health.ts
|
|
12187
|
-
import { existsSync as
|
|
12464
|
+
import { existsSync as existsSync16 } from "fs";
|
|
12188
12465
|
var FALLBACK_SCHEMA_VERSION = "1";
|
|
12189
12466
|
function buildHealth(deps) {
|
|
12190
12467
|
return {
|
|
@@ -12193,7 +12470,7 @@ function buildHealth(deps) {
|
|
|
12193
12470
|
specVersion: deps.specVersion,
|
|
12194
12471
|
implVersion: VERSION,
|
|
12195
12472
|
scope: deps.scope,
|
|
12196
|
-
db:
|
|
12473
|
+
db: existsSync16(deps.dbPath) ? "present" : "missing"
|
|
12197
12474
|
};
|
|
12198
12475
|
}
|
|
12199
12476
|
async function resolveSpecVersion2() {
|
|
@@ -12633,9 +12910,9 @@ function emptyScanResult() {
|
|
|
12633
12910
|
}
|
|
12634
12911
|
|
|
12635
12912
|
// server/static.ts
|
|
12636
|
-
import { existsSync as
|
|
12913
|
+
import { existsSync as existsSync17 } from "fs";
|
|
12637
12914
|
import { readFile as readFile5 } from "fs/promises";
|
|
12638
|
-
import { extname, join as
|
|
12915
|
+
import { extname, join as join14 } from "path";
|
|
12639
12916
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
12640
12917
|
var INDEX_HTML = "index.html";
|
|
12641
12918
|
var PLACEHOLDER_HTML = `<!doctype html>
|
|
@@ -12666,8 +12943,8 @@ function createSpaFallback(uiDist) {
|
|
|
12666
12943
|
return async (c, _next) => {
|
|
12667
12944
|
if (c.req.method !== "GET" && c.req.method !== "HEAD") return c.notFound();
|
|
12668
12945
|
if (uiDist === null) return htmlResponse(c, PLACEHOLDER_HTML);
|
|
12669
|
-
const indexPath =
|
|
12670
|
-
if (!
|
|
12946
|
+
const indexPath = join14(uiDist, INDEX_HTML);
|
|
12947
|
+
if (!existsSync17(indexPath)) return htmlResponse(c, PLACEHOLDER_HTML);
|
|
12671
12948
|
return fileResponse(c, indexPath);
|
|
12672
12949
|
};
|
|
12673
12950
|
}
|
|
@@ -13257,10 +13534,10 @@ function validateWatcherDebounce(value) {
|
|
|
13257
13534
|
}
|
|
13258
13535
|
|
|
13259
13536
|
// server/paths.ts
|
|
13260
|
-
import { existsSync as
|
|
13261
|
-
import { dirname as
|
|
13262
|
-
import { fileURLToPath as
|
|
13263
|
-
var DEFAULT_UI_REL =
|
|
13537
|
+
import { existsSync as existsSync18, statSync as statSync5 } from "fs";
|
|
13538
|
+
import { dirname as dirname10, isAbsolute as isAbsolute5, join as join15, resolve as resolve20 } from "path";
|
|
13539
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
13540
|
+
var DEFAULT_UI_REL = join15("ui", "dist", "ui", "browser");
|
|
13264
13541
|
var PACKAGE_UI_REL = "ui";
|
|
13265
13542
|
var INDEX_HTML2 = "index.html";
|
|
13266
13543
|
function resolveDefaultUiDist(ctx) {
|
|
@@ -13269,13 +13546,13 @@ function resolveDefaultUiDist(ctx) {
|
|
|
13269
13546
|
return walkUpForUi(ctx.cwd);
|
|
13270
13547
|
}
|
|
13271
13548
|
function resolveExplicitUiDist(ctx, raw) {
|
|
13272
|
-
return isAbsolute5(raw) ? raw :
|
|
13549
|
+
return isAbsolute5(raw) ? raw : resolve20(ctx.cwd, raw);
|
|
13273
13550
|
}
|
|
13274
13551
|
function isUiBundleDir(path) {
|
|
13275
|
-
if (!
|
|
13552
|
+
if (!existsSync18(path)) return false;
|
|
13276
13553
|
try {
|
|
13277
13554
|
if (!statSync5(path).isDirectory()) return false;
|
|
13278
|
-
return
|
|
13555
|
+
return existsSync18(join15(path, INDEX_HTML2));
|
|
13279
13556
|
} catch {
|
|
13280
13557
|
return false;
|
|
13281
13558
|
}
|
|
@@ -13283,7 +13560,7 @@ function isUiBundleDir(path) {
|
|
|
13283
13560
|
function resolvePackageBundledUi() {
|
|
13284
13561
|
let here;
|
|
13285
13562
|
try {
|
|
13286
|
-
here =
|
|
13563
|
+
here = dirname10(fileURLToPath6(import.meta.url));
|
|
13287
13564
|
} catch {
|
|
13288
13565
|
return null;
|
|
13289
13566
|
}
|
|
@@ -13292,22 +13569,22 @@ function resolvePackageBundledUi() {
|
|
|
13292
13569
|
function resolvePackageBundledUiFrom(here) {
|
|
13293
13570
|
let current = here;
|
|
13294
13571
|
for (let i = 0; i < 8; i++) {
|
|
13295
|
-
const candidate =
|
|
13572
|
+
const candidate = join15(current, PACKAGE_UI_REL);
|
|
13296
13573
|
if (isUiBundleDir(candidate)) return candidate;
|
|
13297
|
-
const distHere =
|
|
13574
|
+
const distHere = join15(current, "dist", PACKAGE_UI_REL);
|
|
13298
13575
|
if (isUiBundleDir(distHere)) return distHere;
|
|
13299
|
-
const parent =
|
|
13576
|
+
const parent = dirname10(current);
|
|
13300
13577
|
if (parent === current) return null;
|
|
13301
13578
|
current = parent;
|
|
13302
13579
|
}
|
|
13303
13580
|
return null;
|
|
13304
13581
|
}
|
|
13305
13582
|
function walkUpForUi(startDir) {
|
|
13306
|
-
let current =
|
|
13583
|
+
let current = resolve20(startDir);
|
|
13307
13584
|
for (let i = 0; i < 64; i++) {
|
|
13308
|
-
const candidate =
|
|
13585
|
+
const candidate = join15(current, DEFAULT_UI_REL);
|
|
13309
13586
|
if (isUiBundleDir(candidate)) return candidate;
|
|
13310
|
-
const parent =
|
|
13587
|
+
const parent = dirname10(current);
|
|
13311
13588
|
if (parent === current) return null;
|
|
13312
13589
|
current = parent;
|
|
13313
13590
|
}
|
|
@@ -13430,17 +13707,13 @@ function normalizeAddress(addr, fallbackHost, fallbackPort) {
|
|
|
13430
13707
|
|
|
13431
13708
|
// cli/i18n/serve.texts.ts
|
|
13432
13709
|
var SERVE_TEXTS = {
|
|
13433
|
-
//
|
|
13434
|
-
//
|
|
13435
|
-
//
|
|
13436
|
-
|
|
13437
|
-
//
|
|
13438
|
-
//
|
|
13439
|
-
//
|
|
13440
|
-
// Both end with the Ctrl+C reminder so the operational tail is
|
|
13441
|
-
// identical regardless of branch.
|
|
13442
|
-
bootOpening: "sm serve: opening http://{{host}}:{{port}}/ in your browser. Press Ctrl+C to stop.\n",
|
|
13443
|
-
bootVisitHint: "sm serve: visit http://{{host}}:{{port}}/ in your browser. Press Ctrl+C to stop.\n",
|
|
13710
|
+
// The boot banner (TTY box / flat-line fallback) is rendered by
|
|
13711
|
+
// `cli/util/serve-banner.ts` rather than templated through `tx` —
|
|
13712
|
+
// ANSI escapes + box-drawing aren't a good fit for the flat
|
|
13713
|
+
// `{{name}}` interpolation surface. The flat-mode strings live in
|
|
13714
|
+
// that helper and stay byte-equivalent to the pre-banner format so
|
|
13715
|
+
// existing pipes / redirects ('listening on <url>' scrapers) don't
|
|
13716
|
+
// break.
|
|
13444
13717
|
// Browser-open failure. Non-fatal — the URL is already printed; the
|
|
13445
13718
|
// user can open it manually.
|
|
13446
13719
|
openFailed: "sm serve: could not auto-open browser ({{message}}). Visit {{url}} manually.\n",
|
|
@@ -13464,10 +13737,150 @@ var SERVE_TEXTS = {
|
|
|
13464
13737
|
shutdown: "sm serve: shutdown complete.\n"
|
|
13465
13738
|
};
|
|
13466
13739
|
|
|
13740
|
+
// cli/util/serve-banner.ts
|
|
13741
|
+
import { homedir as homedir2 } from "os";
|
|
13742
|
+
import { relative as relative5, isAbsolute as isAbsolute6 } from "path";
|
|
13743
|
+
var ESC = {
|
|
13744
|
+
reset: "\x1B[0m",
|
|
13745
|
+
bold: "\x1B[1m",
|
|
13746
|
+
dim: "\x1B[2m",
|
|
13747
|
+
underline: "\x1B[4m",
|
|
13748
|
+
/** 256-color violet (xterm 141). */
|
|
13749
|
+
violet: "\x1B[38;5;141m",
|
|
13750
|
+
/** 256-color green (xterm 42). */
|
|
13751
|
+
green: "\x1B[38;5;42m"
|
|
13752
|
+
};
|
|
13753
|
+
var LOGO_LINES = [
|
|
13754
|
+
" ____ _ _ _ _ __ __ ",
|
|
13755
|
+
" / ___|| | _(_) | | | \\/ | __ _ _ __ ",
|
|
13756
|
+
" \\___ \\| |/ / | | | | |\\/| |/ _` | '_ \\ ",
|
|
13757
|
+
" ___) | <| | | | | | | | (_| | |_) |",
|
|
13758
|
+
" |____/|_|\\_\\_|_|_| |_| |_|\\__,_| .__/ ",
|
|
13759
|
+
" |_| "
|
|
13760
|
+
];
|
|
13761
|
+
var LOGO_WIDTH = 40;
|
|
13762
|
+
function renderBanner(input) {
|
|
13763
|
+
const url = `http://${input.host}:${input.port}`;
|
|
13764
|
+
const dbDisplay = formatDbPath(input.dbPath, input.cwd);
|
|
13765
|
+
const browserLine = input.openBrowser ? "Opening browser\u2026 Press Ctrl+C to stop." : `Visit ${url}/ in your browser. Press Ctrl+C to stop.`;
|
|
13766
|
+
if (!input.isTTY) {
|
|
13767
|
+
return renderFlat({
|
|
13768
|
+
host: input.host,
|
|
13769
|
+
port: input.port,
|
|
13770
|
+
scope: input.scope,
|
|
13771
|
+
dbPath: input.dbPath,
|
|
13772
|
+
openBrowser: input.openBrowser
|
|
13773
|
+
});
|
|
13774
|
+
}
|
|
13775
|
+
return renderFiglet({
|
|
13776
|
+
version: input.version,
|
|
13777
|
+
url,
|
|
13778
|
+
scope: input.scope,
|
|
13779
|
+
dbDisplay,
|
|
13780
|
+
pathDisplay: formatCwdPath(input.cwd),
|
|
13781
|
+
browserLine,
|
|
13782
|
+
colorEnabled: input.colorEnabled
|
|
13783
|
+
});
|
|
13784
|
+
}
|
|
13785
|
+
function resolveColorEnabled(opts) {
|
|
13786
|
+
if (opts.noColorFlag) return false;
|
|
13787
|
+
const noColor = opts.env["NO_COLOR"];
|
|
13788
|
+
if (noColor !== void 0 && noColor !== "") return false;
|
|
13789
|
+
const forceColor = opts.env["FORCE_COLOR"];
|
|
13790
|
+
if (forceColor !== void 0 && forceColor !== "") return true;
|
|
13791
|
+
return opts.isTTY;
|
|
13792
|
+
}
|
|
13793
|
+
function renderFlat(input) {
|
|
13794
|
+
const safeHost = sanitizeForTerminal(input.host);
|
|
13795
|
+
const safeDb = sanitizeForTerminal(input.dbPath);
|
|
13796
|
+
const url = `http://${safeHost}:${input.port}`;
|
|
13797
|
+
const linesOut = [];
|
|
13798
|
+
linesOut.push(`sm serve: listening on ${url} (scope=${input.scope}, db=${safeDb})`);
|
|
13799
|
+
if (input.openBrowser) {
|
|
13800
|
+
linesOut.push(`sm serve: opening ${url}/ in your browser. Press Ctrl+C to stop.`);
|
|
13801
|
+
} else {
|
|
13802
|
+
linesOut.push(`sm serve: visit ${url}/ in your browser. Press Ctrl+C to stop.`);
|
|
13803
|
+
}
|
|
13804
|
+
return linesOut.join("\n") + "\n";
|
|
13805
|
+
}
|
|
13806
|
+
function renderFiglet(input) {
|
|
13807
|
+
const {
|
|
13808
|
+
dimOpen,
|
|
13809
|
+
dimClose,
|
|
13810
|
+
greenUnderline,
|
|
13811
|
+
greenUnderlineClose,
|
|
13812
|
+
violetOpen,
|
|
13813
|
+
violetClose,
|
|
13814
|
+
greenOpen,
|
|
13815
|
+
greenClose
|
|
13816
|
+
} = resolveAnsi(input.colorEnabled);
|
|
13817
|
+
const logoLines = LOGO_LINES.map((line, i) => {
|
|
13818
|
+
const open = i < 3 ? violetOpen : greenOpen;
|
|
13819
|
+
const close = i < 3 ? violetClose : greenClose;
|
|
13820
|
+
return `${open}${line}${close}`;
|
|
13821
|
+
});
|
|
13822
|
+
const versionText = `v${input.version}`;
|
|
13823
|
+
const versionPad = Math.max(0, LOGO_WIDTH - versionText.length);
|
|
13824
|
+
const versionLine = `${" ".repeat(versionPad)}${dimOpen}${versionText}${dimClose}`;
|
|
13825
|
+
const lines = [];
|
|
13826
|
+
lines.push(...logoLines);
|
|
13827
|
+
lines.push("");
|
|
13828
|
+
lines.push(versionLine);
|
|
13829
|
+
lines.push("");
|
|
13830
|
+
lines.push(` ${dimOpen}Server${dimClose} ${greenUnderline}${input.url}${greenUnderlineClose}`);
|
|
13831
|
+
lines.push(` ${dimOpen}Scope${dimClose} ${input.scope}`);
|
|
13832
|
+
lines.push(` ${dimOpen}Path${dimClose} ${input.pathDisplay}`);
|
|
13833
|
+
lines.push(` ${dimOpen}DB${dimClose} ${input.dbDisplay}`);
|
|
13834
|
+
lines.push("");
|
|
13835
|
+
lines.push(` ${dimOpen}${input.browserLine}${dimClose}`);
|
|
13836
|
+
lines.push("");
|
|
13837
|
+
return lines.join("\n") + "\n";
|
|
13838
|
+
}
|
|
13839
|
+
var EMPTY_ANSI = {
|
|
13840
|
+
dimOpen: "",
|
|
13841
|
+
dimClose: "",
|
|
13842
|
+
greenUnderline: "",
|
|
13843
|
+
greenUnderlineClose: "",
|
|
13844
|
+
violetOpen: "",
|
|
13845
|
+
violetClose: "",
|
|
13846
|
+
greenOpen: "",
|
|
13847
|
+
greenClose: ""
|
|
13848
|
+
};
|
|
13849
|
+
var ENABLED_ANSI = {
|
|
13850
|
+
dimOpen: ESC.dim,
|
|
13851
|
+
dimClose: ESC.reset,
|
|
13852
|
+
greenUnderline: `${ESC.green}${ESC.underline}`,
|
|
13853
|
+
greenUnderlineClose: ESC.reset,
|
|
13854
|
+
violetOpen: ESC.violet,
|
|
13855
|
+
violetClose: ESC.reset,
|
|
13856
|
+
greenOpen: ESC.green,
|
|
13857
|
+
greenClose: ESC.reset
|
|
13858
|
+
};
|
|
13859
|
+
function resolveAnsi(colorEnabled) {
|
|
13860
|
+
return colorEnabled ? ENABLED_ANSI : EMPTY_ANSI;
|
|
13861
|
+
}
|
|
13862
|
+
function formatDbPath(dbPath, cwd) {
|
|
13863
|
+
const safe = sanitizeForTerminal(dbPath);
|
|
13864
|
+
if (!isAbsolute6(safe)) return safe;
|
|
13865
|
+
const rel = relative5(cwd, safe);
|
|
13866
|
+
if (rel === "" || rel.startsWith("..") || isAbsolute6(rel)) {
|
|
13867
|
+
return safe;
|
|
13868
|
+
}
|
|
13869
|
+
return rel;
|
|
13870
|
+
}
|
|
13871
|
+
function formatCwdPath(cwd) {
|
|
13872
|
+
const safe = sanitizeForTerminal(cwd);
|
|
13873
|
+
const home = homedir2();
|
|
13874
|
+
if (home && (safe === home || safe.startsWith(`${home}/`))) {
|
|
13875
|
+
return `~${safe.slice(home.length)}`;
|
|
13876
|
+
}
|
|
13877
|
+
return safe;
|
|
13878
|
+
}
|
|
13879
|
+
|
|
13467
13880
|
// cli/commands/serve.ts
|
|
13468
13881
|
var ServeCommand = class extends SmCommand {
|
|
13469
13882
|
static paths = [["serve"]];
|
|
13470
|
-
static usage =
|
|
13883
|
+
static usage = Command20.Usage({
|
|
13471
13884
|
category: "Setup",
|
|
13472
13885
|
description: "Start the Hono BFF (single-port: REST + WebSocket + SPA bundle).",
|
|
13473
13886
|
details: `
|
|
@@ -13492,22 +13905,22 @@ var ServeCommand = class extends SmCommand {
|
|
|
13492
13905
|
["Point at a pre-built UI bundle", "$0 serve --ui-dist ./ui/dist/browser"]
|
|
13493
13906
|
]
|
|
13494
13907
|
});
|
|
13495
|
-
port =
|
|
13908
|
+
port = Option20.String("--port", {
|
|
13496
13909
|
required: false,
|
|
13497
13910
|
description: "Listening port (default 4242). 0 = OS-assigned."
|
|
13498
13911
|
});
|
|
13499
|
-
host =
|
|
13912
|
+
host = Option20.String("--host", {
|
|
13500
13913
|
required: false,
|
|
13501
13914
|
description: "Listening host (default 127.0.0.1). Loopback-only enforced when --dev-cors is set."
|
|
13502
13915
|
});
|
|
13503
|
-
scope =
|
|
13916
|
+
scope = Option20.String("--scope", {
|
|
13504
13917
|
required: false,
|
|
13505
13918
|
description: "project | global. Alias for -g/--global. Default: project."
|
|
13506
13919
|
});
|
|
13507
|
-
noBuiltIns =
|
|
13920
|
+
noBuiltIns = Option20.Boolean("--no-built-ins", false, {
|
|
13508
13921
|
description: "Skip built-in plugin registration (parity with sm scan --no-built-ins)."
|
|
13509
13922
|
});
|
|
13510
|
-
noPlugins =
|
|
13923
|
+
noPlugins = Option20.Boolean("--no-plugins", false, {
|
|
13511
13924
|
description: "Skip drop-in plugin discovery."
|
|
13512
13925
|
});
|
|
13513
13926
|
// `Option.Boolean('--open', true)` — Clipanion's parser auto-derives
|
|
@@ -13517,24 +13930,24 @@ var ServeCommand = class extends SmCommand {
|
|
|
13517
13930
|
// two registrations for the same flag and rejects the invocation
|
|
13518
13931
|
// with "Ambiguous Syntax Error". Same convention shipped by every
|
|
13519
13932
|
// other `--no-...` flag in the CLI tree.
|
|
13520
|
-
open =
|
|
13933
|
+
open = Option20.Boolean("--open", true, {
|
|
13521
13934
|
description: "Auto-open the SPA in the user's default browser after listen. --no-open opts out."
|
|
13522
13935
|
});
|
|
13523
|
-
devCors =
|
|
13936
|
+
devCors = Option20.Boolean("--dev-cors", false, {
|
|
13524
13937
|
description: "Enable permissive CORS for the Angular dev-server proxy workflow."
|
|
13525
13938
|
});
|
|
13526
13939
|
// `--ui-dist` is intentionally undocumented in the Usage block above
|
|
13527
13940
|
// (the demo build pipeline + tests rely on it; everyday users never
|
|
13528
13941
|
// need it). Clipanion still exposes it on the parser; the Usage
|
|
13529
13942
|
// omission is the "hidden" contract per the 14.1 brief.
|
|
13530
|
-
uiDist =
|
|
13531
|
-
noWatcher =
|
|
13943
|
+
uiDist = Option20.String("--ui-dist", { required: false, hidden: true });
|
|
13944
|
+
noWatcher = Option20.Boolean("--no-watcher", false, {
|
|
13532
13945
|
description: "Disable the chokidar-fed scan-and-broadcast loop. Use only for CI / read-only deployments."
|
|
13533
13946
|
});
|
|
13534
13947
|
// `--watcher-debounce-ms` is undocumented sugar for advanced users
|
|
13535
13948
|
// who want to tighten / relax the watcher's batching window without
|
|
13536
13949
|
// editing settings.json. Hidden flag — the Usage block omits it.
|
|
13537
|
-
watcherDebounceMs =
|
|
13950
|
+
watcherDebounceMs = Option20.String("--watcher-debounce-ms", { required: false, hidden: true });
|
|
13538
13951
|
// Long-running daemon — `done in <…>` after a graceful shutdown is
|
|
13539
13952
|
// noise. Mirrors `sm watch`'s opt-out.
|
|
13540
13953
|
emitElapsed = false;
|
|
@@ -13562,7 +13975,7 @@ var ServeCommand = class extends SmCommand {
|
|
|
13562
13975
|
return ExitCode.Error;
|
|
13563
13976
|
}
|
|
13564
13977
|
const dbPath = resolveDbPath({ global: this.global, db: this.db, ...runtimeCtx });
|
|
13565
|
-
if (this.db !== void 0 && !
|
|
13978
|
+
if (this.db !== void 0 && !existsSync19(dbPath)) {
|
|
13566
13979
|
this.context.stderr.write(
|
|
13567
13980
|
tx(SERVE_TEXTS.dbNotFound, { path: sanitizeForTerminal(dbPath) })
|
|
13568
13981
|
);
|
|
@@ -13616,18 +14029,24 @@ var ServeCommand = class extends SmCommand {
|
|
|
13616
14029
|
);
|
|
13617
14030
|
return ExitCode.Error;
|
|
13618
14031
|
}
|
|
14032
|
+
const stderr = this.context.stderr;
|
|
14033
|
+
const isTTY = stderr.isTTY === true;
|
|
14034
|
+
const colorEnabled = resolveColorEnabled({
|
|
14035
|
+
isTTY,
|
|
14036
|
+
noColorFlag: this.noColor,
|
|
14037
|
+
env: process.env
|
|
14038
|
+
});
|
|
13619
14039
|
this.context.stderr.write(
|
|
13620
|
-
|
|
14040
|
+
renderBanner({
|
|
14041
|
+
version: VERSION,
|
|
13621
14042
|
host: sanitizeForTerminal(handle.address.host),
|
|
13622
14043
|
port: handle.address.port,
|
|
13623
14044
|
scope,
|
|
13624
|
-
|
|
13625
|
-
|
|
13626
|
-
|
|
13627
|
-
|
|
13628
|
-
|
|
13629
|
-
host: sanitizeForTerminal(handle.address.host),
|
|
13630
|
-
port: handle.address.port
|
|
14045
|
+
dbPath,
|
|
14046
|
+
cwd: runtimeCtx.cwd,
|
|
14047
|
+
openBrowser: validation.options.open,
|
|
14048
|
+
isTTY,
|
|
14049
|
+
colorEnabled
|
|
13631
14050
|
})
|
|
13632
14051
|
);
|
|
13633
14052
|
if (validation.options.open) {
|
|
@@ -13743,7 +14162,7 @@ function tryOpenBrowser(url, stderr) {
|
|
|
13743
14162
|
}
|
|
13744
14163
|
|
|
13745
14164
|
// cli/commands/show.ts
|
|
13746
|
-
import { Command as
|
|
14165
|
+
import { Command as Command21, Option as Option21 } from "clipanion";
|
|
13747
14166
|
|
|
13748
14167
|
// cli/i18n/show.texts.ts
|
|
13749
14168
|
var SHOW_TEXTS = {
|
|
@@ -13783,7 +14202,7 @@ var SHOW_TEXTS = {
|
|
|
13783
14202
|
// cli/commands/show.ts
|
|
13784
14203
|
var ShowCommand = class extends SmCommand {
|
|
13785
14204
|
static paths = [["show"]];
|
|
13786
|
-
static usage =
|
|
14205
|
+
static usage = Command21.Usage({
|
|
13787
14206
|
category: "Browse",
|
|
13788
14207
|
description: "Node detail: weight, frontmatter, links, issues.",
|
|
13789
14208
|
details: `
|
|
@@ -13799,7 +14218,7 @@ var ShowCommand = class extends SmCommand {
|
|
|
13799
14218
|
["Machine-readable detail", "$0 show .claude/agents/architect.md --json"]
|
|
13800
14219
|
]
|
|
13801
14220
|
});
|
|
13802
|
-
nodePath =
|
|
14221
|
+
nodePath = Option21.String({ required: true });
|
|
13803
14222
|
async run() {
|
|
13804
14223
|
const dbPath = resolveDbPath({ global: this.global, db: this.db, ...defaultRuntimeContext() });
|
|
13805
14224
|
if (!assertDbExists(dbPath, this.context.stderr)) return ExitCode.NotFound;
|
|
@@ -13948,7 +14367,7 @@ function rankConfidenceForGrouping(c) {
|
|
|
13948
14367
|
}
|
|
13949
14368
|
|
|
13950
14369
|
// cli/commands/stubs.ts
|
|
13951
|
-
import { Command as
|
|
14370
|
+
import { Command as Command22, Option as Option22 } from "clipanion";
|
|
13952
14371
|
|
|
13953
14372
|
// cli/i18n/stubs.texts.ts
|
|
13954
14373
|
var STUBS_TEXTS = {
|
|
@@ -13963,9 +14382,9 @@ function notImplemented(cmd, verb) {
|
|
|
13963
14382
|
cmd.context.stderr.write(tx(STUBS_TEXTS.notImplemented, { verb }));
|
|
13964
14383
|
return ExitCode.Error;
|
|
13965
14384
|
}
|
|
13966
|
-
var DoctorCommand = class extends
|
|
14385
|
+
var DoctorCommand = class extends Command22 {
|
|
13967
14386
|
static paths = [["doctor"]];
|
|
13968
|
-
static usage =
|
|
14387
|
+
static usage = Command22.Usage({
|
|
13969
14388
|
category: "Setup",
|
|
13970
14389
|
description: planned("Diagnostic report: DB integrity, pending migrations, orphan rows, plugin status, runner availability.")
|
|
13971
14390
|
});
|
|
@@ -13973,23 +14392,23 @@ var DoctorCommand = class extends Command21 {
|
|
|
13973
14392
|
return notImplemented(this, "doctor");
|
|
13974
14393
|
}
|
|
13975
14394
|
};
|
|
13976
|
-
var FindingsCommand = class extends
|
|
14395
|
+
var FindingsCommand = class extends Command22 {
|
|
13977
14396
|
static paths = [["findings"]];
|
|
13978
|
-
static usage =
|
|
14397
|
+
static usage = Command22.Usage({
|
|
13979
14398
|
category: "Browse",
|
|
13980
14399
|
description: planned("Probabilistic findings: injection, stale summaries, low confidence.")
|
|
13981
14400
|
});
|
|
13982
|
-
kind =
|
|
13983
|
-
since =
|
|
13984
|
-
threshold =
|
|
13985
|
-
json =
|
|
14401
|
+
kind = Option22.String("--kind", { required: false });
|
|
14402
|
+
since = Option22.String("--since", { required: false });
|
|
14403
|
+
threshold = Option22.String("--threshold", { required: false });
|
|
14404
|
+
json = Option22.Boolean("--json", false);
|
|
13986
14405
|
async execute() {
|
|
13987
14406
|
return notImplemented(this, "findings");
|
|
13988
14407
|
}
|
|
13989
14408
|
};
|
|
13990
|
-
var ActionsListCommand = class extends
|
|
14409
|
+
var ActionsListCommand = class extends Command22 {
|
|
13991
14410
|
static paths = [["actions", "list"]];
|
|
13992
|
-
static usage =
|
|
14411
|
+
static usage = Command22.Usage({
|
|
13993
14412
|
category: "Jobs",
|
|
13994
14413
|
description: planned("Registered action types (manifest view).")
|
|
13995
14414
|
});
|
|
@@ -13997,121 +14416,121 @@ var ActionsListCommand = class extends Command21 {
|
|
|
13997
14416
|
return notImplemented(this, "actions list");
|
|
13998
14417
|
}
|
|
13999
14418
|
};
|
|
14000
|
-
var ActionsShowCommand = class extends
|
|
14419
|
+
var ActionsShowCommand = class extends Command22 {
|
|
14001
14420
|
static paths = [["actions", "show"]];
|
|
14002
|
-
static usage =
|
|
14421
|
+
static usage = Command22.Usage({
|
|
14003
14422
|
category: "Jobs",
|
|
14004
14423
|
description: planned("Full action manifest, including preconditions and expected duration.")
|
|
14005
14424
|
});
|
|
14006
|
-
id =
|
|
14425
|
+
id = Option22.String({ required: true });
|
|
14007
14426
|
async execute() {
|
|
14008
14427
|
return notImplemented(this, "actions show");
|
|
14009
14428
|
}
|
|
14010
14429
|
};
|
|
14011
|
-
var JobSubmitCommand = class extends
|
|
14430
|
+
var JobSubmitCommand = class extends Command22 {
|
|
14012
14431
|
static paths = [["job", "submit"]];
|
|
14013
|
-
static usage =
|
|
14432
|
+
static usage = Command22.Usage({
|
|
14014
14433
|
category: "Jobs",
|
|
14015
14434
|
description: planned("Enqueue a single job or fan out to every matching node (--all).")
|
|
14016
14435
|
});
|
|
14017
|
-
action =
|
|
14018
|
-
node =
|
|
14019
|
-
all =
|
|
14020
|
-
run =
|
|
14021
|
-
force =
|
|
14022
|
-
ttl =
|
|
14023
|
-
priority =
|
|
14436
|
+
action = Option22.String({ required: true });
|
|
14437
|
+
node = Option22.String("-n", { required: false });
|
|
14438
|
+
all = Option22.Boolean("--all", false);
|
|
14439
|
+
run = Option22.Boolean("--run", false);
|
|
14440
|
+
force = Option22.Boolean("--force", false);
|
|
14441
|
+
ttl = Option22.String("--ttl", { required: false });
|
|
14442
|
+
priority = Option22.String("--priority", { required: false });
|
|
14024
14443
|
async execute() {
|
|
14025
14444
|
return notImplemented(this, "job submit");
|
|
14026
14445
|
}
|
|
14027
14446
|
};
|
|
14028
|
-
var JobListCommand = class extends
|
|
14447
|
+
var JobListCommand = class extends Command22 {
|
|
14029
14448
|
static paths = [["job", "list"]];
|
|
14030
|
-
static usage =
|
|
14031
|
-
status =
|
|
14032
|
-
action =
|
|
14033
|
-
node =
|
|
14449
|
+
static usage = Command22.Usage({ category: "Jobs", description: planned("List jobs.") });
|
|
14450
|
+
status = Option22.String("--status", { required: false });
|
|
14451
|
+
action = Option22.String("--action", { required: false });
|
|
14452
|
+
node = Option22.String("--node", { required: false });
|
|
14034
14453
|
async execute() {
|
|
14035
14454
|
return notImplemented(this, "job list");
|
|
14036
14455
|
}
|
|
14037
14456
|
};
|
|
14038
|
-
var JobShowCommand = class extends
|
|
14457
|
+
var JobShowCommand = class extends Command22 {
|
|
14039
14458
|
static paths = [["job", "show"]];
|
|
14040
|
-
static usage =
|
|
14041
|
-
id =
|
|
14459
|
+
static usage = Command22.Usage({ category: "Jobs", description: planned("Job detail: state, claim time, TTL, runner, content hash.") });
|
|
14460
|
+
id = Option22.String({ required: true });
|
|
14042
14461
|
async execute() {
|
|
14043
14462
|
return notImplemented(this, "job show");
|
|
14044
14463
|
}
|
|
14045
14464
|
};
|
|
14046
|
-
var JobPreviewCommand = class extends
|
|
14465
|
+
var JobPreviewCommand = class extends Command22 {
|
|
14047
14466
|
static paths = [["job", "preview"]];
|
|
14048
|
-
static usage =
|
|
14049
|
-
id =
|
|
14467
|
+
static usage = Command22.Usage({ category: "Jobs", description: planned("Render the job MD file without executing.") });
|
|
14468
|
+
id = Option22.String({ required: true });
|
|
14050
14469
|
async execute() {
|
|
14051
14470
|
return notImplemented(this, "job preview");
|
|
14052
14471
|
}
|
|
14053
14472
|
};
|
|
14054
|
-
var JobClaimCommand = class extends
|
|
14473
|
+
var JobClaimCommand = class extends Command22 {
|
|
14055
14474
|
static paths = [["job", "claim"]];
|
|
14056
|
-
static usage =
|
|
14475
|
+
static usage = Command22.Usage({
|
|
14057
14476
|
category: "Jobs",
|
|
14058
14477
|
description: planned("Atomic primitive: return next queued job id, mark it running.")
|
|
14059
14478
|
});
|
|
14060
|
-
filter =
|
|
14479
|
+
filter = Option22.String("--filter", { required: false });
|
|
14061
14480
|
async execute() {
|
|
14062
14481
|
return notImplemented(this, "job claim");
|
|
14063
14482
|
}
|
|
14064
14483
|
};
|
|
14065
|
-
var JobRunCommand = class extends
|
|
14484
|
+
var JobRunCommand = class extends Command22 {
|
|
14066
14485
|
static paths = [["job", "run"]];
|
|
14067
|
-
static usage =
|
|
14486
|
+
static usage = Command22.Usage({
|
|
14068
14487
|
category: "Jobs",
|
|
14069
14488
|
description: planned("Full CLI-runner loop: claim + spawn + record.")
|
|
14070
14489
|
});
|
|
14071
|
-
all =
|
|
14072
|
-
max =
|
|
14490
|
+
all = Option22.Boolean("--all", false);
|
|
14491
|
+
max = Option22.String("--max", { required: false });
|
|
14073
14492
|
async execute() {
|
|
14074
14493
|
return notImplemented(this, "job run");
|
|
14075
14494
|
}
|
|
14076
14495
|
};
|
|
14077
|
-
var JobStatusCommand = class extends
|
|
14496
|
+
var JobStatusCommand = class extends Command22 {
|
|
14078
14497
|
static paths = [["job", "status"]];
|
|
14079
|
-
static usage =
|
|
14498
|
+
static usage = Command22.Usage({
|
|
14080
14499
|
category: "Jobs",
|
|
14081
14500
|
description: planned("Counts (per status) or single-job status.")
|
|
14082
14501
|
});
|
|
14083
|
-
id =
|
|
14502
|
+
id = Option22.String({ required: false });
|
|
14084
14503
|
async execute() {
|
|
14085
14504
|
return notImplemented(this, "job status");
|
|
14086
14505
|
}
|
|
14087
14506
|
};
|
|
14088
|
-
var JobCancelCommand = class extends
|
|
14507
|
+
var JobCancelCommand = class extends Command22 {
|
|
14089
14508
|
static paths = [["job", "cancel"]];
|
|
14090
|
-
static usage =
|
|
14509
|
+
static usage = Command22.Usage({
|
|
14091
14510
|
category: "Jobs",
|
|
14092
14511
|
description: planned("Force a running job to failed with reason user-cancelled.")
|
|
14093
14512
|
});
|
|
14094
|
-
id =
|
|
14095
|
-
all =
|
|
14513
|
+
id = Option22.String({ required: false });
|
|
14514
|
+
all = Option22.Boolean("--all", false);
|
|
14096
14515
|
async execute() {
|
|
14097
14516
|
return notImplemented(this, "job cancel");
|
|
14098
14517
|
}
|
|
14099
14518
|
};
|
|
14100
|
-
var RecordCommand = class extends
|
|
14519
|
+
var RecordCommand = class extends Command22 {
|
|
14101
14520
|
static paths = [["record"]];
|
|
14102
|
-
static usage =
|
|
14521
|
+
static usage = Command22.Usage({
|
|
14103
14522
|
category: "Jobs",
|
|
14104
14523
|
description: planned("Close a running job with success or failure. Nonce is the sole credential.")
|
|
14105
14524
|
});
|
|
14106
|
-
id =
|
|
14107
|
-
nonce =
|
|
14108
|
-
status =
|
|
14109
|
-
report =
|
|
14110
|
-
tokensIn =
|
|
14111
|
-
tokensOut =
|
|
14112
|
-
durationMs =
|
|
14113
|
-
model =
|
|
14114
|
-
error =
|
|
14525
|
+
id = Option22.String("--id", { required: true });
|
|
14526
|
+
nonce = Option22.String("--nonce", { required: true });
|
|
14527
|
+
status = Option22.String("--status", { required: true });
|
|
14528
|
+
report = Option22.String("--report", { required: false });
|
|
14529
|
+
tokensIn = Option22.String("--tokens-in", { required: false });
|
|
14530
|
+
tokensOut = Option22.String("--tokens-out", { required: false });
|
|
14531
|
+
durationMs = Option22.String("--duration-ms", { required: false });
|
|
14532
|
+
model = Option22.String("--model", { required: false });
|
|
14533
|
+
error = Option22.String("--error", { required: false });
|
|
14115
14534
|
async execute() {
|
|
14116
14535
|
return notImplemented(this, "record");
|
|
14117
14536
|
}
|
|
@@ -14133,7 +14552,7 @@ var STUB_COMMANDS = [
|
|
|
14133
14552
|
];
|
|
14134
14553
|
|
|
14135
14554
|
// cli/commands/version.ts
|
|
14136
|
-
import { Command as
|
|
14555
|
+
import { Command as Command23 } from "clipanion";
|
|
14137
14556
|
|
|
14138
14557
|
// cli/i18n/version.texts.ts
|
|
14139
14558
|
var VERSION_TEXTS = {
|
|
@@ -14145,7 +14564,7 @@ var VERSION_TEXTS = {
|
|
|
14145
14564
|
// cli/commands/version.ts
|
|
14146
14565
|
var VersionCommand = class extends SmCommand {
|
|
14147
14566
|
static paths = [["version"]];
|
|
14148
|
-
static usage =
|
|
14567
|
+
static usage = Command23.Usage({
|
|
14149
14568
|
category: "Introspection",
|
|
14150
14569
|
description: "Print the CLI / kernel / spec / runtime / db-schema version matrix."
|
|
14151
14570
|
});
|
|
@@ -14215,6 +14634,7 @@ cli.register(Builtins.VersionCommand);
|
|
|
14215
14634
|
cli.register(RootHelpCommand);
|
|
14216
14635
|
cli.register(HelpCommand);
|
|
14217
14636
|
cli.register(InitCommand);
|
|
14637
|
+
cli.register(GuideCommand);
|
|
14218
14638
|
cli.register(ScanCommand);
|
|
14219
14639
|
cli.register(ScanCompareCommand);
|
|
14220
14640
|
cli.register(ServeCommand);
|
|
@@ -14272,7 +14692,7 @@ var exitCode = await cli.run(routedArgs, {
|
|
|
14272
14692
|
process.exit(exitCode);
|
|
14273
14693
|
function resolveBareDefault() {
|
|
14274
14694
|
const ctx = defaultRuntimeContext();
|
|
14275
|
-
if (
|
|
14695
|
+
if (existsSync20(defaultProjectDbPath(ctx))) {
|
|
14276
14696
|
return ["serve"];
|
|
14277
14697
|
}
|
|
14278
14698
|
process.stderr.write(tx(ENTRY_TEXTS.bareNoProject, { cwd: ctx.cwd }));
|