@skill-map/cli 0.36.0 → 0.37.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.d.ts CHANGED
@@ -1 +1 @@
1
- export { Confidence, DuplicateExtensionError, EXTENSION_KINDS, ExecutionFailureReason, ExecutionKind, ExecutionRecord, ExecutionRunner, ExecutionStatus, ExportQueryError, Extension, ExtensionKind, FilesystemPort, HOOK_TRIGGERS, HistoryStats, HistoryStatsErrorRates, HistoryStatsExecutionsPerPeriod, HistoryStatsPerActionRate, HistoryStatsTokensPerAction, HistoryStatsTopNode, HistoryStatsTotals, IAction, IActionContext, IActionPrecondition, IActionResult, IAnalyzer, IAnalyzerContext, IAnnotationContribution, ICreateFsWatcherOptions, IDedicatedStorePersist, IDedicatedStoreWrapper, IDiscoveredPlugin, IEnrichmentRecord, IExportQuery, IExportSubset, IExtensionBase, IExtractor, IExtractorCallbacks, IExtractorContext, IExtractorRunRecord, IFormatter, IFormatterContext, IFsWatcher, IHook, IHookContext, IHookDispatcher, IIssueRow, IKvStorePersist, IKvStoreWrapper, ILoadedExtension, INodeBundle, INodeChange, INodeCounts, INodeFilter, IPersistOptions, IPersistedEnrichment, IPluginManifest, IPluginStorageSchema, IPluginStore, IProvider, IRawNode, IRegisteredAnnotationKey, IRegisteredViewContribution, IRunOptions, IRunResult, IScanDelta, ISettingDeclaration, ITransactionalStorage, IViewContribution, IWalkOptions, IWatchBatch, IWatchEvent, InMemoryProgressEmitter, Issue, IssueFix, KV_SCHEMA_KEY, Kernel, LOG_LEVELS, Link, LinkKind, LinkLocation, LinkTrigger, LogRecord, LoggerPort, Node, NodeKind, NodeStat, PluginLoaderPort, ProgressEmitterPort, ProgressEvent, Registry, RenameOp, RunScanOptions, RunnerPort, ScanResult, ScanScannedBy, ScanStats, Severity, SilentLogger, Stability, StoragePort, TActionWrite, TExecutionMode, TGranularity, THookFilter, THookTrigger, TInputTypeName, TLogLevel, TLogMethodLevel, TNodeChangeReason, TPluginLoadStatus, TPluginStorage, TProgressListener, TSettingValue, TSeverity, TSlotName, TWatchEventKind, TripleSplit, applyExportQuery, computeScanDelta, configureLogger, createChokidarWatcher, createKernel, detectRenamesAndOrphans, getActiveLogger, isEmptyDelta, isLogLevel, log, logLevelRank, makeDedicatedStoreWrapper, makeEvent, makeHookDispatcher, makeKvStoreWrapper, makePluginStore, mergeNodeWithEnrichments, parseExportQuery, parseLogLevel, qualifiedExtensionId, resetLogger, runExtractorsForNode, runScan, runScanWithRenames } from './kernel/index.js';
1
+ export { Confidence, DuplicateExtensionError, EXTENSION_KINDS, ExecutionFailureReason, ExecutionKind, ExecutionRecord, ExecutionRunner, ExecutionStatus, ExportQueryError, Extension, ExtensionKind, FilesystemPort, HOOK_TRIGGERS, HistoryStats, HistoryStatsErrorRates, HistoryStatsExecutionsPerPeriod, HistoryStatsPerActionRate, HistoryStatsTokensPerAction, HistoryStatsTopNode, HistoryStatsTotals, IAction, IActionContext, IActionPrecondition, IActionResult, IAnalyzer, IAnalyzerContext, IAnnotationContribution, ICreateFsWatcherOptions, IDedicatedStorePersist, IDedicatedStoreWrapper, IDiscoveredPlugin, IEnrichmentRecord, IExportQuery, IExportSubset, IExtensionBase, IExternalRef, IExtractor, IExtractorCallbacks, IExtractorContext, IExtractorRunRecord, IFormatter, IFormatterContext, IFsWatcher, IHook, IHookContext, IHookDispatcher, IIssueRow, IKvStorePersist, IKvStoreWrapper, ILoadedExtension, INodeBundle, INodeChange, INodeCounts, INodeFilter, IPersistOptions, IPersistedEnrichment, IPluginManifest, IPluginStorageSchema, IPluginStore, IProvider, IRawNode, IRegisteredAnnotationKey, IRegisteredViewContribution, IRunOptions, IRunResult, IScanDelta, ISettingDeclaration, ITransactionalStorage, IViewContribution, IWalkOptions, IWatchBatch, IWatchEvent, InMemoryProgressEmitter, Issue, IssueFix, KV_SCHEMA_KEY, Kernel, LOG_LEVELS, Link, LinkKind, LinkLocation, LinkOccurrence, LinkTrigger, LogRecord, LoggerPort, Node, NodeKind, NodeStat, PluginLoaderPort, ProgressEmitterPort, ProgressEvent, Registry, RenameOp, RunScanOptions, RunnerPort, ScanResult, ScanScannedBy, ScanStats, Severity, SilentLogger, Stability, StoragePort, TActionWrite, TExecutionMode, TGranularity, THookFilter, THookTrigger, TInputTypeName, TLogLevel, TLogMethodLevel, TNodeChangeReason, TPluginLoadStatus, TPluginStorage, TProgressListener, TSettingValue, TSeverity, TSlotName, TWatchEventKind, TripleSplit, applyExportQuery, computeScanDelta, configureLogger, createChokidarWatcher, createKernel, detectRenamesAndOrphans, getActiveLogger, isEmptyDelta, isLogLevel, log, logLevelRank, makeDedicatedStoreWrapper, makeEvent, makeHookDispatcher, makeKvStoreWrapper, makePluginStore, mergeNodeWithEnrichments, parseExportQuery, parseLogLevel, qualifiedExtensionId, resetLogger, runExtractorsForNode, runScan, runScanWithRenames } from './kernel/index.js';
package/dist/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.36.0",
104
+ version: "0.37.0",
105
105
  description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
