@skill-map/cli 0.62.2 → 0.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/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/tutorial/sm-tutorial/SKILL.md +1 -1
- package/dist/cli/tutorial/sm-tutorial/references/_core.md +8 -8
- package/dist/cli/tutorial/sm-tutorial/references/part-authoring.md +22 -11
- package/dist/cli/tutorial/sm-tutorial/references/part-project-kickoff.md +2 -2
- package/dist/cli/tutorial/sm-tutorial/references/part-settings.md +2 -2
- package/dist/cli.js +1032 -807
- package/dist/index.js +20 -13
- package/dist/kernel/index.d.ts +10 -18
- package/dist/kernel/index.js +20 -13
- package/dist/ui/chunk-53FVREFR.js +3 -0
- package/dist/ui/{chunk-ECKRC6XD.js → chunk-JEWVC3KW.js} +1 -1
- package/dist/ui/chunk-PEBQMYAG.js +1 -0
- package/dist/ui/{chunk-CM4YB7L4.js → chunk-SR2EXRNN.js} +1 -1
- package/dist/ui/index.html +1 -1
- package/dist/ui/{main-FUEU25PM.js → main-VSGHRLCJ.js} +4 -4
- package/package.json +2 -2
- package/dist/ui/chunk-NC3HOVDG.js +0 -1
- package/dist/ui/chunk-RXGORKP5.js +0 -3
- /package/dist/ui/{chunk-IYC5ZW4L.js → chunk-WDCUTF3U.js} +0 -0
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]="43bb2367-1e14-5df2-9221-a5e7a877a666")}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.0",
|
|
254
254
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
255
255
|
license: "MIT",
|
|
256
256
|
type: "module",
|
|
@@ -1068,6 +1068,108 @@ function buildTooltip(names) {
|
|
|
1068
1068
|
return `${joined.slice(0, TOOLTIP_MAX - 1)}\u2026`;
|
|
1069
1069
|
}
|
|
1070
1070
|
|
|
1071
|
+
// plugins/agent-skills/providers/agent-skills/schemas/skill.schema.json
|
|
1072
|
+
var skill_schema_default2 = {
|
|
1073
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
1074
|
+
$id: "https://skill-map.ai/providers/agent-skills/v1/frontmatter/skill.schema.json",
|
|
1075
|
+
title: "FrontmatterAgentSkillsSkill",
|
|
1076
|
+
description: "Frontmatter shape for nodes classified as `skill` by the neutral `agent-skills` Provider, Agent Skills delivered as `SKILL.md` files at the open-standard path `.agents/skills/<name>/SKILL.md`. Jointly adopted by Anthropic, OpenAI (Codex), and Google (Gemini); the path is vendor-neutral so no single Provider should own it. Required fields are `name` and `description` (from spec base). The standard's optional frontmatter fields are declared below, mirrored verbatim from https://agentskills.io/specification: `license`, `compatibility`, `metadata`, and the experimental `allowed-tools`. `additionalProperties: true` so any future standard field flows through unchanged until this schema catches up.",
|
|
1077
|
+
allOf: [
|
|
1078
|
+
{ $ref: "https://skill-map.ai/spec/v0/frontmatter/base.schema.json" }
|
|
1079
|
+
],
|
|
1080
|
+
type: "object",
|
|
1081
|
+
additionalProperties: true,
|
|
1082
|
+
properties: {
|
|
1083
|
+
license: {
|
|
1084
|
+
type: "string",
|
|
1085
|
+
description: "License applied to the skill: a license name (e.g. `Apache-2.0`) or a reference to a bundled license file. Source: https://agentskills.io/specification."
|
|
1086
|
+
},
|
|
1087
|
+
compatibility: {
|
|
1088
|
+
type: "string",
|
|
1089
|
+
maxLength: 500,
|
|
1090
|
+
description: "Environment requirements (intended product, required system packages, network access, etc.). Most skills omit it. Max 500 characters. Source: https://agentskills.io/specification."
|
|
1091
|
+
},
|
|
1092
|
+
metadata: {
|
|
1093
|
+
type: "object",
|
|
1094
|
+
additionalProperties: { type: "string" },
|
|
1095
|
+
description: "Arbitrary string-keyed, string-valued map for client-defined metadata not covered by the standard. Source: https://agentskills.io/specification."
|
|
1096
|
+
},
|
|
1097
|
+
"allowed-tools": {
|
|
1098
|
+
type: "string",
|
|
1099
|
+
description: "Space-separated list of pre-approved tools the skill may run (e.g. `Bash(git:*) Read`). Experimental in the open standard; support varies between agent implementations. Source: https://agentskills.io/specification."
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
};
|
|
1103
|
+
|
|
1104
|
+
// plugins/agent-skills/providers/agent-skills/index.ts
|
|
1105
|
+
var OPEN_SKILLS_READ = {
|
|
1106
|
+
extensions: [".md"],
|
|
1107
|
+
parser: "frontmatter-yaml"
|
|
1108
|
+
};
|
|
1109
|
+
var OPEN_SKILLS_KINDS = {
|
|
1110
|
+
skill: {
|
|
1111
|
+
schema: "./schemas/skill.schema.json",
|
|
1112
|
+
schemaJson: skill_schema_default2,
|
|
1113
|
+
ui: {
|
|
1114
|
+
label: "Skills",
|
|
1115
|
+
color: "#10b981",
|
|
1116
|
+
colorDark: "#34d399",
|
|
1117
|
+
icon: { kind: "pi", id: "pi-bolt" }
|
|
1118
|
+
},
|
|
1119
|
+
// Open-standard skills mirror Anthropic's: dirname between
|
|
1120
|
+
// `.agents/skills/` and `/SKILL.md` is the canonical handle,
|
|
1121
|
+
// `frontmatter.name` overrides when present.
|
|
1122
|
+
identifiers: ["frontmatter.name", "dirname"]
|
|
1123
|
+
}
|
|
1124
|
+
};
|
|
1125
|
+
var OPEN_SKILLS_RESOLUTION = { invokes: ["skill"] };
|
|
1126
|
+
function classifyOpenSkillsPath(path) {
|
|
1127
|
+
if (/^\.agents\/skills\/[^/]+\/skill\.md$/.test(path.toLowerCase())) return "skill";
|
|
1128
|
+
return null;
|
|
1129
|
+
}
|
|
1130
|
+
var agentSkillsProvider = {
|
|
1131
|
+
id: "agent-skills",
|
|
1132
|
+
pluginId: AGENT_SKILLS_PLUGIN_ID,
|
|
1133
|
+
kind: "provider",
|
|
1134
|
+
description: "Classifies files under `.agents/skills/<name>/SKILL.md` as Agent Skills.",
|
|
1135
|
+
// Provider identity for the active-lens dropdown, the topbar lens chip,
|
|
1136
|
+
// and the per-node provider chip. Neutral slate (this is the
|
|
1137
|
+
// vendor-agnostic open-standard Provider, not a brand). Verbatim from
|
|
1138
|
+
// the previous static UI catalog (`ui/src/services/provider-ui.ts`).
|
|
1139
|
+
presentation: {
|
|
1140
|
+
label: "Open Skills",
|
|
1141
|
+
color: "#64748b",
|
|
1142
|
+
colorDark: "#94a3b8"
|
|
1143
|
+
},
|
|
1144
|
+
// Gated like the vendor providers: `.agents/skills/*` is classified as
|
|
1145
|
+
// `skill` ONLY under the `agent-skills` lens; under any other lens
|
|
1146
|
+
// (including `markdown`) it falls through to `core/markdown`, the sole
|
|
1147
|
+
// universal provider. Keeps the "one active lens" model honest.
|
|
1148
|
+
gatedByActiveLens: true,
|
|
1149
|
+
// Not yet ready for end users: ships disabled by default. The operator
|
|
1150
|
+
// opts in via `sm plugins enable` / the Settings toggle / the tutorial's
|
|
1151
|
+
// `--experimental` flow, so it neither classifies nor auto-detects until
|
|
1152
|
+
// enabled.
|
|
1153
|
+
stability: "experimental",
|
|
1154
|
+
// Auto-detect marker: a `.agents/` directory marks an open-standard
|
|
1155
|
+
// project. This is also the marker a Google/Antigravity project carries
|
|
1156
|
+
// (Antigravity adopted the open standard). The marker only produces an
|
|
1157
|
+
// auto-detect candidate once this experimental provider is enabled.
|
|
1158
|
+
// Provider-owned.
|
|
1159
|
+
detect: { markers: [".agents"] },
|
|
1160
|
+
// Authoring target for `sm tutorial`: the open standard discovers skills
|
|
1161
|
+
// under `.agents/skills/<name>/SKILL.md`. The same path is consumed by
|
|
1162
|
+
// Antigravity (adopted the standard rather than a `.gemini/` layout) and
|
|
1163
|
+
// OpenAI Codex (skills mirror the open standard), so `aka` surfaces both
|
|
1164
|
+
// names in the destination prompt to orient testers on those agents.
|
|
1165
|
+
// `aka` is display-only, `--for` still matches the `agent-skills` id.
|
|
1166
|
+
scaffold: { skillDir: ".agents/skills", aka: ["Antigravity", "OpenAI Codex"] },
|
|
1167
|
+
read: OPEN_SKILLS_READ,
|
|
1168
|
+
kinds: OPEN_SKILLS_KINDS,
|
|
1169
|
+
resolution: OPEN_SKILLS_RESOLUTION,
|
|
1170
|
+
classify: classifyOpenSkillsPath
|
|
1171
|
+
};
|
|
1172
|
+
|
|
1071
1173
|
// plugins/antigravity/providers/antigravity/index.ts
|
|
1072
1174
|
var antigravityProvider = {
|
|
1073
1175
|
id: "antigravity",
|
|
@@ -1080,10 +1182,7 @@ var antigravityProvider = {
|
|
|
1080
1182
|
presentation: {
|
|
1081
1183
|
label: "Antigravity",
|
|
1082
1184
|
color: "#7c3aed",
|
|
1083
|
-
colorDark: "#a78bfa"
|
|
1084
|
-
// Registered but not yet selectable as the active lens; the UI greys
|
|
1085
|
-
// it with a `(coming soon)` suffix.
|
|
1086
|
-
comingSoon: true
|
|
1185
|
+
colorDark: "#a78bfa"
|
|
1087
1186
|
},
|
|
1088
1187
|
// No `detect` block: Antigravity has no vendor-specific workspace marker
|
|
1089
1188
|
// (it adopted the open-standard `.agents/`, owned by `agent-skills`), so
|
|
@@ -1095,17 +1194,23 @@ var antigravityProvider = {
|
|
|
1095
1194
|
// declaration anticipates the migration moment so we don't have to
|
|
1096
1195
|
// remember to flip it then.
|
|
1097
1196
|
gatedByActiveLens: true,
|
|
1098
|
-
//
|
|
1099
|
-
//
|
|
1100
|
-
//
|
|
1101
|
-
|
|
1102
|
-
//
|
|
1103
|
-
|
|
1104
|
-
//
|
|
1105
|
-
//
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1197
|
+
// Not yet ready for end users: ships disabled by default (the operator
|
|
1198
|
+
// opts in via `sm plugins enable` / Settings / the tutorial's
|
|
1199
|
+
// `--experimental` flow). Replaces the retired `comingSoon` flag.
|
|
1200
|
+
stability: "experimental",
|
|
1201
|
+
// Adopt the open-standard `.agents/skills/` layout by REUSING the
|
|
1202
|
+
// `agent-skills` classifier + kind + read config (composition at the
|
|
1203
|
+
// manifest level, not a kernel rule). Under the antigravity lens the
|
|
1204
|
+
// walker classifies `.agents/skills/<name>/SKILL.md` as
|
|
1205
|
+
// `{ provider: 'antigravity', kind: 'skill' }`, so the reservedNames
|
|
1206
|
+
// below apply via SELF scope. `agent-skills` itself is gated to its own
|
|
1207
|
+
// lens, so it never competes here (under the antigravity lens it does
|
|
1208
|
+
// not participate). This is why there is no cross-provider lens-scope
|
|
1209
|
+
// rule in the kernel any more.
|
|
1210
|
+
read: OPEN_SKILLS_READ,
|
|
1211
|
+
kinds: OPEN_SKILLS_KINDS,
|
|
1212
|
+
resolution: OPEN_SKILLS_RESOLUTION,
|
|
1213
|
+
classify: classifyOpenSkillsPath,
|
|
1109
1214
|
// Built-in slash-command catalog, captured verbatim from `agy /help`
|
|
1110
1215
|
// (Antigravity CLI v1.0.3). This REPLACES the earlier provisional list
|
|
1111
1216
|
// that mirrored Gemini CLI's verbs: `agy` ships its own surface. It
|
|
@@ -1123,12 +1228,10 @@ var antigravityProvider = {
|
|
|
1123
1228
|
//
|
|
1124
1229
|
// Declared under the `skill` kind (NOT `command`): Antigravity has no
|
|
1125
1230
|
// vendor-specific command directory, its user slash-commands are skills
|
|
1126
|
-
// (`.agents/skills/<name>/SKILL.md
|
|
1127
|
-
//
|
|
1128
|
-
//
|
|
1129
|
-
//
|
|
1130
|
-
// lends this `skill` catalog to `agent-skills` skill nodes, so a user
|
|
1131
|
-
// `.agents/skills/goal/SKILL.md` is flagged because `/goal` is built-in.
|
|
1231
|
+
// (`.agents/skills/<name>/SKILL.md`). Because the antigravity lens now
|
|
1232
|
+
// classifies those files itself (inherited classifier above), a user
|
|
1233
|
+
// `.agents/skills/goal/SKILL.md` is flagged by SELF scope because `/goal`
|
|
1234
|
+
// is built-in.
|
|
1132
1235
|
//
|
|
1133
1236
|
// **Reconciliation marker**: re-capture from `agy /help` on each major
|
|
1134
1237
|
// Antigravity CLI release and bump the cited version above.
|
|
@@ -1245,10 +1348,7 @@ var openaiProvider = {
|
|
|
1245
1348
|
presentation: {
|
|
1246
1349
|
label: "OpenAI Codex",
|
|
1247
1350
|
color: "#22c55e",
|
|
1248
|
-
colorDark: "#4ade80"
|
|
1249
|
-
// Registered but not yet selectable as the active lens; auto-detect
|
|
1250
|
-
// skips its markers and the UI greys it with a `(coming soon)` suffix.
|
|
1251
|
-
comingSoon: true
|
|
1351
|
+
colorDark: "#4ade80"
|
|
1252
1352
|
},
|
|
1253
1353
|
// Auto-detect markers: a `.codex/` directory or a root `AGENTS.md` marks
|
|
1254
1354
|
// a Codex CLI project. Provider-owned (replaces the old central
|
|
@@ -1259,6 +1359,10 @@ var openaiProvider = {
|
|
|
1259
1359
|
// claiming Codex agents under a `claude` (or any other) lens, where
|
|
1260
1360
|
// the Codex runtime would never resolve them anyway.
|
|
1261
1361
|
gatedByActiveLens: true,
|
|
1362
|
+
// Not yet ready for end users: ships disabled by default (the operator
|
|
1363
|
+
// opts in via `sm plugins enable` / Settings / the tutorial's
|
|
1364
|
+
// `--experimental` flow). Replaces the retired `comingSoon` flag.
|
|
1365
|
+
stability: "experimental",
|
|
1262
1366
|
read: { extensions: [".toml"], parser: "toml" },
|
|
1263
1367
|
kinds: {
|
|
1264
1368
|
agent: {
|
|
@@ -1291,98 +1395,6 @@ var openaiProvider = {
|
|
|
1291
1395
|
}
|
|
1292
1396
|
};
|
|
1293
1397
|
|
|
1294
|
-
// plugins/agent-skills/providers/agent-skills/schemas/skill.schema.json
|
|
1295
|
-
var skill_schema_default2 = {
|
|
1296
|
-
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
1297
|
-
$id: "https://skill-map.ai/providers/agent-skills/v1/frontmatter/skill.schema.json",
|
|
1298
|
-
title: "FrontmatterAgentSkillsSkill",
|
|
1299
|
-
description: "Frontmatter shape for nodes classified as `skill` by the neutral `agent-skills` Provider, Agent Skills delivered as `SKILL.md` files at the open-standard path `.agents/skills/<name>/SKILL.md`. Jointly adopted by Anthropic, OpenAI (Codex), and Google (Gemini); the path is vendor-neutral so no single Provider should own it. Required fields are `name` and `description` (from spec base). The standard's optional frontmatter fields are declared below, mirrored verbatim from https://agentskills.io/specification: `license`, `compatibility`, `metadata`, and the experimental `allowed-tools`. `additionalProperties: true` so any future standard field flows through unchanged until this schema catches up.",
|
|
1300
|
-
allOf: [
|
|
1301
|
-
{ $ref: "https://skill-map.ai/spec/v0/frontmatter/base.schema.json" }
|
|
1302
|
-
],
|
|
1303
|
-
type: "object",
|
|
1304
|
-
additionalProperties: true,
|
|
1305
|
-
properties: {
|
|
1306
|
-
license: {
|
|
1307
|
-
type: "string",
|
|
1308
|
-
description: "License applied to the skill: a license name (e.g. `Apache-2.0`) or a reference to a bundled license file. Source: https://agentskills.io/specification."
|
|
1309
|
-
},
|
|
1310
|
-
compatibility: {
|
|
1311
|
-
type: "string",
|
|
1312
|
-
maxLength: 500,
|
|
1313
|
-
description: "Environment requirements (intended product, required system packages, network access, etc.). Most skills omit it. Max 500 characters. Source: https://agentskills.io/specification."
|
|
1314
|
-
},
|
|
1315
|
-
metadata: {
|
|
1316
|
-
type: "object",
|
|
1317
|
-
additionalProperties: { type: "string" },
|
|
1318
|
-
description: "Arbitrary string-keyed, string-valued map for client-defined metadata not covered by the standard. Source: https://agentskills.io/specification."
|
|
1319
|
-
},
|
|
1320
|
-
"allowed-tools": {
|
|
1321
|
-
type: "string",
|
|
1322
|
-
description: "Space-separated list of pre-approved tools the skill may run (e.g. `Bash(git:*) Read`). Experimental in the open standard; support varies between agent implementations. Source: https://agentskills.io/specification."
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1325
|
-
};
|
|
1326
|
-
|
|
1327
|
-
// plugins/agent-skills/providers/agent-skills/index.ts
|
|
1328
|
-
var agentSkillsProvider = {
|
|
1329
|
-
id: "agent-skills",
|
|
1330
|
-
pluginId: AGENT_SKILLS_PLUGIN_ID,
|
|
1331
|
-
kind: "provider",
|
|
1332
|
-
description: "Classifies files under `.agents/skills/<name>/SKILL.md` as Agent Skills.",
|
|
1333
|
-
// Provider identity for the active-lens dropdown, the topbar lens chip,
|
|
1334
|
-
// and the per-node provider chip. Neutral slate (this is the
|
|
1335
|
-
// vendor-agnostic open-standard Provider, not a brand). Verbatim from
|
|
1336
|
-
// the previous static UI catalog (`ui/src/services/provider-ui.ts`).
|
|
1337
|
-
presentation: {
|
|
1338
|
-
label: "Open Skills",
|
|
1339
|
-
color: "#64748b",
|
|
1340
|
-
colorDark: "#94a3b8",
|
|
1341
|
-
// Registered but not yet selectable as the active lens; auto-detect
|
|
1342
|
-
// skips its `.agents/` marker and the UI greys it with a
|
|
1343
|
-
// `(coming soon)` suffix.
|
|
1344
|
-
comingSoon: true
|
|
1345
|
-
},
|
|
1346
|
-
// Auto-detect marker: a `.agents/` directory marks an open-standard
|
|
1347
|
-
// project. This is also the marker a Google/Antigravity project carries
|
|
1348
|
-
// (Antigravity adopted the open standard), so such projects auto-detect
|
|
1349
|
-
// as this universal lens. Provider-owned.
|
|
1350
|
-
detect: { markers: [".agents"] },
|
|
1351
|
-
// Authoring target for `sm tutorial`: the open standard discovers skills
|
|
1352
|
-
// under `.agents/skills/<name>/SKILL.md`. The same path is consumed by
|
|
1353
|
-
// Antigravity (adopted the standard rather than a `.gemini/` layout) and
|
|
1354
|
-
// OpenAI Codex (skills mirror the open standard), so `aka` surfaces both
|
|
1355
|
-
// names in the destination prompt to orient testers on those agents.
|
|
1356
|
-
// `aka` is display-only, `--for` still matches the `agent-skills` id.
|
|
1357
|
-
scaffold: { skillDir: ".agents/skills", aka: ["Antigravity", "OpenAI Codex"] },
|
|
1358
|
-
read: { extensions: [".md"], parser: "frontmatter-yaml" },
|
|
1359
|
-
kinds: {
|
|
1360
|
-
skill: {
|
|
1361
|
-
schema: "./schemas/skill.schema.json",
|
|
1362
|
-
schemaJson: skill_schema_default2,
|
|
1363
|
-
ui: {
|
|
1364
|
-
label: "Skills",
|
|
1365
|
-
color: "#10b981",
|
|
1366
|
-
colorDark: "#34d399",
|
|
1367
|
-
icon: { kind: "pi", id: "pi-bolt" }
|
|
1368
|
-
},
|
|
1369
|
-
// Open-standard skills mirror Anthropic's: dirname between
|
|
1370
|
-
// `.agents/skills/` and `/SKILL.md` is the canonical handle,
|
|
1371
|
-
// `frontmatter.name` overrides when present.
|
|
1372
|
-
identifiers: ["frontmatter.name", "dirname"]
|
|
1373
|
-
}
|
|
1374
|
-
},
|
|
1375
|
-
// The open standard documents slash-style invocation of skills; no
|
|
1376
|
-
// mention surface (no agents in this Provider's territory).
|
|
1377
|
-
resolution: {
|
|
1378
|
-
invokes: ["skill"]
|
|
1379
|
-
},
|
|
1380
|
-
classify(path) {
|
|
1381
|
-
if (/^\.agents\/skills\/[^/]+\/skill\.md$/.test(path.toLowerCase())) return "skill";
|
|
1382
|
-
return null;
|
|
1383
|
-
}
|
|
1384
|
-
};
|
|
1385
|
-
|
|
1386
1398
|
// plugins/core/providers/core-markdown/schemas/markdown.schema.json
|
|
1387
1399
|
var markdown_schema_default = {
|
|
1388
1400
|
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
@@ -4548,6 +4560,25 @@ var ENTRY_TEXTS = {
|
|
|
4548
4560
|
*/
|
|
4549
4561
|
bareNoProject: "{{glyph}} No skill-map project found in {{cwd}}.\n {{hint}}\n",
|
|
4550
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]: ",
|
|
4551
4582
|
parseErrorHeadline: "sm: {{message}}",
|
|
4552
4583
|
parseErrorUnknownOption: "unknown option '{{name}}'",
|
|
4553
4584
|
parseErrorUnknownOptionForVerb: "{{verb}}: unknown option '{{name}}'",
|
|
@@ -4780,6 +4811,64 @@ function requireDbOrExit(path, stderr) {
|
|
|
4780
4811
|
return ExitCode.NotFound;
|
|
4781
4812
|
}
|
|
4782
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
|
+
|
|
4783
4872
|
// cli/util/edit-distance.ts
|
|
4784
4873
|
function editDistance(a, b, max) {
|
|
4785
4874
|
if (a === b) return 0;
|
|
@@ -4955,7 +5044,7 @@ function defaultRuntimeContext() {
|
|
|
4955
5044
|
}
|
|
4956
5045
|
|
|
4957
5046
|
// cli/telemetry/first-run-prompt.ts
|
|
4958
|
-
import { createInterface } from "readline/promises";
|
|
5047
|
+
import { createInterface as createInterface2 } from "readline/promises";
|
|
4959
5048
|
|
|
4960
5049
|
// cli/i18n/telemetry.texts.ts
|
|
4961
5050
|
var TELEMETRY_PROMPT_TEXTS = {
|
|
@@ -5258,7 +5347,7 @@ async function runConsentPrompt(stdin, stdout, nowMs) {
|
|
|
5258
5347
|
const rendered = renderConsent(
|
|
5259
5348
|
ansiFor({ isTTY: stdout.isTTY === true, noColorFlag: false })
|
|
5260
5349
|
);
|
|
5261
|
-
const rl =
|
|
5350
|
+
const rl = createInterface2({ input: stdin, output: stdout });
|
|
5262
5351
|
try {
|
|
5263
5352
|
const consented = await readConsentDecision(rl, stdout, rendered);
|
|
5264
5353
|
writeUserSettings({
|
|
@@ -5988,13 +6077,13 @@ var CONSENT_TEXTS = {
|
|
|
5988
6077
|
};
|
|
5989
6078
|
|
|
5990
6079
|
// cli/util/confirm.ts
|
|
5991
|
-
import { createInterface as
|
|
6080
|
+
import { createInterface as createInterface3 } from "readline";
|
|
5992
6081
|
var YES_PATTERN = new RegExp(UTIL_TEXTS.confirmYesPatternSource, "i");
|
|
5993
6082
|
var NO_PATTERN = new RegExp(UTIL_TEXTS.confirmNoPatternSource, "i");
|
|
5994
6083
|
async function confirm(question, streams, opts) {
|
|
5995
6084
|
const defaultAnswer = opts?.defaultAnswer ?? "no";
|
|
5996
6085
|
const suffix = defaultAnswer === "yes" ? UTIL_TEXTS.confirmPromptSuffixDefaultYes : UTIL_TEXTS.confirmPromptSuffix;
|
|
5997
|
-
const rl =
|
|
6086
|
+
const rl = createInterface3({ input: streams.stdin, output: streams.stderr });
|
|
5998
6087
|
try {
|
|
5999
6088
|
const answer = await new Promise(
|
|
6000
6089
|
(resolveP) => rl.question(`${question}${suffix}`, resolveP)
|
|
@@ -6348,7 +6437,7 @@ var AsyncMutex = class {
|
|
|
6348
6437
|
this.#locked = true;
|
|
6349
6438
|
return;
|
|
6350
6439
|
}
|
|
6351
|
-
await new Promise((
|
|
6440
|
+
await new Promise((resolve44) => this.#waiters.push(resolve44));
|
|
6352
6441
|
this.#locked = true;
|
|
6353
6442
|
}
|
|
6354
6443
|
unlock() {
|
|
@@ -6795,7 +6884,7 @@ async function selectReferencedJobFilePaths(db) {
|
|
|
6795
6884
|
}
|
|
6796
6885
|
|
|
6797
6886
|
// kernel/adapters/sqlite/migrations.ts
|
|
6798
|
-
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";
|
|
6799
6888
|
import { dirname as dirname7, join as join5, resolve as resolve10 } from "path";
|
|
6800
6889
|
import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
|
|
6801
6890
|
import { fileURLToPath } from "url";
|
|
@@ -6817,7 +6906,7 @@ function defaultMigrationsDir() {
|
|
|
6817
6906
|
}
|
|
6818
6907
|
function discoverMigrations(dir = defaultMigrationsDir()) {
|
|
6819
6908
|
if (!existsSync8(dir)) return [];
|
|
6820
|
-
const files =
|
|
6909
|
+
const files = readdirSync2(dir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => e.name).filter((name) => FILE_RE.test(name)).sort();
|
|
6821
6910
|
const out = [];
|
|
6822
6911
|
for (const name of files) {
|
|
6823
6912
|
const match = FILE_RE.exec(name);
|
|
@@ -6932,7 +7021,7 @@ function writeBackup(dbPath, destPath) {
|
|
|
6932
7021
|
}
|
|
6933
7022
|
|
|
6934
7023
|
// kernel/adapters/sqlite/plugin-migrations.ts
|
|
6935
|
-
import { existsSync as existsSync9, readFileSync as readFileSync9, readdirSync as
|
|
7024
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9, readdirSync as readdirSync3 } from "fs";
|
|
6936
7025
|
import { join as join6 } from "path";
|
|
6937
7026
|
|
|
6938
7027
|
// kernel/adapters/sqlite/plugin-migrations-validator.ts
|
|
@@ -7252,7 +7341,7 @@ function resolvePluginMigrationsDir(plugin) {
|
|
|
7252
7341
|
function discoverPluginMigrations(plugin) {
|
|
7253
7342
|
const dir = resolvePluginMigrationsDir(plugin);
|
|
7254
7343
|
if (!dir) return [];
|
|
7255
|
-
const files =
|
|
7344
|
+
const files = readdirSync3(dir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => e.name).filter((name) => FILE_RE2.test(name)).sort();
|
|
7256
7345
|
const out = [];
|
|
7257
7346
|
for (const name of files) {
|
|
7258
7347
|
const match = FILE_RE2.exec(name);
|
|
@@ -9851,7 +9940,7 @@ var PLUGIN_LOADER_TEXTS = {
|
|
|
9851
9940
|
|
|
9852
9941
|
// kernel/adapters/plugin-loader/index.ts
|
|
9853
9942
|
import { createRequire as createRequire5 } from "module";
|
|
9854
|
-
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";
|
|
9855
9944
|
import { join as join8, resolve as resolve16 } from "path";
|
|
9856
9945
|
import { pathToFileURL } from "url";
|
|
9857
9946
|
import semver from "semver";
|
|
@@ -10194,9 +10283,9 @@ function providerKindFailure(opts, status, fileName, errDescription) {
|
|
|
10194
10283
|
}
|
|
10195
10284
|
};
|
|
10196
10285
|
}
|
|
10197
|
-
function isDirectorySafe(path,
|
|
10286
|
+
function isDirectorySafe(path, statSync13) {
|
|
10198
10287
|
try {
|
|
10199
|
-
return
|
|
10288
|
+
return statSync13(path).isDirectory();
|
|
10200
10289
|
} catch {
|
|
10201
10290
|
return false;
|
|
10202
10291
|
}
|
|
@@ -10306,7 +10395,7 @@ var PluginLoader = class {
|
|
|
10306
10395
|
const out = [];
|
|
10307
10396
|
for (const root of this.#options.searchPaths) {
|
|
10308
10397
|
if (!existsSync13(root)) continue;
|
|
10309
|
-
for (const entry of
|
|
10398
|
+
for (const entry of readdirSync5(root, { withFileTypes: true })) {
|
|
10310
10399
|
if (!entry.isDirectory()) continue;
|
|
10311
10400
|
const candidate = join8(root, entry.name);
|
|
10312
10401
|
if (existsSync13(join8(candidate, "plugin.json"))) {
|
|
@@ -10677,7 +10766,7 @@ function collectKindEntries(pluginPath, kindDir, out) {
|
|
|
10677
10766
|
if (!existsSync13(kindAbs)) return;
|
|
10678
10767
|
let entries;
|
|
10679
10768
|
try {
|
|
10680
|
-
entries =
|
|
10769
|
+
entries = readdirSync5(kindAbs);
|
|
10681
10770
|
} catch {
|
|
10682
10771
|
return;
|
|
10683
10772
|
}
|
|
@@ -11826,13 +11915,14 @@ function detectProvidersFromFilesystem(cwd, providers) {
|
|
|
11826
11915
|
return out;
|
|
11827
11916
|
}
|
|
11828
11917
|
function isDetectableUnderCwd(cwd, provider) {
|
|
11829
|
-
if (provider.
|
|
11918
|
+
if (!installedDefaultEnabled(provider.stability)) return false;
|
|
11830
11919
|
const markers = provider.detect?.markers;
|
|
11831
11920
|
if (!markers || markers.length === 0) return false;
|
|
11832
11921
|
return markers.some((marker) => existsSync15(join10(cwd, marker)));
|
|
11833
11922
|
}
|
|
11834
11923
|
|
|
11835
11924
|
// core/config/active-provider.ts
|
|
11925
|
+
var MARKDOWN_LENS_ID = "markdown";
|
|
11836
11926
|
function resolveActiveProvider(cwd, providers = []) {
|
|
11837
11927
|
const detected = detectProvidersFromFilesystem(cwd, providers);
|
|
11838
11928
|
const fromConfig = readConfigValue("activeProvider", { cwd });
|
|
@@ -11842,7 +11932,7 @@ function resolveActiveProvider(cwd, providers = []) {
|
|
|
11842
11932
|
if (detected.length > 0) {
|
|
11843
11933
|
return { resolved: detected[0], source: "autodetect", detected };
|
|
11844
11934
|
}
|
|
11845
|
-
return { resolved:
|
|
11935
|
+
return { resolved: MARKDOWN_LENS_ID, source: "default", detected };
|
|
11846
11936
|
}
|
|
11847
11937
|
|
|
11848
11938
|
// cli/util/path-display.ts
|
|
@@ -12580,7 +12670,7 @@ import { Command as Command5, Option as Option5 } from "clipanion";
|
|
|
12580
12670
|
|
|
12581
12671
|
// conformance/index.ts
|
|
12582
12672
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
12583
|
-
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";
|
|
12584
12674
|
import { tmpdir } from "os";
|
|
12585
12675
|
import { isAbsolute as isAbsolute6, join as join11, relative as relative3, resolve as resolve20 } from "path";
|
|
12586
12676
|
|
|
@@ -12736,7 +12826,7 @@ function runPriorScansSetup(c, options, scope, fixturesRoot, setupEnv) {
|
|
|
12736
12826
|
}
|
|
12737
12827
|
function replaceFixture(scope, fixturesRoot, fixture) {
|
|
12738
12828
|
assertContained2(fixturesRoot, fixture, "fixture");
|
|
12739
|
-
for (const entry of
|
|
12829
|
+
for (const entry of readdirSync6(scope)) {
|
|
12740
12830
|
if (entry === KERNEL_SKILL_MAP_DIR) continue;
|
|
12741
12831
|
rmSync(join11(scope, entry), { recursive: true, force: true });
|
|
12742
12832
|
}
|
|
@@ -12973,7 +13063,7 @@ var CONFORMANCE_TEXTS = {
|
|
|
12973
13063
|
};
|
|
12974
13064
|
|
|
12975
13065
|
// cli/util/conformance-scopes.ts
|
|
12976
|
-
import { existsSync as existsSync18, readdirSync as
|
|
13066
|
+
import { existsSync as existsSync18, readdirSync as readdirSync7, statSync as statSync4 } from "fs";
|
|
12977
13067
|
import { dirname as dirname11, resolve as resolve21 } from "path";
|
|
12978
13068
|
import { createRequire as createRequire6 } from "module";
|
|
12979
13069
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -13014,7 +13104,7 @@ function collectProviderScopes(specRoot) {
|
|
|
13014
13104
|
}
|
|
13015
13105
|
const pluginsRoot = resolve21(workspaceRoot, "plugins");
|
|
13016
13106
|
if (!existsSync18(pluginsRoot)) return out;
|
|
13017
|
-
for (const pluginEntry of
|
|
13107
|
+
for (const pluginEntry of readdirSync7(pluginsRoot)) {
|
|
13018
13108
|
const pluginDir = resolve21(pluginsRoot, pluginEntry);
|
|
13019
13109
|
if (!isDir(pluginDir)) continue;
|
|
13020
13110
|
const providersRoot = resolve21(pluginDir, "providers");
|
|
@@ -13031,7 +13121,7 @@ function isDir(path) {
|
|
|
13031
13121
|
}
|
|
13032
13122
|
}
|
|
13033
13123
|
function collectPluginProviderScopes(providersRoot, specRoot, out) {
|
|
13034
|
-
for (const entry of
|
|
13124
|
+
for (const entry of readdirSync7(providersRoot)) {
|
|
13035
13125
|
const providerDir = resolve21(providersRoot, entry);
|
|
13036
13126
|
if (!isDir(providerDir)) continue;
|
|
13037
13127
|
const conformanceDir = resolve21(providerDir, "conformance");
|
|
@@ -13077,7 +13167,7 @@ function selectConformanceScopes(scope) {
|
|
|
13077
13167
|
}
|
|
13078
13168
|
function listCaseFiles(scope) {
|
|
13079
13169
|
if (!existsSync18(scope.casesDir)) return [];
|
|
13080
|
-
return
|
|
13170
|
+
return readdirSync7(scope.casesDir).filter((entry) => entry.endsWith(".json")).sort().map((entry) => resolve21(scope.casesDir, entry));
|
|
13081
13171
|
}
|
|
13082
13172
|
|
|
13083
13173
|
// cli/commands/conformance.ts
|
|
@@ -14206,78 +14296,398 @@ var DB_COMMANDS = [
|
|
|
14206
14296
|
DbMigrateCommand
|
|
14207
14297
|
];
|
|
14208
14298
|
|
|
14209
|
-
// 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";
|
|
14210
14303
|
import { Command as Command13, Option as Option12 } from "clipanion";
|
|
14211
14304
|
|
|
14212
|
-
//
|
|
14213
|
-
var
|
|
14214
|
-
|
|
14215
|
-
|
|
14216
|
-
|
|
14217
|
-
|
|
14218
|
-
}
|
|
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."
|
|
14219
14330
|
};
|
|
14220
|
-
|
|
14221
|
-
|
|
14222
|
-
|
|
14223
|
-
|
|
14224
|
-
|
|
14225
|
-
|
|
14226
|
-
|
|
14227
|
-
|
|
14228
|
-
|
|
14229
|
-
|
|
14230
|
-
|
|
14231
|
-
|
|
14232
|
-
|
|
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
|
-
|
|
14270
|
-
|
|
14271
|
-
|
|
14272
|
-
|
|
14273
|
-
|
|
14274
|
-
|
|
14275
|
-
|
|
14276
|
-
|
|
14277
|
-
|
|
14278
|
-
|
|
14279
|
-
|
|
14280
|
-
|
|
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
|
+
});
|
|
14367
|
+
}
|
|
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
|
+
});
|
|
14378
|
+
}
|
|
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;
|
|
14386
|
+
}
|
|
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.`);
|
|
14398
|
+
}
|
|
14399
|
+
return linesOut.join("\n") + "\n";
|
|
14400
|
+
}
|
|
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
|
+
`;
|
|
14412
|
+
}
|
|
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])}`);
|
|
14452
|
+
}
|
|
14453
|
+
return out;
|
|
14454
|
+
}
|
|
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
|
+
}
|
|
14281
14691
|
return values.includes("issues");
|
|
14282
14692
|
}
|
|
14283
14693
|
function applyExportQuery(scan, query) {
|
|
@@ -14386,7 +14796,7 @@ var DEFERRED_FORMATS = {
|
|
|
14386
14796
|
};
|
|
14387
14797
|
var ExportCommand = class extends SmCommand {
|
|
14388
14798
|
static paths = [["export"]];
|
|
14389
|
-
static usage =
|
|
14799
|
+
static usage = Command14.Usage({
|
|
14390
14800
|
category: "Browse",
|
|
14391
14801
|
description: "Filtered export. Query syntax is implementation-defined pre-1.0.",
|
|
14392
14802
|
details: `
|
|
@@ -14411,8 +14821,8 @@ var ExportCommand = class extends SmCommand {
|
|
|
14411
14821
|
["Files under a path glob", '$0 export "path=.claude/commands/**" --format json']
|
|
14412
14822
|
]
|
|
14413
14823
|
});
|
|
14414
|
-
query =
|
|
14415
|
-
format =
|
|
14824
|
+
query = Option13.String({ required: false });
|
|
14825
|
+
format = Option13.String("--format", { required: false });
|
|
14416
14826
|
async run() {
|
|
14417
14827
|
const stderrAnsi = this.ansiFor("stderr");
|
|
14418
14828
|
const errGlyph = stderrAnsi.red("\u2715");
|
|
@@ -14636,7 +15046,7 @@ function pickTitle2(node) {
|
|
|
14636
15046
|
}
|
|
14637
15047
|
|
|
14638
15048
|
// cli/commands/graph.ts
|
|
14639
|
-
import { Command as
|
|
15049
|
+
import { Command as Command15, Option as Option14 } from "clipanion";
|
|
14640
15050
|
|
|
14641
15051
|
// cli/i18n/graph.texts.ts
|
|
14642
15052
|
var GRAPH_TEXTS = {
|
|
@@ -14654,7 +15064,7 @@ var GRAPH_TEXTS = {
|
|
|
14654
15064
|
var DEFAULT_FORMAT = "ascii";
|
|
14655
15065
|
var GraphCommand = class extends SmCommand {
|
|
14656
15066
|
static paths = [["graph"]];
|
|
14657
|
-
static usage =
|
|
15067
|
+
static usage = Command15.Usage({
|
|
14658
15068
|
category: "Browse",
|
|
14659
15069
|
description: "Render the full graph via the named formatter.",
|
|
14660
15070
|
details: `
|
|
@@ -14671,10 +15081,10 @@ var GraphCommand = class extends SmCommand {
|
|
|
14671
15081
|
["Use a non-default DB file", "$0 graph --db /path/to/skill-map.db"]
|
|
14672
15082
|
]
|
|
14673
15083
|
});
|
|
14674
|
-
format =
|
|
15084
|
+
format = Option14.String("--format", DEFAULT_FORMAT, {
|
|
14675
15085
|
description: `Formatter format. Must match the \`formatId\` field of a registered formatter. Default: ${DEFAULT_FORMAT}.`
|
|
14676
15086
|
});
|
|
14677
|
-
noPlugins =
|
|
15087
|
+
noPlugins = Option14.Boolean("--no-plugins", false, {
|
|
14678
15088
|
description: "Skip drop-in plugin discovery. Only built-in formatters participate."
|
|
14679
15089
|
});
|
|
14680
15090
|
async run() {
|
|
@@ -14725,8 +15135,8 @@ var GraphCommand = class extends SmCommand {
|
|
|
14725
15135
|
// cli/commands/help.ts
|
|
14726
15136
|
import { readFileSync as readFileSync17 } from "fs";
|
|
14727
15137
|
import { createRequire as createRequire7 } from "module";
|
|
14728
|
-
import { resolve as
|
|
14729
|
-
import { Command as
|
|
15138
|
+
import { resolve as resolve27 } from "path";
|
|
15139
|
+
import { Command as Command16, Option as Option15 } from "clipanion";
|
|
14730
15140
|
|
|
14731
15141
|
// cli/i18n/help.texts.ts
|
|
14732
15142
|
var HELP_TEXTS = {
|
|
@@ -14869,9 +15279,9 @@ var HELP_GROUPS = {
|
|
|
14869
15279
|
};
|
|
14870
15280
|
|
|
14871
15281
|
// cli/commands/help.ts
|
|
14872
|
-
var HelpCommand = class extends
|
|
15282
|
+
var HelpCommand = class extends Command16 {
|
|
14873
15283
|
static paths = [["help"]];
|
|
14874
|
-
static usage =
|
|
15284
|
+
static usage = Command16.Usage({
|
|
14875
15285
|
category: "Introspection",
|
|
14876
15286
|
description: "Self-describing introspection. --format human|md|json.",
|
|
14877
15287
|
details: `
|
|
@@ -14884,13 +15294,13 @@ var HelpCommand = class extends Command15 {
|
|
|
14884
15294
|
json : structured surface dump per spec/cli-contract.md.
|
|
14885
15295
|
`
|
|
14886
15296
|
});
|
|
14887
|
-
verbParts =
|
|
14888
|
-
format =
|
|
15297
|
+
verbParts = Option15.Rest({ required: 0 });
|
|
15298
|
+
format = Option15.String("--format", "human");
|
|
14889
15299
|
// `HelpCommand` extends Clipanion's `Command` directly (see block
|
|
14890
15300
|
// comment), so it does not inherit `SmCommand`'s `--no-color`. Declared
|
|
14891
15301
|
// here because the human overview now emits a coloured tutorial glyph;
|
|
14892
15302
|
// `ansiFor` still layers `NO_COLOR` / `FORCE_COLOR` / TTY on top.
|
|
14893
|
-
noColor =
|
|
15303
|
+
noColor = Option15.Boolean("--no-color", false, {
|
|
14894
15304
|
description: "Disable ANSI color codes."
|
|
14895
15305
|
});
|
|
14896
15306
|
async execute() {
|
|
@@ -15039,7 +15449,7 @@ function resolveSpecVersion() {
|
|
|
15039
15449
|
try {
|
|
15040
15450
|
const req = createRequire7(import.meta.url);
|
|
15041
15451
|
const indexPath = req.resolve("@skill-map/spec/index.json");
|
|
15042
|
-
const pkgPath =
|
|
15452
|
+
const pkgPath = resolve27(indexPath, "..", "package.json");
|
|
15043
15453
|
const pkg = JSON.parse(readFileSync17(pkgPath, "utf8"));
|
|
15044
15454
|
return pkg.version;
|
|
15045
15455
|
} catch {
|
|
@@ -15282,12 +15692,12 @@ function renderCompactOverview(verbs, ansi) {
|
|
|
15282
15692
|
lines.push(HELP_TEXTS.compactFooter);
|
|
15283
15693
|
return lines.join("\n") + "\n";
|
|
15284
15694
|
}
|
|
15285
|
-
var RootHelpCommand = class extends
|
|
15695
|
+
var RootHelpCommand = class extends Command16 {
|
|
15286
15696
|
static paths = [["-h"], ["--help"]];
|
|
15287
15697
|
// Mirrors `HelpCommand.noColor`: this command extends Clipanion's
|
|
15288
15698
|
// `Command` directly, so the flag is declared here to gate the
|
|
15289
15699
|
// coloured tutorial glyph in the overview.
|
|
15290
|
-
noColor =
|
|
15700
|
+
noColor = Option15.Boolean("--no-color", false, {
|
|
15291
15701
|
description: "Disable ANSI color codes."
|
|
15292
15702
|
});
|
|
15293
15703
|
async execute() {
|
|
@@ -15347,8 +15757,8 @@ function registeredVerbPaths(cli2) {
|
|
|
15347
15757
|
|
|
15348
15758
|
// cli/commands/hooks.ts
|
|
15349
15759
|
import { chmod as chmod2, mkdir as mkdir3, readFile as readFile2, stat as stat2, writeFile } from "fs/promises";
|
|
15350
|
-
import { dirname as
|
|
15351
|
-
import { Command as
|
|
15760
|
+
import { dirname as dirname17, resolve as resolve28 } from "path";
|
|
15761
|
+
import { Command as Command17, Option as Option16 } from "clipanion";
|
|
15352
15762
|
|
|
15353
15763
|
// cli/i18n/hooks.texts.ts
|
|
15354
15764
|
var HOOKS_TEXTS = {
|
|
@@ -15395,7 +15805,7 @@ var SKILL_MAP_BLOCK = [
|
|
|
15395
15805
|
var FRESH_HOOK_BODY = HOOK_SHEBANG + SKILL_MAP_BLOCK;
|
|
15396
15806
|
var HooksInstallCommand = class extends SmCommand {
|
|
15397
15807
|
static paths = [["hooks", "install"]];
|
|
15398
|
-
static usage =
|
|
15808
|
+
static usage = Command17.Usage({
|
|
15399
15809
|
category: "Actions",
|
|
15400
15810
|
description: "Install a git pre-commit hook that auto-bumps staged sidecar drift.",
|
|
15401
15811
|
details: `
|
|
@@ -15418,8 +15828,8 @@ var HooksInstallCommand = class extends SmCommand {
|
|
|
15418
15828
|
["Preview what would be written", "$0 hooks install pre-commit-bump --dry-run"]
|
|
15419
15829
|
]
|
|
15420
15830
|
});
|
|
15421
|
-
flavour =
|
|
15422
|
-
dryRun =
|
|
15831
|
+
flavour = Option16.String({ required: true });
|
|
15832
|
+
dryRun = Option16.Boolean("-n,--dry-run", false);
|
|
15423
15833
|
// The remaining cyclomatic count is from CLI ergonomics, flavour
|
|
15424
15834
|
// guard, repo lookup, marker detection, dry-run / json / chained /
|
|
15425
15835
|
// fresh branches each contributing a guard. Inner work already lives
|
|
@@ -15450,8 +15860,8 @@ var HooksInstallCommand = class extends SmCommand {
|
|
|
15450
15860
|
);
|
|
15451
15861
|
return ExitCode.NotFound;
|
|
15452
15862
|
}
|
|
15453
|
-
const hooksDir =
|
|
15454
|
-
const hookPath =
|
|
15863
|
+
const hooksDir = resolve28(repoRoot, ".git", "hooks");
|
|
15864
|
+
const hookPath = resolve28(hooksDir, "pre-commit");
|
|
15455
15865
|
const existing = await pathExists(hookPath) ? await readFile2(hookPath, "utf8") : null;
|
|
15456
15866
|
const planned2 = computePlannedHookContent(existing);
|
|
15457
15867
|
if (planned2.kind === "already-installed") {
|
|
@@ -15509,8 +15919,8 @@ var HooksInstallCommand = class extends SmCommand {
|
|
|
15509
15919
|
async function findGitRepoRoot(cwd) {
|
|
15510
15920
|
let current = cwd;
|
|
15511
15921
|
while (true) {
|
|
15512
|
-
if (await pathExists(
|
|
15513
|
-
const parent =
|
|
15922
|
+
if (await pathExists(resolve28(current, ".git"))) return current;
|
|
15923
|
+
const parent = dirname17(current);
|
|
15514
15924
|
if (parent === current) return null;
|
|
15515
15925
|
current = parent;
|
|
15516
15926
|
}
|
|
@@ -15532,11 +15942,11 @@ var HOOKS_COMMANDS = [HooksInstallCommand];
|
|
|
15532
15942
|
// cli/commands/init.ts
|
|
15533
15943
|
import { mkdir as mkdir4, readFile as readFile3, unlink, writeFile as writeFile2 } from "fs/promises";
|
|
15534
15944
|
import { join as join16 } from "path";
|
|
15535
|
-
import { Command as
|
|
15945
|
+
import { Command as Command18, Option as Option17 } from "clipanion";
|
|
15536
15946
|
|
|
15537
15947
|
// kernel/orchestrator/index.ts
|
|
15538
|
-
import { existsSync as
|
|
15539
|
-
import { isAbsolute as
|
|
15948
|
+
import { existsSync as existsSync24, statSync as statSync7 } from "fs";
|
|
15949
|
+
import { isAbsolute as isAbsolute10, resolve as resolve31 } from "path";
|
|
15540
15950
|
import { Tiktoken as Tiktoken2 } from "js-tiktoken/lite";
|
|
15541
15951
|
|
|
15542
15952
|
// kernel/i18n/orchestrator.texts.ts
|
|
@@ -16290,8 +16700,7 @@ function matchesKindPrecondition(ex, kind) {
|
|
|
16290
16700
|
function matchesProviderPrecondition(ex, activeProvider) {
|
|
16291
16701
|
const providers = ex.precondition?.provider;
|
|
16292
16702
|
if (!providers || providers.length === 0) return true;
|
|
16293
|
-
|
|
16294
|
-
return providers.includes(activeProvider);
|
|
16703
|
+
return activeProvider !== null && providers.includes(activeProvider);
|
|
16295
16704
|
}
|
|
16296
16705
|
function splitLegacy(applicableExtractors, applicableQualifiedIds, nodeHashCacheEligible) {
|
|
16297
16706
|
const cachedQualifiedIds = /* @__PURE__ */ new Set();
|
|
@@ -16482,7 +16891,7 @@ function collectBrokenLinks(links, nodes, ctx) {
|
|
|
16482
16891
|
return broken;
|
|
16483
16892
|
}
|
|
16484
16893
|
function applyResolution(link, indexes, ctx) {
|
|
16485
|
-
const resolution =
|
|
16894
|
+
const resolution = resolve29(link, indexes, ctx);
|
|
16486
16895
|
if (resolution === "none") return;
|
|
16487
16896
|
link.resolvedTarget = resolution;
|
|
16488
16897
|
}
|
|
@@ -16497,7 +16906,7 @@ function buildIndexes(nodes, ctx) {
|
|
|
16497
16906
|
}
|
|
16498
16907
|
return { byPath: byPath3, byName, nodeByPath };
|
|
16499
16908
|
}
|
|
16500
|
-
function
|
|
16909
|
+
function resolve29(link, indexes, ctx) {
|
|
16501
16910
|
if (indexes.byPath.has(link.target)) return link.target;
|
|
16502
16911
|
return resolveByName(link, indexes, ctx);
|
|
16503
16912
|
}
|
|
@@ -16886,7 +17295,7 @@ function detectRenamesAndOrphans(prior, current, issues, silenced) {
|
|
|
16886
17295
|
}
|
|
16887
17296
|
|
|
16888
17297
|
// kernel/orchestrator/walk.ts
|
|
16889
|
-
import { isAbsolute as
|
|
17298
|
+
import { isAbsolute as isAbsolute9, resolve as resolve30 } from "path";
|
|
16890
17299
|
|
|
16891
17300
|
// kernel/sidecar/drift.ts
|
|
16892
17301
|
function computeDriftStatus(args2) {
|
|
@@ -16899,8 +17308,8 @@ function computeDriftStatus(args2) {
|
|
|
16899
17308
|
}
|
|
16900
17309
|
|
|
16901
17310
|
// kernel/sidecar/discover-orphans.ts
|
|
16902
|
-
import { existsSync as
|
|
16903
|
-
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";
|
|
16904
17313
|
function discoverOrphanSidecars(roots, shouldSkip) {
|
|
16905
17314
|
const out = [];
|
|
16906
17315
|
for (const root of roots) {
|
|
@@ -16911,13 +17320,13 @@ function discoverOrphanSidecars(roots, shouldSkip) {
|
|
|
16911
17320
|
function walk2(root, current, shouldSkip, out) {
|
|
16912
17321
|
let entries;
|
|
16913
17322
|
try {
|
|
16914
|
-
entries =
|
|
17323
|
+
entries = readdirSync8(current, { withFileTypes: true, encoding: "utf8" });
|
|
16915
17324
|
} catch {
|
|
16916
17325
|
return;
|
|
16917
17326
|
}
|
|
16918
17327
|
for (const entry of entries) {
|
|
16919
17328
|
const full = join13(current, entry.name);
|
|
16920
|
-
const rel =
|
|
17329
|
+
const rel = relative6(root, full).split(sep4).join("/");
|
|
16921
17330
|
if (shouldSkip(rel)) continue;
|
|
16922
17331
|
if (entry.isSymbolicLink()) continue;
|
|
16923
17332
|
if (entry.isDirectory()) {
|
|
@@ -16927,13 +17336,13 @@ function walk2(root, current, shouldSkip, out) {
|
|
|
16927
17336
|
if (!entry.isFile()) continue;
|
|
16928
17337
|
if (!entry.name.endsWith(".sm")) continue;
|
|
16929
17338
|
const expectedMd = `${full.slice(0, -".sm".length)}.md`;
|
|
16930
|
-
if (
|
|
17339
|
+
if (existsSync22(expectedMd) && safeIsFile(expectedMd)) continue;
|
|
16931
17340
|
out.push({ sidecarPath: full, relativePath: rel, expectedMdPath: expectedMd });
|
|
16932
17341
|
}
|
|
16933
17342
|
}
|
|
16934
17343
|
function safeIsFile(path) {
|
|
16935
17344
|
try {
|
|
16936
|
-
return
|
|
17345
|
+
return statSync6(path).isFile();
|
|
16937
17346
|
} catch {
|
|
16938
17347
|
return false;
|
|
16939
17348
|
}
|
|
@@ -16941,8 +17350,8 @@ function safeIsFile(path) {
|
|
|
16941
17350
|
|
|
16942
17351
|
// kernel/orchestrator/node-build.ts
|
|
16943
17352
|
import { createHash as createHash2 } from "crypto";
|
|
16944
|
-
import { existsSync as
|
|
16945
|
-
import { isAbsolute as
|
|
17353
|
+
import { existsSync as existsSync23 } from "fs";
|
|
17354
|
+
import { isAbsolute as isAbsolute8, resolve as resolvePath } from "path";
|
|
16946
17355
|
import "js-tiktoken/lite";
|
|
16947
17356
|
import yaml4 from "js-yaml";
|
|
16948
17357
|
|
|
@@ -17105,12 +17514,12 @@ function resolveSidecarOverlay(relativePath2, nodePathForIssue, roots, liveBodyH
|
|
|
17105
17514
|
};
|
|
17106
17515
|
}
|
|
17107
17516
|
function resolveAbsoluteMdPath(relativePath2, roots) {
|
|
17108
|
-
if (
|
|
17109
|
-
return
|
|
17517
|
+
if (isAbsolute8(relativePath2)) {
|
|
17518
|
+
return existsSync23(relativePath2) ? relativePath2 : null;
|
|
17110
17519
|
}
|
|
17111
17520
|
for (const root of roots) {
|
|
17112
17521
|
const candidate = resolvePath(root, relativePath2);
|
|
17113
|
-
if (
|
|
17522
|
+
if (existsSync23(candidate)) return candidate;
|
|
17114
17523
|
}
|
|
17115
17524
|
return null;
|
|
17116
17525
|
}
|
|
@@ -17332,8 +17741,8 @@ function expandSidecarPaths(paths, priorNodesByPath) {
|
|
|
17332
17741
|
}
|
|
17333
17742
|
function toAbsolute(relPath, roots) {
|
|
17334
17743
|
const root = roots[0] ?? ".";
|
|
17335
|
-
const absRoot =
|
|
17336
|
-
return
|
|
17744
|
+
const absRoot = isAbsolute9(root) ? root : resolve30(root);
|
|
17745
|
+
return resolve30(absRoot, relPath);
|
|
17337
17746
|
}
|
|
17338
17747
|
function resolveEffectiveCaps(opts) {
|
|
17339
17748
|
return {
|
|
@@ -17351,7 +17760,6 @@ function buildPriorMtimes(opts) {
|
|
|
17351
17760
|
}
|
|
17352
17761
|
function providerParticipates(provider, activeProvider) {
|
|
17353
17762
|
if (!provider.gatedByActiveLens) return true;
|
|
17354
|
-
if (activeProvider === null) return true;
|
|
17355
17763
|
return provider.id === activeProvider;
|
|
17356
17764
|
}
|
|
17357
17765
|
function createWalkAccumulators() {
|
|
@@ -17773,8 +18181,7 @@ function buildPostWalkTransformCtx(providers, nodes, activeProvider) {
|
|
|
17773
18181
|
const reservedNodePaths = buildReservedNodePaths(
|
|
17774
18182
|
nodes,
|
|
17775
18183
|
kindRegistry,
|
|
17776
|
-
reservedNamesByProviderKind
|
|
17777
|
-
activeProvider
|
|
18184
|
+
reservedNamesByProviderKind
|
|
17778
18185
|
);
|
|
17779
18186
|
return { kindRegistry, providerResolution, activeProvider, reservedNodePaths };
|
|
17780
18187
|
}
|
|
@@ -17805,15 +18212,14 @@ function indexReservedNames(provider, out) {
|
|
|
17805
18212
|
}
|
|
17806
18213
|
}
|
|
17807
18214
|
}
|
|
17808
|
-
function buildReservedNodePaths(nodes, kindRegistry, reservedNamesByProviderKind
|
|
18215
|
+
function buildReservedNodePaths(nodes, kindRegistry, reservedNamesByProviderKind) {
|
|
17809
18216
|
const out = /* @__PURE__ */ new Set();
|
|
17810
18217
|
for (const node of nodes) {
|
|
17811
18218
|
const selfKey = `${node.provider}/${node.kind}`;
|
|
17812
18219
|
const selfReserved = reservedNamesByProviderKind.get(selfKey);
|
|
17813
|
-
|
|
17814
|
-
if (!hasEntries(selfReserved) && !hasEntries(lensReserved)) continue;
|
|
18220
|
+
if (!hasEntries(selfReserved)) continue;
|
|
17815
18221
|
const ids = deriveNodeIdentifiers(node, kindRegistry.get(selfKey));
|
|
17816
|
-
if (ids.some((id) => selfReserved?.has(id) === true
|
|
18222
|
+
if (ids.some((id) => selfReserved?.has(id) === true)) {
|
|
17817
18223
|
out.add(node.path);
|
|
17818
18224
|
}
|
|
17819
18225
|
}
|
|
@@ -17926,7 +18332,7 @@ function validateRoots(roots) {
|
|
|
17926
18332
|
throw new Error(ORCHESTRATOR_TEXTS.runScanRootEmptyArray);
|
|
17927
18333
|
}
|
|
17928
18334
|
for (const root of roots) {
|
|
17929
|
-
if (!
|
|
18335
|
+
if (!existsSync24(root) || !statSync7(root).isDirectory()) {
|
|
17930
18336
|
throw new Error(tx(ORCHESTRATOR_TEXTS.runScanRootMissing, { root }));
|
|
17931
18337
|
}
|
|
17932
18338
|
}
|
|
@@ -17934,8 +18340,8 @@ function validateRoots(roots) {
|
|
|
17934
18340
|
function resolveActiveProviderOption(optionValue, roots, providers) {
|
|
17935
18341
|
if (optionValue !== void 0) return optionValue;
|
|
17936
18342
|
for (const root of roots) {
|
|
17937
|
-
const absRoot =
|
|
17938
|
-
if (!
|
|
18343
|
+
const absRoot = isAbsolute10(root) ? root : resolve31(root);
|
|
18344
|
+
if (!existsSync24(absRoot)) continue;
|
|
17939
18345
|
const detected = detectProvidersFromFilesystem(absRoot, providers)[0] ?? null;
|
|
17940
18346
|
if (detected !== null) return detected;
|
|
17941
18347
|
}
|
|
@@ -17943,10 +18349,10 @@ function resolveActiveProviderOption(optionValue, roots, providers) {
|
|
|
17943
18349
|
}
|
|
17944
18350
|
|
|
17945
18351
|
// kernel/scan/watcher.ts
|
|
17946
|
-
import { resolve as
|
|
18352
|
+
import { resolve as resolve32, relative as relative7, sep as sep5 } from "path";
|
|
17947
18353
|
import chokidar from "chokidar";
|
|
17948
18354
|
function createChokidarWatcher(opts) {
|
|
17949
|
-
const absRoots = opts.roots.map((r) =>
|
|
18355
|
+
const absRoots = opts.roots.map((r) => resolve32(opts.cwd, r));
|
|
17950
18356
|
const ignoreFilterOpt = opts.ignoreFilter;
|
|
17951
18357
|
const getFilter = ignoreFilterOpt === void 0 ? void 0 : typeof ignoreFilterOpt === "function" ? ignoreFilterOpt : () => ignoreFilterOpt;
|
|
17952
18358
|
const ignored = getFilter ? (path) => {
|
|
@@ -18039,7 +18445,7 @@ function createChokidarWatcher(opts) {
|
|
|
18039
18445
|
}
|
|
18040
18446
|
function relativePathFromRoots2(absolute, absRoots) {
|
|
18041
18447
|
for (const root of absRoots) {
|
|
18042
|
-
const rel =
|
|
18448
|
+
const rel = relative7(root, absolute);
|
|
18043
18449
|
if (rel === "" || rel === ".") return "";
|
|
18044
18450
|
if (!rel.startsWith("..") && !rel.startsWith(`..${sep5}`)) {
|
|
18045
18451
|
return rel.split(sep5).join("/");
|
|
@@ -18374,23 +18780,6 @@ var SCAN_RUNNER_TEXTS = {
|
|
|
18374
18780
|
* operator notices a typo without the walker silently swallowing it.
|
|
18375
18781
|
*/
|
|
18376
18782
|
referenceWalkMissingRoot: 'scan.referencePaths: configured path "{{path}}" does not exist; skipped.',
|
|
18377
|
-
/**
|
|
18378
|
-
* Active-provider bootstrap: filesystem auto-detect found no
|
|
18379
|
-
* markers (`.claude/`, `.codex/`, `AGENTS.md`, `.cursor/`) anywhere
|
|
18380
|
-
* under cwd or the effective scan roots. Plain-markdown projects
|
|
18381
|
-
* keep scanning fine; provider-specific extractors silently no-op
|
|
18382
|
-
* for this scan. Follows `context/cli-output-style.md` §3.1b
|
|
18383
|
-
* (two-line block, glyph + dim hint):
|
|
18384
|
-
* - line 1: `{{glyph}}` (yellow `⚠`) + headline naming the
|
|
18385
|
-
* missing markers,
|
|
18386
|
-
* - line 2 (indent 3): `{{hint}}`, dim, names the consequence
|
|
18387
|
-
* and the actionable next step.
|
|
18388
|
-
* Both the full block AND the bare hint are catalog-side so the
|
|
18389
|
-
* caller can wrap the hint in `ansi.dim(...)` without splitting
|
|
18390
|
-
* the template manually.
|
|
18391
|
-
*/
|
|
18392
|
-
activeProviderNoMarkerWarning: "{{glyph}} No provider markers detected (.claude/, .codex/, AGENTS.md, .cursor/).\n {{hint}}\n",
|
|
18393
|
-
activeProviderNoMarkerWarningHint: "Scanning as universal markdown only; provider-specific link types (e.g. claude @-directives, /-commands) will not appear. Set `activeProvider` in .skill-map/settings.json or install a provider plugin to enable them.",
|
|
18394
18783
|
/**
|
|
18395
18784
|
* Active-provider bootstrap: filesystem auto-detect found exactly
|
|
18396
18785
|
* one marker and persisted the detected id to project settings.
|
|
@@ -18467,9 +18856,9 @@ function resolveScanRoots(inputs) {
|
|
|
18467
18856
|
}
|
|
18468
18857
|
|
|
18469
18858
|
// core/runtime/reference-paths-walker.ts
|
|
18470
|
-
import { readdirSync as
|
|
18859
|
+
import { readdirSync as readdirSync9, statSync as statSync8 } from "fs";
|
|
18471
18860
|
import { homedir as osHomedir2 } from "os";
|
|
18472
|
-
import { isAbsolute as
|
|
18861
|
+
import { isAbsolute as isAbsolute11, join as join14, resolve as resolve33 } from "path";
|
|
18473
18862
|
var REFERENCE_WALK_MAX_FILES = 5e4;
|
|
18474
18863
|
var SKIPPED_DIR_NAMES = /* @__PURE__ */ new Set([
|
|
18475
18864
|
"node_modules",
|
|
@@ -18477,10 +18866,10 @@ var SKIPPED_DIR_NAMES = /* @__PURE__ */ new Set([
|
|
|
18477
18866
|
SKILL_MAP_DIR
|
|
18478
18867
|
]);
|
|
18479
18868
|
function resolveScanPath(raw, cwd) {
|
|
18480
|
-
if (raw.startsWith("~/")) return
|
|
18481
|
-
if (raw === "~") return
|
|
18482
|
-
if (
|
|
18483
|
-
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);
|
|
18484
18873
|
}
|
|
18485
18874
|
function walkReferencePaths(rawRoots, cwd) {
|
|
18486
18875
|
const paths = /* @__PURE__ */ new Set();
|
|
@@ -18502,7 +18891,7 @@ function walkInto(dir, out) {
|
|
|
18502
18891
|
if (out.size >= REFERENCE_WALK_MAX_FILES) return true;
|
|
18503
18892
|
let entries;
|
|
18504
18893
|
try {
|
|
18505
|
-
entries =
|
|
18894
|
+
entries = readdirSync9(dir, { withFileTypes: true });
|
|
18506
18895
|
} catch {
|
|
18507
18896
|
return false;
|
|
18508
18897
|
}
|
|
@@ -18521,15 +18910,15 @@ function walkInto(dir, out) {
|
|
|
18521
18910
|
}
|
|
18522
18911
|
function safeStat(path) {
|
|
18523
18912
|
try {
|
|
18524
|
-
return
|
|
18913
|
+
return statSync8(path);
|
|
18525
18914
|
} catch {
|
|
18526
18915
|
return null;
|
|
18527
18916
|
}
|
|
18528
18917
|
}
|
|
18529
18918
|
|
|
18530
18919
|
// core/runtime/active-provider-bootstrap.ts
|
|
18531
|
-
import { createInterface as
|
|
18532
|
-
import { isAbsolute as
|
|
18920
|
+
import { createInterface as createInterface4 } from "readline";
|
|
18921
|
+
import { isAbsolute as isAbsolute12, join as join15 } from "path";
|
|
18533
18922
|
async function bootstrapActiveProvider(opts) {
|
|
18534
18923
|
const fromCwd = resolveActiveProvider(opts.cwd, opts.providers);
|
|
18535
18924
|
if (fromCwd.source === "config") {
|
|
@@ -18549,15 +18938,7 @@ async function bootstrapActiveProvider(opts) {
|
|
|
18549
18938
|
opts.providers
|
|
18550
18939
|
);
|
|
18551
18940
|
if (detected.length === 0) {
|
|
18552
|
-
|
|
18553
|
-
const dim = opts.style?.dim ?? ((s) => s);
|
|
18554
|
-
opts.printer.warn(
|
|
18555
|
-
tx(SCAN_RUNNER_TEXTS.activeProviderNoMarkerWarning, {
|
|
18556
|
-
glyph: warnGlyph,
|
|
18557
|
-
hint: dim(SCAN_RUNNER_TEXTS.activeProviderNoMarkerWarningHint)
|
|
18558
|
-
})
|
|
18559
|
-
);
|
|
18560
|
-
return { kind: "ok", activeProvider: null, source: "none" };
|
|
18941
|
+
return { kind: "ok", activeProvider: MARKDOWN_LENS_ID, source: "default" };
|
|
18561
18942
|
}
|
|
18562
18943
|
if (detected.length === 1) {
|
|
18563
18944
|
const picked2 = detected[0];
|
|
@@ -18588,7 +18969,7 @@ function aggregateDetected(cwd, effectiveRoots, cwdDetected, providers) {
|
|
|
18588
18969
|
out.push(id);
|
|
18589
18970
|
}
|
|
18590
18971
|
for (const root of effectiveRoots) {
|
|
18591
|
-
const absRoot =
|
|
18972
|
+
const absRoot = isAbsolute12(root) ? root : join15(cwd, root);
|
|
18592
18973
|
const r = resolveActiveProvider(absRoot, providers);
|
|
18593
18974
|
for (const id of r.detected) {
|
|
18594
18975
|
if (seen.has(id)) continue;
|
|
@@ -18620,7 +19001,13 @@ function handleDrift(opts, resolvedLens, currentMarkers) {
|
|
|
18620
19001
|
backfillMarkersSnapshot(opts.cwd, currentMarkers);
|
|
18621
19002
|
return;
|
|
18622
19003
|
}
|
|
18623
|
-
const
|
|
19004
|
+
const shipsDisabled = new Set(
|
|
19005
|
+
opts.providers.filter((p) => !installedDefaultEnabled(p.stability)).map((p) => p.id)
|
|
19006
|
+
);
|
|
19007
|
+
const diff = diffMarkers(
|
|
19008
|
+
snapshot.filter((id) => !shipsDisabled.has(id)),
|
|
19009
|
+
currentMarkers.filter((id) => !shipsDisabled.has(id))
|
|
19010
|
+
);
|
|
18624
19011
|
if (diff.added.length === 0 && diff.removed.length === 0) return;
|
|
18625
19012
|
emitDriftWarn(opts, resolvedLens, diff);
|
|
18626
19013
|
}
|
|
@@ -18630,7 +19017,7 @@ function emitDriftWarn(opts, resolvedLens, diff) {
|
|
|
18630
19017
|
const hint = tx(SCAN_RUNNER_TEXTS.activeProviderDriftWarnHint, {
|
|
18631
19018
|
added: diff.added.length === 0 ? "(none)" : diff.added.join(", "),
|
|
18632
19019
|
removed: diff.removed.length === 0 ? "(none)" : diff.removed.join(", "),
|
|
18633
|
-
currentLens: resolvedLens
|
|
19020
|
+
currentLens: resolvedLens
|
|
18634
19021
|
});
|
|
18635
19022
|
opts.printer.warn(
|
|
18636
19023
|
tx(SCAN_RUNNER_TEXTS.activeProviderDriftWarn, {
|
|
@@ -18662,7 +19049,6 @@ function diffMarkers(snapshot, current) {
|
|
|
18662
19049
|
return { added, removed };
|
|
18663
19050
|
}
|
|
18664
19051
|
function warnIfLensPluginDisabled(args2) {
|
|
18665
|
-
if (args2.activeProvider === null) return;
|
|
18666
19052
|
if (args2.resolveEnabled(args2.activeProvider)) return;
|
|
18667
19053
|
args2.printer.warn(
|
|
18668
19054
|
tx(SCAN_RUNNER_TEXTS.activeProviderPluginDisabledWarning, {
|
|
@@ -18683,7 +19069,7 @@ async function promptForLens(detected, stdin, stderr, warnGlyph) {
|
|
|
18683
19069
|
);
|
|
18684
19070
|
}
|
|
18685
19071
|
stderr.write(lines.join("\n") + "\n");
|
|
18686
|
-
const rl =
|
|
19072
|
+
const rl = createInterface4({ input: stdin, output: stderr });
|
|
18687
19073
|
try {
|
|
18688
19074
|
const answer = await new Promise(
|
|
18689
19075
|
(resolveP) => rl.question(SCAN_RUNNER_TEXTS.activeProviderPromptInput, resolveP)
|
|
@@ -18701,8 +19087,8 @@ async function promptForLens(detected, stdin, stderr, warnGlyph) {
|
|
|
18701
19087
|
}
|
|
18702
19088
|
|
|
18703
19089
|
// core/sqlite/db-drift-reset.ts
|
|
18704
|
-
import { existsSync as
|
|
18705
|
-
import { createInterface as
|
|
19090
|
+
import { existsSync as existsSync25 } from "fs";
|
|
19091
|
+
import { createInterface as createInterface5 } from "readline";
|
|
18706
19092
|
import { DatabaseSync as DatabaseSync8 } from "node:sqlite";
|
|
18707
19093
|
|
|
18708
19094
|
// core/sqlite/i18n/db-drift.texts.ts
|
|
@@ -18753,7 +19139,7 @@ function detectDriftReason(dbPath, currentVersion) {
|
|
|
18753
19139
|
return classifyFingerprint(dbPath).kind === "drift" ? "schema" : null;
|
|
18754
19140
|
}
|
|
18755
19141
|
function readScannedByVersion(dbPath) {
|
|
18756
|
-
if (dbPath === ":memory:" || !
|
|
19142
|
+
if (dbPath === ":memory:" || !existsSync25(dbPath)) return null;
|
|
18757
19143
|
let raw = null;
|
|
18758
19144
|
try {
|
|
18759
19145
|
raw = new DatabaseSync8(dbPath, { readOnly: true });
|
|
@@ -18786,7 +19172,7 @@ async function askDriftReset(dbVersion, reason, policy) {
|
|
|
18786
19172
|
hint: dim(DB_DRIFT_TEXTS.driftPromptHint)
|
|
18787
19173
|
})
|
|
18788
19174
|
);
|
|
18789
|
-
const rl =
|
|
19175
|
+
const rl = createInterface5({ input: policy.stdin, output: policy.stderr });
|
|
18790
19176
|
try {
|
|
18791
19177
|
const answer = await new Promise(
|
|
18792
19178
|
(resolveP) => rl.question(DB_DRIFT_TEXTS.driftPromptQuestion, resolveP)
|
|
@@ -19145,7 +19531,7 @@ var INIT_TEXTS = {
|
|
|
19145
19531
|
// cli/commands/init.ts
|
|
19146
19532
|
var InitCommand = class extends SmCommand {
|
|
19147
19533
|
static paths = [["init"]];
|
|
19148
|
-
static usage =
|
|
19534
|
+
static usage = Command18.Usage({
|
|
19149
19535
|
category: "Setup",
|
|
19150
19536
|
description: "Bootstrap the current project: scaffold .skill-map/, provision DB, run first scan.",
|
|
19151
19537
|
details: `
|
|
@@ -19164,16 +19550,16 @@ var InitCommand = class extends SmCommand {
|
|
|
19164
19550
|
["Preview what would be created", "$0 init --dry-run"]
|
|
19165
19551
|
]
|
|
19166
19552
|
});
|
|
19167
|
-
noScan =
|
|
19553
|
+
noScan = Option17.Boolean("--no-scan", false, {
|
|
19168
19554
|
description: "Skip the first scan after scaffolding."
|
|
19169
19555
|
});
|
|
19170
|
-
force =
|
|
19556
|
+
force = Option17.Boolean("--force", false, {
|
|
19171
19557
|
description: "Overwrite an existing settings.json / settings.local.json / .skillmapignore."
|
|
19172
19558
|
});
|
|
19173
|
-
strict =
|
|
19559
|
+
strict = Option17.Boolean("--strict", false, {
|
|
19174
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."
|
|
19175
19561
|
});
|
|
19176
|
-
dryRun =
|
|
19562
|
+
dryRun = Option17.Boolean("-n,--dry-run", false, {
|
|
19177
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."
|
|
19178
19564
|
});
|
|
19179
19565
|
// CLI orchestrator: paths setup + dry-run branch (delegated to
|
|
@@ -19426,7 +19812,7 @@ async function ensureGitignoreEntries(scopeRoot, entries) {
|
|
|
19426
19812
|
}
|
|
19427
19813
|
|
|
19428
19814
|
// cli/commands/history.ts
|
|
19429
|
-
import { Command as
|
|
19815
|
+
import { Command as Command19, Option as Option18 } from "clipanion";
|
|
19430
19816
|
|
|
19431
19817
|
// cli/i18n/history.texts.ts
|
|
19432
19818
|
var HISTORY_TEXTS = {
|
|
@@ -19544,7 +19930,7 @@ function parseStatuses(input, stderr, ansi) {
|
|
|
19544
19930
|
}
|
|
19545
19931
|
var HistoryCommand = class extends SmCommand {
|
|
19546
19932
|
static paths = [["history"]];
|
|
19547
|
-
static usage =
|
|
19933
|
+
static usage = Command19.Usage({
|
|
19548
19934
|
category: "History",
|
|
19549
19935
|
description: "Filter execution records. --json emits an array conforming to execution-record.schema.json.",
|
|
19550
19936
|
details: `
|
|
@@ -19564,12 +19950,12 @@ var HistoryCommand = class extends SmCommand {
|
|
|
19564
19950
|
["Machine-readable, scoped to one node", "$0 history -n skills/foo.md --json"]
|
|
19565
19951
|
]
|
|
19566
19952
|
});
|
|
19567
|
-
node =
|
|
19568
|
-
action =
|
|
19569
|
-
status =
|
|
19570
|
-
since =
|
|
19571
|
-
until =
|
|
19572
|
-
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 });
|
|
19573
19959
|
// CLI list verb: many optional filter flags (`--node`, `--action`,
|
|
19574
19960
|
// `--status`, `--since`, `--until`, `--limit`, `--json`, `--quiet`)
|
|
19575
19961
|
// each adding a guarded mutation to the filter or render path. Each
|
|
@@ -19620,7 +20006,7 @@ var HistoryCommand = class extends SmCommand {
|
|
|
19620
20006
|
};
|
|
19621
20007
|
var HistoryStatsCommand = class extends SmCommand {
|
|
19622
20008
|
static paths = [["history", "stats"]];
|
|
19623
|
-
static usage =
|
|
20009
|
+
static usage = Command19.Usage({
|
|
19624
20010
|
category: "History",
|
|
19625
20011
|
description: "Aggregate counts, tokens, periods, top nodes, and error rates over state_executions. --json conforms to history-stats.schema.json.",
|
|
19626
20012
|
details: `
|
|
@@ -19638,10 +20024,10 @@ var HistoryStatsCommand = class extends SmCommand {
|
|
|
19638
20024
|
["Top 5 nodes, JSON", "$0 history stats --top 5 --json"]
|
|
19639
20025
|
]
|
|
19640
20026
|
});
|
|
19641
|
-
since =
|
|
19642
|
-
until =
|
|
19643
|
-
period =
|
|
19644
|
-
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 });
|
|
19645
20031
|
// CLI stats verb: range parsing + window flags + period flag + JSON
|
|
19646
20032
|
// branch + per-period iteration. Each branch is a single-purpose
|
|
19647
20033
|
// gate; the data work lives in `aggregateHistoryStats`.
|
|
@@ -19942,20 +20328,20 @@ function trimMs(iso) {
|
|
|
19942
20328
|
|
|
19943
20329
|
// cli/commands/jobs.ts
|
|
19944
20330
|
import { unlink as unlink2 } from "fs/promises";
|
|
19945
|
-
import { relative as
|
|
19946
|
-
import { Command as
|
|
20331
|
+
import { relative as relative8 } from "path";
|
|
20332
|
+
import { Command as Command20, Option as Option19 } from "clipanion";
|
|
19947
20333
|
|
|
19948
20334
|
// kernel/jobs/orphan-files.ts
|
|
19949
|
-
import { readdirSync as
|
|
19950
|
-
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";
|
|
19951
20337
|
function findOrphanJobFiles(jobsDir, referencedPaths) {
|
|
19952
20338
|
let entries;
|
|
19953
20339
|
try {
|
|
19954
|
-
const stat3 =
|
|
20340
|
+
const stat3 = statSync9(jobsDir);
|
|
19955
20341
|
if (!stat3.isDirectory()) {
|
|
19956
20342
|
return { orphanFilePaths: [], referencedCount: referencedPaths.size };
|
|
19957
20343
|
}
|
|
19958
|
-
entries =
|
|
20344
|
+
entries = readdirSync10(jobsDir, { withFileTypes: true });
|
|
19959
20345
|
} catch {
|
|
19960
20346
|
return { orphanFilePaths: [], referencedCount: referencedPaths.size };
|
|
19961
20347
|
}
|
|
@@ -19965,7 +20351,7 @@ function findOrphanJobFiles(jobsDir, referencedPaths) {
|
|
|
19965
20351
|
if (!entry.isFile()) continue;
|
|
19966
20352
|
const name = entry.name;
|
|
19967
20353
|
if (!name.endsWith(".md")) continue;
|
|
19968
|
-
const abs =
|
|
20354
|
+
const abs = resolve34(join17(jobsDir, name));
|
|
19969
20355
|
if (!referencedPaths.has(abs)) orphans.push(abs);
|
|
19970
20356
|
}
|
|
19971
20357
|
orphans.sort();
|
|
@@ -19994,7 +20380,7 @@ var JOBS_TEXTS = {
|
|
|
19994
20380
|
// cli/commands/jobs.ts
|
|
19995
20381
|
var JobPruneCommand = class extends SmCommand {
|
|
19996
20382
|
static paths = [["job", "prune"]];
|
|
19997
|
-
static usage =
|
|
20383
|
+
static usage = Command20.Usage({
|
|
19998
20384
|
category: "Jobs",
|
|
19999
20385
|
description: "Retention GC for completed / failed jobs (per config policy). --orphan-files removes MD files with no DB row.",
|
|
20000
20386
|
details: `
|
|
@@ -20021,10 +20407,10 @@ var JobPruneCommand = class extends SmCommand {
|
|
|
20021
20407
|
["Preview without touching the DB", "$0 job prune --dry-run --json"]
|
|
20022
20408
|
]
|
|
20023
20409
|
});
|
|
20024
|
-
orphanFiles =
|
|
20410
|
+
orphanFiles = Option19.Boolean("--orphan-files", false, {
|
|
20025
20411
|
description: "Also remove MD files in .skill-map/jobs/ that have no matching state_jobs row."
|
|
20026
20412
|
});
|
|
20027
|
-
dryRun =
|
|
20413
|
+
dryRun = Option19.Boolean("-n,--dry-run", false, {
|
|
20028
20414
|
description: "Report what would be pruned without touching the DB or filesystem."
|
|
20029
20415
|
});
|
|
20030
20416
|
async run() {
|
|
@@ -20107,7 +20493,7 @@ var JobPruneCommand = class extends SmCommand {
|
|
|
20107
20493
|
let removed = 0;
|
|
20108
20494
|
for (const p of paths) {
|
|
20109
20495
|
try {
|
|
20110
|
-
assertContained(jobsDir,
|
|
20496
|
+
assertContained(jobsDir, relative8(jobsDir, p));
|
|
20111
20497
|
} catch {
|
|
20112
20498
|
continue;
|
|
20113
20499
|
}
|
|
@@ -20162,7 +20548,7 @@ function formatPolicy(seconds) {
|
|
|
20162
20548
|
}
|
|
20163
20549
|
|
|
20164
20550
|
// cli/commands/list.ts
|
|
20165
|
-
import { Command as
|
|
20551
|
+
import { Command as Command21, Option as Option20 } from "clipanion";
|
|
20166
20552
|
|
|
20167
20553
|
// cli/i18n/list.texts.ts
|
|
20168
20554
|
var LIST_TEXTS = {
|
|
@@ -20197,7 +20583,7 @@ var SORT_BY = {
|
|
|
20197
20583
|
var PATH_COL_MAX_WIDTH = 60;
|
|
20198
20584
|
var ListCommand = class extends SmCommand {
|
|
20199
20585
|
static paths = [["list"]];
|
|
20200
|
-
static usage =
|
|
20586
|
+
static usage = Command21.Usage({
|
|
20201
20587
|
category: "Browse",
|
|
20202
20588
|
description: "Tabular listing of nodes. --json emits an array conforming to node.schema.json.",
|
|
20203
20589
|
details: `
|
|
@@ -20221,11 +20607,11 @@ var ListCommand = class extends SmCommand {
|
|
|
20221
20607
|
["Filter by tag", "$0 list --tag urgent"]
|
|
20222
20608
|
]
|
|
20223
20609
|
});
|
|
20224
|
-
kind =
|
|
20225
|
-
issue =
|
|
20226
|
-
sortBy =
|
|
20227
|
-
limit =
|
|
20228
|
-
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 });
|
|
20229
20615
|
async run() {
|
|
20230
20616
|
const stderrAnsi = this.ansiFor("stderr");
|
|
20231
20617
|
const flags = this.#parseFlags(stderrAnsi);
|
|
@@ -20409,7 +20795,7 @@ function formatDataRow(r, w, ansi) {
|
|
|
20409
20795
|
}
|
|
20410
20796
|
|
|
20411
20797
|
// cli/commands/orphans.ts
|
|
20412
|
-
import { Command as
|
|
20798
|
+
import { Command as Command22, Option as Option21 } from "clipanion";
|
|
20413
20799
|
|
|
20414
20800
|
// cli/i18n/orphans.texts.ts
|
|
20415
20801
|
var ORPHANS_TEXTS = {
|
|
@@ -20492,7 +20878,7 @@ function isStringArray2(v) {
|
|
|
20492
20878
|
}
|
|
20493
20879
|
var OrphansCommand = class extends SmCommand {
|
|
20494
20880
|
static paths = [["orphans"]];
|
|
20495
|
-
static usage =
|
|
20881
|
+
static usage = Command22.Usage({
|
|
20496
20882
|
category: "Browse",
|
|
20497
20883
|
description: "List orphan / auto-rename issues from the last scan. --json emits an array conforming to issue.schema.json.",
|
|
20498
20884
|
details: `
|
|
@@ -20507,7 +20893,7 @@ var OrphansCommand = class extends SmCommand {
|
|
|
20507
20893
|
["Just the ambiguous ones, JSON", "$0 orphans --kind ambiguous --json"]
|
|
20508
20894
|
]
|
|
20509
20895
|
});
|
|
20510
|
-
kind =
|
|
20896
|
+
kind = Option21.String("--kind", { required: false });
|
|
20511
20897
|
async run() {
|
|
20512
20898
|
const stderrAnsi = this.ansiFor("stderr");
|
|
20513
20899
|
let analyzerFilter = null;
|
|
@@ -20556,7 +20942,7 @@ var OrphansCommand = class extends SmCommand {
|
|
|
20556
20942
|
};
|
|
20557
20943
|
var OrphansReconcileCommand = class extends SmCommand {
|
|
20558
20944
|
static paths = [["orphans", "reconcile"]];
|
|
20559
|
-
static usage =
|
|
20945
|
+
static usage = Command22.Usage({
|
|
20560
20946
|
category: "Browse",
|
|
20561
20947
|
description: "Migrate state_* FKs from an orphan path to a live node, resolving the orphan issue.",
|
|
20562
20948
|
details: `
|
|
@@ -20572,9 +20958,9 @@ var OrphansReconcileCommand = class extends SmCommand {
|
|
|
20572
20958
|
["Reattach orphan history", "$0 orphans reconcile skills/old.md --to skills/new.md"]
|
|
20573
20959
|
]
|
|
20574
20960
|
});
|
|
20575
|
-
orphanPath =
|
|
20576
|
-
to =
|
|
20577
|
-
dryRun =
|
|
20961
|
+
orphanPath = Option21.String({ required: true });
|
|
20962
|
+
to = Option21.String("--to", { required: true });
|
|
20963
|
+
dryRun = Option21.Boolean("-n,--dry-run", false);
|
|
20578
20964
|
async run() {
|
|
20579
20965
|
const dbPath = resolveDbPath({ db: this.db, ...defaultRuntimeContext() });
|
|
20580
20966
|
const exit = requireDbOrExit(dbPath, this.context.stderr);
|
|
@@ -20675,7 +21061,7 @@ var OrphansReconcileCommand = class extends SmCommand {
|
|
|
20675
21061
|
};
|
|
20676
21062
|
var OrphansUndoRenameCommand = class extends SmCommand {
|
|
20677
21063
|
static paths = [["orphans", "undo-rename"]];
|
|
20678
|
-
static usage =
|
|
21064
|
+
static usage = Command22.Usage({
|
|
20679
21065
|
category: "Browse",
|
|
20680
21066
|
description: "Reverse a medium- or ambiguous-confidence auto-rename. Migrates state_* FKs back, emits a new orphan on the prior path.",
|
|
20681
21067
|
details: `
|
|
@@ -20695,10 +21081,10 @@ var OrphansUndoRenameCommand = class extends SmCommand {
|
|
|
20695
21081
|
["Undo an ambiguous, picking a candidate", "$0 orphans undo-rename skills/new.md --from skills/old-a.md"]
|
|
20696
21082
|
]
|
|
20697
21083
|
});
|
|
20698
|
-
newPath =
|
|
20699
|
-
from =
|
|
20700
|
-
force =
|
|
20701
|
-
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);
|
|
20702
21088
|
async run() {
|
|
20703
21089
|
const dbPath = resolveDbPath({ db: this.db, ...defaultRuntimeContext() });
|
|
20704
21090
|
const exit = requireDbOrExit(dbPath, this.context.stderr);
|
|
@@ -20921,7 +21307,7 @@ var ORPHANS_COMMANDS = [
|
|
|
20921
21307
|
];
|
|
20922
21308
|
|
|
20923
21309
|
// cli/commands/plugins/list.ts
|
|
20924
|
-
import { Command as
|
|
21310
|
+
import { Command as Command23, Option as Option22 } from "clipanion";
|
|
20925
21311
|
|
|
20926
21312
|
// cli/i18n/plugins.texts.ts
|
|
20927
21313
|
var PLUGINS_TEXTS = {
|
|
@@ -21192,9 +21578,9 @@ function sortPluginsForPresentation(plugins) {
|
|
|
21192
21578
|
}
|
|
21193
21579
|
|
|
21194
21580
|
// cli/commands/plugins/shared.ts
|
|
21195
|
-
import { resolve as
|
|
21581
|
+
import { resolve as resolve35 } from "path";
|
|
21196
21582
|
function resolveSearchPaths2(opts, cwd) {
|
|
21197
|
-
if (opts.pluginDir) return [
|
|
21583
|
+
if (opts.pluginDir) return [resolve35(opts.pluginDir)];
|
|
21198
21584
|
return [defaultProjectPluginsDir({ cwd })];
|
|
21199
21585
|
}
|
|
21200
21586
|
async function buildResolver() {
|
|
@@ -21312,7 +21698,7 @@ function wrapText(text, maxWidth) {
|
|
|
21312
21698
|
// cli/commands/plugins/list.ts
|
|
21313
21699
|
var PluginsListCommand = class extends SmCommand {
|
|
21314
21700
|
static paths = [["plugins", "list"]];
|
|
21315
|
-
static usage =
|
|
21701
|
+
static usage = Command23.Usage({
|
|
21316
21702
|
category: "Plugins",
|
|
21317
21703
|
description: "List discovered plugins, or one plugin's extensions.",
|
|
21318
21704
|
details: `
|
|
@@ -21323,8 +21709,8 @@ var PluginsListCommand = class extends SmCommand {
|
|
|
21323
21709
|
\`<plugin>/<ext>\` id is rejected with a redirect to \`sm plugins show\`.
|
|
21324
21710
|
`
|
|
21325
21711
|
});
|
|
21326
|
-
id =
|
|
21327
|
-
pluginDir =
|
|
21712
|
+
id = Option22.String({ required: false });
|
|
21713
|
+
pluginDir = Option22.String("--plugin-dir", { required: false });
|
|
21328
21714
|
async run() {
|
|
21329
21715
|
const plugins = await loadAll({ pluginDir: this.pluginDir });
|
|
21330
21716
|
const resolveEnabled = await buildResolver();
|
|
@@ -21566,10 +21952,10 @@ function renderExtensionItems(items) {
|
|
|
21566
21952
|
}
|
|
21567
21953
|
|
|
21568
21954
|
// cli/commands/plugins/show.ts
|
|
21569
|
-
import { Command as
|
|
21955
|
+
import { Command as Command24, Option as Option23 } from "clipanion";
|
|
21570
21956
|
var PluginsShowCommand = class extends SmCommand {
|
|
21571
21957
|
static paths = [["plugins", "show"]];
|
|
21572
|
-
static usage =
|
|
21958
|
+
static usage = Command24.Usage({
|
|
21573
21959
|
category: "Plugins",
|
|
21574
21960
|
description: "Show a single extension's detail.",
|
|
21575
21961
|
details: `
|
|
@@ -21582,8 +21968,8 @@ var PluginsShowCommand = class extends SmCommand {
|
|
|
21582
21968
|
accept resolves cleanly here too.
|
|
21583
21969
|
`
|
|
21584
21970
|
});
|
|
21585
|
-
id =
|
|
21586
|
-
pluginDir =
|
|
21971
|
+
id = Option23.String({ required: true });
|
|
21972
|
+
pluginDir = Option23.String("--plugin-dir", { required: false });
|
|
21587
21973
|
async run() {
|
|
21588
21974
|
const plugins = await loadAll({ pluginDir: this.pluginDir });
|
|
21589
21975
|
const resolveEnabled = await buildResolver();
|
|
@@ -21724,7 +22110,7 @@ function renderExtensionFields(meta) {
|
|
|
21724
22110
|
}
|
|
21725
22111
|
|
|
21726
22112
|
// cli/commands/plugins/doctor.ts
|
|
21727
|
-
import { Command as
|
|
22113
|
+
import { Command as Command25, Option as Option24 } from "clipanion";
|
|
21728
22114
|
var CONTRIB_ERROR_SAMPLE_CAP = 3;
|
|
21729
22115
|
var STATUS_ORDER = [
|
|
21730
22116
|
"enabled",
|
|
@@ -21737,12 +22123,12 @@ var STATUS_ORDER = [
|
|
|
21737
22123
|
];
|
|
21738
22124
|
var PluginsDoctorCommand = class extends SmCommand {
|
|
21739
22125
|
static paths = [["plugins", "doctor"]];
|
|
21740
|
-
static usage =
|
|
22126
|
+
static usage = Command25.Usage({
|
|
21741
22127
|
category: "Plugins",
|
|
21742
22128
|
description: "Run the full load pass and summarise by failure mode.",
|
|
21743
22129
|
details: "Exit code 0 when every plugin loads or is intentionally disabled; 1 when any plugin is in an error / incompat state."
|
|
21744
22130
|
});
|
|
21745
|
-
pluginDir =
|
|
22131
|
+
pluginDir = Option24.String("--plugin-dir", { required: false });
|
|
21746
22132
|
async run() {
|
|
21747
22133
|
const plugins = await loadAll({ pluginDir: this.pluginDir });
|
|
21748
22134
|
const resolveEnabled = await buildResolver();
|
|
@@ -22195,13 +22581,13 @@ function groupContributionErrorsByPlugin(errors) {
|
|
|
22195
22581
|
}
|
|
22196
22582
|
|
|
22197
22583
|
// cli/commands/plugins/toggle.ts
|
|
22198
|
-
import { Command as
|
|
22584
|
+
import { Command as Command26, Option as Option25 } from "clipanion";
|
|
22199
22585
|
var TogglePluginsBase = class extends SmCommand {
|
|
22200
|
-
all =
|
|
22201
|
-
yes =
|
|
22586
|
+
all = Option25.Boolean("--all", false);
|
|
22587
|
+
yes = Option25.Boolean("--yes,-y", false, {
|
|
22202
22588
|
description: "Skip the interactive confirm when a bare plugin id (or --all) fans the toggle out across multiple extensions."
|
|
22203
22589
|
});
|
|
22204
|
-
ids =
|
|
22590
|
+
ids = Option25.Rest({ name: "ids" });
|
|
22205
22591
|
async toggle(enabled) {
|
|
22206
22592
|
const verb = enabled ? "enable" : "disable";
|
|
22207
22593
|
const stderrAnsi = this.ansiFor("stderr");
|
|
@@ -22424,7 +22810,7 @@ async function purgeContributionsFor(adapter, id) {
|
|
|
22424
22810
|
}
|
|
22425
22811
|
var PluginsEnableCommand = class extends TogglePluginsBase {
|
|
22426
22812
|
static paths = [["plugins", "enable"]];
|
|
22427
|
-
static usage =
|
|
22813
|
+
static usage = Command26.Usage({
|
|
22428
22814
|
category: "Plugins",
|
|
22429
22815
|
description: "Enable one or more extensions (or --all). Persists in config_plugins.",
|
|
22430
22816
|
details: `
|
|
@@ -22452,7 +22838,7 @@ var PluginsEnableCommand = class extends TogglePluginsBase {
|
|
|
22452
22838
|
};
|
|
22453
22839
|
var PluginsDisableCommand = class extends TogglePluginsBase {
|
|
22454
22840
|
static paths = [["plugins", "disable"]];
|
|
22455
|
-
static usage =
|
|
22841
|
+
static usage = Command26.Usage({
|
|
22456
22842
|
category: "Plugins",
|
|
22457
22843
|
description: "Disable one or more extensions (or --all). Persists in config_plugins; does not delete files.",
|
|
22458
22844
|
details: `
|
|
@@ -22507,9 +22893,9 @@ function resolveBareToggle(id, catalogue) {
|
|
|
22507
22893
|
}
|
|
22508
22894
|
|
|
22509
22895
|
// cli/commands/plugins/create.ts
|
|
22510
|
-
import { existsSync as
|
|
22511
|
-
import { dirname as
|
|
22512
|
-
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";
|
|
22513
22899
|
|
|
22514
22900
|
// cli/commands/plugins/scaffold/action.ts
|
|
22515
22901
|
function indexStub(extId) {
|
|
@@ -22914,7 +23300,7 @@ function generateScaffold(kind, pluginId, specVersion) {
|
|
|
22914
23300
|
// cli/commands/plugins/create.ts
|
|
22915
23301
|
var PluginsCreateCommand = class extends SmCommand {
|
|
22916
23302
|
static paths = [["plugins", "create"]];
|
|
22917
|
-
static usage =
|
|
23303
|
+
static usage = Command27.Usage({
|
|
22918
23304
|
category: "Plugins",
|
|
22919
23305
|
description: "Scaffold a new plugin directory.",
|
|
22920
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.",
|
|
@@ -22926,10 +23312,10 @@ var PluginsCreateCommand = class extends SmCommand {
|
|
|
22926
23312
|
});
|
|
22927
23313
|
// First positional: the extension kind (required). Declared before
|
|
22928
23314
|
// `pluginId` so clipanion assigns it the first positional slot.
|
|
22929
|
-
kind =
|
|
22930
|
-
pluginId =
|
|
22931
|
-
at =
|
|
22932
|
-
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);
|
|
22933
23319
|
async run() {
|
|
22934
23320
|
const ansi = this.ansiFor("stderr");
|
|
22935
23321
|
const errGlyph = ansi.red("\u2715");
|
|
@@ -22958,8 +23344,8 @@ var PluginsCreateCommand = class extends SmCommand {
|
|
|
22958
23344
|
const kind = this.kind;
|
|
22959
23345
|
const ctx = defaultRuntimeContext();
|
|
22960
23346
|
const baseDir = defaultProjectPluginsDir(ctx);
|
|
22961
|
-
const targetDir = this.at ?
|
|
22962
|
-
if (
|
|
23347
|
+
const targetDir = this.at ? resolve36(this.at) : join18(baseDir, this.pluginId);
|
|
23348
|
+
if (existsSync26(targetDir) && !this.force) {
|
|
22963
23349
|
this.printer.error(
|
|
22964
23350
|
tx(PLUGINS_TEXTS.createRefuseOverwrite, {
|
|
22965
23351
|
glyph: errGlyph,
|
|
@@ -22973,7 +23359,7 @@ var PluginsCreateCommand = class extends SmCommand {
|
|
|
22973
23359
|
const files = generateScaffold(kind, this.pluginId, specVersion);
|
|
22974
23360
|
for (const file of files) {
|
|
22975
23361
|
const abs = join18(targetDir, file.relPath);
|
|
22976
|
-
mkdirSync5(
|
|
23362
|
+
mkdirSync5(dirname18(abs), { recursive: true });
|
|
22977
23363
|
writeFileSync(abs, file.contents);
|
|
22978
23364
|
}
|
|
22979
23365
|
const mainFile = `${kind}s/${this.pluginId}-${kind}/index.js`;
|
|
@@ -22988,7 +23374,7 @@ var PluginsCreateCommand = class extends SmCommand {
|
|
|
22988
23374
|
};
|
|
22989
23375
|
|
|
22990
23376
|
// cli/commands/plugins/slots.ts
|
|
22991
|
-
import { Command as
|
|
23377
|
+
import { Command as Command28 } from "clipanion";
|
|
22992
23378
|
|
|
22993
23379
|
// cli/commands/plugins/slots-catalog.ts
|
|
22994
23380
|
var VIEW_SLOTS_CATALOG = [
|
|
@@ -23024,7 +23410,7 @@ var INPUT_TYPES_CATALOG = [
|
|
|
23024
23410
|
// cli/commands/plugins/slots.ts
|
|
23025
23411
|
var PluginsSlotsListCommand = class extends SmCommand {
|
|
23026
23412
|
static paths = [["plugins", "slots", "list"]];
|
|
23027
|
-
static usage =
|
|
23413
|
+
static usage = Command28.Usage({
|
|
23028
23414
|
category: "Plugins",
|
|
23029
23415
|
description: "Print the closed catalogs of view slots and input-types.",
|
|
23030
23416
|
details: "Read-only. Use this when picking a slot / input-type for a new plugin."
|
|
@@ -23073,15 +23459,15 @@ var PluginsSlotsListCommand = class extends SmCommand {
|
|
|
23073
23459
|
};
|
|
23074
23460
|
|
|
23075
23461
|
// cli/commands/plugins/upgrade.ts
|
|
23076
|
-
import { Command as
|
|
23462
|
+
import { Command as Command29, Option as Option27 } from "clipanion";
|
|
23077
23463
|
var PluginsUpgradeCommand = class extends SmCommand {
|
|
23078
23464
|
static paths = [["plugins", "upgrade"]];
|
|
23079
|
-
static usage =
|
|
23465
|
+
static usage = Command29.Usage({
|
|
23080
23466
|
category: "Plugins",
|
|
23081
23467
|
description: "Apply catalog migrations to plugin manifests.",
|
|
23082
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."
|
|
23083
23469
|
});
|
|
23084
|
-
pluginId =
|
|
23470
|
+
pluginId = Option27.String({ required: false, name: "plugin-id" });
|
|
23085
23471
|
async run() {
|
|
23086
23472
|
this.printer.data(
|
|
23087
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"
|
|
@@ -23091,7 +23477,7 @@ var PluginsUpgradeCommand = class extends SmCommand {
|
|
|
23091
23477
|
};
|
|
23092
23478
|
|
|
23093
23479
|
// cli/commands/plugins/config.ts
|
|
23094
|
-
import { Command as
|
|
23480
|
+
import { Command as Command30, Option as Option28 } from "clipanion";
|
|
23095
23481
|
|
|
23096
23482
|
// cli/i18n/plugins-config.texts.ts
|
|
23097
23483
|
var PLUGINS_CONFIG_TEXTS = {
|
|
@@ -23132,7 +23518,7 @@ var PLUGINS_CONFIG_TEXTS = {
|
|
|
23132
23518
|
// cli/commands/plugins/config.ts
|
|
23133
23519
|
var PluginsConfigCommand = class extends SmCommand {
|
|
23134
23520
|
static paths = [["plugins", "config"]];
|
|
23135
|
-
static usage =
|
|
23521
|
+
static usage = Command30.Usage({
|
|
23136
23522
|
category: "Plugins",
|
|
23137
23523
|
description: "Read or write an extension's declared settings.",
|
|
23138
23524
|
details: `
|
|
@@ -23147,13 +23533,13 @@ var PluginsConfigCommand = class extends SmCommand {
|
|
|
23147
23533
|
Secret values are shown as <redacted>. Run \`sm scan\` to apply.
|
|
23148
23534
|
`
|
|
23149
23535
|
});
|
|
23150
|
-
id =
|
|
23151
|
-
settingId =
|
|
23152
|
-
value =
|
|
23153
|
-
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, {
|
|
23154
23540
|
description: "Remove the override for <settingId> so the manifest default applies."
|
|
23155
23541
|
});
|
|
23156
|
-
pluginDir =
|
|
23542
|
+
pluginDir = Option28.String("--plugin-dir", { required: false });
|
|
23157
23543
|
// Read-only when listing; the write / reset paths emit their own
|
|
23158
23544
|
// receipt. `sm config` exempts the config family from "done in <…>";
|
|
23159
23545
|
// mirror that here for the read path. The write path keeps the line.
|
|
@@ -23474,8 +23860,8 @@ var PLUGIN_COMMANDS = [
|
|
|
23474
23860
|
|
|
23475
23861
|
// cli/commands/refresh.ts
|
|
23476
23862
|
import { readFile as readFile4 } from "fs/promises";
|
|
23477
|
-
import { resolve as
|
|
23478
|
-
import { Command as
|
|
23863
|
+
import { resolve as resolve37 } from "path";
|
|
23864
|
+
import { Command as Command31, Option as Option29 } from "clipanion";
|
|
23479
23865
|
|
|
23480
23866
|
// cli/i18n/refresh.texts.ts
|
|
23481
23867
|
var REFRESH_TEXTS = {
|
|
@@ -23531,7 +23917,7 @@ var REFRESH_TEXTS = {
|
|
|
23531
23917
|
// cli/commands/refresh.ts
|
|
23532
23918
|
var RefreshCommand = class extends SmCommand {
|
|
23533
23919
|
static paths = [["refresh"]];
|
|
23534
|
-
static usage =
|
|
23920
|
+
static usage = Command31.Usage({
|
|
23535
23921
|
category: "Scan",
|
|
23536
23922
|
description: "Refresh enrichment rows: granular (single node) or batch (every stale row).",
|
|
23537
23923
|
details: `
|
|
@@ -23553,11 +23939,11 @@ var RefreshCommand = class extends SmCommand {
|
|
|
23553
23939
|
["Refresh every node with stale enrichments", "$0 refresh --stale"]
|
|
23554
23940
|
]
|
|
23555
23941
|
});
|
|
23556
|
-
nodePath =
|
|
23557
|
-
stale =
|
|
23942
|
+
nodePath = Option29.String({ name: "node", required: false });
|
|
23943
|
+
stale = Option29.Boolean("--stale", false, {
|
|
23558
23944
|
description: "Refresh every node carrying a stale enrichment row (no-op in this revision; reserved for future Action-prob enrichments)."
|
|
23559
23945
|
});
|
|
23560
|
-
noPlugins =
|
|
23946
|
+
noPlugins = Option29.Boolean("--no-plugins", false, {
|
|
23561
23947
|
description: "Skip drop-in plugin discovery; use only the built-in extractor set."
|
|
23562
23948
|
});
|
|
23563
23949
|
// The remaining cyclomatic count comes from CLI ergonomics that don't
|
|
@@ -23782,7 +24168,7 @@ var RefreshCommand = class extends SmCommand {
|
|
|
23782
24168
|
let body;
|
|
23783
24169
|
try {
|
|
23784
24170
|
assertContained(cwd, node.path);
|
|
23785
|
-
const raw = await readFile4(
|
|
24171
|
+
const raw = await readFile4(resolve37(cwd, node.path), "utf8");
|
|
23786
24172
|
body = stripFrontmatterFence(raw);
|
|
23787
24173
|
} catch (err) {
|
|
23788
24174
|
if (!this.json) {
|
|
@@ -23855,13 +24241,13 @@ var IntentionalFailCommand = class extends SmCommand {
|
|
|
23855
24241
|
setTimeout(() => {
|
|
23856
24242
|
throw new Error(INTENTIONAL_FAIL_TEXTS.errorMessage);
|
|
23857
24243
|
}, 0);
|
|
23858
|
-
await new Promise((
|
|
24244
|
+
await new Promise((resolve44) => setTimeout(resolve44, 5e3));
|
|
23859
24245
|
return ExitCode.Issues;
|
|
23860
24246
|
}
|
|
23861
24247
|
};
|
|
23862
24248
|
|
|
23863
24249
|
// cli/commands/scan.ts
|
|
23864
|
-
import { Command as
|
|
24250
|
+
import { Command as Command33, Option as Option31 } from "clipanion";
|
|
23865
24251
|
|
|
23866
24252
|
// kernel/util/format-bytes.ts
|
|
23867
24253
|
var UNITS = ["B", "KiB", "MiB", "GiB", "TiB", "PiB"];
|
|
@@ -24020,10 +24406,10 @@ var SCAN_TEXTS = {
|
|
|
24020
24406
|
};
|
|
24021
24407
|
|
|
24022
24408
|
// cli/commands/watch.ts
|
|
24023
|
-
import { Command as
|
|
24409
|
+
import { Command as Command32, Option as Option30 } from "clipanion";
|
|
24024
24410
|
|
|
24025
24411
|
// core/watcher/runtime.ts
|
|
24026
|
-
import { dirname as
|
|
24412
|
+
import { dirname as dirname19, isAbsolute as isAbsolute13, relative as relative9, resolve as resolve38, sep as sep6 } from "path";
|
|
24027
24413
|
|
|
24028
24414
|
// core/runtime/fresh-resolver.ts
|
|
24029
24415
|
async function buildFreshResolver(deps) {
|
|
@@ -24069,7 +24455,7 @@ function applyPriorStateToRunOptions(runOptions, priorState, changedPaths) {
|
|
|
24069
24455
|
}
|
|
24070
24456
|
}
|
|
24071
24457
|
function toIncrementalPaths(events, roots, cwd) {
|
|
24072
|
-
const absRoots = roots.map((r) =>
|
|
24458
|
+
const absRoots = roots.map((r) => isAbsolute13(r) ? r : resolve38(cwd, r));
|
|
24073
24459
|
const changed = /* @__PURE__ */ new Set();
|
|
24074
24460
|
const removed = /* @__PURE__ */ new Set();
|
|
24075
24461
|
for (const ev of events) {
|
|
@@ -24083,12 +24469,15 @@ function toIncrementalPaths(events, roots, cwd) {
|
|
|
24083
24469
|
}
|
|
24084
24470
|
function relativeFromRoots2(absolute, absRoots) {
|
|
24085
24471
|
for (const root of absRoots) {
|
|
24086
|
-
const rel =
|
|
24087
|
-
if (rel === "" || rel.startsWith("..") ||
|
|
24472
|
+
const rel = relative9(root, absolute);
|
|
24473
|
+
if (rel === "" || rel.startsWith("..") || isAbsolute13(rel)) continue;
|
|
24088
24474
|
return rel.split(sep6).join("/");
|
|
24089
24475
|
}
|
|
24090
24476
|
return null;
|
|
24091
24477
|
}
|
|
24478
|
+
function resolveWatcherLens(cwd, composed) {
|
|
24479
|
+
return resolveActiveProvider(cwd, composed?.providers ?? []).resolved;
|
|
24480
|
+
}
|
|
24092
24481
|
function createWatcherRuntime(opts) {
|
|
24093
24482
|
const events = opts.events ?? {};
|
|
24094
24483
|
const cwd = opts.runtimeContext.cwd;
|
|
@@ -24196,7 +24585,14 @@ function createWatcherRuntime(opts) {
|
|
|
24196
24585
|
overrideScanCeiling: opts.maxScanOverride ?? null,
|
|
24197
24586
|
maxRenderNodes: cfg.scan.maxNodes,
|
|
24198
24587
|
overrideMaxRenderNodes: opts.maxNodesOverride ?? null,
|
|
24199
|
-
maxFileSizeBytes: cfg.scan.maxFileSizeBytes
|
|
24588
|
+
maxFileSizeBytes: cfg.scan.maxFileSizeBytes,
|
|
24589
|
+
// Resolve the active lens from the persisted config (settings.json)
|
|
24590
|
+
// so a lens switched via `PATCH /api/active-provider` is honoured by
|
|
24591
|
+
// the next watcher batch. Without an explicit value the orchestrator
|
|
24592
|
+
// falls back to filesystem detection, which ignores the operator's
|
|
24593
|
+
// choice (e.g. selecting `markdown` while `.claude/` is still on disk
|
|
24594
|
+
// would re-detect `claude` and silently overwrite the chosen lens).
|
|
24595
|
+
activeProvider: resolveWatcherLens(cwd, composed)
|
|
24200
24596
|
};
|
|
24201
24597
|
if (cfg.scan.referencePaths.length > 0) {
|
|
24202
24598
|
const walk3 = walkReferencePaths(cfg.scan.referencePaths, cwd);
|
|
@@ -24317,7 +24713,7 @@ function createWatcherRuntime(opts) {
|
|
|
24317
24713
|
roots: [
|
|
24318
24714
|
cwd,
|
|
24319
24715
|
// parent of `.skillmapignore`
|
|
24320
|
-
|
|
24716
|
+
dirname19(settingsPath)
|
|
24321
24717
|
// parent of `.skill-map/settings.json`
|
|
24322
24718
|
],
|
|
24323
24719
|
cwd,
|
|
@@ -24607,7 +25003,7 @@ async function runWatchLoop(opts) {
|
|
|
24607
25003
|
}
|
|
24608
25004
|
var WatchCommand = class extends SmCommand {
|
|
24609
25005
|
static paths = [["watch"]];
|
|
24610
|
-
static usage =
|
|
25006
|
+
static usage = Command32.Usage({
|
|
24611
25007
|
category: "Scan",
|
|
24612
25008
|
description: "Watch roots and run an incremental scan after each debounced batch of filesystem events.",
|
|
24613
25009
|
details: `
|
|
@@ -24631,25 +25027,25 @@ var WatchCommand = class extends SmCommand {
|
|
|
24631
25027
|
["Stream ScanResult per batch as ndjson", "$0 watch --json"]
|
|
24632
25028
|
]
|
|
24633
25029
|
});
|
|
24634
|
-
roots =
|
|
24635
|
-
noTokens =
|
|
25030
|
+
roots = Option30.Rest({ name: "roots" });
|
|
25031
|
+
noTokens = Option30.Boolean("--no-tokens", false, {
|
|
24636
25032
|
description: "Skip per-node token counts (cl100k_base BPE)."
|
|
24637
25033
|
});
|
|
24638
|
-
strict =
|
|
25034
|
+
strict = Option30.Boolean("--strict", false, {
|
|
24639
25035
|
description: "Promote frontmatter-validation findings from warn to error inside each batch. Does not change the watcher exit code."
|
|
24640
25036
|
});
|
|
24641
|
-
noPlugins =
|
|
25037
|
+
noPlugins = Option30.Boolean("--no-plugins", false, {
|
|
24642
25038
|
description: "Skip drop-in plugin discovery for the watcher session."
|
|
24643
25039
|
});
|
|
24644
|
-
maxConsecutiveFailures =
|
|
25040
|
+
maxConsecutiveFailures = Option30.String("--max-consecutive-failures", {
|
|
24645
25041
|
required: false,
|
|
24646
25042
|
description: "Shut down with exit 2 after N consecutive batch failures (default 5; 0 disables the breaker)."
|
|
24647
25043
|
});
|
|
24648
|
-
maxScan =
|
|
25044
|
+
maxScan = Option30.String("--max-scan", {
|
|
24649
25045
|
required: false,
|
|
24650
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."
|
|
24651
25047
|
});
|
|
24652
|
-
maxNodes =
|
|
25048
|
+
maxNodes = Option30.String("--max-nodes", {
|
|
24653
25049
|
required: false,
|
|
24654
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."
|
|
24655
25051
|
});
|
|
@@ -24736,7 +25132,7 @@ function parseMaxNodesLimit(raw, stderr, noColor) {
|
|
|
24736
25132
|
// cli/commands/scan.ts
|
|
24737
25133
|
var ScanCommand = class extends SmCommand {
|
|
24738
25134
|
static paths = [["scan"]];
|
|
24739
|
-
static usage =
|
|
25135
|
+
static usage = Command33.Usage({
|
|
24740
25136
|
category: "Scan",
|
|
24741
25137
|
description: "Scan roots for markdown nodes, run extractors and analyzers.",
|
|
24742
25138
|
details: `
|
|
@@ -24771,39 +25167,39 @@ var ScanCommand = class extends SmCommand {
|
|
|
24771
25167
|
["What would the next incremental scan persist?", "$0 scan --changed -n --json"]
|
|
24772
25168
|
]
|
|
24773
25169
|
});
|
|
24774
|
-
roots =
|
|
24775
|
-
noBuiltIns =
|
|
25170
|
+
roots = Option31.Rest({ name: "roots" });
|
|
25171
|
+
noBuiltIns = Option31.Boolean("--no-built-ins", false, {
|
|
24776
25172
|
description: "Skip the built-in extension set. Yields a zero-filled ScanResult (kernel-empty-boot parity); skips DB persistence."
|
|
24777
25173
|
});
|
|
24778
|
-
noPlugins =
|
|
25174
|
+
noPlugins = Option31.Boolean("--no-plugins", false, {
|
|
24779
25175
|
description: "Skip drop-in plugin discovery. Only the built-in set runs. Combine with --no-built-ins for a fully empty pipeline."
|
|
24780
25176
|
});
|
|
24781
|
-
noTokens =
|
|
25177
|
+
noTokens = Option31.Boolean("--no-tokens", false, {
|
|
24782
25178
|
description: "Skip per-node token counts (cl100k_base BPE). Leaves node.tokens undefined; spec-valid since the field is optional."
|
|
24783
25179
|
});
|
|
24784
|
-
dryRun =
|
|
25180
|
+
dryRun = Option31.Boolean("-n,--dry-run", false, {
|
|
24785
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."
|
|
24786
25182
|
});
|
|
24787
|
-
changed =
|
|
25183
|
+
changed = Option31.Boolean("--changed", false, {
|
|
24788
25184
|
description: "Incremental scan: reuse unchanged nodes from the persisted prior snapshot. Degrades to a full scan if no prior snapshot exists."
|
|
24789
25185
|
});
|
|
24790
|
-
allowEmpty =
|
|
25186
|
+
allowEmpty = Option31.Boolean("--allow-empty", false, {
|
|
24791
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."
|
|
24792
25188
|
});
|
|
24793
|
-
strict =
|
|
25189
|
+
strict = Option31.Boolean("--strict", false, {
|
|
24794
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."
|
|
24795
25191
|
});
|
|
24796
|
-
watch =
|
|
25192
|
+
watch = Option31.Boolean("--watch", false, {
|
|
24797
25193
|
description: "Long-running mode: watch the roots and trigger an incremental scan after each debounced batch of filesystem events. Alias of `sm watch`."
|
|
24798
25194
|
});
|
|
24799
|
-
yes =
|
|
25195
|
+
yes = Option31.Boolean("--yes", false, {
|
|
24800
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."
|
|
24801
25197
|
});
|
|
24802
|
-
maxScan =
|
|
25198
|
+
maxScan = Option31.String("--max-scan", {
|
|
24803
25199
|
required: false,
|
|
24804
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."
|
|
24805
25201
|
});
|
|
24806
|
-
maxNodes =
|
|
25202
|
+
maxNodes = Option31.String("--max-nodes", {
|
|
24807
25203
|
required: false,
|
|
24808
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."
|
|
24809
25205
|
});
|
|
@@ -25164,10 +25560,10 @@ function capOverrides(caps) {
|
|
|
25164
25560
|
|
|
25165
25561
|
// cli/commands/scan-compare.ts
|
|
25166
25562
|
import { access, readFile as readFile5 } from "fs/promises";
|
|
25167
|
-
import { Command as
|
|
25563
|
+
import { Command as Command34, Option as Option32 } from "clipanion";
|
|
25168
25564
|
var ScanCompareCommand = class extends SmCommand {
|
|
25169
25565
|
static paths = [["scan", "compare-with"]];
|
|
25170
|
-
static usage =
|
|
25566
|
+
static usage = Command34.Usage({
|
|
25171
25567
|
category: "Scan",
|
|
25172
25568
|
description: "Run a fresh scan in memory and emit a delta against the saved ScanResult dump at <dump>. Read-only.",
|
|
25173
25569
|
details: `
|
|
@@ -25195,15 +25591,15 @@ var ScanCompareCommand = class extends SmCommand {
|
|
|
25195
25591
|
["JSON output for tooling", "$0 scan compare-with baseline.json --json"]
|
|
25196
25592
|
]
|
|
25197
25593
|
});
|
|
25198
|
-
dump =
|
|
25199
|
-
roots =
|
|
25200
|
-
noTokens =
|
|
25594
|
+
dump = Option32.String({ required: true });
|
|
25595
|
+
roots = Option32.Rest({ name: "roots" });
|
|
25596
|
+
noTokens = Option32.Boolean("--no-tokens", false, {
|
|
25201
25597
|
description: "Skip per-node token counts during the fresh scan."
|
|
25202
25598
|
});
|
|
25203
|
-
strict =
|
|
25599
|
+
strict = Option32.Boolean("--strict", false, {
|
|
25204
25600
|
description: "Promote layered-config warnings and frontmatter-validation findings from warn to error."
|
|
25205
25601
|
});
|
|
25206
|
-
noPlugins =
|
|
25602
|
+
noPlugins = Option32.Boolean("--no-plugins", false, {
|
|
25207
25603
|
description: "Skip drop-in plugin discovery."
|
|
25208
25604
|
});
|
|
25209
25605
|
// Cyclomatic count comes from CLI ergonomics: 3 distinct try/catch
|
|
@@ -25409,13 +25805,13 @@ function renderDeltaIssues(issues) {
|
|
|
25409
25805
|
|
|
25410
25806
|
// cli/commands/serve.ts
|
|
25411
25807
|
import { spawn as spawn2 } from "child_process";
|
|
25412
|
-
import { existsSync as
|
|
25413
|
-
import { Command as
|
|
25808
|
+
import { existsSync as existsSync32 } from "fs";
|
|
25809
|
+
import { Command as Command35, Option as Option33 } from "clipanion";
|
|
25414
25810
|
|
|
25415
25811
|
// kernel/util/dev-mode.ts
|
|
25416
25812
|
import { sep as sep7 } from "path";
|
|
25417
|
-
import { fileURLToPath as
|
|
25418
|
-
var SELF_PATH =
|
|
25813
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
25814
|
+
var SELF_PATH = fileURLToPath6(import.meta.url);
|
|
25419
25815
|
var IS_DEV_BUILD = isDevBuildFromPath(SELF_PATH, sep7);
|
|
25420
25816
|
function isDevBuildFromPath(filePath, separator = sep7) {
|
|
25421
25817
|
return !filePath.includes(`${separator}node_modules${separator}`);
|
|
@@ -26371,7 +26767,7 @@ function contentTypeFor(format) {
|
|
|
26371
26767
|
}
|
|
26372
26768
|
|
|
26373
26769
|
// server/health.ts
|
|
26374
|
-
import { existsSync as
|
|
26770
|
+
import { existsSync as existsSync27 } from "fs";
|
|
26375
26771
|
var FALLBACK_SCHEMA_VERSION = "1";
|
|
26376
26772
|
function buildHealth(deps) {
|
|
26377
26773
|
const dev = isDevBuild();
|
|
@@ -26380,7 +26776,7 @@ function buildHealth(deps) {
|
|
|
26380
26776
|
schemaVersion: FALLBACK_SCHEMA_VERSION,
|
|
26381
26777
|
specVersion: deps.specVersion,
|
|
26382
26778
|
implVersion: VERSION,
|
|
26383
|
-
db:
|
|
26779
|
+
db: existsSync27(deps.dbPath) ? "present" : "missing",
|
|
26384
26780
|
cwd: deps.cwd,
|
|
26385
26781
|
dbPath: deps.dbPath,
|
|
26386
26782
|
// Only emit when truthy so a published install keeps the wire
|
|
@@ -26513,9 +26909,9 @@ import { HTTPException as HTTPException8 } from "hono/http-exception";
|
|
|
26513
26909
|
// server/node-body.ts
|
|
26514
26910
|
import { constants as fsConstants2 } from "fs";
|
|
26515
26911
|
import { open } from "fs/promises";
|
|
26516
|
-
import { isAbsolute as
|
|
26912
|
+
import { isAbsolute as isAbsolute14, resolve as resolvePath2, relative as relativePath, sep as sep8 } from "path";
|
|
26517
26913
|
async function readNodeBody(cwd, relPath) {
|
|
26518
|
-
if (
|
|
26914
|
+
if (isAbsolute14(relPath)) return null;
|
|
26519
26915
|
const absRoot = resolvePath2(cwd);
|
|
26520
26916
|
const absFile = resolvePath2(absRoot, relPath);
|
|
26521
26917
|
const rel = relativePath(absRoot, absFile);
|
|
@@ -27502,12 +27898,12 @@ var parsePatchBody2 = makeBodyValidator(PATCH_BODY_SCHEMA, {
|
|
|
27502
27898
|
import { HTTPException as HTTPException12 } from "hono/http-exception";
|
|
27503
27899
|
|
|
27504
27900
|
// server/util/skillmapignore-io.ts
|
|
27505
|
-
import { existsSync as
|
|
27506
|
-
import { resolve as
|
|
27901
|
+
import { existsSync as existsSync28, readFileSync as readFileSync18, writeFileSync as writeFileSync2 } from "fs";
|
|
27902
|
+
import { resolve as resolve39 } from "path";
|
|
27507
27903
|
var IGNORE_FILENAME2 = ".skillmapignore";
|
|
27508
27904
|
function readPatterns(cwd) {
|
|
27509
|
-
const path =
|
|
27510
|
-
if (!
|
|
27905
|
+
const path = resolve39(cwd, IGNORE_FILENAME2);
|
|
27906
|
+
if (!existsSync28(path)) return [];
|
|
27511
27907
|
let raw;
|
|
27512
27908
|
try {
|
|
27513
27909
|
raw = readFileSync18(path, "utf8");
|
|
@@ -27517,8 +27913,8 @@ function readPatterns(cwd) {
|
|
|
27517
27913
|
return raw.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#"));
|
|
27518
27914
|
}
|
|
27519
27915
|
function writePatterns(cwd, nextPatterns) {
|
|
27520
|
-
const path =
|
|
27521
|
-
const prior =
|
|
27916
|
+
const path = resolve39(cwd, IGNORE_FILENAME2);
|
|
27917
|
+
const prior = existsSync28(path) ? safeRead(path) : "";
|
|
27522
27918
|
const content = buildContent(prior, nextPatterns);
|
|
27523
27919
|
writeFileSync2(path, content, "utf8");
|
|
27524
27920
|
}
|
|
@@ -27679,7 +28075,7 @@ var parsePatchBody3 = makeBodyValidator(PATCH_BODY_SCHEMA2, {
|
|
|
27679
28075
|
});
|
|
27680
28076
|
|
|
27681
28077
|
// server/routes/project-preferences.ts
|
|
27682
|
-
import { statSync as
|
|
28078
|
+
import { statSync as statSync10 } from "fs";
|
|
27683
28079
|
import { HTTPException as HTTPException13 } from "hono/http-exception";
|
|
27684
28080
|
function registerProjectPreferencesRoute(app, deps) {
|
|
27685
28081
|
app.get("/api/project-preferences", (c) => {
|
|
@@ -27855,7 +28251,7 @@ function formatPathDetail(path, cwd) {
|
|
|
27855
28251
|
function isExistingDirectory(entry, cwd) {
|
|
27856
28252
|
const abs = resolveScanPath(entry, cwd);
|
|
27857
28253
|
try {
|
|
27858
|
-
return
|
|
28254
|
+
return statSync10(abs).isDirectory();
|
|
27859
28255
|
} catch {
|
|
27860
28256
|
return false;
|
|
27861
28257
|
}
|
|
@@ -27897,7 +28293,7 @@ var parsePatchBody4 = makeBodyValidator(PATCH_BODY_SCHEMA3, {
|
|
|
27897
28293
|
});
|
|
27898
28294
|
|
|
27899
28295
|
// server/routes/active-provider.ts
|
|
27900
|
-
import { existsSync as
|
|
28296
|
+
import { existsSync as existsSync29 } from "fs";
|
|
27901
28297
|
import { HTTPException as HTTPException14 } from "hono/http-exception";
|
|
27902
28298
|
function registerActiveProviderRoute(app, deps) {
|
|
27903
28299
|
app.get("/api/active-provider", async (c) => {
|
|
@@ -27927,7 +28323,6 @@ async function resolveSelectableProviders(deps) {
|
|
|
27927
28323
|
});
|
|
27928
28324
|
const selectable = /* @__PURE__ */ new Set();
|
|
27929
28325
|
for (const provider of deps.providers) {
|
|
27930
|
-
if (provider.presentation?.comingSoon === true) continue;
|
|
27931
28326
|
if (isPluginExtensionEnabled(provider, resolveEnabled)) {
|
|
27932
28327
|
selectable.add(provider.id);
|
|
27933
28328
|
}
|
|
@@ -27946,7 +28341,7 @@ function applyLensSwitch(deps, newValue) {
|
|
|
27946
28341
|
});
|
|
27947
28342
|
}
|
|
27948
28343
|
const dbPath = resolveDbPath({ db: void 0, cwd });
|
|
27949
|
-
if (!
|
|
28344
|
+
if (!existsSync29(dbPath)) return { dropped: null };
|
|
27950
28345
|
const dropResult = dropScanZone(dbPath);
|
|
27951
28346
|
return {
|
|
27952
28347
|
dropped: {
|
|
@@ -27976,7 +28371,7 @@ var parsePatchBody5 = makeBodyValidator(PATCH_BODY_SCHEMA4, {
|
|
|
27976
28371
|
|
|
27977
28372
|
// server/routes/actions.ts
|
|
27978
28373
|
import { HTTPException as HTTPException16 } from "hono/http-exception";
|
|
27979
|
-
import { resolve as
|
|
28374
|
+
import { resolve as resolve40 } from "path";
|
|
27980
28375
|
|
|
27981
28376
|
// server/routes/node-loader.ts
|
|
27982
28377
|
import { HTTPException as HTTPException15 } from "hono/http-exception";
|
|
@@ -28036,7 +28431,7 @@ function registerActionsRoutes(app, deps) {
|
|
|
28036
28431
|
let absPath;
|
|
28037
28432
|
try {
|
|
28038
28433
|
assertContained(deps.runtimeContext.cwd, node.path);
|
|
28039
|
-
absPath =
|
|
28434
|
+
absPath = resolve40(deps.runtimeContext.cwd, node.path);
|
|
28040
28435
|
} catch (err) {
|
|
28041
28436
|
throw new HTTPException16(400, { message: formatErrorMessage(err) });
|
|
28042
28437
|
}
|
|
@@ -28144,14 +28539,14 @@ async function withScanMutex(fn) {
|
|
|
28144
28539
|
if (inFlight !== null) {
|
|
28145
28540
|
throw new ScanBusyError();
|
|
28146
28541
|
}
|
|
28147
|
-
let
|
|
28542
|
+
let resolve44;
|
|
28148
28543
|
inFlight = new Promise((r) => {
|
|
28149
|
-
|
|
28544
|
+
resolve44 = r;
|
|
28150
28545
|
});
|
|
28151
28546
|
try {
|
|
28152
28547
|
return await fn();
|
|
28153
28548
|
} finally {
|
|
28154
|
-
|
|
28549
|
+
resolve44();
|
|
28155
28550
|
inFlight = null;
|
|
28156
28551
|
}
|
|
28157
28552
|
}
|
|
@@ -28667,7 +29062,7 @@ function registerUpdateStatusRoute(app, deps) {
|
|
|
28667
29062
|
}
|
|
28668
29063
|
|
|
28669
29064
|
// server/static.ts
|
|
28670
|
-
import { existsSync as
|
|
29065
|
+
import { existsSync as existsSync30 } from "fs";
|
|
28671
29066
|
import { readFile as readFile6 } from "fs/promises";
|
|
28672
29067
|
import { extname, join as join19 } from "path";
|
|
28673
29068
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
@@ -28722,7 +29117,7 @@ function createSpaFallback(opts) {
|
|
|
28722
29117
|
if (c.req.method !== "GET" && c.req.method !== "HEAD") return c.notFound();
|
|
28723
29118
|
if (opts.uiDist === null) return htmlResponse(c, placeholder);
|
|
28724
29119
|
const indexPath = join19(opts.uiDist, INDEX_HTML);
|
|
28725
|
-
if (!
|
|
29120
|
+
if (!existsSync30(indexPath)) return htmlResponse(c, placeholder);
|
|
28726
29121
|
return fileResponse(c, indexPath);
|
|
28727
29122
|
};
|
|
28728
29123
|
}
|
|
@@ -29271,7 +29666,6 @@ function buildProviderRegistry(providers) {
|
|
|
29271
29666
|
if (ui.emoji !== void 0) entry.emoji = ui.emoji;
|
|
29272
29667
|
if (ui.icon !== void 0) entry.icon = ui.icon;
|
|
29273
29668
|
if (ui.hideChip !== void 0) entry.hideChip = ui.hideChip;
|
|
29274
|
-
if (ui.comingSoon !== void 0) entry.comingSoon = ui.comingSoon;
|
|
29275
29669
|
registry[provider.id] = entry;
|
|
29276
29670
|
}
|
|
29277
29671
|
return registry;
|
|
@@ -29449,9 +29843,9 @@ function validateNoUi(noUi, uiDist) {
|
|
|
29449
29843
|
}
|
|
29450
29844
|
|
|
29451
29845
|
// server/paths.ts
|
|
29452
|
-
import { existsSync as
|
|
29453
|
-
import { dirname as
|
|
29454
|
-
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";
|
|
29455
29849
|
var DEFAULT_UI_REL = join20("ui", "dist", "ui", "browser");
|
|
29456
29850
|
var PACKAGE_UI_REL = "ui";
|
|
29457
29851
|
var INDEX_HTML2 = "index.html";
|
|
@@ -29461,13 +29855,13 @@ function resolveDefaultUiDist(ctx) {
|
|
|
29461
29855
|
return walkUpForUi(ctx.cwd);
|
|
29462
29856
|
}
|
|
29463
29857
|
function resolveExplicitUiDist(ctx, raw) {
|
|
29464
|
-
return
|
|
29858
|
+
return isAbsolute15(raw) ? raw : resolve41(ctx.cwd, raw);
|
|
29465
29859
|
}
|
|
29466
29860
|
function isUiBundleDir(path) {
|
|
29467
|
-
if (!
|
|
29861
|
+
if (!existsSync31(path)) return false;
|
|
29468
29862
|
try {
|
|
29469
|
-
if (!
|
|
29470
|
-
return
|
|
29863
|
+
if (!statSync11(path).isDirectory()) return false;
|
|
29864
|
+
return existsSync31(join20(path, INDEX_HTML2));
|
|
29471
29865
|
} catch {
|
|
29472
29866
|
return false;
|
|
29473
29867
|
}
|
|
@@ -29475,7 +29869,7 @@ function isUiBundleDir(path) {
|
|
|
29475
29869
|
function resolvePackageBundledUi() {
|
|
29476
29870
|
let here;
|
|
29477
29871
|
try {
|
|
29478
|
-
here =
|
|
29872
|
+
here = dirname20(fileURLToPath7(import.meta.url));
|
|
29479
29873
|
} catch {
|
|
29480
29874
|
return null;
|
|
29481
29875
|
}
|
|
@@ -29488,18 +29882,18 @@ function resolvePackageBundledUiFrom(here) {
|
|
|
29488
29882
|
if (isUiBundleDir(candidate)) return candidate;
|
|
29489
29883
|
const distHere = join20(current, "dist", PACKAGE_UI_REL);
|
|
29490
29884
|
if (isUiBundleDir(distHere)) return distHere;
|
|
29491
|
-
const parent =
|
|
29885
|
+
const parent = dirname20(current);
|
|
29492
29886
|
if (parent === current) return null;
|
|
29493
29887
|
current = parent;
|
|
29494
29888
|
}
|
|
29495
29889
|
return null;
|
|
29496
29890
|
}
|
|
29497
29891
|
function walkUpForUi(startDir) {
|
|
29498
|
-
let current =
|
|
29892
|
+
let current = resolve41(startDir);
|
|
29499
29893
|
for (let i = 0; i < 64; i++) {
|
|
29500
29894
|
const candidate = join20(current, DEFAULT_UI_REL);
|
|
29501
29895
|
if (isUiBundleDir(candidate)) return candidate;
|
|
29502
|
-
const parent =
|
|
29896
|
+
const parent = dirname20(current);
|
|
29503
29897
|
if (parent === current) return null;
|
|
29504
29898
|
current = parent;
|
|
29505
29899
|
}
|
|
@@ -29795,169 +30189,10 @@ var SERVE_TEXTS = {
|
|
|
29795
30189
|
driftDeclined: "{{glyph}} sm serve: cache rebuild declined; the {{dbVersion}} cache cannot be reused on {{currentVersion}} ({{reason}}).\n {{hint}}\n"
|
|
29796
30190
|
};
|
|
29797
30191
|
|
|
29798
|
-
// cli/util/serve-banner.ts
|
|
29799
|
-
import { relative as relative8, isAbsolute as isAbsolute15 } from "path";
|
|
29800
|
-
var ESC2 = {
|
|
29801
|
-
reset: "\x1B[0m",
|
|
29802
|
-
bold: "\x1B[1m",
|
|
29803
|
-
dim: "\x1B[2m",
|
|
29804
|
-
underline: "\x1B[4m",
|
|
29805
|
-
/** 256-color violet (xterm 141). */
|
|
29806
|
-
violet: "\x1B[38;5;141m",
|
|
29807
|
-
/** 256-color green (xterm 42). */
|
|
29808
|
-
green: "\x1B[38;5;42m",
|
|
29809
|
-
/** 256-color yellow (xterm 214), matches `cli/util/ansi.ts:yellow`. */
|
|
29810
|
-
yellow: "\x1B[38;5;214m"
|
|
29811
|
-
};
|
|
29812
|
-
var LOGO_LINES = [
|
|
29813
|
-
" ____ _ _ _ _ __ __ ",
|
|
29814
|
-
" / ___|| | _(_) | | | \\/ | __ _ _ __ ",
|
|
29815
|
-
" \\___ \\| |/ / | | | | |\\/| |/ _` | '_ \\ ",
|
|
29816
|
-
" ___) | <| | | | | | | | (_| | |_) |",
|
|
29817
|
-
" |____/|_|\\_\\_|_|_| |_| |_|\\__,_| .__/ ",
|
|
29818
|
-
" |_| "
|
|
29819
|
-
];
|
|
29820
|
-
var LOGO_WIDTH = 40;
|
|
29821
|
-
function renderBanner(input) {
|
|
29822
|
-
const url = `http://${input.host}:${input.port}`;
|
|
29823
|
-
const dbDisplay = formatDbPath(input.dbPath, input.cwd);
|
|
29824
|
-
const browserLine = input.openBrowser ? "Opening browser\u2026 Press Ctrl+C to stop." : `Visit ${url}/ in your browser. Press Ctrl+C to stop.`;
|
|
29825
|
-
if (!input.isTTY) {
|
|
29826
|
-
return renderFlat({
|
|
29827
|
-
host: input.host,
|
|
29828
|
-
port: input.port,
|
|
29829
|
-
dbPath: input.dbPath,
|
|
29830
|
-
openBrowser: input.openBrowser,
|
|
29831
|
-
dev: input.dev === true
|
|
29832
|
-
});
|
|
29833
|
-
}
|
|
29834
|
-
return renderFiglet({
|
|
29835
|
-
version: input.version,
|
|
29836
|
-
url,
|
|
29837
|
-
dbDisplay,
|
|
29838
|
-
pathDisplay: formatCwdPath(input.cwd),
|
|
29839
|
-
browserLine,
|
|
29840
|
-
colorEnabled: input.colorEnabled,
|
|
29841
|
-
referencePaths: input.referencePaths ?? [],
|
|
29842
|
-
dev: input.dev === true
|
|
29843
|
-
});
|
|
29844
|
-
}
|
|
29845
|
-
function resolveColorEnabled(opts) {
|
|
29846
|
-
if (opts.noColorFlag) return false;
|
|
29847
|
-
const noColor = opts.env["NO_COLOR"];
|
|
29848
|
-
if (noColor !== void 0 && noColor !== "") return false;
|
|
29849
|
-
const forceColor = opts.env["FORCE_COLOR"];
|
|
29850
|
-
if (forceColor !== void 0 && forceColor !== "") return true;
|
|
29851
|
-
return opts.isTTY;
|
|
29852
|
-
}
|
|
29853
|
-
function renderFlat(input) {
|
|
29854
|
-
const safeHost = sanitizeForTerminal(input.host);
|
|
29855
|
-
const safeDb = sanitizeForTerminal(input.dbPath);
|
|
29856
|
-
const url = `http://${safeHost}:${input.port}`;
|
|
29857
|
-
const devSuffix = input.dev ? " [dev]" : "";
|
|
29858
|
-
const linesOut = [];
|
|
29859
|
-
linesOut.push(`sm serve${devSuffix}: listening on ${url} (db=${safeDb})`);
|
|
29860
|
-
if (input.openBrowser) {
|
|
29861
|
-
linesOut.push(`sm serve: opening ${url}/ in your browser. Press Ctrl+C to stop.`);
|
|
29862
|
-
} else {
|
|
29863
|
-
linesOut.push(`sm serve: visit ${url}/ in your browser. Press Ctrl+C to stop.`);
|
|
29864
|
-
}
|
|
29865
|
-
return linesOut.join("\n") + "\n";
|
|
29866
|
-
}
|
|
29867
|
-
function renderLogoBlock(input) {
|
|
29868
|
-
const { dimOpen, dimClose, violetOpen, violetClose } = resolveAnsi(input.colorEnabled);
|
|
29869
|
-
const logoLines = LOGO_LINES.map((line) => `${violetOpen}${line}${violetClose}`);
|
|
29870
|
-
const versionText = `v${input.version}`;
|
|
29871
|
-
const versionPad = Math.max(0, LOGO_WIDTH - versionText.length);
|
|
29872
|
-
const versionLine = `${" ".repeat(versionPad)}${dimOpen}${versionText}${dimClose}`;
|
|
29873
|
-
return `${logoLines.join("\n")}
|
|
29874
|
-
|
|
29875
|
-
${versionLine}
|
|
29876
|
-
|
|
29877
|
-
`;
|
|
29878
|
-
}
|
|
29879
|
-
function renderFiglet(input) {
|
|
29880
|
-
const {
|
|
29881
|
-
dimOpen,
|
|
29882
|
-
dimClose,
|
|
29883
|
-
greenUnderline,
|
|
29884
|
-
greenUnderlineClose,
|
|
29885
|
-
violetOpen,
|
|
29886
|
-
violetClose,
|
|
29887
|
-
yellowOpen,
|
|
29888
|
-
yellowClose
|
|
29889
|
-
} = resolveAnsi(input.colorEnabled);
|
|
29890
|
-
const logoLines = LOGO_LINES.map((line) => `${violetOpen}${line}${violetClose}`);
|
|
29891
|
-
const versionText = `v${input.version}`;
|
|
29892
|
-
const devText = "[dev]";
|
|
29893
|
-
const versionWidth = input.dev ? devText.length : versionText.length;
|
|
29894
|
-
const versionPad = Math.max(0, LOGO_WIDTH - versionWidth);
|
|
29895
|
-
const versionLine = input.dev ? `${" ".repeat(versionPad)}${yellowOpen}${devText}${yellowClose}` : `${" ".repeat(versionPad)}${dimOpen}${versionText}${dimClose}`;
|
|
29896
|
-
const lines = [];
|
|
29897
|
-
lines.push(...logoLines);
|
|
29898
|
-
lines.push("");
|
|
29899
|
-
lines.push(versionLine);
|
|
29900
|
-
lines.push("");
|
|
29901
|
-
lines.push(` ${dimOpen}Server${dimClose} ${greenUnderline}${input.url}${greenUnderlineClose}`);
|
|
29902
|
-
lines.push(` ${dimOpen}Path${dimClose} ${input.pathDisplay}`);
|
|
29903
|
-
lines.push(` ${dimOpen}DB${dimClose} ${input.dbDisplay}`);
|
|
29904
|
-
lines.push(...renderListRows("Refs", input.referencePaths, dimOpen, dimClose));
|
|
29905
|
-
lines.push("");
|
|
29906
|
-
lines.push(` ${dimOpen}${input.browserLine}${dimClose}`);
|
|
29907
|
-
lines.push("");
|
|
29908
|
-
return lines.join("\n") + "\n";
|
|
29909
|
-
}
|
|
29910
|
-
function renderListRows(label, values, dimOpen, dimClose) {
|
|
29911
|
-
if (values.length === 0) return [];
|
|
29912
|
-
const out = [];
|
|
29913
|
-
const labelPad = " ".repeat(Math.max(1, 9 - label.length));
|
|
29914
|
-
const continuationPad = " ".repeat(11);
|
|
29915
|
-
out.push(` ${dimOpen}${label}${dimClose}${labelPad}${sanitizeForTerminal(values[0])}`);
|
|
29916
|
-
for (let i = 1; i < values.length; i += 1) {
|
|
29917
|
-
out.push(`${continuationPad}${sanitizeForTerminal(values[i])}`);
|
|
29918
|
-
}
|
|
29919
|
-
return out;
|
|
29920
|
-
}
|
|
29921
|
-
var EMPTY_ANSI = {
|
|
29922
|
-
dimOpen: "",
|
|
29923
|
-
dimClose: "",
|
|
29924
|
-
greenUnderline: "",
|
|
29925
|
-
greenUnderlineClose: "",
|
|
29926
|
-
violetOpen: "",
|
|
29927
|
-
violetClose: "",
|
|
29928
|
-
yellowOpen: "",
|
|
29929
|
-
yellowClose: ""
|
|
29930
|
-
};
|
|
29931
|
-
var ENABLED_ANSI = {
|
|
29932
|
-
dimOpen: ESC2.dim,
|
|
29933
|
-
dimClose: ESC2.reset,
|
|
29934
|
-
greenUnderline: `${ESC2.green}${ESC2.underline}`,
|
|
29935
|
-
greenUnderlineClose: ESC2.reset,
|
|
29936
|
-
violetOpen: ESC2.violet,
|
|
29937
|
-
violetClose: ESC2.reset,
|
|
29938
|
-
yellowOpen: ESC2.yellow,
|
|
29939
|
-
yellowClose: ESC2.reset
|
|
29940
|
-
};
|
|
29941
|
-
function resolveAnsi(colorEnabled) {
|
|
29942
|
-
return colorEnabled ? ENABLED_ANSI : EMPTY_ANSI;
|
|
29943
|
-
}
|
|
29944
|
-
function formatDbPath(dbPath, cwd) {
|
|
29945
|
-
const safe = sanitizeForTerminal(dbPath);
|
|
29946
|
-
if (!isAbsolute15(safe)) return safe;
|
|
29947
|
-
const rel = relative8(cwd, safe);
|
|
29948
|
-
if (rel === "" || rel.startsWith("..") || isAbsolute15(rel)) {
|
|
29949
|
-
return safe;
|
|
29950
|
-
}
|
|
29951
|
-
return rel;
|
|
29952
|
-
}
|
|
29953
|
-
function formatCwdPath(cwd) {
|
|
29954
|
-
return sanitizeForTerminal(cwd);
|
|
29955
|
-
}
|
|
29956
|
-
|
|
29957
30192
|
// cli/commands/serve.ts
|
|
29958
30193
|
var ServeCommand = class extends SmCommand {
|
|
29959
30194
|
static paths = [["serve"]];
|
|
29960
|
-
static usage =
|
|
30195
|
+
static usage = Command35.Usage({
|
|
29961
30196
|
category: "Setup",
|
|
29962
30197
|
description: "Start the Hono BFF (single-port: REST + WebSocket + SPA bundle).",
|
|
29963
30198
|
details: `
|
|
@@ -29981,18 +30216,18 @@ var ServeCommand = class extends SmCommand {
|
|
|
29981
30216
|
["Point at a pre-built UI bundle", "$0 serve --ui-dist ./ui/dist/browser"]
|
|
29982
30217
|
]
|
|
29983
30218
|
});
|
|
29984
|
-
port =
|
|
30219
|
+
port = Option33.String("--port", {
|
|
29985
30220
|
required: false,
|
|
29986
30221
|
description: "Listening port (default 4242). 0 = OS-assigned."
|
|
29987
30222
|
});
|
|
29988
|
-
host =
|
|
30223
|
+
host = Option33.String("--host", {
|
|
29989
30224
|
required: false,
|
|
29990
30225
|
description: "Listening host (default 127.0.0.1). Loopback-only enforced when --dev-cors is set."
|
|
29991
30226
|
});
|
|
29992
|
-
noBuiltIns =
|
|
30227
|
+
noBuiltIns = Option33.Boolean("--no-built-ins", false, {
|
|
29993
30228
|
description: "Skip built-in plugin registration (parity with sm scan --no-built-ins)."
|
|
29994
30229
|
});
|
|
29995
|
-
noPlugins =
|
|
30230
|
+
noPlugins = Option33.Boolean("--no-plugins", false, {
|
|
29996
30231
|
description: "Skip drop-in plugin discovery."
|
|
29997
30232
|
});
|
|
29998
30233
|
// `Option.Boolean('--open', true)`, Clipanion's parser auto-derives
|
|
@@ -30002,35 +30237,35 @@ var ServeCommand = class extends SmCommand {
|
|
|
30002
30237
|
// two registrations for the same flag and rejects the invocation
|
|
30003
30238
|
// with "Ambiguous Syntax Error". Same convention shipped by every
|
|
30004
30239
|
// other `--no-...` flag in the CLI tree.
|
|
30005
|
-
open =
|
|
30240
|
+
open = Option33.Boolean("--open", true, {
|
|
30006
30241
|
description: "Auto-open the SPA in the user's default browser after listen. --no-open opts out."
|
|
30007
30242
|
});
|
|
30008
|
-
devCors =
|
|
30243
|
+
devCors = Option33.Boolean("--dev-cors", false, {
|
|
30009
30244
|
description: "Enable permissive CORS for the Angular dev-server proxy workflow."
|
|
30010
30245
|
});
|
|
30011
30246
|
// `--ui-dist` is intentionally undocumented in the Usage block above
|
|
30012
30247
|
// (the demo build pipeline + tests rely on it; everyday users never
|
|
30013
30248
|
// need it). Clipanion still exposes it on the parser; the Usage
|
|
30014
30249
|
// omission is the "hidden" contract per the 14.1 brief.
|
|
30015
|
-
uiDist =
|
|
30016
|
-
noUi =
|
|
30250
|
+
uiDist = Option33.String("--ui-dist", { required: false, hidden: true });
|
|
30251
|
+
noUi = Option33.Boolean("--no-ui", false, {
|
|
30017
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."
|
|
30018
30253
|
});
|
|
30019
|
-
noWatcher =
|
|
30254
|
+
noWatcher = Option33.Boolean("--no-watcher", false, {
|
|
30020
30255
|
description: "Disable the chokidar-fed scan-and-broadcast loop. Use only for CI / read-only deployments."
|
|
30021
30256
|
});
|
|
30022
|
-
yes =
|
|
30257
|
+
yes = Option33.Boolean("--yes", false, {
|
|
30023
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."
|
|
30024
30259
|
});
|
|
30025
30260
|
// `--watcher-debounce-ms` is undocumented sugar for advanced users
|
|
30026
30261
|
// who want to tighten / relax the watcher's batching window without
|
|
30027
30262
|
// editing settings.json. Hidden flag, the Usage block omits it.
|
|
30028
|
-
watcherDebounceMs =
|
|
30029
|
-
maxScan =
|
|
30263
|
+
watcherDebounceMs = Option33.String("--watcher-debounce-ms", { required: false, hidden: true });
|
|
30264
|
+
maxScan = Option33.String("--max-scan", {
|
|
30030
30265
|
required: false,
|
|
30031
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`."
|
|
30032
30267
|
});
|
|
30033
|
-
maxNodes =
|
|
30268
|
+
maxNodes = Option33.String("--max-nodes", {
|
|
30034
30269
|
required: false,
|
|
30035
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`."
|
|
30036
30271
|
});
|
|
@@ -30060,7 +30295,7 @@ var ServeCommand = class extends SmCommand {
|
|
|
30060
30295
|
return ExitCode.Error;
|
|
30061
30296
|
}
|
|
30062
30297
|
const dbPath = resolveDbPath({ db: this.db, ...runtimeCtx });
|
|
30063
|
-
if (this.db !== void 0 && !
|
|
30298
|
+
if (this.db !== void 0 && !existsSync32(dbPath)) {
|
|
30064
30299
|
this.printer.info(
|
|
30065
30300
|
tx(SERVE_TEXTS.dbNotFound, {
|
|
30066
30301
|
glyph: errGlyph,
|
|
@@ -30400,7 +30635,7 @@ function tryOpenBrowser(url, stderr, warnGlyph) {
|
|
|
30400
30635
|
}
|
|
30401
30636
|
|
|
30402
30637
|
// cli/commands/show.ts
|
|
30403
|
-
import { Command as
|
|
30638
|
+
import { Command as Command36, Option as Option34 } from "clipanion";
|
|
30404
30639
|
|
|
30405
30640
|
// cli/i18n/show.texts.ts
|
|
30406
30641
|
var SHOW_TEXTS = {
|
|
@@ -30451,7 +30686,7 @@ var SHOW_TEXTS = {
|
|
|
30451
30686
|
// cli/commands/show.ts
|
|
30452
30687
|
var ShowCommand = class extends SmCommand {
|
|
30453
30688
|
static paths = [["show"]];
|
|
30454
|
-
static usage =
|
|
30689
|
+
static usage = Command36.Usage({
|
|
30455
30690
|
category: "Browse",
|
|
30456
30691
|
description: "Node detail: weight, frontmatter, links, issues.",
|
|
30457
30692
|
details: `
|
|
@@ -30467,7 +30702,7 @@ var ShowCommand = class extends SmCommand {
|
|
|
30467
30702
|
["Machine-readable detail", "$0 show .claude/agents/architect.md --json"]
|
|
30468
30703
|
]
|
|
30469
30704
|
});
|
|
30470
|
-
nodePath =
|
|
30705
|
+
nodePath = Option34.String({ required: true });
|
|
30471
30706
|
async run() {
|
|
30472
30707
|
const dbPath = resolveDbPath({ db: this.db, ...defaultRuntimeContext() });
|
|
30473
30708
|
const exit = requireDbOrExit(dbPath, this.context.stderr);
|
|
@@ -30708,8 +30943,8 @@ function rankConfidenceForGrouping(c) {
|
|
|
30708
30943
|
|
|
30709
30944
|
// cli/commands/sidecar.ts
|
|
30710
30945
|
import { unlink as unlink3 } from "fs/promises";
|
|
30711
|
-
import { resolve as
|
|
30712
|
-
import { Command as
|
|
30946
|
+
import { resolve as resolve42 } from "path";
|
|
30947
|
+
import { Command as Command37, Option as Option35 } from "clipanion";
|
|
30713
30948
|
|
|
30714
30949
|
// cli/i18n/sidecar.texts.ts
|
|
30715
30950
|
var SIDECAR_TEXTS = {
|
|
@@ -30790,7 +31025,7 @@ async function runWithSidecarConsent(bag, ansi, dispatch) {
|
|
|
30790
31025
|
}
|
|
30791
31026
|
var SidecarRefreshCommand = class extends SmCommand {
|
|
30792
31027
|
static paths = [["sidecar", "refresh"]];
|
|
30793
|
-
static usage =
|
|
31028
|
+
static usage = Command37.Usage({
|
|
30794
31029
|
category: "Actions",
|
|
30795
31030
|
description: "Refresh a sidecar's `for.{bodyHash, frontmatterHash}` to match the live node. Does NOT bump the version.",
|
|
30796
31031
|
details: `
|
|
@@ -30807,8 +31042,8 @@ var SidecarRefreshCommand = class extends SmCommand {
|
|
|
30807
31042
|
["Refresh a node's sidecar hashes", "$0 sidecar refresh .claude/agents/architect.md"]
|
|
30808
31043
|
]
|
|
30809
31044
|
});
|
|
30810
|
-
nodePath =
|
|
30811
|
-
yes =
|
|
31045
|
+
nodePath = Option35.String({ required: true });
|
|
31046
|
+
yes = Option35.Boolean("--yes", false, {
|
|
30812
31047
|
description: "Confirm writing .sm sidecar files in this project (sets allowEditSmFiles=true on first run)."
|
|
30813
31048
|
});
|
|
30814
31049
|
async run() {
|
|
@@ -30866,7 +31101,7 @@ var SidecarRefreshCommand = class extends SmCommand {
|
|
|
30866
31101
|
let absPath;
|
|
30867
31102
|
try {
|
|
30868
31103
|
assertContained(ctx.cwd, node.path);
|
|
30869
|
-
absPath =
|
|
31104
|
+
absPath = resolve42(ctx.cwd, node.path);
|
|
30870
31105
|
} catch (err) {
|
|
30871
31106
|
this.printer.error(
|
|
30872
31107
|
tx(SIDECAR_TEXTS.refreshFailed, { glyph: errGlyph, message: formatErrorMessage(err) })
|
|
@@ -30930,7 +31165,7 @@ var SidecarRefreshCommand = class extends SmCommand {
|
|
|
30930
31165
|
};
|
|
30931
31166
|
var SidecarPruneCommand = class extends SmCommand {
|
|
30932
31167
|
static paths = [["sidecar", "prune"]];
|
|
30933
|
-
static usage =
|
|
31168
|
+
static usage = Command37.Usage({
|
|
30934
31169
|
category: "Actions",
|
|
30935
31170
|
description: "Delete orphan .sm files (sidecars whose accompanying .md no longer exists).",
|
|
30936
31171
|
details: `
|
|
@@ -30952,8 +31187,8 @@ var SidecarPruneCommand = class extends SmCommand {
|
|
|
30952
31187
|
["Delete every orphan .sm file (non-interactive)", "$0 sidecar prune --yes"]
|
|
30953
31188
|
]
|
|
30954
31189
|
});
|
|
30955
|
-
dryRun =
|
|
30956
|
-
yes =
|
|
31190
|
+
dryRun = Option35.Boolean("-n,--dry-run", false);
|
|
31191
|
+
yes = Option35.Boolean("--yes,--force", false, {
|
|
30957
31192
|
description: "Skip the interactive confirmation prompt. Required for non-interactive callers (CI, pre-commit hooks)."
|
|
30958
31193
|
});
|
|
30959
31194
|
// Complexity is from per-orphan handling, empty-set / dry-run /
|
|
@@ -31073,7 +31308,7 @@ var SidecarPruneCommand = class extends SmCommand {
|
|
|
31073
31308
|
};
|
|
31074
31309
|
var SidecarAnnotateCommand = class extends SmCommand {
|
|
31075
31310
|
static paths = [["sidecar", "annotate"]];
|
|
31076
|
-
static usage =
|
|
31311
|
+
static usage = Command37.Usage({
|
|
31077
31312
|
category: "Actions",
|
|
31078
31313
|
description: "Scaffold an empty `<basename>.sm` next to a node ready for editing.",
|
|
31079
31314
|
details: `
|
|
@@ -31091,9 +31326,9 @@ var SidecarAnnotateCommand = class extends SmCommand {
|
|
|
31091
31326
|
["Overwrite an existing one", "$0 sidecar annotate .claude/agents/architect.md --force"]
|
|
31092
31327
|
]
|
|
31093
31328
|
});
|
|
31094
|
-
nodePath =
|
|
31095
|
-
force =
|
|
31096
|
-
yes =
|
|
31329
|
+
nodePath = Option35.String({ required: true });
|
|
31330
|
+
force = Option35.Boolean("--force", false);
|
|
31331
|
+
yes = Option35.Boolean("--yes", false, {
|
|
31097
31332
|
description: "Confirm writing .sm sidecar files in this project (sets allowEditSmFiles=true on first run)."
|
|
31098
31333
|
});
|
|
31099
31334
|
async run() {
|
|
@@ -31150,7 +31385,7 @@ var SidecarAnnotateCommand = class extends SmCommand {
|
|
|
31150
31385
|
let absPath;
|
|
31151
31386
|
try {
|
|
31152
31387
|
assertContained(ctx.cwd, node.path);
|
|
31153
|
-
absPath =
|
|
31388
|
+
absPath = resolve42(ctx.cwd, node.path);
|
|
31154
31389
|
} catch (err) {
|
|
31155
31390
|
this.printer.error(
|
|
31156
31391
|
tx(SIDECAR_TEXTS.annotateFailed, { glyph: errGlyph, message: formatErrorMessage(err) })
|
|
@@ -31232,7 +31467,7 @@ var SIDECAR_COMMANDS = [
|
|
|
31232
31467
|
];
|
|
31233
31468
|
|
|
31234
31469
|
// cli/commands/stubs.ts
|
|
31235
|
-
import { Command as
|
|
31470
|
+
import { Command as Command38, Option as Option36 } from "clipanion";
|
|
31236
31471
|
|
|
31237
31472
|
// cli/i18n/stubs.texts.ts
|
|
31238
31473
|
var STUBS_TEXTS = {
|
|
@@ -31258,7 +31493,7 @@ var StubCommand = class extends SmCommand {
|
|
|
31258
31493
|
};
|
|
31259
31494
|
var DoctorCommand = class extends StubCommand {
|
|
31260
31495
|
static paths = [["doctor"]];
|
|
31261
|
-
static usage =
|
|
31496
|
+
static usage = Command38.Usage({
|
|
31262
31497
|
category: "Setup",
|
|
31263
31498
|
description: planned("Diagnostic report: DB integrity, pending migrations, orphan rows, plugin status, runner availability.")
|
|
31264
31499
|
});
|
|
@@ -31266,18 +31501,18 @@ var DoctorCommand = class extends StubCommand {
|
|
|
31266
31501
|
};
|
|
31267
31502
|
var FindingsCommand = class extends StubCommand {
|
|
31268
31503
|
static paths = [["findings"]];
|
|
31269
|
-
static usage =
|
|
31504
|
+
static usage = Command38.Usage({
|
|
31270
31505
|
category: "Browse",
|
|
31271
31506
|
description: planned("Probabilistic findings: injection, stale summaries, low confidence.")
|
|
31272
31507
|
});
|
|
31273
|
-
kind =
|
|
31274
|
-
since =
|
|
31275
|
-
threshold =
|
|
31508
|
+
kind = Option36.String("--kind", { required: false });
|
|
31509
|
+
since = Option36.String("--since", { required: false });
|
|
31510
|
+
threshold = Option36.String("--threshold", { required: false });
|
|
31276
31511
|
verbName = "findings";
|
|
31277
31512
|
};
|
|
31278
31513
|
var ActionsListCommand = class extends StubCommand {
|
|
31279
31514
|
static paths = [["actions", "list"]];
|
|
31280
|
-
static usage =
|
|
31515
|
+
static usage = Command38.Usage({
|
|
31281
31516
|
category: "Jobs",
|
|
31282
31517
|
description: planned("Registered action types (manifest view).")
|
|
31283
31518
|
});
|
|
@@ -31285,103 +31520,103 @@ var ActionsListCommand = class extends StubCommand {
|
|
|
31285
31520
|
};
|
|
31286
31521
|
var ActionsShowCommand = class extends StubCommand {
|
|
31287
31522
|
static paths = [["actions", "show"]];
|
|
31288
|
-
static usage =
|
|
31523
|
+
static usage = Command38.Usage({
|
|
31289
31524
|
category: "Jobs",
|
|
31290
31525
|
description: planned("Full action manifest, including preconditions and expected duration.")
|
|
31291
31526
|
});
|
|
31292
|
-
id =
|
|
31527
|
+
id = Option36.String({ required: true });
|
|
31293
31528
|
verbName = "actions show";
|
|
31294
31529
|
};
|
|
31295
31530
|
var JobSubmitCommand = class extends StubCommand {
|
|
31296
31531
|
static paths = [["job", "submit"]];
|
|
31297
|
-
static usage =
|
|
31532
|
+
static usage = Command38.Usage({
|
|
31298
31533
|
category: "Jobs",
|
|
31299
31534
|
description: planned("Enqueue a single job or fan out to every matching node (--all).")
|
|
31300
31535
|
});
|
|
31301
|
-
action =
|
|
31302
|
-
node =
|
|
31303
|
-
all =
|
|
31536
|
+
action = Option36.String({ required: true });
|
|
31537
|
+
node = Option36.String("-n", { required: false });
|
|
31538
|
+
all = Option36.Boolean("--all", false);
|
|
31304
31539
|
// CLI flag stays `--run`; field name is `runFlag` per the
|
|
31305
31540
|
// shadow-avoidance convention documented on `SmCommand`.
|
|
31306
|
-
runFlag =
|
|
31307
|
-
force =
|
|
31308
|
-
ttl =
|
|
31309
|
-
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 });
|
|
31310
31545
|
verbName = "job submit";
|
|
31311
31546
|
};
|
|
31312
31547
|
var JobListCommand = class extends StubCommand {
|
|
31313
31548
|
static paths = [["job", "list"]];
|
|
31314
|
-
static usage =
|
|
31315
|
-
status =
|
|
31316
|
-
action =
|
|
31317
|
-
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 });
|
|
31318
31553
|
verbName = "job list";
|
|
31319
31554
|
};
|
|
31320
31555
|
var JobShowCommand = class extends StubCommand {
|
|
31321
31556
|
static paths = [["job", "show"]];
|
|
31322
|
-
static usage =
|
|
31323
|
-
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 });
|
|
31324
31559
|
verbName = "job show";
|
|
31325
31560
|
};
|
|
31326
31561
|
var JobPreviewCommand = class extends StubCommand {
|
|
31327
31562
|
static paths = [["job", "preview"]];
|
|
31328
|
-
static usage =
|
|
31329
|
-
id =
|
|
31563
|
+
static usage = Command38.Usage({ category: "Jobs", description: planned("Render the job MD file without executing.") });
|
|
31564
|
+
id = Option36.String({ required: true });
|
|
31330
31565
|
verbName = "job preview";
|
|
31331
31566
|
};
|
|
31332
31567
|
var JobClaimCommand = class extends StubCommand {
|
|
31333
31568
|
static paths = [["job", "claim"]];
|
|
31334
|
-
static usage =
|
|
31569
|
+
static usage = Command38.Usage({
|
|
31335
31570
|
category: "Jobs",
|
|
31336
31571
|
description: planned("Atomic primitive: return next queued job id, mark it running.")
|
|
31337
31572
|
});
|
|
31338
|
-
filter =
|
|
31573
|
+
filter = Option36.String("--filter", { required: false });
|
|
31339
31574
|
verbName = "job claim";
|
|
31340
31575
|
};
|
|
31341
31576
|
var JobRunCommand = class extends StubCommand {
|
|
31342
31577
|
static paths = [["job", "run"]];
|
|
31343
|
-
static usage =
|
|
31578
|
+
static usage = Command38.Usage({
|
|
31344
31579
|
category: "Jobs",
|
|
31345
31580
|
description: planned("Full CLI-runner loop: claim + spawn + record.")
|
|
31346
31581
|
});
|
|
31347
|
-
all =
|
|
31348
|
-
max =
|
|
31582
|
+
all = Option36.Boolean("--all", false);
|
|
31583
|
+
max = Option36.String("--max", { required: false });
|
|
31349
31584
|
verbName = "job run";
|
|
31350
31585
|
};
|
|
31351
31586
|
var JobStatusCommand = class extends StubCommand {
|
|
31352
31587
|
static paths = [["job", "status"]];
|
|
31353
|
-
static usage =
|
|
31588
|
+
static usage = Command38.Usage({
|
|
31354
31589
|
category: "Jobs",
|
|
31355
31590
|
description: planned("Counts (per status) or single-job status.")
|
|
31356
31591
|
});
|
|
31357
|
-
id =
|
|
31592
|
+
id = Option36.String({ required: false });
|
|
31358
31593
|
verbName = "job status";
|
|
31359
31594
|
};
|
|
31360
31595
|
var JobCancelCommand = class extends StubCommand {
|
|
31361
31596
|
static paths = [["job", "cancel"]];
|
|
31362
|
-
static usage =
|
|
31597
|
+
static usage = Command38.Usage({
|
|
31363
31598
|
category: "Jobs",
|
|
31364
31599
|
description: planned("Force a running job to failed with reason user-cancelled.")
|
|
31365
31600
|
});
|
|
31366
|
-
id =
|
|
31367
|
-
all =
|
|
31601
|
+
id = Option36.String({ required: false });
|
|
31602
|
+
all = Option36.Boolean("--all", false);
|
|
31368
31603
|
verbName = "job cancel";
|
|
31369
31604
|
};
|
|
31370
31605
|
var RecordCommand = class extends StubCommand {
|
|
31371
31606
|
static paths = [["record"]];
|
|
31372
|
-
static usage =
|
|
31607
|
+
static usage = Command38.Usage({
|
|
31373
31608
|
category: "Jobs",
|
|
31374
31609
|
description: planned("Close a running job with success or failure. Nonce is the sole credential.")
|
|
31375
31610
|
});
|
|
31376
|
-
id =
|
|
31377
|
-
nonce =
|
|
31378
|
-
status =
|
|
31379
|
-
report =
|
|
31380
|
-
tokensIn =
|
|
31381
|
-
tokensOut =
|
|
31382
|
-
durationMs =
|
|
31383
|
-
model =
|
|
31384
|
-
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 });
|
|
31385
31620
|
verbName = "record";
|
|
31386
31621
|
};
|
|
31387
31622
|
var STUB_COMMANDS = [
|
|
@@ -31401,11 +31636,11 @@ var STUB_COMMANDS = [
|
|
|
31401
31636
|
];
|
|
31402
31637
|
|
|
31403
31638
|
// cli/commands/tutorial.ts
|
|
31404
|
-
import { cpSync as
|
|
31405
|
-
import { dirname as
|
|
31406
|
-
import { createInterface as
|
|
31407
|
-
import { fileURLToPath as
|
|
31408
|
-
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";
|
|
31409
31644
|
|
|
31410
31645
|
// cli/i18n/tutorial.texts.ts
|
|
31411
31646
|
var TUTORIAL_TEXTS = {
|
|
@@ -31428,14 +31663,8 @@ var TUTORIAL_TEXTS = {
|
|
|
31428
31663
|
// default).
|
|
31429
31664
|
promptHeader: "{{glyph}} Which agent should host the tutorial skill?",
|
|
31430
31665
|
promptOption: " {{index}}) {{label}}: {{skillDir}}{{marker}}",
|
|
31431
|
-
// Coming-soon Providers are listed for visibility but cannot be picked
|
|
31432
|
-
// (no skillDir, a `(coming soon)` tag instead of a target path).
|
|
31433
|
-
promptOptionComingSoon: " {{index}}) {{label}} (coming soon)",
|
|
31434
31666
|
promptDefaultMarker: " (default)",
|
|
31435
31667
|
promptInput: " Enter the number or provider id [default {{index}}]: ",
|
|
31436
|
-
// Shown (and the prompt re-asked) when the tester picks a coming-soon
|
|
31437
|
-
// entry: it is visible but not selectable yet.
|
|
31438
|
-
promptComingSoonNotice: " {{label}} is coming soon, not selectable yet. Pick {{defaultLabel}}.",
|
|
31439
31668
|
// Prompt answer matched neither an index nor an id. Goes to stderr,
|
|
31440
31669
|
// exit code 2. Mirrors the error shape: glyph + headline + dim hint.
|
|
31441
31670
|
promptInvalid: "{{glyph}} sm tutorial: that is not one of the listed providers\n {{hint}}\n",
|
|
@@ -31473,7 +31702,7 @@ var TRIGGER_EN = "run the tutorial";
|
|
|
31473
31702
|
var TRIGGER_ES = "ejecuta el tutorial";
|
|
31474
31703
|
var TutorialCommand = class extends SmCommand {
|
|
31475
31704
|
static paths = [["tutorial"]];
|
|
31476
|
-
static usage =
|
|
31705
|
+
static usage = Command39.Usage({
|
|
31477
31706
|
category: "Setup",
|
|
31478
31707
|
description: "Materialize an interactive tester tutorial as a Claude Code skill folder under `<cwd>/.claude/skills/`.",
|
|
31479
31708
|
details: `
|
|
@@ -31486,27 +31715,36 @@ var TutorialCommand = class extends SmCommand {
|
|
|
31486
31715
|
Does NOT require an initialized .skill-map/ project. Refuses to
|
|
31487
31716
|
overwrite the target directory unless --force is passed. Takes no
|
|
31488
31717
|
positional argument.
|
|
31718
|
+
|
|
31719
|
+
By default only ready providers are offered as destinations. Pass
|
|
31720
|
+
--experimental to also offer experimental ones (e.g. agent-skills);
|
|
31721
|
+
they ship disabled, so enable the chosen one with
|
|
31722
|
+
\`sm plugins enable <id>\` before scanning under its lens.
|
|
31489
31723
|
`,
|
|
31490
31724
|
examples: [
|
|
31491
31725
|
["Materialize the tutorial skill in the cwd", "$0 tutorial"],
|
|
31492
|
-
["Overwrite an existing target directory", "$0 tutorial --force"]
|
|
31726
|
+
["Overwrite an existing target directory", "$0 tutorial --force"],
|
|
31727
|
+
["Offer experimental providers as destinations", "$0 tutorial --experimental"]
|
|
31493
31728
|
]
|
|
31494
31729
|
});
|
|
31495
31730
|
// Legacy positional catcher: the verb takes no positional argument any
|
|
31496
31731
|
// more. Accept one so a stale `sm tutorial master` lands on a friendly
|
|
31497
31732
|
// usage error (guarded in `run()`) instead of clipanion's generic
|
|
31498
31733
|
// "extraneous argument" message.
|
|
31499
|
-
legacyPositional =
|
|
31734
|
+
legacyPositional = Option37.String({ required: false });
|
|
31500
31735
|
// Named `forProvider`, NOT `for` (reserved word). The CLI surface stays
|
|
31501
31736
|
// `--for`; selects the destination Provider whose `scaffold.skillDir`
|
|
31502
31737
|
// the skill is materialised under, skipping the interactive prompt.
|
|
31503
|
-
forProvider =
|
|
31738
|
+
forProvider = Option37.String("--for", {
|
|
31504
31739
|
required: false,
|
|
31505
31740
|
description: "Destination provider id (e.g. claude). Skips the prompt."
|
|
31506
31741
|
});
|
|
31507
|
-
force =
|
|
31742
|
+
force = Option37.Boolean("--force", false, {
|
|
31508
31743
|
description: "Overwrite an existing target directory without prompting."
|
|
31509
31744
|
});
|
|
31745
|
+
experimental = Option37.Boolean("--experimental", false, {
|
|
31746
|
+
description: "Offer experimental providers (e.g. agent-skills) as destinations. They ship disabled; enable the chosen one with `sm plugins enable <id>`."
|
|
31747
|
+
});
|
|
31510
31748
|
async run() {
|
|
31511
31749
|
const ctx = defaultRuntimeContext();
|
|
31512
31750
|
const stderr = this.context.stderr;
|
|
@@ -31532,7 +31770,7 @@ var TutorialCommand = class extends SmCommand {
|
|
|
31532
31770
|
);
|
|
31533
31771
|
return ExitCode.Error;
|
|
31534
31772
|
}
|
|
31535
|
-
const targets = listScaffoldTargets();
|
|
31773
|
+
const targets = listScaffoldTargets(this.experimental);
|
|
31536
31774
|
const target = await this.resolveScaffoldTarget(targets, stderrAnsi, errGlyph);
|
|
31537
31775
|
if (target === null) return ExitCode.Error;
|
|
31538
31776
|
if (target.skillDir === void 0) {
|
|
@@ -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, {
|
|
@@ -31602,21 +31840,20 @@ var TutorialCommand = class extends SmCommand {
|
|
|
31602
31840
|
* Returns `null` after printing an error (caller exits non-zero).
|
|
31603
31841
|
*/
|
|
31604
31842
|
async resolveScaffoldTarget(targets, stderrAnsi, errGlyph) {
|
|
31605
|
-
|
|
31606
|
-
if (selectable.length === 0) {
|
|
31843
|
+
if (targets.length === 0) {
|
|
31607
31844
|
this.printer.error(tx(TUTORIAL_TEXTS.noTargets, { glyph: errGlyph }));
|
|
31608
31845
|
return null;
|
|
31609
31846
|
}
|
|
31610
31847
|
const requested = this.forProvider;
|
|
31611
31848
|
if (requested !== void 0) {
|
|
31612
|
-
const found =
|
|
31849
|
+
const found = targets.find((t) => t.id === requested);
|
|
31613
31850
|
if (found === void 0) {
|
|
31614
31851
|
this.printer.error(
|
|
31615
31852
|
tx(TUTORIAL_TEXTS.forUnknown, {
|
|
31616
31853
|
glyph: errGlyph,
|
|
31617
31854
|
provider: requested,
|
|
31618
31855
|
hint: stderrAnsi.dim(
|
|
31619
|
-
tx(TUTORIAL_TEXTS.forUnknownHint, { ids:
|
|
31856
|
+
tx(TUTORIAL_TEXTS.forUnknownHint, { ids: targets.map((t) => t.id).join(", ") })
|
|
31620
31857
|
)
|
|
31621
31858
|
})
|
|
31622
31859
|
);
|
|
@@ -31624,7 +31861,7 @@ var TutorialCommand = class extends SmCommand {
|
|
|
31624
31861
|
}
|
|
31625
31862
|
return found;
|
|
31626
31863
|
}
|
|
31627
|
-
const def =
|
|
31864
|
+
const def = targets[0];
|
|
31628
31865
|
const stdin = this.context.stdin;
|
|
31629
31866
|
if (stdin.isTTY !== true) return def;
|
|
31630
31867
|
const stderr = this.context.stderr;
|
|
@@ -31640,7 +31877,7 @@ var TutorialCommand = class extends SmCommand {
|
|
|
31640
31877
|
tx(TUTORIAL_TEXTS.promptInvalid, {
|
|
31641
31878
|
glyph: errGlyph,
|
|
31642
31879
|
hint: stderrAnsi.dim(
|
|
31643
|
-
tx(TUTORIAL_TEXTS.forUnknownHint, { ids:
|
|
31880
|
+
tx(TUTORIAL_TEXTS.forUnknownHint, { ids: targets.map((t) => t.id).join(", ") })
|
|
31644
31881
|
)
|
|
31645
31882
|
})
|
|
31646
31883
|
);
|
|
@@ -31649,37 +31886,25 @@ var TutorialCommand = class extends SmCommand {
|
|
|
31649
31886
|
return picked;
|
|
31650
31887
|
}
|
|
31651
31888
|
};
|
|
31652
|
-
function toScaffoldTarget(provider) {
|
|
31653
|
-
const comingSoon = provider.presentation.comingSoon === true;
|
|
31654
|
-
if (comingSoon) {
|
|
31655
|
-
return {
|
|
31656
|
-
id: provider.id,
|
|
31657
|
-
label: provider.presentation.label,
|
|
31658
|
-
aka: provider.scaffold?.aka ?? [],
|
|
31659
|
-
comingSoon: true
|
|
31660
|
-
};
|
|
31661
|
-
}
|
|
31889
|
+
function toScaffoldTarget(provider, includeExperimental) {
|
|
31662
31890
|
const scaffold = provider.scaffold;
|
|
31663
31891
|
if (!scaffold || !scaffold.skillDir) return null;
|
|
31892
|
+
if (!installedDefaultEnabled(provider.stability) && !includeExperimental) return null;
|
|
31664
31893
|
return {
|
|
31665
31894
|
id: provider.id,
|
|
31666
31895
|
label: provider.presentation.label,
|
|
31667
31896
|
skillDir: scaffold.skillDir,
|
|
31668
|
-
aka: scaffold.aka ?? []
|
|
31669
|
-
comingSoon: false
|
|
31897
|
+
aka: scaffold.aka ?? []
|
|
31670
31898
|
};
|
|
31671
31899
|
}
|
|
31672
|
-
function listScaffoldTargets() {
|
|
31900
|
+
function listScaffoldTargets(includeExperimental = false) {
|
|
31673
31901
|
const out = [];
|
|
31674
31902
|
for (const provider of builtIns().providers) {
|
|
31675
|
-
const target = toScaffoldTarget(provider);
|
|
31903
|
+
const target = toScaffoldTarget(provider, includeExperimental);
|
|
31676
31904
|
if (target !== null) out.push(target);
|
|
31677
31905
|
}
|
|
31678
31906
|
return out;
|
|
31679
31907
|
}
|
|
31680
|
-
function selectableTargets(targets) {
|
|
31681
|
-
return targets.filter((t) => !t.comingSoon);
|
|
31682
|
-
}
|
|
31683
31908
|
function labelWithAka(target) {
|
|
31684
31909
|
return target.aka.length > 0 ? `${target.label} (${target.aka.join(", ")})` : target.label;
|
|
31685
31910
|
}
|
|
@@ -31688,7 +31913,7 @@ function renderTargetLines(targets, def, glyph) {
|
|
|
31688
31913
|
for (let i = 0; i < targets.length; i += 1) {
|
|
31689
31914
|
const t = targets[i];
|
|
31690
31915
|
lines.push(
|
|
31691
|
-
|
|
31916
|
+
tx(TUTORIAL_TEXTS.promptOption, {
|
|
31692
31917
|
index: i + 1,
|
|
31693
31918
|
label: labelWithAka(t),
|
|
31694
31919
|
skillDir: `${t.skillDir}/`,
|
|
@@ -31707,56 +31932,35 @@ function classifyAnswer(trimmed, targets, def) {
|
|
|
31707
31932
|
async function promptForTarget(targets, def, stdin, stderr, glyph) {
|
|
31708
31933
|
stderr.write(renderTargetLines(targets, def, glyph) + "\n");
|
|
31709
31934
|
const defIndex = targets.findIndex((t) => t.id === def.id);
|
|
31710
|
-
const rl =
|
|
31935
|
+
const rl = createInterface6({ input: stdin, output: stderr });
|
|
31711
31936
|
try {
|
|
31712
31937
|
for (let attempt = 0; attempt < 5; attempt += 1) {
|
|
31713
31938
|
const answer = await new Promise(
|
|
31714
31939
|
(resolveP) => rl.question(tx(TUTORIAL_TEXTS.promptInput, { index: defIndex + 1 }), resolveP)
|
|
31715
31940
|
);
|
|
31716
31941
|
const result = classifyAnswer(answer.trim(), targets, def);
|
|
31717
|
-
if (result
|
|
31718
|
-
if (!result.comingSoon) return result;
|
|
31719
|
-
stderr.write(
|
|
31720
|
-
tx(TUTORIAL_TEXTS.promptComingSoonNotice, {
|
|
31721
|
-
label: result.label,
|
|
31722
|
-
defaultLabel: def.label
|
|
31723
|
-
}) + "\n"
|
|
31724
|
-
);
|
|
31942
|
+
if (result !== null) return result;
|
|
31725
31943
|
}
|
|
31726
31944
|
return null;
|
|
31727
31945
|
} finally {
|
|
31728
31946
|
rl.close();
|
|
31729
31947
|
}
|
|
31730
31948
|
}
|
|
31731
|
-
|
|
31732
|
-
const segments = cwd.split("/").filter((s) => s.length > 0);
|
|
31733
|
-
if (segments.length === 0) return "./";
|
|
31734
|
-
return `./${segments[segments.length - 1]}/`;
|
|
31735
|
-
}
|
|
31736
|
-
function isDirEmpty(dir) {
|
|
31737
|
-
return readdirSync10(dir).length === 0;
|
|
31738
|
-
}
|
|
31739
|
-
function listCwdEntries(dir) {
|
|
31740
|
-
const entries = readdirSync10(dir).sort();
|
|
31741
|
-
const shown = entries.slice(0, 5);
|
|
31742
|
-
const more = entries.length > shown.length ? ", ..." : "";
|
|
31743
|
-
return shown.join(", ") + more;
|
|
31744
|
-
}
|
|
31745
|
-
var cachedSourceDir;
|
|
31949
|
+
var cachedSourceDir2;
|
|
31746
31950
|
function resolveSkillSourceDir() {
|
|
31747
|
-
if (
|
|
31748
|
-
const here =
|
|
31951
|
+
if (cachedSourceDir2 !== void 0) return cachedSourceDir2;
|
|
31952
|
+
const here = dirname21(fileURLToPath8(import.meta.url));
|
|
31749
31953
|
const candidates = [
|
|
31750
31954
|
// dev: src/cli/commands/ → repo-root .claude/skills/sm-tutorial/
|
|
31751
|
-
|
|
31955
|
+
resolve43(here, "../../..", SKILL_SOURCE_DIR),
|
|
31752
31956
|
// bundled: dist/cli.js → dist/cli/tutorial/sm-tutorial (sibling)
|
|
31753
|
-
|
|
31957
|
+
resolve43(here, "cli/tutorial", SKILL_SLUG),
|
|
31754
31958
|
// bundled fallback: any-depth → cli/tutorial/sm-tutorial
|
|
31755
|
-
|
|
31959
|
+
resolve43(here, "../cli/tutorial", SKILL_SLUG)
|
|
31756
31960
|
];
|
|
31757
31961
|
for (const candidate of candidates) {
|
|
31758
|
-
if (
|
|
31759
|
-
|
|
31962
|
+
if (existsSync33(candidate) && statSync12(candidate).isDirectory()) {
|
|
31963
|
+
cachedSourceDir2 = candidate;
|
|
31760
31964
|
return candidate;
|
|
31761
31965
|
}
|
|
31762
31966
|
}
|
|
@@ -31766,7 +31970,7 @@ function resolveSkillSourceDir() {
|
|
|
31766
31970
|
}
|
|
31767
31971
|
|
|
31768
31972
|
// cli/commands/version.ts
|
|
31769
|
-
import { Command as
|
|
31973
|
+
import { Command as Command40 } from "clipanion";
|
|
31770
31974
|
|
|
31771
31975
|
// cli/i18n/version.texts.ts
|
|
31772
31976
|
var VERSION_TEXTS = {
|
|
@@ -31781,7 +31985,7 @@ var VERSION_TEXTS = {
|
|
|
31781
31985
|
// cli/commands/version.ts
|
|
31782
31986
|
var VersionCommand = class extends SmCommand {
|
|
31783
31987
|
static paths = [["version"]];
|
|
31784
|
-
static usage =
|
|
31988
|
+
static usage = Command40.Usage({
|
|
31785
31989
|
category: "Introspection",
|
|
31786
31990
|
description: "Print the CLI / spec / runtime / db-schema version matrix."
|
|
31787
31991
|
});
|
|
@@ -31856,6 +32060,7 @@ cli.register(RootHelpCommand);
|
|
|
31856
32060
|
cli.register(HelpCommand);
|
|
31857
32061
|
cli.register(InitCommand);
|
|
31858
32062
|
cli.register(TutorialCommand);
|
|
32063
|
+
cli.register(ExampleCommand);
|
|
31859
32064
|
cli.register(IntentionalFailCommand);
|
|
31860
32065
|
cli.register(ScanCommand);
|
|
31861
32066
|
cli.register(ScanCompareCommand);
|
|
@@ -31888,7 +32093,7 @@ var logLevel = resolveLogLevel({
|
|
|
31888
32093
|
errStream: process.stderr
|
|
31889
32094
|
});
|
|
31890
32095
|
configureLogger(new Logger({ level: logLevel, stream: process.stderr }));
|
|
31891
|
-
var bareArgs = resolveBareInvocation(args);
|
|
32096
|
+
var bareArgs = await resolveBareInvocation(args);
|
|
31892
32097
|
var routedArgs = routeHelpArgs(bareArgs ?? args, cli);
|
|
31893
32098
|
var telemetryVerb = routedArgs[0];
|
|
31894
32099
|
await maybeRunFirstRunPrompt();
|
|
@@ -31946,23 +32151,41 @@ await lifecycleDispatcher.dispatch(
|
|
|
31946
32151
|
await closeSentryCli();
|
|
31947
32152
|
await flushUsageCli();
|
|
31948
32153
|
process.exit(exitCode);
|
|
31949
|
-
function resolveBareInvocation(rawArgs) {
|
|
31950
|
-
if (rawArgs.length === 0) return
|
|
32154
|
+
async function resolveBareInvocation(rawArgs) {
|
|
32155
|
+
if (rawArgs.length === 0) return resolveNoArgsBare();
|
|
31951
32156
|
const first = rawArgs[0];
|
|
31952
32157
|
const passthrough = /* @__PURE__ */ new Set(["--help", "-h", "--version", "-V", "-v"]);
|
|
31953
32158
|
if (first !== void 0 && first.startsWith("-") && !passthrough.has(first)) {
|
|
31954
32159
|
const isSingleDashLong = !first.startsWith("--") && first.length > 2;
|
|
31955
32160
|
if (isSingleDashLong) return null;
|
|
31956
|
-
if (
|
|
32161
|
+
if (existsSync34(defaultProjectDbPath(defaultRuntimeContext()))) {
|
|
31957
32162
|
return ["serve", ...rawArgs];
|
|
31958
32163
|
}
|
|
31959
32164
|
return resolveBareDefault();
|
|
31960
32165
|
}
|
|
31961
32166
|
return null;
|
|
31962
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
|
+
}
|
|
31963
32186
|
function resolveBareDefault() {
|
|
31964
32187
|
const ctx = defaultRuntimeContext();
|
|
31965
|
-
if (
|
|
32188
|
+
if (existsSync34(defaultProjectDbPath(ctx))) {
|
|
31966
32189
|
return ["serve"];
|
|
31967
32190
|
}
|
|
31968
32191
|
const stderr = process.stderr;
|
|
@@ -31971,10 +32194,12 @@ function resolveBareDefault() {
|
|
|
31971
32194
|
tx(ENTRY_TEXTS.bareNoProject, {
|
|
31972
32195
|
glyph: ansi.red("\u2715"),
|
|
31973
32196
|
cwd: ctx.cwd,
|
|
31974
|
-
hint: ansi.dim(
|
|
32197
|
+
hint: ansi.dim(
|
|
32198
|
+
isDirEmpty(ctx.cwd) ? ENTRY_TEXTS.bareEmptyHint : ENTRY_TEXTS.bareNoProjectHint
|
|
32199
|
+
)
|
|
31975
32200
|
})
|
|
31976
32201
|
);
|
|
31977
32202
|
process.exit(ExitCode.Error);
|
|
31978
32203
|
}
|
|
31979
32204
|
//# sourceMappingURL=cli.js.map
|
|
31980
|
-
//# debugId=
|
|
32205
|
+
//# debugId=43bb2367-1e14-5df2-9221-a5e7a877a666
|