@skill-map/cli 0.27.0 → 0.29.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.
Files changed (36) hide show
  1. package/dist/cli/tutorial/sm-master.md +181 -97
  2. package/dist/cli/tutorial/sm-tutorial.md +94 -20
  3. package/dist/cli.js +1422 -1194
  4. package/dist/cli.js.map +1 -1
  5. package/dist/index.js +116 -99
  6. package/dist/index.js.map +1 -1
  7. package/dist/kernel/index.d.ts +903 -1004
  8. package/dist/kernel/index.js +116 -99
  9. package/dist/kernel/index.js.map +1 -1
  10. package/dist/ui/chunk-3SI3TVER.js +7 -0
  11. package/dist/ui/{chunk-4GTCV7V4.js → chunk-47OZB7LR.js} +1 -1
  12. package/dist/ui/{chunk-JMP2LDMI.js → chunk-5JBW2LUN.js} +1 -1
  13. package/dist/ui/chunk-BL7KARTN.js +317 -0
  14. package/dist/ui/chunk-DMSZOXER.js +1 -0
  15. package/dist/ui/{chunk-Y7MXGXU3.js → chunk-DZBSELHN.js} +1 -1
  16. package/dist/ui/chunk-EFKSD7PT.js +123 -0
  17. package/dist/ui/{chunk-Z2667C3S.js → chunk-FEPH4VNB.js} +1 -1
  18. package/dist/ui/{chunk-PY2R7LHN.js → chunk-FQOZBFJ5.js} +1 -1
  19. package/dist/ui/{chunk-WOLLYGGL.js → chunk-KJQEO6P3.js} +1 -1
  20. package/dist/ui/{chunk-VO6NF24F.js → chunk-LS2NXZQZ.js} +1 -1
  21. package/dist/ui/{chunk-J3YWUNFO.js → chunk-LTQTJU54.js} +1 -1
  22. package/dist/ui/{chunk-6BG7PBUN.js → chunk-NGIFGXW7.js} +1 -1
  23. package/dist/ui/{chunk-5W6J6H76.js → chunk-SBCO7ZSP.js} +1 -1
  24. package/dist/ui/chunk-VB56BUGO.js +1 -0
  25. package/dist/ui/{chunk-UXCAEDR6.js → chunk-VDQLDTTR.js} +1 -1
  26. package/dist/ui/{chunk-AD7RBRD3.js → chunk-WJLIYGWJ.js} +5 -5
  27. package/dist/ui/index.html +2 -2
  28. package/dist/ui/{main-LM44IIOO.js → main-LGW7AYEA.js} +2 -2
  29. package/dist/ui/skill-map-mark-matrix.svg +8 -0
  30. package/dist/ui/{styles-EGXMA46P.css → styles-CDN434T2.css} +1 -1
  31. package/package.json +10 -7
  32. package/dist/ui/chunk-H2J55DNK.js +0 -7
  33. package/dist/ui/chunk-LTSP2F6C.js +0 -123
  34. package/dist/ui/chunk-Q7L6LLAK.js +0 -1
  35. package/dist/ui/chunk-UAG2DUVV.js +0 -1
  36. package/dist/ui/chunk-VH5GRUT7.js +0 -255
@@ -93,14 +93,14 @@ var Registry = class {
93
93
  };
94
94
 
95
95
  // kernel/orchestrator/index.ts
96
- import { existsSync as existsSync9, statSync as statSync2 } from "fs";
96
+ import { existsSync as existsSync10, statSync as statSync4 } from "fs";
97
97
  import { Tiktoken as Tiktoken2 } from "js-tiktoken/lite";
98
98
  import cl100k_base from "js-tiktoken/ranks/cl100k_base";
99
99
 
100
100
  // package.json