106
106
  license: "MIT",
107
107
  type: "module",
@@ -197,7 +197,7 @@ var package_default = {
197
197
  eslint: "10.2.1",
198
198
  "eslint-plugin-import-x": "4.16.2",
199
199
  tsup: "8.5.1",
200
- tsx: "4.21.0",
200
+ tsx: "4.22.3",
201
201
  typescript: "5.9.3",
202
202
  "typescript-eslint": "8.59.1"
203
203
  },
@@ -1396,6 +1396,20 @@ function dedupeLinks(links) {
1396
1396
  if (link.confidence > existing.confidence) {
1397
1397
  existing.confidence = link.confidence;
1398
1398
  }
1399
+ if (link.occurrences && link.occurrences.length > 0) {
1400
+ const existingOccurrences = existing.occurrences ?? [];
1401
+ const occKey = (o) => `${o.extractor}\0${o.originalTrigger}\0${o.location?.line ?? -1}`;
1402
+ const occSeen = new Set(existingOccurrences.map(occKey));
1403
+ const merged = [...existingOccurrences];
1404
+ for (const occ of link.occurrences) {
1405
+ const k = occKey(occ);
1406
+ if (!occSeen.has(k)) {
1407
+ occSeen.add(k);
1408
+ merged.push(occ);
1409
+ }
1410
+ }
1411
+ existing.occurrences = merged;
1412
+ }
1399
1413
  continue;
1400
1414
  }
1401
1415
  out.set(key, link);
