@skill-map/cli 0.34.0 → 0.35.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.js +196 -45
- package/dist/cli.js.map +1 -1
- package/dist/index.js +109 -36
- package/dist/index.js.map +1 -1
- package/dist/kernel/index.d.ts +67 -0
- package/dist/kernel/index.js +109 -36
- package/dist/kernel/index.js.map +1 -1
- package/dist/ui/{chunk-MHWM2642.js → chunk-P25ABCQU.js} +3 -3
- package/dist/ui/index.html +1 -1
- package/dist/ui/{main-4X6AAGKZ.js → main-MNZ7YAUE.js} +1 -1
- package/package.json +2 -2
package/dist/kernel/index.d.ts
CHANGED
|
@@ -1742,7 +1742,42 @@ interface IProviderKind {
|
|
|
1742
1742
|
* invent visuals for a Provider-declared kind.
|
|
1743
1743
|
*/
|
|
1744
1744
|
ui: IProviderKindUi;
|
|
1745
|
+
/**
|
|
1746
|
+
* Priority-ordered list of identifier sources the post-walk resolver
|
|
1747
|
+
* uses to derive this kind's canonical name(s). Each entry contributes
|
|
1748
|
+
* one normalized name to the name index built by
|
|
1749
|
+
* `liftResolvedLinkConfidence`; multiple sources accumulate (e.g. a
|
|
1750
|
+
* skill with `name: foo` AND dirname `foo` yields one entry, a skill
|
|
1751
|
+
* with `name: bar` and dirname `foo` yields two).
|
|
1752
|
+
*
|
|
1753
|
+
* Defaults to `[]` (no name-resolvable). Source semantics:
|
|
1754
|
+
*
|
|
1755
|
+
* - `'frontmatter.name'`, read `node.frontmatter.name`. Required-name
|
|
1756
|
+
* kinds (`agent`, `command`, `skill` per their schemas) typically
|
|
1757
|
+
* declare this first.
|
|
1758
|
+
* - `'filename-basename'`, `basename(path)` without the extension.
|
|
1759
|
+
* For Claude/Gemini/OpenAI agents and commands the filename IS the
|
|
1760
|
+
* invocation handle when `name:` is absent.
|
|
1761
|
+
* - `'dirname'`, `basename(dirname(path))`. Anthropic skills + Gemini
|
|
1762
|
+
* skills + agent-skills resolve to the directory between the
|
|
1763
|
+
* skills root and the SKILL.md (e.g.
|
|
1764
|
+
* `.claude/skills/foo/SKILL.md` → `foo`).
|
|
1765
|
+
*
|
|
1766
|
+
* Compare with `IProvider.resolution` (which declares which target
|
|
1767
|
+
* kinds resolve which link.kind): `identifiers` is a per-kind detail
|
|
1768
|
+
* about WHERE the name lives; `resolution` is a per-provider strict
|
|
1769
|
+
* matrix about WHICH kinds count as resolution for a given link.kind.
|
|
1770
|
+
*/
|
|
1771
|
+
identifiers?: TIdentifierSource[];
|
|
1745
1772
|
}
|
|
1773
|
+
/**
|
|
1774
|
+
* Sources the post-walk confidence-lift transform consults to derive a
|
|
1775
|
+
* node's canonical name. Closed set: extending it is a spec + kernel
|
|
1776
|
+
* change. Order is meaningful inside `IProviderKind.identifiers`, the
|
|
1777
|
+
* resolver visits sources in declaration order, but the resulting index
|
|
1778
|
+
* is presence-based so multiple matches collapse.
|
|
1779
|
+
*/
|
|
1780
|
+
type TIdentifierSource = 'frontmatter.name' | 'filename-basename' | 'dirname';
|
|
1746
1781
|
/**
|
|
1747
1782
|
* Presentation contract for one Provider kind. The Provider declares
|
|
1748
1783
|
* intent (label + base color, optional dark variant + emoji + icon);
|
|
@@ -1902,6 +1937,38 @@ interface IProvider extends IExtensionBase {
|
|
|
1902
1937
|
* kind against `NodeKind`.
|
|
1903
1938
|
*/
|
|
1904
1939
|
classify(path: string, frontmatter: Record<string, unknown>): string | null;
|
|
1940
|
+
/**
|
|
1941
|
+
* Strict resolution matrix consumed by the post-walk confidence-lift
|
|
1942
|
+
* transform: maps a `link.kind` (emitted by an Extractor in this
|
|
1943
|
+
* Provider's bundle, e.g. `'mentions'`, `'invokes'`) to the set of
|
|
1944
|
+
* target `node.kind` values that count as a valid resolution.
|
|
1945
|
+
*
|
|
1946
|
+
* Used to decide whether to bump a link's confidence to 1.0 when its
|
|
1947
|
+
* normalized trigger matches some node's identifier (see
|
|
1948
|
+
* `IProviderKind.identifiers`). A link whose name resolves to a node
|
|
1949
|
+
* whose kind is NOT in `resolution[link.kind]` stays at its
|
|
1950
|
+
* extractor-emitted confidence, the name exists but does not resolve
|
|
1951
|
+
* AS THIS link.kind. Example: in `claude`, `invokes` resolves to
|
|
1952
|
+
* `['command', 'skill']`, so a `/foo` slash matching an `agent` named
|
|
1953
|
+
* `foo` does not bump (agents are mentioned with `@`, not invoked
|
|
1954
|
+
* with `/`).
|
|
1955
|
+
*
|
|
1956
|
+
* The lookup uses the Provider id attached to the link's SOURCE node
|
|
1957
|
+
* (i.e. who wrote the trigger). A link sourced from a markdown body
|
|
1958
|
+
* outside any Provider's territory falls under `core/markdown`'s
|
|
1959
|
+
* empty rules, no bump applies via the name path (the path-match rule
|
|
1960
|
+
* still does).
|
|
1961
|
+
*
|
|
1962
|
+
* Default `undefined` ≡ empty map ≡ no link.kind bumps under this
|
|
1963
|
+
* Provider's name index. Path matches (`link.target === node.path`)
|
|
1964
|
+
* are unaffected, those always bump regardless of `resolution`.
|
|
1965
|
+
*
|
|
1966
|
+
* Distinct from the spec's `IProvider.resolverRules` (referenced in
|
|
1967
|
+
* §Resolver phase): `resolverRules` rank candidates inside the Signal
|
|
1968
|
+
* IR (Phase 3+, not wired today); `resolution` is the post-walk
|
|
1969
|
+
* confidence-lift contract, which runs against the merged Link graph.
|
|
1970
|
+
*/
|
|
1971
|
+
resolution?: Record<string, string[]>;
|
|
1905
1972
|
}
|
|
1906
1973
|
/**
|
|
1907
1974
|
* Declarative read config a Provider declares via `IProvider.read`.
|
package/dist/kernel/index.js
CHANGED
|
@@ -101,7 +101,7 @@ import cl100k_base from "js-tiktoken/ranks/cl100k_base";
|
|
|
101
101
|
// package.json
|
|
102
102
|
var package_default = {
|
|
103
103
|
name: "@skill-map/cli",
|
|
104
|
-
version: "0.
|
|
104
|
+
version: "0.35.0",
|
|
105
105
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
106
106
|
license: "MIT",
|
|
107
107
|
type: "module",
|
|
@@ -1584,7 +1584,7 @@ function originatingNodeOf(link, priorNodePaths) {
|
|
|
1584
1584
|
function computeCacheDecision(opts) {
|
|
1585
1585
|
const applicableExtractors = opts.extractors.filter((ex) => {
|
|
1586
1586
|
if (!matchesKindPrecondition(ex, opts.kind)) return false;
|
|
1587
|
-
if (!matchesProviderPrecondition(ex, opts.
|
|
1587
|
+
if (!matchesProviderPrecondition(ex, opts.activeProvider)) return false;
|
|
1588
1588
|
return true;
|
|
1589
1589
|
});
|
|
1590
1590
|
const applicableQualifiedIds = new Set(
|
|
@@ -1608,10 +1608,9 @@ function matchesKindPrecondition(ex, kind) {
|
|
|
1608
1608
|
return kindOnly === kind;
|
|
1609
1609
|
});
|
|
1610
1610
|
}
|
|
1611
|
-
function matchesProviderPrecondition(ex,
|
|
1611
|
+
function matchesProviderPrecondition(ex, activeProvider) {
|
|
1612
1612
|
const providers = ex.precondition?.provider;
|
|
1613
1613
|
if (!providers || providers.length === 0) return true;
|
|
1614
|
-
if (!providers.includes(nodeProvider)) return false;
|
|
1615
1614
|
if (activeProvider === null) return false;
|
|
1616
1615
|
return providers.includes(activeProvider);
|
|
1617
1616
|
}
|
|
@@ -1714,6 +1713,9 @@ function classifyLinkSource(source, shortIdToQualified, cachedQualifiedIds, appl
|
|
|
1714
1713
|
return "obsolete";
|
|
1715
1714
|
}
|
|
1716
1715
|
|
|
1716
|
+
// kernel/orchestrator/lift-resolved-link-confidence.ts
|
|
1717
|
+
import { posix as pathPosix } from "path";
|
|
1718
|
+
|
|
1717
1719
|
// kernel/trigger-normalize.ts
|
|
1718
1720
|
function normalizeTrigger(source) {
|
|
1719
1721
|
let out = source.normalize("NFD");
|
|
@@ -1724,37 +1726,92 @@ function normalizeTrigger(source) {
|
|
|
1724
1726
|
return out.trim();
|
|
1725
1727
|
}
|
|
1726
1728
|
|
|
1727
|
-
// kernel/orchestrator/lift-
|
|
1728
|
-
function
|
|
1729
|
-
if (!links.some((l) => l.
|
|
1730
|
-
const
|
|
1731
|
-
for (const node of nodes) byPath2.add(node.path);
|
|
1732
|
-
const byNormalizedName = indexByNormalizedName(nodes);
|
|
1729
|
+
// kernel/orchestrator/lift-resolved-link-confidence.ts
|
|
1730
|
+
function liftResolvedLinkConfidence(links, nodes, ctx) {
|
|
1731
|
+
if (!links.some((l) => l.confidence < 1)) return;
|
|
1732
|
+
const indexes = buildIndexes(nodes, ctx);
|
|
1733
1733
|
for (const link of links) {
|
|
1734
|
-
if (link.
|
|
1735
|
-
if (isResolved(link, byPath2, byNormalizedName)) {
|
|
1734
|
+
if (link.confidence < 1 && resolves(link, indexes, ctx)) {
|
|
1736
1735
|
link.confidence = 1;
|
|
1737
1736
|
}
|
|
1738
1737
|
}
|
|
1739
1738
|
}
|
|
1740
|
-
function
|
|
1741
|
-
const
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
if (byNormalizedName.has(withoutSigil)) return true;
|
|
1745
|
-
}
|
|
1746
|
-
if (byPath2.has(link.target)) return true;
|
|
1747
|
-
return false;
|
|
1748
|
-
}
|
|
1749
|
-
function indexByNormalizedName(nodes) {
|
|
1750
|
-
const out = /* @__PURE__ */ new Map();
|
|
1739
|
+
function buildIndexes(nodes, ctx) {
|
|
1740
|
+
const byPath2 = /* @__PURE__ */ new Set();
|
|
1741
|
+
const byName = /* @__PURE__ */ new Map();
|
|
1742
|
+
const nodeByPath = /* @__PURE__ */ new Map();
|
|
1751
1743
|
for (const node of nodes) {
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1744
|
+
byPath2.add(node.path);
|
|
1745
|
+
nodeByPath.set(node.path, node);
|
|
1746
|
+
indexNode(node, ctx, byName);
|
|
1747
|
+
}
|
|
1748
|
+
return { byPath: byPath2, byName, nodeByPath };
|
|
1749
|
+
}
|
|
1750
|
+
function resolves(link, indexes, ctx) {
|
|
1751
|
+
if (indexes.byPath.has(link.target)) return true;
|
|
1752
|
+
return resolvesByName(link, indexes, ctx);
|
|
1753
|
+
}
|
|
1754
|
+
function resolvesByName(link, indexes, ctx) {
|
|
1755
|
+
const stripped = stripTriggerSigil(link.trigger?.normalizedTrigger);
|
|
1756
|
+
if (stripped === null) return false;
|
|
1757
|
+
const candidates = indexes.byName.get(stripped);
|
|
1758
|
+
if (!candidates?.length) return false;
|
|
1759
|
+
const allowedKinds = lookupAllowedKinds(link, indexes, ctx);
|
|
1760
|
+
if (!allowedKinds?.length) return false;
|
|
1761
|
+
return candidates.some((c) => allowedKinds.includes(c.kind));
|
|
1762
|
+
}
|
|
1763
|
+
function lookupAllowedKinds(link, indexes, ctx) {
|
|
1764
|
+
const sourceNode = indexes.nodeByPath.get(link.source);
|
|
1765
|
+
if (!sourceNode) return void 0;
|
|
1766
|
+
return ctx.providerResolution.get(sourceNode.provider)?.[link.kind];
|
|
1767
|
+
}
|
|
1768
|
+
function stripTriggerSigil(normalized) {
|
|
1769
|
+
if (!normalized) return null;
|
|
1770
|
+
const trimmed = normalized.replace(/^[/@]/, "").trim();
|
|
1771
|
+
return trimmed.length === 0 ? null : trimmed;
|
|
1772
|
+
}
|
|
1773
|
+
function indexNode(node, ctx, byName) {
|
|
1774
|
+
const kindDescriptor = ctx.kindRegistry.get(kindKey(node));
|
|
1775
|
+
const sources = kindDescriptor?.identifiers;
|
|
1776
|
+
if (!sources || sources.length === 0) return;
|
|
1777
|
+
for (const source of sources) {
|
|
1778
|
+
const raw = deriveIdentifier(source, node);
|
|
1779
|
+
if (!raw) continue;
|
|
1780
|
+
const normalized = normalizeTrigger(raw);
|
|
1781
|
+
if (!normalized) continue;
|
|
1782
|
+
const bucket = byName.get(normalized);
|
|
1783
|
+
if (bucket) {
|
|
1784
|
+
bucket.push({ kind: node.kind });
|
|
1785
|
+
} else {
|
|
1786
|
+
byName.set(normalized, [{ kind: node.kind }]);
|
|
1787
|
+
}
|
|
1756
1788
|
}
|
|
1757
|
-
|
|
1789
|
+
}
|
|
1790
|
+
function deriveIdentifier(source, node) {
|
|
1791
|
+
if (source === "frontmatter.name") return readFrontmatterName(node);
|
|
1792
|
+
if (source === "filename-basename") return readFilenameBasename(node);
|
|
1793
|
+
return readDirname(node);
|
|
1794
|
+
}
|
|
1795
|
+
function readFrontmatterName(node) {
|
|
1796
|
+
const raw = node.frontmatter?.["name"];
|
|
1797
|
+
if (typeof raw !== "string") return null;
|
|
1798
|
+
return raw.length > 0 ? raw : null;
|
|
1799
|
+
}
|
|
1800
|
+
function readFilenameBasename(node) {
|
|
1801
|
+
const base = pathPosix.basename(node.path);
|
|
1802
|
+
if (!base) return null;
|
|
1803
|
+
const ext = pathPosix.extname(base);
|
|
1804
|
+
const stem = ext ? base.slice(0, -ext.length) : base;
|
|
1805
|
+
return stem.length > 0 ? stem : null;
|
|
1806
|
+
}
|
|
1807
|
+
function readDirname(node) {
|
|
1808
|
+
const dir = pathPosix.dirname(node.path);
|
|
1809
|
+
if (!dir || dir === "." || dir === "/") return null;
|
|
1810
|
+
const base = pathPosix.basename(dir);
|
|
1811
|
+
return base.length > 0 ? base : null;
|
|
1812
|
+
}
|
|
1813
|
+
function kindKey(node) {
|
|
1814
|
+
return `${node.provider}/${node.kind}`;
|
|
1758
1815
|
}
|
|
1759
1816
|
|
|
1760
1817
|
// kernel/orchestrator/post-walk-transforms.ts
|
|
@@ -1767,17 +1824,17 @@ var POST_WALK_TRANSFORMS = [
|
|
|
1767
1824
|
}
|
|
1768
1825
|
},
|
|
1769
1826
|
{
|
|
1770
|
-
id: "lift-
|
|
1771
|
-
description: "Bump
|
|
1772
|
-
run(links, nodes) {
|
|
1773
|
-
|
|
1827
|
+
id: "lift-resolved-link-confidence",
|
|
1828
|
+
description: "Bump invocation links to confidence 1.0 when target / trigger resolves against the full node graph per the source Provider rules.",
|
|
1829
|
+
run(links, nodes, ctx) {
|
|
1830
|
+
liftResolvedLinkConfidence(links, nodes, ctx);
|
|
1774
1831
|
}
|
|
1775
1832
|
}
|
|
1776
1833
|
];
|
|
1777
|
-
function applyPostWalkTransforms(links, nodes, transforms = POST_WALK_TRANSFORMS) {
|
|
1834
|
+
function applyPostWalkTransforms(links, nodes, ctx, transforms = POST_WALK_TRANSFORMS) {
|
|
1778
1835
|
let current = links;
|
|
1779
1836
|
for (const transform of transforms) {
|
|
1780
|
-
const next = transform.run(current, nodes);
|
|
1837
|
+
const next = transform.run(current, nodes, ctx);
|
|
1781
1838
|
if (next) current = next;
|
|
1782
1839
|
}
|
|
1783
1840
|
return current;
|
|
@@ -2630,7 +2687,6 @@ async function processRawNode(raw, provider, wctx, accum, claimedPaths, nextInde
|
|
|
2630
2687
|
const cacheDecision = computeCacheDecision({
|
|
2631
2688
|
extractors: wctx.opts.extractors,
|
|
2632
2689
|
kind,
|
|
2633
|
-
provider: provider.id,
|
|
2634
2690
|
activeProvider: wctx.opts.activeProvider,
|
|
2635
2691
|
nodePath: raw.path,
|
|
2636
2692
|
bodyHash,
|
|
@@ -2848,7 +2904,8 @@ async function runScanInternal(_kernel, options) {
|
|
|
2848
2904
|
pluginStores: options.pluginStores,
|
|
2849
2905
|
activeProvider: resolveActiveProviderOption(options.activeProvider, options.roots)
|
|
2850
2906
|
});
|
|
2851
|
-
|
|
2907
|
+
const postWalkCtx = buildPostWalkTransformCtx(_kernel);
|
|
2908
|
+
walked.internalLinks = applyPostWalkTransforms(walked.internalLinks, walked.nodes, postWalkCtx);
|
|
2852
2909
|
recomputeLinkCounts(walked.nodes, walked.internalLinks);
|
|
2853
2910
|
recomputeExternalRefsCount(walked.nodes, walked.externalLinks, walked.cachedPaths);
|
|
2854
2911
|
await dispatchExtractorCompleted(exts.extractors, emitter, hookDispatcher);
|
|
@@ -2881,6 +2938,22 @@ async function runScanInternal(_kernel, options) {
|
|
|
2881
2938
|
await hookDispatcher.dispatch("scan.completed", scanCompletedEvent);
|
|
2882
2939
|
return buildScanReturn(walked, issues, renameOps, stats, options, setup);
|
|
2883
2940
|
}
|
|
2941
|
+
function buildPostWalkTransformCtx(kernel) {
|
|
2942
|
+
const kindRegistry = /* @__PURE__ */ new Map();
|
|
2943
|
+
const providerResolution = /* @__PURE__ */ new Map();
|
|
2944
|
+
const providers = kernel.registry.all("provider");
|
|
2945
|
+
for (const provider of providers) {
|
|
2946
|
+
if (provider.kinds) {
|
|
2947
|
+
for (const [kindName, descriptor] of Object.entries(provider.kinds)) {
|
|
2948
|
+
kindRegistry.set(`${provider.id}/${kindName}`, descriptor);
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
if (provider.resolution) {
|
|
2952
|
+
providerResolution.set(provider.id, provider.resolution);
|
|
2953
|
+
}
|
|
2954
|
+
}
|
|
2955
|
+
return { kindRegistry, providerResolution };
|
|
2956
|
+
}
|
|
2884
2957
|
function buildScanSetup(options) {
|
|
2885
2958
|
const start = Date.now();
|
|
2886
2959
|
const emitter = options.emitter ?? new InMemoryProgressEmitter();
|