@skill-map/cli 0.37.0 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/tutorial/sm-tutorial/SKILL.md +37 -7
- package/dist/cli.js +367 -256
- package/dist/cli.js.map +1 -1
- package/dist/conformance/index.d.ts +4 -4
- package/dist/conformance/index.js +48 -2
- package/dist/conformance/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +12 -12
- package/dist/index.js.map +1 -1
- package/dist/kernel/index.d.ts +25 -16
- package/dist/kernel/index.js +12 -12
- package/dist/kernel/index.js.map +1 -1
- package/dist/ui/chunk-47MG5XH2.js +317 -0
- package/dist/ui/{chunk-YZ7KCL3G.js → chunk-4CDTW64C.js} +1 -1
- package/dist/ui/chunk-4XEJUDPL.js +123 -0
- package/dist/ui/{chunk-2QZDJSJN.js → chunk-5AZ5S6JB.js} +1 -1
- package/dist/ui/{chunk-GX2V3PSZ.js → chunk-AAR3Y55J.js} +3 -3
- package/dist/ui/chunk-CR3AANNX.js +3 -0
- package/dist/ui/{chunk-UMCC32EJ.js → chunk-G5CKBDBB.js} +1 -1
- package/dist/ui/{chunk-5CFY2K3Y.js → chunk-KKOZFBXQ.js} +1 -1
- package/dist/ui/{chunk-UK5YFHL3.js → chunk-NTM2J2WO.js} +5 -5
- package/dist/ui/{chunk-LTQTJU54.js → chunk-O5N7UH37.js} +13 -13
- package/dist/ui/{chunk-S2NIJM7Z.js → chunk-QZM2G474.js} +2 -2
- package/dist/ui/chunk-Z4LANJFK.js +1 -0
- package/dist/ui/index.html +6 -9
- package/dist/ui/main-EO5QNLE4.js +2 -0
- package/package.json +2 -2
- package/dist/ui/chunk-5JBW2LUN.js +0 -2
- package/dist/ui/chunk-DGXHJVQN.js +0 -317
- package/dist/ui/chunk-O2N4CRRW.js +0 -123
- package/dist/ui/chunk-VFYNKTSB.js +0 -1
- package/dist/ui/main-YSELA4XD.js +0 -2
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// cli/entry.ts
|
|
2
|
-
import { existsSync as
|
|
2
|
+
import { existsSync as existsSync30 } from "fs";
|
|
3
3
|
import { Builtins, Cli as Cli2 } from "clipanion";
|
|
4
4
|
|
|
5
5
|
// kernel/adapters/in-memory-progress.ts
|
|
@@ -61,7 +61,7 @@ var DuplicateExtensionError = class extends Error {
|
|
|
61
61
|
}
|
|
62
62
|
};
|
|
63
63
|
var Registry = class {
|
|
64
|
-
/** kind → qualifiedId →
|
|
64
|
+
/** kind → qualifiedId → IExtension. */
|
|
65
65
|
#byKind;
|
|
66
66
|
constructor() {
|
|
67
67
|
this.#byKind = new Map(
|
|
@@ -429,10 +429,17 @@ var command_schema_default = {
|
|
|
429
429
|
properties: {}
|
|
430
430
|
};
|
|
431
431
|
|
|
432
|
+
// plugins/ids.ts
|
|
433
|
+
var CORE_PLUGIN_ID = "core";
|
|
434
|
+
var CLAUDE_PLUGIN_ID = "claude";
|
|
435
|
+
var OPENAI_PLUGIN_ID = "openai";
|
|
436
|
+
var ANTIGRAVITY_PLUGIN_ID = "antigravity";
|
|
437
|
+
var AGENT_SKILLS_PLUGIN_ID = "agent-skills";
|
|
438
|
+
|
|
432
439
|
// plugins/claude/providers/claude/index.ts
|
|
433
440
|
var claudeProvider = {
|
|
434
441
|
id: "claude",
|
|
435
|
-
pluginId:
|
|
442
|
+
pluginId: CLAUDE_PLUGIN_ID,
|
|
436
443
|
kind: "provider",
|
|
437
444
|
version: "1.0.0",
|
|
438
445
|
description: "Walks Claude Code scope conventions (.claude/{agents,commands,skills}).",
|
|
@@ -657,9 +664,9 @@ function stripFences(input) {
|
|
|
657
664
|
}
|
|
658
665
|
continue;
|
|
659
666
|
}
|
|
660
|
-
const
|
|
661
|
-
if (
|
|
662
|
-
openFence =
|
|
667
|
+
const open2 = FENCE_RE.exec(line);
|
|
668
|
+
if (open2?.groups) {
|
|
669
|
+
openFence = open2.groups["fence"];
|
|
663
670
|
out.push(blank(line));
|
|
664
671
|
continue;
|
|
665
672
|
}
|
|
@@ -717,7 +724,7 @@ var AT_RE = /(?:^|[^A-Za-z0-9_@])(@(?:\.{1,2}\/|\/)?[a-z0-9](?:[a-z0-9_\-./]*[a-
|
|
|
717
724
|
var FILE_EXT_RE = /\.(md|mdx|js|jsx|ts|tsx|json|yml|yaml|toml|txt|html|css|scss|less|py|rb|go|rs|java|c|cpp|h|hpp|sh|sql|svg|png|jpg|jpeg|gif|webp|pdf)$/i;
|
|
718
725
|
var atDirectiveExtractor = {
|
|
719
726
|
id: ID,
|
|
720
|
-
pluginId:
|
|
727
|
+
pluginId: CLAUDE_PLUGIN_ID,
|
|
721
728
|
kind: "extractor",
|
|
722
729
|
version: "1.0.0",
|
|
723
730
|
description: "Detects `@<token>` directives in a node's body using Claude Code interpretation rules. A bare handle (e.g. `@team`) becomes a `mentions` link; a file-flavoured token (e.g. `@docs/api.md`, `@./readme.md`) becomes a `references` link. Gated by `precondition.provider: ['claude']` so Antigravity / Cursor / Codex apply their own at-directive flavours via their own extractors.",
|
|
@@ -806,7 +813,7 @@ var ID2 = "slash";
|
|
|
806
813
|
var SLASH_RE = /(?<![A-Za-z0-9_/.:?#=&])(\/[a-z0-9][a-z0-9_-]*(?::[a-z0-9][a-z0-9_-]*)?)/gi;
|
|
807
814
|
var slashExtractor = {
|
|
808
815
|
id: ID2,
|
|
809
|
-
pluginId:
|
|
816
|
+
pluginId: CLAUDE_PLUGIN_ID,
|
|
810
817
|
kind: "extractor",
|
|
811
818
|
version: "1.0.0",
|
|
812
819
|
description: "Detects `/command` invocations in a node's body using Claude Code routing rules and turns each one into an arrow between nodes in the graph. Gated by `precondition.provider: ['claude']` so Antigravity / Cursor / Codex apply their own slash flavours (Antigravity ships subagent and skill panels, Codex deprecated user slash commands, etc.) via their own extractors.",
|
|
@@ -856,7 +863,7 @@ var slashExtractor = {
|
|
|
856
863
|
// plugins/antigravity/providers/antigravity/index.ts
|
|
857
864
|
var antigravityProvider = {
|
|
858
865
|
id: "antigravity",
|
|
859
|
-
pluginId:
|
|
866
|
+
pluginId: ANTIGRAVITY_PLUGIN_ID,
|
|
860
867
|
kind: "provider",
|
|
861
868
|
version: "1.0.0",
|
|
862
869
|
description: "Google Antigravity CLI. Replaces the retired Gemini CLI; skills route through the neutral `agent-skills` Provider via `.agents/skills/`. This Provider contributes lens identity and a reserved-name seed catalog.",
|
|
@@ -1005,7 +1012,7 @@ var agent_schema_default2 = {
|
|
|
1005
1012
|
// plugins/openai/providers/openai/index.ts
|
|
1006
1013
|
var openaiProvider = {
|
|
1007
1014
|
id: "openai",
|
|
1008
|
-
pluginId:
|
|
1015
|
+
pluginId: OPENAI_PLUGIN_ID,
|
|
1009
1016
|
kind: "provider",
|
|
1010
1017
|
version: "1.0.0",
|
|
1011
1018
|
description: "Walks OpenAI Codex CLI scope conventions (.codex/agents/*.toml).",
|
|
@@ -1063,7 +1070,7 @@ var skill_schema_default2 = {
|
|
|
1063
1070
|
// plugins/agent-skills/providers/agent-skills/index.ts
|
|
1064
1071
|
var agentSkillsProvider = {
|
|
1065
1072
|
id: "agent-skills",
|
|
1066
|
-
pluginId:
|
|
1073
|
+
pluginId: AGENT_SKILLS_PLUGIN_ID,
|
|
1067
1074
|
kind: "provider",
|
|
1068
1075
|
version: "1.0.0",
|
|
1069
1076
|
description: "Agent Skills open standard. Vendor-neutral path `.agents/skills/<name>/SKILL.md` (Anthropic, OpenAI, Google). See agentskills.io.",
|
|
@@ -1111,7 +1118,7 @@ var markdown_schema_default = {
|
|
|
1111
1118
|
// plugins/core/providers/core-markdown/index.ts
|
|
1112
1119
|
var coreMarkdownProvider = {
|
|
1113
1120
|
id: "markdown",
|
|
1114
|
-
pluginId:
|
|
1121
|
+
pluginId: CORE_PLUGIN_ID,
|
|
1115
1122
|
kind: "provider",
|
|
1116
1123
|
version: "1.0.0",
|
|
1117
1124
|
description: "Universal `.md` fallback. Claims any markdown file no vendor-specific Provider classifies.",
|
|
@@ -1162,7 +1169,7 @@ var coreMarkdownProvider = {
|
|
|
1162
1169
|
var ID3 = "annotations";
|
|
1163
1170
|
var annotationsExtractor = {
|
|
1164
1171
|
id: ID3,
|
|
1165
|
-
pluginId:
|
|
1172
|
+
pluginId: CORE_PLUGIN_ID,
|
|
1166
1173
|
kind: "extractor",
|
|
1167
1174
|
version: "1.0.0",
|
|
1168
1175
|
description: "Turns the `supersedes` and `supersededBy` entries you write in a node's `.sm` sidecar into the arrows (edges) shown between nodes in the graph.",
|
|
@@ -1224,7 +1231,7 @@ var URL_RE = /https?:\/\/[^\s<>"'`)\]]+/g;
|
|
|
1224
1231
|
var TRAILING_PUNCT = /[.,;:!?]+$/;
|
|
1225
1232
|
var externalUrlCounterExtractor = {
|
|
1226
1233
|
id: ID4,
|
|
1227
|
-
pluginId:
|
|
1234
|
+
pluginId: CORE_PLUGIN_ID,
|
|
1228
1235
|
kind: "extractor",
|
|
1229
1236
|
version: "1.0.0",
|
|
1230
1237
|
description: "Counts the distinct external URLs in a node's body and shows the total on the card.",
|
|
@@ -1313,7 +1320,7 @@ var LINK_RE = /(?<!!)\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g;
|
|
|
1313
1320
|
var URL_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;
|
|
1314
1321
|
var markdownLinkExtractor = {
|
|
1315
1322
|
id: ID5,
|
|
1316
|
-
pluginId:
|
|
1323
|
+
pluginId: CORE_PLUGIN_ID,
|
|
1317
1324
|
kind: "extractor",
|
|
1318
1325
|
version: "1.0.0",
|
|
1319
1326
|
description: "Detects markdown links (`[text](path)`) in a node's body and turns each one into an arrow between nodes in the graph.",
|
|
@@ -1375,7 +1382,7 @@ var ID6 = "mcp-tools";
|
|
|
1375
1382
|
var MCP_PATTERN = /^mcp__([a-z0-9][a-z0-9_-]*)__[a-z0-9_-]+$/i;
|
|
1376
1383
|
var mcpToolsExtractor = {
|
|
1377
1384
|
id: ID6,
|
|
1378
|
-
pluginId:
|
|
1385
|
+
pluginId: CORE_PLUGIN_ID,
|
|
1379
1386
|
kind: "extractor",
|
|
1380
1387
|
version: "1.0.0",
|
|
1381
1388
|
description: "Detects `tools: [mcp__<server>__<tool>]` entries in a node's frontmatter and turns each unique server into an MCP node + a reference edge from the source.",
|
|
@@ -1437,7 +1444,7 @@ var ID7 = "tools-count";
|
|
|
1437
1444
|
var TOOLTIP_MAX = 255;
|
|
1438
1445
|
var toolsCountExtractor = {
|
|
1439
1446
|
id: ID7,
|
|
1440
|
-
pluginId:
|
|
1447
|
+
pluginId: CORE_PLUGIN_ID,
|
|
1441
1448
|
kind: "extractor",
|
|
1442
1449
|
version: "1.0.0",
|
|
1443
1450
|
description: "Counts the tools an agent declares in its frontmatter and shows the total on the agent card.",
|
|
@@ -1482,7 +1489,7 @@ var ANNOTATION_ORPHAN_TEXTS = {
|
|
|
1482
1489
|
var ID8 = "annotation-orphan";
|
|
1483
1490
|
var annotationOrphanAnalyzer = {
|
|
1484
1491
|
id: ID8,
|
|
1485
|
-
pluginId:
|
|
1492
|
+
pluginId: CORE_PLUGIN_ID,
|
|
1486
1493
|
kind: "analyzer",
|
|
1487
1494
|
version: "1.0.0",
|
|
1488
1495
|
description: "Detects and flags sidecars (`.sm`) whose `.md` no longer exists.",
|
|
@@ -1534,7 +1541,7 @@ var ANNOTATION_STALE_TEXTS = {
|
|
|
1534
1541
|
var ID9 = "annotation-stale";
|
|
1535
1542
|
var annotationStaleAnalyzer = {
|
|
1536
1543
|
id: ID9,
|
|
1537
|
-
pluginId:
|
|
1544
|
+
pluginId: CORE_PLUGIN_ID,
|
|
1538
1545
|
kind: "analyzer",
|
|
1539
1546
|
version: "1.0.0",
|
|
1540
1547
|
description: "Detects and marks sidecars (`.sm`) out of date of their `.md`.",
|
|
@@ -1617,7 +1624,7 @@ var BROKEN_REF_TEXTS = {
|
|
|
1617
1624
|
var ID10 = "broken-ref";
|
|
1618
1625
|
var brokenRefAnalyzer = {
|
|
1619
1626
|
id: ID10,
|
|
1620
|
-
pluginId:
|
|
1627
|
+
pluginId: CORE_PLUGIN_ID,
|
|
1621
1628
|
kind: "analyzer",
|
|
1622
1629
|
version: "1.0.0",
|
|
1623
1630
|
description: "Detects and flags arrows pointing at a node not part of the current scan.",
|
|
@@ -1782,7 +1789,7 @@ function isPathStyleLink(link) {
|
|
|
1782
1789
|
var ID11 = "contribution-orphan";
|
|
1783
1790
|
var contributionOrphanAnalyzer = {
|
|
1784
1791
|
id: ID11,
|
|
1785
|
-
pluginId:
|
|
1792
|
+
pluginId: CORE_PLUGIN_ID,
|
|
1786
1793
|
kind: "analyzer",
|
|
1787
1794
|
version: "0.0.0",
|
|
1788
1795
|
description: "Detects and warns about plugin data referencing nodes renamed or deleted in the latest scan.",
|
|
@@ -1805,7 +1812,7 @@ var JOB_ORPHAN_FILE_TEXTS = {
|
|
|
1805
1812
|
var ID12 = "job-orphan-file";
|
|
1806
1813
|
var jobOrphanFileAnalyzer = {
|
|
1807
1814
|
id: ID12,
|
|
1808
|
-
pluginId:
|
|
1815
|
+
pluginId: CORE_PLUGIN_ID,
|
|
1809
1816
|
kind: "analyzer",
|
|
1810
1817
|
version: "1.0.0",
|
|
1811
1818
|
description: "Detects and flags leftover job result files (no live job references them). Cleanup via `sm job prune --orphan-files`.",
|
|
@@ -1954,7 +1961,7 @@ function resolveLinkTargetToPath(link, nameIndex) {
|
|
|
1954
1961
|
var ID14 = "link-counts";
|
|
1955
1962
|
var linkCountsAnalyzer = {
|
|
1956
1963
|
id: ID14,
|
|
1957
|
-
pluginId:
|
|
1964
|
+
pluginId: CORE_PLUGIN_ID,
|
|
1958
1965
|
kind: "analyzer",
|
|
1959
1966
|
version: "1.0.0",
|
|
1960
1967
|
description: "Counts incoming and outgoing links per node.",
|
|
@@ -2037,7 +2044,7 @@ var REDUNDANT_TARGET_REFERENCE_TEXTS = {
|
|
|
2037
2044
|
var ID15 = "redundant-target-reference";
|
|
2038
2045
|
var redundantTargetReferenceAnalyzer = {
|
|
2039
2046
|
id: ID15,
|
|
2040
|
-
pluginId:
|
|
2047
|
+
pluginId: CORE_PLUGIN_ID,
|
|
2041
2048
|
kind: "analyzer",
|
|
2042
2049
|
version: "1.0.0",
|
|
2043
2050
|
description: "Flags when one node references the same resolved target via two or more syntactic surfaces (cross-extractor multi-form OR cross-kind multi-edge). Emits a warn on the source listing every occurrence (kind + trigger + line). Helps consolidate authorial redundancy and avoid duplicate runtime inlining.",
|
|
@@ -2288,7 +2295,7 @@ var RESERVED_NAME_TEXTS = {
|
|
|
2288
2295
|
var ID16 = "reserved-name";
|
|
2289
2296
|
var reservedNameAnalyzer = {
|
|
2290
2297
|
id: ID16,
|
|
2291
|
-
pluginId:
|
|
2298
|
+
pluginId: CORE_PLUGIN_ID,
|
|
2292
2299
|
kind: "analyzer",
|
|
2293
2300
|
version: "1.0.0",
|
|
2294
2301
|
description: "Flags reserved-name collisions on two surfaces. Target side: a user file whose name collides with a Provider runtime's built-in invocable (the runtime shadows the file silently). Source side: a link that resolves to a reserved name, which the post-walk lift transform downgrades to the sentinel `RESERVED_TARGET_CONFIDENCE` (0.1). The two findings share the analyzer id so consumers can group by root cause; the source-side issue carries `data.target` matching the link so UIs can correlate per-row.",
|
|
@@ -2397,7 +2404,7 @@ var SELF_LOOP_TEXTS = {
|
|
|
2397
2404
|
var ID17 = "self-loop";
|
|
2398
2405
|
var selfLoopAnalyzer = {
|
|
2399
2406
|
id: ID17,
|
|
2400
|
-
pluginId:
|
|
2407
|
+
pluginId: CORE_PLUGIN_ID,
|
|
2401
2408
|
kind: "analyzer",
|
|
2402
2409
|
version: "1.0.0",
|
|
2403
2410
|
description: "Flags links whose source is its own resolved target (a body heading like `# /deploy` inside the file that defines `/deploy`). One warn per self-looping link, attached to the source. UI consumers hide self-loops by default; this analyzer is the authoritative detector.",
|
|
@@ -2474,7 +2481,7 @@ var SIGNAL_COLLISION_TEXTS = {
|
|
|
2474
2481
|
var ID18 = "signal-collision";
|
|
2475
2482
|
var signalCollisionAnalyzer = {
|
|
2476
2483
|
id: ID18,
|
|
2477
|
-
pluginId:
|
|
2484
|
+
pluginId: CORE_PLUGIN_ID,
|
|
2478
2485
|
kind: "analyzer",
|
|
2479
2486
|
version: "1.0.0",
|
|
2480
2487
|
description: "Surfaces Signal IR resolver rejections (range-overlap losers, disabled extractors, below-floor candidates) as warn issues attached to the Signal's source node.",
|
|
@@ -2576,7 +2583,7 @@ var EXPERIMENTAL_TOOLTIP = "Experimental: API may change";
|
|
|
2576
2583
|
var DEPRECATED_TOOLTIP = "Deprecated: avoid in new code";
|
|
2577
2584
|
var stabilityAnalyzer = {
|
|
2578
2585
|
id: ID19,
|
|
2579
|
-
pluginId:
|
|
2586
|
+
pluginId: CORE_PLUGIN_ID,
|
|
2580
2587
|
kind: "analyzer",
|
|
2581
2588
|
version: "1.0.0",
|
|
2582
2589
|
description: "Reports node lifecycle stage (`experimental`, `deprecated`) on the card.",
|
|
@@ -2657,7 +2664,7 @@ var SUPERSEDED_TEXTS = {
|
|
|
2657
2664
|
var ID20 = "superseded";
|
|
2658
2665
|
var supersededAnalyzer = {
|
|
2659
2666
|
id: ID20,
|
|
2660
|
-
pluginId:
|
|
2667
|
+
pluginId: CORE_PLUGIN_ID,
|
|
2661
2668
|
kind: "analyzer",
|
|
2662
2669
|
version: "1.0.0",
|
|
2663
2670
|
description: "Detects and marks nodes replaced by a newer one via `supersededBy`.",
|
|
@@ -2725,7 +2732,7 @@ var ADVERTISING_KINDS = /* @__PURE__ */ new Set([
|
|
|
2725
2732
|
]);
|
|
2726
2733
|
var triggerCollisionAnalyzer = {
|
|
2727
2734
|
id: ID21,
|
|
2728
|
-
pluginId:
|
|
2735
|
+
pluginId: CORE_PLUGIN_ID,
|
|
2729
2736
|
kind: "analyzer",
|
|
2730
2737
|
mode: "deterministic",
|
|
2731
2738
|
version: "1.0.0",
|
|
@@ -2867,7 +2874,7 @@ var ID22 = "unknown-field";
|
|
|
2867
2874
|
var RESERVED_ROOT_BLOCKS = /* @__PURE__ */ new Set(["identity", "annotations", "settings", "audit"]);
|
|
2868
2875
|
var unknownFieldAnalyzer = {
|
|
2869
2876
|
id: ID22,
|
|
2870
|
-
pluginId:
|
|
2877
|
+
pluginId: CORE_PLUGIN_ID,
|
|
2871
2878
|
kind: "analyzer",
|
|
2872
2879
|
version: "1.0.0",
|
|
2873
2880
|
description: "Detects and flags typos or unrecognized keys in sidecars (`.sm`).",
|
|
@@ -3263,7 +3270,7 @@ var VALIDATE_ALL_TEXTS = {
|
|
|
3263
3270
|
var ID23 = "validate-all";
|
|
3264
3271
|
var validateAllAnalyzer = {
|
|
3265
3272
|
id: ID23,
|
|
3266
|
-
pluginId:
|
|
3273
|
+
pluginId: CORE_PLUGIN_ID,
|
|
3267
3274
|
kind: "analyzer",
|
|
3268
3275
|
version: "1.0.0",
|
|
3269
3276
|
description: "Detects and flags nodes or links violating the project schemas.",
|
|
@@ -3438,7 +3445,7 @@ var ID24 = "ascii";
|
|
|
3438
3445
|
var KIND_ORDER = ["agent", "command", "skill", "markdown"];
|
|
3439
3446
|
var asciiFormatter = {
|
|
3440
3447
|
id: ID24,
|
|
3441
|
-
pluginId:
|
|
3448
|
+
pluginId: CORE_PLUGIN_ID,
|
|
3442
3449
|
kind: "formatter",
|
|
3443
3450
|
formatId: ID24,
|
|
3444
3451
|
version: "1.0.0",
|
|
@@ -3538,7 +3545,7 @@ function renderSection(out, kind, group) {
|
|
|
3538
3545
|
var ID25 = "json";
|
|
3539
3546
|
var jsonFormatter = {
|
|
3540
3547
|
id: ID25,
|
|
3541
|
-
pluginId:
|
|
3548
|
+
pluginId: CORE_PLUGIN_ID,
|
|
3542
3549
|
kind: "formatter",
|
|
3543
3550
|
version: "1.0.0",
|
|
3544
3551
|
description: "Renders the persisted scan as JSON (conforms to `scan-result.schema.json` when the full ScanResult is available). Used by `sm graph --format json` and `GET /api/graph?format=json`.",
|
|
@@ -3682,10 +3689,9 @@ function resolveSpecRoot2() {
|
|
|
3682
3689
|
|
|
3683
3690
|
// plugins/core/actions/bump/index.ts
|
|
3684
3691
|
var ID26 = "bump";
|
|
3685
|
-
var PLUGIN_ID = "core";
|
|
3686
3692
|
var bumpAction = {
|
|
3687
3693
|
id: ID26,
|
|
3688
|
-
pluginId:
|
|
3694
|
+
pluginId: CORE_PLUGIN_ID,
|
|
3689
3695
|
kind: "action",
|
|
3690
3696
|
version: "1.0.0",
|
|
3691
3697
|
description: "Marks a node as updated: bumps version, refreshes sidecar hashes, records the timestamp.",
|
|
@@ -3744,10 +3750,9 @@ function pickCurrentVersion(overlay) {
|
|
|
3744
3750
|
|
|
3745
3751
|
// plugins/core/actions/mark-superseded/index.ts
|
|
3746
3752
|
var ID27 = "mark-superseded";
|
|
3747
|
-
var PLUGIN_ID2 = "core";
|
|
3748
3753
|
var markSupersededAction = {
|
|
3749
3754
|
id: ID27,
|
|
3750
|
-
pluginId:
|
|
3755
|
+
pluginId: CORE_PLUGIN_ID,
|
|
3751
3756
|
kind: "action",
|
|
3752
3757
|
version: "0.0.0",
|
|
3753
3758
|
description: "Declares the current node as superseded by another (writes `supersededBy` to the sidecar). Paired with the `core/superseded` analyzer.",
|
|
@@ -3856,7 +3861,7 @@ var UPDATE_CHECK_TEXTS = {
|
|
|
3856
3861
|
// package.json
|
|
3857
3862
|
var package_default = {
|
|
3858
3863
|
name: "@skill-map/cli",
|
|
3859
|
-
version: "0.
|
|
3864
|
+
version: "0.38.0",
|
|
3860
3865
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
3861
3866
|
license: "MIT",
|
|
3862
3867
|
type: "module",
|
|
@@ -3939,7 +3944,7 @@ var package_default = {
|
|
|
3939
3944
|
semver: "7.7.4",
|
|
3940
3945
|
"smol-toml": "1.6.1",
|
|
3941
3946
|
typanion: "3.14.0",
|
|
3942
|
-
ws: "8.
|
|
3947
|
+
ws: "8.21.0"
|
|
3943
3948
|
},
|
|
3944
3949
|
devDependencies: {
|
|
3945
3950
|
"@eslint/js": "10.0.1",
|
|
@@ -4006,10 +4011,67 @@ function ansiFor(opts) {
|
|
|
4006
4011
|
}
|
|
4007
4012
|
|
|
4008
4013
|
// cli/util/user-settings-store.ts
|
|
4009
|
-
import { existsSync as
|
|
4014
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync5 } from "fs";
|
|
4010
4015
|
import { homedir } from "os";
|
|
4011
4016
|
import { join as join2 } from "path";
|
|
4012
4017
|
|
|
4018
|
+
// core/config/atomic-write.ts
|
|
4019
|
+
import {
|
|
4020
|
+
closeSync,
|
|
4021
|
+
constants as fsConstants,
|
|
4022
|
+
existsSync as existsSync2,
|
|
4023
|
+
mkdirSync,
|
|
4024
|
+
openSync,
|
|
4025
|
+
readFileSync as readFileSync4,
|
|
4026
|
+
renameSync,
|
|
4027
|
+
unlinkSync,
|
|
4028
|
+
writeSync
|
|
4029
|
+
} from "fs";
|
|
4030
|
+
import { randomBytes } from "crypto";
|
|
4031
|
+
import { dirname as dirname4 } from "path";
|
|
4032
|
+
function readJsonObjectOrEmpty(path) {
|
|
4033
|
+
if (!existsSync2(path)) return {};
|
|
4034
|
+
try {
|
|
4035
|
+
const raw = JSON.parse(readFileSync4(path, "utf8"));
|
|
4036
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
4037
|
+
return raw;
|
|
4038
|
+
}
|
|
4039
|
+
} catch {
|
|
4040
|
+
}
|
|
4041
|
+
return {};
|
|
4042
|
+
}
|
|
4043
|
+
function writeFileAtomicExclusive(path, content, mode = 384) {
|
|
4044
|
+
const tmp = `${path}.tmp.${process.pid}.${randomBytes(8).toString("hex")}`;
|
|
4045
|
+
let fd = null;
|
|
4046
|
+
try {
|
|
4047
|
+
fd = openSync(
|
|
4048
|
+
tmp,
|
|
4049
|
+
fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | fsConstants.O_NOFOLLOW,
|
|
4050
|
+
mode
|
|
4051
|
+
);
|
|
4052
|
+
writeSync(fd, content);
|
|
4053
|
+
closeSync(fd);
|
|
4054
|
+
fd = null;
|
|
4055
|
+
renameSync(tmp, path);
|
|
4056
|
+
} catch (err) {
|
|
4057
|
+
if (fd !== null) {
|
|
4058
|
+
try {
|
|
4059
|
+
closeSync(fd);
|
|
4060
|
+
} catch {
|
|
4061
|
+
}
|
|
4062
|
+
}
|
|
4063
|
+
try {
|
|
4064
|
+
unlinkSync(tmp);
|
|
4065
|
+
} catch {
|
|
4066
|
+
}
|
|
4067
|
+
throw err;
|
|
4068
|
+
}
|
|
4069
|
+
}
|
|
4070
|
+
function writeJsonAtomic(path, content) {
|
|
4071
|
+
mkdirSync(dirname4(path), { recursive: true });
|
|
4072
|
+
writeFileAtomicExclusive(path, JSON.stringify(content, null, 2) + "\n");
|
|
4073
|
+
}
|
|
4074
|
+
|
|
4013
4075
|
// core/paths/db-path.ts
|
|
4014
4076
|
import { join, resolve as resolve6 } from "path";
|
|
4015
4077
|
var SKILL_MAP_DIR = ".skill-map";
|
|
@@ -4067,9 +4129,9 @@ function readUserSettings() {
|
|
|
4067
4129
|
}
|
|
4068
4130
|
function readParsedFile() {
|
|
4069
4131
|
const path = userSettingsFilePath();
|
|
4070
|
-
if (!
|
|
4132
|
+
if (!existsSync3(path)) return null;
|
|
4071
4133
|
try {
|
|
4072
|
-
const parsed = JSON.parse(
|
|
4134
|
+
const parsed = JSON.parse(readFileSync5(path, "utf8"));
|
|
4073
4135
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
4074
4136
|
return null;
|
|
4075
4137
|
}
|
|
@@ -4102,8 +4164,8 @@ function writeUserSettings(patch) {
|
|
|
4102
4164
|
const result = validators.validate("user-settings", merged);
|
|
4103
4165
|
if (!result.ok) return;
|
|
4104
4166
|
}
|
|
4105
|
-
|
|
4106
|
-
|
|
4167
|
+
mkdirSync2(dir, { recursive: true, mode: 448 });
|
|
4168
|
+
writeFileAtomicExclusive(path, JSON.stringify(merged, null, 2) + "\n");
|
|
4107
4169
|
} catch {
|
|
4108
4170
|
}
|
|
4109
4171
|
}
|
|
@@ -4214,7 +4276,7 @@ ${footer}
|
|
|
4214
4276
|
// plugins/core/hooks/update-check/index.ts
|
|
4215
4277
|
var updateCheckHook = {
|
|
4216
4278
|
id: "update-check",
|
|
4217
|
-
pluginId:
|
|
4279
|
+
pluginId: CORE_PLUGIN_ID,
|
|
4218
4280
|
kind: "hook",
|
|
4219
4281
|
version: "1.0.0",
|
|
4220
4282
|
description: "Checks daily for a newer skill-map version on npm. Shows an `update available` banner when one is found.",
|
|
@@ -4546,7 +4608,7 @@ function extractLogLevelFlag(argv) {
|
|
|
4546
4608
|
var LOGGER_ENV_VAR = ENV_VAR;
|
|
4547
4609
|
|
|
4548
4610
|
// cli/util/db-path.ts
|
|
4549
|
-
import { existsSync as
|
|
4611
|
+
import { existsSync as existsSync4 } from "fs";
|
|
4550
4612
|
|
|
4551
4613
|
// cli/i18n/util.texts.ts
|
|
4552
4614
|
var UTIL_TEXTS = {
|
|
@@ -4589,7 +4651,7 @@ var ExitCode = {
|
|
|
4589
4651
|
|
|
4590
4652
|
// cli/util/db-path.ts
|
|
4591
4653
|
function assertDbExists(path, stderr) {
|
|
4592
|
-
if (path === ":memory:" ||
|
|
4654
|
+
if (path === ":memory:" || existsSync4(path)) return true;
|
|
4593
4655
|
const stderrTty = stderr;
|
|
4594
4656
|
const ansi = ansiFor({ isTTY: stderrTty.isTTY === true, noColorFlag: false });
|
|
4595
4657
|
stderr.write(
|
|
@@ -4784,10 +4846,10 @@ import { Command as Command2, Option as Option2 } from "clipanion";
|
|
|
4784
4846
|
|
|
4785
4847
|
// core/config/helper.ts
|
|
4786
4848
|
import { homedir as osHomedir } from "os";
|
|
4787
|
-
import { isAbsolute, join as join4, resolve as resolve7 } from "path";
|
|
4849
|
+
import { isAbsolute, join as join4, resolve as resolve7, sep } from "path";
|
|
4788
4850
|
|
|
4789
4851
|
// kernel/config/loader.ts
|
|
4790
|
-
import { existsSync as
|
|
4852
|
+
import { existsSync as existsSync5, readFileSync as readFileSync6 } from "fs";
|
|
4791
4853
|
|
|
4792
4854
|
// kernel/i18n/config-loader.texts.ts
|
|
4793
4855
|
var CONFIG_LOADER_TEXTS = {
|
|
@@ -4869,7 +4931,7 @@ function loadConfig(opts) {
|
|
|
4869
4931
|
{ path: kernelLocalSettingsPath(cwd), layer: "project-local" }
|
|
4870
4932
|
];
|
|
4871
4933
|
for (const { path, layer } of filePairs) {
|
|
4872
|
-
if (!
|
|
4934
|
+
if (!existsSync5(path)) continue;
|
|
4873
4935
|
const partial = readJsonSafe(path, layer, warnings, strict);
|
|
4874
4936
|
if (partial === null) continue;
|
|
4875
4937
|
const cleaned = validateAndStrip(validators, partial, layer, warnings, strict);
|
|
@@ -4890,7 +4952,7 @@ function loadConfig(opts) {
|
|
|
4890
4952
|
function readJsonSafe(path, layer, warnings, strict) {
|
|
4891
4953
|
let text;
|
|
4892
4954
|
try {
|
|
4893
|
-
text =
|
|
4955
|
+
text = readFileSync6(path, "utf8");
|
|
4894
4956
|
} catch (err) {
|
|
4895
4957
|
return reportAndSkip(
|
|
4896
4958
|
tx(CONFIG_LOADER_TEXTS.readFailure, { layer, path, message: formatErrorMessage(err) }),
|
|
@@ -5132,63 +5194,6 @@ function enumerateConfigPaths(obj, prefix = "") {
|
|
|
5132
5194
|
return out;
|
|
5133
5195
|
}
|
|
5134
5196
|
|
|
5135
|
-
// core/config/atomic-write.ts
|
|
5136
|
-
import {
|
|
5137
|
-
closeSync,
|
|
5138
|
-
constants as fsConstants,
|
|
5139
|
-
existsSync as existsSync5,
|
|
5140
|
-
mkdirSync as mkdirSync2,
|
|
5141
|
-
openSync,
|
|
5142
|
-
readFileSync as readFileSync6,
|
|
5143
|
-
renameSync,
|
|
5144
|
-
unlinkSync,
|
|
5145
|
-
writeSync
|
|
5146
|
-
} from "fs";
|
|
5147
|
-
import { randomBytes } from "crypto";
|
|
5148
|
-
import { dirname as dirname4 } from "path";
|
|
5149
|
-
function readJsonObjectOrEmpty(path) {
|
|
5150
|
-
if (!existsSync5(path)) return {};
|
|
5151
|
-
try {
|
|
5152
|
-
const raw = JSON.parse(readFileSync6(path, "utf8"));
|
|
5153
|
-
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
5154
|
-
return raw;
|
|
5155
|
-
}
|
|
5156
|
-
} catch {
|
|
5157
|
-
}
|
|
5158
|
-
return {};
|
|
5159
|
-
}
|
|
5160
|
-
function writeFileAtomicExclusive(path, content, mode = 384) {
|
|
5161
|
-
const tmp = `${path}.tmp.${process.pid}.${randomBytes(8).toString("hex")}`;
|
|
5162
|
-
let fd = null;
|
|
5163
|
-
try {
|
|
5164
|
-
fd = openSync(
|
|
5165
|
-
tmp,
|
|
5166
|
-
fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | fsConstants.O_NOFOLLOW,
|
|
5167
|
-
mode
|
|
5168
|
-
);
|
|
5169
|
-
writeSync(fd, content);
|
|
5170
|
-
closeSync(fd);
|
|
5171
|
-
fd = null;
|
|
5172
|
-
renameSync(tmp, path);
|
|
5173
|
-
} catch (err) {
|
|
5174
|
-
if (fd !== null) {
|
|
5175
|
-
try {
|
|
5176
|
-
closeSync(fd);
|
|
5177
|
-
} catch {
|
|
5178
|
-
}
|
|
5179
|
-
}
|
|
5180
|
-
try {
|
|
5181
|
-
unlinkSync(tmp);
|
|
5182
|
-
} catch {
|
|
5183
|
-
}
|
|
5184
|
-
throw err;
|
|
5185
|
-
}
|
|
5186
|
-
}
|
|
5187
|
-
function writeJsonAtomic(path, content) {
|
|
5188
|
-
mkdirSync2(dirname4(path), { recursive: true });
|
|
5189
|
-
writeFileAtomicExclusive(path, JSON.stringify(content, null, 2) + "\n");
|
|
5190
|
-
}
|
|
5191
|
-
|
|
5192
5197
|
// core/config/helper.ts
|
|
5193
5198
|
var PRIVACY_SENSITIVE_KEYS = /* @__PURE__ */ new Set([
|
|
5194
5199
|
"scan.referencePaths"
|
|
@@ -5282,7 +5287,7 @@ function resolveScanPathForExposure(raw, cwd) {
|
|
|
5282
5287
|
}
|
|
5283
5288
|
function isUnderProject(absPath, cwd) {
|
|
5284
5289
|
const projectRoot = resolve7(cwd);
|
|
5285
|
-
return absPath === projectRoot || absPath.startsWith(`${projectRoot}
|
|
5290
|
+
return absPath === projectRoot || absPath.startsWith(`${projectRoot}${sep}`);
|
|
5286
5291
|
}
|
|
5287
5292
|
|
|
5288
5293
|
// core/config/sidecar-consent.ts
|
|
@@ -5674,7 +5679,11 @@ var SmCommand = class extends Command {
|
|
|
5674
5679
|
this.printer = createPrinter({
|
|
5675
5680
|
stdout: this.context.stdout,
|
|
5676
5681
|
stderr: this.context.stderr,
|
|
5677
|
-
|
|
5682
|
+
// `--json` suppresses info banners even on stderr: users piping
|
|
5683
|
+
// JSON through `jq` (or asserting machine output in tests) don't
|
|
5684
|
+
// want decorative lines polluting either channel. Aligns CLI
|
|
5685
|
+
// behaviour with the printer docstring.
|
|
5686
|
+
quietInfo: this.quiet || this.json
|
|
5678
5687
|
});
|
|
5679
5688
|
try {
|
|
5680
5689
|
return await this.run();
|
|
@@ -7237,9 +7246,9 @@ async function sweepPerTupleContributions(trx, contributions, freshlyRunTuples)
|
|
|
7237
7246
|
const bufferKeys = buildContributionsBufferKeys(contributions);
|
|
7238
7247
|
const tuplesByPluginExt = groupFreshlyRunTuplesByPluginExt(freshlyRunTuples);
|
|
7239
7248
|
for (const [pe, nodes] of tuplesByPluginExt) {
|
|
7240
|
-
const
|
|
7241
|
-
if (
|
|
7242
|
-
await deleteStaleTupleRows(trx, pe.slice(0,
|
|
7249
|
+
const sep7 = pe.indexOf("\0");
|
|
7250
|
+
if (sep7 < 0) continue;
|
|
7251
|
+
await deleteStaleTupleRows(trx, pe.slice(0, sep7), pe.slice(sep7 + 1), [...nodes], bufferKeys);
|
|
7243
7252
|
}
|
|
7244
7253
|
}
|
|
7245
7254
|
function buildContributionsBufferKeys(contributions) {
|
|
@@ -8018,8 +8027,24 @@ function applyIssueFilters(query, filter) {
|
|
|
8018
8027
|
)
|
|
8019
8028
|
);
|
|
8020
8029
|
}
|
|
8030
|
+
if (filter.nodePaths !== void 0) {
|
|
8031
|
+
q = applyNodePathsFilter(q, filter.nodePaths);
|
|
8032
|
+
}
|
|
8021
8033
|
return q;
|
|
8022
8034
|
}
|
|
8035
|
+
function applyNodePathsFilter(query, nodePaths) {
|
|
8036
|
+
if (nodePaths.length === 0) {
|
|
8037
|
+
return query.where(sql3`0`, "=", 1);
|
|
8038
|
+
}
|
|
8039
|
+
const targets = [...nodePaths];
|
|
8040
|
+
return query.where(
|
|
8041
|
+
({ exists, selectFrom }) => exists(
|
|
8042
|
+
selectFrom(
|
|
8043
|
+
sql3`json_each(scan_issues.node_ids_json)`.as("je")
|
|
8044
|
+
).select(sql3`1`.as("one")).where(sql3.ref("je.value"), "in", targets)
|
|
8045
|
+
)
|
|
8046
|
+
);
|
|
8047
|
+
}
|
|
8023
8048
|
async function findActiveIssues(db, predicate) {
|
|
8024
8049
|
const rows = await db.selectFrom("scan_issues").selectAll().execute();
|
|
8025
8050
|
const out = [];
|
|
@@ -8308,15 +8333,32 @@ async function tryWithSqlite(options, fn) {
|
|
|
8308
8333
|
import { resolve as resolve14 } from "path";
|
|
8309
8334
|
|
|
8310
8335
|
// core/paths/path-guard.ts
|
|
8311
|
-
import {
|
|
8336
|
+
import { lstatSync } from "fs";
|
|
8337
|
+
import { isAbsolute as isAbsolute2, resolve as resolve13, sep as sep2 } from "path";
|
|
8312
8338
|
function assertContained(cwd, rel) {
|
|
8313
8339
|
if (isAbsolute2(rel)) {
|
|
8314
8340
|
throw new Error(`node path is absolute, refusing to read: ${rel}`);
|
|
8315
8341
|
}
|
|
8316
8342
|
const abs = resolve13(cwd, rel);
|
|
8317
|
-
if (abs !== cwd && !abs.startsWith(cwd +
|
|
8343
|
+
if (abs !== cwd && !abs.startsWith(cwd + sep2)) {
|
|
8318
8344
|
throw new Error(`node path escapes repo root: ${rel}`);
|
|
8319
8345
|
}
|
|
8346
|
+
let isSymlink;
|
|
8347
|
+
try {
|
|
8348
|
+
isSymlink = lstatSync(abs).isSymbolicLink();
|
|
8349
|
+
} catch (err) {
|
|
8350
|
+
if (isAllowedLstatError(err)) return;
|
|
8351
|
+
throw err;
|
|
8352
|
+
}
|
|
8353
|
+
if (isSymlink) {
|
|
8354
|
+
throw new Error(`node path is a symlink, refusing to dereference: ${rel}`);
|
|
8355
|
+
}
|
|
8356
|
+
}
|
|
8357
|
+
var ALLOWED_LSTAT_ERROR_CODES = /* @__PURE__ */ new Set(["ENOENT", "ENOTDIR"]);
|
|
8358
|
+
function isAllowedLstatError(err) {
|
|
8359
|
+
if (err === null || typeof err !== "object") return false;
|
|
8360
|
+
const code = err.code;
|
|
8361
|
+
return typeof code === "string" && ALLOWED_LSTAT_ERROR_CODES.has(code);
|
|
8320
8362
|
}
|
|
8321
8363
|
|
|
8322
8364
|
// cli/commands/bump-plan.ts
|
|
@@ -9259,9 +9301,9 @@ function providerKindFailure(opts, status, fileName, errDescription) {
|
|
|
9259
9301
|
}
|
|
9260
9302
|
};
|
|
9261
9303
|
}
|
|
9262
|
-
function isDirectorySafe(path,
|
|
9304
|
+
function isDirectorySafe(path, statSync12) {
|
|
9263
9305
|
try {
|
|
9264
|
-
return
|
|
9306
|
+
return statSync12(path).isDirectory();
|
|
9265
9307
|
} catch {
|
|
9266
9308
|
return false;
|
|
9267
9309
|
}
|
|
@@ -9855,7 +9897,7 @@ async function buildEnabledResolver(ctx) {
|
|
|
9855
9897
|
|
|
9856
9898
|
// kernel/scan/walk-content.ts
|
|
9857
9899
|
import { readFile, readdir, lstat } from "fs/promises";
|
|
9858
|
-
import { join as join9, relative as relative2, sep as
|
|
9900
|
+
import { join as join9, relative as relative2, sep as sep3 } from "path";
|
|
9859
9901
|
|
|
9860
9902
|
// kernel/scan/ignore.ts
|
|
9861
9903
|
import { existsSync as existsSync13, readFileSync as readFileSync13 } from "fs";
|
|
@@ -10036,7 +10078,7 @@ async function* walkContent(roots, options) {
|
|
|
10036
10078
|
const extensions = options.extensions;
|
|
10037
10079
|
for (const root of roots) {
|
|
10038
10080
|
for await (const file of walkRoot(root, root, filter, extensions)) {
|
|
10039
|
-
const relPath = relative2(root, file).split(
|
|
10081
|
+
const relPath = relative2(root, file).split(sep3).join("/");
|
|
10040
10082
|
let raw;
|
|
10041
10083
|
try {
|
|
10042
10084
|
raw = await readFile(file, "utf8");
|
|
@@ -10068,7 +10110,7 @@ async function* walkRoot(root, current, filter, extensions) {
|
|
|
10068
10110
|
for (const entry of entries) {
|
|
10069
10111
|
const name = entry.name;
|
|
10070
10112
|
const full = join9(current, name);
|
|
10071
|
-
const rel = relative2(root, full).split(
|
|
10113
|
+
const rel = relative2(root, full).split(sep3).join("/");
|
|
10072
10114
|
if (filter.ignores(rel)) continue;
|
|
10073
10115
|
if (entry.isSymbolicLink()) continue;
|
|
10074
10116
|
if (entry.isDirectory()) {
|
|
@@ -11489,6 +11531,52 @@ function disableEnv(setup) {
|
|
|
11489
11531
|
if (setup?.disableAllAnalyzers) env["SKILL_MAP_DISABLE_ALL_ANALYZERS"] = "1";
|
|
11490
11532
|
return env;
|
|
11491
11533
|
}
|
|
11534
|
+
var SAFE_CONFORMANCE_ENV_KEYS = [
|
|
11535
|
+
"PATH",
|
|
11536
|
+
"HOME",
|
|
11537
|
+
"USERPROFILE",
|
|
11538
|
+
"TMPDIR",
|
|
11539
|
+
"TMP",
|
|
11540
|
+
"TEMP",
|
|
11541
|
+
"SystemRoot",
|
|
11542
|
+
"SystemDrive",
|
|
11543
|
+
"OS",
|
|
11544
|
+
"COMSPEC",
|
|
11545
|
+
"PATHEXT",
|
|
11546
|
+
"NODE_OPTIONS",
|
|
11547
|
+
"NODE_PATH",
|
|
11548
|
+
"NODE_NO_WARNINGS",
|
|
11549
|
+
"NODE_DEBUG",
|
|
11550
|
+
"LANG",
|
|
11551
|
+
"TERM",
|
|
11552
|
+
"COLORTERM",
|
|
11553
|
+
"NO_COLOR",
|
|
11554
|
+
"FORCE_COLOR",
|
|
11555
|
+
"CI"
|
|
11556
|
+
];
|
|
11557
|
+
var SAFE_CONFORMANCE_ENV_PREFIXES = [
|
|
11558
|
+
"LC_",
|
|
11559
|
+
"SKILL_MAP_",
|
|
11560
|
+
"SM_"
|
|
11561
|
+
];
|
|
11562
|
+
function pickSafeEnv(source) {
|
|
11563
|
+
const out = {};
|
|
11564
|
+
for (const key of SAFE_CONFORMANCE_ENV_KEYS) {
|
|
11565
|
+
const value = source[key];
|
|
11566
|
+
if (value !== void 0) out[key] = value;
|
|
11567
|
+
}
|
|
11568
|
+
for (const key of Object.keys(source)) {
|
|
11569
|
+
if (out[key] !== void 0) continue;
|
|
11570
|
+
for (const prefix of SAFE_CONFORMANCE_ENV_PREFIXES) {
|
|
11571
|
+
if (key.startsWith(prefix)) {
|
|
11572
|
+
const value = source[key];
|
|
11573
|
+
if (value !== void 0) out[key] = value;
|
|
11574
|
+
break;
|
|
11575
|
+
}
|
|
11576
|
+
}
|
|
11577
|
+
}
|
|
11578
|
+
return out;
|
|
11579
|
+
}
|
|
11492
11580
|
function runConformanceCase(options) {
|
|
11493
11581
|
const raw = readFileSync14(options.casePath, "utf8");
|
|
11494
11582
|
const c = JSON.parse(raw);
|
|
@@ -11508,7 +11596,7 @@ function runConformanceCase(options) {
|
|
|
11508
11596
|
if (c.invoke.flags) argv.push(...c.invoke.flags);
|
|
11509
11597
|
const child = spawnSync2(process.execPath, [options.binary, ...argv], {
|
|
11510
11598
|
cwd: scope,
|
|
11511
|
-
env: { ...process.env, ...options.env, ...setupEnv },
|
|
11599
|
+
env: { ...pickSafeEnv(process.env), ...options.env, ...setupEnv },
|
|
11512
11600
|
encoding: "utf8"
|
|
11513
11601
|
});
|
|
11514
11602
|
const stdout = child.stdout ?? "";
|
|
@@ -11536,7 +11624,7 @@ function runPriorScansSetup(c, options, scope, fixturesRoot, setupEnv) {
|
|
|
11536
11624
|
const stepArgv = ["scan", ...step.flags ?? []];
|
|
11537
11625
|
const stepChild = spawnSync2(process.execPath, [options.binary, ...stepArgv], {
|
|
11538
11626
|
cwd: scope,
|
|
11539
|
-
env: { ...process.env, ...options.env, ...setupEnv },
|
|
11627
|
+
env: { ...pickSafeEnv(process.env), ...options.env, ...setupEnv },
|
|
11540
11628
|
encoding: "utf8"
|
|
11541
11629
|
});
|
|
11542
11630
|
if ((stepChild.status ?? 0) !== 0) {
|
|
@@ -14035,14 +14123,7 @@ function registeredVerbPaths(cli2) {
|
|
|
14035
14123
|
}
|
|
14036
14124
|
|
|
14037
14125
|
// cli/commands/hooks.ts
|
|
14038
|
-
import {
|
|
14039
|
-
chmodSync,
|
|
14040
|
-
existsSync as existsSync19,
|
|
14041
|
-
mkdirSync as mkdirSync5,
|
|
14042
|
-
readFileSync as readFileSync17,
|
|
14043
|
-
statSync as statSync5,
|
|
14044
|
-
writeFileSync as writeFileSync2
|
|
14045
|
-
} from "fs";
|
|
14126
|
+
import { chmod as chmod2, mkdir as mkdir3, readFile as readFile2, stat as stat2, writeFile } from "fs/promises";
|
|
14046
14127
|
import { dirname as dirname16, resolve as resolve27 } from "path";
|
|
14047
14128
|
import { Command as Command16, Option as Option15 } from "clipanion";
|
|
14048
14129
|
|
|
@@ -14136,7 +14217,7 @@ var HooksInstallCommand = class extends SmCommand {
|
|
|
14136
14217
|
return ExitCode.Error;
|
|
14137
14218
|
}
|
|
14138
14219
|
const ctx = defaultRuntimeContext();
|
|
14139
|
-
const repoRoot = findGitRepoRoot(ctx.cwd);
|
|
14220
|
+
const repoRoot = await findGitRepoRoot(ctx.cwd);
|
|
14140
14221
|
if (repoRoot === null) {
|
|
14141
14222
|
this.printer.error(
|
|
14142
14223
|
tx(HOOKS_TEXTS.notInGitRepo, {
|
|
@@ -14148,7 +14229,7 @@ var HooksInstallCommand = class extends SmCommand {
|
|
|
14148
14229
|
}
|
|
14149
14230
|
const hooksDir = resolve27(repoRoot, ".git", "hooks");
|
|
14150
14231
|
const hookPath = resolve27(hooksDir, "pre-commit");
|
|
14151
|
-
const existing =
|
|
14232
|
+
const existing = await pathExists(hookPath) ? await readFile2(hookPath, "utf8") : null;
|
|
14152
14233
|
const planned2 = computePlannedHookContent(existing);
|
|
14153
14234
|
if (planned2.kind === "already-installed") {
|
|
14154
14235
|
this.printer.info(tx(HOOKS_TEXTS.alreadyInstalled, { glyph: okGlyph, hookPath }));
|
|
@@ -14174,9 +14255,9 @@ var HooksInstallCommand = class extends SmCommand {
|
|
|
14174
14255
|
return ExitCode.Ok;
|
|
14175
14256
|
}
|
|
14176
14257
|
try {
|
|
14177
|
-
if (!
|
|
14178
|
-
|
|
14179
|
-
ensureExecutableBit(hookPath);
|
|
14258
|
+
if (!await pathExists(hooksDir)) await mkdir3(hooksDir, { recursive: true });
|
|
14259
|
+
await writeFile(hookPath, planned2.content, { encoding: "utf8" });
|
|
14260
|
+
await ensureExecutableBit(hookPath);
|
|
14180
14261
|
} catch (err) {
|
|
14181
14262
|
this.printer.error(
|
|
14182
14263
|
tx(HOOKS_TEXTS.installFailed, { glyph: errGlyph, message: formatErrorMessage(err) })
|
|
@@ -14202,10 +14283,10 @@ var HooksInstallCommand = class extends SmCommand {
|
|
|
14202
14283
|
return ExitCode.Ok;
|
|
14203
14284
|
}
|
|
14204
14285
|
};
|
|
14205
|
-
function findGitRepoRoot(cwd) {
|
|
14286
|
+
async function findGitRepoRoot(cwd) {
|
|
14206
14287
|
let current = cwd;
|
|
14207
14288
|
while (true) {
|
|
14208
|
-
if (
|
|
14289
|
+
if (await pathExists(resolve27(current, ".git"))) return current;
|
|
14209
14290
|
const parent = dirname16(current);
|
|
14210
14291
|
if (parent === current) return null;
|
|
14211
14292
|
current = parent;
|
|
@@ -14216,22 +14297,22 @@ function computePlannedHookContent(existing) {
|
|
|
14216
14297
|
if (existing.includes(SKILL_MAP_MARKER)) {
|
|
14217
14298
|
return { kind: "already-installed", content: existing };
|
|
14218
14299
|
}
|
|
14219
|
-
const
|
|
14220
|
-
return { kind: "chained", content: existing +
|
|
14300
|
+
const sep7 = existing.endsWith("\n") ? "" : "\n";
|
|
14301
|
+
return { kind: "chained", content: existing + sep7 + "\n" + SKILL_MAP_BLOCK };
|
|
14221
14302
|
}
|
|
14222
|
-
function ensureExecutableBit(path) {
|
|
14223
|
-
const mode =
|
|
14224
|
-
|
|
14303
|
+
async function ensureExecutableBit(path) {
|
|
14304
|
+
const mode = (await stat2(path)).mode;
|
|
14305
|
+
await chmod2(path, mode | 73);
|
|
14225
14306
|
}
|
|
14226
14307
|
var HOOKS_COMMANDS = [HooksInstallCommand];
|
|
14227
14308
|
|
|
14228
14309
|
// cli/commands/init.ts
|
|
14229
|
-
import { mkdir as
|
|
14310
|
+
import { mkdir as mkdir4, readFile as readFile3, unlink, writeFile as writeFile2 } from "fs/promises";
|
|
14230
14311
|
import { join as join17 } from "path";
|
|
14231
14312
|
import { Command as Command17, Option as Option16 } from "clipanion";
|
|
14232
14313
|
|
|
14233
14314
|
// kernel/orchestrator/index.ts
|
|
14234
|
-
import { existsSync as
|
|
14315
|
+
import { existsSync as existsSync21, statSync as statSync6 } from "fs";
|
|
14235
14316
|
import { isAbsolute as isAbsolute7, resolve as resolve28 } from "path";
|
|
14236
14317
|
import { Tiktoken as Tiktoken2 } from "js-tiktoken/lite";
|
|
14237
14318
|
import cl100k_base from "js-tiktoken/ranks/cl100k_base";
|
|
@@ -15265,8 +15346,8 @@ function computeDriftStatus(args2) {
|
|
|
15265
15346
|
}
|
|
15266
15347
|
|
|
15267
15348
|
// kernel/sidecar/discover-orphans.ts
|
|
15268
|
-
import { existsSync as
|
|
15269
|
-
import { join as join13, relative as relative4, sep as
|
|
15349
|
+
import { existsSync as existsSync19, readdirSync as readdirSync7, statSync as statSync5 } from "fs";
|
|
15350
|
+
import { join as join13, relative as relative4, sep as sep4 } from "path";
|
|
15270
15351
|
function discoverOrphanSidecars(roots, shouldSkip) {
|
|
15271
15352
|
const out = [];
|
|
15272
15353
|
for (const root of roots) {
|
|
@@ -15283,7 +15364,7 @@ function walk(root, current, shouldSkip, out) {
|
|
|
15283
15364
|
}
|
|
15284
15365
|
for (const entry of entries) {
|
|
15285
15366
|
const full = join13(current, entry.name);
|
|
15286
|
-
const rel = relative4(root, full).split(
|
|
15367
|
+
const rel = relative4(root, full).split(sep4).join("/");
|
|
15287
15368
|
if (shouldSkip(rel)) continue;
|
|
15288
15369
|
if (entry.isSymbolicLink()) continue;
|
|
15289
15370
|
if (entry.isDirectory()) {
|
|
@@ -15293,13 +15374,13 @@ function walk(root, current, shouldSkip, out) {
|
|
|
15293
15374
|
if (!entry.isFile()) continue;
|
|
15294
15375
|
if (!entry.name.endsWith(".sm")) continue;
|
|
15295
15376
|
const expectedMd = `${full.slice(0, -".sm".length)}.md`;
|
|
15296
|
-
if (
|
|
15377
|
+
if (existsSync19(expectedMd) && safeIsFile(expectedMd)) continue;
|
|
15297
15378
|
out.push({ sidecarPath: full, relativePath: rel, expectedMdPath: expectedMd });
|
|
15298
15379
|
}
|
|
15299
15380
|
}
|
|
15300
15381
|
function safeIsFile(path) {
|
|
15301
15382
|
try {
|
|
15302
|
-
return
|
|
15383
|
+
return statSync5(path).isFile();
|
|
15303
15384
|
} catch {
|
|
15304
15385
|
return false;
|
|
15305
15386
|
}
|
|
@@ -15307,7 +15388,7 @@ function safeIsFile(path) {
|
|
|
15307
15388
|
|
|
15308
15389
|
// kernel/orchestrator/node-build.ts
|
|
15309
15390
|
import { createHash } from "crypto";
|
|
15310
|
-
import { existsSync as
|
|
15391
|
+
import { existsSync as existsSync20 } from "fs";
|
|
15311
15392
|
import { isAbsolute as isAbsolute6, resolve as resolvePath } from "path";
|
|
15312
15393
|
import "js-tiktoken/lite";
|
|
15313
15394
|
import yaml4 from "js-yaml";
|
|
@@ -15471,11 +15552,11 @@ function resolveSidecarOverlay(relativePath2, nodePathForIssue, roots, liveBodyH
|
|
|
15471
15552
|
}
|
|
15472
15553
|
function resolveAbsoluteMdPath(relativePath2, roots) {
|
|
15473
15554
|
if (isAbsolute6(relativePath2)) {
|
|
15474
|
-
return
|
|
15555
|
+
return existsSync20(relativePath2) ? relativePath2 : null;
|
|
15475
15556
|
}
|
|
15476
15557
|
for (const root of roots) {
|
|
15477
15558
|
const candidate = resolvePath(root, relativePath2);
|
|
15478
|
-
if (
|
|
15559
|
+
if (existsSync20(candidate)) return candidate;
|
|
15479
15560
|
}
|
|
15480
15561
|
return null;
|
|
15481
15562
|
}
|
|
@@ -16016,7 +16097,7 @@ function validateRoots(roots) {
|
|
|
16016
16097
|
throw new Error(ORCHESTRATOR_TEXTS.runScanRootEmptyArray);
|
|
16017
16098
|
}
|
|
16018
16099
|
for (const root of roots) {
|
|
16019
|
-
if (!
|
|
16100
|
+
if (!existsSync21(root) || !statSync6(root).isDirectory()) {
|
|
16020
16101
|
throw new Error(tx(ORCHESTRATOR_TEXTS.runScanRootMissing, { root }));
|
|
16021
16102
|
}
|
|
16022
16103
|
}
|
|
@@ -16025,7 +16106,7 @@ function resolveActiveProviderOption(optionValue, roots) {
|
|
|
16025
16106
|
if (optionValue !== void 0) return optionValue;
|
|
16026
16107
|
for (const root of roots) {
|
|
16027
16108
|
const absRoot = isAbsolute7(root) ? root : resolve28(root);
|
|
16028
|
-
if (!
|
|
16109
|
+
if (!existsSync21(absRoot)) continue;
|
|
16029
16110
|
const detected = resolveActiveProvider(absRoot).resolved;
|
|
16030
16111
|
if (detected !== null) return detected;
|
|
16031
16112
|
}
|
|
@@ -16033,7 +16114,7 @@ function resolveActiveProviderOption(optionValue, roots) {
|
|
|
16033
16114
|
}
|
|
16034
16115
|
|
|
16035
16116
|
// kernel/scan/watcher.ts
|
|
16036
|
-
import { resolve as resolve29, relative as relative5, sep as
|
|
16117
|
+
import { resolve as resolve29, relative as relative5, sep as sep5 } from "path";
|
|
16037
16118
|
import chokidar from "chokidar";
|
|
16038
16119
|
function createChokidarWatcher(opts) {
|
|
16039
16120
|
const absRoots = opts.roots.map((r) => resolve29(opts.cwd, r));
|
|
@@ -16131,8 +16212,8 @@ function relativePathFromRoots2(absolute, absRoots) {
|
|
|
16131
16212
|
for (const root of absRoots) {
|
|
16132
16213
|
const rel = relative5(root, absolute);
|
|
16133
16214
|
if (rel === "" || rel === ".") return "";
|
|
16134
|
-
if (!rel.startsWith("..") && !rel.startsWith(`..${
|
|
16135
|
-
return rel.split(
|
|
16215
|
+
if (!rel.startsWith("..") && !rel.startsWith(`..${sep5}`)) {
|
|
16216
|
+
return rel.split(sep5).join("/");
|
|
16136
16217
|
}
|
|
16137
16218
|
}
|
|
16138
16219
|
return null;
|
|
@@ -16254,13 +16335,13 @@ function createKernel() {
|
|
|
16254
16335
|
}
|
|
16255
16336
|
|
|
16256
16337
|
// kernel/jobs/orphan-files.ts
|
|
16257
|
-
import { readdirSync as readdirSync8, statSync as
|
|
16338
|
+
import { readdirSync as readdirSync8, statSync as statSync7 } from "fs";
|
|
16258
16339
|
import { join as join14, resolve as resolve30 } from "path";
|
|
16259
16340
|
function findOrphanJobFiles(jobsDir, referencedPaths) {
|
|
16260
16341
|
let entries;
|
|
16261
16342
|
try {
|
|
16262
|
-
const
|
|
16263
|
-
if (!
|
|
16343
|
+
const stat3 = statSync7(jobsDir);
|
|
16344
|
+
if (!stat3.isDirectory()) {
|
|
16264
16345
|
return { orphanFilePaths: [], referencedCount: referencedPaths.size };
|
|
16265
16346
|
}
|
|
16266
16347
|
entries = readdirSync8(jobsDir, { withFileTypes: true });
|
|
@@ -16422,7 +16503,7 @@ function resolveScanRoots(inputs) {
|
|
|
16422
16503
|
}
|
|
16423
16504
|
|
|
16424
16505
|
// core/runtime/reference-paths-walker.ts
|
|
16425
|
-
import { readdirSync as readdirSync9, statSync as
|
|
16506
|
+
import { readdirSync as readdirSync9, statSync as statSync8 } from "fs";
|
|
16426
16507
|
import { homedir as osHomedir2 } from "os";
|
|
16427
16508
|
import { isAbsolute as isAbsolute8, join as join15, resolve as resolve31 } from "path";
|
|
16428
16509
|
var REFERENCE_WALK_MAX_FILES = 5e4;
|
|
@@ -16444,8 +16525,8 @@ function walkReferencePaths(rawRoots, cwd) {
|
|
|
16444
16525
|
for (const raw of rawRoots) {
|
|
16445
16526
|
if (truncated) break;
|
|
16446
16527
|
const root = resolveScanPath(raw, cwd);
|
|
16447
|
-
const
|
|
16448
|
-
if (!
|
|
16528
|
+
const stat3 = safeStat(root);
|
|
16529
|
+
if (!stat3 || !stat3.isDirectory()) {
|
|
16449
16530
|
missingRoots.push(root);
|
|
16450
16531
|
continue;
|
|
16451
16532
|
}
|
|
@@ -16476,7 +16557,7 @@ function walkInto(dir, out) {
|
|
|
16476
16557
|
}
|
|
16477
16558
|
function safeStat(path) {
|
|
16478
16559
|
try {
|
|
16479
|
-
return
|
|
16560
|
+
return statSync8(path);
|
|
16480
16561
|
} catch {
|
|
16481
16562
|
return null;
|
|
16482
16563
|
}
|
|
@@ -16979,7 +17060,7 @@ var InitCommand = class extends SmCommand {
|
|
|
16979
17060
|
const printer = this.printer ?? createPrinter({
|
|
16980
17061
|
stdout: this.context.stdout,
|
|
16981
17062
|
stderr: this.context.stderr,
|
|
16982
|
-
quietInfo: this.quiet
|
|
17063
|
+
quietInfo: this.quiet || this.json
|
|
16983
17064
|
});
|
|
16984
17065
|
if (this.dryRun) {
|
|
16985
17066
|
await writeDryRunPlan(printer, {
|
|
@@ -16994,7 +17075,7 @@ var InitCommand = class extends SmCommand {
|
|
|
16994
17075
|
});
|
|
16995
17076
|
return ExitCode.Ok;
|
|
16996
17077
|
}
|
|
16997
|
-
await
|
|
17078
|
+
await mkdir4(skillMapDir, { recursive: true });
|
|
16998
17079
|
writeFileAtomicExclusive(settingsPath, JSON.stringify({ schemaVersion: 1 }, null, 2) + "\n");
|
|
16999
17080
|
if (!await pathExists(localPath) || this.force) {
|
|
17000
17081
|
writeFileAtomicExclusive(localPath, "{}\n");
|
|
@@ -17168,7 +17249,7 @@ async function runFirstScan(scopeRoot, strict, printer, stderr, stdin, ansi) {
|
|
|
17168
17249
|
}
|
|
17169
17250
|
async function previewGitignoreEntries(scopeRoot, entries) {
|
|
17170
17251
|
const path = join17(scopeRoot, ".gitignore");
|
|
17171
|
-
const body = await pathExists(path) ? await
|
|
17252
|
+
const body = await pathExists(path) ? await readFile3(path, "utf8") : "";
|
|
17172
17253
|
const present = new Set(
|
|
17173
17254
|
body.split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"))
|
|
17174
17255
|
);
|
|
@@ -17178,7 +17259,7 @@ async function ensureGitignoreEntries(scopeRoot, entries) {
|
|
|
17178
17259
|
const path = join17(scopeRoot, ".gitignore");
|
|
17179
17260
|
let body = "";
|
|
17180
17261
|
if (await pathExists(path)) {
|
|
17181
|
-
body = await
|
|
17262
|
+
body = await readFile3(path, "utf8");
|
|
17182
17263
|
}
|
|
17183
17264
|
const present = new Set(
|
|
17184
17265
|
body.split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"))
|
|
@@ -17192,7 +17273,7 @@ async function ensureGitignoreEntries(scopeRoot, entries) {
|
|
|
17192
17273
|
present.add(entry);
|
|
17193
17274
|
changed = true;
|
|
17194
17275
|
}
|
|
17195
|
-
if (changed) await
|
|
17276
|
+
if (changed) await writeFile2(path, body);
|
|
17196
17277
|
return changed;
|
|
17197
17278
|
}
|
|
17198
17279
|
|
|
@@ -19058,10 +19139,10 @@ function pluginToListRow(p) {
|
|
|
19058
19139
|
}
|
|
19059
19140
|
function wrapNames(names, indent, maxWidth) {
|
|
19060
19141
|
const out = [];
|
|
19061
|
-
const
|
|
19142
|
+
const sep7 = ", ";
|
|
19062
19143
|
let current = "";
|
|
19063
19144
|
for (const name of names) {
|
|
19064
|
-
const candidate = current === "" ? name : `${current}${
|
|
19145
|
+
const candidate = current === "" ? name : `${current}${sep7}${name}`;
|
|
19065
19146
|
if (indent.length + candidate.length > maxWidth && current !== "") {
|
|
19066
19147
|
out.push(`${current},`);
|
|
19067
19148
|
current = name;
|
|
@@ -20066,7 +20147,7 @@ function resolveBareToggle(id, catalogue, verb, ansi) {
|
|
|
20066
20147
|
}
|
|
20067
20148
|
|
|
20068
20149
|
// cli/commands/plugins/create.ts
|
|
20069
|
-
import { existsSync as
|
|
20150
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync5, writeFileSync } from "fs";
|
|
20070
20151
|
import { join as join18, resolve as resolve33 } from "path";
|
|
20071
20152
|
import { Command as Command26, Option as Option25 } from "clipanion";
|
|
20072
20153
|
var PluginsCreateCommand = class extends SmCommand {
|
|
@@ -20095,7 +20176,7 @@ var PluginsCreateCommand = class extends SmCommand {
|
|
|
20095
20176
|
const ctx = defaultRuntimeContext();
|
|
20096
20177
|
const baseDir = defaultProjectPluginsDir(ctx);
|
|
20097
20178
|
const targetDir = this.at ? resolve33(this.at) : join18(baseDir, this.pluginId);
|
|
20098
|
-
if (
|
|
20179
|
+
if (existsSync22(targetDir) && !this.force) {
|
|
20099
20180
|
this.printer.error(
|
|
20100
20181
|
tx(PLUGINS_TEXTS.createRefuseOverwrite, {
|
|
20101
20182
|
glyph: errGlyph,
|
|
@@ -20106,7 +20187,7 @@ var PluginsCreateCommand = class extends SmCommand {
|
|
|
20106
20187
|
return ExitCode.Error;
|
|
20107
20188
|
}
|
|
20108
20189
|
const extractorName = `${this.pluginId}-extractor`;
|
|
20109
|
-
|
|
20190
|
+
mkdirSync5(join18(targetDir, "extractors", extractorName), { recursive: true });
|
|
20110
20191
|
const specVersion = installedSpecVersion();
|
|
20111
20192
|
const manifest = {
|
|
20112
20193
|
id: this.pluginId,
|
|
@@ -20125,15 +20206,15 @@ var PluginsCreateCommand = class extends SmCommand {
|
|
|
20125
20206
|
}
|
|
20126
20207
|
}
|
|
20127
20208
|
};
|
|
20128
|
-
|
|
20209
|
+
writeFileSync(
|
|
20129
20210
|
join18(targetDir, "plugin.json"),
|
|
20130
20211
|
JSON.stringify(manifest, null, 2) + "\n"
|
|
20131
20212
|
);
|
|
20132
|
-
|
|
20213
|
+
writeFileSync(
|
|
20133
20214
|
join18(targetDir, "extractors", extractorName, "index.js"),
|
|
20134
20215
|
scaffolderExtractorStub(extractorName)
|
|
20135
20216
|
);
|
|
20136
|
-
|
|
20217
|
+
writeFileSync(join18(targetDir, "README.md"), scaffolderReadme(this.pluginId));
|
|
20137
20218
|
this.printer.data(
|
|
20138
20219
|
tx(PLUGINS_TEXTS.createSuccess, {
|
|
20139
20220
|
targetDir: sanitizeForTerminal(targetDir),
|
|
@@ -20335,7 +20416,7 @@ var PLUGIN_COMMANDS = [
|
|
|
20335
20416
|
];
|
|
20336
20417
|
|
|
20337
20418
|
// cli/commands/refresh.ts
|
|
20338
|
-
import { readFile as
|
|
20419
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
20339
20420
|
import { resolve as resolve34 } from "path";
|
|
20340
20421
|
import { Command as Command29, Option as Option27 } from "clipanion";
|
|
20341
20422
|
|
|
@@ -20642,7 +20723,7 @@ var RefreshCommand = class extends SmCommand {
|
|
|
20642
20723
|
let body;
|
|
20643
20724
|
try {
|
|
20644
20725
|
assertContained(cwd, node.path);
|
|
20645
|
-
const raw = await
|
|
20726
|
+
const raw = await readFile4(resolve34(cwd, node.path), "utf8");
|
|
20646
20727
|
body = stripFrontmatterFence(raw);
|
|
20647
20728
|
} catch (err) {
|
|
20648
20729
|
if (!this.json) {
|
|
@@ -21491,7 +21572,7 @@ var ScanCommand = class extends SmCommand {
|
|
|
21491
21572
|
}
|
|
21492
21573
|
return null;
|
|
21493
21574
|
}
|
|
21494
|
-
/** Render the failure branch of `
|
|
21575
|
+
/** Render the failure branch of `TScanRunResult` to stderr. */
|
|
21495
21576
|
renderFailure(outcome) {
|
|
21496
21577
|
const ansi = this.ansiFor("stderr");
|
|
21497
21578
|
const errGlyph = ansi.red("\u2715");
|
|
@@ -21570,7 +21651,7 @@ var ScanCommand = class extends SmCommand {
|
|
|
21570
21651
|
this.printer.info(
|
|
21571
21652
|
tx(SCAN_TEXTS.jsonSelfValidationFailed, {
|
|
21572
21653
|
glyph: ansi.red("\u2715"),
|
|
21573
|
-
errors: validation.errors
|
|
21654
|
+
errors: JSON.stringify(validation.errors, null, 2)
|
|
21574
21655
|
})
|
|
21575
21656
|
);
|
|
21576
21657
|
return ExitCode.Error;
|
|
@@ -21591,7 +21672,7 @@ function plural(count, word) {
|
|
|
21591
21672
|
}
|
|
21592
21673
|
|
|
21593
21674
|
// cli/commands/scan-compare.ts
|
|
21594
|
-
import {
|
|
21675
|
+
import { access, readFile as readFile5 } from "fs/promises";
|
|
21595
21676
|
import { Command as Command32, Option as Option30 } from "clipanion";
|
|
21596
21677
|
var ScanCompareCommand = class extends SmCommand {
|
|
21597
21678
|
static paths = [["scan", "compare-with"]];
|
|
@@ -21644,7 +21725,7 @@ var ScanCompareCommand = class extends SmCommand {
|
|
|
21644
21725
|
const roots = this.roots.length > 0 ? this.roots : ["."];
|
|
21645
21726
|
let prior;
|
|
21646
21727
|
try {
|
|
21647
|
-
prior = loadAndValidateDump(this.dump);
|
|
21728
|
+
prior = await loadAndValidateDump(this.dump);
|
|
21648
21729
|
} catch (err) {
|
|
21649
21730
|
const message = formatErrorMessage(err);
|
|
21650
21731
|
this.printer.info(tx(SCAN_TEXTS.compareErrorPrefix, { message }));
|
|
@@ -21702,13 +21783,15 @@ var ScanCompareCommand = class extends SmCommand {
|
|
|
21702
21783
|
return exitCode2;
|
|
21703
21784
|
}
|
|
21704
21785
|
};
|
|
21705
|
-
function loadAndValidateDump(path) {
|
|
21706
|
-
|
|
21786
|
+
async function loadAndValidateDump(path) {
|
|
21787
|
+
try {
|
|
21788
|
+
await access(path);
|
|
21789
|
+
} catch {
|
|
21707
21790
|
throw new Error(tx(SCAN_TEXTS.compareDumpNotFound, { path }));
|
|
21708
21791
|
}
|
|
21709
21792
|
let raw;
|
|
21710
21793
|
try {
|
|
21711
|
-
raw =
|
|
21794
|
+
raw = await readFile5(path, "utf8");
|
|
21712
21795
|
} catch (err) {
|
|
21713
21796
|
const message = formatErrorMessage(err);
|
|
21714
21797
|
throw new Error(tx(SCAN_TEXTS.compareDumpReadFailed, { path, message }), { cause: err });
|
|
@@ -21833,7 +21916,7 @@ function renderDeltaIssues(issues) {
|
|
|
21833
21916
|
|
|
21834
21917
|
// cli/commands/serve.ts
|
|
21835
21918
|
import { spawn as spawn2 } from "child_process";
|
|
21836
|
-
import { existsSync as
|
|
21919
|
+
import { existsSync as existsSync28 } from "fs";
|
|
21837
21920
|
import { Command as Command33, Option as Option31 } from "clipanion";
|
|
21838
21921
|
|
|
21839
21922
|
// cli/util/browser-launch.ts
|
|
@@ -22459,7 +22542,7 @@ function registerFavoritesRoutes(app, deps) {
|
|
|
22459
22542
|
);
|
|
22460
22543
|
if (!result || !result.found) {
|
|
22461
22544
|
throw new HTTPException4(404, {
|
|
22462
|
-
message: tx(SERVER_TEXTS.nodeNotFound, { path: nodePath })
|
|
22545
|
+
message: tx(SERVER_TEXTS.nodeNotFound, { path: sanitizeForTerminal(nodePath) })
|
|
22463
22546
|
});
|
|
22464
22547
|
}
|
|
22465
22548
|
return c.body(null, 204);
|
|
@@ -22546,7 +22629,7 @@ function contentTypeFor(format) {
|
|
|
22546
22629
|
}
|
|
22547
22630
|
|
|
22548
22631
|
// server/health.ts
|
|
22549
|
-
import { existsSync as
|
|
22632
|
+
import { existsSync as existsSync23 } from "fs";
|
|
22550
22633
|
var FALLBACK_SCHEMA_VERSION = "1";
|
|
22551
22634
|
function buildHealth(deps) {
|
|
22552
22635
|
return {
|
|
@@ -22554,7 +22637,7 @@ function buildHealth(deps) {
|
|
|
22554
22637
|
schemaVersion: FALLBACK_SCHEMA_VERSION,
|
|
22555
22638
|
specVersion: deps.specVersion,
|
|
22556
22639
|
implVersion: VERSION,
|
|
22557
|
-
db:
|
|
22640
|
+
db: existsSync23(deps.dbPath) ? "present" : "missing",
|
|
22558
22641
|
cwd: deps.cwd,
|
|
22559
22642
|
dbPath: deps.dbPath
|
|
22560
22643
|
};
|
|
@@ -22586,47 +22669,60 @@ function registerHealthRoute(app, deps) {
|
|
|
22586
22669
|
});
|
|
22587
22670
|
}
|
|
22588
22671
|
|
|
22589
|
-
// server/
|
|
22672
|
+
// server/limits.ts
|
|
22590
22673
|
var DEFAULT_LIMIT = 100;
|
|
22591
22674
|
var MAX_LIMIT = 1e3;
|
|
22675
|
+
var BFF_MAX_BULK_CONTRIBUTIONS = 200;
|
|
22676
|
+
|
|
22677
|
+
// server/routes/issues.ts
|
|
22592
22678
|
function registerIssuesRoute(app, deps) {
|
|
22593
22679
|
app.get("/api/issues", async (c) => {
|
|
22594
|
-
const
|
|
22595
|
-
const analyzerFilter = parseCsv(c.req.query("analyzerId"));
|
|
22596
|
-
const nodePath = c.req.query("node") ?? null;
|
|
22597
|
-
const { offset, limit } = parsePagination(c.req.query(), {
|
|
22598
|
-
limit: DEFAULT_LIMIT,
|
|
22599
|
-
max: MAX_LIMIT
|
|
22600
|
-
});
|
|
22680
|
+
const inputs = parseIssuesQuery(c.req.query());
|
|
22601
22681
|
const result = await tryWithSqlite(
|
|
22602
22682
|
{ databasePath: deps.options.dbPath, autoBackup: false },
|
|
22603
|
-
(adapter) => adapter.issues.list(
|
|
22604
|
-
severities: severityFilter,
|
|
22605
|
-
analyzerIds: analyzerFilter,
|
|
22606
|
-
nodePath,
|
|
22607
|
-
offset,
|
|
22608
|
-
limit
|
|
22609
|
-
})
|
|
22683
|
+
(adapter) => adapter.issues.list(inputs.filter)
|
|
22610
22684
|
);
|
|
22611
|
-
const items = result?.items ?? [];
|
|
22612
|
-
const total = result?.total ?? 0;
|
|
22613
22685
|
return c.json(
|
|
22614
22686
|
buildListEnvelope({
|
|
22615
22687
|
kind: "issues",
|
|
22616
|
-
items,
|
|
22617
|
-
filters:
|
|
22618
|
-
|
|
22619
|
-
|
|
22620
|
-
node: nodePath
|
|
22621
|
-
},
|
|
22622
|
-
total,
|
|
22623
|
-
page: { offset, limit },
|
|
22688
|
+
items: result?.items ?? [],
|
|
22689
|
+
filters: inputs.echo,
|
|
22690
|
+
total: result?.total ?? 0,
|
|
22691
|
+
page: { offset: inputs.filter.offset, limit: inputs.filter.limit },
|
|
22624
22692
|
kindRegistry: deps.kindRegistry,
|
|
22625
22693
|
contributionsRegistry: deps.contributionsRegistry
|
|
22626
22694
|
})
|
|
22627
22695
|
);
|
|
22628
22696
|
});
|
|
22629
22697
|
}
|
|
22698
|
+
function parseIssuesQuery(query) {
|
|
22699
|
+
const severityFilter = parseCsv(query["severity"]);
|
|
22700
|
+
const analyzerFilter = parseCsv(query["analyzerId"]);
|
|
22701
|
+
const nodePath = query["node"] ?? null;
|
|
22702
|
+
const nodesRaw = parseCsv(query["nodes"]);
|
|
22703
|
+
const nodesFilter = nodesRaw.length > 0 ? nodesRaw : null;
|
|
22704
|
+
const { offset, limit } = parsePagination(query, {
|
|
22705
|
+
limit: DEFAULT_LIMIT,
|
|
22706
|
+
max: MAX_LIMIT
|
|
22707
|
+
});
|
|
22708
|
+
const filter = {
|
|
22709
|
+
severities: severityFilter,
|
|
22710
|
+
analyzerIds: analyzerFilter,
|
|
22711
|
+
nodePath,
|
|
22712
|
+
offset,
|
|
22713
|
+
limit
|
|
22714
|
+
};
|
|
22715
|
+
if (nodesFilter) filter.nodePaths = nodesFilter;
|
|
22716
|
+
return {
|
|
22717
|
+
filter,
|
|
22718
|
+
echo: {
|
|
22719
|
+
severity: severityFilter.length > 0 ? severityFilter : null,
|
|
22720
|
+
analyzerId: analyzerFilter.length > 0 ? analyzerFilter : null,
|
|
22721
|
+
node: nodePath,
|
|
22722
|
+
nodes: nodesFilter
|
|
22723
|
+
}
|
|
22724
|
+
};
|
|
22725
|
+
}
|
|
22630
22726
|
|
|
22631
22727
|
// server/routes/links.ts
|
|
22632
22728
|
function registerLinksRoute(app, deps) {
|
|
@@ -22666,22 +22762,30 @@ function registerLinksRoute(app, deps) {
|
|
|
22666
22762
|
import { HTTPException as HTTPException6 } from "hono/http-exception";
|
|
22667
22763
|
|
|
22668
22764
|
// server/node-body.ts
|
|
22669
|
-
import {
|
|
22670
|
-
import {
|
|
22765
|
+
import { constants as fsConstants2 } from "fs";
|
|
22766
|
+
import { open } from "fs/promises";
|
|
22767
|
+
import { isAbsolute as isAbsolute10, resolve as resolvePath2, relative as relativePath, sep as sep6 } from "path";
|
|
22671
22768
|
async function readNodeBody(cwd, relPath) {
|
|
22672
22769
|
if (isAbsolute10(relPath)) return null;
|
|
22673
22770
|
const absRoot = resolvePath2(cwd);
|
|
22674
22771
|
const absFile = resolvePath2(absRoot, relPath);
|
|
22675
22772
|
const rel = relativePath(absRoot, absFile);
|
|
22676
|
-
if (rel.startsWith("..") || rel.startsWith(
|
|
22773
|
+
if (rel.startsWith("..") || rel.startsWith(sep6) || rel.length === 0) {
|
|
22677
22774
|
return null;
|
|
22678
22775
|
}
|
|
22679
22776
|
let raw;
|
|
22777
|
+
let handle = null;
|
|
22680
22778
|
try {
|
|
22681
|
-
|
|
22779
|
+
handle = await open(absFile, fsConstants2.O_RDONLY | fsConstants2.O_NOFOLLOW);
|
|
22780
|
+
raw = await handle.readFile("utf-8");
|
|
22682
22781
|
} catch (err) {
|
|
22683
22782
|
if (isExpectedFsError(err)) return null;
|
|
22684
22783
|
throw err;
|
|
22784
|
+
} finally {
|
|
22785
|
+
if (handle !== null) {
|
|
22786
|
+
await handle.close().catch(() => {
|
|
22787
|
+
});
|
|
22788
|
+
}
|
|
22685
22789
|
}
|
|
22686
22790
|
return stripFrontmatter(raw);
|
|
22687
22791
|
}
|
|
@@ -22691,7 +22795,16 @@ function stripFrontmatter(raw) {
|
|
|
22691
22795
|
if (!match) return raw;
|
|
22692
22796
|
return raw.slice(match[0].length);
|
|
22693
22797
|
}
|
|
22694
|
-
var EXPECTED_FS_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
22798
|
+
var EXPECTED_FS_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
22799
|
+
"ENOENT",
|
|
22800
|
+
"EACCES",
|
|
22801
|
+
"EISDIR",
|
|
22802
|
+
"ENOTDIR",
|
|
22803
|
+
// `O_NOFOLLOW` opens fail with `ELOOP` on Linux / macOS when the
|
|
22804
|
+
// leaf is a symlink. Treat the same as "body unavailable" so the
|
|
22805
|
+
// BFF returns null, not a 500.
|
|
22806
|
+
"ELOOP"
|
|
22807
|
+
]);
|
|
22695
22808
|
function isExpectedFsError(err) {
|
|
22696
22809
|
if (err === null || typeof err !== "object") return false;
|
|
22697
22810
|
const code = err.code;
|
|
@@ -22749,9 +22862,6 @@ function splitCsv(raw) {
|
|
|
22749
22862
|
}
|
|
22750
22863
|
|
|
22751
22864
|
// server/routes/nodes.ts
|
|
22752
|
-
var DEFAULT_LIMIT2 = 100;
|
|
22753
|
-
var MAX_LIMIT2 = 1e3;
|
|
22754
|
-
var BFF_MAX_BULK_CONTRIBUTIONS = 200;
|
|
22755
22865
|
function registerNodesRoutes(app, deps) {
|
|
22756
22866
|
app.get("/api/nodes/:pathB64", async (c) => {
|
|
22757
22867
|
const pathB64 = c.req.param("pathB64");
|
|
@@ -22813,8 +22923,8 @@ function registerNodesRoutes(app, deps) {
|
|
|
22813
22923
|
const params = new URL(c.req.url).searchParams;
|
|
22814
22924
|
const { query, filters } = urlParamsToExportQuery(params);
|
|
22815
22925
|
const { offset, limit } = parsePagination(c.req.query(), {
|
|
22816
|
-
limit:
|
|
22817
|
-
max:
|
|
22926
|
+
limit: DEFAULT_LIMIT,
|
|
22927
|
+
max: MAX_LIMIT
|
|
22818
22928
|
});
|
|
22819
22929
|
const opened = await tryWithSqlite(
|
|
22820
22930
|
{ databasePath: deps.options.dbPath, autoBackup: false },
|
|
@@ -23389,15 +23499,15 @@ var parsePatchBody2 = makeBodyValidator(PATCH_BODY_SCHEMA, {
|
|
|
23389
23499
|
import { HTTPException as HTTPException10 } from "hono/http-exception";
|
|
23390
23500
|
|
|
23391
23501
|
// server/util/skillmapignore-io.ts
|
|
23392
|
-
import { existsSync as
|
|
23502
|
+
import { existsSync as existsSync24, readFileSync as readFileSync17, writeFileSync as writeFileSync2 } from "fs";
|
|
23393
23503
|
import { resolve as resolve35 } from "path";
|
|
23394
23504
|
var IGNORE_FILENAME2 = ".skillmapignore";
|
|
23395
23505
|
function readPatterns(cwd) {
|
|
23396
23506
|
const path = resolve35(cwd, IGNORE_FILENAME2);
|
|
23397
|
-
if (!
|
|
23507
|
+
if (!existsSync24(path)) return [];
|
|
23398
23508
|
let raw;
|
|
23399
23509
|
try {
|
|
23400
|
-
raw =
|
|
23510
|
+
raw = readFileSync17(path, "utf8");
|
|
23401
23511
|
} catch {
|
|
23402
23512
|
return [];
|
|
23403
23513
|
}
|
|
@@ -23405,13 +23515,13 @@ function readPatterns(cwd) {
|
|
|
23405
23515
|
}
|
|
23406
23516
|
function writePatterns(cwd, nextPatterns) {
|
|
23407
23517
|
const path = resolve35(cwd, IGNORE_FILENAME2);
|
|
23408
|
-
const prior =
|
|
23518
|
+
const prior = existsSync24(path) ? safeRead(path) : "";
|
|
23409
23519
|
const content = buildContent(prior, nextPatterns);
|
|
23410
|
-
|
|
23520
|
+
writeFileSync2(path, content, "utf8");
|
|
23411
23521
|
}
|
|
23412
23522
|
function safeRead(path) {
|
|
23413
23523
|
try {
|
|
23414
|
-
return
|
|
23524
|
+
return readFileSync17(path, "utf8");
|
|
23415
23525
|
} catch {
|
|
23416
23526
|
return "";
|
|
23417
23527
|
}
|
|
@@ -23566,7 +23676,7 @@ var parsePatchBody3 = makeBodyValidator(PATCH_BODY_SCHEMA2, {
|
|
|
23566
23676
|
});
|
|
23567
23677
|
|
|
23568
23678
|
// server/routes/project-preferences.ts
|
|
23569
|
-
import { statSync as
|
|
23679
|
+
import { statSync as statSync9 } from "fs";
|
|
23570
23680
|
import { HTTPException as HTTPException11 } from "hono/http-exception";
|
|
23571
23681
|
function registerProjectPreferencesRoute(app, deps) {
|
|
23572
23682
|
app.get("/api/project-preferences", (c) => {
|
|
@@ -23715,7 +23825,7 @@ function formatPathDetail(path, cwd) {
|
|
|
23715
23825
|
function isExistingDirectory(entry, cwd) {
|
|
23716
23826
|
const abs = resolveScanPath(entry, cwd);
|
|
23717
23827
|
try {
|
|
23718
|
-
return
|
|
23828
|
+
return statSync9(abs).isDirectory();
|
|
23719
23829
|
} catch {
|
|
23720
23830
|
return false;
|
|
23721
23831
|
}
|
|
@@ -23755,7 +23865,7 @@ var parsePatchBody4 = makeBodyValidator(PATCH_BODY_SCHEMA3, {
|
|
|
23755
23865
|
});
|
|
23756
23866
|
|
|
23757
23867
|
// server/routes/active-provider.ts
|
|
23758
|
-
import { existsSync as
|
|
23868
|
+
import { existsSync as existsSync25 } from "fs";
|
|
23759
23869
|
import { HTTPException as HTTPException12 } from "hono/http-exception";
|
|
23760
23870
|
function registerActiveProviderRoute(app, deps) {
|
|
23761
23871
|
app.get("/api/active-provider", (c) => {
|
|
@@ -23788,7 +23898,7 @@ function applyLensSwitch(deps, newValue) {
|
|
|
23788
23898
|
});
|
|
23789
23899
|
}
|
|
23790
23900
|
const dbPath = resolveDbPath({ db: void 0, cwd });
|
|
23791
|
-
if (!
|
|
23901
|
+
if (!existsSync25(dbPath)) return { dropped: null };
|
|
23792
23902
|
const dropResult = dropScanZone(dbPath);
|
|
23793
23903
|
return {
|
|
23794
23904
|
dropped: {
|
|
@@ -24180,7 +24290,7 @@ function registerSidecarRoutes(app, deps) {
|
|
|
24180
24290
|
assertContained(deps.runtimeContext.cwd, node.path);
|
|
24181
24291
|
absPath = resolve36(deps.runtimeContext.cwd, node.path);
|
|
24182
24292
|
} catch (err) {
|
|
24183
|
-
throw new HTTPException14(
|
|
24293
|
+
throw new HTTPException14(400, { message: formatErrorMessage(err) });
|
|
24184
24294
|
}
|
|
24185
24295
|
const result = invokeBump2(node, absPath, body);
|
|
24186
24296
|
if (result.report.ok === false && result.report.reason === "fresh") {
|
|
@@ -24302,8 +24412,8 @@ function registerUpdateStatusRoute(app, deps) {
|
|
|
24302
24412
|
}
|
|
24303
24413
|
|
|
24304
24414
|
// server/static.ts
|
|
24305
|
-
import { existsSync as
|
|
24306
|
-
import { readFile as
|
|
24415
|
+
import { existsSync as existsSync26 } from "fs";
|
|
24416
|
+
import { readFile as readFile6 } from "fs/promises";
|
|
24307
24417
|
import { extname, join as join19 } from "path";
|
|
24308
24418
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
24309
24419
|
var INDEX_HTML = "index.html";
|
|
@@ -24357,7 +24467,7 @@ function createSpaFallback(opts) {
|
|
|
24357
24467
|
if (c.req.method !== "GET" && c.req.method !== "HEAD") return c.notFound();
|
|
24358
24468
|
if (opts.uiDist === null) return htmlResponse(c, placeholder);
|
|
24359
24469
|
const indexPath = join19(opts.uiDist, INDEX_HTML);
|
|
24360
|
-
if (!
|
|
24470
|
+
if (!existsSync26(indexPath)) return htmlResponse(c, placeholder);
|
|
24361
24471
|
return fileResponse(c, indexPath);
|
|
24362
24472
|
};
|
|
24363
24473
|
}
|
|
@@ -24399,7 +24509,7 @@ function htmlResponse(c, html) {
|
|
|
24399
24509
|
return c.body(html, 200, { "content-type": "text/html; charset=UTF-8" });
|
|
24400
24510
|
}
|
|
24401
24511
|
async function fileResponse(c, absPath) {
|
|
24402
|
-
const buf = await
|
|
24512
|
+
const buf = await readFile6(absPath);
|
|
24403
24513
|
return c.body(buf, 200, { "content-type": mimeFor(absPath) });
|
|
24404
24514
|
}
|
|
24405
24515
|
|
|
@@ -24929,7 +25039,7 @@ function validateNoUi(noUi, uiDist) {
|
|
|
24929
25039
|
}
|
|
24930
25040
|
|
|
24931
25041
|
// server/paths.ts
|
|
24932
|
-
import { existsSync as
|
|
25042
|
+
import { existsSync as existsSync27, statSync as statSync10 } from "fs";
|
|
24933
25043
|
import { dirname as dirname18, isAbsolute as isAbsolute11, join as join20, resolve as resolve37 } from "path";
|
|
24934
25044
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
24935
25045
|
var DEFAULT_UI_REL = join20("ui", "dist", "ui", "browser");
|
|
@@ -24944,10 +25054,10 @@ function resolveExplicitUiDist(ctx, raw) {
|
|
|
24944
25054
|
return isAbsolute11(raw) ? raw : resolve37(ctx.cwd, raw);
|
|
24945
25055
|
}
|
|
24946
25056
|
function isUiBundleDir(path) {
|
|
24947
|
-
if (!
|
|
25057
|
+
if (!existsSync27(path)) return false;
|
|
24948
25058
|
try {
|
|
24949
|
-
if (!
|
|
24950
|
-
return
|
|
25059
|
+
if (!statSync10(path).isDirectory()) return false;
|
|
25060
|
+
return existsSync27(join20(path, INDEX_HTML2));
|
|
24951
25061
|
} catch {
|
|
24952
25062
|
return false;
|
|
24953
25063
|
}
|
|
@@ -25478,7 +25588,7 @@ var ServeCommand = class extends SmCommand {
|
|
|
25478
25588
|
return ExitCode.Error;
|
|
25479
25589
|
}
|
|
25480
25590
|
const dbPath = resolveDbPath({ db: this.db, ...runtimeCtx });
|
|
25481
|
-
if (this.db !== void 0 && !
|
|
25591
|
+
if (this.db !== void 0 && !existsSync28(dbPath)) {
|
|
25482
25592
|
this.printer.info(
|
|
25483
25593
|
tx(SERVE_TEXTS.dbNotFound, {
|
|
25484
25594
|
glyph: errGlyph,
|
|
@@ -26028,7 +26138,7 @@ function rankConfidenceForGrouping(c) {
|
|
|
26028
26138
|
}
|
|
26029
26139
|
|
|
26030
26140
|
// cli/commands/sidecar.ts
|
|
26031
|
-
import {
|
|
26141
|
+
import { unlink as unlink3 } from "fs/promises";
|
|
26032
26142
|
import { resolve as resolve38 } from "path";
|
|
26033
26143
|
import { Command as Command35, Option as Option33 } from "clipanion";
|
|
26034
26144
|
|
|
@@ -26320,7 +26430,7 @@ var SidecarPruneCommand = class extends SmCommand {
|
|
|
26320
26430
|
continue;
|
|
26321
26431
|
}
|
|
26322
26432
|
try {
|
|
26323
|
-
|
|
26433
|
+
await unlink3(orphan.sidecarPath);
|
|
26324
26434
|
items.push({
|
|
26325
26435
|
sidecarPath: orphan.sidecarPath,
|
|
26326
26436
|
expectedMd: orphan.expectedMdPath,
|
|
@@ -26477,7 +26587,8 @@ var SidecarAnnotateCommand = class extends SmCommand {
|
|
|
26477
26587
|
return ExitCode.Error;
|
|
26478
26588
|
}
|
|
26479
26589
|
const sidecarAbsPath = sidecarPathFor(absPath);
|
|
26480
|
-
|
|
26590
|
+
const sidecarExists = await pathExists(sidecarAbsPath);
|
|
26591
|
+
if (sidecarExists && this.force !== true) {
|
|
26481
26592
|
this.printer.error(
|
|
26482
26593
|
tx(SIDECAR_TEXTS.annotateExists, {
|
|
26483
26594
|
glyph: errGlyph,
|
|
@@ -26487,9 +26598,9 @@ var SidecarAnnotateCommand = class extends SmCommand {
|
|
|
26487
26598
|
);
|
|
26488
26599
|
return ExitCode.Error;
|
|
26489
26600
|
}
|
|
26490
|
-
if (
|
|
26601
|
+
if (sidecarExists && this.force === true) {
|
|
26491
26602
|
try {
|
|
26492
|
-
|
|
26603
|
+
await unlink3(sidecarAbsPath);
|
|
26493
26604
|
} catch (err) {
|
|
26494
26605
|
this.printer.error(
|
|
26495
26606
|
tx(SIDECAR_TEXTS.annotateFailed, { glyph: errGlyph, message: formatErrorMessage(err) })
|
|
@@ -26717,7 +26828,7 @@ var STUB_COMMANDS = [
|
|
|
26717
26828
|
];
|
|
26718
26829
|
|
|
26719
26830
|
// cli/commands/tutorial.ts
|
|
26720
|
-
import { cpSync as cpSync2, existsSync as
|
|
26831
|
+
import { cpSync as cpSync2, existsSync as existsSync29, mkdirSync as mkdirSync6, rmSync as rmSync2, statSync as statSync11 } from "fs";
|
|
26721
26832
|
import { dirname as dirname19, join as join21, resolve as resolve39 } from "path";
|
|
26722
26833
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
26723
26834
|
import { Command as Command37, Option as Option35 } from "clipanion";
|
|
@@ -26816,7 +26927,7 @@ var TutorialCommand = class extends SmCommand {
|
|
|
26816
26927
|
const spec = VARIANT_SPECS[variant];
|
|
26817
26928
|
const targetDir = join21(ctx.cwd, ".claude", "skills", spec.slug);
|
|
26818
26929
|
const targetDisplay = `.claude/skills/${spec.slug}/`;
|
|
26819
|
-
if (
|
|
26930
|
+
if (existsSync29(targetDir) && !this.force) {
|
|
26820
26931
|
this.printer.error(
|
|
26821
26932
|
tx(TUTORIAL_TEXTS.alreadyExists, {
|
|
26822
26933
|
glyph: errGlyph,
|
|
@@ -26842,7 +26953,7 @@ var TutorialCommand = class extends SmCommand {
|
|
|
26842
26953
|
}
|
|
26843
26954
|
try {
|
|
26844
26955
|
rmSync2(targetDir, { recursive: true, force: true });
|
|
26845
|
-
|
|
26956
|
+
mkdirSync6(dirname19(targetDir), { recursive: true });
|
|
26846
26957
|
cpSync2(sourceDir, targetDir, { recursive: true });
|
|
26847
26958
|
} catch (err) {
|
|
26848
26959
|
this.printer.error(
|
|
@@ -26899,7 +27010,7 @@ function resolveSkillSourceDir(variant) {
|
|
|
26899
27010
|
resolve39(here, "../cli/tutorial", spec.slug)
|
|
26900
27011
|
];
|
|
26901
27012
|
for (const candidate of candidates) {
|
|
26902
|
-
if (
|
|
27013
|
+
if (existsSync29(candidate) && statSync11(candidate).isDirectory()) {
|
|
26903
27014
|
cachedSourceDirs.set(variant, candidate);
|
|
26904
27015
|
return candidate;
|
|
26905
27016
|
}
|
|
@@ -27076,7 +27187,7 @@ await lifecycleDispatcher.dispatch(
|
|
|
27076
27187
|
process.exit(exitCode);
|
|
27077
27188
|
function resolveBareDefault() {
|
|
27078
27189
|
const ctx = defaultRuntimeContext();
|
|
27079
|
-
if (
|
|
27190
|
+
if (existsSync30(defaultProjectDbPath(ctx))) {
|
|
27080
27191
|
return ["serve"];
|
|
27081
27192
|
}
|
|
27082
27193
|
const stderr = process.stderr;
|