@skill-map/cli 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/tutorial/sm-tutorial.md +876 -0
- package/dist/cli.js +494 -345
- 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-7PFTODKS.js +1031 -0
- package/dist/ui/{chunk-WFJRSBK6.js → chunk-A4RBO3TD.js} +1 -1
- package/dist/ui/{chunk-VJAWM5V3.js → chunk-E2ZFWQW6.js} +1 -1
- package/dist/ui/{chunk-TEPC3SFH.js → chunk-KPEISNOV.js} +1 -1
- package/dist/ui/{chunk-T5SUVDLE.js → chunk-S5C4U3I3.js} +1 -1
- package/dist/ui/chunk-TG6IWVEC.js +54 -0
- package/dist/ui/{chunk-DOJURY6T.js → chunk-TGJQE3TH.js} +1 -1
- package/dist/ui/{chunk-G6SL4UFD.js → chunk-UGEECDPV.js} +1 -1
- package/dist/ui/index.html +1 -1
- package/dist/ui/main-JI2DDER5.js +1 -0
- package/package.json +2 -2
- package/dist/cli/guide/sm-guide.md +0 -688
- package/dist/ui/chunk-AVRC55YV.js +0 -971
- package/dist/ui/chunk-ZF7H74JY.js +0 -114
- package/dist/ui/main-TG4BEOVI.js +0 -1
package/dist/cli.js
CHANGED
|
@@ -7353,108 +7353,16 @@ var GraphCommand = class extends SmCommand {
|
|
|
7353
7353
|
}
|
|
7354
7354
|
};
|
|
7355
7355
|
|
|
7356
|
-
// cli/commands/guide.ts
|
|
7357
|
-
import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
|
|
7358
|
-
import { writeFile } from "fs/promises";
|
|
7359
|
-
import { dirname as dirname9, join as join10, resolve as resolve13 } from "path";
|
|
7360
|
-
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
7361
|
-
import { Command as Command8, Option as Option8 } from "clipanion";
|
|
7362
|
-
|
|
7363
|
-
// cli/i18n/guide.texts.ts
|
|
7364
|
-
var GUIDE_TEXTS = {
|
|
7365
|
-
// Success — written to stdout after `<cwd>/sm-guide.md` is created.
|
|
7366
|
-
written: 'Listo. sm-guide.md creado en {{cwd}}. Abr\xED Claude Code ac\xE1 y decile "gu\xEDame" para arrancar la gu\xEDa interactiva.\n',
|
|
7367
|
-
// Refusal — `sm-guide.md` already exists and `--force` was not set.
|
|
7368
|
-
// Goes to stderr, exit code 2 (operational error per spec § Exit codes).
|
|
7369
|
-
alreadyExists: "sm guide: sm-guide.md ya existe en {{cwd}}. Us\xE1 `--force` para sobrescribir.\n",
|
|
7370
|
-
// I/O failure on write or on reading the bundled SKILL source.
|
|
7371
|
-
writeFailed: "sm guide: no se pudo escribir sm-guide.md: {{message}}\n",
|
|
7372
|
-
sourceMissing: "sm guide: no se pudo leer la gu\xEDa empaquetada (SKILL.md) desde la instalaci\xF3n. Reinstal\xE1 @skill-map/cli o report\xE1 el bug.\n"
|
|
7373
|
-
};
|
|
7374
|
-
|
|
7375
|
-
// cli/commands/guide.ts
|
|
7376
|
-
var SM_GUIDE_FILENAME = "sm-guide.md";
|
|
7377
|
-
var GuideCommand = class extends SmCommand {
|
|
7378
|
-
static paths = [["guide"]];
|
|
7379
|
-
static usage = Command8.Usage({
|
|
7380
|
-
category: "Setup",
|
|
7381
|
-
description: "Materialize the interactive tester guide (sm-guide.md) in the current directory.",
|
|
7382
|
-
details: `
|
|
7383
|
-
Drops the canonical SKILL.md content as ./sm-guide.md so a tester
|
|
7384
|
-
can open Claude Code in the cwd and trigger the sm-guide skill
|
|
7385
|
-
("gu\xEDame"). Top-level only \u2014 no subdirectory is created.
|
|
7386
|
-
|
|
7387
|
-
Does NOT require an initialized .skill-map/ project. Refuses to
|
|
7388
|
-
overwrite an existing sm-guide.md unless --force is passed.
|
|
7389
|
-
`,
|
|
7390
|
-
examples: [
|
|
7391
|
-
["Materialize the guide in the cwd", "$0 guide"],
|
|
7392
|
-
["Overwrite an existing sm-guide.md", "$0 guide --force"]
|
|
7393
|
-
]
|
|
7394
|
-
});
|
|
7395
|
-
force = Option8.Boolean("--force", false, {
|
|
7396
|
-
description: "Overwrite an existing sm-guide.md without prompting."
|
|
7397
|
-
});
|
|
7398
|
-
async run() {
|
|
7399
|
-
const ctx = defaultRuntimeContext();
|
|
7400
|
-
const target = join10(ctx.cwd, SM_GUIDE_FILENAME);
|
|
7401
|
-
if (await pathExists(target) && !this.force) {
|
|
7402
|
-
this.context.stderr.write(tx(GUIDE_TEXTS.alreadyExists, { cwd: ctx.cwd }));
|
|
7403
|
-
return ExitCode.Error;
|
|
7404
|
-
}
|
|
7405
|
-
let body;
|
|
7406
|
-
try {
|
|
7407
|
-
body = loadBundledGuideText();
|
|
7408
|
-
} catch {
|
|
7409
|
-
this.context.stderr.write(GUIDE_TEXTS.sourceMissing);
|
|
7410
|
-
return ExitCode.Error;
|
|
7411
|
-
}
|
|
7412
|
-
try {
|
|
7413
|
-
await writeFile(target, body);
|
|
7414
|
-
} catch (err) {
|
|
7415
|
-
this.context.stderr.write(
|
|
7416
|
-
tx(GUIDE_TEXTS.writeFailed, { message: formatErrorMessage(err) })
|
|
7417
|
-
);
|
|
7418
|
-
return ExitCode.Error;
|
|
7419
|
-
}
|
|
7420
|
-
this.context.stdout.write(tx(GUIDE_TEXTS.written, { cwd: ctx.cwd }));
|
|
7421
|
-
return ExitCode.Ok;
|
|
7422
|
-
}
|
|
7423
|
-
};
|
|
7424
|
-
var cachedGuide = null;
|
|
7425
|
-
function loadBundledGuideText() {
|
|
7426
|
-
if (cachedGuide !== null) return cachedGuide;
|
|
7427
|
-
cachedGuide = readGuideFromDisk();
|
|
7428
|
-
return cachedGuide;
|
|
7429
|
-
}
|
|
7430
|
-
function readGuideFromDisk() {
|
|
7431
|
-
const here = dirname9(fileURLToPath5(import.meta.url));
|
|
7432
|
-
const candidates = [
|
|
7433
|
-
// dev: src/cli/commands/ → repo-root .claude/skills/sm-guide/SKILL.md
|
|
7434
|
-
resolve13(here, "../../../.claude/skills/sm-guide/SKILL.md"),
|
|
7435
|
-
// bundled: dist/cli.js → dist/cli/guide/sm-guide.md (sibling)
|
|
7436
|
-
resolve13(here, "cli/guide/sm-guide.md"),
|
|
7437
|
-
// bundled fallback: any-depth → cli/guide/sm-guide.md
|
|
7438
|
-
resolve13(here, "../cli/guide/sm-guide.md")
|
|
7439
|
-
];
|
|
7440
|
-
for (const candidate of candidates) {
|
|
7441
|
-
if (existsSync12(candidate)) {
|
|
7442
|
-
return readFileSync10(candidate, "utf8");
|
|
7443
|
-
}
|
|
7444
|
-
}
|
|
7445
|
-
throw new Error(`SKILL.md not found in any candidate location (last tried: ${candidates[candidates.length - 1]})`);
|
|
7446
|
-
}
|
|
7447
|
-
|
|
7448
7356
|
// cli/commands/help.ts
|
|
7449
|
-
import { readFileSync as
|
|
7357
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
7450
7358
|
import { createRequire as createRequire4 } from "module";
|
|
7451
|
-
import { resolve as
|
|
7452
|
-
import { Command as
|
|
7359
|
+
import { resolve as resolve13 } from "path";
|
|
7360
|
+
import { Command as Command8, Option as Option8 } from "clipanion";
|
|
7453
7361
|
|
|
7454
7362
|
// package.json
|
|
7455
7363
|
var package_default = {
|
|
7456
7364
|
name: "@skill-map/cli",
|
|
7457
|
-
version: "0.
|
|
7365
|
+
version: "0.15.0",
|
|
7458
7366
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
7459
7367
|
license: "MIT",
|
|
7460
7368
|
type: "module",
|
|
@@ -7513,7 +7421,7 @@ var package_default = {
|
|
|
7513
7421
|
},
|
|
7514
7422
|
dependencies: {
|
|
7515
7423
|
"@hono/node-server": "2.0.1",
|
|
7516
|
-
"@skill-map/spec": "0.
|
|
7424
|
+
"@skill-map/spec": "0.15.0",
|
|
7517
7425
|
ajv: "8.18.0",
|
|
7518
7426
|
"ajv-formats": "3.0.1",
|
|
7519
7427
|
chokidar: "5.0.0",
|
|
@@ -7630,9 +7538,9 @@ var HELP_TEXTS = {
|
|
|
7630
7538
|
};
|
|
7631
7539
|
|
|
7632
7540
|
// cli/commands/help.ts
|
|
7633
|
-
var HelpCommand = class extends
|
|
7541
|
+
var HelpCommand = class extends Command8 {
|
|
7634
7542
|
static paths = [["help"]];
|
|
7635
|
-
static usage =
|
|
7543
|
+
static usage = Command8.Usage({
|
|
7636
7544
|
category: "Introspection",
|
|
7637
7545
|
description: "Self-describing introspection. --format human|md|json.",
|
|
7638
7546
|
details: `
|
|
@@ -7646,8 +7554,8 @@ var HelpCommand = class extends Command9 {
|
|
|
7646
7554
|
json \u2014 structured surface dump per spec/cli-contract.md.
|
|
7647
7555
|
`
|
|
7648
7556
|
});
|
|
7649
|
-
verbParts =
|
|
7650
|
-
format =
|
|
7557
|
+
verbParts = Option8.Rest({ required: 0 });
|
|
7558
|
+
format = Option8.String("--format", "human");
|
|
7651
7559
|
async execute() {
|
|
7652
7560
|
const format = normalizeFormat(this.format);
|
|
7653
7561
|
if (!format) {
|
|
@@ -7769,8 +7677,8 @@ function resolveSpecVersion() {
|
|
|
7769
7677
|
try {
|
|
7770
7678
|
const req = createRequire4(import.meta.url);
|
|
7771
7679
|
const indexPath = req.resolve("@skill-map/spec/index.json");
|
|
7772
|
-
const pkgPath =
|
|
7773
|
-
const pkg = JSON.parse(
|
|
7680
|
+
const pkgPath = resolve13(indexPath, "..", "package.json");
|
|
7681
|
+
const pkg = JSON.parse(readFileSync10(pkgPath, "utf8"));
|
|
7774
7682
|
return pkg.version;
|
|
7775
7683
|
} catch {
|
|
7776
7684
|
return "unknown";
|
|
@@ -7965,7 +7873,7 @@ function renderCompactOverview(verbs) {
|
|
|
7965
7873
|
lines.push(HELP_TEXTS.compactFooter);
|
|
7966
7874
|
return lines.join("\n") + "\n";
|
|
7967
7875
|
}
|
|
7968
|
-
var RootHelpCommand = class extends
|
|
7876
|
+
var RootHelpCommand = class extends Command8 {
|
|
7969
7877
|
static paths = [["-h"], ["--help"]];
|
|
7970
7878
|
async execute() {
|
|
7971
7879
|
const rawDefs = this.cli.definitions();
|
|
@@ -8021,13 +7929,13 @@ function registeredVerbPaths(cli2) {
|
|
|
8021
7929
|
}
|
|
8022
7930
|
|
|
8023
7931
|
// cli/commands/init.ts
|
|
8024
|
-
import { mkdir as mkdir2, readFile as readFile2, writeFile
|
|
8025
|
-
import { join as
|
|
8026
|
-
import { Command as
|
|
7932
|
+
import { mkdir as mkdir2, readFile as readFile2, writeFile } from "fs/promises";
|
|
7933
|
+
import { join as join10 } from "path";
|
|
7934
|
+
import { Command as Command9, Option as Option9 } from "clipanion";
|
|
8027
7935
|
|
|
8028
7936
|
// kernel/orchestrator.ts
|
|
8029
7937
|
import { createHash } from "crypto";
|
|
8030
|
-
import { existsSync as
|
|
7938
|
+
import { existsSync as existsSync12, statSync as statSync3 } from "fs";
|
|
8031
7939
|
import { Tiktoken } from "js-tiktoken/lite";
|
|
8032
7940
|
import cl100k_base from "js-tiktoken/ranks/cl100k_base";
|
|
8033
7941
|
import yaml2 from "js-yaml";
|
|
@@ -8162,7 +8070,7 @@ function validateRoots(roots) {
|
|
|
8162
8070
|
throw new Error(ORCHESTRATOR_TEXTS.runScanRootEmptyArray);
|
|
8163
8071
|
}
|
|
8164
8072
|
for (const root of roots) {
|
|
8165
|
-
if (!
|
|
8073
|
+
if (!existsSync12(root) || !statSync3(root).isDirectory()) {
|
|
8166
8074
|
throw new Error(tx(ORCHESTRATOR_TEXTS.runScanRootMissing, { root }));
|
|
8167
8075
|
}
|
|
8168
8076
|
}
|
|
@@ -8938,10 +8846,10 @@ function recomputeExternalRefsCount(nodes, externalLinks, cachedPaths) {
|
|
|
8938
8846
|
}
|
|
8939
8847
|
|
|
8940
8848
|
// kernel/scan/watcher.ts
|
|
8941
|
-
import { resolve as
|
|
8849
|
+
import { resolve as resolve14, relative as relative4, sep as sep2 } from "path";
|
|
8942
8850
|
import chokidar from "chokidar";
|
|
8943
8851
|
function createChokidarWatcher(opts) {
|
|
8944
|
-
const absRoots = opts.roots.map((r) =>
|
|
8852
|
+
const absRoots = opts.roots.map((r) => resolve14(opts.cwd, r));
|
|
8945
8853
|
const ignoreFilter = opts.ignoreFilter;
|
|
8946
8854
|
const ignored = ignoreFilter ? (path) => {
|
|
8947
8855
|
const rel = relativePathFromRoots(path, absRoots);
|
|
@@ -9187,7 +9095,7 @@ function createCliProgressEmitter(stderr) {
|
|
|
9187
9095
|
// cli/commands/init.ts
|
|
9188
9096
|
var InitCommand = class extends SmCommand {
|
|
9189
9097
|
static paths = [["init"]];
|
|
9190
|
-
static usage =
|
|
9098
|
+
static usage = Command9.Usage({
|
|
9191
9099
|
category: "Setup",
|
|
9192
9100
|
description: "Bootstrap the current scope: scaffold .skill-map/, provision DB, run first scan.",
|
|
9193
9101
|
details: `
|
|
@@ -9211,16 +9119,16 @@ var InitCommand = class extends SmCommand {
|
|
|
9211
9119
|
["Preview what would be created", "$0 init --dry-run"]
|
|
9212
9120
|
]
|
|
9213
9121
|
});
|
|
9214
|
-
noScan =
|
|
9122
|
+
noScan = Option9.Boolean("--no-scan", false, {
|
|
9215
9123
|
description: "Skip the first scan after scaffolding."
|
|
9216
9124
|
});
|
|
9217
|
-
force =
|
|
9125
|
+
force = Option9.Boolean("--force", false, {
|
|
9218
9126
|
description: "Overwrite an existing settings.json / settings.local.json / .skill-mapignore."
|
|
9219
9127
|
});
|
|
9220
|
-
strict =
|
|
9128
|
+
strict = Option9.Boolean("--strict", false, {
|
|
9221
9129
|
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."
|
|
9222
9130
|
});
|
|
9223
|
-
dryRun =
|
|
9131
|
+
dryRun = Option9.Boolean("-n,--dry-run", false, {
|
|
9224
9132
|
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."
|
|
9225
9133
|
});
|
|
9226
9134
|
// CLI orchestrator: paths setup + dry-run branch (delegated to
|
|
@@ -9231,7 +9139,7 @@ var InitCommand = class extends SmCommand {
|
|
|
9231
9139
|
async run() {
|
|
9232
9140
|
const ctx = defaultRuntimeContext();
|
|
9233
9141
|
const scopeRoot = this.global ? ctx.homedir : ctx.cwd;
|
|
9234
|
-
const skillMapDir =
|
|
9142
|
+
const skillMapDir = join10(scopeRoot, SKILL_MAP_DIR);
|
|
9235
9143
|
const settingsPath = defaultSettingsPath(scopeRoot);
|
|
9236
9144
|
const localPath = defaultLocalSettingsPath(scopeRoot);
|
|
9237
9145
|
const ignorePath = defaultIgnoreFilePath(scopeRoot);
|
|
@@ -9255,17 +9163,17 @@ var InitCommand = class extends SmCommand {
|
|
|
9255
9163
|
return ExitCode.Ok;
|
|
9256
9164
|
}
|
|
9257
9165
|
await mkdir2(skillMapDir, { recursive: true });
|
|
9258
|
-
await
|
|
9166
|
+
await writeFile(settingsPath, JSON.stringify({ schemaVersion: 1 }, null, 2) + "\n");
|
|
9259
9167
|
if (!await pathExists(localPath) || this.force) {
|
|
9260
|
-
await
|
|
9168
|
+
await writeFile(localPath, "{}\n");
|
|
9261
9169
|
}
|
|
9262
9170
|
if (!await pathExists(ignorePath) || this.force) {
|
|
9263
|
-
await
|
|
9171
|
+
await writeFile(ignorePath, loadBundledIgnoreText());
|
|
9264
9172
|
}
|
|
9265
9173
|
if (!this.global) {
|
|
9266
9174
|
const updated = await ensureGitignoreEntries(scopeRoot, GITIGNORE_ENTRIES);
|
|
9267
9175
|
if (updated) {
|
|
9268
|
-
const gitignorePath =
|
|
9176
|
+
const gitignorePath = join10(scopeRoot, ".gitignore");
|
|
9269
9177
|
this.context.stdout.write(
|
|
9270
9178
|
GITIGNORE_ENTRIES.length === 1 ? tx(INIT_TEXTS.gitignoreUpdatedSingular, { path: gitignorePath }) : tx(INIT_TEXTS.gitignoreUpdatedPlural, {
|
|
9271
9179
|
path: gitignorePath,
|
|
@@ -9304,7 +9212,7 @@ async function dryRunFileMessage(path) {
|
|
|
9304
9212
|
}
|
|
9305
9213
|
async function writeDryRunGitignorePlan(stdout, scopeRoot) {
|
|
9306
9214
|
const wouldAdd = await previewGitignoreEntries(scopeRoot, GITIGNORE_ENTRIES);
|
|
9307
|
-
const gitignorePath =
|
|
9215
|
+
const gitignorePath = join10(scopeRoot, ".gitignore");
|
|
9308
9216
|
if (wouldAdd.length === 0) {
|
|
9309
9217
|
stdout.write(tx(INIT_TEXTS.dryRunWouldLeaveGitignoreUnchanged, { path: gitignorePath }));
|
|
9310
9218
|
} else if (wouldAdd.length === 1) {
|
|
@@ -9324,13 +9232,13 @@ async function writeDryRunGitignorePlan(stdout, scopeRoot) {
|
|
|
9324
9232
|
);
|
|
9325
9233
|
}
|
|
9326
9234
|
}
|
|
9327
|
-
async function runFirstScan(scopeRoot,
|
|
9235
|
+
async function runFirstScan(scopeRoot, homedir3, dbPath, strict, stdout, stderr) {
|
|
9328
9236
|
stdout.write(INIT_TEXTS.runningFirstScan);
|
|
9329
9237
|
const kernel = createKernel();
|
|
9330
9238
|
for (const manifest of listBuiltIns()) kernel.registry.register(manifest);
|
|
9331
9239
|
let cfg;
|
|
9332
9240
|
try {
|
|
9333
|
-
cfg = loadConfig({ scope: "project", cwd: scopeRoot, homedir:
|
|
9241
|
+
cfg = loadConfig({ scope: "project", cwd: scopeRoot, homedir: homedir3, strict }).effective;
|
|
9334
9242
|
} catch (err) {
|
|
9335
9243
|
const message = formatErrorMessage(err);
|
|
9336
9244
|
stderr.write(tx(INIT_TEXTS.configLoadFailure, { message }));
|
|
@@ -9379,7 +9287,7 @@ async function runFirstScan(scopeRoot, homedir2, dbPath, strict, stdout, stderr)
|
|
|
9379
9287
|
return hasErrors ? ExitCode.Issues : ExitCode.Ok;
|
|
9380
9288
|
}
|
|
9381
9289
|
async function previewGitignoreEntries(scopeRoot, entries) {
|
|
9382
|
-
const path =
|
|
9290
|
+
const path = join10(scopeRoot, ".gitignore");
|
|
9383
9291
|
const body = await pathExists(path) ? await readFile2(path, "utf8") : "";
|
|
9384
9292
|
const present = new Set(
|
|
9385
9293
|
body.split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"))
|
|
@@ -9387,7 +9295,7 @@ async function previewGitignoreEntries(scopeRoot, entries) {
|
|
|
9387
9295
|
return entries.filter((entry) => !present.has(entry));
|
|
9388
9296
|
}
|
|
9389
9297
|
async function ensureGitignoreEntries(scopeRoot, entries) {
|
|
9390
|
-
const path =
|
|
9298
|
+
const path = join10(scopeRoot, ".gitignore");
|
|
9391
9299
|
let body = "";
|
|
9392
9300
|
if (await pathExists(path)) {
|
|
9393
9301
|
body = await readFile2(path, "utf8");
|
|
@@ -9404,12 +9312,12 @@ async function ensureGitignoreEntries(scopeRoot, entries) {
|
|
|
9404
9312
|
present.add(entry);
|
|
9405
9313
|
changed = true;
|
|
9406
9314
|
}
|
|
9407
|
-
if (changed) await
|
|
9315
|
+
if (changed) await writeFile(path, body);
|
|
9408
9316
|
return changed;
|
|
9409
9317
|
}
|
|
9410
9318
|
|
|
9411
9319
|
// cli/commands/history.ts
|
|
9412
|
-
import { Command as
|
|
9320
|
+
import { Command as Command10, Option as Option10 } from "clipanion";
|
|
9413
9321
|
|
|
9414
9322
|
// cli/i18n/option-validators.texts.ts
|
|
9415
9323
|
var OPTION_VALIDATORS_TEXTS = {
|
|
@@ -9498,7 +9406,7 @@ function parseStatuses(input, stderr) {
|
|
|
9498
9406
|
}
|
|
9499
9407
|
var HistoryCommand = class extends SmCommand {
|
|
9500
9408
|
static paths = [["history"]];
|
|
9501
|
-
static usage =
|
|
9409
|
+
static usage = Command10.Usage({
|
|
9502
9410
|
category: "History",
|
|
9503
9411
|
description: "Filter execution records. --json emits an array conforming to execution-record.schema.json.",
|
|
9504
9412
|
details: `
|
|
@@ -9518,12 +9426,12 @@ var HistoryCommand = class extends SmCommand {
|
|
|
9518
9426
|
["Machine-readable, scoped to one node", "$0 history -n skills/foo.md --json"]
|
|
9519
9427
|
]
|
|
9520
9428
|
});
|
|
9521
|
-
node =
|
|
9522
|
-
action =
|
|
9523
|
-
status =
|
|
9524
|
-
since =
|
|
9525
|
-
until =
|
|
9526
|
-
limit =
|
|
9429
|
+
node = Option10.String("-n", { required: false });
|
|
9430
|
+
action = Option10.String("--action", { required: false });
|
|
9431
|
+
status = Option10.String("--status", { required: false });
|
|
9432
|
+
since = Option10.String("--since", { required: false });
|
|
9433
|
+
until = Option10.String("--until", { required: false });
|
|
9434
|
+
limit = Option10.String("--limit", { required: false });
|
|
9527
9435
|
// CLI list verb: many optional filter flags (`--node`, `--action`,
|
|
9528
9436
|
// `--status`, `--since`, `--until`, `--limit`, `--json`, `--quiet`)
|
|
9529
9437
|
// each adding a guarded mutation to the filter or render path. Each
|
|
@@ -9571,7 +9479,7 @@ var HistoryCommand = class extends SmCommand {
|
|
|
9571
9479
|
};
|
|
9572
9480
|
var HistoryStatsCommand = class extends SmCommand {
|
|
9573
9481
|
static paths = [["history", "stats"]];
|
|
9574
|
-
static usage =
|
|
9482
|
+
static usage = Command10.Usage({
|
|
9575
9483
|
category: "History",
|
|
9576
9484
|
description: "Aggregate counts, tokens, periods, top nodes, and error rates over state_executions. --json conforms to history-stats.schema.json.",
|
|
9577
9485
|
details: `
|
|
@@ -9589,10 +9497,10 @@ var HistoryStatsCommand = class extends SmCommand {
|
|
|
9589
9497
|
["Top 5 nodes, JSON", "$0 history stats --top 5 --json"]
|
|
9590
9498
|
]
|
|
9591
9499
|
});
|
|
9592
|
-
since =
|
|
9593
|
-
until =
|
|
9594
|
-
period =
|
|
9595
|
-
top =
|
|
9500
|
+
since = Option10.String("--since", { required: false });
|
|
9501
|
+
until = Option10.String("--until", { required: false });
|
|
9502
|
+
period = Option10.String("--period", { required: false });
|
|
9503
|
+
top = Option10.String("--top", { required: false });
|
|
9596
9504
|
// CLI stats verb: range parsing + window flags + period flag + JSON
|
|
9597
9505
|
// branch + per-period iteration. Each branch is a single-purpose
|
|
9598
9506
|
// gate; the data work lives in `aggregateHistoryStats`.
|
|
@@ -9773,11 +9681,11 @@ function formatRow(...cols) {
|
|
|
9773
9681
|
|
|
9774
9682
|
// cli/commands/jobs.ts
|
|
9775
9683
|
import { unlink } from "fs/promises";
|
|
9776
|
-
import { Command as
|
|
9684
|
+
import { Command as Command11, Option as Option11 } from "clipanion";
|
|
9777
9685
|
|
|
9778
9686
|
// kernel/jobs/orphan-files.ts
|
|
9779
9687
|
import { readdirSync as readdirSync6, statSync as statSync4 } from "fs";
|
|
9780
|
-
import { join as
|
|
9688
|
+
import { join as join11, resolve as resolve15 } from "path";
|
|
9781
9689
|
function findOrphanJobFiles(jobsDir, referencedPaths) {
|
|
9782
9690
|
let entries;
|
|
9783
9691
|
try {
|
|
@@ -9792,7 +9700,7 @@ function findOrphanJobFiles(jobsDir, referencedPaths) {
|
|
|
9792
9700
|
const orphans = [];
|
|
9793
9701
|
for (const name of entries) {
|
|
9794
9702
|
if (!name.endsWith(".md")) continue;
|
|
9795
|
-
const abs =
|
|
9703
|
+
const abs = resolve15(join11(jobsDir, name));
|
|
9796
9704
|
if (!referencedPaths.has(abs)) orphans.push(abs);
|
|
9797
9705
|
}
|
|
9798
9706
|
orphans.sort();
|
|
@@ -9821,7 +9729,7 @@ var JOBS_TEXTS = {
|
|
|
9821
9729
|
// cli/commands/jobs.ts
|
|
9822
9730
|
var JobPruneCommand = class extends SmCommand {
|
|
9823
9731
|
static paths = [["job", "prune"]];
|
|
9824
|
-
static usage =
|
|
9732
|
+
static usage = Command11.Usage({
|
|
9825
9733
|
category: "Jobs",
|
|
9826
9734
|
description: "Retention GC for completed / failed jobs (per config policy). --orphan-files removes MD files with no DB row.",
|
|
9827
9735
|
details: `
|
|
@@ -9848,10 +9756,10 @@ var JobPruneCommand = class extends SmCommand {
|
|
|
9848
9756
|
["Preview without touching the DB", "$0 job prune --dry-run --json"]
|
|
9849
9757
|
]
|
|
9850
9758
|
});
|
|
9851
|
-
orphanFiles =
|
|
9759
|
+
orphanFiles = Option11.Boolean("--orphan-files", false, {
|
|
9852
9760
|
description: "Also remove MD files in .skill-map/jobs/ that have no matching state_jobs row."
|
|
9853
9761
|
});
|
|
9854
|
-
dryRun =
|
|
9762
|
+
dryRun = Option11.Boolean("-n,--dry-run", false, {
|
|
9855
9763
|
description: "Report what would be pruned without touching the DB or filesystem."
|
|
9856
9764
|
});
|
|
9857
9765
|
async run() {
|
|
@@ -9968,7 +9876,7 @@ function formatPolicy(seconds) {
|
|
|
9968
9876
|
}
|
|
9969
9877
|
|
|
9970
9878
|
// cli/commands/list.ts
|
|
9971
|
-
import { Command as
|
|
9879
|
+
import { Command as Command12, Option as Option12 } from "clipanion";
|
|
9972
9880
|
|
|
9973
9881
|
// cli/i18n/list.texts.ts
|
|
9974
9882
|
var LIST_TEXTS = {
|
|
@@ -9996,7 +9904,7 @@ var SORT_BY = {
|
|
|
9996
9904
|
var PATH_COL_WIDTH = 50;
|
|
9997
9905
|
var ListCommand = class extends SmCommand {
|
|
9998
9906
|
static paths = [["list"]];
|
|
9999
|
-
static usage =
|
|
9907
|
+
static usage = Command12.Usage({
|
|
10000
9908
|
category: "Browse",
|
|
10001
9909
|
description: "Tabular listing of nodes. --json emits an array conforming to node.schema.json.",
|
|
10002
9910
|
details: `
|
|
@@ -10017,10 +9925,10 @@ var ListCommand = class extends SmCommand {
|
|
|
10017
9925
|
["Only nodes with issues, machine-readable", "$0 list --issue --json"]
|
|
10018
9926
|
]
|
|
10019
9927
|
});
|
|
10020
|
-
kind =
|
|
10021
|
-
issue =
|
|
10022
|
-
sortBy =
|
|
10023
|
-
limit =
|
|
9928
|
+
kind = Option12.String("--kind", { required: false });
|
|
9929
|
+
issue = Option12.Boolean("--issue", false);
|
|
9930
|
+
sortBy = Option12.String("--sort-by", { required: false });
|
|
9931
|
+
limit = Option12.String("--limit", { required: false });
|
|
10024
9932
|
async run() {
|
|
10025
9933
|
let sortColumn = "path";
|
|
10026
9934
|
let sortDirection = "asc";
|
|
@@ -10122,7 +10030,7 @@ function formatRow2(path, kind, out, inCount, ext, issues, bytes) {
|
|
|
10122
10030
|
}
|
|
10123
10031
|
|
|
10124
10032
|
// cli/commands/orphans.ts
|
|
10125
|
-
import { Command as
|
|
10033
|
+
import { Command as Command13, Option as Option13 } from "clipanion";
|
|
10126
10034
|
|
|
10127
10035
|
// cli/i18n/orphans.texts.ts
|
|
10128
10036
|
var ORPHANS_TEXTS = {
|
|
@@ -10177,7 +10085,7 @@ function isStringArray(v) {
|
|
|
10177
10085
|
}
|
|
10178
10086
|
var OrphansCommand = class extends SmCommand {
|
|
10179
10087
|
static paths = [["orphans"]];
|
|
10180
|
-
static usage =
|
|
10088
|
+
static usage = Command13.Usage({
|
|
10181
10089
|
category: "Browse",
|
|
10182
10090
|
description: "List orphan / auto-rename issues from the last scan. --json emits an array conforming to issue.schema.json.",
|
|
10183
10091
|
details: `
|
|
@@ -10192,7 +10100,7 @@ var OrphansCommand = class extends SmCommand {
|
|
|
10192
10100
|
["Just the ambiguous ones, JSON", "$0 orphans --kind ambiguous --json"]
|
|
10193
10101
|
]
|
|
10194
10102
|
});
|
|
10195
|
-
kind =
|
|
10103
|
+
kind = Option13.String("--kind", { required: false });
|
|
10196
10104
|
async run() {
|
|
10197
10105
|
let ruleFilter = null;
|
|
10198
10106
|
if (this.kind !== void 0) {
|
|
@@ -10230,7 +10138,7 @@ var OrphansCommand = class extends SmCommand {
|
|
|
10230
10138
|
};
|
|
10231
10139
|
var OrphansReconcileCommand = class extends SmCommand {
|
|
10232
10140
|
static paths = [["orphans", "reconcile"]];
|
|
10233
|
-
static usage =
|
|
10141
|
+
static usage = Command13.Usage({
|
|
10234
10142
|
category: "Browse",
|
|
10235
10143
|
description: "Migrate state_* FKs from an orphan path to a live node, resolving the orphan issue.",
|
|
10236
10144
|
details: `
|
|
@@ -10246,9 +10154,9 @@ var OrphansReconcileCommand = class extends SmCommand {
|
|
|
10246
10154
|
["Reattach orphan history", "$0 orphans reconcile skills/old.md --to skills/new.md"]
|
|
10247
10155
|
]
|
|
10248
10156
|
});
|
|
10249
|
-
orphanPath =
|
|
10250
|
-
to =
|
|
10251
|
-
dryRun =
|
|
10157
|
+
orphanPath = Option13.String({ required: true });
|
|
10158
|
+
to = Option13.String("--to", { required: true });
|
|
10159
|
+
dryRun = Option13.Boolean("-n,--dry-run", false);
|
|
10252
10160
|
async run() {
|
|
10253
10161
|
const dbPath = resolveDbPath({ global: this.global, db: this.db, ...defaultRuntimeContext() });
|
|
10254
10162
|
if (!assertDbExists(dbPath, this.context.stderr)) return ExitCode.NotFound;
|
|
@@ -10318,7 +10226,7 @@ var OrphansReconcileCommand = class extends SmCommand {
|
|
|
10318
10226
|
};
|
|
10319
10227
|
var OrphansUndoRenameCommand = class extends SmCommand {
|
|
10320
10228
|
static paths = [["orphans", "undo-rename"]];
|
|
10321
|
-
static usage =
|
|
10229
|
+
static usage = Command13.Usage({
|
|
10322
10230
|
category: "Browse",
|
|
10323
10231
|
description: "Reverse a medium- or ambiguous-confidence auto-rename. Migrates state_* FKs back, emits a new orphan on the prior path.",
|
|
10324
10232
|
details: `
|
|
@@ -10338,10 +10246,10 @@ var OrphansUndoRenameCommand = class extends SmCommand {
|
|
|
10338
10246
|
["Undo an ambiguous, picking a candidate", "$0 orphans undo-rename skills/new.md --from skills/old-a.md"]
|
|
10339
10247
|
]
|
|
10340
10248
|
});
|
|
10341
|
-
newPath =
|
|
10342
|
-
from =
|
|
10343
|
-
force =
|
|
10344
|
-
dryRun =
|
|
10249
|
+
newPath = Option13.String({ required: true });
|
|
10250
|
+
from = Option13.String("--from", { required: false });
|
|
10251
|
+
force = Option13.Boolean("--force", false);
|
|
10252
|
+
dryRun = Option13.Boolean("-n,--dry-run", false);
|
|
10345
10253
|
async run() {
|
|
10346
10254
|
const dbPath = resolveDbPath({ global: this.global, db: this.db, ...defaultRuntimeContext() });
|
|
10347
10255
|
if (!assertDbExists(dbPath, this.context.stderr)) return ExitCode.NotFound;
|
|
@@ -10505,9 +10413,9 @@ var ORPHANS_COMMANDS = [
|
|
|
10505
10413
|
];
|
|
10506
10414
|
|
|
10507
10415
|
// cli/commands/plugins.ts
|
|
10508
|
-
import { existsSync as
|
|
10509
|
-
import { join as
|
|
10510
|
-
import { Command as
|
|
10416
|
+
import { existsSync as existsSync13 } from "fs";
|
|
10417
|
+
import { join as join12, resolve as resolve16 } from "path";
|
|
10418
|
+
import { Command as Command14, Option as Option14 } from "clipanion";
|
|
10511
10419
|
|
|
10512
10420
|
// cli/i18n/plugins.texts.ts
|
|
10513
10421
|
var PLUGINS_TEXTS = {
|
|
@@ -10554,8 +10462,8 @@ var PLUGINS_TEXTS = {
|
|
|
10554
10462
|
rowStatusOkPad: "ok ",
|
|
10555
10463
|
rowStatusOffPad: "off ",
|
|
10556
10464
|
builtInBundleHeader: "{{status}} {{id}}@built-in (granularity={{granularity}})",
|
|
10557
|
-
builtInBundleKindsLine: "
|
|
10558
|
-
builtInExtensionRow: "
|
|
10465
|
+
builtInBundleKindsLine: " {{kinds}}",
|
|
10466
|
+
builtInExtensionRow: "{{stat}} {{kind}}:{{qualifiedId}}@{{version}}",
|
|
10559
10467
|
pluginRow: "{{statusIcon}} {{id}}@{{version}}{{granularitySuffix}}{{tail}}",
|
|
10560
10468
|
pluginRowGranularitySuffix: " (granularity={{granularity}})",
|
|
10561
10469
|
pluginRowTailEnabled: " \xB7 {{kinds}}",
|
|
@@ -10582,9 +10490,9 @@ var PLUGINS_TEXTS = {
|
|
|
10582
10490
|
};
|
|
10583
10491
|
|
|
10584
10492
|
// cli/commands/plugins.ts
|
|
10585
|
-
function resolveSearchPaths2(opts, cwd,
|
|
10586
|
-
if (opts.pluginDir) return [
|
|
10587
|
-
const ctx = { cwd, homedir:
|
|
10493
|
+
function resolveSearchPaths2(opts, cwd, homedir3) {
|
|
10494
|
+
if (opts.pluginDir) return [resolve16(opts.pluginDir)];
|
|
10495
|
+
const ctx = { cwd, homedir: homedir3 };
|
|
10588
10496
|
const project = defaultProjectPluginsDir(ctx);
|
|
10589
10497
|
const user = defaultUserPluginsDir(ctx);
|
|
10590
10498
|
return opts.global ? [user] : [project, user];
|
|
@@ -10652,12 +10560,12 @@ function builtInRows(resolveEnabled) {
|
|
|
10652
10560
|
}
|
|
10653
10561
|
var PluginsListCommand = class extends SmCommand {
|
|
10654
10562
|
static paths = [["plugins", "list"]];
|
|
10655
|
-
static usage =
|
|
10563
|
+
static usage = Command14.Usage({
|
|
10656
10564
|
category: "Plugins",
|
|
10657
10565
|
description: "List discovered plugins and their load status.",
|
|
10658
10566
|
details: "Scans <scope>/.skill-map/plugins and ~/.skill-map/plugins (or --plugin-dir <path>). Built-in bundles (claude, core) are listed alongside user plugins."
|
|
10659
10567
|
});
|
|
10660
|
-
pluginDir =
|
|
10568
|
+
pluginDir = Option14.String("--plugin-dir", { required: false });
|
|
10661
10569
|
async run() {
|
|
10662
10570
|
const plugins = await loadAll({ global: this.global, pluginDir: this.pluginDir });
|
|
10663
10571
|
const resolveEnabled = await buildResolver(this.global);
|
|
@@ -10687,13 +10595,15 @@ function renderBuiltInBundleRow(bundle) {
|
|
|
10687
10595
|
})
|
|
10688
10596
|
);
|
|
10689
10597
|
if (bundle.granularity === "bundle") {
|
|
10690
|
-
const
|
|
10691
|
-
|
|
10598
|
+
for (const ext of bundle.extensions) {
|
|
10599
|
+
const line = `${ext.kind}:${qualifiedExtensionId(bundle.id, ext.id)}@${ext.version}`;
|
|
10600
|
+
lines.push(tx(PLUGINS_TEXTS.builtInBundleKindsLine, { kinds: line }));
|
|
10601
|
+
}
|
|
10692
10602
|
} else {
|
|
10693
10603
|
for (const ext of bundle.extensions) {
|
|
10694
10604
|
lines.push(
|
|
10695
10605
|
tx(PLUGINS_TEXTS.builtInExtensionRow, {
|
|
10696
|
-
stat: ext.enabled ? PLUGINS_TEXTS.
|
|
10606
|
+
stat: ext.enabled ? PLUGINS_TEXTS.rowStatusOk : PLUGINS_TEXTS.rowStatusOff,
|
|
10697
10607
|
kind: ext.kind,
|
|
10698
10608
|
qualifiedId: qualifiedExtensionId(bundle.id, ext.id),
|
|
10699
10609
|
version: ext.version
|
|
@@ -10719,12 +10629,12 @@ function renderPluginRow(p) {
|
|
|
10719
10629
|
}
|
|
10720
10630
|
var PluginsShowCommand = class extends SmCommand {
|
|
10721
10631
|
static paths = [["plugins", "show"]];
|
|
10722
|
-
static usage =
|
|
10632
|
+
static usage = Command14.Usage({
|
|
10723
10633
|
category: "Plugins",
|
|
10724
10634
|
description: "Show a single plugin's manifest + loaded extensions."
|
|
10725
10635
|
});
|
|
10726
|
-
id =
|
|
10727
|
-
pluginDir =
|
|
10636
|
+
id = Option14.String({ required: true });
|
|
10637
|
+
pluginDir = Option14.String("--plugin-dir", { required: false });
|
|
10728
10638
|
async run() {
|
|
10729
10639
|
const plugins = await loadAll({ global: this.global, pluginDir: this.pluginDir });
|
|
10730
10640
|
const resolveEnabled = await buildResolver(this.global);
|
|
@@ -10899,18 +10809,18 @@ function appendUnknownKindWarnings(out, extractorQualifiedId, applicableKinds, k
|
|
|
10899
10809
|
if (!knownKinds.has(k)) out.push({ extractorQualifiedId, unknownKind: k });
|
|
10900
10810
|
}
|
|
10901
10811
|
}
|
|
10902
|
-
function expandHome(p,
|
|
10903
|
-
if (p === "~") return
|
|
10904
|
-
if (p.startsWith("~/")) return
|
|
10812
|
+
function expandHome(p, homedir3) {
|
|
10813
|
+
if (p === "~") return homedir3;
|
|
10814
|
+
if (p.startsWith("~/")) return join12(homedir3, p.slice(2));
|
|
10905
10815
|
return p;
|
|
10906
10816
|
}
|
|
10907
|
-
function collectExplorationDirWarnings(plugins,
|
|
10817
|
+
function collectExplorationDirWarnings(plugins, homedir3) {
|
|
10908
10818
|
const out = [];
|
|
10909
10819
|
forEachProviderInstance(plugins, ({ id, pluginId, instance }) => {
|
|
10910
10820
|
const dir = instance["explorationDir"];
|
|
10911
10821
|
if (typeof dir !== "string" || dir.length === 0) return;
|
|
10912
|
-
const resolved = expandHome(dir,
|
|
10913
|
-
if (!
|
|
10822
|
+
const resolved = expandHome(dir, homedir3);
|
|
10823
|
+
if (!existsSync13(resolved)) {
|
|
10914
10824
|
out.push({
|
|
10915
10825
|
providerQualifiedId: qualifiedExtensionId(pluginId, id),
|
|
10916
10826
|
explorationDir: dir,
|
|
@@ -10922,12 +10832,12 @@ function collectExplorationDirWarnings(plugins, homedir2) {
|
|
|
10922
10832
|
}
|
|
10923
10833
|
var PluginsDoctorCommand = class extends SmCommand {
|
|
10924
10834
|
static paths = [["plugins", "doctor"]];
|
|
10925
|
-
static usage =
|
|
10835
|
+
static usage = Command14.Usage({
|
|
10926
10836
|
category: "Plugins",
|
|
10927
10837
|
description: "Run the full load pass and summarise by failure mode.",
|
|
10928
10838
|
details: "Exit code 0 when every plugin loads or is intentionally disabled; 1 when any plugin is in an error / incompat state."
|
|
10929
10839
|
});
|
|
10930
|
-
pluginDir =
|
|
10840
|
+
pluginDir = Option14.String("--plugin-dir", { required: false });
|
|
10931
10841
|
// Doctor verb: counts by status + applicableKinds warnings +
|
|
10932
10842
|
// explorationDir warnings + bad-plugins issues, each with its own
|
|
10933
10843
|
// gated render. Branching is intrinsic to the multi-section diagnostic
|
|
@@ -11093,8 +11003,8 @@ function resolveToggleTarget(id, catalogue, verb) {
|
|
|
11093
11003
|
return { key: bundle.id };
|
|
11094
11004
|
}
|
|
11095
11005
|
var TogglePluginsBase = class extends SmCommand {
|
|
11096
|
-
all =
|
|
11097
|
-
id =
|
|
11006
|
+
all = Option14.Boolean("--all", false);
|
|
11007
|
+
id = Option14.String({ required: false });
|
|
11098
11008
|
// eslint-disable-next-line complexity
|
|
11099
11009
|
async toggle(enabled) {
|
|
11100
11010
|
const verb = enabled ? "enable" : "disable";
|
|
@@ -11145,7 +11055,7 @@ var TogglePluginsBase = class extends SmCommand {
|
|
|
11145
11055
|
};
|
|
11146
11056
|
var PluginsEnableCommand = class extends TogglePluginsBase {
|
|
11147
11057
|
static paths = [["plugins", "enable"]];
|
|
11148
|
-
static usage =
|
|
11058
|
+
static usage = Command14.Usage({
|
|
11149
11059
|
category: "Plugins",
|
|
11150
11060
|
description: "Enable a plugin (or --all). Persists in config_plugins.",
|
|
11151
11061
|
details: `
|
|
@@ -11167,7 +11077,7 @@ var PluginsEnableCommand = class extends TogglePluginsBase {
|
|
|
11167
11077
|
};
|
|
11168
11078
|
var PluginsDisableCommand = class extends TogglePluginsBase {
|
|
11169
11079
|
static paths = [["plugins", "disable"]];
|
|
11170
|
-
static usage =
|
|
11080
|
+
static usage = Command14.Usage({
|
|
11171
11081
|
category: "Plugins",
|
|
11172
11082
|
description: "Disable a plugin (or --all). Persists in config_plugins; does not delete files.",
|
|
11173
11083
|
details: `
|
|
@@ -11203,8 +11113,8 @@ var PLUGIN_COMMANDS = [
|
|
|
11203
11113
|
|
|
11204
11114
|
// cli/commands/refresh.ts
|
|
11205
11115
|
import { readFile as readFile3 } from "fs/promises";
|
|
11206
|
-
import { resolve as
|
|
11207
|
-
import { Command as
|
|
11116
|
+
import { resolve as resolve18 } from "path";
|
|
11117
|
+
import { Command as Command15, Option as Option15 } from "clipanion";
|
|
11208
11118
|
|
|
11209
11119
|
// cli/i18n/refresh.texts.ts
|
|
11210
11120
|
var REFRESH_TEXTS = {
|
|
@@ -11233,12 +11143,12 @@ var REFRESH_TEXTS = {
|
|
|
11233
11143
|
};
|
|
11234
11144
|
|
|
11235
11145
|
// cli/util/path-guard.ts
|
|
11236
|
-
import { isAbsolute as isAbsolute3, resolve as
|
|
11146
|
+
import { isAbsolute as isAbsolute3, resolve as resolve17, sep as sep3 } from "path";
|
|
11237
11147
|
function assertContained2(cwd, rel) {
|
|
11238
11148
|
if (isAbsolute3(rel)) {
|
|
11239
11149
|
throw new Error(`node path is absolute, refusing to read: ${rel}`);
|
|
11240
11150
|
}
|
|
11241
|
-
const abs =
|
|
11151
|
+
const abs = resolve17(cwd, rel);
|
|
11242
11152
|
if (abs !== cwd && !abs.startsWith(cwd + sep3)) {
|
|
11243
11153
|
throw new Error(`node path escapes repo root: ${rel}`);
|
|
11244
11154
|
}
|
|
@@ -11247,7 +11157,7 @@ function assertContained2(cwd, rel) {
|
|
|
11247
11157
|
// cli/commands/refresh.ts
|
|
11248
11158
|
var RefreshCommand = class extends SmCommand {
|
|
11249
11159
|
static paths = [["refresh"]];
|
|
11250
|
-
static usage =
|
|
11160
|
+
static usage = Command15.Usage({
|
|
11251
11161
|
category: "Scan",
|
|
11252
11162
|
description: "Refresh enrichment rows: granular (single node) or batch (every stale row).",
|
|
11253
11163
|
details: `
|
|
@@ -11272,11 +11182,11 @@ var RefreshCommand = class extends SmCommand {
|
|
|
11272
11182
|
["Refresh every node with stale enrichments", "$0 refresh --stale"]
|
|
11273
11183
|
]
|
|
11274
11184
|
});
|
|
11275
|
-
nodePath =
|
|
11276
|
-
stale =
|
|
11185
|
+
nodePath = Option15.String({ name: "node", required: false });
|
|
11186
|
+
stale = Option15.Boolean("--stale", false, {
|
|
11277
11187
|
description: "Refresh every node whose probabilistic enrichment row is flagged stale=1."
|
|
11278
11188
|
});
|
|
11279
|
-
noPlugins =
|
|
11189
|
+
noPlugins = Option15.Boolean("--no-plugins", false, {
|
|
11280
11190
|
description: "Skip drop-in plugin discovery; use only the built-in extractor set."
|
|
11281
11191
|
});
|
|
11282
11192
|
// The remaining cyclomatic count comes from CLI ergonomics that don't
|
|
@@ -11412,7 +11322,7 @@ var RefreshCommand = class extends SmCommand {
|
|
|
11412
11322
|
let body;
|
|
11413
11323
|
try {
|
|
11414
11324
|
assertContained2(cwd, node.path);
|
|
11415
|
-
const raw = await readFile3(
|
|
11325
|
+
const raw = await readFile3(resolve18(cwd, node.path), "utf8");
|
|
11416
11326
|
body = stripFrontmatterFence(raw);
|
|
11417
11327
|
} catch (err) {
|
|
11418
11328
|
this.context.stderr.write(
|
|
@@ -11461,7 +11371,7 @@ function stripFrontmatterFence(text) {
|
|
|
11461
11371
|
var REFRESH_COMMANDS = [RefreshCommand];
|
|
11462
11372
|
|
|
11463
11373
|
// cli/commands/scan.ts
|
|
11464
|
-
import { Command as
|
|
11374
|
+
import { Command as Command17, Option as Option17 } from "clipanion";
|
|
11465
11375
|
|
|
11466
11376
|
// cli/i18n/scan.texts.ts
|
|
11467
11377
|
var SCAN_TEXTS = {
|
|
@@ -11653,7 +11563,7 @@ async function runEphemeralPath(opts, dbPath, strict, loadPrior, runScanWith) {
|
|
|
11653
11563
|
}
|
|
11654
11564
|
|
|
11655
11565
|
// cli/commands/watch.ts
|
|
11656
|
-
import { Command as
|
|
11566
|
+
import { Command as Command16, Option as Option16 } from "clipanion";
|
|
11657
11567
|
|
|
11658
11568
|
// cli/i18n/watch.texts.ts
|
|
11659
11569
|
var WATCH_TEXTS = {
|
|
@@ -11832,7 +11742,7 @@ async function runWatchLoop(opts) {
|
|
|
11832
11742
|
}
|
|
11833
11743
|
var WatchCommand = class extends SmCommand {
|
|
11834
11744
|
static paths = [["watch"]];
|
|
11835
|
-
static usage =
|
|
11745
|
+
static usage = Command16.Usage({
|
|
11836
11746
|
category: "Scan",
|
|
11837
11747
|
description: "Watch roots and run an incremental scan after each debounced batch of filesystem events.",
|
|
11838
11748
|
details: `
|
|
@@ -11856,17 +11766,17 @@ var WatchCommand = class extends SmCommand {
|
|
|
11856
11766
|
["Stream ScanResult per batch as ndjson", "$0 watch --json"]
|
|
11857
11767
|
]
|
|
11858
11768
|
});
|
|
11859
|
-
roots =
|
|
11860
|
-
noTokens =
|
|
11769
|
+
roots = Option16.Rest({ name: "roots" });
|
|
11770
|
+
noTokens = Option16.Boolean("--no-tokens", false, {
|
|
11861
11771
|
description: "Skip per-node token counts (cl100k_base BPE)."
|
|
11862
11772
|
});
|
|
11863
|
-
strict =
|
|
11773
|
+
strict = Option16.Boolean("--strict", false, {
|
|
11864
11774
|
description: "Promote frontmatter-validation findings from warn to error inside each batch. Does not change the watcher exit code."
|
|
11865
11775
|
});
|
|
11866
|
-
noPlugins =
|
|
11776
|
+
noPlugins = Option16.Boolean("--no-plugins", false, {
|
|
11867
11777
|
description: "Skip drop-in plugin discovery for the watcher session."
|
|
11868
11778
|
});
|
|
11869
|
-
maxConsecutiveFailures =
|
|
11779
|
+
maxConsecutiveFailures = Option16.String("--max-consecutive-failures", {
|
|
11870
11780
|
required: false,
|
|
11871
11781
|
description: "Shut down with exit 2 after N consecutive batch failures (default 5; 0 disables the breaker)."
|
|
11872
11782
|
});
|
|
@@ -11904,7 +11814,7 @@ function parseBreakerLimit(raw, stderr) {
|
|
|
11904
11814
|
// cli/commands/scan.ts
|
|
11905
11815
|
var ScanCommand = class extends SmCommand {
|
|
11906
11816
|
static paths = [["scan"]];
|
|
11907
|
-
static usage =
|
|
11817
|
+
static usage = Command17.Usage({
|
|
11908
11818
|
category: "Scan",
|
|
11909
11819
|
description: "Scan roots for markdown nodes, run extractors and rules.",
|
|
11910
11820
|
details: `
|
|
@@ -11933,29 +11843,29 @@ var ScanCommand = class extends SmCommand {
|
|
|
11933
11843
|
["What would the next incremental scan persist?", "$0 scan --changed -n --json"]
|
|
11934
11844
|
]
|
|
11935
11845
|
});
|
|
11936
|
-
roots =
|
|
11937
|
-
noBuiltIns =
|
|
11846
|
+
roots = Option17.Rest({ name: "roots" });
|
|
11847
|
+
noBuiltIns = Option17.Boolean("--no-built-ins", false, {
|
|
11938
11848
|
description: "Skip the built-in extension set. Yields a zero-filled ScanResult (kernel-empty-boot parity); skips DB persistence."
|
|
11939
11849
|
});
|
|
11940
|
-
noPlugins =
|
|
11850
|
+
noPlugins = Option17.Boolean("--no-plugins", false, {
|
|
11941
11851
|
description: "Skip drop-in plugin discovery. Only the built-in set runs. Combine with --no-built-ins for a fully empty pipeline."
|
|
11942
11852
|
});
|
|
11943
|
-
noTokens =
|
|
11853
|
+
noTokens = Option17.Boolean("--no-tokens", false, {
|
|
11944
11854
|
description: "Skip per-node token counts (cl100k_base BPE). Leaves node.tokens undefined; spec-valid since the field is optional."
|
|
11945
11855
|
});
|
|
11946
|
-
dryRun =
|
|
11856
|
+
dryRun = Option17.Boolean("-n,--dry-run", false, {
|
|
11947
11857
|
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."
|
|
11948
11858
|
});
|
|
11949
|
-
changed =
|
|
11859
|
+
changed = Option17.Boolean("--changed", false, {
|
|
11950
11860
|
description: "Incremental scan: reuse unchanged nodes from the persisted prior snapshot. Degrades to a full scan if no prior snapshot exists."
|
|
11951
11861
|
});
|
|
11952
|
-
allowEmpty =
|
|
11862
|
+
allowEmpty = Option17.Boolean("--allow-empty", false, {
|
|
11953
11863
|
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."
|
|
11954
11864
|
});
|
|
11955
|
-
strict =
|
|
11865
|
+
strict = Option17.Boolean("--strict", false, {
|
|
11956
11866
|
description: "Promote frontmatter-validation findings from warn to error (exit code 1 on any violation). Overrides scan.strict from config when both are set."
|
|
11957
11867
|
});
|
|
11958
|
-
watch =
|
|
11868
|
+
watch = Option17.Boolean("--watch", false, {
|
|
11959
11869
|
description: "Long-running mode: watch the roots and trigger an incremental scan after each debounced batch of filesystem events. Alias of `sm watch`."
|
|
11960
11870
|
});
|
|
11961
11871
|
async run() {
|
|
@@ -12053,11 +11963,11 @@ var ScanCommand = class extends SmCommand {
|
|
|
12053
11963
|
};
|
|
12054
11964
|
|
|
12055
11965
|
// cli/commands/scan-compare.ts
|
|
12056
|
-
import { existsSync as
|
|
12057
|
-
import { Command as
|
|
11966
|
+
import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
|
|
11967
|
+
import { Command as Command18, Option as Option18 } from "clipanion";
|
|
12058
11968
|
var ScanCompareCommand = class extends SmCommand {
|
|
12059
11969
|
static paths = [["scan", "compare-with"]];
|
|
12060
|
-
static usage =
|
|
11970
|
+
static usage = Command18.Usage({
|
|
12061
11971
|
category: "Scan",
|
|
12062
11972
|
description: "Run a fresh scan in memory and emit a delta against the saved ScanResult dump at <dump>. Read-only.",
|
|
12063
11973
|
details: `
|
|
@@ -12085,15 +11995,15 @@ var ScanCompareCommand = class extends SmCommand {
|
|
|
12085
11995
|
["JSON output for tooling", "$0 scan compare-with baseline.json --json"]
|
|
12086
11996
|
]
|
|
12087
11997
|
});
|
|
12088
|
-
dump =
|
|
12089
|
-
roots =
|
|
12090
|
-
noTokens =
|
|
11998
|
+
dump = Option18.String({ required: true });
|
|
11999
|
+
roots = Option18.Rest({ name: "roots" });
|
|
12000
|
+
noTokens = Option18.Boolean("--no-tokens", false, {
|
|
12091
12001
|
description: "Skip per-node token counts during the fresh scan."
|
|
12092
12002
|
});
|
|
12093
|
-
strict =
|
|
12003
|
+
strict = Option18.Boolean("--strict", false, {
|
|
12094
12004
|
description: "Promote layered-config warnings and frontmatter-validation findings from warn to error."
|
|
12095
12005
|
});
|
|
12096
|
-
noPlugins =
|
|
12006
|
+
noPlugins = Option18.Boolean("--no-plugins", false, {
|
|
12097
12007
|
description: "Skip drop-in plugin discovery."
|
|
12098
12008
|
});
|
|
12099
12009
|
// Cyclomatic count comes from CLI ergonomics: 3 distinct try/catch
|
|
@@ -12164,12 +12074,12 @@ var ScanCompareCommand = class extends SmCommand {
|
|
|
12164
12074
|
}
|
|
12165
12075
|
};
|
|
12166
12076
|
function loadAndValidateDump(path) {
|
|
12167
|
-
if (!
|
|
12077
|
+
if (!existsSync14(path)) {
|
|
12168
12078
|
throw new Error(tx(SCAN_TEXTS.compareDumpNotFound, { path }));
|
|
12169
12079
|
}
|
|
12170
12080
|
let raw;
|
|
12171
12081
|
try {
|
|
12172
|
-
raw =
|
|
12082
|
+
raw = readFileSync11(path, "utf8");
|
|
12173
12083
|
} catch (err) {
|
|
12174
12084
|
const message = formatErrorMessage(err);
|
|
12175
12085
|
throw new Error(tx(SCAN_TEXTS.compareDumpReadFailed, { path, message }), { cause: err });
|
|
@@ -12278,8 +12188,8 @@ function renderDeltaIssues(issues) {
|
|
|
12278
12188
|
|
|
12279
12189
|
// cli/commands/serve.ts
|
|
12280
12190
|
import { spawn } from "child_process";
|
|
12281
|
-
import { existsSync as
|
|
12282
|
-
import { Command as
|
|
12191
|
+
import { existsSync as existsSync18 } from "fs";
|
|
12192
|
+
import { Command as Command19, Option as Option19 } from "clipanion";
|
|
12283
12193
|
|
|
12284
12194
|
// server/index.ts
|
|
12285
12195
|
import { serve } from "@hono/node-server";
|
|
@@ -12460,7 +12370,7 @@ function contentTypeFor(format) {
|
|
|
12460
12370
|
}
|
|
12461
12371
|
|
|
12462
12372
|
// server/health.ts
|
|
12463
|
-
import { existsSync as
|
|
12373
|
+
import { existsSync as existsSync15 } from "fs";
|
|
12464
12374
|
var FALLBACK_SCHEMA_VERSION = "1";
|
|
12465
12375
|
function buildHealth(deps) {
|
|
12466
12376
|
return {
|
|
@@ -12469,7 +12379,7 @@ function buildHealth(deps) {
|
|
|
12469
12379
|
specVersion: deps.specVersion,
|
|
12470
12380
|
implVersion: VERSION,
|
|
12471
12381
|
scope: deps.scope,
|
|
12472
|
-
db:
|
|
12382
|
+
db: existsSync15(deps.dbPath) ? "present" : "missing"
|
|
12473
12383
|
};
|
|
12474
12384
|
}
|
|
12475
12385
|
async function resolveSpecVersion2() {
|
|
@@ -12909,9 +12819,9 @@ function emptyScanResult() {
|
|
|
12909
12819
|
}
|
|
12910
12820
|
|
|
12911
12821
|
// server/static.ts
|
|
12912
|
-
import { existsSync as
|
|
12822
|
+
import { existsSync as existsSync16 } from "fs";
|
|
12913
12823
|
import { readFile as readFile5 } from "fs/promises";
|
|
12914
|
-
import { extname, join as
|
|
12824
|
+
import { extname, join as join13 } from "path";
|
|
12915
12825
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
12916
12826
|
var INDEX_HTML = "index.html";
|
|
12917
12827
|
var PLACEHOLDER_HTML = `<!doctype html>
|
|
@@ -12942,8 +12852,8 @@ function createSpaFallback(uiDist) {
|
|
|
12942
12852
|
return async (c, _next) => {
|
|
12943
12853
|
if (c.req.method !== "GET" && c.req.method !== "HEAD") return c.notFound();
|
|
12944
12854
|
if (uiDist === null) return htmlResponse(c, PLACEHOLDER_HTML);
|
|
12945
|
-
const indexPath =
|
|
12946
|
-
if (!
|
|
12855
|
+
const indexPath = join13(uiDist, INDEX_HTML);
|
|
12856
|
+
if (!existsSync16(indexPath)) return htmlResponse(c, PLACEHOLDER_HTML);
|
|
12947
12857
|
return fileResponse(c, indexPath);
|
|
12948
12858
|
};
|
|
12949
12859
|
}
|
|
@@ -13347,6 +13257,7 @@ function createWatcherService(opts) {
|
|
|
13347
13257
|
if ("ready" in chokidarHandle && chokidarHandle.ready instanceof Promise) {
|
|
13348
13258
|
await chokidarHandle.ready;
|
|
13349
13259
|
}
|
|
13260
|
+
await runInitialBatch({ isStopped: () => stopped, runOneBatch });
|
|
13350
13261
|
opts.broadcaster.broadcast(
|
|
13351
13262
|
buildWatcherStartedEvent({ roots: [WATCH_ROOT], debounceMs })
|
|
13352
13263
|
);
|
|
@@ -13429,6 +13340,19 @@ async function persistOutcome(dbPath, ran) {
|
|
|
13429
13340
|
(writer) => writer.scans.persist(result, { renameOps, extractorRuns, enrichments })
|
|
13430
13341
|
);
|
|
13431
13342
|
}
|
|
13343
|
+
async function runInitialBatch(deps) {
|
|
13344
|
+
if (deps.isStopped()) return;
|
|
13345
|
+
try {
|
|
13346
|
+
await deps.runOneBatch();
|
|
13347
|
+
} catch (err) {
|
|
13348
|
+
const message = formatErrorMessage(err);
|
|
13349
|
+
log.warn(
|
|
13350
|
+
tx(SERVER_TEXTS.watcherBatchFailed, {
|
|
13351
|
+
message: sanitizeForTerminal(message)
|
|
13352
|
+
})
|
|
13353
|
+
);
|
|
13354
|
+
}
|
|
13355
|
+
}
|
|
13432
13356
|
|
|
13433
13357
|
// server/options.ts
|
|
13434
13358
|
var DEFAULT_PORT = 4242;
|
|
@@ -13533,10 +13457,10 @@ function validateWatcherDebounce(value) {
|
|
|
13533
13457
|
}
|
|
13534
13458
|
|
|
13535
13459
|
// server/paths.ts
|
|
13536
|
-
import { existsSync as
|
|
13537
|
-
import { dirname as
|
|
13538
|
-
import { fileURLToPath as
|
|
13539
|
-
var DEFAULT_UI_REL =
|
|
13460
|
+
import { existsSync as existsSync17, statSync as statSync5 } from "fs";
|
|
13461
|
+
import { dirname as dirname9, isAbsolute as isAbsolute5, join as join14, resolve as resolve19 } from "path";
|
|
13462
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
13463
|
+
var DEFAULT_UI_REL = join14("ui", "dist", "ui", "browser");
|
|
13540
13464
|
var PACKAGE_UI_REL = "ui";
|
|
13541
13465
|
var INDEX_HTML2 = "index.html";
|
|
13542
13466
|
function resolveDefaultUiDist(ctx) {
|
|
@@ -13545,13 +13469,13 @@ function resolveDefaultUiDist(ctx) {
|
|
|
13545
13469
|
return walkUpForUi(ctx.cwd);
|
|
13546
13470
|
}
|
|
13547
13471
|
function resolveExplicitUiDist(ctx, raw) {
|
|
13548
|
-
return isAbsolute5(raw) ? raw :
|
|
13472
|
+
return isAbsolute5(raw) ? raw : resolve19(ctx.cwd, raw);
|
|
13549
13473
|
}
|
|
13550
13474
|
function isUiBundleDir(path) {
|
|
13551
|
-
if (!
|
|
13475
|
+
if (!existsSync17(path)) return false;
|
|
13552
13476
|
try {
|
|
13553
13477
|
if (!statSync5(path).isDirectory()) return false;
|
|
13554
|
-
return
|
|
13478
|
+
return existsSync17(join14(path, INDEX_HTML2));
|
|
13555
13479
|
} catch {
|
|
13556
13480
|
return false;
|
|
13557
13481
|
}
|
|
@@ -13559,7 +13483,7 @@ function isUiBundleDir(path) {
|
|
|
13559
13483
|
function resolvePackageBundledUi() {
|
|
13560
13484
|
let here;
|
|
13561
13485
|
try {
|
|
13562
|
-
here =
|
|
13486
|
+
here = dirname9(fileURLToPath5(import.meta.url));
|
|
13563
13487
|
} catch {
|
|
13564
13488
|
return null;
|
|
13565
13489
|
}
|
|
@@ -13568,22 +13492,22 @@ function resolvePackageBundledUi() {
|
|
|
13568
13492
|
function resolvePackageBundledUiFrom(here) {
|
|
13569
13493
|
let current = here;
|
|
13570
13494
|
for (let i = 0; i < 8; i++) {
|
|
13571
|
-
const candidate =
|
|
13495
|
+
const candidate = join14(current, PACKAGE_UI_REL);
|
|
13572
13496
|
if (isUiBundleDir(candidate)) return candidate;
|
|
13573
|
-
const distHere =
|
|
13497
|
+
const distHere = join14(current, "dist", PACKAGE_UI_REL);
|
|
13574
13498
|
if (isUiBundleDir(distHere)) return distHere;
|
|
13575
|
-
const parent =
|
|
13499
|
+
const parent = dirname9(current);
|
|
13576
13500
|
if (parent === current) return null;
|
|
13577
13501
|
current = parent;
|
|
13578
13502
|
}
|
|
13579
13503
|
return null;
|
|
13580
13504
|
}
|
|
13581
13505
|
function walkUpForUi(startDir) {
|
|
13582
|
-
let current =
|
|
13506
|
+
let current = resolve19(startDir);
|
|
13583
13507
|
for (let i = 0; i < 64; i++) {
|
|
13584
|
-
const candidate =
|
|
13508
|
+
const candidate = join14(current, DEFAULT_UI_REL);
|
|
13585
13509
|
if (isUiBundleDir(candidate)) return candidate;
|
|
13586
|
-
const parent =
|
|
13510
|
+
const parent = dirname9(current);
|
|
13587
13511
|
if (parent === current) return null;
|
|
13588
13512
|
current = parent;
|
|
13589
13513
|
}
|
|
@@ -13706,17 +13630,13 @@ function normalizeAddress(addr, fallbackHost, fallbackPort) {
|
|
|
13706
13630
|
|
|
13707
13631
|
// cli/i18n/serve.texts.ts
|
|
13708
13632
|
var SERVE_TEXTS = {
|
|
13709
|
-
//
|
|
13710
|
-
//
|
|
13711
|
-
//
|
|
13712
|
-
|
|
13713
|
-
//
|
|
13714
|
-
//
|
|
13715
|
-
//
|
|
13716
|
-
// Both end with the Ctrl+C reminder so the operational tail is
|
|
13717
|
-
// identical regardless of branch.
|
|
13718
|
-
bootOpening: "sm serve: opening http://{{host}}:{{port}}/ in your browser. Press Ctrl+C to stop.\n",
|
|
13719
|
-
bootVisitHint: "sm serve: visit http://{{host}}:{{port}}/ in your browser. Press Ctrl+C to stop.\n",
|
|
13633
|
+
// The boot banner (TTY box / flat-line fallback) is rendered by
|
|
13634
|
+
// `cli/util/serve-banner.ts` rather than templated through `tx` —
|
|
13635
|
+
// ANSI escapes + box-drawing aren't a good fit for the flat
|
|
13636
|
+
// `{{name}}` interpolation surface. The flat-mode strings live in
|
|
13637
|
+
// that helper and stay byte-equivalent to the pre-banner format so
|
|
13638
|
+
// existing pipes / redirects ('listening on <url>' scrapers) don't
|
|
13639
|
+
// break.
|
|
13720
13640
|
// Browser-open failure. Non-fatal — the URL is already printed; the
|
|
13721
13641
|
// user can open it manually.
|
|
13722
13642
|
openFailed: "sm serve: could not auto-open browser ({{message}}). Visit {{url}} manually.\n",
|
|
@@ -13740,10 +13660,140 @@ var SERVE_TEXTS = {
|
|
|
13740
13660
|
shutdown: "sm serve: shutdown complete.\n"
|
|
13741
13661
|
};
|
|
13742
13662
|
|
|
13663
|
+
// cli/util/serve-banner.ts
|
|
13664
|
+
import { homedir as homedir2 } from "os";
|
|
13665
|
+
import { relative as relative5, isAbsolute as isAbsolute6 } from "path";
|
|
13666
|
+
var ESC = {
|
|
13667
|
+
reset: "\x1B[0m",
|
|
13668
|
+
bold: "\x1B[1m",
|
|
13669
|
+
dim: "\x1B[2m",
|
|
13670
|
+
underline: "\x1B[4m",
|
|
13671
|
+
/** 256-color violet (xterm 141). */
|
|
13672
|
+
violet: "\x1B[38;5;141m",
|
|
13673
|
+
/** 256-color green (xterm 42). */
|
|
13674
|
+
green: "\x1B[38;5;42m"
|
|
13675
|
+
};
|
|
13676
|
+
var LOGO_LINES = [
|
|
13677
|
+
" ____ _ _ _ _ __ __ ",
|
|
13678
|
+
" / ___|| | _(_) | | | \\/ | __ _ _ __ ",
|
|
13679
|
+
" \\___ \\| |/ / | | | | |\\/| |/ _` | '_ \\ ",
|
|
13680
|
+
" ___) | <| | | | | | | | (_| | |_) |",
|
|
13681
|
+
" |____/|_|\\_\\_|_|_| |_| |_|\\__,_| .__/ ",
|
|
13682
|
+
" |_| "
|
|
13683
|
+
];
|
|
13684
|
+
var LOGO_WIDTH = 40;
|
|
13685
|
+
function renderBanner(input) {
|
|
13686
|
+
const url = `http://${input.host}:${input.port}`;
|
|
13687
|
+
const dbDisplay = formatDbPath(input.dbPath, input.cwd);
|
|
13688
|
+
const browserLine = input.openBrowser ? "Opening browser\u2026 Press Ctrl+C to stop." : `Visit ${url}/ in your browser. Press Ctrl+C to stop.`;
|
|
13689
|
+
if (!input.isTTY) {
|
|
13690
|
+
return renderFlat({
|
|
13691
|
+
host: input.host,
|
|
13692
|
+
port: input.port,
|
|
13693
|
+
scope: input.scope,
|
|
13694
|
+
dbPath: input.dbPath,
|
|
13695
|
+
openBrowser: input.openBrowser
|
|
13696
|
+
});
|
|
13697
|
+
}
|
|
13698
|
+
return renderFiglet({
|
|
13699
|
+
version: input.version,
|
|
13700
|
+
url,
|
|
13701
|
+
scope: input.scope,
|
|
13702
|
+
dbDisplay,
|
|
13703
|
+
pathDisplay: formatCwdPath(input.cwd),
|
|
13704
|
+
browserLine,
|
|
13705
|
+
colorEnabled: input.colorEnabled
|
|
13706
|
+
});
|
|
13707
|
+
}
|
|
13708
|
+
function resolveColorEnabled(opts) {
|
|
13709
|
+
if (opts.noColorFlag) return false;
|
|
13710
|
+
const noColor = opts.env["NO_COLOR"];
|
|
13711
|
+
if (noColor !== void 0 && noColor !== "") return false;
|
|
13712
|
+
const forceColor = opts.env["FORCE_COLOR"];
|
|
13713
|
+
if (forceColor !== void 0 && forceColor !== "") return true;
|
|
13714
|
+
return opts.isTTY;
|
|
13715
|
+
}
|
|
13716
|
+
function renderFlat(input) {
|
|
13717
|
+
const safeHost = sanitizeForTerminal(input.host);
|
|
13718
|
+
const safeDb = sanitizeForTerminal(input.dbPath);
|
|
13719
|
+
const url = `http://${safeHost}:${input.port}`;
|
|
13720
|
+
const linesOut = [];
|
|
13721
|
+
linesOut.push(`sm serve: listening on ${url} (scope=${input.scope}, db=${safeDb})`);
|
|
13722
|
+
if (input.openBrowser) {
|
|
13723
|
+
linesOut.push(`sm serve: opening ${url}/ in your browser. Press Ctrl+C to stop.`);
|
|
13724
|
+
} else {
|
|
13725
|
+
linesOut.push(`sm serve: visit ${url}/ in your browser. Press Ctrl+C to stop.`);
|
|
13726
|
+
}
|
|
13727
|
+
return linesOut.join("\n") + "\n";
|
|
13728
|
+
}
|
|
13729
|
+
function renderFiglet(input) {
|
|
13730
|
+
const {
|
|
13731
|
+
dimOpen,
|
|
13732
|
+
dimClose,
|
|
13733
|
+
greenUnderline,
|
|
13734
|
+
greenUnderlineClose,
|
|
13735
|
+
violetOpen,
|
|
13736
|
+
violetClose
|
|
13737
|
+
} = resolveAnsi(input.colorEnabled);
|
|
13738
|
+
const logoLines = LOGO_LINES.map((line) => `${violetOpen}${line}${violetClose}`);
|
|
13739
|
+
const versionText = `v${input.version}`;
|
|
13740
|
+
const versionPad = Math.max(0, LOGO_WIDTH - versionText.length);
|
|
13741
|
+
const versionLine = `${" ".repeat(versionPad)}${dimOpen}${versionText}${dimClose}`;
|
|
13742
|
+
const lines = [];
|
|
13743
|
+
lines.push(...logoLines);
|
|
13744
|
+
lines.push("");
|
|
13745
|
+
lines.push(versionLine);
|
|
13746
|
+
lines.push("");
|
|
13747
|
+
lines.push(` ${dimOpen}Server${dimClose} ${greenUnderline}${input.url}${greenUnderlineClose}`);
|
|
13748
|
+
lines.push(` ${dimOpen}Scope${dimClose} ${input.scope}`);
|
|
13749
|
+
lines.push(` ${dimOpen}Path${dimClose} ${input.pathDisplay}`);
|
|
13750
|
+
lines.push(` ${dimOpen}DB${dimClose} ${input.dbDisplay}`);
|
|
13751
|
+
lines.push("");
|
|
13752
|
+
lines.push(` ${dimOpen}${input.browserLine}${dimClose}`);
|
|
13753
|
+
lines.push("");
|
|
13754
|
+
return lines.join("\n") + "\n";
|
|
13755
|
+
}
|
|
13756
|
+
var EMPTY_ANSI = {
|
|
13757
|
+
dimOpen: "",
|
|
13758
|
+
dimClose: "",
|
|
13759
|
+
greenUnderline: "",
|
|
13760
|
+
greenUnderlineClose: "",
|
|
13761
|
+
violetOpen: "",
|
|
13762
|
+
violetClose: ""
|
|
13763
|
+
};
|
|
13764
|
+
var ENABLED_ANSI = {
|
|
13765
|
+
dimOpen: ESC.dim,
|
|
13766
|
+
dimClose: ESC.reset,
|
|
13767
|
+
greenUnderline: `${ESC.green}${ESC.underline}`,
|
|
13768
|
+
greenUnderlineClose: ESC.reset,
|
|
13769
|
+
violetOpen: ESC.violet,
|
|
13770
|
+
violetClose: ESC.reset
|
|
13771
|
+
};
|
|
13772
|
+
function resolveAnsi(colorEnabled) {
|
|
13773
|
+
return colorEnabled ? ENABLED_ANSI : EMPTY_ANSI;
|
|
13774
|
+
}
|
|
13775
|
+
function formatDbPath(dbPath, cwd) {
|
|
13776
|
+
const safe = sanitizeForTerminal(dbPath);
|
|
13777
|
+
if (!isAbsolute6(safe)) return safe;
|
|
13778
|
+
const rel = relative5(cwd, safe);
|
|
13779
|
+
if (rel === "" || rel.startsWith("..") || isAbsolute6(rel)) {
|
|
13780
|
+
return safe;
|
|
13781
|
+
}
|
|
13782
|
+
return rel;
|
|
13783
|
+
}
|
|
13784
|
+
function formatCwdPath(cwd) {
|
|
13785
|
+
const safe = sanitizeForTerminal(cwd);
|
|
13786
|
+
const home = homedir2();
|
|
13787
|
+
if (home && (safe === home || safe.startsWith(`${home}/`))) {
|
|
13788
|
+
return `~${safe.slice(home.length)}`;
|
|
13789
|
+
}
|
|
13790
|
+
return safe;
|
|
13791
|
+
}
|
|
13792
|
+
|
|
13743
13793
|
// cli/commands/serve.ts
|
|
13744
13794
|
var ServeCommand = class extends SmCommand {
|
|
13745
13795
|
static paths = [["serve"]];
|
|
13746
|
-
static usage =
|
|
13796
|
+
static usage = Command19.Usage({
|
|
13747
13797
|
category: "Setup",
|
|
13748
13798
|
description: "Start the Hono BFF (single-port: REST + WebSocket + SPA bundle).",
|
|
13749
13799
|
details: `
|
|
@@ -13768,22 +13818,22 @@ var ServeCommand = class extends SmCommand {
|
|
|
13768
13818
|
["Point at a pre-built UI bundle", "$0 serve --ui-dist ./ui/dist/browser"]
|
|
13769
13819
|
]
|
|
13770
13820
|
});
|
|
13771
|
-
port =
|
|
13821
|
+
port = Option19.String("--port", {
|
|
13772
13822
|
required: false,
|
|
13773
13823
|
description: "Listening port (default 4242). 0 = OS-assigned."
|
|
13774
13824
|
});
|
|
13775
|
-
host =
|
|
13825
|
+
host = Option19.String("--host", {
|
|
13776
13826
|
required: false,
|
|
13777
13827
|
description: "Listening host (default 127.0.0.1). Loopback-only enforced when --dev-cors is set."
|
|
13778
13828
|
});
|
|
13779
|
-
scope =
|
|
13829
|
+
scope = Option19.String("--scope", {
|
|
13780
13830
|
required: false,
|
|
13781
13831
|
description: "project | global. Alias for -g/--global. Default: project."
|
|
13782
13832
|
});
|
|
13783
|
-
noBuiltIns =
|
|
13833
|
+
noBuiltIns = Option19.Boolean("--no-built-ins", false, {
|
|
13784
13834
|
description: "Skip built-in plugin registration (parity with sm scan --no-built-ins)."
|
|
13785
13835
|
});
|
|
13786
|
-
noPlugins =
|
|
13836
|
+
noPlugins = Option19.Boolean("--no-plugins", false, {
|
|
13787
13837
|
description: "Skip drop-in plugin discovery."
|
|
13788
13838
|
});
|
|
13789
13839
|
// `Option.Boolean('--open', true)` — Clipanion's parser auto-derives
|
|
@@ -13793,24 +13843,24 @@ var ServeCommand = class extends SmCommand {
|
|
|
13793
13843
|
// two registrations for the same flag and rejects the invocation
|
|
13794
13844
|
// with "Ambiguous Syntax Error". Same convention shipped by every
|
|
13795
13845
|
// other `--no-...` flag in the CLI tree.
|
|
13796
|
-
open =
|
|
13846
|
+
open = Option19.Boolean("--open", true, {
|
|
13797
13847
|
description: "Auto-open the SPA in the user's default browser after listen. --no-open opts out."
|
|
13798
13848
|
});
|
|
13799
|
-
devCors =
|
|
13849
|
+
devCors = Option19.Boolean("--dev-cors", false, {
|
|
13800
13850
|
description: "Enable permissive CORS for the Angular dev-server proxy workflow."
|
|
13801
13851
|
});
|
|
13802
13852
|
// `--ui-dist` is intentionally undocumented in the Usage block above
|
|
13803
13853
|
// (the demo build pipeline + tests rely on it; everyday users never
|
|
13804
13854
|
// need it). Clipanion still exposes it on the parser; the Usage
|
|
13805
13855
|
// omission is the "hidden" contract per the 14.1 brief.
|
|
13806
|
-
uiDist =
|
|
13807
|
-
noWatcher =
|
|
13856
|
+
uiDist = Option19.String("--ui-dist", { required: false, hidden: true });
|
|
13857
|
+
noWatcher = Option19.Boolean("--no-watcher", false, {
|
|
13808
13858
|
description: "Disable the chokidar-fed scan-and-broadcast loop. Use only for CI / read-only deployments."
|
|
13809
13859
|
});
|
|
13810
13860
|
// `--watcher-debounce-ms` is undocumented sugar for advanced users
|
|
13811
13861
|
// who want to tighten / relax the watcher's batching window without
|
|
13812
13862
|
// editing settings.json. Hidden flag — the Usage block omits it.
|
|
13813
|
-
watcherDebounceMs =
|
|
13863
|
+
watcherDebounceMs = Option19.String("--watcher-debounce-ms", { required: false, hidden: true });
|
|
13814
13864
|
// Long-running daemon — `done in <…>` after a graceful shutdown is
|
|
13815
13865
|
// noise. Mirrors `sm watch`'s opt-out.
|
|
13816
13866
|
emitElapsed = false;
|
|
@@ -13838,7 +13888,7 @@ var ServeCommand = class extends SmCommand {
|
|
|
13838
13888
|
return ExitCode.Error;
|
|
13839
13889
|
}
|
|
13840
13890
|
const dbPath = resolveDbPath({ global: this.global, db: this.db, ...runtimeCtx });
|
|
13841
|
-
if (this.db !== void 0 && !
|
|
13891
|
+
if (this.db !== void 0 && !existsSync18(dbPath)) {
|
|
13842
13892
|
this.context.stderr.write(
|
|
13843
13893
|
tx(SERVE_TEXTS.dbNotFound, { path: sanitizeForTerminal(dbPath) })
|
|
13844
13894
|
);
|
|
@@ -13892,18 +13942,24 @@ var ServeCommand = class extends SmCommand {
|
|
|
13892
13942
|
);
|
|
13893
13943
|
return ExitCode.Error;
|
|
13894
13944
|
}
|
|
13945
|
+
const stderr = this.context.stderr;
|
|
13946
|
+
const isTTY = stderr.isTTY === true;
|
|
13947
|
+
const colorEnabled = resolveColorEnabled({
|
|
13948
|
+
isTTY,
|
|
13949
|
+
noColorFlag: this.noColor,
|
|
13950
|
+
env: process.env
|
|
13951
|
+
});
|
|
13895
13952
|
this.context.stderr.write(
|
|
13896
|
-
|
|
13953
|
+
renderBanner({
|
|
13954
|
+
version: VERSION,
|
|
13897
13955
|
host: sanitizeForTerminal(handle.address.host),
|
|
13898
13956
|
port: handle.address.port,
|
|
13899
13957
|
scope,
|
|
13900
|
-
|
|
13901
|
-
|
|
13902
|
-
|
|
13903
|
-
|
|
13904
|
-
|
|
13905
|
-
host: sanitizeForTerminal(handle.address.host),
|
|
13906
|
-
port: handle.address.port
|
|
13958
|
+
dbPath,
|
|
13959
|
+
cwd: runtimeCtx.cwd,
|
|
13960
|
+
openBrowser: validation.options.open,
|
|
13961
|
+
isTTY,
|
|
13962
|
+
colorEnabled
|
|
13907
13963
|
})
|
|
13908
13964
|
);
|
|
13909
13965
|
if (validation.options.open) {
|
|
@@ -14019,7 +14075,7 @@ function tryOpenBrowser(url, stderr) {
|
|
|
14019
14075
|
}
|
|
14020
14076
|
|
|
14021
14077
|
// cli/commands/show.ts
|
|
14022
|
-
import { Command as
|
|
14078
|
+
import { Command as Command20, Option as Option20 } from "clipanion";
|
|
14023
14079
|
|
|
14024
14080
|
// cli/i18n/show.texts.ts
|
|
14025
14081
|
var SHOW_TEXTS = {
|
|
@@ -14059,7 +14115,7 @@ var SHOW_TEXTS = {
|
|
|
14059
14115
|
// cli/commands/show.ts
|
|
14060
14116
|
var ShowCommand = class extends SmCommand {
|
|
14061
14117
|
static paths = [["show"]];
|
|
14062
|
-
static usage =
|
|
14118
|
+
static usage = Command20.Usage({
|
|
14063
14119
|
category: "Browse",
|
|
14064
14120
|
description: "Node detail: weight, frontmatter, links, issues.",
|
|
14065
14121
|
details: `
|
|
@@ -14075,7 +14131,7 @@ var ShowCommand = class extends SmCommand {
|
|
|
14075
14131
|
["Machine-readable detail", "$0 show .claude/agents/architect.md --json"]
|
|
14076
14132
|
]
|
|
14077
14133
|
});
|
|
14078
|
-
nodePath =
|
|
14134
|
+
nodePath = Option20.String({ required: true });
|
|
14079
14135
|
async run() {
|
|
14080
14136
|
const dbPath = resolveDbPath({ global: this.global, db: this.db, ...defaultRuntimeContext() });
|
|
14081
14137
|
if (!assertDbExists(dbPath, this.context.stderr)) return ExitCode.NotFound;
|
|
@@ -14224,7 +14280,7 @@ function rankConfidenceForGrouping(c) {
|
|
|
14224
14280
|
}
|
|
14225
14281
|
|
|
14226
14282
|
// cli/commands/stubs.ts
|
|
14227
|
-
import { Command as
|
|
14283
|
+
import { Command as Command21, Option as Option21 } from "clipanion";
|
|
14228
14284
|
|
|
14229
14285
|
// cli/i18n/stubs.texts.ts
|
|
14230
14286
|
var STUBS_TEXTS = {
|
|
@@ -14239,9 +14295,9 @@ function notImplemented(cmd, verb) {
|
|
|
14239
14295
|
cmd.context.stderr.write(tx(STUBS_TEXTS.notImplemented, { verb }));
|
|
14240
14296
|
return ExitCode.Error;
|
|
14241
14297
|
}
|
|
14242
|
-
var DoctorCommand = class extends
|
|
14298
|
+
var DoctorCommand = class extends Command21 {
|
|
14243
14299
|
static paths = [["doctor"]];
|
|
14244
|
-
static usage =
|
|
14300
|
+
static usage = Command21.Usage({
|
|
14245
14301
|
category: "Setup",
|
|
14246
14302
|
description: planned("Diagnostic report: DB integrity, pending migrations, orphan rows, plugin status, runner availability.")
|
|
14247
14303
|
});
|
|
@@ -14249,23 +14305,23 @@ var DoctorCommand = class extends Command22 {
|
|
|
14249
14305
|
return notImplemented(this, "doctor");
|
|
14250
14306
|
}
|
|
14251
14307
|
};
|
|
14252
|
-
var FindingsCommand = class extends
|
|
14308
|
+
var FindingsCommand = class extends Command21 {
|
|
14253
14309
|
static paths = [["findings"]];
|
|
14254
|
-
static usage =
|
|
14310
|
+
static usage = Command21.Usage({
|
|
14255
14311
|
category: "Browse",
|
|
14256
14312
|
description: planned("Probabilistic findings: injection, stale summaries, low confidence.")
|
|
14257
14313
|
});
|
|
14258
|
-
kind =
|
|
14259
|
-
since =
|
|
14260
|
-
threshold =
|
|
14261
|
-
json =
|
|
14314
|
+
kind = Option21.String("--kind", { required: false });
|
|
14315
|
+
since = Option21.String("--since", { required: false });
|
|
14316
|
+
threshold = Option21.String("--threshold", { required: false });
|
|
14317
|
+
json = Option21.Boolean("--json", false);
|
|
14262
14318
|
async execute() {
|
|
14263
14319
|
return notImplemented(this, "findings");
|
|
14264
14320
|
}
|
|
14265
14321
|
};
|
|
14266
|
-
var ActionsListCommand = class extends
|
|
14322
|
+
var ActionsListCommand = class extends Command21 {
|
|
14267
14323
|
static paths = [["actions", "list"]];
|
|
14268
|
-
static usage =
|
|
14324
|
+
static usage = Command21.Usage({
|
|
14269
14325
|
category: "Jobs",
|
|
14270
14326
|
description: planned("Registered action types (manifest view).")
|
|
14271
14327
|
});
|
|
@@ -14273,121 +14329,121 @@ var ActionsListCommand = class extends Command22 {
|
|
|
14273
14329
|
return notImplemented(this, "actions list");
|
|
14274
14330
|
}
|
|
14275
14331
|
};
|
|
14276
|
-
var ActionsShowCommand = class extends
|
|
14332
|
+
var ActionsShowCommand = class extends Command21 {
|
|
14277
14333
|
static paths = [["actions", "show"]];
|
|
14278
|
-
static usage =
|
|
14334
|
+
static usage = Command21.Usage({
|
|
14279
14335
|
category: "Jobs",
|
|
14280
14336
|
description: planned("Full action manifest, including preconditions and expected duration.")
|
|
14281
14337
|
});
|
|
14282
|
-
id =
|
|
14338
|
+
id = Option21.String({ required: true });
|
|
14283
14339
|
async execute() {
|
|
14284
14340
|
return notImplemented(this, "actions show");
|
|
14285
14341
|
}
|
|
14286
14342
|
};
|
|
14287
|
-
var JobSubmitCommand = class extends
|
|
14343
|
+
var JobSubmitCommand = class extends Command21 {
|
|
14288
14344
|
static paths = [["job", "submit"]];
|
|
14289
|
-
static usage =
|
|
14345
|
+
static usage = Command21.Usage({
|
|
14290
14346
|
category: "Jobs",
|
|
14291
14347
|
description: planned("Enqueue a single job or fan out to every matching node (--all).")
|
|
14292
14348
|
});
|
|
14293
|
-
action =
|
|
14294
|
-
node =
|
|
14295
|
-
all =
|
|
14296
|
-
run =
|
|
14297
|
-
force =
|
|
14298
|
-
ttl =
|
|
14299
|
-
priority =
|
|
14349
|
+
action = Option21.String({ required: true });
|
|
14350
|
+
node = Option21.String("-n", { required: false });
|
|
14351
|
+
all = Option21.Boolean("--all", false);
|
|
14352
|
+
run = Option21.Boolean("--run", false);
|
|
14353
|
+
force = Option21.Boolean("--force", false);
|
|
14354
|
+
ttl = Option21.String("--ttl", { required: false });
|
|
14355
|
+
priority = Option21.String("--priority", { required: false });
|
|
14300
14356
|
async execute() {
|
|
14301
14357
|
return notImplemented(this, "job submit");
|
|
14302
14358
|
}
|
|
14303
14359
|
};
|
|
14304
|
-
var JobListCommand = class extends
|
|
14360
|
+
var JobListCommand = class extends Command21 {
|
|
14305
14361
|
static paths = [["job", "list"]];
|
|
14306
|
-
static usage =
|
|
14307
|
-
status =
|
|
14308
|
-
action =
|
|
14309
|
-
node =
|
|
14362
|
+
static usage = Command21.Usage({ category: "Jobs", description: planned("List jobs.") });
|
|
14363
|
+
status = Option21.String("--status", { required: false });
|
|
14364
|
+
action = Option21.String("--action", { required: false });
|
|
14365
|
+
node = Option21.String("--node", { required: false });
|
|
14310
14366
|
async execute() {
|
|
14311
14367
|
return notImplemented(this, "job list");
|
|
14312
14368
|
}
|
|
14313
14369
|
};
|
|
14314
|
-
var JobShowCommand = class extends
|
|
14370
|
+
var JobShowCommand = class extends Command21 {
|
|
14315
14371
|
static paths = [["job", "show"]];
|
|
14316
|
-
static usage =
|
|
14317
|
-
id =
|
|
14372
|
+
static usage = Command21.Usage({ category: "Jobs", description: planned("Job detail: state, claim time, TTL, runner, content hash.") });
|
|
14373
|
+
id = Option21.String({ required: true });
|
|
14318
14374
|
async execute() {
|
|
14319
14375
|
return notImplemented(this, "job show");
|
|
14320
14376
|
}
|
|
14321
14377
|
};
|
|
14322
|
-
var JobPreviewCommand = class extends
|
|
14378
|
+
var JobPreviewCommand = class extends Command21 {
|
|
14323
14379
|
static paths = [["job", "preview"]];
|
|
14324
|
-
static usage =
|
|
14325
|
-
id =
|
|
14380
|
+
static usage = Command21.Usage({ category: "Jobs", description: planned("Render the job MD file without executing.") });
|
|
14381
|
+
id = Option21.String({ required: true });
|
|
14326
14382
|
async execute() {
|
|
14327
14383
|
return notImplemented(this, "job preview");
|
|
14328
14384
|
}
|
|
14329
14385
|
};
|
|
14330
|
-
var JobClaimCommand = class extends
|
|
14386
|
+
var JobClaimCommand = class extends Command21 {
|
|
14331
14387
|
static paths = [["job", "claim"]];
|
|
14332
|
-
static usage =
|
|
14388
|
+
static usage = Command21.Usage({
|
|
14333
14389
|
category: "Jobs",
|
|
14334
14390
|
description: planned("Atomic primitive: return next queued job id, mark it running.")
|
|
14335
14391
|
});
|
|
14336
|
-
filter =
|
|
14392
|
+
filter = Option21.String("--filter", { required: false });
|
|
14337
14393
|
async execute() {
|
|
14338
14394
|
return notImplemented(this, "job claim");
|
|
14339
14395
|
}
|
|
14340
14396
|
};
|
|
14341
|
-
var JobRunCommand = class extends
|
|
14397
|
+
var JobRunCommand = class extends Command21 {
|
|
14342
14398
|
static paths = [["job", "run"]];
|
|
14343
|
-
static usage =
|
|
14399
|
+
static usage = Command21.Usage({
|
|
14344
14400
|
category: "Jobs",
|
|
14345
14401
|
description: planned("Full CLI-runner loop: claim + spawn + record.")
|
|
14346
14402
|
});
|
|
14347
|
-
all =
|
|
14348
|
-
max =
|
|
14403
|
+
all = Option21.Boolean("--all", false);
|
|
14404
|
+
max = Option21.String("--max", { required: false });
|
|
14349
14405
|
async execute() {
|
|
14350
14406
|
return notImplemented(this, "job run");
|
|
14351
14407
|
}
|
|
14352
14408
|
};
|
|
14353
|
-
var JobStatusCommand = class extends
|
|
14409
|
+
var JobStatusCommand = class extends Command21 {
|
|
14354
14410
|
static paths = [["job", "status"]];
|
|
14355
|
-
static usage =
|
|
14411
|
+
static usage = Command21.Usage({
|
|
14356
14412
|
category: "Jobs",
|
|
14357
14413
|
description: planned("Counts (per status) or single-job status.")
|
|
14358
14414
|
});
|
|
14359
|
-
id =
|
|
14415
|
+
id = Option21.String({ required: false });
|
|
14360
14416
|
async execute() {
|
|
14361
14417
|
return notImplemented(this, "job status");
|
|
14362
14418
|
}
|
|
14363
14419
|
};
|
|
14364
|
-
var JobCancelCommand = class extends
|
|
14420
|
+
var JobCancelCommand = class extends Command21 {
|
|
14365
14421
|
static paths = [["job", "cancel"]];
|
|
14366
|
-
static usage =
|
|
14422
|
+
static usage = Command21.Usage({
|
|
14367
14423
|
category: "Jobs",
|
|
14368
14424
|
description: planned("Force a running job to failed with reason user-cancelled.")
|
|
14369
14425
|
});
|
|
14370
|
-
id =
|
|
14371
|
-
all =
|
|
14426
|
+
id = Option21.String({ required: false });
|
|
14427
|
+
all = Option21.Boolean("--all", false);
|
|
14372
14428
|
async execute() {
|
|
14373
14429
|
return notImplemented(this, "job cancel");
|
|
14374
14430
|
}
|
|
14375
14431
|
};
|
|
14376
|
-
var RecordCommand = class extends
|
|
14432
|
+
var RecordCommand = class extends Command21 {
|
|
14377
14433
|
static paths = [["record"]];
|
|
14378
|
-
static usage =
|
|
14434
|
+
static usage = Command21.Usage({
|
|
14379
14435
|
category: "Jobs",
|
|
14380
14436
|
description: planned("Close a running job with success or failure. Nonce is the sole credential.")
|
|
14381
14437
|
});
|
|
14382
|
-
id =
|
|
14383
|
-
nonce =
|
|
14384
|
-
status =
|
|
14385
|
-
report =
|
|
14386
|
-
tokensIn =
|
|
14387
|
-
tokensOut =
|
|
14388
|
-
durationMs =
|
|
14389
|
-
model =
|
|
14390
|
-
error =
|
|
14438
|
+
id = Option21.String("--id", { required: true });
|
|
14439
|
+
nonce = Option21.String("--nonce", { required: true });
|
|
14440
|
+
status = Option21.String("--status", { required: true });
|
|
14441
|
+
report = Option21.String("--report", { required: false });
|
|
14442
|
+
tokensIn = Option21.String("--tokens-in", { required: false });
|
|
14443
|
+
tokensOut = Option21.String("--tokens-out", { required: false });
|
|
14444
|
+
durationMs = Option21.String("--duration-ms", { required: false });
|
|
14445
|
+
model = Option21.String("--model", { required: false });
|
|
14446
|
+
error = Option21.String("--error", { required: false });
|
|
14391
14447
|
async execute() {
|
|
14392
14448
|
return notImplemented(this, "record");
|
|
14393
14449
|
}
|
|
@@ -14408,6 +14464,99 @@ var STUB_COMMANDS = [
|
|
|
14408
14464
|
RecordCommand
|
|
14409
14465
|
];
|
|
14410
14466
|
|
|
14467
|
+
// cli/commands/tutorial.ts
|
|
14468
|
+
import { existsSync as existsSync19, readFileSync as readFileSync12 } from "fs";
|
|
14469
|
+
import { writeFile as writeFile2 } from "fs/promises";
|
|
14470
|
+
import { dirname as dirname10, join as join15, resolve as resolve20 } from "path";
|
|
14471
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
14472
|
+
import { Command as Command22, Option as Option22 } from "clipanion";
|
|
14473
|
+
|
|
14474
|
+
// cli/i18n/tutorial.texts.ts
|
|
14475
|
+
var TUTORIAL_TEXTS = {
|
|
14476
|
+
// Success — written to stdout after `<cwd>/sm-tutorial.md` is created.
|
|
14477
|
+
written: 'Done. sm-tutorial.md created at {{cwd}}. Open Claude Code here and tell it "run @sm-tutorial.md" to start the interactive tutorial.\n',
|
|
14478
|
+
// Refusal — `sm-tutorial.md` already exists and `--force` was not set.
|
|
14479
|
+
// Goes to stderr, exit code 2 (operational error per spec § Exit codes).
|
|
14480
|
+
alreadyExists: "sm tutorial: sm-tutorial.md already exists at {{cwd}}. Pass `--force` to overwrite.\n",
|
|
14481
|
+
// I/O failure on write or on reading the bundled SKILL source.
|
|
14482
|
+
writeFailed: "sm tutorial: failed to write sm-tutorial.md: {{message}}\n",
|
|
14483
|
+
sourceMissing: "sm tutorial: could not read the bundled tutorial (SKILL.md) from the install. Reinstall @skill-map/cli or report the bug.\n"
|
|
14484
|
+
};
|
|
14485
|
+
|
|
14486
|
+
// cli/commands/tutorial.ts
|
|
14487
|
+
var SM_TUTORIAL_FILENAME = "sm-tutorial.md";
|
|
14488
|
+
var TutorialCommand = class extends SmCommand {
|
|
14489
|
+
static paths = [["tutorial"]];
|
|
14490
|
+
static usage = Command22.Usage({
|
|
14491
|
+
category: "Setup",
|
|
14492
|
+
description: "Materialize the interactive tester tutorial (sm-tutorial.md) in the current directory.",
|
|
14493
|
+
details: `
|
|
14494
|
+
Drops the canonical SKILL.md content as ./sm-tutorial.md so a tester
|
|
14495
|
+
can open Claude Code in the cwd and load the file as a skill by
|
|
14496
|
+
typing "ejecut\xE1 @sm-tutorial.md". Top-level only \u2014 no subdirectory
|
|
14497
|
+
is created.
|
|
14498
|
+
|
|
14499
|
+
Does NOT require an initialized .skill-map/ project. Refuses to
|
|
14500
|
+
overwrite an existing sm-tutorial.md unless --force is passed.
|
|
14501
|
+
`,
|
|
14502
|
+
examples: [
|
|
14503
|
+
["Materialize the tutorial in the cwd", "$0 tutorial"],
|
|
14504
|
+
["Overwrite an existing sm-tutorial.md", "$0 tutorial --force"]
|
|
14505
|
+
]
|
|
14506
|
+
});
|
|
14507
|
+
force = Option22.Boolean("--force", false, {
|
|
14508
|
+
description: "Overwrite an existing sm-tutorial.md without prompting."
|
|
14509
|
+
});
|
|
14510
|
+
async run() {
|
|
14511
|
+
const ctx = defaultRuntimeContext();
|
|
14512
|
+
const target = join15(ctx.cwd, SM_TUTORIAL_FILENAME);
|
|
14513
|
+
if (await pathExists(target) && !this.force) {
|
|
14514
|
+
this.context.stderr.write(tx(TUTORIAL_TEXTS.alreadyExists, { cwd: ctx.cwd }));
|
|
14515
|
+
return ExitCode.Error;
|
|
14516
|
+
}
|
|
14517
|
+
let body;
|
|
14518
|
+
try {
|
|
14519
|
+
body = loadBundledTutorialText();
|
|
14520
|
+
} catch {
|
|
14521
|
+
this.context.stderr.write(TUTORIAL_TEXTS.sourceMissing);
|
|
14522
|
+
return ExitCode.Error;
|
|
14523
|
+
}
|
|
14524
|
+
try {
|
|
14525
|
+
await writeFile2(target, body);
|
|
14526
|
+
} catch (err) {
|
|
14527
|
+
this.context.stderr.write(
|
|
14528
|
+
tx(TUTORIAL_TEXTS.writeFailed, { message: formatErrorMessage(err) })
|
|
14529
|
+
);
|
|
14530
|
+
return ExitCode.Error;
|
|
14531
|
+
}
|
|
14532
|
+
this.context.stdout.write(tx(TUTORIAL_TEXTS.written, { cwd: ctx.cwd }));
|
|
14533
|
+
return ExitCode.Ok;
|
|
14534
|
+
}
|
|
14535
|
+
};
|
|
14536
|
+
var cachedTutorial = null;
|
|
14537
|
+
function loadBundledTutorialText() {
|
|
14538
|
+
if (cachedTutorial !== null) return cachedTutorial;
|
|
14539
|
+
cachedTutorial = readTutorialFromDisk();
|
|
14540
|
+
return cachedTutorial;
|
|
14541
|
+
}
|
|
14542
|
+
function readTutorialFromDisk() {
|
|
14543
|
+
const here = dirname10(fileURLToPath6(import.meta.url));
|
|
14544
|
+
const candidates = [
|
|
14545
|
+
// dev: src/cli/commands/ → repo-root .claude/skills/sm-tutorial/SKILL.md
|
|
14546
|
+
resolve20(here, "../../../.claude/skills/sm-tutorial/SKILL.md"),
|
|
14547
|
+
// bundled: dist/cli.js → dist/cli/tutorial/sm-tutorial.md (sibling)
|
|
14548
|
+
resolve20(here, "cli/tutorial/sm-tutorial.md"),
|
|
14549
|
+
// bundled fallback: any-depth → cli/tutorial/sm-tutorial.md
|
|
14550
|
+
resolve20(here, "../cli/tutorial/sm-tutorial.md")
|
|
14551
|
+
];
|
|
14552
|
+
for (const candidate of candidates) {
|
|
14553
|
+
if (existsSync19(candidate)) {
|
|
14554
|
+
return readFileSync12(candidate, "utf8");
|
|
14555
|
+
}
|
|
14556
|
+
}
|
|
14557
|
+
throw new Error(`SKILL.md not found in any candidate location (last tried: ${candidates[candidates.length - 1]})`);
|
|
14558
|
+
}
|
|
14559
|
+
|
|
14411
14560
|
// cli/commands/version.ts
|
|
14412
14561
|
import { Command as Command23 } from "clipanion";
|
|
14413
14562
|
|
|
@@ -14491,7 +14640,7 @@ cli.register(Builtins.VersionCommand);
|
|
|
14491
14640
|
cli.register(RootHelpCommand);
|
|
14492
14641
|
cli.register(HelpCommand);
|
|
14493
14642
|
cli.register(InitCommand);
|
|
14494
|
-
cli.register(
|
|
14643
|
+
cli.register(TutorialCommand);
|
|
14495
14644
|
cli.register(ScanCommand);
|
|
14496
14645
|
cli.register(ScanCompareCommand);
|
|
14497
14646
|
cli.register(ServeCommand);
|