@@ -1419,12 +1433,23 @@ function recomputeLinkCounts(nodes, links) {
1419
1433
  function recomputeExternalRefsCount(nodes, externalLinks, cachedPaths) {
1420
1434
  const byPath2 = /* @__PURE__ */ new Map();
1421
1435
  for (const node of nodes) {
1422
- if (!cachedPaths.has(node.path)) node.externalRefsCount = 0;
1436
+ if (!cachedPaths.has(node.path)) {
1437
+ node.externalRefsCount = 0;
1438
+ delete node.externalRefs;
1439
+ }
1423
1440
  byPath2.set(node.path, node);
1424
1441
  }
1425
1442
  for (const link of externalLinks) {
1426
1443
  const source = byPath2.get(link.source);
1427
- if (source && !cachedPaths.has(source.path)) source.externalRefsCount += 1;
1444
+ if (!source || cachedPaths.has(source.path)) continue;
1445
+ source.externalRefsCount += 1;
1446
+ const refs = source.externalRefs ?? [];
1447
+ refs.push({
1448
+ url: link.target,
1449
+ ...link.location?.line !== void 0 ? { line: link.location.line } : {},
1450
+ ...link.trigger?.originalTrigger ? { originalTrigger: link.trigger.originalTrigger } : {}
1451
+ });
1452
+ source.externalRefs = refs;
1428
1453
  }
1429
1454
  }
1430
1455
  var EXTERNAL_URL_SCHEME_RE = /^[a-z][a-z0-9+\-.]+:/i;
@@ -1435,7 +1460,7 @@ function isExternalUrlLink(link) {
1435
1460
  }
1436
1461
 
1437
1462
  // kernel/orchestrator/analyzers.ts
1438
- async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sidecarRoots, annotationContributions, viewContributions, orphanJobFiles, referenceablePaths, cwd, registeredActionIds, emitter, hookDispatcher, reservedNodePaths) {
1463
+ async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sidecarRoots, annotationContributions, viewContributions, orphanJobFiles, referenceablePaths, cwd, registeredActionIds, emitter, hookDispatcher, reservedNodePaths, signals) {
1439
1464
  const issues = [];
1440
1465
  const contributions = [];
1441
1466
  const validators = loadSchemaValidators();
@@ -1500,6 +1525,7 @@ async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sid
1500
1525
  ...referenceablePaths ? { referenceablePaths } : {},
1501
1526
  ...cwd ? { cwd } : {},
1502
1527
  ...reservedNodePaths ? { reservedNodePaths } : {},
1528
+ ...signals && signals.length > 0 ? { signals } : {},
1503
1529
  emitContribution
1504
1530
  });
1505
1531
  for (const issue of emitted) {
@@ -1780,6 +1806,7 @@ function liftResolvedLinkConfidence(links, nodes, ctx) {
1780
1806
  const resolution = resolve7(link, indexes, ctx);
1781
1807
  if (resolution === "none") continue;
1782
1808
  link.confidence = ctx.reservedNodePaths.has(resolution) ? RESERVED_TARGET_CONFIDENCE : 1;
1809
+ link.resolvedTarget = resolution;
1783
1810
  }
1784
1811
  }
