@skill-map/cli 0.63.0 → 0.64.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/example/.claude/agents/content-editor.md +22 -0
- package/dist/cli/example/.claude/agents/content-editor.sm +17 -0
- package/dist/cli/example/.claude/commands/init.md +9 -0
- package/dist/cli/example/.claude/commands/publish.md +15 -0
- package/dist/cli/example/.claude/commands/publish.sm +9 -0
- package/dist/cli/example/.claude/skills/check-links/SKILL.md +16 -0
- package/dist/cli/example/.claude/skills/check-links/SKILL.sm +9 -0
- package/dist/cli/example/.skillmapignore +30 -0
- package/dist/cli/example/AGENTS.md +10 -0
- package/dist/cli/example/AGENTS.sm +8 -0
- package/dist/cli/example/docs/DEPLOY.md +11 -0
- package/dist/cli/example/docs/STYLE.md +20 -0
- package/dist/cli/example/package.json +6 -0
- package/dist/cli/example/public/index.html +5 -0
- package/dist/cli/example/server.js +11 -0
- package/dist/cli.js +889 -644
- package/dist/index.js +3 -3
- package/dist/kernel/index.js +3 -3
- package/dist/ui/chunk-UKS6NPIF.js +3 -0
- package/dist/ui/index.html +1 -1
- package/dist/ui/{main-BCFZVCQW.js → main-DCL7WTKB.js} +4 -4
- package/package.json +2 -2
- package/dist/ui/chunk-PNEFOABG.js +0 -3
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// cli/entry.ts
|
|
2
2
|
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
4
|
-
import { existsSync as
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ef7d5528-7273-5d01-b514-635331ee2072")}catch(e){}}();
|
|
4
|
+
import { existsSync as existsSync34 } from "fs";
|
|
5
5
|
import { Builtins, Cli as Cli2 } from "clipanion";
|
|
6
6
|
|
|
7
7
|
// kernel/adapters/in-memory-progress.ts
|
|
@@ -250,7 +250,7 @@ function bucketByKind(kind, instance, bag) {
|
|
|
250
250
|
// package.json
|
|
251
251
|
var package_default = {
|
|
252
252
|
name: "@skill-map/cli",
|
|
253
|
-
version: "0.
|
|
253
|
+
version: "0.64.1",
|
|
254
254
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
255
255
|
license: "MIT",
|
|
256
256
|
type: "module",
|
|
@@ -4560,6 +4560,25 @@ var ENTRY_TEXTS = {
|
|
|
4560
4560
|
*/
|
|
4561
4561
|
bareNoProject: "{{glyph}} No skill-map project found in {{cwd}}.\n {{hint}}\n",
|
|
4562
4562
|
bareNoProjectHint: "Run `sm init` to bootstrap one, or `sm --help` to see all commands.",
|
|
4563
|
+
/**
|
|
4564
|
+
* Hint variant for a bare `sm` in an EMPTY cwd when the interactive
|
|
4565
|
+
* menu cannot run (non-TTY stdin) or the operator gave no valid pick.
|
|
4566
|
+
* Points at the two getting-started verbs instead of `sm init` (a
|
|
4567
|
+
* brand-new user in an empty folder wants to try the tool, not
|
|
4568
|
+
* bootstrap an empty project).
|
|
4569
|
+
*/
|
|
4570
|
+
bareEmptyHint: "Run `sm tutorial` for a guided walkthrough, or `sm example` to drop a project to explore.",
|
|
4571
|
+
/**
|
|
4572
|
+
* Getting-started menu shown on bare `sm` in an empty folder on an
|
|
4573
|
+
* interactive terminal. Header uses a yellow `?` glyph; two numbered
|
|
4574
|
+
* options dispatch to `sm tutorial` / `sm example`; the input line
|
|
4575
|
+
* accepts a number, a verb name, or an empty answer (which takes the
|
|
4576
|
+
* default, option 1, the tutorial).
|
|
4577
|
+
*/
|
|
4578
|
+
emptyMenuHeader: "{{glyph}} This folder is empty. How would you like to start?",
|
|
4579
|
+
emptyMenuOptionTutorial: " 1) Run the guided tutorial (sm tutorial) (default)",
|
|
4580
|
+
emptyMenuOptionExample: " 2) Copy an example project to try (sm example)",
|
|
4581
|
+
emptyMenuInput: " Enter the number [default 1]: ",
|
|
4563
4582
|
parseErrorHeadline: "sm: {{message}}",
|
|
4564
4583
|
parseErrorUnknownOption: "unknown option '{{name}}'",
|
|
4565
4584
|
parseErrorUnknownOptionForVerb: "{{verb}}: unknown option '{{name}}'",
|
|
@@ -4792,6 +4811,64 @@ function requireDbOrExit(path, stderr) {
|
|
|
4792
4811
|
return ExitCode.NotFound;
|
|
4793
4812
|
}
|
|
4794
4813
|
|
|
4814
|
+
// cli/util/empty-cwd.ts
|
|
4815
|
+
import { readdirSync } from "fs";
|
|
4816
|
+
function isDirEmpty(dir) {
|
|
4817
|
+
return readdirSync(dir).length === 0;
|
|
4818
|
+
}
|
|
4819
|
+
function listCwdEntries(dir) {
|
|
4820
|
+
const entries = readdirSync(dir).sort();
|
|
4821
|
+
const shown = entries.slice(0, 5);
|
|
4822
|
+
const more = entries.length > shown.length ? ", ..." : "";
|
|
4823
|
+
return shown.join(", ") + more;
|
|
4824
|
+
}
|
|
4825
|
+
function displayCwd(cwd) {
|
|
4826
|
+
const segments = cwd.split("/").filter((s) => s.length > 0);
|
|
4827
|
+
if (segments.length === 0) return "./";
|
|
4828
|
+
return `./${segments[segments.length - 1]}/`;
|
|
4829
|
+
}
|
|
4830
|
+
|
|
4831
|
+
// cli/util/empty-folder-prompt.ts
|
|
4832
|
+
import { createInterface } from "readline";
|
|
4833
|
+
async function decideBareNoArgs(state, prompt) {
|
|
4834
|
+
if (state.hasDb) return { kind: "route", argv: ["serve"] };
|
|
4835
|
+
if (state.isTty && state.isEmptyDir) {
|
|
4836
|
+
const choice = await prompt();
|
|
4837
|
+
if (choice !== null) return { kind: "route", argv: [choice] };
|
|
4838
|
+
}
|
|
4839
|
+
return { kind: "hint" };
|
|
4840
|
+
}
|
|
4841
|
+
function classifyEmptyFolderAnswer(trimmed) {
|
|
4842
|
+
if (trimmed === "") return "tutorial";
|
|
4843
|
+
if (trimmed === "1") return "tutorial";
|
|
4844
|
+
if (trimmed === "2") return "example";
|
|
4845
|
+
const lower = trimmed.toLowerCase();
|
|
4846
|
+
if (lower === "tutorial") return "tutorial";
|
|
4847
|
+
if (lower === "example") return "example";
|
|
4848
|
+
return null;
|
|
4849
|
+
}
|
|
4850
|
+
async function promptEmptyFolderChoice(stdin, stderr, ansi) {
|
|
4851
|
+
const menu = [
|
|
4852
|
+
tx(ENTRY_TEXTS.emptyMenuHeader, { glyph: ansi.yellow("?") }),
|
|
4853
|
+
ENTRY_TEXTS.emptyMenuOptionTutorial,
|
|
4854
|
+
ENTRY_TEXTS.emptyMenuOptionExample
|
|
4855
|
+
].join("\n");
|
|
4856
|
+
stderr.write(menu + "\n");
|
|
4857
|
+
const rl = createInterface({ input: stdin, output: stderr });
|
|
4858
|
+
try {
|
|
4859
|
+
for (let attempt = 0; attempt < 5; attempt += 1) {
|
|
4860
|
+
const answer = await new Promise(
|
|
4861
|
+
(resolveP) => rl.question(ENTRY_TEXTS.emptyMenuInput, resolveP)
|
|
4862
|
+
);
|
|
4863
|
+
const choice = classifyEmptyFolderAnswer(answer.trim());
|
|
4864
|
+
if (choice !== null) return choice;
|
|
4865
|
+
}
|
|
4866
|
+
return null;
|
|
4867
|
+
} finally {
|
|
4868
|
+
rl.close();
|
|
4869
|
+
}
|
|
4870
|
+
}
|
|
4871
|
+
|
|
4795
4872
|
// cli/util/edit-distance.ts
|
|
4796
4873
|
function editDistance(a, b, max) {
|
|
4797
4874
|
if (a === b) return 0;
|
|
@@ -4967,7 +5044,7 @@ function defaultRuntimeContext() {
|
|
|
4967
5044
|
}
|
|
4968
5045
|
|
|
4969
5046
|
// cli/telemetry/first-run-prompt.ts
|
|
4970
|
-
import { createInterface } from "readline/promises";
|
|
5047
|
+
import { createInterface as createInterface2 } from "readline/promises";
|
|
4971
5048
|
|
|
4972
5049
|
// cli/i18n/telemetry.texts.ts
|
|
4973
5050
|
var TELEMETRY_PROMPT_TEXTS = {
|
|
@@ -5270,7 +5347,7 @@ async function runConsentPrompt(stdin, stdout, nowMs) {
|
|
|
5270
5347
|
const rendered = renderConsent(
|
|
5271
5348
|
ansiFor({ isTTY: stdout.isTTY === true, noColorFlag: false })
|
|
5272
5349
|
);
|
|
5273
|
-
const rl =
|
|
5350
|
+
const rl = createInterface2({ input: stdin, output: stdout });
|
|
5274
5351
|
try {
|
|
5275
5352
|
const consented = await readConsentDecision(rl, stdout, rendered);
|
|
5276
5353
|
writeUserSettings({
|
|
@@ -6000,13 +6077,13 @@ var CONSENT_TEXTS = {
|
|
|
6000
6077
|
};
|
|
6001
6078
|
|
|
6002
6079
|
// cli/util/confirm.ts
|
|
6003
|
-
import { createInterface as
|
|
6080
|
+
import { createInterface as createInterface3 } from "readline";
|
|
6004
6081
|
var YES_PATTERN = new RegExp(UTIL_TEXTS.confirmYesPatternSource, "i");
|
|
6005
6082
|
var NO_PATTERN = new RegExp(UTIL_TEXTS.confirmNoPatternSource, "i");
|
|
6006
6083
|
async function confirm(question, streams, opts) {
|
|
6007
6084
|
const defaultAnswer = opts?.defaultAnswer ?? "no";
|
|
6008
6085
|
const suffix = defaultAnswer === "yes" ? UTIL_TEXTS.confirmPromptSuffixDefaultYes : UTIL_TEXTS.confirmPromptSuffix;
|
|
6009
|
-
const rl =
|
|
6086
|
+
const rl = createInterface3({ input: streams.stdin, output: streams.stderr });
|
|
6010
6087
|
try {
|
|
6011
6088
|
const answer = await new Promise(
|
|
6012
6089
|
(resolveP) => rl.question(`${question}${suffix}`, resolveP)
|
|
@@ -6360,7 +6437,7 @@ var AsyncMutex = class {
|
|
|
6360
6437
|
this.#locked = true;
|
|
6361
6438
|
return;
|
|
6362
6439
|
}
|
|
6363
|
-
await new Promise((
|
|
6440
|
+
await new Promise((resolve44) => this.#waiters.push(resolve44));
|
|
6364
6441
|
this.#locked = true;
|
|
6365
6442
|
}
|
|
6366
6443
|
unlock() {
|
|
@@ -6807,7 +6884,7 @@ async function selectReferencedJobFilePaths(db) {
|
|
|
6807
6884
|
}
|
|
6808
6885
|
|
|
6809
6886
|
// kernel/adapters/sqlite/migrations.ts
|
|
6810
|
-
import { copyFileSync, existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync8, readdirSync } from "fs";
|
|
6887
|
+
import { copyFileSync, existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync8, readdirSync as readdirSync2 } from "fs";
|
|
6811
6888
|
import { dirname as dirname7, join as join5, resolve as resolve10 } from "path";
|
|
6812
6889
|
import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
|
|
6813
6890
|
import { fileURLToPath } from "url";
|
|
@@ -6829,7 +6906,7 @@ function defaultMigrationsDir() {
|
|
|
6829
6906
|
}
|
|
6830
6907
|
function discoverMigrations(dir = defaultMigrationsDir()) {
|
|
6831
6908
|
if (!existsSync8(dir)) return [];
|
|
6832
|
-
const files =
|
|
6909
|
+
const files = readdirSync2(dir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => e.name).filter((name) => FILE_RE.test(name)).sort();
|
|
6833
6910
|
const out = [];
|
|
6834
6911
|
for (const name of files) {
|
|
6835
6912
|
const match = FILE_RE.exec(name);
|
|
@@ -6944,7 +7021,7 @@ function writeBackup(dbPath, destPath) {
|
|
|
6944
7021
|
}
|
|
6945
7022
|
|
|
6946
7023
|
// kernel/adapters/sqlite/plugin-migrations.ts
|
|
6947
|
-
import { existsSync as existsSync9, readFileSync as readFileSync9, readdirSync as
|
|
7024
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9, readdirSync as readdirSync3 } from "fs";
|
|
6948
7025
|
import { join as join6 } from "path";
|
|
6949
7026
|
|
|
6950
7027
|
// kernel/adapters/sqlite/plugin-migrations-validator.ts
|
|
@@ -7264,7 +7341,7 @@ function resolvePluginMigrationsDir(plugin) {
|
|
|
7264
7341
|
function discoverPluginMigrations(plugin) {
|
|
7265
7342
|
const dir = resolvePluginMigrationsDir(plugin);
|
|
7266
7343
|
if (!dir) return [];
|
|
7267
|
-
const files =
|
|
7344
|
+
const files = readdirSync3(dir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => e.name).filter((name) => FILE_RE2.test(name)).sort();
|
|
7268
7345
|
const out = [];
|
|
7269
7346
|
for (const name of files) {
|
|
7270
7347
|
const match = FILE_RE2.exec(name);
|
|
@@ -9863,7 +9940,7 @@ var PLUGIN_LOADER_TEXTS = {
|
|
|
9863
9940
|
|
|
9864
9941
|
// kernel/adapters/plugin-loader/index.ts
|
|
9865
9942
|
import { createRequire as createRequire5 } from "module";
|
|
9866
|
-
import { existsSync as existsSync13, readFileSync as readFileSync13, readdirSync as
|
|
9943
|
+
import { existsSync as existsSync13, readFileSync as readFileSync13, readdirSync as readdirSync5, statSync as statSync2 } from "fs";
|
|
9867
9944
|
import { join as join8, resolve as resolve16 } from "path";
|
|
9868
9945
|
import { pathToFileURL } from "url";
|
|
9869
9946
|
import semver from "semver";
|
|
@@ -10206,9 +10283,9 @@ function providerKindFailure(opts, status, fileName, errDescription) {
|
|
|
10206
10283
|
}
|
|
10207
10284
|
};
|
|
10208
10285
|
}
|
|
10209
|
-
function isDirectorySafe(path,
|
|
10286
|
+
function isDirectorySafe(path, statSync13) {
|
|
10210
10287
|
try {
|
|
10211
|
-
return
|
|
10288
|
+
return statSync13(path).isDirectory();
|
|
10212
10289
|
} catch {
|
|
10213
10290
|
return false;
|
|
10214
10291
|
}
|
|
@@ -10318,7 +10395,7 @@ var PluginLoader = class {
|
|
|
10318
10395
|
const out = [];
|
|
10319
10396
|
for (const root of this.#options.searchPaths) {
|
|
10320
10397
|
if (!existsSync13(root)) continue;
|
|
10321
|
-
for (const entry of
|
|
10398
|
+
for (const entry of readdirSync5(root, { withFileTypes: true })) {
|
|
10322
10399
|
if (!entry.isDirectory()) continue;
|
|
10323
10400
|
const candidate = join8(root, entry.name);
|
|
10324
10401
|
if (existsSync13(join8(candidate, "plugin.json"))) {
|
|
@@ -10689,7 +10766,7 @@ function collectKindEntries(pluginPath, kindDir, out) {
|
|
|
10689
10766
|
if (!existsSync13(kindAbs)) return;
|
|
10690
10767
|
let entries;
|
|
10691
10768
|
try {
|
|
10692
|
-
entries =
|
|
10769
|
+
entries = readdirSync5(kindAbs);
|
|
10693
10770
|
} catch {
|
|
10694
10771
|
return;
|
|
10695
10772
|
}
|
|
@@ -12593,7 +12670,7 @@ import { Command as Command5, Option as Option5 } from "clipanion";
|
|
|
12593
12670
|
|
|
12594
12671
|
// conformance/index.ts
|
|
12595
12672
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
12596
|
-
import { cpSync, existsSync as existsSync17, mkdtempSync, readdirSync as
|
|
12673
|
+
import { cpSync, existsSync as existsSync17, mkdtempSync, readdirSync as readdirSync6, readFileSync as readFileSync15, rmSync, statSync as statSync3 } from "fs";
|
|
12597
12674
|
import { tmpdir } from "os";
|
|
12598
12675
|
import { isAbsolute as isAbsolute6, join as join11, relative as relative3, resolve as resolve20 } from "path";
|
|
12599
12676
|
|
|
@@ -12749,7 +12826,7 @@ function runPriorScansSetup(c, options, scope, fixturesRoot, setupEnv) {
|
|
|
12749
12826
|
}
|
|
12750
12827
|
function replaceFixture(scope, fixturesRoot, fixture) {
|
|
12751
12828
|
assertContained2(fixturesRoot, fixture, "fixture");
|
|
12752
|
-
for (const entry of
|
|
12829
|
+
for (const entry of readdirSync6(scope)) {
|
|
12753
12830
|
if (entry === KERNEL_SKILL_MAP_DIR) continue;
|
|
12754
12831
|
rmSync(join11(scope, entry), { recursive: true, force: true });
|
|
12755
12832
|
}
|
|
@@ -12986,7 +13063,7 @@ var CONFORMANCE_TEXTS = {
|
|
|
12986
13063
|
};
|
|
12987
13064
|
|
|
12988
13065
|
// cli/util/conformance-scopes.ts
|
|
12989
|
-
import { existsSync as existsSync18, readdirSync as
|
|
13066
|
+
import { existsSync as existsSync18, readdirSync as readdirSync7, statSync as statSync4 } from "fs";
|
|
12990
13067
|
import { dirname as dirname11, resolve as resolve21 } from "path";
|
|
12991
13068
|
import { createRequire as createRequire6 } from "module";
|
|
12992
13069
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -13027,7 +13104,7 @@ function collectProviderScopes(specRoot) {
|
|
|
13027
13104
|
}
|
|
13028
13105
|
const pluginsRoot = resolve21(workspaceRoot, "plugins");
|
|
13029
13106
|
if (!existsSync18(pluginsRoot)) return out;
|
|
13030
|
-
for (const pluginEntry of
|
|
13107
|
+
for (const pluginEntry of readdirSync7(pluginsRoot)) {
|
|
13031
13108
|
const pluginDir = resolve21(pluginsRoot, pluginEntry);
|
|
13032
13109
|
if (!isDir(pluginDir)) continue;
|
|
13033
13110
|
const providersRoot = resolve21(pluginDir, "providers");
|
|
@@ -13044,7 +13121,7 @@ function isDir(path) {
|
|
|
13044
13121
|
}
|
|
13045
13122
|
}
|
|
13046
13123
|
function collectPluginProviderScopes(providersRoot, specRoot, out) {
|
|
13047
|
-
for (const entry of
|
|
13124
|
+
for (const entry of readdirSync7(providersRoot)) {
|
|
13048
13125
|
const providerDir = resolve21(providersRoot, entry);
|
|
13049
13126
|
if (!isDir(providerDir)) continue;
|
|
13050
13127
|
const conformanceDir = resolve21(providerDir, "conformance");
|
|
@@ -13090,7 +13167,7 @@ function selectConformanceScopes(scope) {
|
|
|
13090
13167
|
}
|
|
13091
13168
|
function listCaseFiles(scope) {
|
|
13092
13169
|
if (!existsSync18(scope.casesDir)) return [];
|
|
13093
|
-
return
|
|
13170
|
+
return readdirSync7(scope.casesDir).filter((entry) => entry.endsWith(".json")).sort().map((entry) => resolve21(scope.casesDir, entry));
|
|
13094
13171
|
}
|
|
13095
13172
|
|
|
13096
13173
|
// cli/commands/conformance.ts
|
|
@@ -14219,123 +14296,443 @@ var DB_COMMANDS = [
|
|
|
14219
14296
|
DbMigrateCommand
|
|
14220
14297
|
];
|
|
14221
14298
|
|
|
14222
|
-
// cli/commands/
|
|
14299
|
+
// cli/commands/example.ts
|
|
14300
|
+
import { cpSync as cpSync2, existsSync as existsSync21, statSync as statSync5 } from "fs";
|
|
14301
|
+
import { dirname as dirname16, relative as relative5, resolve as resolve26 } from "path";
|
|
14302
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
14223
14303
|
import { Command as Command13, Option as Option12 } from "clipanion";
|
|
14224
14304
|
|
|
14225
|
-
//
|
|
14226
|
-
var
|
|
14227
|
-
|
|
14228
|
-
|
|
14229
|
-
|
|
14230
|
-
|
|
14231
|
-
}
|
|
14305
|
+
// cli/i18n/example.texts.ts
|
|
14306
|
+
var EXAMPLE_TEXTS = {
|
|
14307
|
+
// Success, written to stdout after the example project is created in
|
|
14308
|
+
// the cwd. The project ships unscanned (no `.skill-map/`), so the
|
|
14309
|
+
// next-steps block points the user at `sm scan` (provisions the
|
|
14310
|
+
// project and builds the graph) then `sm serve` (opens the map).
|
|
14311
|
+
written: " {{glyph}} Example project created in {{cwd}}\n\n A small wired portfolio is ready to explore: a handbook\n (AGENTS.md) that mentions a content-editor agent and invokes a\n publish command, a check-links skill the command calls, and the\n docs they reference. Next:\n\n {{scanGlyph}} sm scan build the graph from these files\n {{serveGlyph}} sm serve open the interactive map in the browser\n",
|
|
14312
|
+
writtenScanGlyph: "1)",
|
|
14313
|
+
writtenServeGlyph: "2)",
|
|
14314
|
+
// Refusal, the cwd is not empty and `--force` was not set. Goes to
|
|
14315
|
+
// stderr, exit code 2 (operational error per spec § Exit codes). The
|
|
14316
|
+
// example writes a self-contained project into the cwd, so it needs an
|
|
14317
|
+
// empty directory; the hint spells the two ways forward. Mirrors the
|
|
14318
|
+
// error shape: glyph + headline + dim hint.
|
|
14319
|
+
notEmpty: "{{glyph}} sm example: the current directory is not empty (found {{entries}})\n {{hint}}\n",
|
|
14320
|
+
notEmptyHint: "sm example writes a self-contained project; run it in a fresh empty directory, or pass `--force` to use this one anyway (colliding files are overwritten).",
|
|
14321
|
+
// Unexpected positional argument. The verb takes none. Goes to
|
|
14322
|
+
// stderr, exit code 2. Mirrors the error shape: glyph + headline +
|
|
14323
|
+
// dim hint.
|
|
14324
|
+
unexpectedArg: "{{glyph}} sm example: unexpected argument '{{arg}}'\n {{hint}}\n",
|
|
14325
|
+
unexpectedArgHint: "sm example takes no positional argument. Run `sm example` in an empty directory.",
|
|
14326
|
+
// I/O failure on write or on reading the bundled example payload.
|
|
14327
|
+
writeFailed: "{{glyph}} sm example: failed to write the example project: {{message}}\n",
|
|
14328
|
+
sourceMissing: "{{glyph}} sm example: could not read the bundled example payload from the install.\n {{hint}}\n",
|
|
14329
|
+
sourceMissingHint: "Reinstall @skill-map/cli or report the bug."
|
|
14232
14330
|
};
|
|
14233
|
-
|
|
14234
|
-
|
|
14235
|
-
|
|
14236
|
-
|
|
14237
|
-
|
|
14238
|
-
|
|
14239
|
-
|
|
14240
|
-
|
|
14241
|
-
|
|
14242
|
-
|
|
14243
|
-
|
|
14244
|
-
|
|
14245
|
-
|
|
14246
|
-
|
|
14247
|
-
|
|
14248
|
-
|
|
14249
|
-
|
|
14250
|
-
|
|
14251
|
-
|
|
14252
|
-
|
|
14253
|
-
|
|
14254
|
-
|
|
14255
|
-
|
|
14256
|
-
|
|
14257
|
-
|
|
14258
|
-
|
|
14259
|
-
|
|
14260
|
-
|
|
14261
|
-
|
|
14262
|
-
|
|
14263
|
-
|
|
14264
|
-
|
|
14265
|
-
|
|
14266
|
-
|
|
14267
|
-
|
|
14268
|
-
|
|
14269
|
-
tx(QUERY_TEXTS.exportQueryUnknownKey, { key })
|
|
14270
|
-
);
|
|
14271
|
-
}
|
|
14331
|
+
|
|
14332
|
+
// cli/util/serve-banner.ts
|
|
14333
|
+
import { relative as relative4, isAbsolute as isAbsolute7 } from "path";
|
|
14334
|
+
var ESC2 = {
|
|
14335
|
+
reset: "\x1B[0m",
|
|
14336
|
+
bold: "\x1B[1m",
|
|
14337
|
+
dim: "\x1B[2m",
|
|
14338
|
+
underline: "\x1B[4m",
|
|
14339
|
+
/** 256-color violet (xterm 141). */
|
|
14340
|
+
violet: "\x1B[38;5;141m",
|
|
14341
|
+
/** 256-color green (xterm 42). */
|
|
14342
|
+
green: "\x1B[38;5;42m",
|
|
14343
|
+
/** 256-color yellow (xterm 214), matches `cli/util/ansi.ts:yellow`. */
|
|
14344
|
+
yellow: "\x1B[38;5;214m"
|
|
14345
|
+
};
|
|
14346
|
+
var LOGO_LINES = [
|
|
14347
|
+
" ____ _ _ _ _ __ __ ",
|
|
14348
|
+
" / ___|| | _(_) | | | \\/ | __ _ _ __ ",
|
|
14349
|
+
" \\___ \\| |/ / | | | | |\\/| |/ _` | '_ \\ ",
|
|
14350
|
+
" ___) | <| | | | | | | | (_| | |_) |",
|
|
14351
|
+
" |____/|_|\\_\\_|_|_| |_| |_|\\__,_| .__/ ",
|
|
14352
|
+
" |_| "
|
|
14353
|
+
];
|
|
14354
|
+
var LOGO_WIDTH = 40;
|
|
14355
|
+
function renderBanner(input) {
|
|
14356
|
+
const url = `http://${input.host}:${input.port}`;
|
|
14357
|
+
const dbDisplay = formatDbPath(input.dbPath, input.cwd);
|
|
14358
|
+
const browserLine = input.openBrowser ? "Opening browser\u2026 Press Ctrl+C to stop." : `Visit ${url}/ in your browser. Press Ctrl+C to stop.`;
|
|
14359
|
+
if (!input.isTTY) {
|
|
14360
|
+
return renderFlat({
|
|
14361
|
+
host: input.host,
|
|
14362
|
+
port: input.port,
|
|
14363
|
+
dbPath: input.dbPath,
|
|
14364
|
+
openBrowser: input.openBrowser,
|
|
14365
|
+
dev: input.dev === true
|
|
14366
|
+
});
|
|
14272
14367
|
}
|
|
14273
|
-
return
|
|
14368
|
+
return renderFiglet({
|
|
14369
|
+
version: input.version,
|
|
14370
|
+
url,
|
|
14371
|
+
dbDisplay,
|
|
14372
|
+
pathDisplay: formatCwdPath(input.cwd),
|
|
14373
|
+
browserLine,
|
|
14374
|
+
colorEnabled: input.colorEnabled,
|
|
14375
|
+
referencePaths: input.referencePaths ?? [],
|
|
14376
|
+
dev: input.dev === true
|
|
14377
|
+
});
|
|
14274
14378
|
}
|
|
14275
|
-
function
|
|
14276
|
-
|
|
14277
|
-
|
|
14278
|
-
|
|
14279
|
-
|
|
14280
|
-
|
|
14281
|
-
return
|
|
14379
|
+
function resolveColorEnabled(opts) {
|
|
14380
|
+
if (opts.noColorFlag) return false;
|
|
14381
|
+
const noColor = opts.env["NO_COLOR"];
|
|
14382
|
+
if (noColor !== void 0 && noColor !== "") return false;
|
|
14383
|
+
const forceColor = opts.env["FORCE_COLOR"];
|
|
14384
|
+
if (forceColor !== void 0 && forceColor !== "") return true;
|
|
14385
|
+
return opts.isTTY;
|
|
14282
14386
|
}
|
|
14283
|
-
function
|
|
14284
|
-
|
|
14285
|
-
|
|
14286
|
-
|
|
14287
|
-
|
|
14288
|
-
|
|
14289
|
-
|
|
14290
|
-
|
|
14291
|
-
|
|
14292
|
-
|
|
14387
|
+
function renderFlat(input) {
|
|
14388
|
+
const safeHost = sanitizeForTerminal(input.host);
|
|
14389
|
+
const safeDb = sanitizeForTerminal(input.dbPath);
|
|
14390
|
+
const url = `http://${safeHost}:${input.port}`;
|
|
14391
|
+
const devSuffix = input.dev ? " [dev]" : "";
|
|
14392
|
+
const linesOut = [];
|
|
14393
|
+
linesOut.push(`sm serve${devSuffix}: listening on ${url} (db=${safeDb})`);
|
|
14394
|
+
if (input.openBrowser) {
|
|
14395
|
+
linesOut.push(`sm serve: opening ${url}/ in your browser. Press Ctrl+C to stop.`);
|
|
14396
|
+
} else {
|
|
14397
|
+
linesOut.push(`sm serve: visit ${url}/ in your browser. Press Ctrl+C to stop.`);
|
|
14293
14398
|
}
|
|
14294
|
-
return
|
|
14399
|
+
return linesOut.join("\n") + "\n";
|
|
14295
14400
|
}
|
|
14296
|
-
function
|
|
14297
|
-
const
|
|
14298
|
-
const
|
|
14299
|
-
const
|
|
14300
|
-
|
|
14301
|
-
|
|
14302
|
-
|
|
14303
|
-
|
|
14304
|
-
|
|
14305
|
-
|
|
14306
|
-
|
|
14307
|
-
(link) => survivingPaths.has(link.source) && survivingPaths.has(link.target)
|
|
14308
|
-
);
|
|
14309
|
-
const filteredIssues = scan.issues.filter(
|
|
14310
|
-
(issue) => issue.nodeIds.some((id) => survivingPaths.has(id))
|
|
14311
|
-
);
|
|
14312
|
-
return {
|
|
14313
|
-
query,
|
|
14314
|
-
nodes: filteredNodes,
|
|
14315
|
-
links: filteredLinks,
|
|
14316
|
-
issues: filteredIssues
|
|
14317
|
-
};
|
|
14401
|
+
function renderLogoBlock(input) {
|
|
14402
|
+
const { dimOpen, dimClose, violetOpen, violetClose } = resolveAnsi(input.colorEnabled);
|
|
14403
|
+
const logoLines = LOGO_LINES.map((line) => `${violetOpen}${line}${violetClose}`);
|
|
14404
|
+
const versionText = `v${input.version}`;
|
|
14405
|
+
const versionPad = Math.max(0, LOGO_WIDTH - versionText.length);
|
|
14406
|
+
const versionLine = `${" ".repeat(versionPad)}${dimOpen}${versionText}${dimClose}`;
|
|
14407
|
+
return `${logoLines.join("\n")}
|
|
14408
|
+
|
|
14409
|
+
${versionLine}
|
|
14410
|
+
|
|
14411
|
+
`;
|
|
14318
14412
|
}
|
|
14319
|
-
function
|
|
14320
|
-
const
|
|
14321
|
-
|
|
14322
|
-
|
|
14413
|
+
function renderFiglet(input) {
|
|
14414
|
+
const {
|
|
14415
|
+
dimOpen,
|
|
14416
|
+
dimClose,
|
|
14417
|
+
greenUnderline,
|
|
14418
|
+
greenUnderlineClose,
|
|
14419
|
+
violetOpen,
|
|
14420
|
+
violetClose,
|
|
14421
|
+
yellowOpen,
|
|
14422
|
+
yellowClose
|
|
14423
|
+
} = resolveAnsi(input.colorEnabled);
|
|
14424
|
+
const logoLines = LOGO_LINES.map((line) => `${violetOpen}${line}${violetClose}`);
|
|
14425
|
+
const versionText = `v${input.version}`;
|
|
14426
|
+
const devText = "[dev]";
|
|
14427
|
+
const versionWidth = input.dev ? devText.length : versionText.length;
|
|
14428
|
+
const versionPad = Math.max(0, LOGO_WIDTH - versionWidth);
|
|
14429
|
+
const versionLine = input.dev ? `${" ".repeat(versionPad)}${yellowOpen}${devText}${yellowClose}` : `${" ".repeat(versionPad)}${dimOpen}${versionText}${dimClose}`;
|
|
14430
|
+
const lines = [];
|
|
14431
|
+
lines.push(...logoLines);
|
|
14432
|
+
lines.push("");
|
|
14433
|
+
lines.push(versionLine);
|
|
14434
|
+
lines.push("");
|
|
14435
|
+
lines.push(` ${dimOpen}Server${dimClose} ${greenUnderline}${input.url}${greenUnderlineClose}`);
|
|
14436
|
+
lines.push(` ${dimOpen}Path${dimClose} ${input.pathDisplay}`);
|
|
14437
|
+
lines.push(` ${dimOpen}DB${dimClose} ${input.dbDisplay}`);
|
|
14438
|
+
lines.push(...renderListRows("Refs", input.referencePaths, dimOpen, dimClose));
|
|
14439
|
+
lines.push("");
|
|
14440
|
+
lines.push(` ${dimOpen}${input.browserLine}${dimClose}`);
|
|
14441
|
+
lines.push("");
|
|
14442
|
+
return lines.join("\n") + "\n";
|
|
14443
|
+
}
|
|
14444
|
+
function renderListRows(label, values, dimOpen, dimClose) {
|
|
14445
|
+
if (values.length === 0) return [];
|
|
14446
|
+
const out = [];
|
|
14447
|
+
const labelPad = " ".repeat(Math.max(1, 9 - label.length));
|
|
14448
|
+
const continuationPad = " ".repeat(11);
|
|
14449
|
+
out.push(` ${dimOpen}${label}${dimClose}${labelPad}${sanitizeForTerminal(values[0])}`);
|
|
14450
|
+
for (let i = 1; i < values.length; i += 1) {
|
|
14451
|
+
out.push(`${continuationPad}${sanitizeForTerminal(values[i])}`);
|
|
14323
14452
|
}
|
|
14324
14453
|
return out;
|
|
14325
14454
|
}
|
|
14326
|
-
|
|
14327
|
-
|
|
14328
|
-
|
|
14329
|
-
|
|
14330
|
-
|
|
14331
|
-
|
|
14332
|
-
|
|
14333
|
-
|
|
14334
|
-
|
|
14335
|
-
|
|
14336
|
-
|
|
14337
|
-
|
|
14338
|
-
|
|
14455
|
+
var EMPTY_ANSI = {
|
|
14456
|
+
dimOpen: "",
|
|
14457
|
+
dimClose: "",
|
|
14458
|
+
greenUnderline: "",
|
|
14459
|
+
greenUnderlineClose: "",
|
|
14460
|
+
violetOpen: "",
|
|
14461
|
+
violetClose: "",
|
|
14462
|
+
yellowOpen: "",
|
|
14463
|
+
yellowClose: ""
|
|
14464
|
+
};
|
|
14465
|
+
var ENABLED_ANSI = {
|
|
14466
|
+
dimOpen: ESC2.dim,
|
|
14467
|
+
dimClose: ESC2.reset,
|
|
14468
|
+
greenUnderline: `${ESC2.green}${ESC2.underline}`,
|
|
14469
|
+
greenUnderlineClose: ESC2.reset,
|
|
14470
|
+
violetOpen: ESC2.violet,
|
|
14471
|
+
violetClose: ESC2.reset,
|
|
14472
|
+
yellowOpen: ESC2.yellow,
|
|
14473
|
+
yellowClose: ESC2.reset
|
|
14474
|
+
};
|
|
14475
|
+
function resolveAnsi(colorEnabled) {
|
|
14476
|
+
return colorEnabled ? ENABLED_ANSI : EMPTY_ANSI;
|
|
14477
|
+
}
|
|
14478
|
+
function formatDbPath(dbPath, cwd) {
|
|
14479
|
+
const safe = sanitizeForTerminal(dbPath);
|
|
14480
|
+
if (!isAbsolute7(safe)) return safe;
|
|
14481
|
+
const rel = relative4(cwd, safe);
|
|
14482
|
+
if (rel === "" || rel.startsWith("..") || isAbsolute7(rel)) {
|
|
14483
|
+
return safe;
|
|
14484
|
+
}
|
|
14485
|
+
return rel;
|
|
14486
|
+
}
|
|
14487
|
+
function formatCwdPath(cwd) {
|
|
14488
|
+
return sanitizeForTerminal(cwd);
|
|
14489
|
+
}
|
|
14490
|
+
|
|
14491
|
+
// cli/commands/example.ts
|
|
14492
|
+
var EXAMPLE_SOURCE_DIR = "fixtures/demo-scope";
|
|
14493
|
+
var ExampleCommand = class extends SmCommand {
|
|
14494
|
+
static paths = [["example"]];
|
|
14495
|
+
static usage = Command13.Usage({
|
|
14496
|
+
category: "Setup",
|
|
14497
|
+
description: "Materialize a ready-to-explore example project (the demo harness) in the current directory.",
|
|
14498
|
+
details: `
|
|
14499
|
+
Writes a small wired portfolio into <cwd>: a handbook (AGENTS.md)
|
|
14500
|
+
that mentions a content-editor agent and invokes a publish command,
|
|
14501
|
+
a check-links skill the command calls, and the docs they reference.
|
|
14502
|
+
It is the same harness the public demo renders.
|
|
14503
|
+
|
|
14504
|
+
Ships unscanned (no .skill-map/): run \`sm scan\` then \`sm serve\`
|
|
14505
|
+
to build and open the graph. Requires an empty directory; refuses a
|
|
14506
|
+
non-empty cwd (exit 2) unless --force. Takes no positional argument.
|
|
14507
|
+
`,
|
|
14508
|
+
examples: [
|
|
14509
|
+
["Create the example project in the cwd", "$0 example"],
|
|
14510
|
+
["Create it even if the directory is not empty", "$0 example --force"]
|
|
14511
|
+
]
|
|
14512
|
+
});
|
|
14513
|
+
// The verb takes no positional argument. Accept one so a stray
|
|
14514
|
+
// `sm example foo` lands on a friendly usage error (guarded in
|
|
14515
|
+
// `run()`) instead of clipanion's generic "extraneous argument".
|
|
14516
|
+
legacyPositional = Option12.String({ required: false });
|
|
14517
|
+
force = Option12.Boolean("--force", false, {
|
|
14518
|
+
description: "Overwrite colliding files in a non-empty directory without prompting."
|
|
14519
|
+
});
|
|
14520
|
+
async run() {
|
|
14521
|
+
const ctx = defaultRuntimeContext();
|
|
14522
|
+
const stderr = this.context.stderr;
|
|
14523
|
+
const stderrAnsi = this.ansiFor("stderr");
|
|
14524
|
+
const errGlyph = stderrAnsi.red("\u2715");
|
|
14525
|
+
if (this.legacyPositional !== void 0) {
|
|
14526
|
+
this.printer.error(
|
|
14527
|
+
tx(EXAMPLE_TEXTS.unexpectedArg, {
|
|
14528
|
+
glyph: errGlyph,
|
|
14529
|
+
arg: this.legacyPositional,
|
|
14530
|
+
hint: stderrAnsi.dim(EXAMPLE_TEXTS.unexpectedArgHint)
|
|
14531
|
+
})
|
|
14532
|
+
);
|
|
14533
|
+
return ExitCode.Error;
|
|
14534
|
+
}
|
|
14535
|
+
if (!this.force && !isDirEmpty(ctx.cwd)) {
|
|
14536
|
+
this.printer.error(
|
|
14537
|
+
tx(EXAMPLE_TEXTS.notEmpty, {
|
|
14538
|
+
glyph: errGlyph,
|
|
14539
|
+
entries: listCwdEntries(ctx.cwd),
|
|
14540
|
+
hint: stderrAnsi.dim(EXAMPLE_TEXTS.notEmptyHint)
|
|
14541
|
+
})
|
|
14542
|
+
);
|
|
14543
|
+
return ExitCode.Error;
|
|
14544
|
+
}
|
|
14545
|
+
let sourceDir;
|
|
14546
|
+
try {
|
|
14547
|
+
sourceDir = resolveExampleSourceDir();
|
|
14548
|
+
} catch {
|
|
14549
|
+
this.printer.error(
|
|
14550
|
+
tx(EXAMPLE_TEXTS.sourceMissing, {
|
|
14551
|
+
glyph: errGlyph,
|
|
14552
|
+
hint: stderrAnsi.dim(EXAMPLE_TEXTS.sourceMissingHint)
|
|
14553
|
+
})
|
|
14554
|
+
);
|
|
14555
|
+
return ExitCode.Error;
|
|
14556
|
+
}
|
|
14557
|
+
try {
|
|
14558
|
+
cpSync2(sourceDir, ctx.cwd, {
|
|
14559
|
+
recursive: true,
|
|
14560
|
+
// Never copy the example's own scan state: the project must ship
|
|
14561
|
+
// unscanned so the user's first `sm scan` provisions it fresh.
|
|
14562
|
+
filter: (src) => isExamplePayloadEntry(sourceDir, src)
|
|
14563
|
+
});
|
|
14564
|
+
} catch (err) {
|
|
14565
|
+
this.printer.error(
|
|
14566
|
+
tx(EXAMPLE_TEXTS.writeFailed, {
|
|
14567
|
+
glyph: errGlyph,
|
|
14568
|
+
message: formatErrorMessage(err)
|
|
14569
|
+
})
|
|
14570
|
+
);
|
|
14571
|
+
return ExitCode.Error;
|
|
14572
|
+
}
|
|
14573
|
+
const colorEnabled = resolveColorEnabled({
|
|
14574
|
+
isTTY: stderr.isTTY === true,
|
|
14575
|
+
noColorFlag: this.noColor,
|
|
14576
|
+
env: process.env
|
|
14577
|
+
});
|
|
14578
|
+
this.printer.info(renderLogoBlock({ version: VERSION, colorEnabled }));
|
|
14579
|
+
const ansi = this.ansiFor("stdout");
|
|
14580
|
+
this.printer.data(
|
|
14581
|
+
tx(EXAMPLE_TEXTS.written, {
|
|
14582
|
+
glyph: ansi.green("\u2713"),
|
|
14583
|
+
cwd: ansi.dim(displayCwd(ctx.cwd)),
|
|
14584
|
+
scanGlyph: ansi.dim(EXAMPLE_TEXTS.writtenScanGlyph),
|
|
14585
|
+
serveGlyph: ansi.dim(EXAMPLE_TEXTS.writtenServeGlyph)
|
|
14586
|
+
})
|
|
14587
|
+
);
|
|
14588
|
+
return ExitCode.Ok;
|
|
14589
|
+
}
|
|
14590
|
+
};
|
|
14591
|
+
var cachedSourceDir;
|
|
14592
|
+
function resolveExampleSourceDir() {
|
|
14593
|
+
if (cachedSourceDir !== void 0) return cachedSourceDir;
|
|
14594
|
+
const here = dirname16(fileURLToPath5(import.meta.url));
|
|
14595
|
+
const candidates = [
|
|
14596
|
+
// dev: src/cli/commands/ → repo-root fixtures/demo-scope/
|
|
14597
|
+
resolve26(here, "../../..", EXAMPLE_SOURCE_DIR),
|
|
14598
|
+
// bundled: dist/cli.js → dist/cli/example (sibling)
|
|
14599
|
+
resolve26(here, "cli/example"),
|
|
14600
|
+
// bundled fallback: any-depth → cli/example
|
|
14601
|
+
resolve26(here, "../cli/example")
|
|
14602
|
+
];
|
|
14603
|
+
for (const candidate of candidates) {
|
|
14604
|
+
if (existsSync21(candidate) && statSync5(candidate).isDirectory()) {
|
|
14605
|
+
cachedSourceDir = candidate;
|
|
14606
|
+
return candidate;
|
|
14607
|
+
}
|
|
14608
|
+
}
|
|
14609
|
+
throw new Error(
|
|
14610
|
+
`example payload directory not found in any candidate location (last tried: ${candidates[candidates.length - 1]})`
|
|
14611
|
+
);
|
|
14612
|
+
}
|
|
14613
|
+
function isExamplePayloadEntry(sourceRoot, src) {
|
|
14614
|
+
const rel = relative5(sourceRoot, src);
|
|
14615
|
+
if (rel === "") return true;
|
|
14616
|
+
return rel.split(/[\\/]/)[0] !== ".skill-map";
|
|
14617
|
+
}
|
|
14618
|
+
|
|
14619
|
+
// cli/commands/export.ts
|
|
14620
|
+
import { Command as Command14, Option as Option13 } from "clipanion";
|
|
14621
|
+
|
|
14622
|
+
// kernel/scan/query.ts
|
|
14623
|
+
var HAS_VALUES = /* @__PURE__ */ new Set(["issues"]);
|
|
14624
|
+
var ExportQueryError = class extends Error {
|
|
14625
|
+
constructor(message) {
|
|
14626
|
+
super(message);
|
|
14627
|
+
this.name = "ExportQueryError";
|
|
14628
|
+
}
|
|
14629
|
+
};
|
|
14630
|
+
function parseExportQuery(raw) {
|
|
14631
|
+
const trimmed = raw.trim();
|
|
14632
|
+
const out = { raw: trimmed };
|
|
14633
|
+
if (trimmed.length === 0) return out;
|
|
14634
|
+
const seen = /* @__PURE__ */ new Set();
|
|
14635
|
+
for (const token of trimmed.split(/\s+/)) {
|
|
14636
|
+
const eq = token.indexOf("=");
|
|
14637
|
+
if (eq <= 0 || eq === token.length - 1) {
|
|
14638
|
+
throw new ExportQueryError(
|
|
14639
|
+
tx(QUERY_TEXTS.exportQueryInvalidToken, { token })
|
|
14640
|
+
);
|
|
14641
|
+
}
|
|
14642
|
+
const key = token.slice(0, eq).toLowerCase();
|
|
14643
|
+
const valuePart = token.slice(eq + 1);
|
|
14644
|
+
if (seen.has(key)) {
|
|
14645
|
+
throw new ExportQueryError(
|
|
14646
|
+
tx(QUERY_TEXTS.exportQueryDuplicateKey, { key })
|
|
14647
|
+
);
|
|
14648
|
+
}
|
|
14649
|
+
seen.add(key);
|
|
14650
|
+
const values = valuePart.split(",").map((v) => v.trim()).filter((v) => v.length > 0);
|
|
14651
|
+
if (values.length === 0) {
|
|
14652
|
+
throw new ExportQueryError(tx(QUERY_TEXTS.exportQueryEmptyValues, { key }));
|
|
14653
|
+
}
|
|
14654
|
+
switch (key) {
|
|
14655
|
+
case "kind":
|
|
14656
|
+
out.kinds = parseKindValues(values);
|
|
14657
|
+
break;
|
|
14658
|
+
case "has":
|
|
14659
|
+
if (parseHasValues(values)) out.hasIssues = true;
|
|
14660
|
+
break;
|
|
14661
|
+
case "path":
|
|
14662
|
+
out.pathGlobs = values;
|
|
14663
|
+
break;
|
|
14664
|
+
default:
|
|
14665
|
+
throw new ExportQueryError(
|
|
14666
|
+
tx(QUERY_TEXTS.exportQueryUnknownKey, { key })
|
|
14667
|
+
);
|
|
14668
|
+
}
|
|
14669
|
+
}
|
|
14670
|
+
return out;
|
|
14671
|
+
}
|
|
14672
|
+
function parseKindValues(values) {
|
|
14673
|
+
for (const v of values) {
|
|
14674
|
+
if (v.length === 0) {
|
|
14675
|
+
throw new ExportQueryError(QUERY_TEXTS.exportQueryEmptyKind);
|
|
14676
|
+
}
|
|
14677
|
+
}
|
|
14678
|
+
return values;
|
|
14679
|
+
}
|
|
14680
|
+
function parseHasValues(values) {
|
|
14681
|
+
for (const v of values) {
|
|
14682
|
+
if (!HAS_VALUES.has(v)) {
|
|
14683
|
+
throw new ExportQueryError(
|
|
14684
|
+
tx(QUERY_TEXTS.exportQueryUnsupportedHas, {
|
|
14685
|
+
value: v,
|
|
14686
|
+
allowed: [...HAS_VALUES].join(", ")
|
|
14687
|
+
})
|
|
14688
|
+
);
|
|
14689
|
+
}
|
|
14690
|
+
}
|
|
14691
|
+
return values.includes("issues");
|
|
14692
|
+
}
|
|
14693
|
+
function applyExportQuery(scan, query) {
|
|
14694
|
+
const nodesWithIssues = query.hasIssues ? collectNodesWithIssues(scan.issues) : null;
|
|
14695
|
+
const compiledGlobs = query.pathGlobs ? query.pathGlobs.map(compileGlob) : null;
|
|
14696
|
+
const filteredNodes = scan.nodes.filter((node) => {
|
|
14697
|
+
if (query.kinds && !query.kinds.includes(node.kind)) return false;
|
|
14698
|
+
if (nodesWithIssues && !nodesWithIssues.has(node.path)) return false;
|
|
14699
|
+
if (compiledGlobs && !compiledGlobs.some((re) => re.test(node.path))) return false;
|
|
14700
|
+
return true;
|
|
14701
|
+
});
|
|
14702
|
+
const survivingPaths = new Set(filteredNodes.map((n) => n.path));
|
|
14703
|
+
const filteredLinks = scan.links.filter(
|
|
14704
|
+
(link) => survivingPaths.has(link.source) && survivingPaths.has(link.target)
|
|
14705
|
+
);
|
|
14706
|
+
const filteredIssues = scan.issues.filter(
|
|
14707
|
+
(issue) => issue.nodeIds.some((id) => survivingPaths.has(id))
|
|
14708
|
+
);
|
|
14709
|
+
return {
|
|
14710
|
+
query,
|
|
14711
|
+
nodes: filteredNodes,
|
|
14712
|
+
links: filteredLinks,
|
|
14713
|
+
issues: filteredIssues
|
|
14714
|
+
};
|
|
14715
|
+
}
|
|
14716
|
+
function collectNodesWithIssues(issues) {
|
|
14717
|
+
const out = /* @__PURE__ */ new Set();
|
|
14718
|
+
for (const issue of issues) {
|
|
14719
|
+
for (const nodeId of issue.nodeIds) out.add(nodeId);
|
|
14720
|
+
}
|
|
14721
|
+
return out;
|
|
14722
|
+
}
|
|
14723
|
+
function compileGlob(pattern) {
|
|
14724
|
+
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
|
|
14725
|
+
const withDouble = escaped.replace(/\*\*/g, "\0DOUBLESTAR\0");
|
|
14726
|
+
const withSingle = withDouble.replace(/\*/g, "[^/]*");
|
|
14727
|
+
const final = withSingle.replace(/DOUBLESTAR/g, ".*");
|
|
14728
|
+
return new RegExp(`^${final}$`);
|
|
14729
|
+
}
|
|
14730
|
+
|
|
14731
|
+
// cli/i18n/export.texts.ts
|
|
14732
|
+
var EXPORT_TEXTS = {
|
|
14733
|
+
/**
|
|
14734
|
+
* Generic §3.1 single-line error wrapper. The caller passes the
|
|
14735
|
+
* already-rendered glyph (red `✕`) and the inner error message. No
|
|
14339
14736
|
* hint here because the inner message itself varies across call
|
|
14340
14737
|
* sites (config load, file write, malformed query). Specific errors
|
|
14341
14738
|
* with actionable next steps use their own §3.1b blocks below.
|
|
@@ -14399,7 +14796,7 @@ var DEFERRED_FORMATS = {
|
|
|
14399
14796
|
};
|
|
14400
14797
|
var ExportCommand = class extends SmCommand {
|
|
14401
14798
|
static paths = [["export"]];
|
|
14402
|
-
static usage =
|
|
14799
|
+
static usage = Command14.Usage({
|
|
14403
14800
|
category: "Browse",
|
|
14404
14801
|
description: "Filtered export. Query syntax is implementation-defined pre-1.0.",
|
|
14405
14802
|
details: `
|
|
@@ -14424,8 +14821,8 @@ var ExportCommand = class extends SmCommand {
|
|
|
14424
14821
|
["Files under a path glob", '$0 export "path=.claude/commands/**" --format json']
|
|
14425
14822
|
]
|
|
14426
14823
|
});
|
|
14427
|
-
query =
|
|
14428
|
-
format =
|
|
14824
|
+
query = Option13.String({ required: false });
|
|
14825
|
+
format = Option13.String("--format", { required: false });
|
|
14429
14826
|
async run() {
|
|
14430
14827
|
const stderrAnsi = this.ansiFor("stderr");
|
|
14431
14828
|
const errGlyph = stderrAnsi.red("\u2715");
|
|
@@ -14649,7 +15046,7 @@ function pickTitle2(node) {
|
|
|
14649
15046
|
}
|
|
14650
15047
|
|
|
14651
15048
|
// cli/commands/graph.ts
|
|
14652
|
-
import { Command as
|
|
15049
|
+
import { Command as Command15, Option as Option14 } from "clipanion";
|
|
14653
15050
|
|
|
14654
15051
|
// cli/i18n/graph.texts.ts
|
|
14655
15052
|
var GRAPH_TEXTS = {
|
|
@@ -14667,7 +15064,7 @@ var GRAPH_TEXTS = {
|
|
|
14667
15064
|
var DEFAULT_FORMAT = "ascii";
|
|
14668
15065
|
var GraphCommand = class extends SmCommand {
|
|
14669
15066
|
static paths = [["graph"]];
|
|
14670
|
-
static usage =
|
|
15067
|
+
static usage = Command15.Usage({
|
|
14671
15068
|
category: "Browse",
|
|
14672
15069
|
description: "Render the full graph via the named formatter.",
|
|
14673
15070
|
details: `
|
|
@@ -14684,10 +15081,10 @@ var GraphCommand = class extends SmCommand {
|
|
|
14684
15081
|
["Use a non-default DB file", "$0 graph --db /path/to/skill-map.db"]
|
|
14685
15082
|
]
|
|
14686
15083
|
});
|
|
14687
|
-
format =
|
|
15084
|
+
format = Option14.String("--format", DEFAULT_FORMAT, {
|
|
14688
15085
|
description: `Formatter format. Must match the \`formatId\` field of a registered formatter. Default: ${DEFAULT_FORMAT}.`
|
|
14689
15086
|
});
|
|
14690
|
-
noPlugins =
|
|
15087
|
+
noPlugins = Option14.Boolean("--no-plugins", false, {
|
|
14691
15088
|
description: "Skip drop-in plugin discovery. Only built-in formatters participate."
|
|
14692
15089
|
});
|
|
14693
15090
|
async run() {
|
|
@@ -14738,8 +15135,8 @@ var GraphCommand = class extends SmCommand {
|
|
|
14738
15135
|
// cli/commands/help.ts
|
|
14739
15136
|
import { readFileSync as readFileSync17 } from "fs";
|
|
14740
15137
|
import { createRequire as createRequire7 } from "module";
|
|
14741
|
-
import { resolve as
|
|
14742
|
-
import { Command as
|
|
15138
|
+
import { resolve as resolve27 } from "path";
|
|
15139
|
+
import { Command as Command16, Option as Option15 } from "clipanion";
|
|
14743
15140
|
|
|
14744
15141
|
// cli/i18n/help.texts.ts
|
|
14745
15142
|
var HELP_TEXTS = {
|
|
@@ -14882,9 +15279,9 @@ var HELP_GROUPS = {
|
|
|
14882
15279
|
};
|
|
14883
15280
|
|
|
14884
15281
|
// cli/commands/help.ts
|
|
14885
|
-
var HelpCommand = class extends
|
|
15282
|
+
var HelpCommand = class extends Command16 {
|
|
14886
15283
|
static paths = [["help"]];
|
|
14887
|
-
static usage =
|
|
15284
|
+
static usage = Command16.Usage({
|
|
14888
15285
|
category: "Introspection",
|
|
14889
15286
|
description: "Self-describing introspection. --format human|md|json.",
|
|
14890
15287
|
details: `
|
|
@@ -14897,13 +15294,13 @@ var HelpCommand = class extends Command15 {
|
|
|
14897
15294
|
json : structured surface dump per spec/cli-contract.md.
|
|
14898
15295
|
`
|
|
14899
15296
|
});
|
|
14900
|
-
verbParts =
|
|
14901
|
-
format =
|
|
15297
|
+
verbParts = Option15.Rest({ required: 0 });
|
|
15298
|
+
format = Option15.String("--format", "human");
|
|
14902
15299
|
// `HelpCommand` extends Clipanion's `Command` directly (see block
|
|
14903
15300
|
// comment), so it does not inherit `SmCommand`'s `--no-color`. Declared
|
|
14904
15301
|
// here because the human overview now emits a coloured tutorial glyph;
|
|
14905
15302
|
// `ansiFor` still layers `NO_COLOR` / `FORCE_COLOR` / TTY on top.
|
|
14906
|
-
noColor =
|
|
15303
|
+
noColor = Option15.Boolean("--no-color", false, {
|
|
14907
15304
|
description: "Disable ANSI color codes."
|
|
14908
15305
|
});
|
|
14909
15306
|
async execute() {
|
|
@@ -15052,7 +15449,7 @@ function resolveSpecVersion() {
|
|
|
15052
15449
|
try {
|
|
15053
15450
|
const req = createRequire7(import.meta.url);
|
|
15054
15451
|
const indexPath = req.resolve("@skill-map/spec/index.json");
|
|
15055
|
-
const pkgPath =
|
|
15452
|
+
const pkgPath = resolve27(indexPath, "..", "package.json");
|
|
15056
15453
|
const pkg = JSON.parse(readFileSync17(pkgPath, "utf8"));
|
|
15057
15454
|
return pkg.version;
|
|
15058
15455
|
} catch {
|
|
@@ -15295,12 +15692,12 @@ function renderCompactOverview(verbs, ansi) {
|
|
|
15295
15692
|
lines.push(HELP_TEXTS.compactFooter);
|
|
15296
15693
|
return lines.join("\n") + "\n";
|
|
15297
15694
|
}
|
|
15298
|
-
var RootHelpCommand = class extends
|
|
15695
|
+
var RootHelpCommand = class extends Command16 {
|
|
15299
15696
|
static paths = [["-h"], ["--help"]];
|
|
15300
15697
|
// Mirrors `HelpCommand.noColor`: this command extends Clipanion's
|
|
15301
15698
|
// `Command` directly, so the flag is declared here to gate the
|
|
15302
15699
|
// coloured tutorial glyph in the overview.
|
|
15303
|
-
noColor =
|
|
15700
|
+
noColor = Option15.Boolean("--no-color", false, {
|
|
15304
15701
|
description: "Disable ANSI color codes."
|
|
15305
15702
|
});
|
|
15306
15703
|
async execute() {
|
|
@@ -15360,8 +15757,8 @@ function registeredVerbPaths(cli2) {
|
|
|
15360
15757
|
|
|
15361
15758
|
// cli/commands/hooks.ts
|
|
15362
15759
|
import { chmod as chmod2, mkdir as mkdir3, readFile as readFile2, stat as stat2, writeFile } from "fs/promises";
|
|
15363
|
-
import { dirname as
|
|
15364
|
-
import { Command as
|
|
15760
|
+
import { dirname as dirname17, resolve as resolve28 } from "path";
|
|
15761
|
+
import { Command as Command17, Option as Option16 } from "clipanion";
|
|
15365
15762
|
|
|
15366
15763
|
// cli/i18n/hooks.texts.ts
|
|
15367
15764
|
var HOOKS_TEXTS = {
|
|
@@ -15408,7 +15805,7 @@ var SKILL_MAP_BLOCK = [
|
|
|
15408
15805
|
var FRESH_HOOK_BODY = HOOK_SHEBANG + SKILL_MAP_BLOCK;
|
|
15409
15806
|
var HooksInstallCommand = class extends SmCommand {
|
|
15410
15807
|
static paths = [["hooks", "install"]];
|
|
15411
|
-
static usage =
|
|
15808
|
+
static usage = Command17.Usage({
|
|
15412
15809
|
category: "Actions",
|
|
15413
15810
|
description: "Install a git pre-commit hook that auto-bumps staged sidecar drift.",
|
|
15414
15811
|
details: `
|
|
@@ -15431,8 +15828,8 @@ var HooksInstallCommand = class extends SmCommand {
|
|
|
15431
15828
|
["Preview what would be written", "$0 hooks install pre-commit-bump --dry-run"]
|
|
15432
15829
|
]
|
|
15433
15830
|
});
|
|
15434
|
-
flavour =
|
|
15435
|
-
dryRun =
|
|
15831
|
+
flavour = Option16.String({ required: true });
|
|
15832
|
+
dryRun = Option16.Boolean("-n,--dry-run", false);
|
|
15436
15833
|
// The remaining cyclomatic count is from CLI ergonomics, flavour
|
|
15437
15834
|
// guard, repo lookup, marker detection, dry-run / json / chained /
|
|
15438
15835
|
// fresh branches each contributing a guard. Inner work already lives
|
|
@@ -15463,8 +15860,8 @@ var HooksInstallCommand = class extends SmCommand {
|
|
|
15463
15860
|
);
|
|
15464
15861
|
return ExitCode.NotFound;
|
|
15465
15862
|
}
|
|
15466
|
-
const hooksDir =
|
|
15467
|
-
const hookPath =
|
|
15863
|
+
const hooksDir = resolve28(repoRoot, ".git", "hooks");
|
|
15864
|
+
const hookPath = resolve28(hooksDir, "pre-commit");
|
|
15468
15865
|
const existing = await pathExists(hookPath) ? await readFile2(hookPath, "utf8") : null;
|
|
15469
15866
|
const planned2 = computePlannedHookContent(existing);
|
|
15470
15867
|
if (planned2.kind === "already-installed") {
|
|
@@ -15522,8 +15919,8 @@ var HooksInstallCommand = class extends SmCommand {
|
|
|
15522
15919
|
async function findGitRepoRoot(cwd) {
|
|
15523
15920
|
let current = cwd;
|
|
15524
15921
|
while (true) {
|
|
15525
|
-
if (await pathExists(
|
|
15526
|
-
const parent =
|
|
15922
|
+
if (await pathExists(resolve28(current, ".git"))) return current;
|
|
15923
|
+
const parent = dirname17(current);
|
|
15527
15924
|
if (parent === current) return null;
|
|
15528
15925
|
current = parent;
|
|
15529
15926
|
}
|
|
@@ -15545,11 +15942,11 @@ var HOOKS_COMMANDS = [HooksInstallCommand];
|
|
|
15545
15942
|
// cli/commands/init.ts
|
|
15546
15943
|
import { mkdir as mkdir4, readFile as readFile3, unlink, writeFile as writeFile2 } from "fs/promises";
|
|
15547
15944
|
import { join as join16 } from "path";
|
|
15548
|
-
import { Command as
|
|
15945
|
+
import { Command as Command18, Option as Option17 } from "clipanion";
|
|
15549
15946
|
|
|
15550
15947
|
// kernel/orchestrator/index.ts
|
|
15551
|
-
import { existsSync as
|
|
15552
|
-
import { isAbsolute as
|
|
15948
|
+
import { existsSync as existsSync24, statSync as statSync7 } from "fs";
|
|
15949
|
+
import { isAbsolute as isAbsolute10, resolve as resolve31 } from "path";
|
|
15553
15950
|
import { Tiktoken as Tiktoken2 } from "js-tiktoken/lite";
|
|
15554
15951
|
|
|
15555
15952
|
// kernel/i18n/orchestrator.texts.ts
|
|
@@ -16494,7 +16891,7 @@ function collectBrokenLinks(links, nodes, ctx) {
|
|
|
16494
16891
|
return broken;
|
|
16495
16892
|
}
|
|
16496
16893
|
function applyResolution(link, indexes, ctx) {
|
|
16497
|
-
const resolution =
|
|
16894
|
+
const resolution = resolve29(link, indexes, ctx);
|
|
16498
16895
|
if (resolution === "none") return;
|
|
16499
16896
|
link.resolvedTarget = resolution;
|
|
16500
16897
|
}
|
|
@@ -16509,7 +16906,7 @@ function buildIndexes(nodes, ctx) {
|
|
|
16509
16906
|
}
|
|
16510
16907
|
return { byPath: byPath3, byName, nodeByPath };
|
|
16511
16908
|
}
|
|
16512
|
-
function
|
|
16909
|
+
function resolve29(link, indexes, ctx) {
|
|
16513
16910
|
if (indexes.byPath.has(link.target)) return link.target;
|
|
16514
16911
|
return resolveByName(link, indexes, ctx);
|
|
16515
16912
|
}
|
|
@@ -16898,7 +17295,7 @@ function detectRenamesAndOrphans(prior, current, issues, silenced) {
|
|
|
16898
17295
|
}
|
|
16899
17296
|
|
|
16900
17297
|
// kernel/orchestrator/walk.ts
|
|
16901
|
-
import { isAbsolute as
|
|
17298
|
+
import { isAbsolute as isAbsolute9, resolve as resolve30 } from "path";
|
|
16902
17299
|
|
|
16903
17300
|
// kernel/sidecar/drift.ts
|
|
16904
17301
|
function computeDriftStatus(args2) {
|
|
@@ -16911,8 +17308,8 @@ function computeDriftStatus(args2) {
|
|
|
16911
17308
|
}
|
|
16912
17309
|
|
|
16913
17310
|
// kernel/sidecar/discover-orphans.ts
|
|
16914
|
-
import { existsSync as
|
|
16915
|
-
import { join as join13, relative as
|
|
17311
|
+
import { existsSync as existsSync22, readdirSync as readdirSync8, statSync as statSync6 } from "fs";
|
|
17312
|
+
import { join as join13, relative as relative6, sep as sep4 } from "path";
|
|
16916
17313
|
function discoverOrphanSidecars(roots, shouldSkip) {
|
|
16917
17314
|
const out = [];
|
|
16918
17315
|
for (const root of roots) {
|
|
@@ -16923,13 +17320,13 @@ function discoverOrphanSidecars(roots, shouldSkip) {
|
|
|
16923
17320
|
function walk2(root, current, shouldSkip, out) {
|
|
16924
17321
|
let entries;
|
|
16925
17322
|
try {
|
|
16926
|
-
entries =
|
|
17323
|
+
entries = readdirSync8(current, { withFileTypes: true, encoding: "utf8" });
|
|
16927
17324
|
} catch {
|
|
16928
17325
|
return;
|
|
16929
17326
|
}
|
|
16930
17327
|
for (const entry of entries) {
|
|
16931
17328
|
const full = join13(current, entry.name);
|
|
16932
|
-
const rel =
|
|
17329
|
+
const rel = relative6(root, full).split(sep4).join("/");
|
|
16933
17330
|
if (shouldSkip(rel)) continue;
|
|
16934
17331
|
if (entry.isSymbolicLink()) continue;
|
|
16935
17332
|
if (entry.isDirectory()) {
|
|
@@ -16939,13 +17336,13 @@ function walk2(root, current, shouldSkip, out) {
|
|
|
16939
17336
|
if (!entry.isFile()) continue;
|
|
16940
17337
|
if (!entry.name.endsWith(".sm")) continue;
|
|
16941
17338
|
const expectedMd = `${full.slice(0, -".sm".length)}.md`;
|
|
16942
|
-
if (
|
|
17339
|
+
if (existsSync22(expectedMd) && safeIsFile(expectedMd)) continue;
|
|
16943
17340
|
out.push({ sidecarPath: full, relativePath: rel, expectedMdPath: expectedMd });
|
|
16944
17341
|
}
|
|
16945
17342
|
}
|
|
16946
17343
|
function safeIsFile(path) {
|
|
16947
17344
|
try {
|
|
16948
|
-
return
|
|
17345
|
+
return statSync6(path).isFile();
|
|
16949
17346
|
} catch {
|
|
16950
17347
|
return false;
|
|
16951
17348
|
}
|
|
@@ -16953,8 +17350,8 @@ function safeIsFile(path) {
|
|
|
16953
17350
|
|
|
16954
17351
|
// kernel/orchestrator/node-build.ts
|
|
16955
17352
|
import { createHash as createHash2 } from "crypto";
|
|
16956
|
-
import { existsSync as
|
|
16957
|
-
import { isAbsolute as
|
|
17353
|
+
import { existsSync as existsSync23 } from "fs";
|
|
17354
|
+
import { isAbsolute as isAbsolute8, resolve as resolvePath } from "path";
|
|
16958
17355
|
import "js-tiktoken/lite";
|
|
16959
17356
|
import yaml4 from "js-yaml";
|
|
16960
17357
|
|
|
@@ -17117,12 +17514,12 @@ function resolveSidecarOverlay(relativePath2, nodePathForIssue, roots, liveBodyH
|
|
|
17117
17514
|
};
|
|
17118
17515
|
}
|
|
17119
17516
|
function resolveAbsoluteMdPath(relativePath2, roots) {
|
|
17120
|
-
if (
|
|
17121
|
-
return
|
|
17517
|
+
if (isAbsolute8(relativePath2)) {
|
|
17518
|
+
return existsSync23(relativePath2) ? relativePath2 : null;
|
|
17122
17519
|
}
|
|
17123
17520
|
for (const root of roots) {
|
|
17124
17521
|
const candidate = resolvePath(root, relativePath2);
|
|
17125
|
-
if (
|
|
17522
|
+
if (existsSync23(candidate)) return candidate;
|
|
17126
17523
|
}
|
|
17127
17524
|
return null;
|
|
17128
17525
|
}
|
|
@@ -17344,8 +17741,8 @@ function expandSidecarPaths(paths, priorNodesByPath) {
|
|
|
17344
17741
|
}
|
|
17345
17742
|
function toAbsolute(relPath, roots) {
|
|
17346
17743
|
const root = roots[0] ?? ".";
|
|
17347
|
-
const absRoot =
|
|
17348
|
-
return
|
|
17744
|
+
const absRoot = isAbsolute9(root) ? root : resolve30(root);
|
|
17745
|
+
return resolve30(absRoot, relPath);
|
|
17349
17746
|
}
|
|
17350
17747
|
function resolveEffectiveCaps(opts) {
|
|
17351
17748
|
return {
|
|
@@ -17935,7 +18332,7 @@ function validateRoots(roots) {
|
|
|
17935
18332
|
throw new Error(ORCHESTRATOR_TEXTS.runScanRootEmptyArray);
|
|
17936
18333
|
}
|
|
17937
18334
|
for (const root of roots) {
|
|
17938
|
-
if (!
|
|
18335
|
+
if (!existsSync24(root) || !statSync7(root).isDirectory()) {
|
|
17939
18336
|
throw new Error(tx(ORCHESTRATOR_TEXTS.runScanRootMissing, { root }));
|
|
17940
18337
|
}
|
|
17941
18338
|
}
|
|
@@ -17943,8 +18340,8 @@ function validateRoots(roots) {
|
|
|
17943
18340
|
function resolveActiveProviderOption(optionValue, roots, providers) {
|
|
17944
18341
|
if (optionValue !== void 0) return optionValue;
|
|
17945
18342
|
for (const root of roots) {
|
|
17946
|
-
const absRoot =
|
|
17947
|
-
if (!
|
|
18343
|
+
const absRoot = isAbsolute10(root) ? root : resolve31(root);
|
|
18344
|
+
if (!existsSync24(absRoot)) continue;
|
|
17948
18345
|
const detected = detectProvidersFromFilesystem(absRoot, providers)[0] ?? null;
|
|
17949
18346
|
if (detected !== null) return detected;
|
|
17950
18347
|
}
|
|
@@ -17952,10 +18349,10 @@ function resolveActiveProviderOption(optionValue, roots, providers) {
|
|
|
17952
18349
|
}
|
|
17953
18350
|
|
|
17954
18351
|
// kernel/scan/watcher.ts
|
|
17955
|
-
import { resolve as
|
|
18352
|
+
import { resolve as resolve32, relative as relative7, sep as sep5 } from "path";
|
|
17956
18353
|
import chokidar from "chokidar";
|
|
17957
18354
|
function createChokidarWatcher(opts) {
|
|
17958
|
-
const absRoots = opts.roots.map((r) =>
|
|
18355
|
+
const absRoots = opts.roots.map((r) => resolve32(opts.cwd, r));
|
|
17959
18356
|
const ignoreFilterOpt = opts.ignoreFilter;
|
|
17960
18357
|
const getFilter = ignoreFilterOpt === void 0 ? void 0 : typeof ignoreFilterOpt === "function" ? ignoreFilterOpt : () => ignoreFilterOpt;
|
|
17961
18358
|
const ignored = getFilter ? (path) => {
|
|
@@ -18048,7 +18445,7 @@ function createChokidarWatcher(opts) {
|
|
|
18048
18445
|
}
|
|
18049
18446
|
function relativePathFromRoots2(absolute, absRoots) {
|
|
18050
18447
|
for (const root of absRoots) {
|
|
18051
|
-
const rel =
|
|
18448
|
+
const rel = relative7(root, absolute);
|
|
18052
18449
|
if (rel === "" || rel === ".") return "";
|
|
18053
18450
|
if (!rel.startsWith("..") && !rel.startsWith(`..${sep5}`)) {
|
|
18054
18451
|
return rel.split(sep5).join("/");
|
|
@@ -18459,9 +18856,9 @@ function resolveScanRoots(inputs) {
|
|
|
18459
18856
|
}
|
|
18460
18857
|
|
|
18461
18858
|
// core/runtime/reference-paths-walker.ts
|
|
18462
|
-
import { readdirSync as
|
|
18859
|
+
import { readdirSync as readdirSync9, statSync as statSync8 } from "fs";
|
|
18463
18860
|
import { homedir as osHomedir2 } from "os";
|
|
18464
|
-
import { isAbsolute as
|
|
18861
|
+
import { isAbsolute as isAbsolute11, join as join14, resolve as resolve33 } from "path";
|
|
18465
18862
|
var REFERENCE_WALK_MAX_FILES = 5e4;
|
|
18466
18863
|
var SKIPPED_DIR_NAMES = /* @__PURE__ */ new Set([
|
|
18467
18864
|
"node_modules",
|
|
@@ -18469,10 +18866,10 @@ var SKIPPED_DIR_NAMES = /* @__PURE__ */ new Set([
|
|
|
18469
18866
|
SKILL_MAP_DIR
|
|
18470
18867
|
]);
|
|
18471
18868
|
function resolveScanPath(raw, cwd) {
|
|
18472
|
-
if (raw.startsWith("~/")) return
|
|
18473
|
-
if (raw === "~") return
|
|
18474
|
-
if (
|
|
18475
|
-
return
|
|
18869
|
+
if (raw.startsWith("~/")) return resolve33(join14(osHomedir2(), raw.slice(2)));
|
|
18870
|
+
if (raw === "~") return resolve33(osHomedir2());
|
|
18871
|
+
if (isAbsolute11(raw)) return resolve33(raw);
|
|
18872
|
+
return resolve33(cwd, raw);
|
|
18476
18873
|
}
|
|
18477
18874
|
function walkReferencePaths(rawRoots, cwd) {
|
|
18478
18875
|
const paths = /* @__PURE__ */ new Set();
|
|
@@ -18494,7 +18891,7 @@ function walkInto(dir, out) {
|
|
|
18494
18891
|
if (out.size >= REFERENCE_WALK_MAX_FILES) return true;
|
|
18495
18892
|
let entries;
|
|
18496
18893
|
try {
|
|
18497
|
-
entries =
|
|
18894
|
+
entries = readdirSync9(dir, { withFileTypes: true });
|
|
18498
18895
|
} catch {
|
|
18499
18896
|
return false;
|
|
18500
18897
|
}
|
|
@@ -18513,15 +18910,15 @@ function walkInto(dir, out) {
|
|
|
18513
18910
|
}
|
|
18514
18911
|
function safeStat(path) {
|
|
18515
18912
|
try {
|
|
18516
|
-
return
|
|
18913
|
+
return statSync8(path);
|
|
18517
18914
|
} catch {
|
|
18518
18915
|
return null;
|
|
18519
18916
|
}
|
|
18520
18917
|
}
|
|
18521
18918
|
|
|
18522
18919
|
// core/runtime/active-provider-bootstrap.ts
|
|
18523
|
-
import { createInterface as
|
|
18524
|
-
import { isAbsolute as
|
|
18920
|
+
import { createInterface as createInterface4 } from "readline";
|
|
18921
|
+
import { isAbsolute as isAbsolute12, join as join15 } from "path";
|
|
18525
18922
|
async function bootstrapActiveProvider(opts) {
|
|
18526
18923
|
const fromCwd = resolveActiveProvider(opts.cwd, opts.providers);
|
|
18527
18924
|
if (fromCwd.source === "config") {
|
|
@@ -18572,7 +18969,7 @@ function aggregateDetected(cwd, effectiveRoots, cwdDetected, providers) {
|
|
|
18572
18969
|
out.push(id);
|
|
18573
18970
|
}
|
|
18574
18971
|
for (const root of effectiveRoots) {
|
|
18575
|
-
const absRoot =
|
|
18972
|
+
const absRoot = isAbsolute12(root) ? root : join15(cwd, root);
|
|
18576
18973
|
const r = resolveActiveProvider(absRoot, providers);
|
|
18577
18974
|
for (const id of r.detected) {
|
|
18578
18975
|
if (seen.has(id)) continue;
|
|
@@ -18672,7 +19069,7 @@ async function promptForLens(detected, stdin, stderr, warnGlyph) {
|
|
|
18672
19069
|
);
|
|
18673
19070
|
}
|
|
18674
19071
|
stderr.write(lines.join("\n") + "\n");
|
|
18675
|
-
const rl =
|
|
19072
|
+
const rl = createInterface4({ input: stdin, output: stderr });
|
|
18676
19073
|
try {
|
|
18677
19074
|
const answer = await new Promise(
|
|
18678
19075
|
(resolveP) => rl.question(SCAN_RUNNER_TEXTS.activeProviderPromptInput, resolveP)
|
|
@@ -18690,8 +19087,8 @@ async function promptForLens(detected, stdin, stderr, warnGlyph) {
|
|
|
18690
19087
|
}
|
|
18691
19088
|
|
|
18692
19089
|
// core/sqlite/db-drift-reset.ts
|
|
18693
|
-
import { existsSync as
|
|
18694
|
-
import { createInterface as
|
|
19090
|
+
import { existsSync as existsSync25 } from "fs";
|
|
19091
|
+
import { createInterface as createInterface5 } from "readline";
|
|
18695
19092
|
import { DatabaseSync as DatabaseSync8 } from "node:sqlite";
|
|
18696
19093
|
|
|
18697
19094
|
// core/sqlite/i18n/db-drift.texts.ts
|
|
@@ -18742,7 +19139,7 @@ function detectDriftReason(dbPath, currentVersion) {
|
|
|
18742
19139
|
return classifyFingerprint(dbPath).kind === "drift" ? "schema" : null;
|
|
18743
19140
|
}
|
|
18744
19141
|
function readScannedByVersion(dbPath) {
|
|
18745
|
-
if (dbPath === ":memory:" || !
|
|
19142
|
+
if (dbPath === ":memory:" || !existsSync25(dbPath)) return null;
|
|
18746
19143
|
let raw = null;
|
|
18747
19144
|
try {
|
|
18748
19145
|
raw = new DatabaseSync8(dbPath, { readOnly: true });
|
|
@@ -18775,7 +19172,7 @@ async function askDriftReset(dbVersion, reason, policy) {
|
|
|
18775
19172
|
hint: dim(DB_DRIFT_TEXTS.driftPromptHint)
|
|
18776
19173
|
})
|
|
18777
19174
|
);
|
|
18778
|
-
const rl =
|
|
19175
|
+
const rl = createInterface5({ input: policy.stdin, output: policy.stderr });
|
|
18779
19176
|
try {
|
|
18780
19177
|
const answer = await new Promise(
|
|
18781
19178
|
(resolveP) => rl.question(DB_DRIFT_TEXTS.driftPromptQuestion, resolveP)
|
|
@@ -19134,7 +19531,7 @@ var INIT_TEXTS = {
|
|
|
19134
19531
|
// cli/commands/init.ts
|
|
19135
19532
|
var InitCommand = class extends SmCommand {
|
|
19136
19533
|
static paths = [["init"]];
|
|
19137
|
-
static usage =
|
|
19534
|
+
static usage = Command18.Usage({
|
|
19138
19535
|
category: "Setup",
|
|
19139
19536
|
description: "Bootstrap the current project: scaffold .skill-map/, provision DB, run first scan.",
|
|
19140
19537
|
details: `
|
|
@@ -19153,16 +19550,16 @@ var InitCommand = class extends SmCommand {
|
|
|
19153
19550
|
["Preview what would be created", "$0 init --dry-run"]
|
|
19154
19551
|
]
|
|
19155
19552
|
});
|
|
19156
|
-
noScan =
|
|
19553
|
+
noScan = Option17.Boolean("--no-scan", false, {
|
|
19157
19554
|
description: "Skip the first scan after scaffolding."
|
|
19158
19555
|
});
|
|
19159
|
-
force =
|
|
19556
|
+
force = Option17.Boolean("--force", false, {
|
|
19160
19557
|
description: "Overwrite an existing settings.json / settings.local.json / .skillmapignore."
|
|
19161
19558
|
});
|
|
19162
|
-
strict =
|
|
19559
|
+
strict = Option17.Boolean("--strict", false, {
|
|
19163
19560
|
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."
|
|
19164
19561
|
});
|
|
19165
|
-
dryRun =
|
|
19562
|
+
dryRun = Option17.Boolean("-n,--dry-run", false, {
|
|
19166
19563
|
description: "Preview the scope provisioning without touching the filesystem or the DB. Honours --force for the would-overwrite preview. Skips the first scan unconditionally; dry-run never persists."
|
|
19167
19564
|
});
|
|
19168
19565
|
// CLI orchestrator: paths setup + dry-run branch (delegated to
|
|
@@ -19415,7 +19812,7 @@ async function ensureGitignoreEntries(scopeRoot, entries) {
|
|
|
19415
19812
|
}
|
|
19416
19813
|
|
|
19417
19814
|
// cli/commands/history.ts
|
|
19418
|
-
import { Command as
|
|
19815
|
+
import { Command as Command19, Option as Option18 } from "clipanion";
|
|
19419
19816
|
|
|
19420
19817
|
// cli/i18n/history.texts.ts
|
|
19421
19818
|
var HISTORY_TEXTS = {
|
|
@@ -19533,7 +19930,7 @@ function parseStatuses(input, stderr, ansi) {
|
|
|
19533
19930
|
}
|
|
19534
19931
|
var HistoryCommand = class extends SmCommand {
|
|
19535
19932
|
static paths = [["history"]];
|
|
19536
|
-
static usage =
|
|
19933
|
+
static usage = Command19.Usage({
|
|
19537
19934
|
category: "History",
|
|
19538
19935
|
description: "Filter execution records. --json emits an array conforming to execution-record.schema.json.",
|
|
19539
19936
|
details: `
|
|
@@ -19553,12 +19950,12 @@ var HistoryCommand = class extends SmCommand {
|
|
|
19553
19950
|
["Machine-readable, scoped to one node", "$0 history -n skills/foo.md --json"]
|
|
19554
19951
|
]
|
|
19555
19952
|
});
|
|
19556
|
-
node =
|
|
19557
|
-
action =
|
|
19558
|
-
status =
|
|
19559
|
-
since =
|
|
19560
|
-
until =
|
|
19561
|
-
limit =
|
|
19953
|
+
node = Option18.String("-n", { required: false });
|
|
19954
|
+
action = Option18.String("--action", { required: false });
|
|
19955
|
+
status = Option18.String("--status", { required: false });
|
|
19956
|
+
since = Option18.String("--since", { required: false });
|
|
19957
|
+
until = Option18.String("--until", { required: false });
|
|
19958
|
+
limit = Option18.String("--limit", { required: false });
|
|
19562
19959
|
// CLI list verb: many optional filter flags (`--node`, `--action`,
|
|
19563
19960
|
// `--status`, `--since`, `--until`, `--limit`, `--json`, `--quiet`)
|
|
19564
19961
|
// each adding a guarded mutation to the filter or render path. Each
|
|
@@ -19609,7 +20006,7 @@ var HistoryCommand = class extends SmCommand {
|
|
|
19609
20006
|
};
|
|
19610
20007
|
var HistoryStatsCommand = class extends SmCommand {
|
|
19611
20008
|
static paths = [["history", "stats"]];
|
|
19612
|
-
static usage =
|
|
20009
|
+
static usage = Command19.Usage({
|
|
19613
20010
|
category: "History",
|
|
19614
20011
|
description: "Aggregate counts, tokens, periods, top nodes, and error rates over state_executions. --json conforms to history-stats.schema.json.",
|
|
19615
20012
|
details: `
|
|
@@ -19627,10 +20024,10 @@ var HistoryStatsCommand = class extends SmCommand {
|
|
|
19627
20024
|
["Top 5 nodes, JSON", "$0 history stats --top 5 --json"]
|
|
19628
20025
|
]
|
|
19629
20026
|
});
|
|
19630
|
-
since =
|
|
19631
|
-
until =
|
|
19632
|
-
period =
|
|
19633
|
-
top =
|
|
20027
|
+
since = Option18.String("--since", { required: false });
|
|
20028
|
+
until = Option18.String("--until", { required: false });
|
|
20029
|
+
period = Option18.String("--period", { required: false });
|
|
20030
|
+
top = Option18.String("--top", { required: false });
|
|
19634
20031
|
// CLI stats verb: range parsing + window flags + period flag + JSON
|
|
19635
20032
|
// branch + per-period iteration. Each branch is a single-purpose
|
|
19636
20033
|
// gate; the data work lives in `aggregateHistoryStats`.
|
|
@@ -19931,20 +20328,20 @@ function trimMs(iso) {
|
|
|
19931
20328
|
|
|
19932
20329
|
// cli/commands/jobs.ts
|
|
19933
20330
|
import { unlink as unlink2 } from "fs/promises";
|
|
19934
|
-
import { relative as
|
|
19935
|
-
import { Command as
|
|
20331
|
+
import { relative as relative8 } from "path";
|
|
20332
|
+
import { Command as Command20, Option as Option19 } from "clipanion";
|
|
19936
20333
|
|
|
19937
20334
|
// kernel/jobs/orphan-files.ts
|
|
19938
|
-
import { readdirSync as
|
|
19939
|
-
import { join as join17, resolve as
|
|
20335
|
+
import { readdirSync as readdirSync10, statSync as statSync9 } from "fs";
|
|
20336
|
+
import { join as join17, resolve as resolve34 } from "path";
|
|
19940
20337
|
function findOrphanJobFiles(jobsDir, referencedPaths) {
|
|
19941
20338
|
let entries;
|
|
19942
20339
|
try {
|
|
19943
|
-
const stat3 =
|
|
20340
|
+
const stat3 = statSync9(jobsDir);
|
|
19944
20341
|
if (!stat3.isDirectory()) {
|
|
19945
20342
|
return { orphanFilePaths: [], referencedCount: referencedPaths.size };
|
|
19946
20343
|
}
|
|
19947
|
-
entries =
|
|
20344
|
+
entries = readdirSync10(jobsDir, { withFileTypes: true });
|
|
19948
20345
|
} catch {
|
|
19949
20346
|
return { orphanFilePaths: [], referencedCount: referencedPaths.size };
|
|
19950
20347
|
}
|
|
@@ -19954,7 +20351,7 @@ function findOrphanJobFiles(jobsDir, referencedPaths) {
|
|
|
19954
20351
|
if (!entry.isFile()) continue;
|
|
19955
20352
|
const name = entry.name;
|
|
19956
20353
|
if (!name.endsWith(".md")) continue;
|
|
19957
|
-
const abs =
|
|
20354
|
+
const abs = resolve34(join17(jobsDir, name));
|
|
19958
20355
|
if (!referencedPaths.has(abs)) orphans.push(abs);
|
|
19959
20356
|
}
|
|
19960
20357
|
orphans.sort();
|
|
@@ -19983,7 +20380,7 @@ var JOBS_TEXTS = {
|
|
|
19983
20380
|
// cli/commands/jobs.ts
|
|
19984
20381
|
var JobPruneCommand = class extends SmCommand {
|
|
19985
20382
|
static paths = [["job", "prune"]];
|
|
19986
|
-
static usage =
|
|
20383
|
+
static usage = Command20.Usage({
|
|
19987
20384
|
category: "Jobs",
|
|
19988
20385
|
description: "Retention GC for completed / failed jobs (per config policy). --orphan-files removes MD files with no DB row.",
|
|
19989
20386
|
details: `
|
|
@@ -20010,10 +20407,10 @@ var JobPruneCommand = class extends SmCommand {
|
|
|
20010
20407
|
["Preview without touching the DB", "$0 job prune --dry-run --json"]
|
|
20011
20408
|
]
|
|
20012
20409
|
});
|
|
20013
|
-
orphanFiles =
|
|
20410
|
+
orphanFiles = Option19.Boolean("--orphan-files", false, {
|
|
20014
20411
|
description: "Also remove MD files in .skill-map/jobs/ that have no matching state_jobs row."
|
|
20015
20412
|
});
|
|
20016
|
-
dryRun =
|
|
20413
|
+
dryRun = Option19.Boolean("-n,--dry-run", false, {
|
|
20017
20414
|
description: "Report what would be pruned without touching the DB or filesystem."
|
|
20018
20415
|
});
|
|
20019
20416
|
async run() {
|
|
@@ -20096,7 +20493,7 @@ var JobPruneCommand = class extends SmCommand {
|
|
|
20096
20493
|
let removed = 0;
|
|
20097
20494
|
for (const p of paths) {
|
|
20098
20495
|
try {
|
|
20099
|
-
assertContained(jobsDir,
|
|
20496
|
+
assertContained(jobsDir, relative8(jobsDir, p));
|
|
20100
20497
|
} catch {
|
|
20101
20498
|
continue;
|
|
20102
20499
|
}
|
|
@@ -20151,7 +20548,7 @@ function formatPolicy(seconds) {
|
|
|
20151
20548
|
}
|
|
20152
20549
|
|
|
20153
20550
|
// cli/commands/list.ts
|
|
20154
|
-
import { Command as
|
|
20551
|
+
import { Command as Command21, Option as Option20 } from "clipanion";
|
|
20155
20552
|
|
|
20156
20553
|
// cli/i18n/list.texts.ts
|
|
20157
20554
|
var LIST_TEXTS = {
|
|
@@ -20186,7 +20583,7 @@ var SORT_BY = {
|
|
|
20186
20583
|
var PATH_COL_MAX_WIDTH = 60;
|
|
20187
20584
|
var ListCommand = class extends SmCommand {
|
|
20188
20585
|
static paths = [["list"]];
|
|
20189
|
-
static usage =
|
|
20586
|
+
static usage = Command21.Usage({
|
|
20190
20587
|
category: "Browse",
|
|
20191
20588
|
description: "Tabular listing of nodes. --json emits an array conforming to node.schema.json.",
|
|
20192
20589
|
details: `
|
|
@@ -20210,11 +20607,11 @@ var ListCommand = class extends SmCommand {
|
|
|
20210
20607
|
["Filter by tag", "$0 list --tag urgent"]
|
|
20211
20608
|
]
|
|
20212
20609
|
});
|
|
20213
|
-
kind =
|
|
20214
|
-
issue =
|
|
20215
|
-
sortBy =
|
|
20216
|
-
limit =
|
|
20217
|
-
tag =
|
|
20610
|
+
kind = Option20.String("--kind", { required: false });
|
|
20611
|
+
issue = Option20.Boolean("--issue", false);
|
|
20612
|
+
sortBy = Option20.String("--sort-by", { required: false });
|
|
20613
|
+
limit = Option20.String("--limit", { required: false });
|
|
20614
|
+
tag = Option20.String("--tag", { required: false });
|
|
20218
20615
|
async run() {
|
|
20219
20616
|
const stderrAnsi = this.ansiFor("stderr");
|
|
20220
20617
|
const flags = this.#parseFlags(stderrAnsi);
|
|
@@ -20398,7 +20795,7 @@ function formatDataRow(r, w, ansi) {
|
|
|
20398
20795
|
}
|
|
20399
20796
|
|
|
20400
20797
|
// cli/commands/orphans.ts
|
|
20401
|
-
import { Command as
|
|
20798
|
+
import { Command as Command22, Option as Option21 } from "clipanion";
|
|
20402
20799
|
|
|
20403
20800
|
// cli/i18n/orphans.texts.ts
|
|
20404
20801
|
var ORPHANS_TEXTS = {
|
|
@@ -20481,7 +20878,7 @@ function isStringArray2(v) {
|
|
|
20481
20878
|
}
|
|
20482
20879
|
var OrphansCommand = class extends SmCommand {
|
|
20483
20880
|
static paths = [["orphans"]];
|
|
20484
|
-
static usage =
|
|
20881
|
+
static usage = Command22.Usage({
|
|
20485
20882
|
category: "Browse",
|
|
20486
20883
|
description: "List orphan / auto-rename issues from the last scan. --json emits an array conforming to issue.schema.json.",
|
|
20487
20884
|
details: `
|
|
@@ -20496,7 +20893,7 @@ var OrphansCommand = class extends SmCommand {
|
|
|
20496
20893
|
["Just the ambiguous ones, JSON", "$0 orphans --kind ambiguous --json"]
|
|
20497
20894
|
]
|
|
20498
20895
|
});
|
|
20499
|
-
kind =
|
|
20896
|
+
kind = Option21.String("--kind", { required: false });
|
|
20500
20897
|
async run() {
|
|
20501
20898
|
const stderrAnsi = this.ansiFor("stderr");
|
|
20502
20899
|
let analyzerFilter = null;
|
|
@@ -20545,7 +20942,7 @@ var OrphansCommand = class extends SmCommand {
|
|
|
20545
20942
|
};
|
|
20546
20943
|
var OrphansReconcileCommand = class extends SmCommand {
|
|
20547
20944
|
static paths = [["orphans", "reconcile"]];
|
|
20548
|
-
static usage =
|
|
20945
|
+
static usage = Command22.Usage({
|
|
20549
20946
|
category: "Browse",
|
|
20550
20947
|
description: "Migrate state_* FKs from an orphan path to a live node, resolving the orphan issue.",
|
|
20551
20948
|
details: `
|
|
@@ -20561,9 +20958,9 @@ var OrphansReconcileCommand = class extends SmCommand {
|
|
|
20561
20958
|
["Reattach orphan history", "$0 orphans reconcile skills/old.md --to skills/new.md"]
|
|
20562
20959
|
]
|
|
20563
20960
|
});
|
|
20564
|
-
orphanPath =
|
|
20565
|
-
to =
|
|
20566
|
-
dryRun =
|
|
20961
|
+
orphanPath = Option21.String({ required: true });
|
|
20962
|
+
to = Option21.String("--to", { required: true });
|
|
20963
|
+
dryRun = Option21.Boolean("-n,--dry-run", false);
|
|
20567
20964
|
async run() {
|
|
20568
20965
|
const dbPath = resolveDbPath({ db: this.db, ...defaultRuntimeContext() });
|
|
20569
20966
|
const exit = requireDbOrExit(dbPath, this.context.stderr);
|
|
@@ -20664,7 +21061,7 @@ var OrphansReconcileCommand = class extends SmCommand {
|
|
|
20664
21061
|
};
|
|
20665
21062
|
var OrphansUndoRenameCommand = class extends SmCommand {
|
|
20666
21063
|
static paths = [["orphans", "undo-rename"]];
|
|
20667
|
-
static usage =
|
|
21064
|
+
static usage = Command22.Usage({
|
|
20668
21065
|
category: "Browse",
|
|
20669
21066
|
description: "Reverse a medium- or ambiguous-confidence auto-rename. Migrates state_* FKs back, emits a new orphan on the prior path.",
|
|
20670
21067
|
details: `
|
|
@@ -20684,10 +21081,10 @@ var OrphansUndoRenameCommand = class extends SmCommand {
|
|
|
20684
21081
|
["Undo an ambiguous, picking a candidate", "$0 orphans undo-rename skills/new.md --from skills/old-a.md"]
|
|
20685
21082
|
]
|
|
20686
21083
|
});
|
|
20687
|
-
newPath =
|
|
20688
|
-
from =
|
|
20689
|
-
force =
|
|
20690
|
-
dryRun =
|
|
21084
|
+
newPath = Option21.String({ required: true });
|
|
21085
|
+
from = Option21.String("--from", { required: false });
|
|
21086
|
+
force = Option21.Boolean("--force", false);
|
|
21087
|
+
dryRun = Option21.Boolean("-n,--dry-run", false);
|
|
20691
21088
|
async run() {
|
|
20692
21089
|
const dbPath = resolveDbPath({ db: this.db, ...defaultRuntimeContext() });
|
|
20693
21090
|
const exit = requireDbOrExit(dbPath, this.context.stderr);
|
|
@@ -20910,7 +21307,7 @@ var ORPHANS_COMMANDS = [
|
|
|
20910
21307
|
];
|
|
20911
21308
|
|
|
20912
21309
|
// cli/commands/plugins/list.ts
|
|
20913
|
-
import { Command as
|
|
21310
|
+
import { Command as Command23, Option as Option22 } from "clipanion";
|
|
20914
21311
|
|
|
20915
21312
|
// cli/i18n/plugins.texts.ts
|
|
20916
21313
|
var PLUGINS_TEXTS = {
|
|
@@ -21181,9 +21578,9 @@ function sortPluginsForPresentation(plugins) {
|
|
|
21181
21578
|
}
|
|
21182
21579
|
|
|
21183
21580
|
// cli/commands/plugins/shared.ts
|
|
21184
|
-
import { resolve as
|
|
21581
|
+
import { resolve as resolve35 } from "path";
|
|
21185
21582
|
function resolveSearchPaths2(opts, cwd) {
|
|
21186
|
-
if (opts.pluginDir) return [
|
|
21583
|
+
if (opts.pluginDir) return [resolve35(opts.pluginDir)];
|
|
21187
21584
|
return [defaultProjectPluginsDir({ cwd })];
|
|
21188
21585
|
}
|
|
21189
21586
|
async function buildResolver() {
|
|
@@ -21301,7 +21698,7 @@ function wrapText(text, maxWidth) {
|
|
|
21301
21698
|
// cli/commands/plugins/list.ts
|
|
21302
21699
|
var PluginsListCommand = class extends SmCommand {
|
|
21303
21700
|
static paths = [["plugins", "list"]];
|
|
21304
|
-
static usage =
|
|
21701
|
+
static usage = Command23.Usage({
|
|
21305
21702
|
category: "Plugins",
|
|
21306
21703
|
description: "List discovered plugins, or one plugin's extensions.",
|
|
21307
21704
|
details: `
|
|
@@ -21312,8 +21709,8 @@ var PluginsListCommand = class extends SmCommand {
|
|
|
21312
21709
|
\`<plugin>/<ext>\` id is rejected with a redirect to \`sm plugins show\`.
|
|
21313
21710
|
`
|
|
21314
21711
|
});
|
|
21315
|
-
id =
|
|
21316
|
-
pluginDir =
|
|
21712
|
+
id = Option22.String({ required: false });
|
|
21713
|
+
pluginDir = Option22.String("--plugin-dir", { required: false });
|
|
21317
21714
|
async run() {
|
|
21318
21715
|
const plugins = await loadAll({ pluginDir: this.pluginDir });
|
|
21319
21716
|
const resolveEnabled = await buildResolver();
|
|
@@ -21555,10 +21952,10 @@ function renderExtensionItems(items) {
|
|
|
21555
21952
|
}
|
|
21556
21953
|
|
|
21557
21954
|
// cli/commands/plugins/show.ts
|
|
21558
|
-
import { Command as
|
|
21955
|
+
import { Command as Command24, Option as Option23 } from "clipanion";
|
|
21559
21956
|
var PluginsShowCommand = class extends SmCommand {
|
|
21560
21957
|
static paths = [["plugins", "show"]];
|
|
21561
|
-
static usage =
|
|
21958
|
+
static usage = Command24.Usage({
|
|
21562
21959
|
category: "Plugins",
|
|
21563
21960
|
description: "Show a single extension's detail.",
|
|
21564
21961
|
details: `
|
|
@@ -21571,8 +21968,8 @@ var PluginsShowCommand = class extends SmCommand {
|
|
|
21571
21968
|
accept resolves cleanly here too.
|
|
21572
21969
|
`
|
|
21573
21970
|
});
|
|
21574
|
-
id =
|
|
21575
|
-
pluginDir =
|
|
21971
|
+
id = Option23.String({ required: true });
|
|
21972
|
+
pluginDir = Option23.String("--plugin-dir", { required: false });
|
|
21576
21973
|
async run() {
|
|
21577
21974
|
const plugins = await loadAll({ pluginDir: this.pluginDir });
|
|
21578
21975
|
const resolveEnabled = await buildResolver();
|
|
@@ -21713,7 +22110,7 @@ function renderExtensionFields(meta) {
|
|
|
21713
22110
|
}
|
|
21714
22111
|
|
|
21715
22112
|
// cli/commands/plugins/doctor.ts
|
|
21716
|
-
import { Command as
|
|
22113
|
+
import { Command as Command25, Option as Option24 } from "clipanion";
|
|
21717
22114
|
var CONTRIB_ERROR_SAMPLE_CAP = 3;
|
|
21718
22115
|
var STATUS_ORDER = [
|
|
21719
22116
|
"enabled",
|
|
@@ -21726,12 +22123,12 @@ var STATUS_ORDER = [
|
|
|
21726
22123
|
];
|
|
21727
22124
|
var PluginsDoctorCommand = class extends SmCommand {
|
|
21728
22125
|
static paths = [["plugins", "doctor"]];
|
|
21729
|
-
static usage =
|
|
22126
|
+
static usage = Command25.Usage({
|
|
21730
22127
|
category: "Plugins",
|
|
21731
22128
|
description: "Run the full load pass and summarise by failure mode.",
|
|
21732
22129
|
details: "Exit code 0 when every plugin loads or is intentionally disabled; 1 when any plugin is in an error / incompat state."
|
|
21733
22130
|
});
|
|
21734
|
-
pluginDir =
|
|
22131
|
+
pluginDir = Option24.String("--plugin-dir", { required: false });
|
|
21735
22132
|
async run() {
|
|
21736
22133
|
const plugins = await loadAll({ pluginDir: this.pluginDir });
|
|
21737
22134
|
const resolveEnabled = await buildResolver();
|
|
@@ -22184,13 +22581,13 @@ function groupContributionErrorsByPlugin(errors) {
|
|
|
22184
22581
|
}
|
|
22185
22582
|
|
|
22186
22583
|
// cli/commands/plugins/toggle.ts
|
|
22187
|
-
import { Command as
|
|
22584
|
+
import { Command as Command26, Option as Option25 } from "clipanion";
|
|
22188
22585
|
var TogglePluginsBase = class extends SmCommand {
|
|
22189
|
-
all =
|
|
22190
|
-
yes =
|
|
22586
|
+
all = Option25.Boolean("--all", false);
|
|
22587
|
+
yes = Option25.Boolean("--yes,-y", false, {
|
|
22191
22588
|
description: "Skip the interactive confirm when a bare plugin id (or --all) fans the toggle out across multiple extensions."
|
|
22192
22589
|
});
|
|
22193
|
-
ids =
|
|
22590
|
+
ids = Option25.Rest({ name: "ids" });
|
|
22194
22591
|
async toggle(enabled) {
|
|
22195
22592
|
const verb = enabled ? "enable" : "disable";
|
|
22196
22593
|
const stderrAnsi = this.ansiFor("stderr");
|
|
@@ -22413,7 +22810,7 @@ async function purgeContributionsFor(adapter, id) {
|
|
|
22413
22810
|
}
|
|
22414
22811
|
var PluginsEnableCommand = class extends TogglePluginsBase {
|
|
22415
22812
|
static paths = [["plugins", "enable"]];
|
|
22416
|
-
static usage =
|
|
22813
|
+
static usage = Command26.Usage({
|
|
22417
22814
|
category: "Plugins",
|
|
22418
22815
|
description: "Enable one or more extensions (or --all). Persists in config_plugins.",
|
|
22419
22816
|
details: `
|
|
@@ -22441,7 +22838,7 @@ var PluginsEnableCommand = class extends TogglePluginsBase {
|
|
|
22441
22838
|
};
|
|
22442
22839
|
var PluginsDisableCommand = class extends TogglePluginsBase {
|
|
22443
22840
|
static paths = [["plugins", "disable"]];
|
|
22444
|
-
static usage =
|
|
22841
|
+
static usage = Command26.Usage({
|
|
22445
22842
|
category: "Plugins",
|
|
22446
22843
|
description: "Disable one or more extensions (or --all). Persists in config_plugins; does not delete files.",
|
|
22447
22844
|
details: `
|
|
@@ -22496,9 +22893,9 @@ function resolveBareToggle(id, catalogue) {
|
|
|
22496
22893
|
}
|
|
22497
22894
|
|
|
22498
22895
|
// cli/commands/plugins/create.ts
|
|
22499
|
-
import { existsSync as
|
|
22500
|
-
import { dirname as
|
|
22501
|
-
import { Command as
|
|
22896
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync5, writeFileSync } from "fs";
|
|
22897
|
+
import { dirname as dirname18, join as join18, resolve as resolve36 } from "path";
|
|
22898
|
+
import { Command as Command27, Option as Option26 } from "clipanion";
|
|
22502
22899
|
|
|
22503
22900
|
// cli/commands/plugins/scaffold/action.ts
|
|
22504
22901
|
function indexStub(extId) {
|
|
@@ -22903,7 +23300,7 @@ function generateScaffold(kind, pluginId, specVersion) {
|
|
|
22903
23300
|
// cli/commands/plugins/create.ts
|
|
22904
23301
|
var PluginsCreateCommand = class extends SmCommand {
|
|
22905
23302
|
static paths = [["plugins", "create"]];
|
|
22906
|
-
static usage =
|
|
23303
|
+
static usage = Command27.Usage({
|
|
22907
23304
|
category: "Plugins",
|
|
22908
23305
|
description: "Scaffold a new plugin directory.",
|
|
22909
23306
|
details: "Emits plugin.json + a per-kind extension stub + README. `<kind>` is one of: provider, extractor, analyzer, action, formatter, hook. The extractor stub ships one view contribution (slot `card.footer.left`) and one setting (`string-list`); edit to taste. Use `sm plugins slots list` to browse the slot / input-type catalog.",
|
|
@@ -22915,10 +23312,10 @@ var PluginsCreateCommand = class extends SmCommand {
|
|
|
22915
23312
|
});
|
|
22916
23313
|
// First positional: the extension kind (required). Declared before
|
|
22917
23314
|
// `pluginId` so clipanion assigns it the first positional slot.
|
|
22918
|
-
kind =
|
|
22919
|
-
pluginId =
|
|
22920
|
-
at =
|
|
22921
|
-
force =
|
|
23315
|
+
kind = Option26.String({ required: true, name: "kind" });
|
|
23316
|
+
pluginId = Option26.String({ required: true, name: "plugin-id" });
|
|
23317
|
+
at = Option26.String("--at", { required: false });
|
|
23318
|
+
force = Option26.Boolean("--force", false);
|
|
22922
23319
|
async run() {
|
|
22923
23320
|
const ansi = this.ansiFor("stderr");
|
|
22924
23321
|
const errGlyph = ansi.red("\u2715");
|
|
@@ -22947,8 +23344,8 @@ var PluginsCreateCommand = class extends SmCommand {
|
|
|
22947
23344
|
const kind = this.kind;
|
|
22948
23345
|
const ctx = defaultRuntimeContext();
|
|
22949
23346
|
const baseDir = defaultProjectPluginsDir(ctx);
|
|
22950
|
-
const targetDir = this.at ?
|
|
22951
|
-
if (
|
|
23347
|
+
const targetDir = this.at ? resolve36(this.at) : join18(baseDir, this.pluginId);
|
|
23348
|
+
if (existsSync26(targetDir) && !this.force) {
|
|
22952
23349
|
this.printer.error(
|
|
22953
23350
|
tx(PLUGINS_TEXTS.createRefuseOverwrite, {
|
|
22954
23351
|
glyph: errGlyph,
|
|
@@ -22962,7 +23359,7 @@ var PluginsCreateCommand = class extends SmCommand {
|
|
|
22962
23359
|
const files = generateScaffold(kind, this.pluginId, specVersion);
|
|
22963
23360
|
for (const file of files) {
|
|
22964
23361
|
const abs = join18(targetDir, file.relPath);
|
|
22965
|
-
mkdirSync5(
|
|
23362
|
+
mkdirSync5(dirname18(abs), { recursive: true });
|
|
22966
23363
|
writeFileSync(abs, file.contents);
|
|
22967
23364
|
}
|
|
22968
23365
|
const mainFile = `${kind}s/${this.pluginId}-${kind}/index.js`;
|
|
@@ -22977,7 +23374,7 @@ var PluginsCreateCommand = class extends SmCommand {
|
|
|
22977
23374
|
};
|
|
22978
23375
|
|
|
22979
23376
|
// cli/commands/plugins/slots.ts
|
|
22980
|
-
import { Command as
|
|
23377
|
+
import { Command as Command28 } from "clipanion";
|
|
22981
23378
|
|
|
22982
23379
|
// cli/commands/plugins/slots-catalog.ts
|
|
22983
23380
|
var VIEW_SLOTS_CATALOG = [
|
|
@@ -23013,7 +23410,7 @@ var INPUT_TYPES_CATALOG = [
|
|
|
23013
23410
|
// cli/commands/plugins/slots.ts
|
|
23014
23411
|
var PluginsSlotsListCommand = class extends SmCommand {
|
|
23015
23412
|
static paths = [["plugins", "slots", "list"]];
|
|
23016
|
-
static usage =
|
|
23413
|
+
static usage = Command28.Usage({
|
|
23017
23414
|
category: "Plugins",
|
|
23018
23415
|
description: "Print the closed catalogs of view slots and input-types.",
|
|
23019
23416
|
details: "Read-only. Use this when picking a slot / input-type for a new plugin."
|
|
@@ -23062,15 +23459,15 @@ var PluginsSlotsListCommand = class extends SmCommand {
|
|
|
23062
23459
|
};
|
|
23063
23460
|
|
|
23064
23461
|
// cli/commands/plugins/upgrade.ts
|
|
23065
|
-
import { Command as
|
|
23462
|
+
import { Command as Command29, Option as Option27 } from "clipanion";
|
|
23066
23463
|
var PluginsUpgradeCommand = class extends SmCommand {
|
|
23067
23464
|
static paths = [["plugins", "upgrade"]];
|
|
23068
|
-
static usage =
|
|
23465
|
+
static usage = Command29.Usage({
|
|
23069
23466
|
category: "Plugins",
|
|
23070
23467
|
description: "Apply catalog migrations to plugin manifests.",
|
|
23071
23468
|
details: "No migrations registered against catalog v1.0.0 yet; this verb is a no-op today. The structure exists so future slot renames / deprecations land without spec churn."
|
|
23072
23469
|
});
|
|
23073
|
-
pluginId =
|
|
23470
|
+
pluginId = Option27.String({ required: false, name: "plugin-id" });
|
|
23074
23471
|
async run() {
|
|
23075
23472
|
this.printer.data(
|
|
23076
23473
|
"sm plugins upgrade: no migrations registered for catalog v1.0.0.\n All loaded plugins are catalog-current.\n Run `sm plugins doctor` to surface any incompatible-catalog status.\n"
|
|
@@ -23080,7 +23477,7 @@ var PluginsUpgradeCommand = class extends SmCommand {
|
|
|
23080
23477
|
};
|
|
23081
23478
|
|
|
23082
23479
|
// cli/commands/plugins/config.ts
|
|
23083
|
-
import { Command as
|
|
23480
|
+
import { Command as Command30, Option as Option28 } from "clipanion";
|
|
23084
23481
|
|
|
23085
23482
|
// cli/i18n/plugins-config.texts.ts
|
|
23086
23483
|
var PLUGINS_CONFIG_TEXTS = {
|
|
@@ -23121,7 +23518,7 @@ var PLUGINS_CONFIG_TEXTS = {
|
|
|
23121
23518
|
// cli/commands/plugins/config.ts
|
|
23122
23519
|
var PluginsConfigCommand = class extends SmCommand {
|
|
23123
23520
|
static paths = [["plugins", "config"]];
|
|
23124
|
-
static usage =
|
|
23521
|
+
static usage = Command30.Usage({
|
|
23125
23522
|
category: "Plugins",
|
|
23126
23523
|
description: "Read or write an extension's declared settings.",
|
|
23127
23524
|
details: `
|
|
@@ -23136,13 +23533,13 @@ var PluginsConfigCommand = class extends SmCommand {
|
|
|
23136
23533
|
Secret values are shown as <redacted>. Run \`sm scan\` to apply.
|
|
23137
23534
|
`
|
|
23138
23535
|
});
|
|
23139
|
-
id =
|
|
23140
|
-
settingId =
|
|
23141
|
-
value =
|
|
23142
|
-
reset =
|
|
23536
|
+
id = Option28.String({ required: true });
|
|
23537
|
+
settingId = Option28.String({ required: false });
|
|
23538
|
+
value = Option28.String({ required: false });
|
|
23539
|
+
reset = Option28.Boolean("--reset", false, {
|
|
23143
23540
|
description: "Remove the override for <settingId> so the manifest default applies."
|
|
23144
23541
|
});
|
|
23145
|
-
pluginDir =
|
|
23542
|
+
pluginDir = Option28.String("--plugin-dir", { required: false });
|
|
23146
23543
|
// Read-only when listing; the write / reset paths emit their own
|
|
23147
23544
|
// receipt. `sm config` exempts the config family from "done in <…>";
|
|
23148
23545
|
// mirror that here for the read path. The write path keeps the line.
|
|
@@ -23463,8 +23860,8 @@ var PLUGIN_COMMANDS = [
|
|
|
23463
23860
|
|
|
23464
23861
|
// cli/commands/refresh.ts
|
|
23465
23862
|
import { readFile as readFile4 } from "fs/promises";
|
|
23466
|
-
import { resolve as
|
|
23467
|
-
import { Command as
|
|
23863
|
+
import { resolve as resolve37 } from "path";
|
|
23864
|
+
import { Command as Command31, Option as Option29 } from "clipanion";
|
|
23468
23865
|
|
|
23469
23866
|
// cli/i18n/refresh.texts.ts
|
|
23470
23867
|
var REFRESH_TEXTS = {
|
|
@@ -23520,7 +23917,7 @@ var REFRESH_TEXTS = {
|
|
|
23520
23917
|
// cli/commands/refresh.ts
|
|
23521
23918
|
var RefreshCommand = class extends SmCommand {
|
|
23522
23919
|
static paths = [["refresh"]];
|
|
23523
|
-
static usage =
|
|
23920
|
+
static usage = Command31.Usage({
|
|
23524
23921
|
category: "Scan",
|
|
23525
23922
|
description: "Refresh enrichment rows: granular (single node) or batch (every stale row).",
|
|
23526
23923
|
details: `
|
|
@@ -23542,11 +23939,11 @@ var RefreshCommand = class extends SmCommand {
|
|
|
23542
23939
|
["Refresh every node with stale enrichments", "$0 refresh --stale"]
|
|
23543
23940
|
]
|
|
23544
23941
|
});
|
|
23545
|
-
nodePath =
|
|
23546
|
-
stale =
|
|
23942
|
+
nodePath = Option29.String({ name: "node", required: false });
|
|
23943
|
+
stale = Option29.Boolean("--stale", false, {
|
|
23547
23944
|
description: "Refresh every node carrying a stale enrichment row (no-op in this revision; reserved for future Action-prob enrichments)."
|
|
23548
23945
|
});
|
|
23549
|
-
noPlugins =
|
|
23946
|
+
noPlugins = Option29.Boolean("--no-plugins", false, {
|
|
23550
23947
|
description: "Skip drop-in plugin discovery; use only the built-in extractor set."
|
|
23551
23948
|
});
|
|
23552
23949
|
// The remaining cyclomatic count comes from CLI ergonomics that don't
|
|
@@ -23771,7 +24168,7 @@ var RefreshCommand = class extends SmCommand {
|
|
|
23771
24168
|
let body;
|
|
23772
24169
|
try {
|
|
23773
24170
|
assertContained(cwd, node.path);
|
|
23774
|
-
const raw = await readFile4(
|
|
24171
|
+
const raw = await readFile4(resolve37(cwd, node.path), "utf8");
|
|
23775
24172
|
body = stripFrontmatterFence(raw);
|
|
23776
24173
|
} catch (err) {
|
|
23777
24174
|
if (!this.json) {
|
|
@@ -23844,13 +24241,13 @@ var IntentionalFailCommand = class extends SmCommand {
|
|
|
23844
24241
|
setTimeout(() => {
|
|
23845
24242
|
throw new Error(INTENTIONAL_FAIL_TEXTS.errorMessage);
|
|
23846
24243
|
}, 0);
|
|
23847
|
-
await new Promise((
|
|
24244
|
+
await new Promise((resolve44) => setTimeout(resolve44, 5e3));
|
|
23848
24245
|
return ExitCode.Issues;
|
|
23849
24246
|
}
|
|
23850
24247
|
};
|
|
23851
24248
|
|
|
23852
24249
|
// cli/commands/scan.ts
|
|
23853
|
-
import { Command as
|
|
24250
|
+
import { Command as Command33, Option as Option31 } from "clipanion";
|
|
23854
24251
|
|
|
23855
24252
|
// kernel/util/format-bytes.ts
|
|
23856
24253
|
var UNITS = ["B", "KiB", "MiB", "GiB", "TiB", "PiB"];
|
|
@@ -24009,10 +24406,10 @@ var SCAN_TEXTS = {
|
|
|
24009
24406
|
};
|
|
24010
24407
|
|
|
24011
24408
|
// cli/commands/watch.ts
|
|
24012
|
-
import { Command as
|
|
24409
|
+
import { Command as Command32, Option as Option30 } from "clipanion";
|
|
24013
24410
|
|
|
24014
24411
|
// core/watcher/runtime.ts
|
|
24015
|
-
import { dirname as
|
|
24412
|
+
import { dirname as dirname19, isAbsolute as isAbsolute13, relative as relative9, resolve as resolve38, sep as sep6 } from "path";
|
|
24016
24413
|
|
|
24017
24414
|
// core/runtime/fresh-resolver.ts
|
|
24018
24415
|
async function buildFreshResolver(deps) {
|
|
@@ -24058,7 +24455,7 @@ function applyPriorStateToRunOptions(runOptions, priorState, changedPaths) {
|
|
|
24058
24455
|
}
|
|
24059
24456
|
}
|
|
24060
24457
|
function toIncrementalPaths(events, roots, cwd) {
|
|
24061
|
-
const absRoots = roots.map((r) =>
|
|
24458
|
+
const absRoots = roots.map((r) => isAbsolute13(r) ? r : resolve38(cwd, r));
|
|
24062
24459
|
const changed = /* @__PURE__ */ new Set();
|
|
24063
24460
|
const removed = /* @__PURE__ */ new Set();
|
|
24064
24461
|
for (const ev of events) {
|
|
@@ -24072,8 +24469,8 @@ function toIncrementalPaths(events, roots, cwd) {
|
|
|
24072
24469
|
}
|
|
24073
24470
|
function relativeFromRoots2(absolute, absRoots) {
|
|
24074
24471
|
for (const root of absRoots) {
|
|
24075
|
-
const rel =
|
|
24076
|
-
if (rel === "" || rel.startsWith("..") ||
|
|
24472
|
+
const rel = relative9(root, absolute);
|
|
24473
|
+
if (rel === "" || rel.startsWith("..") || isAbsolute13(rel)) continue;
|
|
24077
24474
|
return rel.split(sep6).join("/");
|
|
24078
24475
|
}
|
|
24079
24476
|
return null;
|
|
@@ -24316,7 +24713,7 @@ function createWatcherRuntime(opts) {
|
|
|
24316
24713
|
roots: [
|
|
24317
24714
|
cwd,
|
|
24318
24715
|
// parent of `.skillmapignore`
|
|
24319
|
-
|
|
24716
|
+
dirname19(settingsPath)
|
|
24320
24717
|
// parent of `.skill-map/settings.json`
|
|
24321
24718
|
],
|
|
24322
24719
|
cwd,
|
|
@@ -24606,7 +25003,7 @@ async function runWatchLoop(opts) {
|
|
|
24606
25003
|
}
|
|
24607
25004
|
var WatchCommand = class extends SmCommand {
|
|
24608
25005
|
static paths = [["watch"]];
|
|
24609
|
-
static usage =
|
|
25006
|
+
static usage = Command32.Usage({
|
|
24610
25007
|
category: "Scan",
|
|
24611
25008
|
description: "Watch roots and run an incremental scan after each debounced batch of filesystem events.",
|
|
24612
25009
|
details: `
|
|
@@ -24630,25 +25027,25 @@ var WatchCommand = class extends SmCommand {
|
|
|
24630
25027
|
["Stream ScanResult per batch as ndjson", "$0 watch --json"]
|
|
24631
25028
|
]
|
|
24632
25029
|
});
|
|
24633
|
-
roots =
|
|
24634
|
-
noTokens =
|
|
25030
|
+
roots = Option30.Rest({ name: "roots" });
|
|
25031
|
+
noTokens = Option30.Boolean("--no-tokens", false, {
|
|
24635
25032
|
description: "Skip per-node token counts (cl100k_base BPE)."
|
|
24636
25033
|
});
|
|
24637
|
-
strict =
|
|
25034
|
+
strict = Option30.Boolean("--strict", false, {
|
|
24638
25035
|
description: "Promote frontmatter-validation findings from warn to error inside each batch. Does not change the watcher exit code."
|
|
24639
25036
|
});
|
|
24640
|
-
noPlugins =
|
|
25037
|
+
noPlugins = Option30.Boolean("--no-plugins", false, {
|
|
24641
25038
|
description: "Skip drop-in plugin discovery for the watcher session."
|
|
24642
25039
|
});
|
|
24643
|
-
maxConsecutiveFailures =
|
|
25040
|
+
maxConsecutiveFailures = Option30.String("--max-consecutive-failures", {
|
|
24644
25041
|
required: false,
|
|
24645
25042
|
description: "Shut down with exit 2 after N consecutive batch failures (default 5; 0 disables the breaker)."
|
|
24646
25043
|
});
|
|
24647
|
-
maxScan =
|
|
25044
|
+
maxScan = Option30.String("--max-scan", {
|
|
24648
25045
|
required: false,
|
|
24649
25046
|
description: "Per-batch override of scan.maxScan (default 50000), the WALK-INTAKE ceiling. The scan walks, parses, analyzes, and reference-validates the full corpus up to this number. Bidirectional: raises OR lowers the ceiling. When a batch hits it, additional files are dropped in stable order and the UI surfaces the persistent truncation banner. Validation: integer >= 1."
|
|
24650
25047
|
});
|
|
24651
|
-
maxNodes =
|
|
25048
|
+
maxNodes = Option30.String("--max-nodes", {
|
|
24652
25049
|
required: false,
|
|
24653
25050
|
description: "Per-batch override of scan.maxNodes (default 256), the MAP RENDER cap (pure metadata): it does NOT bound the scan, only the graph projection. Bidirectional: raises OR lowers the render cap. Validation: integer >= 1."
|
|
24654
25051
|
});
|
|
@@ -24735,7 +25132,7 @@ function parseMaxNodesLimit(raw, stderr, noColor) {
|
|
|
24735
25132
|
// cli/commands/scan.ts
|
|
24736
25133
|
var ScanCommand = class extends SmCommand {
|
|
24737
25134
|
static paths = [["scan"]];
|
|
24738
|
-
static usage =
|
|
25135
|
+
static usage = Command33.Usage({
|
|
24739
25136
|
category: "Scan",
|
|
24740
25137
|
description: "Scan roots for markdown nodes, run extractors and analyzers.",
|
|
24741
25138
|
details: `
|
|
@@ -24770,39 +25167,39 @@ var ScanCommand = class extends SmCommand {
|
|
|
24770
25167
|
["What would the next incremental scan persist?", "$0 scan --changed -n --json"]
|
|
24771
25168
|
]
|
|
24772
25169
|
});
|
|
24773
|
-
roots =
|
|
24774
|
-
noBuiltIns =
|
|
25170
|
+
roots = Option31.Rest({ name: "roots" });
|
|
25171
|
+
noBuiltIns = Option31.Boolean("--no-built-ins", false, {
|
|
24775
25172
|
description: "Skip the built-in extension set. Yields a zero-filled ScanResult (kernel-empty-boot parity); skips DB persistence."
|
|
24776
25173
|
});
|
|
24777
|
-
noPlugins =
|
|
25174
|
+
noPlugins = Option31.Boolean("--no-plugins", false, {
|
|
24778
25175
|
description: "Skip drop-in plugin discovery. Only the built-in set runs. Combine with --no-built-ins for a fully empty pipeline."
|
|
24779
25176
|
});
|
|
24780
|
-
noTokens =
|
|
25177
|
+
noTokens = Option31.Boolean("--no-tokens", false, {
|
|
24781
25178
|
description: "Skip per-node token counts (cl100k_base BPE). Leaves node.tokens undefined; spec-valid since the field is optional."
|
|
24782
25179
|
});
|
|
24783
|
-
dryRun =
|
|
25180
|
+
dryRun = Option31.Boolean("-n,--dry-run", false, {
|
|
24784
25181
|
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."
|
|
24785
25182
|
});
|
|
24786
|
-
changed =
|
|
25183
|
+
changed = Option31.Boolean("--changed", false, {
|
|
24787
25184
|
description: "Incremental scan: reuse unchanged nodes from the persisted prior snapshot. Degrades to a full scan if no prior snapshot exists."
|
|
24788
25185
|
});
|
|
24789
|
-
allowEmpty =
|
|
25186
|
+
allowEmpty = Option31.Boolean("--allow-empty", false, {
|
|
24790
25187
|
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."
|
|
24791
25188
|
});
|
|
24792
|
-
strict =
|
|
25189
|
+
strict = Option31.Boolean("--strict", false, {
|
|
24793
25190
|
description: "Promote frontmatter-validation findings from warn to error (exit code 1 on any violation). Overrides scan.strict from config when both are set."
|
|
24794
25191
|
});
|
|
24795
|
-
watch =
|
|
25192
|
+
watch = Option31.Boolean("--watch", false, {
|
|
24796
25193
|
description: "Long-running mode: watch the roots and trigger an incremental scan after each debounced batch of filesystem events. Alias of `sm watch`."
|
|
24797
25194
|
});
|
|
24798
|
-
yes =
|
|
25195
|
+
yes = Option31.Boolean("--yes", false, {
|
|
24799
25196
|
description: "Non-interactive mode. For ambiguous activeProvider auto-detect, multiple provider markers (.claude/, .codex/, AGENTS.md, .cursor/) under the scan tree exit non-zero instead of prompting; set the lens manually via `sm config set activeProvider <id>` and re-run. Also auto-confirms the pre-1.0 schema-drift rebuild (when the DB was written by a different skill-map major.minor it is deleted and regenerated) instead of prompting."
|
|
24800
25197
|
});
|
|
24801
|
-
maxScan =
|
|
25198
|
+
maxScan = Option31.String("--max-scan", {
|
|
24802
25199
|
required: false,
|
|
24803
25200
|
description: "Per-invocation override of `scan.maxScan` (default 50000). The WALK-INTAKE ceiling: the scan walks, parses, analyzes, and reference-validates the full corpus up to this number. Bidirectional: raises OR lowers the ceiling. When the walker hits it, additional files are dropped in stable order and the scan is marked truncated in scan_meta (the UI raises a persistent banner pointing at the .skillmapignore editor in Settings \u2192 Project). Validation: integer >= 1."
|
|
24804
25201
|
});
|
|
24805
|
-
maxNodes =
|
|
25202
|
+
maxNodes = Option31.String("--max-nodes", {
|
|
24806
25203
|
required: false,
|
|
24807
25204
|
description: "Per-invocation override of `scan.maxNodes` (default 256). The MAP RENDER cap (pure metadata): it does NOT bound the scan, only how many nodes the graph view projects onto the canvas. Bidirectional: raises OR lowers the render cap. Validation: integer >= 1."
|
|
24808
25205
|
});
|
|
@@ -25163,10 +25560,10 @@ function capOverrides(caps) {
|
|
|
25163
25560
|
|
|
25164
25561
|
// cli/commands/scan-compare.ts
|
|
25165
25562
|
import { access, readFile as readFile5 } from "fs/promises";
|
|
25166
|
-
import { Command as
|
|
25563
|
+
import { Command as Command34, Option as Option32 } from "clipanion";
|
|
25167
25564
|
var ScanCompareCommand = class extends SmCommand {
|
|
25168
25565
|
static paths = [["scan", "compare-with"]];
|
|
25169
|
-
static usage =
|
|
25566
|
+
static usage = Command34.Usage({
|
|
25170
25567
|
category: "Scan",
|
|
25171
25568
|
description: "Run a fresh scan in memory and emit a delta against the saved ScanResult dump at <dump>. Read-only.",
|
|
25172
25569
|
details: `
|
|
@@ -25194,15 +25591,15 @@ var ScanCompareCommand = class extends SmCommand {
|
|
|
25194
25591
|
["JSON output for tooling", "$0 scan compare-with baseline.json --json"]
|
|
25195
25592
|
]
|
|
25196
25593
|
});
|
|
25197
|
-
dump =
|
|
25198
|
-
roots =
|
|
25199
|
-
noTokens =
|
|
25594
|
+
dump = Option32.String({ required: true });
|
|
25595
|
+
roots = Option32.Rest({ name: "roots" });
|
|
25596
|
+
noTokens = Option32.Boolean("--no-tokens", false, {
|
|
25200
25597
|
description: "Skip per-node token counts during the fresh scan."
|
|
25201
25598
|
});
|
|
25202
|
-
strict =
|
|
25599
|
+
strict = Option32.Boolean("--strict", false, {
|
|
25203
25600
|
description: "Promote layered-config warnings and frontmatter-validation findings from warn to error."
|
|
25204
25601
|
});
|
|
25205
|
-
noPlugins =
|
|
25602
|
+
noPlugins = Option32.Boolean("--no-plugins", false, {
|
|
25206
25603
|
description: "Skip drop-in plugin discovery."
|
|
25207
25604
|
});
|
|
25208
25605
|
// Cyclomatic count comes from CLI ergonomics: 3 distinct try/catch
|
|
@@ -25408,13 +25805,13 @@ function renderDeltaIssues(issues) {
|
|
|
25408
25805
|
|
|
25409
25806
|
// cli/commands/serve.ts
|
|
25410
25807
|
import { spawn as spawn2 } from "child_process";
|
|
25411
|
-
import { existsSync as
|
|
25412
|
-
import { Command as
|
|
25808
|
+
import { existsSync as existsSync32 } from "fs";
|
|
25809
|
+
import { Command as Command35, Option as Option33 } from "clipanion";
|
|
25413
25810
|
|
|
25414
25811
|
// kernel/util/dev-mode.ts
|
|
25415
25812
|
import { sep as sep7 } from "path";
|
|
25416
|
-
import { fileURLToPath as
|
|
25417
|
-
var SELF_PATH =
|
|
25813
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
25814
|
+
var SELF_PATH = fileURLToPath6(import.meta.url);
|
|
25418
25815
|
var IS_DEV_BUILD = isDevBuildFromPath(SELF_PATH, sep7);
|
|
25419
25816
|
function isDevBuildFromPath(filePath, separator = sep7) {
|
|
25420
25817
|
return !filePath.includes(`${separator}node_modules${separator}`);
|
|
@@ -26370,7 +26767,7 @@ function contentTypeFor(format) {
|
|
|
26370
26767
|
}
|
|
26371
26768
|
|
|
26372
26769
|
// server/health.ts
|
|
26373
|
-
import { existsSync as
|
|
26770
|
+
import { existsSync as existsSync27 } from "fs";
|
|
26374
26771
|
var FALLBACK_SCHEMA_VERSION = "1";
|
|
26375
26772
|
function buildHealth(deps) {
|
|
26376
26773
|
const dev = isDevBuild();
|
|
@@ -26379,7 +26776,7 @@ function buildHealth(deps) {
|
|
|
26379
26776
|
schemaVersion: FALLBACK_SCHEMA_VERSION,
|
|
26380
26777
|
specVersion: deps.specVersion,
|
|
26381
26778
|
implVersion: VERSION,
|
|
26382
|
-
db:
|
|
26779
|
+
db: existsSync27(deps.dbPath) ? "present" : "missing",
|
|
26383
26780
|
cwd: deps.cwd,
|
|
26384
26781
|
dbPath: deps.dbPath,
|
|
26385
26782
|
// Only emit when truthy so a published install keeps the wire
|
|
@@ -26512,9 +26909,9 @@ import { HTTPException as HTTPException8 } from "hono/http-exception";
|
|
|
26512
26909
|
// server/node-body.ts
|
|
26513
26910
|
import { constants as fsConstants2 } from "fs";
|
|
26514
26911
|
import { open } from "fs/promises";
|
|
26515
|
-
import { isAbsolute as
|
|
26912
|
+
import { isAbsolute as isAbsolute14, resolve as resolvePath2, relative as relativePath, sep as sep8 } from "path";
|
|
26516
26913
|
async function readNodeBody(cwd, relPath) {
|
|
26517
|
-
if (
|
|
26914
|
+
if (isAbsolute14(relPath)) return null;
|
|
26518
26915
|
const absRoot = resolvePath2(cwd);
|
|
26519
26916
|
const absFile = resolvePath2(absRoot, relPath);
|
|
26520
26917
|
const rel = relativePath(absRoot, absFile);
|
|
@@ -27501,12 +27898,12 @@ var parsePatchBody2 = makeBodyValidator(PATCH_BODY_SCHEMA, {
|
|
|
27501
27898
|
import { HTTPException as HTTPException12 } from "hono/http-exception";
|
|
27502
27899
|
|
|
27503
27900
|
// server/util/skillmapignore-io.ts
|
|
27504
|
-
import { existsSync as
|
|
27505
|
-
import { resolve as
|
|
27901
|
+
import { existsSync as existsSync28, readFileSync as readFileSync18, writeFileSync as writeFileSync2 } from "fs";
|
|
27902
|
+
import { resolve as resolve39 } from "path";
|
|
27506
27903
|
var IGNORE_FILENAME2 = ".skillmapignore";
|
|
27507
27904
|
function readPatterns(cwd) {
|
|
27508
|
-
const path =
|
|
27509
|
-
if (!
|
|
27905
|
+
const path = resolve39(cwd, IGNORE_FILENAME2);
|
|
27906
|
+
if (!existsSync28(path)) return [];
|
|
27510
27907
|
let raw;
|
|
27511
27908
|
try {
|
|
27512
27909
|
raw = readFileSync18(path, "utf8");
|
|
@@ -27516,8 +27913,8 @@ function readPatterns(cwd) {
|
|
|
27516
27913
|
return raw.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#"));
|
|
27517
27914
|
}
|
|
27518
27915
|
function writePatterns(cwd, nextPatterns) {
|
|
27519
|
-
const path =
|
|
27520
|
-
const prior =
|
|
27916
|
+
const path = resolve39(cwd, IGNORE_FILENAME2);
|
|
27917
|
+
const prior = existsSync28(path) ? safeRead(path) : "";
|
|
27521
27918
|
const content = buildContent(prior, nextPatterns);
|
|
27522
27919
|
writeFileSync2(path, content, "utf8");
|
|
27523
27920
|
}
|
|
@@ -27678,7 +28075,7 @@ var parsePatchBody3 = makeBodyValidator(PATCH_BODY_SCHEMA2, {
|
|
|
27678
28075
|
});
|
|
27679
28076
|
|
|
27680
28077
|
// server/routes/project-preferences.ts
|
|
27681
|
-
import { statSync as
|
|
28078
|
+
import { statSync as statSync10 } from "fs";
|
|
27682
28079
|
import { HTTPException as HTTPException13 } from "hono/http-exception";
|
|
27683
28080
|
function registerProjectPreferencesRoute(app, deps) {
|
|
27684
28081
|
app.get("/api/project-preferences", (c) => {
|
|
@@ -27854,7 +28251,7 @@ function formatPathDetail(path, cwd) {
|
|
|
27854
28251
|
function isExistingDirectory(entry, cwd) {
|
|
27855
28252
|
const abs = resolveScanPath(entry, cwd);
|
|
27856
28253
|
try {
|
|
27857
|
-
return
|
|
28254
|
+
return statSync10(abs).isDirectory();
|
|
27858
28255
|
} catch {
|
|
27859
28256
|
return false;
|
|
27860
28257
|
}
|
|
@@ -27896,7 +28293,7 @@ var parsePatchBody4 = makeBodyValidator(PATCH_BODY_SCHEMA3, {
|
|
|
27896
28293
|
});
|
|
27897
28294
|
|
|
27898
28295
|
// server/routes/active-provider.ts
|
|
27899
|
-
import { existsSync as
|
|
28296
|
+
import { existsSync as existsSync29 } from "fs";
|
|
27900
28297
|
import { HTTPException as HTTPException14 } from "hono/http-exception";
|
|
27901
28298
|
function registerActiveProviderRoute(app, deps) {
|
|
27902
28299
|
app.get("/api/active-provider", async (c) => {
|
|
@@ -27944,7 +28341,7 @@ function applyLensSwitch(deps, newValue) {
|
|
|
27944
28341
|
});
|
|
27945
28342
|
}
|
|
27946
28343
|
const dbPath = resolveDbPath({ db: void 0, cwd });
|
|
27947
|
-
if (!
|
|
28344
|
+
if (!existsSync29(dbPath)) return { dropped: null };
|
|
27948
28345
|
const dropResult = dropScanZone(dbPath);
|
|
27949
28346
|
return {
|
|
27950
28347
|
dropped: {
|
|
@@ -27974,7 +28371,7 @@ var parsePatchBody5 = makeBodyValidator(PATCH_BODY_SCHEMA4, {
|
|
|
27974
28371
|
|
|
27975
28372
|
// server/routes/actions.ts
|
|
27976
28373
|
import { HTTPException as HTTPException16 } from "hono/http-exception";
|
|
27977
|
-
import { resolve as
|
|
28374
|
+
import { resolve as resolve40 } from "path";
|
|
27978
28375
|
|
|
27979
28376
|
// server/routes/node-loader.ts
|
|
27980
28377
|
import { HTTPException as HTTPException15 } from "hono/http-exception";
|
|
@@ -28034,7 +28431,7 @@ function registerActionsRoutes(app, deps) {
|
|
|
28034
28431
|
let absPath;
|
|
28035
28432
|
try {
|
|
28036
28433
|
assertContained(deps.runtimeContext.cwd, node.path);
|
|
28037
|
-
absPath =
|
|
28434
|
+
absPath = resolve40(deps.runtimeContext.cwd, node.path);
|
|
28038
28435
|
} catch (err) {
|
|
28039
28436
|
throw new HTTPException16(400, { message: formatErrorMessage(err) });
|
|
28040
28437
|
}
|
|
@@ -28142,14 +28539,14 @@ async function withScanMutex(fn) {
|
|
|
28142
28539
|
if (inFlight !== null) {
|
|
28143
28540
|
throw new ScanBusyError();
|
|
28144
28541
|
}
|
|
28145
|
-
let
|
|
28542
|
+
let resolve44;
|
|
28146
28543
|
inFlight = new Promise((r) => {
|
|
28147
|
-
|
|
28544
|
+
resolve44 = r;
|
|
28148
28545
|
});
|
|
28149
28546
|
try {
|
|
28150
28547
|
return await fn();
|
|
28151
28548
|
} finally {
|
|
28152
|
-
|
|
28549
|
+
resolve44();
|
|
28153
28550
|
inFlight = null;
|
|
28154
28551
|
}
|
|
28155
28552
|
}
|
|
@@ -28665,7 +29062,7 @@ function registerUpdateStatusRoute(app, deps) {
|
|
|
28665
29062
|
}
|
|
28666
29063
|
|
|
28667
29064
|
// server/static.ts
|
|
28668
|
-
import { existsSync as
|
|
29065
|
+
import { existsSync as existsSync30 } from "fs";
|
|
28669
29066
|
import { readFile as readFile6 } from "fs/promises";
|
|
28670
29067
|
import { extname, join as join19 } from "path";
|
|
28671
29068
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
@@ -28720,7 +29117,7 @@ function createSpaFallback(opts) {
|
|
|
28720
29117
|
if (c.req.method !== "GET" && c.req.method !== "HEAD") return c.notFound();
|
|
28721
29118
|
if (opts.uiDist === null) return htmlResponse(c, placeholder);
|
|
28722
29119
|
const indexPath = join19(opts.uiDist, INDEX_HTML);
|
|
28723
|
-
if (!
|
|
29120
|
+
if (!existsSync30(indexPath)) return htmlResponse(c, placeholder);
|
|
28724
29121
|
return fileResponse(c, indexPath);
|
|
28725
29122
|
};
|
|
28726
29123
|
}
|
|
@@ -29446,9 +29843,9 @@ function validateNoUi(noUi, uiDist) {
|
|
|
29446
29843
|
}
|
|
29447
29844
|
|
|
29448
29845
|
// server/paths.ts
|
|
29449
|
-
import { existsSync as
|
|
29450
|
-
import { dirname as
|
|
29451
|
-
import { fileURLToPath as
|
|
29846
|
+
import { existsSync as existsSync31, statSync as statSync11 } from "fs";
|
|
29847
|
+
import { dirname as dirname20, isAbsolute as isAbsolute15, join as join20, resolve as resolve41 } from "path";
|
|
29848
|
+
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
29452
29849
|
var DEFAULT_UI_REL = join20("ui", "dist", "ui", "browser");
|
|
29453
29850
|
var PACKAGE_UI_REL = "ui";
|
|
29454
29851
|
var INDEX_HTML2 = "index.html";
|
|
@@ -29458,13 +29855,13 @@ function resolveDefaultUiDist(ctx) {
|
|
|
29458
29855
|
return walkUpForUi(ctx.cwd);
|
|
29459
29856
|
}
|
|
29460
29857
|
function resolveExplicitUiDist(ctx, raw) {
|
|
29461
|
-
return
|
|
29858
|
+
return isAbsolute15(raw) ? raw : resolve41(ctx.cwd, raw);
|
|
29462
29859
|
}
|
|
29463
29860
|
function isUiBundleDir(path) {
|
|
29464
|
-
if (!
|
|
29861
|
+
if (!existsSync31(path)) return false;
|
|
29465
29862
|
try {
|
|
29466
|
-
if (!
|
|
29467
|
-
return
|
|
29863
|
+
if (!statSync11(path).isDirectory()) return false;
|
|
29864
|
+
return existsSync31(join20(path, INDEX_HTML2));
|
|
29468
29865
|
} catch {
|
|
29469
29866
|
return false;
|
|
29470
29867
|
}
|
|
@@ -29472,7 +29869,7 @@ function isUiBundleDir(path) {
|
|
|
29472
29869
|
function resolvePackageBundledUi() {
|
|
29473
29870
|
let here;
|
|
29474
29871
|
try {
|
|
29475
|
-
here =
|
|
29872
|
+
here = dirname20(fileURLToPath7(import.meta.url));
|
|
29476
29873
|
} catch {
|
|
29477
29874
|
return null;
|
|
29478
29875
|
}
|
|
@@ -29485,18 +29882,18 @@ function resolvePackageBundledUiFrom(here) {
|
|
|
29485
29882
|
if (isUiBundleDir(candidate)) return candidate;
|
|
29486
29883
|
const distHere = join20(current, "dist", PACKAGE_UI_REL);
|
|
29487
29884
|
if (isUiBundleDir(distHere)) return distHere;
|
|
29488
|
-
const parent =
|
|
29885
|
+
const parent = dirname20(current);
|
|
29489
29886
|
if (parent === current) return null;
|
|
29490
29887
|
current = parent;
|
|
29491
29888
|
}
|
|
29492
29889
|
return null;
|
|
29493
29890
|
}
|
|
29494
29891
|
function walkUpForUi(startDir) {
|
|
29495
|
-
let current =
|
|
29892
|
+
let current = resolve41(startDir);
|
|
29496
29893
|
for (let i = 0; i < 64; i++) {
|
|
29497
29894
|
const candidate = join20(current, DEFAULT_UI_REL);
|
|
29498
29895
|
if (isUiBundleDir(candidate)) return candidate;
|
|
29499
|
-
const parent =
|
|
29896
|
+
const parent = dirname20(current);
|
|
29500
29897
|
if (parent === current) return null;
|
|
29501
29898
|
current = parent;
|
|
29502
29899
|
}
|
|
@@ -29792,169 +30189,10 @@ var SERVE_TEXTS = {
|
|
|
29792
30189
|
driftDeclined: "{{glyph}} sm serve: cache rebuild declined; the {{dbVersion}} cache cannot be reused on {{currentVersion}} ({{reason}}).\n {{hint}}\n"
|
|
29793
30190
|
};
|
|
29794
30191
|
|
|
29795
|
-
// cli/util/serve-banner.ts
|
|
29796
|
-
import { relative as relative8, isAbsolute as isAbsolute15 } from "path";
|
|
29797
|
-
var ESC2 = {
|
|
29798
|
-
reset: "\x1B[0m",
|
|
29799
|
-
bold: "\x1B[1m",
|
|
29800
|
-
dim: "\x1B[2m",
|
|
29801
|
-
underline: "\x1B[4m",
|
|
29802
|
-
/** 256-color violet (xterm 141). */
|
|
29803
|
-
violet: "\x1B[38;5;141m",
|
|
29804
|
-
/** 256-color green (xterm 42). */
|
|
29805
|
-
green: "\x1B[38;5;42m",
|
|
29806
|
-
/** 256-color yellow (xterm 214), matches `cli/util/ansi.ts:yellow`. */
|
|
29807
|
-
yellow: "\x1B[38;5;214m"
|
|
29808
|
-
};
|
|
29809
|
-
var LOGO_LINES = [
|
|
29810
|
-
" ____ _ _ _ _ __ __ ",
|
|
29811
|
-
" / ___|| | _(_) | | | \\/ | __ _ _ __ ",
|
|
29812
|
-
" \\___ \\| |/ / | | | | |\\/| |/ _` | '_ \\ ",
|
|
29813
|
-
" ___) | <| | | | | | | | (_| | |_) |",
|
|
29814
|
-
" |____/|_|\\_\\_|_|_| |_| |_|\\__,_| .__/ ",
|
|
29815
|
-
" |_| "
|
|
29816
|
-
];
|
|
29817
|
-
var LOGO_WIDTH = 40;
|
|
29818
|
-
function renderBanner(input) {
|
|
29819
|
-
const url = `http://${input.host}:${input.port}`;
|
|
29820
|
-
const dbDisplay = formatDbPath(input.dbPath, input.cwd);
|
|
29821
|
-
const browserLine = input.openBrowser ? "Opening browser\u2026 Press Ctrl+C to stop." : `Visit ${url}/ in your browser. Press Ctrl+C to stop.`;
|
|
29822
|
-
if (!input.isTTY) {
|
|
29823
|
-
return renderFlat({
|
|
29824
|
-
host: input.host,
|
|
29825
|
-
port: input.port,
|
|
29826
|
-
dbPath: input.dbPath,
|
|
29827
|
-
openBrowser: input.openBrowser,
|
|
29828
|
-
dev: input.dev === true
|
|
29829
|
-
});
|
|
29830
|
-
}
|
|
29831
|
-
return renderFiglet({
|
|
29832
|
-
version: input.version,
|
|
29833
|
-
url,
|
|
29834
|
-
dbDisplay,
|
|
29835
|
-
pathDisplay: formatCwdPath(input.cwd),
|
|
29836
|
-
browserLine,
|
|
29837
|
-
colorEnabled: input.colorEnabled,
|
|
29838
|
-
referencePaths: input.referencePaths ?? [],
|
|
29839
|
-
dev: input.dev === true
|
|
29840
|
-
});
|
|
29841
|
-
}
|
|
29842
|
-
function resolveColorEnabled(opts) {
|
|
29843
|
-
if (opts.noColorFlag) return false;
|
|
29844
|
-
const noColor = opts.env["NO_COLOR"];
|
|
29845
|
-
if (noColor !== void 0 && noColor !== "") return false;
|
|
29846
|
-
const forceColor = opts.env["FORCE_COLOR"];
|
|
29847
|
-
if (forceColor !== void 0 && forceColor !== "") return true;
|
|
29848
|
-
return opts.isTTY;
|
|
29849
|
-
}
|
|
29850
|
-
function renderFlat(input) {
|
|
29851
|
-
const safeHost = sanitizeForTerminal(input.host);
|
|
29852
|
-
const safeDb = sanitizeForTerminal(input.dbPath);
|
|
29853
|
-
const url = `http://${safeHost}:${input.port}`;
|
|
29854
|
-
const devSuffix = input.dev ? " [dev]" : "";
|
|
29855
|
-
const linesOut = [];
|
|
29856
|
-
linesOut.push(`sm serve${devSuffix}: listening on ${url} (db=${safeDb})`);
|
|
29857
|
-
if (input.openBrowser) {
|
|
29858
|
-
linesOut.push(`sm serve: opening ${url}/ in your browser. Press Ctrl+C to stop.`);
|
|
29859
|
-
} else {
|
|
29860
|
-
linesOut.push(`sm serve: visit ${url}/ in your browser. Press Ctrl+C to stop.`);
|
|
29861
|
-
}
|
|
29862
|
-
return linesOut.join("\n") + "\n";
|
|
29863
|
-
}
|
|
29864
|
-
function renderLogoBlock(input) {
|
|
29865
|
-
const { dimOpen, dimClose, violetOpen, violetClose } = resolveAnsi(input.colorEnabled);
|
|
29866
|
-
const logoLines = LOGO_LINES.map((line) => `${violetOpen}${line}${violetClose}`);
|
|
29867
|
-
const versionText = `v${input.version}`;
|
|
29868
|
-
const versionPad = Math.max(0, LOGO_WIDTH - versionText.length);
|
|
29869
|
-
const versionLine = `${" ".repeat(versionPad)}${dimOpen}${versionText}${dimClose}`;
|
|
29870
|
-
return `${logoLines.join("\n")}
|
|
29871
|
-
|
|
29872
|
-
${versionLine}
|
|
29873
|
-
|
|
29874
|
-
`;
|
|
29875
|
-
}
|
|
29876
|
-
function renderFiglet(input) {
|
|
29877
|
-
const {
|
|
29878
|
-
dimOpen,
|
|
29879
|
-
dimClose,
|
|
29880
|
-
greenUnderline,
|
|
29881
|
-
greenUnderlineClose,
|
|
29882
|
-
violetOpen,
|
|
29883
|
-
violetClose,
|
|
29884
|
-
yellowOpen,
|
|
29885
|
-
yellowClose
|
|
29886
|
-
} = resolveAnsi(input.colorEnabled);
|
|
29887
|
-
const logoLines = LOGO_LINES.map((line) => `${violetOpen}${line}${violetClose}`);
|
|
29888
|
-
const versionText = `v${input.version}`;
|
|
29889
|
-
const devText = "[dev]";
|
|
29890
|
-
const versionWidth = input.dev ? devText.length : versionText.length;
|
|
29891
|
-
const versionPad = Math.max(0, LOGO_WIDTH - versionWidth);
|
|
29892
|
-
const versionLine = input.dev ? `${" ".repeat(versionPad)}${yellowOpen}${devText}${yellowClose}` : `${" ".repeat(versionPad)}${dimOpen}${versionText}${dimClose}`;
|
|
29893
|
-
const lines = [];
|
|
29894
|
-
lines.push(...logoLines);
|
|
29895
|
-
lines.push("");
|
|
29896
|
-
lines.push(versionLine);
|
|
29897
|
-
lines.push("");
|
|
29898
|
-
lines.push(` ${dimOpen}Server${dimClose} ${greenUnderline}${input.url}${greenUnderlineClose}`);
|
|
29899
|
-
lines.push(` ${dimOpen}Path${dimClose} ${input.pathDisplay}`);
|
|
29900
|
-
lines.push(` ${dimOpen}DB${dimClose} ${input.dbDisplay}`);
|
|
29901
|
-
lines.push(...renderListRows("Refs", input.referencePaths, dimOpen, dimClose));
|
|
29902
|
-
lines.push("");
|
|
29903
|
-
lines.push(` ${dimOpen}${input.browserLine}${dimClose}`);
|
|
29904
|
-
lines.push("");
|
|
29905
|
-
return lines.join("\n") + "\n";
|
|
29906
|
-
}
|
|
29907
|
-
function renderListRows(label, values, dimOpen, dimClose) {
|
|
29908
|
-
if (values.length === 0) return [];
|
|
29909
|
-
const out = [];
|
|
29910
|
-
const labelPad = " ".repeat(Math.max(1, 9 - label.length));
|
|
29911
|
-
const continuationPad = " ".repeat(11);
|
|
29912
|
-
out.push(` ${dimOpen}${label}${dimClose}${labelPad}${sanitizeForTerminal(values[0])}`);
|
|
29913
|
-
for (let i = 1; i < values.length; i += 1) {
|
|
29914
|
-
out.push(`${continuationPad}${sanitizeForTerminal(values[i])}`);
|
|
29915
|
-
}
|
|
29916
|
-
return out;
|
|
29917
|
-
}
|
|
29918
|
-
var EMPTY_ANSI = {
|
|
29919
|
-
dimOpen: "",
|
|
29920
|
-
dimClose: "",
|
|
29921
|
-
greenUnderline: "",
|
|
29922
|
-
greenUnderlineClose: "",
|
|
29923
|
-
violetOpen: "",
|
|
29924
|
-
violetClose: "",
|
|
29925
|
-
yellowOpen: "",
|
|
29926
|
-
yellowClose: ""
|
|
29927
|
-
};
|
|
29928
|
-
var ENABLED_ANSI = {
|
|
29929
|
-
dimOpen: ESC2.dim,
|
|
29930
|
-
dimClose: ESC2.reset,
|
|
29931
|
-
greenUnderline: `${ESC2.green}${ESC2.underline}`,
|
|
29932
|
-
greenUnderlineClose: ESC2.reset,
|
|
29933
|
-
violetOpen: ESC2.violet,
|
|
29934
|
-
violetClose: ESC2.reset,
|
|
29935
|
-
yellowOpen: ESC2.yellow,
|
|
29936
|
-
yellowClose: ESC2.reset
|
|
29937
|
-
};
|
|
29938
|
-
function resolveAnsi(colorEnabled) {
|
|
29939
|
-
return colorEnabled ? ENABLED_ANSI : EMPTY_ANSI;
|
|
29940
|
-
}
|
|
29941
|
-
function formatDbPath(dbPath, cwd) {
|
|
29942
|
-
const safe = sanitizeForTerminal(dbPath);
|
|
29943
|
-
if (!isAbsolute15(safe)) return safe;
|
|
29944
|
-
const rel = relative8(cwd, safe);
|
|
29945
|
-
if (rel === "" || rel.startsWith("..") || isAbsolute15(rel)) {
|
|
29946
|
-
return safe;
|
|
29947
|
-
}
|
|
29948
|
-
return rel;
|
|
29949
|
-
}
|
|
29950
|
-
function formatCwdPath(cwd) {
|
|
29951
|
-
return sanitizeForTerminal(cwd);
|
|
29952
|
-
}
|
|
29953
|
-
|
|
29954
30192
|
// cli/commands/serve.ts
|
|
29955
30193
|
var ServeCommand = class extends SmCommand {
|
|
29956
30194
|
static paths = [["serve"]];
|
|
29957
|
-
static usage =
|
|
30195
|
+
static usage = Command35.Usage({
|
|
29958
30196
|
category: "Setup",
|
|
29959
30197
|
description: "Start the Hono BFF (single-port: REST + WebSocket + SPA bundle).",
|
|
29960
30198
|
details: `
|
|
@@ -29978,18 +30216,18 @@ var ServeCommand = class extends SmCommand {
|
|
|
29978
30216
|
["Point at a pre-built UI bundle", "$0 serve --ui-dist ./ui/dist/browser"]
|
|
29979
30217
|
]
|
|
29980
30218
|
});
|
|
29981
|
-
port =
|
|
30219
|
+
port = Option33.String("--port", {
|
|
29982
30220
|
required: false,
|
|
29983
30221
|
description: "Listening port (default 4242). 0 = OS-assigned."
|
|
29984
30222
|
});
|
|
29985
|
-
host =
|
|
30223
|
+
host = Option33.String("--host", {
|
|
29986
30224
|
required: false,
|
|
29987
30225
|
description: "Listening host (default 127.0.0.1). Loopback-only enforced when --dev-cors is set."
|
|
29988
30226
|
});
|
|
29989
|
-
noBuiltIns =
|
|
30227
|
+
noBuiltIns = Option33.Boolean("--no-built-ins", false, {
|
|
29990
30228
|
description: "Skip built-in plugin registration (parity with sm scan --no-built-ins)."
|
|
29991
30229
|
});
|
|
29992
|
-
noPlugins =
|
|
30230
|
+
noPlugins = Option33.Boolean("--no-plugins", false, {
|
|
29993
30231
|
description: "Skip drop-in plugin discovery."
|
|
29994
30232
|
});
|
|
29995
30233
|
// `Option.Boolean('--open', true)`, Clipanion's parser auto-derives
|
|
@@ -29999,35 +30237,35 @@ var ServeCommand = class extends SmCommand {
|
|
|
29999
30237
|
// two registrations for the same flag and rejects the invocation
|
|
30000
30238
|
// with "Ambiguous Syntax Error". Same convention shipped by every
|
|
30001
30239
|
// other `--no-...` flag in the CLI tree.
|
|
30002
|
-
open =
|
|
30240
|
+
open = Option33.Boolean("--open", true, {
|
|
30003
30241
|
description: "Auto-open the SPA in the user's default browser after listen. --no-open opts out."
|
|
30004
30242
|
});
|
|
30005
|
-
devCors =
|
|
30243
|
+
devCors = Option33.Boolean("--dev-cors", false, {
|
|
30006
30244
|
description: "Enable permissive CORS for the Angular dev-server proxy workflow."
|
|
30007
30245
|
});
|
|
30008
30246
|
// `--ui-dist` is intentionally undocumented in the Usage block above
|
|
30009
30247
|
// (the demo build pipeline + tests rely on it; everyday users never
|
|
30010
30248
|
// need it). Clipanion still exposes it on the parser; the Usage
|
|
30011
30249
|
// omission is the "hidden" contract per the 14.1 brief.
|
|
30012
|
-
uiDist =
|
|
30013
|
-
noUi =
|
|
30250
|
+
uiDist = Option33.String("--ui-dist", { required: false, hidden: true });
|
|
30251
|
+
noUi = Option33.Boolean("--no-ui", false, {
|
|
30014
30252
|
description: "Don't serve the Angular UI bundle. Use this when running the BFF alongside `ui:dev` (Angular dev server with HMR). The root `/` then renders an inline placeholder pointing the user at the dev server."
|
|
30015
30253
|
});
|
|
30016
|
-
noWatcher =
|
|
30254
|
+
noWatcher = Option33.Boolean("--no-watcher", false, {
|
|
30017
30255
|
description: "Disable the chokidar-fed scan-and-broadcast loop. Use only for CI / read-only deployments."
|
|
30018
30256
|
});
|
|
30019
|
-
yes =
|
|
30257
|
+
yes = Option33.Boolean("--yes", false, {
|
|
30020
30258
|
description: "Skip the interactive prompt and rebuild the local cache when the on-disk DB has drifted (version skew or an inline schema change). Non-TTY invocations rebuild without asking regardless of this flag."
|
|
30021
30259
|
});
|
|
30022
30260
|
// `--watcher-debounce-ms` is undocumented sugar for advanced users
|
|
30023
30261
|
// who want to tighten / relax the watcher's batching window without
|
|
30024
30262
|
// editing settings.json. Hidden flag, the Usage block omits it.
|
|
30025
|
-
watcherDebounceMs =
|
|
30026
|
-
maxScan =
|
|
30263
|
+
watcherDebounceMs = Option33.String("--watcher-debounce-ms", { required: false, hidden: true });
|
|
30264
|
+
maxScan = Option33.String("--max-scan", {
|
|
30027
30265
|
required: false,
|
|
30028
30266
|
description: "Per-invocation override of scan.maxScan (default 50000), the WALK-INTAKE ceiling. The scan walks, parses, analyzes, and reference-validates the full corpus up to this number. Bidirectional: raises OR lowers the ceiling. Applies to every scan the server runs (initial watcher pass, debounced batches, POST /api/scan, GET /api/scan?fresh=1). Same flag is honoured on the bare `sm` invocation, which routes to `sm serve`."
|
|
30029
30267
|
});
|
|
30030
|
-
maxNodes =
|
|
30268
|
+
maxNodes = Option33.String("--max-nodes", {
|
|
30031
30269
|
required: false,
|
|
30032
30270
|
description: "Per-invocation override of scan.maxNodes (default 256), the MAP RENDER cap (pure metadata): it does NOT bound the scan, only how many nodes the graph view projects onto the canvas. Bidirectional: raises OR lowers the render cap. Same flag is honoured on the bare `sm` invocation, which routes to `sm serve`."
|
|
30033
30271
|
});
|
|
@@ -30057,7 +30295,7 @@ var ServeCommand = class extends SmCommand {
|
|
|
30057
30295
|
return ExitCode.Error;
|
|
30058
30296
|
}
|
|
30059
30297
|
const dbPath = resolveDbPath({ db: this.db, ...runtimeCtx });
|
|
30060
|
-
if (this.db !== void 0 && !
|
|
30298
|
+
if (this.db !== void 0 && !existsSync32(dbPath)) {
|
|
30061
30299
|
this.printer.info(
|
|
30062
30300
|
tx(SERVE_TEXTS.dbNotFound, {
|
|
30063
30301
|
glyph: errGlyph,
|
|
@@ -30397,7 +30635,7 @@ function tryOpenBrowser(url, stderr, warnGlyph) {
|
|
|
30397
30635
|
}
|
|
30398
30636
|
|
|
30399
30637
|
// cli/commands/show.ts
|
|
30400
|
-
import { Command as
|
|
30638
|
+
import { Command as Command36, Option as Option34 } from "clipanion";
|
|
30401
30639
|
|
|
30402
30640
|
// cli/i18n/show.texts.ts
|
|
30403
30641
|
var SHOW_TEXTS = {
|
|
@@ -30448,7 +30686,7 @@ var SHOW_TEXTS = {
|
|
|
30448
30686
|
// cli/commands/show.ts
|
|
30449
30687
|
var ShowCommand = class extends SmCommand {
|
|
30450
30688
|
static paths = [["show"]];
|
|
30451
|
-
static usage =
|
|
30689
|
+
static usage = Command36.Usage({
|
|
30452
30690
|
category: "Browse",
|
|
30453
30691
|
description: "Node detail: weight, frontmatter, links, issues.",
|
|
30454
30692
|
details: `
|
|
@@ -30464,7 +30702,7 @@ var ShowCommand = class extends SmCommand {
|
|
|
30464
30702
|
["Machine-readable detail", "$0 show .claude/agents/architect.md --json"]
|
|
30465
30703
|
]
|
|
30466
30704
|
});
|
|
30467
|
-
nodePath =
|
|
30705
|
+
nodePath = Option34.String({ required: true });
|
|
30468
30706
|
async run() {
|
|
30469
30707
|
const dbPath = resolveDbPath({ db: this.db, ...defaultRuntimeContext() });
|
|
30470
30708
|
const exit = requireDbOrExit(dbPath, this.context.stderr);
|
|
@@ -30705,8 +30943,8 @@ function rankConfidenceForGrouping(c) {
|
|
|
30705
30943
|
|
|
30706
30944
|
// cli/commands/sidecar.ts
|
|
30707
30945
|
import { unlink as unlink3 } from "fs/promises";
|
|
30708
|
-
import { resolve as
|
|
30709
|
-
import { Command as
|
|
30946
|
+
import { resolve as resolve42 } from "path";
|
|
30947
|
+
import { Command as Command37, Option as Option35 } from "clipanion";
|
|
30710
30948
|
|
|
30711
30949
|
// cli/i18n/sidecar.texts.ts
|
|
30712
30950
|
var SIDECAR_TEXTS = {
|
|
@@ -30787,7 +31025,7 @@ async function runWithSidecarConsent(bag, ansi, dispatch) {
|
|
|
30787
31025
|
}
|
|
30788
31026
|
var SidecarRefreshCommand = class extends SmCommand {
|
|
30789
31027
|
static paths = [["sidecar", "refresh"]];
|
|
30790
|
-
static usage =
|
|
31028
|
+
static usage = Command37.Usage({
|
|
30791
31029
|
category: "Actions",
|
|
30792
31030
|
description: "Refresh a sidecar's `for.{bodyHash, frontmatterHash}` to match the live node. Does NOT bump the version.",
|
|
30793
31031
|
details: `
|
|
@@ -30804,8 +31042,8 @@ var SidecarRefreshCommand = class extends SmCommand {
|
|
|
30804
31042
|
["Refresh a node's sidecar hashes", "$0 sidecar refresh .claude/agents/architect.md"]
|
|
30805
31043
|
]
|
|
30806
31044
|
});
|
|
30807
|
-
nodePath =
|
|
30808
|
-
yes =
|
|
31045
|
+
nodePath = Option35.String({ required: true });
|
|
31046
|
+
yes = Option35.Boolean("--yes", false, {
|
|
30809
31047
|
description: "Confirm writing .sm sidecar files in this project (sets allowEditSmFiles=true on first run)."
|
|
30810
31048
|
});
|
|
30811
31049
|
async run() {
|
|
@@ -30863,7 +31101,7 @@ var SidecarRefreshCommand = class extends SmCommand {
|
|
|
30863
31101
|
let absPath;
|
|
30864
31102
|
try {
|
|
30865
31103
|
assertContained(ctx.cwd, node.path);
|
|
30866
|
-
absPath =
|
|
31104
|
+
absPath = resolve42(ctx.cwd, node.path);
|
|
30867
31105
|
} catch (err) {
|
|
30868
31106
|
this.printer.error(
|
|
30869
31107
|
tx(SIDECAR_TEXTS.refreshFailed, { glyph: errGlyph, message: formatErrorMessage(err) })
|
|
@@ -30927,7 +31165,7 @@ var SidecarRefreshCommand = class extends SmCommand {
|
|
|
30927
31165
|
};
|
|
30928
31166
|
var SidecarPruneCommand = class extends SmCommand {
|
|
30929
31167
|
static paths = [["sidecar", "prune"]];
|
|
30930
|
-
static usage =
|
|
31168
|
+
static usage = Command37.Usage({
|
|
30931
31169
|
category: "Actions",
|
|
30932
31170
|
description: "Delete orphan .sm files (sidecars whose accompanying .md no longer exists).",
|
|
30933
31171
|
details: `
|
|
@@ -30949,8 +31187,8 @@ var SidecarPruneCommand = class extends SmCommand {
|
|
|
30949
31187
|
["Delete every orphan .sm file (non-interactive)", "$0 sidecar prune --yes"]
|
|
30950
31188
|
]
|
|
30951
31189
|
});
|
|
30952
|
-
dryRun =
|
|
30953
|
-
yes =
|
|
31190
|
+
dryRun = Option35.Boolean("-n,--dry-run", false);
|
|
31191
|
+
yes = Option35.Boolean("--yes,--force", false, {
|
|
30954
31192
|
description: "Skip the interactive confirmation prompt. Required for non-interactive callers (CI, pre-commit hooks)."
|
|
30955
31193
|
});
|
|
30956
31194
|
// Complexity is from per-orphan handling, empty-set / dry-run /
|
|
@@ -31070,7 +31308,7 @@ var SidecarPruneCommand = class extends SmCommand {
|
|
|
31070
31308
|
};
|
|
31071
31309
|
var SidecarAnnotateCommand = class extends SmCommand {
|
|
31072
31310
|
static paths = [["sidecar", "annotate"]];
|
|
31073
|
-
static usage =
|
|
31311
|
+
static usage = Command37.Usage({
|
|
31074
31312
|
category: "Actions",
|
|
31075
31313
|
description: "Scaffold an empty `<basename>.sm` next to a node ready for editing.",
|
|
31076
31314
|
details: `
|
|
@@ -31088,9 +31326,9 @@ var SidecarAnnotateCommand = class extends SmCommand {
|
|
|
31088
31326
|
["Overwrite an existing one", "$0 sidecar annotate .claude/agents/architect.md --force"]
|
|
31089
31327
|
]
|
|
31090
31328
|
});
|
|
31091
|
-
nodePath =
|
|
31092
|
-
force =
|
|
31093
|
-
yes =
|
|
31329
|
+
nodePath = Option35.String({ required: true });
|
|
31330
|
+
force = Option35.Boolean("--force", false);
|
|
31331
|
+
yes = Option35.Boolean("--yes", false, {
|
|
31094
31332
|
description: "Confirm writing .sm sidecar files in this project (sets allowEditSmFiles=true on first run)."
|
|
31095
31333
|
});
|
|
31096
31334
|
async run() {
|
|
@@ -31147,7 +31385,7 @@ var SidecarAnnotateCommand = class extends SmCommand {
|
|
|
31147
31385
|
let absPath;
|
|
31148
31386
|
try {
|
|
31149
31387
|
assertContained(ctx.cwd, node.path);
|
|
31150
|
-
absPath =
|
|
31388
|
+
absPath = resolve42(ctx.cwd, node.path);
|
|
31151
31389
|
} catch (err) {
|
|
31152
31390
|
this.printer.error(
|
|
31153
31391
|
tx(SIDECAR_TEXTS.annotateFailed, { glyph: errGlyph, message: formatErrorMessage(err) })
|
|
@@ -31229,7 +31467,7 @@ var SIDECAR_COMMANDS = [
|
|
|
31229
31467
|
];
|
|
31230
31468
|
|
|
31231
31469
|
// cli/commands/stubs.ts
|
|
31232
|
-
import { Command as
|
|
31470
|
+
import { Command as Command38, Option as Option36 } from "clipanion";
|
|
31233
31471
|
|
|
31234
31472
|
// cli/i18n/stubs.texts.ts
|
|
31235
31473
|
var STUBS_TEXTS = {
|
|
@@ -31255,7 +31493,7 @@ var StubCommand = class extends SmCommand {
|
|
|
31255
31493
|
};
|
|
31256
31494
|
var DoctorCommand = class extends StubCommand {
|
|
31257
31495
|
static paths = [["doctor"]];
|
|
31258
|
-
static usage =
|
|
31496
|
+
static usage = Command38.Usage({
|
|
31259
31497
|
category: "Setup",
|
|
31260
31498
|
description: planned("Diagnostic report: DB integrity, pending migrations, orphan rows, plugin status, runner availability.")
|
|
31261
31499
|
});
|
|
@@ -31263,18 +31501,18 @@ var DoctorCommand = class extends StubCommand {
|
|
|
31263
31501
|
};
|
|
31264
31502
|
var FindingsCommand = class extends StubCommand {
|
|
31265
31503
|
static paths = [["findings"]];
|
|
31266
|
-
static usage =
|
|
31504
|
+
static usage = Command38.Usage({
|
|
31267
31505
|
category: "Browse",
|
|
31268
31506
|
description: planned("Probabilistic findings: injection, stale summaries, low confidence.")
|
|
31269
31507
|
});
|
|
31270
|
-
kind =
|
|
31271
|
-
since =
|
|
31272
|
-
threshold =
|
|
31508
|
+
kind = Option36.String("--kind", { required: false });
|
|
31509
|
+
since = Option36.String("--since", { required: false });
|
|
31510
|
+
threshold = Option36.String("--threshold", { required: false });
|
|
31273
31511
|
verbName = "findings";
|
|
31274
31512
|
};
|
|
31275
31513
|
var ActionsListCommand = class extends StubCommand {
|
|
31276
31514
|
static paths = [["actions", "list"]];
|
|
31277
|
-
static usage =
|
|
31515
|
+
static usage = Command38.Usage({
|
|
31278
31516
|
category: "Jobs",
|
|
31279
31517
|
description: planned("Registered action types (manifest view).")
|
|
31280
31518
|
});
|
|
@@ -31282,103 +31520,103 @@ var ActionsListCommand = class extends StubCommand {
|
|
|
31282
31520
|
};
|
|
31283
31521
|
var ActionsShowCommand = class extends StubCommand {
|
|
31284
31522
|
static paths = [["actions", "show"]];
|
|
31285
|
-
static usage =
|
|
31523
|
+
static usage = Command38.Usage({
|
|
31286
31524
|
category: "Jobs",
|
|
31287
31525
|
description: planned("Full action manifest, including preconditions and expected duration.")
|
|
31288
31526
|
});
|
|
31289
|
-
id =
|
|
31527
|
+
id = Option36.String({ required: true });
|
|
31290
31528
|
verbName = "actions show";
|
|
31291
31529
|
};
|
|
31292
31530
|
var JobSubmitCommand = class extends StubCommand {
|
|
31293
31531
|
static paths = [["job", "submit"]];
|
|
31294
|
-
static usage =
|
|
31532
|
+
static usage = Command38.Usage({
|
|
31295
31533
|
category: "Jobs",
|
|
31296
31534
|
description: planned("Enqueue a single job or fan out to every matching node (--all).")
|
|
31297
31535
|
});
|
|
31298
|
-
action =
|
|
31299
|
-
node =
|
|
31300
|
-
all =
|
|
31536
|
+
action = Option36.String({ required: true });
|
|
31537
|
+
node = Option36.String("-n", { required: false });
|
|
31538
|
+
all = Option36.Boolean("--all", false);
|
|
31301
31539
|
// CLI flag stays `--run`; field name is `runFlag` per the
|
|
31302
31540
|
// shadow-avoidance convention documented on `SmCommand`.
|
|
31303
|
-
runFlag =
|
|
31304
|
-
force =
|
|
31305
|
-
ttl =
|
|
31306
|
-
priority =
|
|
31541
|
+
runFlag = Option36.Boolean("--run", false);
|
|
31542
|
+
force = Option36.Boolean("--force", false);
|
|
31543
|
+
ttl = Option36.String("--ttl", { required: false });
|
|
31544
|
+
priority = Option36.String("--priority", { required: false });
|
|
31307
31545
|
verbName = "job submit";
|
|
31308
31546
|
};
|
|
31309
31547
|
var JobListCommand = class extends StubCommand {
|
|
31310
31548
|
static paths = [["job", "list"]];
|
|
31311
|
-
static usage =
|
|
31312
|
-
status =
|
|
31313
|
-
action =
|
|
31314
|
-
node =
|
|
31549
|
+
static usage = Command38.Usage({ category: "Jobs", description: planned("List jobs.") });
|
|
31550
|
+
status = Option36.String("--status", { required: false });
|
|
31551
|
+
action = Option36.String("--action", { required: false });
|
|
31552
|
+
node = Option36.String("--node", { required: false });
|
|
31315
31553
|
verbName = "job list";
|
|
31316
31554
|
};
|
|
31317
31555
|
var JobShowCommand = class extends StubCommand {
|
|
31318
31556
|
static paths = [["job", "show"]];
|
|
31319
|
-
static usage =
|
|
31320
|
-
id =
|
|
31557
|
+
static usage = Command38.Usage({ category: "Jobs", description: planned("Job detail: state, claim time, TTL, runner, content hash.") });
|
|
31558
|
+
id = Option36.String({ required: true });
|
|
31321
31559
|
verbName = "job show";
|
|
31322
31560
|
};
|
|
31323
31561
|
var JobPreviewCommand = class extends StubCommand {
|
|
31324
31562
|
static paths = [["job", "preview"]];
|
|
31325
|
-
static usage =
|
|
31326
|
-
id =
|
|
31563
|
+
static usage = Command38.Usage({ category: "Jobs", description: planned("Render the job MD file without executing.") });
|
|
31564
|
+
id = Option36.String({ required: true });
|
|
31327
31565
|
verbName = "job preview";
|
|
31328
31566
|
};
|
|
31329
31567
|
var JobClaimCommand = class extends StubCommand {
|
|
31330
31568
|
static paths = [["job", "claim"]];
|
|
31331
|
-
static usage =
|
|
31569
|
+
static usage = Command38.Usage({
|
|
31332
31570
|
category: "Jobs",
|
|
31333
31571
|
description: planned("Atomic primitive: return next queued job id, mark it running.")
|
|
31334
31572
|
});
|
|
31335
|
-
filter =
|
|
31573
|
+
filter = Option36.String("--filter", { required: false });
|
|
31336
31574
|
verbName = "job claim";
|
|
31337
31575
|
};
|
|
31338
31576
|
var JobRunCommand = class extends StubCommand {
|
|
31339
31577
|
static paths = [["job", "run"]];
|
|
31340
|
-
static usage =
|
|
31578
|
+
static usage = Command38.Usage({
|
|
31341
31579
|
category: "Jobs",
|
|
31342
31580
|
description: planned("Full CLI-runner loop: claim + spawn + record.")
|
|
31343
31581
|
});
|
|
31344
|
-
all =
|
|
31345
|
-
max =
|
|
31582
|
+
all = Option36.Boolean("--all", false);
|
|
31583
|
+
max = Option36.String("--max", { required: false });
|
|
31346
31584
|
verbName = "job run";
|
|
31347
31585
|
};
|
|
31348
31586
|
var JobStatusCommand = class extends StubCommand {
|
|
31349
31587
|
static paths = [["job", "status"]];
|
|
31350
|
-
static usage =
|
|
31588
|
+
static usage = Command38.Usage({
|
|
31351
31589
|
category: "Jobs",
|
|
31352
31590
|
description: planned("Counts (per status) or single-job status.")
|
|
31353
31591
|
});
|
|
31354
|
-
id =
|
|
31592
|
+
id = Option36.String({ required: false });
|
|
31355
31593
|
verbName = "job status";
|
|
31356
31594
|
};
|
|
31357
31595
|
var JobCancelCommand = class extends StubCommand {
|
|
31358
31596
|
static paths = [["job", "cancel"]];
|
|
31359
|
-
static usage =
|
|
31597
|
+
static usage = Command38.Usage({
|
|
31360
31598
|
category: "Jobs",
|
|
31361
31599
|
description: planned("Force a running job to failed with reason user-cancelled.")
|
|
31362
31600
|
});
|
|
31363
|
-
id =
|
|
31364
|
-
all =
|
|
31601
|
+
id = Option36.String({ required: false });
|
|
31602
|
+
all = Option36.Boolean("--all", false);
|
|
31365
31603
|
verbName = "job cancel";
|
|
31366
31604
|
};
|
|
31367
31605
|
var RecordCommand = class extends StubCommand {
|
|
31368
31606
|
static paths = [["record"]];
|
|
31369
|
-
static usage =
|
|
31607
|
+
static usage = Command38.Usage({
|
|
31370
31608
|
category: "Jobs",
|
|
31371
31609
|
description: planned("Close a running job with success or failure. Nonce is the sole credential.")
|
|
31372
31610
|
});
|
|
31373
|
-
id =
|
|
31374
|
-
nonce =
|
|
31375
|
-
status =
|
|
31376
|
-
report =
|
|
31377
|
-
tokensIn =
|
|
31378
|
-
tokensOut =
|
|
31379
|
-
durationMs =
|
|
31380
|
-
model =
|
|
31381
|
-
error =
|
|
31611
|
+
id = Option36.String("--id", { required: true });
|
|
31612
|
+
nonce = Option36.String("--nonce", { required: true });
|
|
31613
|
+
status = Option36.String("--status", { required: true });
|
|
31614
|
+
report = Option36.String("--report", { required: false });
|
|
31615
|
+
tokensIn = Option36.String("--tokens-in", { required: false });
|
|
31616
|
+
tokensOut = Option36.String("--tokens-out", { required: false });
|
|
31617
|
+
durationMs = Option36.String("--duration-ms", { required: false });
|
|
31618
|
+
model = Option36.String("--model", { required: false });
|
|
31619
|
+
error = Option36.String("--error", { required: false });
|
|
31382
31620
|
verbName = "record";
|
|
31383
31621
|
};
|
|
31384
31622
|
var STUB_COMMANDS = [
|
|
@@ -31398,11 +31636,11 @@ var STUB_COMMANDS = [
|
|
|
31398
31636
|
];
|
|
31399
31637
|
|
|
31400
31638
|
// cli/commands/tutorial.ts
|
|
31401
|
-
import { cpSync as
|
|
31402
|
-
import { dirname as
|
|
31403
|
-
import { createInterface as
|
|
31404
|
-
import { fileURLToPath as
|
|
31405
|
-
import { Command as
|
|
31639
|
+
import { cpSync as cpSync3, existsSync as existsSync33, mkdirSync as mkdirSync6, rmSync as rmSync2, statSync as statSync12 } from "fs";
|
|
31640
|
+
import { dirname as dirname21, join as join21, resolve as resolve43 } from "path";
|
|
31641
|
+
import { createInterface as createInterface6 } from "readline";
|
|
31642
|
+
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
31643
|
+
import { Command as Command39, Option as Option37 } from "clipanion";
|
|
31406
31644
|
|
|
31407
31645
|
// cli/i18n/tutorial.texts.ts
|
|
31408
31646
|
var TUTORIAL_TEXTS = {
|
|
@@ -31464,7 +31702,7 @@ var TRIGGER_EN = "run the tutorial";
|
|
|
31464
31702
|
var TRIGGER_ES = "ejecuta el tutorial";
|
|
31465
31703
|
var TutorialCommand = class extends SmCommand {
|
|
31466
31704
|
static paths = [["tutorial"]];
|
|
31467
|
-
static usage =
|
|
31705
|
+
static usage = Command39.Usage({
|
|
31468
31706
|
category: "Setup",
|
|
31469
31707
|
description: "Materialize an interactive tester tutorial as a Claude Code skill folder under `<cwd>/.claude/skills/`.",
|
|
31470
31708
|
details: `
|
|
@@ -31493,18 +31731,18 @@ var TutorialCommand = class extends SmCommand {
|
|
|
31493
31731
|
// more. Accept one so a stale `sm tutorial master` lands on a friendly
|
|
31494
31732
|
// usage error (guarded in `run()`) instead of clipanion's generic
|
|
31495
31733
|
// "extraneous argument" message.
|
|
31496
|
-
legacyPositional =
|
|
31734
|
+
legacyPositional = Option37.String({ required: false });
|
|
31497
31735
|
// Named `forProvider`, NOT `for` (reserved word). The CLI surface stays
|
|
31498
31736
|
// `--for`; selects the destination Provider whose `scaffold.skillDir`
|
|
31499
31737
|
// the skill is materialised under, skipping the interactive prompt.
|
|
31500
|
-
forProvider =
|
|
31738
|
+
forProvider = Option37.String("--for", {
|
|
31501
31739
|
required: false,
|
|
31502
31740
|
description: "Destination provider id (e.g. claude). Skips the prompt."
|
|
31503
31741
|
});
|
|
31504
|
-
force =
|
|
31742
|
+
force = Option37.Boolean("--force", false, {
|
|
31505
31743
|
description: "Overwrite an existing target directory without prompting."
|
|
31506
31744
|
});
|
|
31507
|
-
experimental =
|
|
31745
|
+
experimental = Option37.Boolean("--experimental", false, {
|
|
31508
31746
|
description: "Offer experimental providers (e.g. agent-skills) as destinations. They ship disabled; enable the chosen one with `sm plugins enable <id>`."
|
|
31509
31747
|
});
|
|
31510
31748
|
async run() {
|
|
@@ -31556,8 +31794,8 @@ var TutorialCommand = class extends SmCommand {
|
|
|
31556
31794
|
}
|
|
31557
31795
|
try {
|
|
31558
31796
|
rmSync2(targetDir, { recursive: true, force: true });
|
|
31559
|
-
mkdirSync6(
|
|
31560
|
-
|
|
31797
|
+
mkdirSync6(dirname21(targetDir), { recursive: true });
|
|
31798
|
+
cpSync3(sourceDir, targetDir, { recursive: true });
|
|
31561
31799
|
} catch (err) {
|
|
31562
31800
|
this.printer.error(
|
|
31563
31801
|
tx(TUTORIAL_TEXTS.writeFailed, {
|
|
@@ -31694,7 +31932,7 @@ function classifyAnswer(trimmed, targets, def) {
|
|
|
31694
31932
|
async function promptForTarget(targets, def, stdin, stderr, glyph) {
|
|
31695
31933
|
stderr.write(renderTargetLines(targets, def, glyph) + "\n");
|
|
31696
31934
|
const defIndex = targets.findIndex((t) => t.id === def.id);
|
|
31697
|
-
const rl =
|
|
31935
|
+
const rl = createInterface6({ input: stdin, output: stderr });
|
|
31698
31936
|
try {
|
|
31699
31937
|
for (let attempt = 0; attempt < 5; attempt += 1) {
|
|
31700
31938
|
const answer = await new Promise(
|
|
@@ -31708,35 +31946,21 @@ async function promptForTarget(targets, def, stdin, stderr, glyph) {
|
|
|
31708
31946
|
rl.close();
|
|
31709
31947
|
}
|
|
31710
31948
|
}
|
|
31711
|
-
|
|
31712
|
-
const segments = cwd.split("/").filter((s) => s.length > 0);
|
|
31713
|
-
if (segments.length === 0) return "./";
|
|
31714
|
-
return `./${segments[segments.length - 1]}/`;
|
|
31715
|
-
}
|
|
31716
|
-
function isDirEmpty(dir) {
|
|
31717
|
-
return readdirSync10(dir).length === 0;
|
|
31718
|
-
}
|
|
31719
|
-
function listCwdEntries(dir) {
|
|
31720
|
-
const entries = readdirSync10(dir).sort();
|
|
31721
|
-
const shown = entries.slice(0, 5);
|
|
31722
|
-
const more = entries.length > shown.length ? ", ..." : "";
|
|
31723
|
-
return shown.join(", ") + more;
|
|
31724
|
-
}
|
|
31725
|
-
var cachedSourceDir;
|
|
31949
|
+
var cachedSourceDir2;
|
|
31726
31950
|
function resolveSkillSourceDir() {
|
|
31727
|
-
if (
|
|
31728
|
-
const here =
|
|
31951
|
+
if (cachedSourceDir2 !== void 0) return cachedSourceDir2;
|
|
31952
|
+
const here = dirname21(fileURLToPath8(import.meta.url));
|
|
31729
31953
|
const candidates = [
|
|
31730
31954
|
// dev: src/cli/commands/ → repo-root .claude/skills/sm-tutorial/
|
|
31731
|
-
|
|
31955
|
+
resolve43(here, "../../..", SKILL_SOURCE_DIR),
|
|
31732
31956
|
// bundled: dist/cli.js → dist/cli/tutorial/sm-tutorial (sibling)
|
|
31733
|
-
|
|
31957
|
+
resolve43(here, "cli/tutorial", SKILL_SLUG),
|
|
31734
31958
|
// bundled fallback: any-depth → cli/tutorial/sm-tutorial
|
|
31735
|
-
|
|
31959
|
+
resolve43(here, "../cli/tutorial", SKILL_SLUG)
|
|
31736
31960
|
];
|
|
31737
31961
|
for (const candidate of candidates) {
|
|
31738
|
-
if (
|
|
31739
|
-
|
|
31962
|
+
if (existsSync33(candidate) && statSync12(candidate).isDirectory()) {
|
|
31963
|
+
cachedSourceDir2 = candidate;
|
|
31740
31964
|
return candidate;
|
|
31741
31965
|
}
|
|
31742
31966
|
}
|
|
@@ -31746,7 +31970,7 @@ function resolveSkillSourceDir() {
|
|
|
31746
31970
|
}
|
|
31747
31971
|
|
|
31748
31972
|
// cli/commands/version.ts
|
|
31749
|
-
import { Command as
|
|
31973
|
+
import { Command as Command40 } from "clipanion";
|
|
31750
31974
|
|
|
31751
31975
|
// cli/i18n/version.texts.ts
|
|
31752
31976
|
var VERSION_TEXTS = {
|
|
@@ -31761,7 +31985,7 @@ var VERSION_TEXTS = {
|
|
|
31761
31985
|
// cli/commands/version.ts
|
|
31762
31986
|
var VersionCommand = class extends SmCommand {
|
|
31763
31987
|
static paths = [["version"]];
|
|
31764
|
-
static usage =
|
|
31988
|
+
static usage = Command40.Usage({
|
|
31765
31989
|
category: "Introspection",
|
|
31766
31990
|
description: "Print the CLI / spec / runtime / db-schema version matrix."
|
|
31767
31991
|
});
|
|
@@ -31836,6 +32060,7 @@ cli.register(RootHelpCommand);
|
|
|
31836
32060
|
cli.register(HelpCommand);
|
|
31837
32061
|
cli.register(InitCommand);
|
|
31838
32062
|
cli.register(TutorialCommand);
|
|
32063
|
+
cli.register(ExampleCommand);
|
|
31839
32064
|
cli.register(IntentionalFailCommand);
|
|
31840
32065
|
cli.register(ScanCommand);
|
|
31841
32066
|
cli.register(ScanCompareCommand);
|
|
@@ -31868,7 +32093,7 @@ var logLevel = resolveLogLevel({
|
|
|
31868
32093
|
errStream: process.stderr
|
|
31869
32094
|
});
|
|
31870
32095
|
configureLogger(new Logger({ level: logLevel, stream: process.stderr }));
|
|
31871
|
-
var bareArgs = resolveBareInvocation(args);
|
|
32096
|
+
var bareArgs = await resolveBareInvocation(args);
|
|
31872
32097
|
var routedArgs = routeHelpArgs(bareArgs ?? args, cli);
|
|
31873
32098
|
var telemetryVerb = routedArgs[0];
|
|
31874
32099
|
await maybeRunFirstRunPrompt();
|
|
@@ -31926,23 +32151,41 @@ await lifecycleDispatcher.dispatch(
|
|
|
31926
32151
|
await closeSentryCli();
|
|
31927
32152
|
await flushUsageCli();
|
|
31928
32153
|
process.exit(exitCode);
|
|
31929
|
-
function resolveBareInvocation(rawArgs) {
|
|
31930
|
-
if (rawArgs.length === 0) return
|
|
32154
|
+
async function resolveBareInvocation(rawArgs) {
|
|
32155
|
+
if (rawArgs.length === 0) return resolveNoArgsBare();
|
|
31931
32156
|
const first = rawArgs[0];
|
|
31932
32157
|
const passthrough = /* @__PURE__ */ new Set(["--help", "-h", "--version", "-V", "-v"]);
|
|
31933
32158
|
if (first !== void 0 && first.startsWith("-") && !passthrough.has(first)) {
|
|
31934
32159
|
const isSingleDashLong = !first.startsWith("--") && first.length > 2;
|
|
31935
32160
|
if (isSingleDashLong) return null;
|
|
31936
|
-
if (
|
|
32161
|
+
if (existsSync34(defaultProjectDbPath(defaultRuntimeContext()))) {
|
|
31937
32162
|
return ["serve", ...rawArgs];
|
|
31938
32163
|
}
|
|
31939
32164
|
return resolveBareDefault();
|
|
31940
32165
|
}
|
|
31941
32166
|
return null;
|
|
31942
32167
|
}
|
|
32168
|
+
async function resolveNoArgsBare() {
|
|
32169
|
+
const ctx = defaultRuntimeContext();
|
|
32170
|
+
const stdin = process.stdin;
|
|
32171
|
+
const result = await decideBareNoArgs(
|
|
32172
|
+
{
|
|
32173
|
+
hasDb: existsSync34(defaultProjectDbPath(ctx)),
|
|
32174
|
+
isTty: stdin.isTTY === true,
|
|
32175
|
+
isEmptyDir: isDirEmpty(ctx.cwd)
|
|
32176
|
+
},
|
|
32177
|
+
() => {
|
|
32178
|
+
const stderr = process.stderr;
|
|
32179
|
+
const ansi = ansiFor({ isTTY: stderr.isTTY === true, noColorFlag: false });
|
|
32180
|
+
return promptEmptyFolderChoice(stdin, stderr, ansi);
|
|
32181
|
+
}
|
|
32182
|
+
);
|
|
32183
|
+
if (result.kind === "route") return result.argv;
|
|
32184
|
+
return resolveBareDefault();
|
|
32185
|
+
}
|
|
31943
32186
|
function resolveBareDefault() {
|
|
31944
32187
|
const ctx = defaultRuntimeContext();
|
|
31945
|
-
if (
|
|
32188
|
+
if (existsSync34(defaultProjectDbPath(ctx))) {
|
|
31946
32189
|
return ["serve"];
|
|
31947
32190
|
}
|
|
31948
32191
|
const stderr = process.stderr;
|
|
@@ -31951,10 +32194,12 @@ function resolveBareDefault() {
|
|
|
31951
32194
|
tx(ENTRY_TEXTS.bareNoProject, {
|
|
31952
32195
|
glyph: ansi.red("\u2715"),
|
|
31953
32196
|
cwd: ctx.cwd,
|
|
31954
|
-
hint: ansi.dim(
|
|
32197
|
+
hint: ansi.dim(
|
|
32198
|
+
isDirEmpty(ctx.cwd) ? ENTRY_TEXTS.bareEmptyHint : ENTRY_TEXTS.bareNoProjectHint
|
|
32199
|
+
)
|
|
31955
32200
|
})
|
|
31956
32201
|
);
|
|
31957
32202
|
process.exit(ExitCode.Error);
|
|
31958
32203
|
}
|
|
31959
32204
|
//# sourceMappingURL=cli.js.map
|
|
31960
|
-
//# debugId=
|
|
32205
|
+
//# debugId=ef7d5528-7273-5d01-b514-635331ee2072
|