@skill-map/cli 0.34.1 → 0.36.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/index.js CHANGED
@@ -94,14 +94,14 @@ var Registry = class {
94
94
 
95
95
  // kernel/orchestrator/index.ts
96
96
  import { existsSync as existsSync11, statSync as statSync4 } from "fs";
97
- import { isAbsolute as isAbsolute4, resolve as resolve10 } from "path";
97
+ import { isAbsolute as isAbsolute4, resolve as resolve11 } from "path";
98
98
  import { Tiktoken as Tiktoken2 } from "js-tiktoken/lite";
99
99
  import cl100k_base from "js-tiktoken/ranks/cl100k_base";
100
100
 
101
101
  // package.json
102
102
  var package_default = {
103
103
  name: "@skill-map/cli",
104
- version: "0.34.1",
104
+ version: "0.36.0",
105
105
  description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
106
106
  license: "MIT",
107
107
  type: "module",
@@ -1051,7 +1051,13 @@ function loadConfigForScope(opts) {
1051
1051
  // core/config/active-provider.ts
1052
1052
  var DETECTION_RULES = [
1053
1053
  { providerId: "claude", marker: ".claude" },
1054
- { providerId: "gemini", marker: ".gemini" },
1054
+ // `gemini` retired 2026-05-22: Google replaced the Gemini CLI with the
1055
+ // Antigravity CLI (released 2026-05-19; Gemini CLI sunsets 2026-06-18).
1056
+ // Antigravity adopted the open-standard `.agents/` instead of a
1057
+ // vendor-specific directory, so detection of a Google CLI project
1058
+ // falls through to the universal `agent-skills` lens (`.agents/`
1059
+ // already classifies via that neutral provider). The lens can still
1060
+ // be set manually via `sm config set activeProvider antigravity`.
1055
1061
  { providerId: "openai", marker: ".codex" },
1056
1062
  { providerId: "openai", marker: "AGENTS.md" },
1057
1063
  { providerId: "cursor", marker: ".cursor" }
@@ -1429,7 +1435,7 @@ function isExternalUrlLink(link) {
1429
1435
  }
1430
1436
 
1431
1437
  // kernel/orchestrator/analyzers.ts
1432
- async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sidecarRoots, annotationContributions, viewContributions, orphanJobFiles, referenceablePaths, cwd, registeredActionIds, emitter, hookDispatcher) {
1438
+ async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sidecarRoots, annotationContributions, viewContributions, orphanJobFiles, referenceablePaths, cwd, registeredActionIds, emitter, hookDispatcher, reservedNodePaths) {
1433
1439
  const issues = [];
1434
1440
  const contributions = [];
1435
1441
  const validators = loadSchemaValidators();
@@ -1493,6 +1499,7 @@ async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sid
1493
1499
  orphanJobFiles,
1494
1500
  ...referenceablePaths ? { referenceablePaths } : {},
1495
1501
  ...cwd ? { cwd } : {},
1502
+ ...reservedNodePaths ? { reservedNodePaths } : {},
1496
1503
  emitContribution
1497
1504
  });
1498
1505
  for (const issue of emitted) {
@@ -1713,6 +1720,9 @@ function classifyLinkSource(source, shortIdToQualified, cachedQualifiedIds, appl
1713
1720
  return "obsolete";
1714
1721
  }
1715
1722
 
1723
+ // kernel/orchestrator/node-identifiers.ts
1724
+ import { posix as pathPosix } from "path";
1725
+
1716
1726
  // kernel/trigger-normalize.ts
1717
1727
  function normalizeTrigger(source) {
1718
1728
  let out = source.normalize("NFD");
@@ -1723,37 +1733,105 @@ function normalizeTrigger(source) {
1723
1733
  return out.trim();
1724
1734
  }
1725
1735
 
1726
- // kernel/orchestrator/lift-mention-confidence.ts
1727
- function liftMentionConfidence(links, nodes) {
1728
- if (!links.some((l) => l.kind === "mentions")) return;
1729
- const byPath2 = /* @__PURE__ */ new Set();
1730
- for (const node of nodes) byPath2.add(node.path);
1731
- const byNormalizedName = indexByNormalizedName(nodes);
1732
- for (const link of links) {
1733
- if (link.kind !== "mentions") continue;
1734
- if (isResolved(link, byPath2, byNormalizedName)) {
1735
- link.confidence = 1;
1736
- }
1736
+ // kernel/orchestrator/node-identifiers.ts
1737
+ function deriveNodeIdentifiers(node, kindDescriptor) {
1738
+ const sources = kindDescriptor?.identifiers;
1739
+ if (!sources || sources.length === 0) return [];
1740
+ const out = [];
1741
+ for (const source of sources) {
1742
+ const raw = readIdentifier(source, node);
1743
+ if (!raw) continue;
1744
+ const normalised = normalizeTrigger(raw);
1745
+ if (normalised) out.push(normalised);
1737
1746
  }
1747
+ return out;
1738
1748
  }
1739
- function isResolved(link, byPath2, byNormalizedName) {
1740
- const normalized = link.trigger?.normalizedTrigger;
1741
- if (normalized) {
1742
- const withoutSigil = normalized.replace(/^[/@]/, "").trim();
1743
- if (byNormalizedName.has(withoutSigil)) return true;
1749
+ function readIdentifier(source, node) {
1750
+ if (source === "frontmatter.name") return readFrontmatterName(node);
1751
+ if (source === "filename-basename") return readFilenameBasename(node);
1752
+ return readDirname(node);
1753
+ }
1754
+ function readFrontmatterName(node) {
1755
+ const raw = node.frontmatter?.["name"];
1756
+ if (typeof raw !== "string") return null;
1757
+ return raw.length > 0 ? raw : null;
1758
+ }
1759
+ function readFilenameBasename(node) {
1760
+ const base = pathPosix.basename(node.path);
1761
+ if (!base) return null;
1762
+ const ext = pathPosix.extname(base);
1763
+ const stem = ext ? base.slice(0, -ext.length) : base;
1764
+ return stem.length > 0 ? stem : null;
1765
+ }
1766
+ function readDirname(node) {
1767
+ const dir = pathPosix.dirname(node.path);
1768
+ if (!dir || dir === "." || dir === "/") return null;
1769
+ const base = pathPosix.basename(dir);
1770
+ return base.length > 0 ? base : null;
1771
+ }
1772
+
1773
+ // kernel/orchestrator/lift-resolved-link-confidence.ts
1774
+ var RESERVED_TARGET_CONFIDENCE = 0.1;
1775
+ function liftResolvedLinkConfidence(links, nodes, ctx) {
1776
+ if (!links.some((l) => l.confidence < 1)) return;
1777
+ const indexes = buildIndexes(nodes, ctx);
1778
+ for (const link of links) {
1779
+ if (link.confidence >= 1) continue;
1780
+ const resolution = resolve7(link, indexes, ctx);
1781
+ if (resolution === "none") continue;
1782
+ link.confidence = ctx.reservedNodePaths.has(resolution) ? RESERVED_TARGET_CONFIDENCE : 1;
1744
1783
  }
1745
- if (byPath2.has(link.target)) return true;
1746
- return false;
1747
1784
  }
1748
- function indexByNormalizedName(nodes) {
1749
- const out = /* @__PURE__ */ new Map();
1785
+ function buildIndexes(nodes, ctx) {
1786
+ const byPath2 = /* @__PURE__ */ new Set();
1787
+ const byName = /* @__PURE__ */ new Map();
1788
+ const nodeByPath = /* @__PURE__ */ new Map();
1750
1789
  for (const node of nodes) {
1751
- const raw = node.frontmatter?.["name"];
1752
- const name = typeof raw === "string" ? raw : "";
1753
- if (!name) continue;
1754
- out.set(normalizeTrigger(name), true);
1790
+ byPath2.add(node.path);
1791
+ nodeByPath.set(node.path, node);
1792
+ indexNode(node, ctx, byName);
1793
+ }
1794
+ return { byPath: byPath2, byName, nodeByPath };
1795
+ }
1796
+ function resolve7(link, indexes, ctx) {
1797
+ if (indexes.byPath.has(link.target)) return link.target;
1798
+ return resolveByName(link, indexes, ctx);
1799
+ }
1800
+ function resolveByName(link, indexes, ctx) {
1801
+ const stripped = stripTriggerSigil(link.trigger?.normalizedTrigger);
1802
+ if (stripped === null) return "none";
1803
+ const candidates = indexes.byName.get(stripped);
1804
+ if (!candidates?.length) return "none";
1805
+ const allowedKinds = lookupAllowedKinds(link, indexes, ctx);
1806
+ if (!allowedKinds?.length) return "none";
1807
+ const winner = candidates.find((c) => allowedKinds.includes(c.kind));
1808
+ return winner ? winner.path : "none";
1809
+ }
1810
+ function lookupAllowedKinds(link, indexes, ctx) {
1811
+ const sourceNode = indexes.nodeByPath.get(link.source);
1812
+ if (!sourceNode) return void 0;
1813
+ return ctx.providerResolution.get(sourceNode.provider)?.[link.kind];
1814
+ }
1815
+ function stripTriggerSigil(normalized) {
1816
+ if (!normalized) return null;
1817
+ const trimmed = normalized.replace(/^[/@]/, "").trim();
1818
+ return trimmed.length === 0 ? null : trimmed;
1819
+ }
1820
+ function indexNode(node, ctx, byName) {
1821
+ const kindDescriptor = ctx.kindRegistry.get(kindKey(node));
1822
+ const normalised = deriveNodeIdentifiers(node, kindDescriptor);
1823
+ for (const name of normalised) {
1824
+ const entry = { kind: node.kind, path: node.path };
1825
+ const bucket = byName.get(name);
1826
+ if (bucket) {
1827
+ bucket.push(entry);
1828
+ } else {
1829
+ byName.set(name, [entry]);
1830
+ }
1755
1831
  }
1756
- return out;
1832
+ }
1833
+ function kindKey(node) {
1834
+ return `${node.provider}/${node.kind}`;
1757
1835
  }
1758
1836
 
1759
1837
  // kernel/orchestrator/post-walk-transforms.ts
@@ -1766,17 +1844,17 @@ var POST_WALK_TRANSFORMS = [
1766
1844
  }
1767
1845
  },
1768
1846
  {
1769
- id: "lift-mention-confidence",
1770
- description: "Bump resolved `mentions` links to confidence 1.0 once the full node graph is known (post-merge polish).",
1771
- run(links, nodes) {
1772
- liftMentionConfidence(links, nodes);
1847
+ id: "lift-resolved-link-confidence",
1848
+ description: "Bump invocation links to confidence 1.0 when target / trigger resolves against the full node graph per the source Provider rules.",
1849
+ run(links, nodes, ctx) {
1850
+ liftResolvedLinkConfidence(links, nodes, ctx);
1773
1851
  }
1774
1852
  }
1775
1853
  ];
1776
- function applyPostWalkTransforms(links, nodes, transforms = POST_WALK_TRANSFORMS) {
1854
+ function applyPostWalkTransforms(links, nodes, ctx, transforms = POST_WALK_TRANSFORMS) {
1777
1855
  let current = links;
1778
1856
  for (const transform of transforms) {
1779
- const next = transform.run(current, nodes);
1857
+ const next = transform.run(current, nodes, ctx);
1780
1858
  if (next) current = next;
1781
1859
  }
1782
1860
  return current;
@@ -1920,7 +1998,7 @@ import { join as join7, relative as relative2, sep } from "path";
1920
1998
 
1921
1999
  // kernel/scan/ignore.ts
1922
2000
  import { existsSync as existsSync6, readFileSync as readFileSync7 } from "fs";
1923
- import { dirname as dirname4, resolve as resolve7 } from "path";
2001
+ import { dirname as dirname4, resolve as resolve8 } from "path";
1924
2002
  import { fileURLToPath } from "url";
1925
2003
  import ignoreFactory from "ignore";
1926
2004
  function buildIgnoreFilter(opts = {}) {
@@ -1954,11 +2032,11 @@ function loadDefaultsText() {
1954
2032
  function readDefaultsFromDisk() {
1955
2033
  const here = dirname4(fileURLToPath(import.meta.url));
1956
2034
  const candidates = [
1957
- resolve7(here, "../../config/defaults/skillmapignore"),
2035
+ resolve8(here, "../../config/defaults/skillmapignore"),
1958
2036
  // src/kernel/scan/ → src/config/defaults/
1959
- resolve7(here, "../config/defaults/skillmapignore"),
2037
+ resolve8(here, "../config/defaults/skillmapignore"),
1960
2038
  // dist/cli.js → dist/config/defaults/ (siblings)
1961
- resolve7(here, "config/defaults/skillmapignore")
2039
+ resolve8(here, "config/defaults/skillmapignore")
1962
2040
  ];
1963
2041
  for (const candidate of candidates) {
1964
2042
  if (existsSync6(candidate)) {
@@ -2149,7 +2227,7 @@ function resolveProviderWalk(provider) {
2149
2227
 
2150
2228
  // kernel/sidecar/parse.ts
2151
2229
  import { existsSync as existsSync7, readFileSync as readFileSync8 } from "fs";
2152
- import { dirname as dirname5, resolve as resolve8 } from "path";
2230
+ import { dirname as dirname5, resolve as resolve9 } from "path";
2153
2231
  import { createRequire as createRequire3 } from "module";
2154
2232
  import { Ajv2020 as Ajv20204 } from "ajv/dist/2020.js";
2155
2233
  import yaml2 from "js-yaml";
@@ -2228,10 +2306,10 @@ function getSidecarValidator() {
2228
2306
  applyAjvFormats(ajv);
2229
2307
  const specRoot = resolveSpecRoot2();
2230
2308
  const annotationsSchema = JSON.parse(
2231
- readFileSync8(resolve8(specRoot, "schemas/annotations.schema.json"), "utf8")
2309
+ readFileSync8(resolve9(specRoot, "schemas/annotations.schema.json"), "utf8")
2232
2310
  );
2233
2311
  const sidecarSchema = JSON.parse(
2234
- readFileSync8(resolve8(specRoot, "schemas/sidecar.schema.json"), "utf8")
2312
+ readFileSync8(resolve9(specRoot, "schemas/sidecar.schema.json"), "utf8")
2235
2313
  );
2236
2314
  ajv.addSchema(annotationsSchema);
2237
2315
  cachedSidecarValidator = ajv.compile(sidecarSchema);
@@ -2302,7 +2380,7 @@ function safeIsFile(path) {
2302
2380
 
2303
2381
  // kernel/sidecar/store.ts
2304
2382
  import { existsSync as existsSync9, readFileSync as readFileSync9 } from "fs";
2305
- import { dirname as dirname6, resolve as resolve9 } from "path";
2383
+ import { dirname as dirname6, resolve as resolve10 } from "path";
2306
2384
  import { createRequire as createRequire4 } from "module";
2307
2385
  import { Ajv2020 as Ajv20205 } from "ajv/dist/2020.js";
2308
2386
  import yaml3 from "js-yaml";
@@ -2846,7 +2924,8 @@ async function runScanInternal(_kernel, options) {
2846
2924
  pluginStores: options.pluginStores,
2847
2925
  activeProvider: resolveActiveProviderOption(options.activeProvider, options.roots)
2848
2926
  });
2849
- walked.internalLinks = applyPostWalkTransforms(walked.internalLinks, walked.nodes);
2927
+ const postWalkCtx = buildPostWalkTransformCtx(_kernel, walked.nodes);
2928
+ walked.internalLinks = applyPostWalkTransforms(walked.internalLinks, walked.nodes, postWalkCtx);
2850
2929
  recomputeLinkCounts(walked.nodes, walked.internalLinks);
2851
2930
  recomputeExternalRefsCount(walked.nodes, walked.externalLinks, walked.cachedPaths);
2852
2931
  await dispatchExtractorCompleted(exts.extractors, emitter, hookDispatcher);
@@ -2866,7 +2945,8 @@ async function runScanInternal(_kernel, options) {
2866
2945
  options.cwd,
2867
2946
  registeredActionIds,
2868
2947
  emitter,
2869
- hookDispatcher
2948
+ hookDispatcher,
2949
+ postWalkCtx.reservedNodePaths
2870
2950
  );
2871
2951
  mergeAnalyzerEmissions(walked, analyzerResult, exts.analyzers);
2872
2952
  const issues = analyzerResult.issues;
@@ -2879,6 +2959,56 @@ async function runScanInternal(_kernel, options) {
2879
2959
  await hookDispatcher.dispatch("scan.completed", scanCompletedEvent);
2880
2960
  return buildScanReturn(walked, issues, renameOps, stats, options, setup);
2881
2961
  }
2962
+ function buildPostWalkTransformCtx(kernel, nodes) {
2963
+ const { kindRegistry, providerResolution, reservedNamesByProviderKind } = buildProviderIndexes(kernel);
2964
+ const reservedNodePaths = buildReservedNodePaths(
2965
+ nodes,
2966
+ kindRegistry,
2967
+ reservedNamesByProviderKind
2968
+ );
2969
+ return { kindRegistry, providerResolution, reservedNodePaths };
2970
+ }
2971
+ function buildProviderIndexes(kernel) {
2972
+ const kindRegistry = /* @__PURE__ */ new Map();
2973
+ const providerResolution = /* @__PURE__ */ new Map();
2974
+ const reservedNamesByProviderKind = /* @__PURE__ */ new Map();
2975
+ const providers = kernel.registry.all("provider");
2976
+ for (const provider of providers) {
2977
+ if (provider.kinds) {
2978
+ for (const [kindName, descriptor] of Object.entries(provider.kinds)) {
2979
+ kindRegistry.set(`${provider.id}/${kindName}`, descriptor);
2980
+ }
2981
+ }
2982
+ if (provider.resolution) {
2983
+ providerResolution.set(provider.id, provider.resolution);
2984
+ }
2985
+ if (provider.reservedNames) {
2986
+ indexReservedNames(provider, reservedNamesByProviderKind);
2987
+ }
2988
+ }
2989
+ return { kindRegistry, providerResolution, reservedNamesByProviderKind };
2990
+ }
2991
+ function indexReservedNames(provider, out) {
2992
+ for (const [kindName, list] of Object.entries(provider.reservedNames ?? {})) {
2993
+ const normalised = new Set(list.map((raw) => normalizeTrigger(raw)).filter(Boolean));
2994
+ if (normalised.size > 0) {
2995
+ out.set(`${provider.id}/${kindName}`, normalised);
2996
+ }
2997
+ }
2998
+ }
2999
+ function buildReservedNodePaths(nodes, kindRegistry, reservedNamesByProviderKind) {
3000
+ const out = /* @__PURE__ */ new Set();
3001
+ for (const node of nodes) {
3002
+ const key = `${node.provider}/${node.kind}`;
3003
+ const reservedSet = reservedNamesByProviderKind.get(key);
3004
+ if (!reservedSet || reservedSet.size === 0) continue;
3005
+ const ids = deriveNodeIdentifiers(node, kindRegistry.get(key));
3006
+ if (ids.some((id) => reservedSet.has(id))) {
3007
+ out.add(node.path);
3008
+ }
3009
+ }
3010
+ return out;
3011
+ }
2882
3012
  function buildScanSetup(options) {
2883
3013
  const start = Date.now();
2884
3014
  const emitter = options.emitter ?? new InMemoryProgressEmitter();
@@ -2970,7 +3100,7 @@ function validateRoots(roots) {
2970
3100
  function resolveActiveProviderOption(optionValue, roots) {
2971
3101
  if (optionValue !== void 0) return optionValue;
2972
3102
  for (const root of roots) {
2973
- const absRoot = isAbsolute4(root) ? root : resolve10(root);
3103
+ const absRoot = isAbsolute4(root) ? root : resolve11(root);
2974
3104
  if (!existsSync11(absRoot)) continue;
2975
3105
  const detected = resolveActiveProvider(absRoot).resolved;
2976
3106
  if (detected !== null) return detected;
@@ -2979,10 +3109,10 @@ function resolveActiveProviderOption(optionValue, roots) {
2979
3109
  }
2980
3110
 
2981
3111
  // kernel/scan/watcher.ts
2982
- import { resolve as resolve11, relative as relative4, sep as sep3 } from "path";
3112
+ import { resolve as resolve12, relative as relative4, sep as sep3 } from "path";
2983
3113
  import chokidar from "chokidar";
2984
3114
  function createChokidarWatcher(opts) {
2985
- const absRoots = opts.roots.map((r) => resolve11(opts.cwd, r));
3115
+ const absRoots = opts.roots.map((r) => resolve12(opts.cwd, r));
2986
3116
  const ignoreFilterOpt = opts.ignoreFilter;
2987
3117
  const getFilter = ignoreFilterOpt === void 0 ? void 0 : typeof ignoreFilterOpt === "function" ? ignoreFilterOpt : () => ignoreFilterOpt;
2988
3118
  const ignored = getFilter ? (path) => {