101
101
  var package_default = {
102
102
  name: "@skill-map/cli",
103
- version: "0.27.0",
103
+ version: "0.29.0",
104
104
  description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
105
105
  license: "MIT",
106
106
  type: "module",
@@ -153,16 +153,19 @@ var package_default = {
153
153
  "lint:fix": "eslint . --fix",
154
154
  reference: "node scripts/build-reference.js",
155
155
  "reference:check": "node scripts/build-reference.js --check",
156
+ "build-built-ins": "node ../scripts/generate-built-ins.js",
157
+ "built-ins:check": "node ../scripts/generate-built-ins.js --check",
158
+ prebuild: "pnpm build-built-ins",
156
159
  validate: "pnpm validate:compile && pnpm validate:test",
157
- "validate:compile": "pnpm typecheck && pnpm lint && pnpm build && pnpm reference:check",
160
+ "validate:compile": "pnpm typecheck && pnpm lint && pnpm build && pnpm reference:check && pnpm built-ins:check",
158
161
  "validate:test": "pnpm test:ci",
159
162
  pretest: "tsup",
160
163
  "pretest:coverage": "tsup",
161
164
  "pretest:coverage:html": "tsup",
162
- test: "tsc --noEmit && node --import tsx --test --test-reporter=spec 'test/**/*.test.ts' 'built-in-plugins/**/*.test.ts' 'kernel/**/*.test.ts' 'server/**/*.test.ts'",
163
- "test:ci": "node --import tsx --test 'test/**/*.test.ts' 'built-in-plugins/**/*.test.ts' 'kernel/**/*.test.ts' 'server/**/*.test.ts'",
164
- "test:coverage": "tsc --noEmit && SKILL_MAP_SKIP_BENCHMARK=1 node --experimental-default-config-file --import tsx --test --experimental-test-coverage 'test/**/*.test.ts' 'built-in-plugins/**/*.test.ts' 'kernel/**/*.test.ts' 'server/**/*.test.ts'",
165
- "test:coverage:html": "tsc --noEmit && SKILL_MAP_SKIP_BENCHMARK=1 c8 node --import tsx --test 'test/**/*.test.ts' 'built-in-plugins/**/*.test.ts' 'kernel/**/*.test.ts' 'server/**/*.test.ts'",
165
+ test: "tsc --noEmit && node --import tsx --test --test-reporter=spec '__tests__/**/*.spec.ts' 'kernel/**/__tests__/**/*.spec.ts' 'cli/**/__tests__/**/*.spec.ts' 'server/**/__tests__/**/*.spec.ts' 'plugins/**/__tests__/**/*.spec.ts' 'core/**/__tests__/**/*.spec.ts' 'conformance/**/__tests__/**/*.spec.ts'",
166
+ "test:ci": "node --import tsx --test '__tests__/**/*.spec.ts' 'kernel/**/__tests__/**/*.spec.ts' 'cli/**/__tests__/**/*.spec.ts' 'server/**/__tests__/**/*.spec.ts' 'plugins/**/__tests__/**/*.spec.ts' 'core/**/__tests__/**/*.spec.ts' 'conformance/**/__tests__/**/*.spec.ts'",
167
+ "test:coverage": "tsc --noEmit && SKILL_MAP_SKIP_BENCHMARK=1 node --experimental-default-config-file --import tsx --test --experimental-test-coverage '__tests__/**/*.spec.ts' 'kernel/**/__tests__/**/*.spec.ts' 'cli/**/__tests__/**/*.spec.ts' 'server/**/__tests__/**/*.spec.ts' 'plugins/**/__tests__/**/*.spec.ts' 'core/**/__tests__/**/*.spec.ts' 'conformance/**/__tests__/**/*.spec.ts'",
168
+ "test:coverage:html": "tsc --noEmit && SKILL_MAP_SKIP_BENCHMARK=1 c8 node --import tsx --test '__tests__/**/*.spec.ts' 'kernel/**/__tests__/**/*.spec.ts' 'cli/**/__tests__/**/*.spec.ts' 'server/**/__tests__/**/*.spec.ts' 'plugins/**/__tests__/**/*.spec.ts' 'core/**/__tests__/**/*.spec.ts' 'conformance/**/__tests__/**/*.spec.ts'",
166
169
  clean: "rm -rf dist coverage"
167
170
  },
168
171
  dependencies: {
@@ -220,8 +223,8 @@ var InMemoryProgressEmitter = class {
220
223
 
221
224
  // kernel/adapters/plugin-loader/index.ts
222
225
  import { createRequire } from "module";
223
- import { existsSync, readFileSync as readFileSync2, readdirSync } from "fs";
224
- import { join, resolve as resolve3 } from "path";
226
+ import { existsSync as existsSync2, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
227
+ import { join as join2, resolve as resolve3 } from "path";
225
228
  import { pathToFileURL } from "url";
226
229
  import semver from "semver";
227
230
 
@@ -229,6 +232,9 @@ import semver from "semver";
229
232
  import { isAbsolute, relative, resolve } from "path";
230
233
 
231
234
  // kernel/adapters/plugin-loader/validation.ts
235
+ import * as nodeFs from "fs";
236
+ import { existsSync } from "fs";
237
+ import { dirname, join } from "path";
232
238
  import { Ajv2020 } from "ajv/dist/2020.js";
233
239
 
234
240
  // kernel/util/ajv-interop.ts
@@ -265,7 +271,7 @@ var KNOWN_KINDS_LIST = [...KNOWN_KINDS].join(" / ");
265
271
  var HOOKABLE_TRIGGERS_LIST = HOOK_TRIGGERS.join(", ");
266
272
 
267
273
  // kernel/adapters/plugin-loader/storage-schemas.ts
268
- import { readFileSync } from "fs";
274
+ import { readFileSync as readFileSync2 } from "fs";
269
275
  import { resolve as resolve2 } from "path";
270
276
  import { Ajv2020 as Ajv20202 } from "ajv/dist/2020.js";
271
277
 
@@ -326,7 +332,7 @@ function makePluginStore(opts) {
326
332
  if (!opts.persistKv) return void 0;
327
333
  const schema = storageSchemas?.[KV_SCHEMA_KEY];
328
334
  return makeKvStoreWrapper({
329
- pluginId: manifest.id,
335
+ pluginId: opts.plugin.id,
330
336
  schema,
331
337
  persist: opts.persistKv
332
338
  });
@@ -334,7 +340,7 @@ function makePluginStore(opts) {
334
340
  if (manifest.storage.mode === "dedicated") {
335
341
  if (!opts.persistDedicated) return void 0;
336
342
  return makeDedicatedStoreWrapper({
337
- pluginId: manifest.id,
343
+ pluginId: opts.plugin.id,
338
344
  schemas: storageSchemas,
339
345
  persist: opts.persistDedicated
340
346
  });
@@ -351,13 +357,13 @@ function installedSpecVersion() {
351
357
  const require2 = createRequire(import.meta.url);
352
358
  const indexPath = require2.resolve("@skill-map/spec/index.json");
353
359
  const pkgPath = resolve3(indexPath, "..", "package.json");
354
- const pkg = JSON.parse(readFileSync2(pkgPath, "utf8"));
360
+ const pkg = JSON.parse(readFileSync3(pkgPath, "utf8"));
355
361
  return pkg.version;
356
362
  }
357
363
 
358
364
  // kernel/adapters/schema-validators.ts
359
- import { readFileSync as readFileSync3 } from "fs";
360
- import { dirname, resolve as resolve4 } from "path";
365
+ import { readFileSync as readFileSync4 } from "fs";
366
+ import { dirname as dirname2, resolve as resolve4 } from "path";
361
367
  import { createRequire as createRequire2 } from "module";
362
368
  import { Ajv2020 as Ajv20203 } from "ajv/dist/2020.js";
363
369
 
@@ -395,6 +401,7 @@ var SCHEMA_FILES = {
395
401
  "conformance-case": "schemas/conformance-case.schema.json",
396
402
  "history-stats": "schemas/history-stats.schema.json",
397
403
  "extension-provider": "schemas/extensions/provider.schema.json",
404
+ "extension-provider-kind": "schemas/extensions/provider-kind.schema.json",
398
405
  "extension-extractor": "schemas/extensions/extractor.schema.json",
399
406
  "extension-analyzer": "schemas/extensions/analyzer.schema.json",
400
407
  "extension-action": "schemas/extensions/action.schema.json",
@@ -426,13 +433,13 @@ function buildSchemaValidators() {
426
433
  for (const rel of SUPPORTING_SCHEMAS) {
427
434
  const file = resolve4(specRoot, rel);
428
435
  if (!existsSyncSafe(file)) continue;
429
- const schema = JSON.parse(readFileSync3(file, "utf8"));
436
+ const schema = JSON.parse(readFileSync4(file, "utf8"));
430
437
  ajv.addSchema(schema);
431
438
  }
432
439
  const validators = /* @__PURE__ */ new Map();
433
440
  for (const [name, rel] of Object.entries(SCHEMA_FILES)) {
434
441
  const file = resolve4(specRoot, rel);
435
- const schema = JSON.parse(readFileSync3(file, "utf8"));
442
+ const schema = JSON.parse(readFileSync4(file, "utf8"));
436
443
  const byId = typeof schema.$id === "string" ? ajv.getSchema(schema.$id) : void 0;
437
444
  validators.set(name, byId ?? ajv.compile(schema));
438
445
  }
@@ -504,7 +511,7 @@ function buildProviderFrontmatterValidator(providers) {
504
511
  });
505
512
  applyAjvFormats(ajv);
506
513
  const baseFile = resolve4(specRoot, "schemas/frontmatter/base.schema.json");
507
- const baseSchema = JSON.parse(readFileSync3(baseFile, "utf8"));
514
+ const baseSchema = JSON.parse(readFileSync4(baseFile, "utf8"));
508
515
  ajv.addSchema(baseSchema);
509
516
  registerProviderAuxiliarySchemas(ajv, providers);
510
517
  const compiled = /* @__PURE__ */ new Map();
@@ -545,7 +552,7 @@ function resolveSpecRoot() {
545
552
  const require2 = createRequire2(import.meta.url);
546
553
  try {
547
554
  const indexPath = require2.resolve("@skill-map/spec/index.json");
548
- return dirname(indexPath);
555
+ return dirname2(indexPath);
549
556
  } catch {
550
557
  throw new Error(
551
558
  "@skill-map/spec not resolvable: ensure the workspace is linked or the package is installed."
@@ -554,7 +561,7 @@ function resolveSpecRoot() {
554
561
  }
555
562
  function existsSyncSafe(path) {
556
563
  try {
557
- readFileSync3(path, "utf8");
564
+ readFileSync4(path, "utf8");
558
565
  return true;
559
566
  } catch {
560
567
  return false;
@@ -607,14 +614,6 @@ function makeHookDispatcher(hooks, emitter) {
607
614
  }
608
615
  const byTrigger = /* @__PURE__ */ new Map();
609
616
  for (const hook of hooks) {
610
- if (hook.mode === "probabilistic") {
611
- const qualifiedId = qualifiedExtensionId(hook.pluginId, hook.id);
612
- log.warn(
613
- `Probabilistic hook ${qualifiedId} deferred to job subsystem (future job subsystem). The hook is registered but will not dispatch in-scan.`,
614
- { hookId: qualifiedId, mode: "probabilistic" }
615
- );
616
- continue;
617
- }
618
617
  for (const trig of hook.triggers) {
619
618
  const bucket = byTrigger.get(trig);
620
619
  if (bucket) bucket.push(hook);
@@ -792,7 +791,7 @@ async function runExtractorsForNode(opts) {
792
791
  }
793
792
  function readDeclaredContributions(extension) {
794
793
  const out = /* @__PURE__ */ new Map();
795
- const raw = extension.viewContributions;
794
+ const raw = extension.ui;
796
795
  if (typeof raw !== "object" || raw === null) return out;
797
796
  for (const [id, value] of Object.entries(raw)) {
798
797
  if (typeof value !== "object" || value === null) continue;
@@ -813,11 +812,13 @@ function emitExtensionError(emitter, qualifiedId, nodePath, data) {
813
812
  );
814
813
  }
815
814
  function buildExtractorContext(extractor, node, body, frontmatter, emitLink, enrichNode, emitContribution, store) {
816
- const scope = extractor.scope;
815
+ const scope = extractor.scope ?? "both";
816
+ const settings = extractor.resolvedSettings ?? {};
817
817
  return {
818
818
  node,
819
819
  body: scope === "frontmatter" ? "" : body,
820
820
  frontmatter: scope === "body" ? {} : frontmatter,
821
+ settings,
821
822
  emitLink,
822
823
  enrichNode,
823
824
  emitContribution,
@@ -825,25 +826,26 @@ function buildExtractorContext(extractor, node, body, frontmatter, emitLink, enr
825
826
  };
826
827
  }
827
828
  function validateLink(extractor, link, emitter) {
828
- if (!extractor.emitsLinkKinds.includes(link.kind)) {
829
+ const knownKinds = ["invokes", "references", "mentions", "supersedes"];
830
+ if (!knownKinds.includes(link.kind)) {
829
831
  const qualifiedId = `${extractor.pluginId}/${extractor.id}`;
830
832
  emitter.emit(
831
833
  makeEvent("extension.error", {
832
834
  kind: "link-kind-not-declared",
833
835
  extensionId: qualifiedId,
834
836
  linkKind: link.kind,
835
- declaredKinds: extractor.emitsLinkKinds,
837
+ declaredKinds: knownKinds,
836
838
  link: { source: link.source, target: link.target, kind: link.kind },
837
839
  message: tx(ORCHESTRATOR_TEXTS.extensionErrorLinkKindNotDeclared, {
838
840
  extractorId: qualifiedId,
839
841
  linkKind: link.kind,
840
- declaredKinds: extractor.emitsLinkKinds.join(", ")
842
+ declaredKinds: knownKinds.join(", ")
841
843
  })
842
844
  })
843
845
  );
844
846
  return null;
845
847
  }
846
- const confidence = link.confidence ?? extractor.defaultConfidence;
848
+ const confidence = link.confidence ?? "medium";
847
849
  return { ...link, confidence };
848
850
  }
849
851
  function dedupeLinks(links) {
@@ -901,7 +903,7 @@ async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sid
901
903
  const issues = [];
902
904
  const contributions = [];
903
905
  const validators = loadSchemaValidators();
904
- validateRecommendedActions(analyzers, registeredActionIds, emitter);
906
+ void registeredActionIds;
905
907
  const analyzerOrphans = orphanSidecars.map((o) => ({
906
908
  relativePath: o.relativePath,
907
909
  expectedMdPath: o.expectedMdPath
@@ -973,27 +975,6 @@ async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sid
973
975
  }
974
976
  return { issues, contributions };
975
977
  }
976
- function validateRecommendedActions(analyzers, registeredActionIds, emitter) {
977
- for (const analyzer of analyzers) {
978
- const refs = analyzer.recommendedActions;
979
- if (refs === void 0 || refs.length === 0) continue;
980
- const analyzerId = qualifiedExtensionId(analyzer.pluginId, analyzer.id);
981
- for (const actionId of refs) {
982
- if (registeredActionIds.has(actionId)) continue;
983
- emitter.emit(
984
- makeEvent("extension.error", {
985
- kind: "recommended-action-missing",
986
- extensionId: analyzerId,
987
- actionId,
988
- message: tx(ORCHESTRATOR_TEXTS.extensionErrorRecommendedActionMissing, {
989
- analyzerId,
990
- actionId
991
- })
992
- })
993
- );
994
- }
995
- }
996
- }
997
978
  function validateIssue(analyzer, issue, emitter) {
998
979
  const severity = issue.severity;
999
980
  if (severity !== "error" && severity !== "warn" && severity !== "info") {
@@ -1071,9 +1052,15 @@ function originatingNodeOf(link, priorNodePaths) {
1071
1052
  return link.source;
1072
1053
  }
1073
1054
  function computeCacheDecision(opts) {
1074
- const applicableExtractors = opts.extractors.filter(
1075
- (ex) => ex.applicableKinds === void 0 || ex.applicableKinds.includes(opts.kind)
1076
- );
1055
+ const applicableExtractors = opts.extractors.filter((ex) => {
1056
+ const kinds = ex.precondition?.kind;
1057
+ if (!kinds || kinds.length === 0) return true;
1058
+ return kinds.some((qualified) => {
1059
+ const slashIdx = qualified.indexOf("/");
1060
+ const kindOnly = slashIdx === -1 ? qualified : qualified.slice(slashIdx + 1);
1061
+ return kindOnly === opts.kind;
1062
+ });
1063
+ });
1077
1064
  const applicableQualifiedIds = new Set(
1078
1065
  applicableExtractors.map((ex) => qualifiedExtensionId(ex.pluginId, ex.id))
1079
1066
  );
@@ -1264,6 +1251,7 @@ function flagAmbiguousRenames(opts) {
1264
1251
  function flagOrphans(opts) {
1265
1252
  for (const fromPath of opts.deletedPaths) {
1266
1253
  if (opts.claimedDeleted.has(fromPath)) continue;
1254
+ if (opts.silenced?.(fromPath)) continue;
1267
1255
  opts.issues.push({
1268
1256
  analyzerId: "orphan",
1269
1257
  severity: "info",
@@ -1273,7 +1261,7 @@ function flagOrphans(opts) {
1273
1261
  });
1274
1262
  }
1275
1263
  }
1276
- function detectRenamesAndOrphans(prior, current, issues) {
1264
+ function detectRenamesAndOrphans(prior, current, issues, silenced) {
1277
1265
  const priorByPath = /* @__PURE__ */ new Map();
1278
1266
  for (const n of prior.nodes) priorByPath.set(n.path, n);
1279
1267
  const currentByPath = /* @__PURE__ */ new Map();
@@ -1307,17 +1295,22 @@ function detectRenamesAndOrphans(prior, current, issues) {
1307
1295
  issues
1308
1296
  }));
1309
1297
  flagAmbiguousRenames({ newPaths, candidatesByNew, claimedDeleted, claimedNew, issues });
1310
- flagOrphans({ deletedPaths, claimedDeleted, issues });
1298
+ flagOrphans({
1299
+ deletedPaths,
1300
+ claimedDeleted,
1301
+ issues,
1302
+ ...silenced ? { silenced } : {}
1303
+ });
1311
1304
  return ops;
1312
1305
  }
1313
1306
 
1314
1307
  // kernel/scan/walk-content.ts
1315
1308
  import { readFile, readdir, lstat } from "fs/promises";
1316
- import { join as join2, relative as relative2, sep } from "path";
1309
+ import { join as join3, relative as relative2, sep } from "path";
1317
1310
 
1318
1311
  // kernel/scan/ignore.ts
1319
- import { existsSync as existsSync2, readFileSync as readFileSync4 } from "fs";
1320
- import { dirname as dirname2, resolve as resolve5 } from "path";
1312
+ import { existsSync as existsSync3, readFileSync as readFileSync5 } from "fs";
1313
+ import { dirname as dirname3, resolve as resolve5 } from "path";
1321
1314
  import { fileURLToPath } from "url";
1322
1315
  import ignoreFactory from "ignore";
1323
1316
  function buildIgnoreFilter(opts = {}) {
@@ -1349,7 +1342,7 @@ function loadDefaultsText() {
1349
1342
  return cachedDefaults;
1350
1343
  }
1351
1344
  function readDefaultsFromDisk() {
1352
- const here = dirname2(fileURLToPath(import.meta.url));
1345
+ const here = dirname3(fileURLToPath(import.meta.url));
1353
1346
  const candidates = [
1354
1347
  resolve5(here, "../../config/defaults/skillmapignore"),
1355
1348
  // src/kernel/scan/ → src/config/defaults/
@@ -1358,9 +1351,9 @@ function readDefaultsFromDisk() {
1358
1351
  resolve5(here, "config/defaults/skillmapignore")
1359
1352
  ];
1360
1353
  for (const candidate of candidates) {
1361
- if (existsSync2(candidate)) {
1354
+ if (existsSync3(candidate)) {
1362
1355
  try {
1363
- return readFileSync4(candidate, "utf8");
1356
+ return readFileSync5(candidate, "utf8");
1364
1357
  } catch {
1365
1358
  }
1366
1359
  }
@@ -1368,7 +1361,7 @@ function readDefaultsFromDisk() {
1368
1361
  return "";
1369
1362
  }
1370
1363
 
1371
- // built-in-plugins/parsers/frontmatter-yaml/index.ts
1364
+ // plugins/core/parsers/frontmatter-yaml/index.ts
1372
1365
  import yaml from "js-yaml";
1373
1366
 
1374
1367
  // kernel/util/strip-prototype-pollution.ts
@@ -1392,7 +1385,7 @@ function strip(value) {
1392
1385
  return out;
1393
1386
  }
1394
1387
 
1395
- // built-in-plugins/parsers/frontmatter-yaml/index.ts
1388
+ // plugins/core/parsers/frontmatter-yaml/index.ts
1396
1389
  var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
1397
1390
  var frontmatterYamlParser = {
1398
1391
  id: "frontmatter-yaml",
@@ -1426,7 +1419,7 @@ function sanitiseParseErrorMessage(err) {
1426
1419
  return raw.replace(/[-]+/g, " ").replace(/\s+/g, " ").trim();
1427
1420
  }
1428
1421
 
1429
- // built-in-plugins/parsers/plain/index.ts
1422
+ // plugins/core/parsers/plain/index.ts
1430
1423
  var plainParser = {
1431
1424
  id: "plain",
1432
1425
  parse(raw, _path) {
@@ -1489,7 +1482,7 @@ async function* walkRoot(root, current, filter, extensions) {
1489
1482
  }
1490
1483
  for (const entry of entries) {
1491
1484
  const name = entry.name;
1492
- const full = join2(current, name);
1485
+ const full = join3(current, name);
1493
1486
  const rel = relative2(root, full).split(sep).join("/");
1494
1487
  if (filter.ignores(rel)) continue;
1495
1488
  if (entry.isSymbolicLink()) continue;
@@ -1533,19 +1526,19 @@ function resolveProviderWalk(provider) {
1533
1526
  }
1534
1527
 
1535
1528
  // kernel/sidecar/parse.ts
1536
- import { existsSync as existsSync3, readFileSync as readFileSync5 } from "fs";
1537
- import { dirname as dirname3, resolve as resolve6 } from "path";
1529
+ import { existsSync as existsSync4, readFileSync as readFileSync6 } from "fs";
1530
+ import { dirname as dirname4, resolve as resolve6 } from "path";
1538
1531
  import { createRequire as createRequire3 } from "module";
1539
1532
  import { Ajv2020 as Ajv20204 } from "ajv/dist/2020.js";
1540
1533
  import yaml2 from "js-yaml";
1541
1534
  function readSidecarFor(mdAbsolutePath) {
1542
1535
  const sidecarPath = sidecarPathFor(mdAbsolutePath);
1543
- if (!existsSync3(sidecarPath)) {
1536
+ if (!existsSync4(sidecarPath)) {
1544
1537
  return { parsed: null, present: false, issues: [] };
1545
1538
  }
1546
1539
  let raw;
1547
1540
  try {
1548
- raw = readFileSync5(sidecarPath, "utf8");
1541
+ raw = readFileSync6(sidecarPath, "utf8");
1549
1542
  } catch (err) {
1550
1543
  return {
1551
1544
  parsed: null,
@@ -1613,10 +1606,10 @@ function getSidecarValidator() {
1613
1606
  applyAjvFormats(ajv);
1614
1607
  const specRoot = resolveSpecRoot2();
1615
1608
  const annotationsSchema = JSON.parse(
1616
- readFileSync5(resolve6(specRoot, "schemas/annotations.schema.json"), "utf8")
1609
+ readFileSync6(resolve6(specRoot, "schemas/annotations.schema.json"), "utf8")
1617
1610
  );
1618
1611
  const sidecarSchema = JSON.parse(
1619
- readFileSync5(resolve6(specRoot, "schemas/sidecar.schema.json"), "utf8")
1612
+ readFileSync6(resolve6(specRoot, "schemas/sidecar.schema.json"), "utf8")
1620
1613
  );
1621
1614
  ajv.addSchema(annotationsSchema);
1622
1615
  cachedSidecarValidator = ajv.compile(sidecarSchema);
@@ -1626,7 +1619,7 @@ function resolveSpecRoot2() {
1626
1619
  const require2 = createRequire3(import.meta.url);
1627
1620
  try {
1628
1621
  const indexPath = require2.resolve("@skill-map/spec/index.json");
1629
- return dirname3(indexPath);
1622
+ return dirname4(indexPath);
1630
1623
  } catch {
1631
1624
  throw new Error(
1632
1625
  "@skill-map/spec not resolvable: sidecar reader cannot load schemas."
@@ -1645,8 +1638,8 @@ function computeDriftStatus(args) {
1645
1638
  }
1646
1639
 
1647
1640
  // kernel/sidecar/discover-orphans.ts
1648
- import { existsSync as existsSync4, readdirSync as readdirSync2, statSync } from "fs";
1649
- import { join as join3, relative as relative3, sep as sep2 } from "path";
1641
+ import { existsSync as existsSync5, readdirSync as readdirSync3, statSync as statSync3 } from "fs";
1642
+ import { join as join4, relative as relative3, sep as sep2 } from "path";
1650
1643
  function discoverOrphanSidecars(roots, shouldSkip) {
1651
1644
  const out = [];
1652
1645
  for (const root of roots) {
@@ -1657,12 +1650,12 @@ function discoverOrphanSidecars(roots, shouldSkip) {
1657
1650
  function walk(root, current, shouldSkip, out) {
1658
1651
  let entries;
1659
1652
  try {
1660
- entries = readdirSync2(current, { withFileTypes: true, encoding: "utf8" });
1653
+ entries = readdirSync3(current, { withFileTypes: true, encoding: "utf8" });
1661
1654
  } catch {
1662
1655
  return;
1663
1656
  }
1664
1657
  for (const entry of entries) {
1665
- const full = join3(current, entry.name);
1658
+ const full = join4(current, entry.name);
1666
1659
  const rel = relative3(root, full).split(sep2).join("/");
1667
1660
  if (shouldSkip(rel)) continue;
1668
1661
  if (entry.isSymbolicLink()) continue;
@@ -1673,21 +1666,21 @@ function walk(root, current, shouldSkip, out) {
1673
1666
  if (!entry.isFile()) continue;
1674
1667
  if (!entry.name.endsWith(".sm")) continue;
1675
1668
  const expectedMd = `${full.slice(0, -".sm".length)}.md`;
1676
- if (existsSync4(expectedMd) && safeIsFile(expectedMd)) continue;
1669
+ if (existsSync5(expectedMd) && safeIsFile(expectedMd)) continue;
1677
1670
  out.push({ sidecarPath: full, relativePath: rel, expectedMdPath: expectedMd });
1678
1671
  }
1679
1672
  }
1680
1673
  function safeIsFile(path) {
1681
1674
  try {
1682
- return statSync(path).isFile();
1675
+ return statSync3(path).isFile();
1683
1676
  } catch {
1684
1677
  return false;
1685
1678
  }
1686
1679
  }
1687
1680
 
1688
1681
  // kernel/sidecar/store.ts
1689
- import { existsSync as existsSync7, readFileSync as readFileSync8 } from "fs";
1690
- import { dirname as dirname5, resolve as resolve9 } from "path";
1682
+ import { existsSync as existsSync8, readFileSync as readFileSync9 } from "fs";
1683
+ import { dirname as dirname6, resolve as resolve9 } from "path";
1691
1684
  import { createRequire as createRequire4 } from "module";
1692
1685
  import { Ajv2020 as Ajv20205 } from "ajv/dist/2020.js";
1693
1686
  import yaml3 from "js-yaml";
@@ -1696,29 +1689,29 @@ import yaml3 from "js-yaml";
1696
1689
  import {
1697
1690
  closeSync,
1698
1691
  constants as fsConstants,
1699
- existsSync as existsSync5,
1692
+ existsSync as existsSync6,
1700
1693
  mkdirSync,
1701
1694
  openSync,
1702
- readFileSync as readFileSync6,
1695
+ readFileSync as readFileSync7,
1703
1696
  renameSync,
1704
1697
  unlinkSync,
1705
1698
  writeSync
1706
1699
  } from "fs";
1707
1700
  import { randomBytes } from "crypto";
1708
- import { dirname as dirname4 } from "path";
1701
+ import { dirname as dirname5 } from "path";
1709
1702
 
1710
1703
  // core/config/helper.ts
1711
1704
  import { homedir as osHomedir } from "os";
1712
- import { isAbsolute as isAbsolute2, join as join6, resolve as resolve8 } from "path";
1705
+ import { isAbsolute as isAbsolute2, join as join7, resolve as resolve8 } from "path";
1713
1706
 
1714
1707
  // kernel/config/loader.ts
1715
- import { existsSync as existsSync6, readFileSync as readFileSync7 } from "fs";
1708
+ import { existsSync as existsSync7, readFileSync as readFileSync8 } from "fs";
1716
1709
 
1717
1710
  // kernel/util/skill-map-paths.ts
1718
- import { join as join5 } from "path";
1711
+ import { join as join6 } from "path";
1719
1712
 
1720
1713
  // core/paths/db-path.ts
1721
- import { join as join4, resolve as resolve7 } from "path";
1714
+ import { join as join5, resolve as resolve7 } from "path";
1722
1715
  var SKILL_MAP_DIR = ".skill-map";
1723
1716
  var DB_FILENAME = "skill-map.db";
1724
1717
  var LOCAL_SETTINGS_FILENAME = "settings.local.json";
@@ -1730,7 +1723,7 @@ var GITIGNORE_ENTRIES = [
1730
1723
 
1731
1724
  // kernel/orchestrator/node-build.ts
1732
1725
  import { createHash } from "crypto";
1733
- import { existsSync as existsSync8 } from "fs";
1726
+ import { existsSync as existsSync9 } from "fs";
1734
1727
  import { isAbsolute as isAbsolute3, resolve as resolvePath } from "path";
1735
1728
  import "js-tiktoken/lite";
1736
1729
  import yaml4 from "js-yaml";
@@ -1894,11 +1887,11 @@ function resolveSidecarOverlay(relativePath, nodePathForIssue, roots, liveBodyHa
1894
1887
  }
1895
1888
  function resolveAbsoluteMdPath(relativePath, roots) {
1896
1889
  if (isAbsolute3(relativePath)) {
1897
- return existsSync8(relativePath) ? relativePath : null;
1890
+ return existsSync9(relativePath) ? relativePath : null;
1898
1891
  }
1899
1892
  for (const root of roots) {
1900
1893
  const candidate = resolvePath(root, relativePath);
1901
- if (existsSync8(candidate)) return candidate;
1894
+ if (existsSync9(candidate)) return candidate;
1902
1895
  }
1903
1896
  return null;
1904
1897
  }
@@ -2027,6 +2020,9 @@ function buildWalkContext(opts) {
2027
2020
  async function processRawNode(raw, provider, wctx, accum, claimedPaths, nextIndex) {
2028
2021
  const bodyHash = sha256(raw.body);
2029
2022
  const frontmatterHash = sha256(canonicalFrontmatter(raw.frontmatter, raw.frontmatterRaw));
2023
+ if (Array.isArray(provider.roots) && provider.roots.length > 0) {
2024
+ if (!matchesAnyRoot(raw.path, provider.roots)) return false;
2025
+ }
2030
2026
  const kind = provider.classify(raw.path, raw.frontmatter);
2031
2027
  if (kind === null) {
2032
2028
  return false;
@@ -2195,6 +2191,26 @@ function recordExtractorRuns(nodePath, ctx, accum) {
2195
2191
  });
2196
2192
  }
2197
2193
  }
2194
+ function matchesAnyRoot(relPath, roots) {
2195
+ for (const r of roots) {
2196
+ if (matchesOneRoot(relPath, r)) return true;
2197
+ }
2198
+ return false;
2199
+ }
2200
+ function matchesOneRoot(relPath, pattern) {
2201
+ if (pattern.endsWith("/**")) return matchesDeepGlob(relPath, pattern.slice(0, -3));
2202
+ if (pattern.endsWith("/*")) return matchesShallowGlob(relPath, pattern.slice(0, -2));
2203
+ return relPath === pattern;
2204
+ }
2205
+ function matchesDeepGlob(relPath, prefix) {
2206
+ if (prefix.length === 0) return true;
2207
+ return relPath === prefix || relPath.startsWith(`${prefix}/`);
2208
+ }
2209
+ function matchesShallowGlob(relPath, prefix) {
2210
+ if (!relPath.startsWith(`${prefix}/`)) return false;
2211
+ const tail = relPath.slice(prefix.length + 1);
2212
+ return tail.length > 0 && !tail.includes("/");
2213
+ }
2198
2214
 
2199
2215
  // kernel/orchestrator/index.ts
2200
2216
  var SCANNED_BY = {
@@ -2263,7 +2279,8 @@ async function runScanInternal(_kernel, options) {
2263
2279
  mergeAnalyzerEmissions(walked, analyzerResult, exts.analyzers);
2264
2280
  const issues = analyzerResult.issues;
2265
2281
  for (const issue of walked.frontmatterIssues) issues.push(issue);
2266
- const renameOps = prior ? detectRenamesAndOrphans(prior, walked.nodes, issues) : [];
2282
+ const silenced = options.ignoreFilter ? (path) => options.ignoreFilter.ignores(path) : void 0;
2283
+ const renameOps = prior ? detectRenamesAndOrphans(prior, walked.nodes, issues, silenced) : [];
2267
2284
  const stats = buildScanStats(walked, issues, start);
2268
2285
  const scanCompletedEvent = makeEvent("scan.completed", { stats });
2269
2286
  emitter.emit(scanCompletedEvent);
@@ -2306,7 +2323,7 @@ async function dispatchExtractorCompleted(extractors, emitter, hookDispatcher) {
2306
2323
  function mergeAnalyzerEmissions(walked, analyzerResult, analyzers) {
2307
2324
  for (const c of analyzerResult.contributions) walked.contributions.push(c);
2308
2325
  for (const analyzer of analyzers ?? []) {
2309
- if (analyzer.viewContributions === void 0) continue;
2326
+ if (analyzer.ui === void 0) continue;
2310
2327
  for (const node of walked.nodes) {
2311
2328
  walked.freshlyRunTuples.add(`${analyzer.pluginId}\0${analyzer.id}\0${node.path}`);
2312
2329
  }
@@ -2353,7 +2370,7 @@ function validateRoots(roots) {
2353
2370
  throw new Error(ORCHESTRATOR_TEXTS.runScanRootEmptyArray);
2354
2371
  }
2355
2372
  for (const root of roots) {
2356
- if (!existsSync9(root) || !statSync2(root).isDirectory()) {
2373
+ if (!existsSync10(root) || !statSync4(root).isDirectory()) {
2357
2374
  throw new Error(tx(ORCHESTRATOR_TEXTS.runScanRootMissing, { root }));
2358
2375
  }
2359
2376
  }