@skill-map/cli 0.28.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.
- package/dist/cli/tutorial/sm-tutorial.md +94 -20
- package/dist/cli.js +1408 -1193
- package/dist/cli.js.map +1 -1
- package/dist/index.js +116 -99
- package/dist/index.js.map +1 -1
- package/dist/kernel/index.d.ts +903 -1004
- package/dist/kernel/index.js +116 -99
- package/dist/kernel/index.js.map +1 -1
- package/dist/ui/chunk-3SI3TVER.js +7 -0
- package/dist/ui/{chunk-4GTCV7V4.js → chunk-47OZB7LR.js} +1 -1
- package/dist/ui/{chunk-JMP2LDMI.js → chunk-5JBW2LUN.js} +1 -1
- package/dist/ui/chunk-BL7KARTN.js +317 -0
- package/dist/ui/chunk-DMSZOXER.js +1 -0
- package/dist/ui/{chunk-Y7MXGXU3.js → chunk-DZBSELHN.js} +1 -1
- package/dist/ui/chunk-EFKSD7PT.js +123 -0
- package/dist/ui/{chunk-Z2667C3S.js → chunk-FEPH4VNB.js} +1 -1
- package/dist/ui/{chunk-PY2R7LHN.js → chunk-FQOZBFJ5.js} +1 -1
- package/dist/ui/{chunk-WOLLYGGL.js → chunk-KJQEO6P3.js} +1 -1
- package/dist/ui/{chunk-VO6NF24F.js → chunk-LS2NXZQZ.js} +1 -1
- package/dist/ui/{chunk-J3YWUNFO.js → chunk-LTQTJU54.js} +1 -1
- package/dist/ui/{chunk-6BG7PBUN.js → chunk-NGIFGXW7.js} +1 -1
- package/dist/ui/{chunk-5W6J6H76.js → chunk-SBCO7ZSP.js} +1 -1
- package/dist/ui/chunk-VB56BUGO.js +1 -0
- package/dist/ui/{chunk-UXCAEDR6.js → chunk-VDQLDTTR.js} +1 -1
- package/dist/ui/{chunk-AD7RBRD3.js → chunk-WJLIYGWJ.js} +5 -5
- package/dist/ui/index.html +2 -2
- package/dist/ui/{main-TZL26MZU.js → main-LGW7AYEA.js} +2 -2
- package/dist/ui/{styles-IKG3B6AM.css → styles-CDN434T2.css} +1 -1
- package/package.json +10 -7
- package/dist/ui/chunk-BGDH7CDV.js +0 -1
- package/dist/ui/chunk-H2J55DNK.js +0 -7
- package/dist/ui/chunk-Q7L6LLAK.js +0 -1
- package/dist/ui/chunk-VH5GRUT7.js +0 -255
- package/dist/ui/chunk-XCUOAV77.js +0 -123
package/dist/index.js
CHANGED
|
@@ -93,14 +93,14 @@ var Registry = class {
|
|
|
93
93
|
};
|
|
94
94
|
|
|
95
95
|
// kernel/orchestrator/index.ts
|
|
96
|
-
import { existsSync as
|
|
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.
|
|
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 '
|
|
163
|
-
"test:ci": "node --import tsx --test '
|
|
164
|
-
"test:coverage": "tsc --noEmit && SKILL_MAP_SKIP_BENCHMARK=1 node --experimental-default-config-file --import tsx --test --experimental-test-coverage '
|
|
165
|
-
"test:coverage:html": "tsc --noEmit && SKILL_MAP_SKIP_BENCHMARK=1 c8 node --import tsx --test '
|
|
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
|
|
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:
|
|
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:
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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:
|
|
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:
|
|
842
|
+
declaredKinds: knownKinds.join(", ")
|
|
841
843
|
})
|
|
842
844
|
})
|
|
843
845
|
);
|
|
844
846
|
return null;
|
|
845
847
|
}
|
|
846
|
-
const confidence = link.confidence ??
|
|
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
|
-
|
|
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
|
-
|
|
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({
|
|
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
|
|
1309
|
+
import { join as join3, relative as relative2, sep } from "path";
|
|
1317
1310
|
|
|
1318
1311
|
// kernel/scan/ignore.ts
|
|
1319
|
-
import { existsSync as
|
|
1320
|
-
import { dirname as
|
|
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 =
|
|
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 (
|
|
1354
|
+
if (existsSync3(candidate)) {
|
|
1362
1355
|
try {
|
|
1363
|
-
return
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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 =
|
|
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
|
|
1537
|
-
import { dirname as
|
|
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 (!
|
|
1536
|
+
if (!existsSync4(sidecarPath)) {
|
|
1544
1537
|
return { parsed: null, present: false, issues: [] };
|
|
1545
1538
|
}
|
|
1546
1539
|
let raw;
|
|
1547
1540
|
try {
|
|
1548
|
-
raw =
|
|
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
|
-
|
|
1609
|
+
readFileSync6(resolve6(specRoot, "schemas/annotations.schema.json"), "utf8")
|
|
1617
1610
|
);
|
|
1618
1611
|
const sidecarSchema = JSON.parse(
|
|
1619
|
-
|
|
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
|
|
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
|
|
1649
|
-
import { join as
|
|
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 =
|
|
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 =
|
|
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 (
|
|
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
|
|
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
|
|
1690
|
-
import { dirname as
|
|
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
|
|
1692
|
+
existsSync as existsSync6,
|
|
1700
1693
|
mkdirSync,
|
|
1701
1694
|
openSync,
|
|
1702
|
-
readFileSync as
|
|
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
|
|
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
|
|
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
|
|
1708
|
+
import { existsSync as existsSync7, readFileSync as readFileSync8 } from "fs";
|
|
1716
1709
|
|
|
1717
1710
|
// kernel/util/skill-map-paths.ts
|
|
1718
|
-
import { join as
|
|
1711
|
+
import { join as join6 } from "path";
|
|
1719
1712
|
|
|
1720
1713
|
// core/paths/db-path.ts
|
|
1721
|
-
import { join as
|
|
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
|
|
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
|
|
1890
|
+
return existsSync9(relativePath) ? relativePath : null;
|
|
1898
1891
|
}
|
|
1899
1892
|
for (const root of roots) {
|
|
1900
1893
|
const candidate = resolvePath(root, relativePath);
|
|
1901
|
-
if (
|
|
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
|
|
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.
|
|
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 (!
|
|
2373
|
+
if (!existsSync10(root) || !statSync4(root).isDirectory()) {
|
|
2357
2374
|
throw new Error(tx(ORCHESTRATOR_TEXTS.runScanRootMissing, { root }));
|
|
2358
2375
|
}
|
|
2359
2376
|
}
|