1785
1812
  function buildIndexes(nodes, ctx) {
@@ -1860,6 +1887,190 @@ function applyPostWalkTransforms(links, nodes, ctx, transforms = POST_WALK_TRANS
1860
1887
  return current;
1861
1888
  }
1862
1889
 
1890
+ // kernel/orchestrator/resolver.ts
1891
+ function resolveSignals(opts) {
1892
+ const kindPriority = opts.activeProvider?.resolverRules?.kindPriority ?? [];
1893
+ const extractorRank = buildExtractorRank(opts.extractorOrder);
1894
+ for (const signal of opts.signals) {
1895
+ signal.resolution = pickIntraWinner(signal, kindPriority, extractorRank);
1896
+ }
1897
+ const bySource = /* @__PURE__ */ new Map();
1898
+ for (const signal of opts.signals) {
1899
+ if (signal.resolution?.outcome !== "materialised") continue;
1900
+ const bucket = bySource.get(signal.source) ?? [];
1901
+ bucket.push(signal);
1902
+ bySource.set(signal.source, bucket);
1903
+ }
1904
+ for (const [, signals] of bySource) {
1905
+ const clusters = buildOverlapClusters(signals);
1906
+ for (const cluster of clusters) {
1907
+ if (cluster.length < 2) continue;
1908
+ if (everyCandidateIsExternalUrl(cluster)) continue;
1909
+ resolveCluster(cluster, kindPriority, extractorRank);
1910
+ }
1911
+ }
1912
+ const links = [];
1913
+ for (const signal of opts.signals) {
1914
+ if (signal.resolution?.outcome !== "materialised") continue;
1915
+ const winnerIndex = signal.resolution.winnerIndex ?? 0;
1916
+ const winner = signal.candidates[winnerIndex];
1917
+ if (!winner) continue;
1918
+ links.push(materialise(signal, winner));
1919
+ }
1920
+ return { links, resolvedSignals: [...opts.signals] };
1921
+ }
1922
+ function buildExtractorRank(order) {
1923
+ const rank = /* @__PURE__ */ new Map();
1924
+ for (let i = 0; i < order.length; i += 1) rank.set(order[i], i);
1925
+ return rank;
1926
+ }
1927
+ function pickIntraWinner(signal, kindPriority, extractorRank) {
1928
+ let bestIndex = 0;
1929
+ for (let i = 1; i < signal.candidates.length; i += 1) {
1930
+ if (compareCandidates(signal.candidates[i], signal.candidates[bestIndex], kindPriority, extractorRank) < 0) {
1931
+ bestIndex = i;
1932
+ }
1933
+ }
1934
+ return { outcome: "materialised", winnerIndex: bestIndex };
1935
+ }
1936
+ function compareCandidates(a, b, kindPriority, extractorRank) {
1937
+ const kindCmp = compareKindPriority(a.kind, b.kind, kindPriority);
1938
+ if (kindCmp !== 0) return kindCmp;
1939
+ if (a.confidence !== b.confidence) return b.confidence - a.confidence;
1940
+ const aRank = extractorRank.get(a.extractorId) ?? Number.MAX_SAFE_INTEGER;
1941
+ const bRank = extractorRank.get(b.extractorId) ?? Number.MAX_SAFE_INTEGER;
1942
+ return aRank - bRank;
1943
+ }
1944
+ function compareKindPriority(aKind, bKind, kindPriority) {
1945
+ if (kindPriority.length === 0) return 0;
1946
+ const aIdx = kindPriority.indexOf(aKind);
1947
+ const bIdx = kindPriority.indexOf(bKind);
1948
+ const aEff = aIdx === -1 ? Number.MAX_SAFE_INTEGER : aIdx;
1949
+ const bEff = bIdx === -1 ? Number.MAX_SAFE_INTEGER : bIdx;
1950
+ return aEff - bEff;
1951
+ }
1952
+ function buildOverlapClusters(signals) {
1953
+ const bodySignals = signals.filter((s) => s.scope === "body" && s.range);
1954
+ const others = signals.filter((s) => !(s.scope === "body" && s.range));
1955
+ const parent = bodySignals.map((_, i) => i);
1956
+ const find = (i) => {
1957
+ while (parent[i] !== i) {
1958
+ parent[i] = parent[parent[i]];
1959
+ i = parent[i];
1960
+ }
1961
+ return i;
1962
+ };
1963
+ const union = (a, b) => {
1964
+ const ra = find(a);
1965
+ const rb = find(b);
1966
+ if (ra !== rb) parent[ra] = rb;
1967
+ };
1968
+ for (let i = 0; i < bodySignals.length; i += 1) {
1969
+ for (let j = i + 1; j < bodySignals.length; j += 1) {
1970
+ if (rangesOverlap(bodySignals[i].range, bodySignals[j].range)) {
1971
+ union(i, j);
1972
+ }
1973
+ }
1974
+ }
1975
+ const byRoot = /* @__PURE__ */ new Map();
1976
+ for (let i = 0; i < bodySignals.length; i += 1) {
1977
+ const root = find(i);
1978
+ const bucket = byRoot.get(root) ?? [];
1979
+ bucket.push(bodySignals[i]);
1980
+ byRoot.set(root, bucket);
1981
+ }
1982
+ return [...byRoot.values(), ...others.map((s) => [s])];
1983
+ }
1984
+ function rangesOverlap(a, b) {
1985
+ return a.end > b.start && b.end > a.start;
1986
+ }
1987
+ function everyCandidateIsExternalUrl(cluster) {
1988
+ for (const signal of cluster) {
1989
+ const winnerIndex = signal.resolution?.winnerIndex ?? 0;
1990
+ const winner = signal.candidates[winnerIndex];
1991
+ if (!winner) return false;
1992
+ if (!isExternalUrl(winner.target)) return false;
1993
+ }
1994
+ return true;
1995
+ }
1996
+ function isExternalUrl(target) {
1997
+ return target.startsWith("http://") || target.startsWith("https://");
1998
+ }
1999
+ function resolveCluster(cluster, kindPriority, extractorRank) {
2000
+ let winnerIdx = 0;
2001
+ for (let i = 1; i < cluster.length; i += 1) {
2002
+ const result = compareClusterMembers(cluster[i], cluster[winnerIdx], kindPriority, extractorRank);
2003
+ if (result.winner === "challenger") winnerIdx = i;
2004
+ }
2005
+ const winner = cluster[winnerIdx];
2006
+ const winnerCandidate = winner.candidates[winner.resolution?.winnerIndex ?? 0];
2007
+ for (let i = 0; i < cluster.length; i += 1) {
2008
+ if (i === winnerIdx) continue;
2009
+ const loser = cluster[i];
2010
+ loser.resolution = {
2011
+ outcome: "rejected",
2012
+ rejectedBy: {
2013
+ source: winner.source,
2014
+ range: winner.range,
2015
+ extractorId: winnerCandidate.extractorId,
2016
+ reason: whyLost(loser, winner, kindPriority, extractorRank)
2017
+ }
2018
+ };
2019
+ }
2020
+ }
2021
+ function compareClusterMembers(challenger, champion, kindPriority, extractorRank) {
2022
+ const cWinner = challenger.candidates[challenger.resolution?.winnerIndex ?? 0];
2023
+ const xWinner = champion.candidates[champion.resolution?.winnerIndex ?? 0];
2024
+ const kindCmp = compareKindPriority(cWinner.kind, xWinner.kind, kindPriority);
2025
+ if (kindCmp < 0) return { winner: "challenger", reason: "kind-priority" };
2026
+ if (kindCmp > 0) return { winner: "champion", reason: "kind-priority" };
2027
+ if (cWinner.confidence !== xWinner.confidence) {
2028
+ return cWinner.confidence > xWinner.confidence ? { winner: "challenger", reason: "higher-confidence" } : { winner: "champion", reason: "higher-confidence" };
2029
+ }
2030
+ const cLen = rangeLength(challenger.range);
2031
+ const xLen = rangeLength(champion.range);
2032
+ if (cLen !== xLen) {
2033
+ return cLen > xLen ? { winner: "challenger", reason: "longer-range" } : { winner: "champion", reason: "longer-range" };
2034
+ }
2035
+ const cRank = extractorRank.get(cWinner.extractorId) ?? Number.MAX_SAFE_INTEGER;
2036
+ const xRank = extractorRank.get(xWinner.extractorId) ?? Number.MAX_SAFE_INTEGER;
2037
+ if (cRank !== xRank) {
2038
+ return cRank < xRank ? { winner: "challenger", reason: "earlier-declaration" } : { winner: "champion", reason: "earlier-declaration" };
2039
+ }
2040
+ return { winner: "tie", reason: "earlier-declaration" };
2041
+ }
2042
+ function rangeLength(range) {
2043
+ if (!range) return 0;
2044
+ return range.end - range.start;
2045
+ }
2046
+ function whyLost(loser, winner, kindPriority, extractorRank) {
2047
+ return compareClusterMembers(winner, loser, kindPriority, extractorRank).reason;
2048
+ }
2049
+ function materialise(signal, winner) {
2050
+ const link = {
2051
+ source: signal.source,
2052
+ target: winner.target,
2053
+ kind: winner.kind,
2054
+ confidence: winner.confidence,
2055
+ sources: [winner.extractorId],
2056
+ raw: signal.raw
2057
+ };
2058
+ if (winner.trigger) link.trigger = winner.trigger;
2059
+ if (signal.range) {
2060
+ link.location = { line: signal.range.line ?? 1, offset: signal.range.start };
2061
+ }
2062
+ const occurrenceTrigger = winner.trigger?.originalTrigger ?? signal.raw;
2063
+ const occurrenceLocation = signal.range ? { line: signal.range.line ?? 1 } : null;
2064
+ link.occurrences = [
2065
+ {
2066
+ extractor: winner.extractorId,
2067
+ originalTrigger: occurrenceTrigger,
2068
+ location: occurrenceLocation
2069
+ }
2070
+ ];
2071
+ return link;
2072
+ }
2073
+
1863
2074
  // kernel/orchestrator/renames.ts
1864
2075
  function findHighConfidenceRenames(opts) {
1865
2076
  const ops = [];
@@ -2632,7 +2843,12 @@ async function walkAndExtract(opts) {
2632
2843
  const walkOptions = opts.ignoreFilter ? { ignoreFilter: opts.ignoreFilter } : {};
2633
2844
  let filesWalked = 0;
2634
2845
  let index = 0;
2635
- for (const provider of opts.providers) {
2846
+ const activeProviders = opts.providers.filter((provider) => {
2847
+ if (!provider.gatedByActiveLens) return true;
2848
+ if (opts.activeProvider === null) return true;
2849
+ return provider.id === opts.activeProvider;
2850
+ });
2851
+ for (const provider of activeProviders) {
2636
2852
  for await (const raw of resolveProviderWalk(provider)(opts.roots, walkOptions)) {
2637
2853
  filesWalked += 1;
2638
2854
  if (claimedPaths.has(raw.path)) continue;
@@ -2653,7 +2869,8 @@ async function walkAndExtract(opts) {
2653
2869
  contributions: accum.contributionsBuffer,
2654
2870
  freshlyRunTuples: accum.freshlyRunTuples,
2655
2871
  orphanSidecars,
2656
- sidecarRoots: accum.sidecarRoots
2872
+ sidecarRoots: accum.sidecarRoots,
2873
+ signals: accum.signals
2657
2874
  };
2658
2875
  }
2659
2876
  function createWalkAccumulators() {
@@ -2661,6 +2878,7 @@ function createWalkAccumulators() {
2661
2878
  nodes: [],
2662
2879
  internalLinks: [],
2663
2880
  externalLinks: [],
2881
+ signals: [],
2664
2882
  cachedPaths: /* @__PURE__ */ new Set(),
2665
2883
  frontmatterIssues: [],
2666
2884
  enrichmentBuffer: /* @__PURE__ */ new Map(),
@@ -2806,6 +3024,7 @@ function recordFreshlyRunTuples(extractors, nodePath, accum) {
2806
3024
  function mergeExtractResult(extractResult, accum) {
2807
3025
  for (const link of extractResult.internalLinks) accum.internalLinks.push(link);
2808
3026
  for (const link of extractResult.externalLinks) accum.externalLinks.push(link);
3027
+ for (const signal of extractResult.signals) accum.signals.push(signal);
2809
3028
  for (const enr of extractResult.enrichments) {
2810
3029
  accum.enrichmentBuffer.set(`${enr.nodePath}\0${enr.extractorId}`, enr);
2811
3030
  }
@@ -2908,6 +3127,7 @@ async function runScanInternal(_kernel, options) {
2908
3127
  const scanStartedEvent = makeEvent("scan.started", { roots: options.roots });
2909
3128
  emitter.emit(scanStartedEvent);
2910
3129
  await hookDispatcher.dispatch("scan.started", scanStartedEvent);
3130
+ const activeProviderId = resolveActiveProviderOption(options.activeProvider, options.roots);
2911
3131
  const walked = await walkAndExtract({
2912
3132
  providers: exts.providers,
2913
3133
  extractors: exts.extractors,
@@ -2922,9 +3142,20 @@ async function runScanInternal(_kernel, options) {
2922
3142
  priorExtractorRuns: setup.priorExtractorRuns,
2923
3143
  providerFrontmatter: setup.providerFrontmatter,
2924
3144
  pluginStores: options.pluginStores,
2925
- activeProvider: resolveActiveProviderOption(options.activeProvider, options.roots)
3145
+ activeProvider: activeProviderId
3146
+ });
3147
+ const activeProvider = activeProviderId ? exts.providers.find((p) => p.id === activeProviderId) ?? null : null;
3148
+ const resolved = resolveSignals({
3149
+ signals: walked.signals,
3150
+ activeProvider,
3151
+ extractorOrder: exts.extractors.map((e) => e.id)
2926
3152
  });
2927
- const postWalkCtx = buildPostWalkTransformCtx(_kernel, walked.nodes);
3153
+ for (const link of resolved.links) {
3154
+ if (isExternalUrlLink(link)) walked.externalLinks.push(link);
3155
+ else walked.internalLinks.push(link);
3156
+ }
3157
+ walked.signals = resolved.resolvedSignals;
3158
+ const postWalkCtx = buildPostWalkTransformCtx(exts.providers, walked.nodes);
2928
3159
  walked.internalLinks = applyPostWalkTransforms(walked.internalLinks, walked.nodes, postWalkCtx);
2929
3160
  recomputeLinkCounts(walked.nodes, walked.internalLinks);
2930
3161
  recomputeExternalRefsCount(walked.nodes, walked.externalLinks, walked.cachedPaths);
@@ -2946,7 +3177,8 @@ async function runScanInternal(_kernel, options) {
2946
3177
  registeredActionIds,
2947
3178
  emitter,
2948
3179
  hookDispatcher,
2949
- postWalkCtx.reservedNodePaths
3180
+ postWalkCtx.reservedNodePaths,
3181
+ walked.signals
2950
3182
  );
2951
3183
  mergeAnalyzerEmissions(walked, analyzerResult, exts.analyzers);
2952
3184
  const issues = analyzerResult.issues;
@@ -2959,8 +3191,8 @@ async function runScanInternal(_kernel, options) {
2959
3191
  await hookDispatcher.dispatch("scan.completed", scanCompletedEvent);
2960
3192
  return buildScanReturn(walked, issues, renameOps, stats, options, setup);
2961
3193
  }
2962
- function buildPostWalkTransformCtx(kernel, nodes) {
2963
- const { kindRegistry, providerResolution, reservedNamesByProviderKind } = buildProviderIndexes(kernel);
3194
+ function buildPostWalkTransformCtx(providers, nodes) {
3195
+ const { kindRegistry, providerResolution, reservedNamesByProviderKind } = buildProviderIndexes(providers);
2964
3196
  const reservedNodePaths = buildReservedNodePaths(
2965
3197
  nodes,
2966
3198
  kindRegistry,
@@ -2968,11 +3200,10 @@ function buildPostWalkTransformCtx(kernel, nodes) {
2968
3200
  );
2969
3201
  return { kindRegistry, providerResolution, reservedNodePaths };
2970
3202
  }
2971
- function buildProviderIndexes(kernel) {
3203
+ function buildProviderIndexes(providers) {
2972
3204
  const kindRegistry = /* @__PURE__ */ new Map();
2973
3205
  const providerResolution = /* @__PURE__ */ new Map();
2974
3206
  const reservedNamesByProviderKind = /* @__PURE__ */ new Map();
2975
- const providers = kernel.registry.all("provider");
2976
3207
  for (const provider of providers) {
2977
3208
  if (provider.kinds) {
2978
3209
  for (const [kindName, descriptor] of Object.entries(provider.kinds)) {