@skill-map/cli 0.16.6 → 0.18.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 +8 -0
- package/dist/cli.js +8324 -5644
- package/dist/cli.js.map +1 -1
- package/dist/conformance/index.js +36 -14
- package/dist/conformance/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +540 -61
- package/dist/index.js.map +1 -1
- package/dist/kernel/index.d.ts +443 -87
- package/dist/kernel/index.js +540 -61
- package/dist/kernel/index.js.map +1 -1
- package/dist/migrations/002_sidecar_columns.sql +53 -0
- package/dist/migrations/003_drop_node_author.sql +20 -0
- package/dist/migrations/004_sidecar_root_json.sql +23 -0
- package/dist/migrations/005_node_favorites.sql +20 -0
- package/dist/ui/chunk-3R7E3HPC.js +7 -0
- package/dist/ui/chunk-JKJGGXCS.js +1025 -0
- package/dist/ui/chunk-SX2A3WBX.js +247 -0
- package/dist/ui/chunk-TWZHUCAT.js +237 -0
- package/dist/ui/chunk-UJOZYR5I.js +1 -0
- package/dist/ui/chunk-WTAL2RK4.js +1 -0
- package/dist/ui/chunk-Z3UJHHTC.js +3091 -0
- package/dist/ui/index.html +2 -2
- package/dist/ui/main-AAYGMON4.js +1 -0
- package/dist/ui/skill-map-mark-dark.svg +8 -0
- package/dist/ui/skill-map-mark-light.svg +8 -0
- package/dist/ui/{styles-TCK5JUQE.css → styles-CBPFNGXA.css} +1 -1
- package/migrations/002_sidecar_columns.sql +53 -0
- package/migrations/003_drop_node_author.sql +20 -0
- package/migrations/004_sidecar_root_json.sql +23 -0
- package/migrations/005_node_favorites.sql +20 -0
- package/package.json +6 -6
- package/dist/ui/chunk-7PFTODKS.js +0 -1031
- package/dist/ui/chunk-A4RBO3TD.js +0 -38
- package/dist/ui/chunk-KPEISNOV.js +0 -819
- package/dist/ui/chunk-NKC42FI7.js +0 -210
- package/dist/ui/chunk-S5C4U3I3.js +0 -2403
- package/dist/ui/chunk-TG6IWVEC.js +0 -54
- package/dist/ui/chunk-TGJQE3TH.js +0 -54
- package/dist/ui/chunk-UGEECDPV.js +0 -1
- package/dist/ui/main-XSGTD7FQ.js +0 -1
package/dist/kernel/index.js
CHANGED
|
@@ -94,15 +94,16 @@ var Registry = class {
|
|
|
94
94
|
|
|
95
95
|
// kernel/orchestrator.ts
|
|
96
96
|
import { createHash } from "crypto";
|
|
97
|
-
import { existsSync as
|
|
97
|
+
import { existsSync as existsSync6, statSync as statSync2 } from "fs";
|
|
98
|
+
import { isAbsolute as isAbsolute2, resolve as resolvePath } from "path";
|
|
98
99
|
import { Tiktoken } from "js-tiktoken/lite";
|
|
99
100
|
import cl100k_base from "js-tiktoken/ranks/cl100k_base";
|
|
100
|
-
import
|
|
101
|
+
import yaml4 from "js-yaml";
|
|
101
102
|
|
|
102
103
|
// package.json
|
|
103
104
|
var package_default = {
|
|
104
105
|
name: "@skill-map/cli",
|
|
105
|
-
version: "0.
|
|
106
|
+
version: "0.18.0",
|
|
106
107
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
107
108
|
license: "MIT",
|
|
108
109
|
type: "module",
|
|
@@ -160,15 +161,15 @@ var package_default = {
|
|
|
160
161
|
"pretest:ci": "tsup",
|
|
161
162
|
"pretest:coverage": "tsup",
|
|
162
163
|
"pretest:coverage:html": "tsup",
|
|
163
|
-
test: "tsc --noEmit && node --import tsx --test --test-reporter=spec 'test/**/*.test.ts' 'built-in-plugins/**/*.test.ts' 'kernel/**/*.test.ts'",
|
|
164
|
-
"test:ci": "tsc --noEmit && node --import tsx --test 'test/**/*.test.ts' 'built-in-plugins/**/*.test.ts' 'kernel/**/*.test.ts'",
|
|
165
|
-
"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'",
|
|
166
|
-
"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'",
|
|
164
|
+
test: "tsc --noEmit && node --import tsx --test --test-reporter=spec 'test/**/*.test.ts' 'built-in-plugins/**/*.test.ts' 'kernel/**/*.test.ts' 'server/**/*.test.ts'",
|
|
165
|
+
"test:ci": "tsc --noEmit && node --import tsx --test 'test/**/*.test.ts' 'built-in-plugins/**/*.test.ts' 'kernel/**/*.test.ts' 'server/**/*.test.ts'",
|
|
166
|
+
"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'",
|
|
167
|
+
"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'",
|
|
167
168
|
clean: "rm -rf dist coverage"
|
|
168
169
|
},
|
|
169
170
|
dependencies: {
|
|
170
171
|
"@hono/node-server": "2.0.1",
|
|
171
|
-
"@skill-map/spec": "0.
|
|
172
|
+
"@skill-map/spec": "0.18.0",
|
|
172
173
|
ajv: "8.18.0",
|
|
173
174
|
"ajv-formats": "3.0.1",
|
|
174
175
|
chokidar: "5.0.0",
|
|
@@ -205,6 +206,174 @@ var package_default = {
|
|
|
205
206
|
}
|
|
206
207
|
};
|
|
207
208
|
|
|
209
|
+
// kernel/sidecar/parse.ts
|
|
210
|
+
import { existsSync, readFileSync } from "fs";
|
|
211
|
+
import { dirname, resolve } from "path";
|
|
212
|
+
import { createRequire } from "module";
|
|
213
|
+
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
214
|
+
import yaml from "js-yaml";
|
|
215
|
+
|
|
216
|
+
// kernel/util/ajv-interop.ts
|
|
217
|
+
import addFormatsModule from "ajv-formats";
|
|
218
|
+
var addFormats = addFormatsModule.default ?? addFormatsModule;
|
|
219
|
+
function applyAjvFormats(ajv) {
|
|
220
|
+
addFormats(ajv);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// kernel/sidecar/parse.ts
|
|
224
|
+
function readSidecarFor(mdAbsolutePath) {
|
|
225
|
+
const sidecarPath = sidecarPathFor(mdAbsolutePath);
|
|
226
|
+
if (!existsSync(sidecarPath)) {
|
|
227
|
+
return { parsed: null, present: false, issues: [] };
|
|
228
|
+
}
|
|
229
|
+
let raw;
|
|
230
|
+
try {
|
|
231
|
+
raw = readFileSync(sidecarPath, "utf8");
|
|
232
|
+
} catch (err) {
|
|
233
|
+
return {
|
|
234
|
+
parsed: null,
|
|
235
|
+
present: true,
|
|
236
|
+
issues: [{ message: `cannot read ${sidecarPath}: ${err.message}` }]
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
let parsedYaml;
|
|
240
|
+
try {
|
|
241
|
+
parsedYaml = yaml.load(raw);
|
|
242
|
+
} catch (err) {
|
|
243
|
+
return {
|
|
244
|
+
parsed: null,
|
|
245
|
+
present: true,
|
|
246
|
+
issues: [{ message: `malformed YAML in ${sidecarPath}: ${err.message}` }]
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
if (!isPlainObject(parsedYaml)) {
|
|
250
|
+
return {
|
|
251
|
+
parsed: null,
|
|
252
|
+
present: true,
|
|
253
|
+
issues: [{ message: `sidecar root must be a YAML mapping at ${sidecarPath}` }]
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
const sidecarValidator = getSidecarValidator();
|
|
257
|
+
if (!sidecarValidator(parsedYaml)) {
|
|
258
|
+
const errors = (sidecarValidator.errors ?? []).map((e) => `${e.instancePath || "(root)"} ${e.message ?? e.keyword}`).join("; ");
|
|
259
|
+
return {
|
|
260
|
+
parsed: null,
|
|
261
|
+
present: true,
|
|
262
|
+
issues: [{ message: `sidecar schema validation failed at ${sidecarPath}: ${errors}` }]
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
const root = parsedYaml;
|
|
266
|
+
const forBlock = root["for"];
|
|
267
|
+
const annotationsRaw = root["annotations"];
|
|
268
|
+
const annotations = isPlainObject(annotationsRaw) ? Object.keys(annotationsRaw).length === 0 ? null : annotationsRaw : null;
|
|
269
|
+
return {
|
|
270
|
+
parsed: {
|
|
271
|
+
filePath: sidecarPath,
|
|
272
|
+
forBodyHash: String(forBlock["bodyHash"]),
|
|
273
|
+
forFrontmatterHash: String(forBlock["frontmatterHash"]),
|
|
274
|
+
forPath: String(forBlock["path"]),
|
|
275
|
+
annotations,
|
|
276
|
+
raw: root
|
|
277
|
+
},
|
|
278
|
+
present: true,
|
|
279
|
+
issues: []
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
function sidecarPathFor(mdAbsolutePath) {
|
|
283
|
+
if (mdAbsolutePath.endsWith(".md")) {
|
|
284
|
+
return `${mdAbsolutePath.slice(0, -".md".length)}.sm`;
|
|
285
|
+
}
|
|
286
|
+
return `${mdAbsolutePath}.sm`;
|
|
287
|
+
}
|
|
288
|
+
function isPlainObject(value) {
|
|
289
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
290
|
+
}
|
|
291
|
+
var cachedSidecarValidator = null;
|
|
292
|
+
function getSidecarValidator() {
|
|
293
|
+
if (cachedSidecarValidator) return cachedSidecarValidator;
|
|
294
|
+
const ajv = new Ajv2020({ strict: false, allErrors: true, allowUnionTypes: true });
|
|
295
|
+
applyAjvFormats(ajv);
|
|
296
|
+
const specRoot = resolveSpecRoot();
|
|
297
|
+
const annotationsSchema = JSON.parse(
|
|
298
|
+
readFileSync(resolve(specRoot, "schemas/annotations.schema.json"), "utf8")
|
|
299
|
+
);
|
|
300
|
+
const sidecarSchema = JSON.parse(
|
|
301
|
+
readFileSync(resolve(specRoot, "schemas/sidecar.schema.json"), "utf8")
|
|
302
|
+
);
|
|
303
|
+
ajv.addSchema(annotationsSchema);
|
|
304
|
+
cachedSidecarValidator = ajv.compile(sidecarSchema);
|
|
305
|
+
return cachedSidecarValidator;
|
|
306
|
+
}
|
|
307
|
+
function resolveSpecRoot() {
|
|
308
|
+
const require2 = createRequire(import.meta.url);
|
|
309
|
+
try {
|
|
310
|
+
const indexPath = require2.resolve("@skill-map/spec/index.json");
|
|
311
|
+
return dirname(indexPath);
|
|
312
|
+
} catch {
|
|
313
|
+
throw new Error(
|
|
314
|
+
"@skill-map/spec not resolvable \u2014 sidecar reader cannot load schemas."
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// kernel/sidecar/drift.ts
|
|
320
|
+
function computeDriftStatus(args) {
|
|
321
|
+
const bodyDrift = args.storedBodyHash !== args.liveBodyHash;
|
|
322
|
+
const fmDrift = args.storedFrontmatterHash !== args.liveFrontmatterHash;
|
|
323
|
+
if (bodyDrift && fmDrift) return "stale-both";
|
|
324
|
+
if (bodyDrift) return "stale-body";
|
|
325
|
+
if (fmDrift) return "stale-frontmatter";
|
|
326
|
+
return "fresh";
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// kernel/sidecar/discover-orphans.ts
|
|
330
|
+
import { existsSync as existsSync2, readdirSync, statSync } from "fs";
|
|
331
|
+
import { join, relative, sep } from "path";
|
|
332
|
+
function discoverOrphanSidecars(roots, shouldSkip) {
|
|
333
|
+
const out = [];
|
|
334
|
+
for (const root of roots) {
|
|
335
|
+
walk(root, root, shouldSkip ?? (() => false), out);
|
|
336
|
+
}
|
|
337
|
+
return out;
|
|
338
|
+
}
|
|
339
|
+
function walk(root, current, shouldSkip, out) {
|
|
340
|
+
let entries;
|
|
341
|
+
try {
|
|
342
|
+
entries = readdirSync(current, { withFileTypes: true, encoding: "utf8" });
|
|
343
|
+
} catch {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
for (const entry of entries) {
|
|
347
|
+
const full = join(current, entry.name);
|
|
348
|
+
const rel = relative(root, full).split(sep).join("/");
|
|
349
|
+
if (shouldSkip(rel)) continue;
|
|
350
|
+
if (entry.isSymbolicLink()) continue;
|
|
351
|
+
if (entry.isDirectory()) {
|
|
352
|
+
walk(root, full, shouldSkip, out);
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
if (!entry.isFile()) continue;
|
|
356
|
+
if (!entry.name.endsWith(".sm")) continue;
|
|
357
|
+
const expectedMd = `${full.slice(0, -".sm".length)}.md`;
|
|
358
|
+
if (existsSync2(expectedMd) && safeIsFile(expectedMd)) continue;
|
|
359
|
+
out.push({ sidecarPath: full, relativePath: rel, expectedMdPath: expectedMd });
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
function safeIsFile(path) {
|
|
363
|
+
try {
|
|
364
|
+
return statSync(path).isFile();
|
|
365
|
+
} catch {
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// kernel/sidecar/store.ts
|
|
371
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2, renameSync, writeFileSync, unlinkSync } from "fs";
|
|
372
|
+
import { dirname as dirname2, resolve as resolve2 } from "path";
|
|
373
|
+
import { createRequire as createRequire2 } from "module";
|
|
374
|
+
import { Ajv2020 as Ajv20202 } from "ajv/dist/2020.js";
|
|
375
|
+
import yaml2 from "js-yaml";
|
|
376
|
+
|
|
208
377
|
// kernel/adapters/in-memory-progress.ts
|
|
209
378
|
var InMemoryProgressEmitter = class {
|
|
210
379
|
#listeners = /* @__PURE__ */ new Set();
|
|
@@ -253,20 +422,13 @@ function getActiveLogger() {
|
|
|
253
422
|
}
|
|
254
423
|
|
|
255
424
|
// kernel/adapters/plugin-loader.ts
|
|
256
|
-
import { createRequire } from "module";
|
|
257
|
-
import { existsSync, readFileSync, readdirSync } from "fs";
|
|
258
|
-
import { isAbsolute, join, relative, resolve } from "path";
|
|
425
|
+
import { createRequire as createRequire3 } from "module";
|
|
426
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync2 } from "fs";
|
|
427
|
+
import { isAbsolute, join as join2, relative as relative2, resolve as resolve3 } from "path";
|
|
259
428
|
import { pathToFileURL } from "url";
|
|
260
|
-
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
429
|
+
import { Ajv2020 as Ajv20203 } from "ajv/dist/2020.js";
|
|
261
430
|
import semver from "semver";
|
|
262
431
|
|
|
263
|
-
// kernel/util/ajv-interop.ts
|
|
264
|
-
import addFormatsModule from "ajv-formats";
|
|
265
|
-
var addFormats = addFormatsModule.default ?? addFormatsModule;
|
|
266
|
-
function applyAjvFormats(ajv) {
|
|
267
|
-
addFormats(ajv);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
432
|
// kernel/i18n/plugin-store.texts.ts
|
|
271
433
|
var PLUGIN_STORE_TEXTS = {
|
|
272
434
|
kvValidationFailed: "plugin '{{pluginId}}' ctx.store.set('{{key}}', value): value violates declared schema ({{schemaPath}}) \u2014 {{errors}}",
|
|
@@ -361,29 +523,30 @@ var KNOWN_KINDS = /* @__PURE__ */ new Set(["provider", "extractor", "rule", "act
|
|
|
361
523
|
var KNOWN_KINDS_LIST = [...KNOWN_KINDS].join(" / ");
|
|
362
524
|
var HOOKABLE_TRIGGERS_LIST = HOOK_TRIGGERS.join(", ");
|
|
363
525
|
function installedSpecVersion() {
|
|
364
|
-
const require2 =
|
|
526
|
+
const require2 = createRequire3(import.meta.url);
|
|
365
527
|
const indexPath = require2.resolve("@skill-map/spec/index.json");
|
|
366
|
-
const pkgPath =
|
|
367
|
-
const pkg = JSON.parse(
|
|
528
|
+
const pkgPath = resolve3(indexPath, "..", "package.json");
|
|
529
|
+
const pkg = JSON.parse(readFileSync3(pkgPath, "utf8"));
|
|
368
530
|
return pkg.version;
|
|
369
531
|
}
|
|
370
532
|
|
|
371
533
|
// kernel/adapters/schema-validators.ts
|
|
372
|
-
import { readFileSync as
|
|
373
|
-
import { dirname, resolve as
|
|
374
|
-
import { createRequire as
|
|
375
|
-
import { Ajv2020 as
|
|
534
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
535
|
+
import { dirname as dirname3, resolve as resolve4 } from "path";
|
|
536
|
+
import { createRequire as createRequire4 } from "module";
|
|
537
|
+
import { Ajv2020 as Ajv20204 } from "ajv/dist/2020.js";
|
|
376
538
|
function buildProviderFrontmatterValidator(providers) {
|
|
377
|
-
const specRoot =
|
|
378
|
-
const ajv = new
|
|
539
|
+
const specRoot = resolveSpecRoot2();
|
|
540
|
+
const ajv = new Ajv20204({
|
|
379
541
|
strict: false,
|
|
380
542
|
allErrors: true,
|
|
381
543
|
allowUnionTypes: true
|
|
382
544
|
});
|
|
383
545
|
applyAjvFormats(ajv);
|
|
384
|
-
const baseFile =
|
|
385
|
-
const baseSchema = JSON.parse(
|
|
546
|
+
const baseFile = resolve4(specRoot, "schemas/frontmatter/base.schema.json");
|
|
547
|
+
const baseSchema = JSON.parse(readFileSync4(baseFile, "utf8"));
|
|
386
548
|
ajv.addSchema(baseSchema);
|
|
549
|
+
registerProviderAuxiliarySchemas(ajv, providers);
|
|
387
550
|
const compiled = /* @__PURE__ */ new Map();
|
|
388
551
|
for (const provider of providers) {
|
|
389
552
|
for (const [kind, entry] of Object.entries(provider.kinds)) {
|
|
@@ -408,11 +571,21 @@ function formatError(err) {
|
|
|
408
571
|
const path = err.instancePath || "(root)";
|
|
409
572
|
return `${path} ${err.message ?? err.keyword}`;
|
|
410
573
|
}
|
|
411
|
-
function
|
|
412
|
-
const
|
|
574
|
+
function registerProviderAuxiliarySchemas(ajv, providers) {
|
|
575
|
+
for (const provider of providers) {
|
|
576
|
+
if (!provider.schemas) continue;
|
|
577
|
+
for (const aux of provider.schemas) {
|
|
578
|
+
const auxJson = aux;
|
|
579
|
+
if (typeof auxJson.$id === "string" && ajv.getSchema(auxJson.$id)) continue;
|
|
580
|
+
ajv.addSchema(aux);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
function resolveSpecRoot2() {
|
|
585
|
+
const require2 = createRequire4(import.meta.url);
|
|
413
586
|
try {
|
|
414
587
|
const indexPath = require2.resolve("@skill-map/spec/index.json");
|
|
415
|
-
return
|
|
588
|
+
return dirname3(indexPath);
|
|
416
589
|
} catch {
|
|
417
590
|
throw new Error(
|
|
418
591
|
"@skill-map/spec not resolvable \u2014 ensure the workspace is linked or the package is installed."
|
|
@@ -432,6 +605,195 @@ var ORCHESTRATOR_TEXTS = {
|
|
|
432
605
|
runScanRootMissing: "runScan: root path '{{root}}' does not exist or is not a directory"
|
|
433
606
|
};
|
|
434
607
|
|
|
608
|
+
// kernel/util/format-error.ts
|
|
609
|
+
function formatErrorMessage(err) {
|
|
610
|
+
return err instanceof Error ? err.message : String(err);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// kernel/scan/walk-content.ts
|
|
614
|
+
import { readFile, readdir, stat } from "fs/promises";
|
|
615
|
+
import { join as join3, relative as relative3, sep as sep2 } from "path";
|
|
616
|
+
|
|
617
|
+
// kernel/scan/ignore.ts
|
|
618
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
|
|
619
|
+
import { dirname as dirname4, resolve as resolve5 } from "path";
|
|
620
|
+
import { fileURLToPath } from "url";
|
|
621
|
+
import ignoreFactory from "ignore";
|
|
622
|
+
function buildIgnoreFilter(opts = {}) {
|
|
623
|
+
const ig = ignoreFactory();
|
|
624
|
+
if (opts.includeDefaults !== false) {
|
|
625
|
+
ig.add(loadDefaultsText());
|
|
626
|
+
}
|
|
627
|
+
if (opts.configIgnore && opts.configIgnore.length > 0) {
|
|
628
|
+
ig.add(opts.configIgnore);
|
|
629
|
+
}
|
|
630
|
+
if (opts.ignoreFileText && opts.ignoreFileText.length > 0) {
|
|
631
|
+
ig.add(opts.ignoreFileText);
|
|
632
|
+
}
|
|
633
|
+
return {
|
|
634
|
+
ignores(relativePath) {
|
|
635
|
+
if (relativePath === "" || relativePath === "." || relativePath === "./") {
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
const normalised = relativePath.replace(/^\.\//, "").replace(/\\/g, "/").replace(/^\//, "");
|
|
639
|
+
if (normalised === "") return false;
|
|
640
|
+
return ig.ignores(normalised);
|
|
641
|
+
}
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
var cachedDefaults = null;
|
|
645
|
+
function loadDefaultsText() {
|
|
646
|
+
if (cachedDefaults !== null) return cachedDefaults;
|
|
647
|
+
cachedDefaults = readDefaultsFromDisk();
|
|
648
|
+
return cachedDefaults;
|
|
649
|
+
}
|
|
650
|
+
function readDefaultsFromDisk() {
|
|
651
|
+
const here = dirname4(fileURLToPath(import.meta.url));
|
|
652
|
+
const candidates = [
|
|
653
|
+
resolve5(here, "../../config/defaults/skillmapignore"),
|
|
654
|
+
// src/kernel/scan/ → src/config/defaults/
|
|
655
|
+
resolve5(here, "../config/defaults/skillmapignore"),
|
|
656
|
+
// dist/cli.js → dist/config/defaults/ (siblings)
|
|
657
|
+
resolve5(here, "config/defaults/skillmapignore")
|
|
658
|
+
];
|
|
659
|
+
for (const candidate of candidates) {
|
|
660
|
+
if (existsSync5(candidate)) {
|
|
661
|
+
try {
|
|
662
|
+
return readFileSync5(candidate, "utf8");
|
|
663
|
+
} catch {
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
return "";
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// kernel/scan/parsers/frontmatter-yaml.ts
|
|
671
|
+
import yaml3 from "js-yaml";
|
|
672
|
+
var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
673
|
+
var FORBIDDEN_FRONTMATTER_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
674
|
+
var frontmatterYamlParser = {
|
|
675
|
+
id: "frontmatter-yaml",
|
|
676
|
+
parse(raw, _path) {
|
|
677
|
+
const match = FRONTMATTER_RE.exec(raw);
|
|
678
|
+
if (!match) return { frontmatterRaw: "", frontmatter: {}, body: raw };
|
|
679
|
+
const frontmatterRaw = match[1];
|
|
680
|
+
const body = match[2];
|
|
681
|
+
const parsed = {};
|
|
682
|
+
try {
|
|
683
|
+
const doc = yaml3.load(frontmatterRaw, { schema: yaml3.JSON_SCHEMA });
|
|
684
|
+
if (doc && typeof doc === "object" && !Array.isArray(doc)) {
|
|
685
|
+
for (const [k, v] of Object.entries(doc)) {
|
|
686
|
+
if (FORBIDDEN_FRONTMATTER_KEYS.has(k)) continue;
|
|
687
|
+
parsed[k] = v;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
} catch {
|
|
691
|
+
}
|
|
692
|
+
return { frontmatterRaw, frontmatter: parsed, body };
|
|
693
|
+
}
|
|
694
|
+
};
|
|
695
|
+
|
|
696
|
+
// kernel/scan/parsers/plain.ts
|
|
697
|
+
var plainParser = {
|
|
698
|
+
id: "plain",
|
|
699
|
+
parse(raw, _path) {
|
|
700
|
+
return { frontmatter: {}, frontmatterRaw: "", body: raw };
|
|
701
|
+
}
|
|
702
|
+
};
|
|
703
|
+
|
|
704
|
+
// kernel/scan/parsers/index.ts
|
|
705
|
+
var REGISTRY = /* @__PURE__ */ new Map([
|
|
706
|
+
[frontmatterYamlParser.id, frontmatterYamlParser],
|
|
707
|
+
[plainParser.id, plainParser]
|
|
708
|
+
]);
|
|
709
|
+
var FROZEN_IDS = new Set(REGISTRY.keys());
|
|
710
|
+
function getParser(id) {
|
|
711
|
+
return REGISTRY.get(id);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// kernel/scan/walk-content.ts
|
|
715
|
+
var UnknownParserError = class extends Error {
|
|
716
|
+
constructor(parserId) {
|
|
717
|
+
super(`Unknown parser id '${parserId}'. Built-in parsers: 'frontmatter-yaml', 'plain'.`);
|
|
718
|
+
this.name = "UnknownParserError";
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
async function* walkContent(roots, options) {
|
|
722
|
+
const parser = getParser(options.parser);
|
|
723
|
+
if (!parser) throw new UnknownParserError(options.parser);
|
|
724
|
+
const filter = options.ignoreFilter ?? buildIgnoreFilter();
|
|
725
|
+
const extensions = options.extensions;
|
|
726
|
+
for (const root of roots) {
|
|
727
|
+
for await (const file of walkRoot(root, root, filter, extensions)) {
|
|
728
|
+
const relPath = relative3(root, file).split(sep2).join("/");
|
|
729
|
+
let raw;
|
|
730
|
+
try {
|
|
731
|
+
raw = await readFile(file, "utf8");
|
|
732
|
+
} catch {
|
|
733
|
+
continue;
|
|
734
|
+
}
|
|
735
|
+
const parsed = parser.parse(raw, relPath);
|
|
736
|
+
yield {
|
|
737
|
+
path: relPath,
|
|
738
|
+
body: parsed.body,
|
|
739
|
+
frontmatterRaw: parsed.frontmatterRaw,
|
|
740
|
+
frontmatter: parsed.frontmatter
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
async function* walkRoot(root, current, filter, extensions) {
|
|
746
|
+
let entries;
|
|
747
|
+
try {
|
|
748
|
+
entries = await readdir(current, { withFileTypes: true, encoding: "utf8" });
|
|
749
|
+
} catch {
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
for (const entry of entries) {
|
|
753
|
+
const name = entry.name;
|
|
754
|
+
const full = join3(current, name);
|
|
755
|
+
const rel = relative3(root, full).split(sep2).join("/");
|
|
756
|
+
if (filter.ignores(rel)) continue;
|
|
757
|
+
if (entry.isSymbolicLink()) continue;
|
|
758
|
+
if (entry.isDirectory()) {
|
|
759
|
+
yield* walkRoot(root, full, filter, extensions);
|
|
760
|
+
} else if (entry.isFile() && hasMatchingExtension(name, extensions)) {
|
|
761
|
+
try {
|
|
762
|
+
const s = await stat(full);
|
|
763
|
+
if (s.isFile()) yield full;
|
|
764
|
+
} catch {
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
function hasMatchingExtension(name, extensions) {
|
|
770
|
+
for (const ext of extensions) {
|
|
771
|
+
if (name.endsWith(ext)) return true;
|
|
772
|
+
}
|
|
773
|
+
return false;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
// kernel/extensions/provider.ts
|
|
777
|
+
var DEFAULT_READ_CONFIG = Object.freeze({
|
|
778
|
+
extensions: Object.freeze([".md"]),
|
|
779
|
+
parser: "frontmatter-yaml"
|
|
780
|
+
});
|
|
781
|
+
function resolveProviderWalk(provider) {
|
|
782
|
+
if (provider.walk) {
|
|
783
|
+
const walk2 = provider.walk.bind(provider);
|
|
784
|
+
return walk2;
|
|
785
|
+
}
|
|
786
|
+
const read = provider.read ?? DEFAULT_READ_CONFIG;
|
|
787
|
+
return (roots, options) => {
|
|
788
|
+
const walkOptions = {
|
|
789
|
+
extensions: read.extensions,
|
|
790
|
+
parser: read.parser
|
|
791
|
+
};
|
|
792
|
+
if (options?.ignoreFilter) walkOptions.ignoreFilter = options.ignoreFilter;
|
|
793
|
+
return walkContent(roots, walkOptions);
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
|
|
435
797
|
// kernel/orchestrator.ts
|
|
436
798
|
var SCANNED_BY = {
|
|
437
799
|
name: "skill-map",
|
|
@@ -494,14 +856,23 @@ async function runScanInternal(_kernel, options) {
|
|
|
494
856
|
emitter.emit(evt);
|
|
495
857
|
await hookDispatcher.dispatch("extractor.completed", evt);
|
|
496
858
|
}
|
|
497
|
-
const issues = await runRules(
|
|
859
|
+
const issues = await runRules(
|
|
860
|
+
exts.rules,
|
|
861
|
+
walked.nodes,
|
|
862
|
+
walked.internalLinks,
|
|
863
|
+
walked.orphanSidecars,
|
|
864
|
+
walked.sidecarRoots,
|
|
865
|
+
options.annotationContributions ?? [],
|
|
866
|
+
emitter,
|
|
867
|
+
hookDispatcher
|
|
868
|
+
);
|
|
498
869
|
for (const issue of walked.frontmatterIssues) issues.push(issue);
|
|
499
870
|
const renameOps = prior ? detectRenamesAndOrphans(prior, walked.nodes, issues) : [];
|
|
500
871
|
const stats = {
|
|
501
872
|
// `filesSkipped` is "files walked but not classified by any Provider".
|
|
502
873
|
// Today every walked file IS classified by its Provider (the `claude`
|
|
503
874
|
// Provider's `classify()` always returns a kind, falling back to
|
|
504
|
-
// `'
|
|
875
|
+
// `'markdown'`), so this is always 0. Wired now so the field shape is
|
|
505
876
|
// spec-conformant; meaningful once multiple Providers compete.
|
|
506
877
|
filesWalked: walked.filesWalked,
|
|
507
878
|
filesSkipped: 0,
|
|
@@ -536,7 +907,7 @@ function validateRoots(roots) {
|
|
|
536
907
|
throw new Error(ORCHESTRATOR_TEXTS.runScanRootEmptyArray);
|
|
537
908
|
}
|
|
538
909
|
for (const root of roots) {
|
|
539
|
-
if (!
|
|
910
|
+
if (!existsSync6(root) || !statSync2(root).isDirectory()) {
|
|
540
911
|
throw new Error(tx(ORCHESTRATOR_TEXTS.runScanRootMissing, { root }));
|
|
541
912
|
}
|
|
542
913
|
}
|
|
@@ -740,6 +1111,7 @@ async function walkAndExtract(opts) {
|
|
|
740
1111
|
const frontmatterIssues = [];
|
|
741
1112
|
const enrichmentBuffer = /* @__PURE__ */ new Map();
|
|
742
1113
|
const extractorRuns = [];
|
|
1114
|
+
const sidecarRoots = /* @__PURE__ */ new Map();
|
|
743
1115
|
let filesWalked = 0;
|
|
744
1116
|
let index = 0;
|
|
745
1117
|
const walkOptions = ignoreFilter ? { ignoreFilter } : {};
|
|
@@ -751,13 +1123,16 @@ async function walkAndExtract(opts) {
|
|
|
751
1123
|
else shortIdToQualified.set(ex.id, [qualified]);
|
|
752
1124
|
}
|
|
753
1125
|
for (const provider of providers) {
|
|
754
|
-
for await (const raw of provider
|
|
1126
|
+
for await (const raw of resolveProviderWalk(provider)(roots, walkOptions)) {
|
|
755
1127
|
filesWalked += 1;
|
|
756
1128
|
const bodyHash = sha256(raw.body);
|
|
757
1129
|
const frontmatterHash = sha256(canonicalFrontmatter(raw.frontmatter, raw.frontmatterRaw));
|
|
758
1130
|
const priorNode = priorNodesByPath.get(raw.path);
|
|
759
1131
|
const nodeHashCacheEligible = enableCache && prior !== null && priorNode !== void 0 && priorNode.bodyHash === bodyHash && priorNode.frontmatterHash === frontmatterHash;
|
|
760
1132
|
const kind = provider.classify(raw.path, raw.frontmatter);
|
|
1133
|
+
if (kind === null) {
|
|
1134
|
+
continue;
|
|
1135
|
+
}
|
|
761
1136
|
index += 1;
|
|
762
1137
|
const cacheDecision = computeCacheDecision({
|
|
763
1138
|
extractors,
|
|
@@ -785,10 +1160,21 @@ async function walkAndExtract(opts) {
|
|
|
785
1160
|
priorLinksByOriginating,
|
|
786
1161
|
priorFrontmatterIssuesByNode
|
|
787
1162
|
});
|
|
1163
|
+
reused.node.stability = null;
|
|
1164
|
+
reused.node.version = null;
|
|
1165
|
+
const reusedSidecarIssues = resolveAndApplySidecar(
|
|
1166
|
+
reused.node,
|
|
1167
|
+
raw.path,
|
|
1168
|
+
roots,
|
|
1169
|
+
bodyHash,
|
|
1170
|
+
frontmatterHash,
|
|
1171
|
+
sidecarRoots
|
|
1172
|
+
);
|
|
788
1173
|
nodes.push(reused.node);
|
|
789
1174
|
cachedPaths.add(reused.node.path);
|
|
790
1175
|
for (const link of reused.internalLinks) internalLinks.push(link);
|
|
791
1176
|
for (const issue of reused.frontmatterIssues) frontmatterIssues.push(issue);
|
|
1177
|
+
for (const issue of reusedSidecarIssues) frontmatterIssues.push(issue);
|
|
792
1178
|
for (const run of reused.extractorRuns) extractorRuns.push(run);
|
|
793
1179
|
emitter.emit(makeEvent("scan.progress", { index, path: raw.path, kind, cached: true }));
|
|
794
1180
|
continue;
|
|
@@ -824,6 +1210,15 @@ async function walkAndExtract(opts) {
|
|
|
824
1210
|
nodes.push(node);
|
|
825
1211
|
for (const issue of fresh.frontmatterIssues) frontmatterIssues.push(issue);
|
|
826
1212
|
}
|
|
1213
|
+
const sidecarIssues = resolveAndApplySidecar(
|
|
1214
|
+
node,
|
|
1215
|
+
raw.path,
|
|
1216
|
+
roots,
|
|
1217
|
+
bodyHash,
|
|
1218
|
+
frontmatterHash,
|
|
1219
|
+
sidecarRoots
|
|
1220
|
+
);
|
|
1221
|
+
for (const issue of sidecarIssues) frontmatterIssues.push(issue);
|
|
827
1222
|
emitter.emit(makeEvent("scan.progress", {
|
|
828
1223
|
index,
|
|
829
1224
|
path: raw.path,
|
|
@@ -858,6 +1253,7 @@ async function walkAndExtract(opts) {
|
|
|
858
1253
|
}
|
|
859
1254
|
}
|
|
860
1255
|
}
|
|
1256
|
+
const orphanSidecars = discoverOrphanSidecars(roots);
|
|
861
1257
|
return {
|
|
862
1258
|
nodes,
|
|
863
1259
|
internalLinks,
|
|
@@ -866,7 +1262,9 @@ async function walkAndExtract(opts) {
|
|
|
866
1262
|
frontmatterIssues,
|
|
867
1263
|
filesWalked,
|
|
868
1264
|
enrichments: [...enrichmentBuffer.values()],
|
|
869
|
-
extractorRuns
|
|
1265
|
+
extractorRuns,
|
|
1266
|
+
orphanSidecars,
|
|
1267
|
+
sidecarRoots
|
|
870
1268
|
};
|
|
871
1269
|
}
|
|
872
1270
|
function reuseCachedLink(link, shortIdToQualified, cachedQualifiedIds, applicableQualifiedIds) {
|
|
@@ -895,10 +1293,20 @@ function reuseCachedLink(link, shortIdToQualified, cachedQualifiedIds, applicabl
|
|
|
895
1293
|
if (obsoleteSources.length === 0) return link;
|
|
896
1294
|
return { ...link, sources: cachedSources };
|
|
897
1295
|
}
|
|
898
|
-
async function runRules(rules, nodes, internalLinks, emitter, hookDispatcher) {
|
|
1296
|
+
async function runRules(rules, nodes, internalLinks, orphanSidecars, sidecarRoots, annotationContributions, emitter, hookDispatcher) {
|
|
899
1297
|
const issues = [];
|
|
1298
|
+
const ruleOrphans = orphanSidecars.map((o) => ({
|
|
1299
|
+
relativePath: o.relativePath,
|
|
1300
|
+
expectedMdPath: o.expectedMdPath
|
|
1301
|
+
}));
|
|
900
1302
|
for (const rule of rules) {
|
|
901
|
-
const emitted = await rule.evaluate({
|
|
1303
|
+
const emitted = await rule.evaluate({
|
|
1304
|
+
nodes,
|
|
1305
|
+
links: internalLinks,
|
|
1306
|
+
orphanSidecars: ruleOrphans,
|
|
1307
|
+
sidecarRoots,
|
|
1308
|
+
annotationContributions
|
|
1309
|
+
});
|
|
902
1310
|
for (const issue of emitted) {
|
|
903
1311
|
const validated = validateIssue(rule, issue, emitter);
|
|
904
1312
|
if (validated) issues.push(validated);
|
|
@@ -1079,7 +1487,7 @@ function makeHookDispatcher(hooks, emitter) {
|
|
|
1079
1487
|
await hook.on(ctx);
|
|
1080
1488
|
} catch (err) {
|
|
1081
1489
|
const qualifiedId = qualifiedExtensionId(hook.pluginId, hook.id);
|
|
1082
|
-
const message =
|
|
1490
|
+
const message = formatErrorMessage(err);
|
|
1083
1491
|
emitter.emit(
|
|
1084
1492
|
makeEvent("extension.error", {
|
|
1085
1493
|
kind: "hook-error",
|
|
@@ -1124,7 +1532,6 @@ function buildHookContext(_hook, trigger, event) {
|
|
|
1124
1532
|
function buildNode(args) {
|
|
1125
1533
|
const bytesFrontmatter = Buffer.byteLength(args.frontmatterRaw, "utf8");
|
|
1126
1534
|
const bytesBody = Buffer.byteLength(args.body, "utf8");
|
|
1127
|
-
const metadata = pickMetadata(args.frontmatter);
|
|
1128
1535
|
const node = {
|
|
1129
1536
|
path: args.path,
|
|
1130
1537
|
kind: args.kind,
|
|
@@ -1142,9 +1549,8 @@ function buildNode(args) {
|
|
|
1142
1549
|
frontmatter: args.frontmatter,
|
|
1143
1550
|
title: pickString(args.frontmatter["name"]),
|
|
1144
1551
|
description: pickString(args.frontmatter["description"]),
|
|
1145
|
-
stability:
|
|
1146
|
-
version:
|
|
1147
|
-
author: pickString(args.frontmatter["author"])
|
|
1552
|
+
stability: null,
|
|
1553
|
+
version: null
|
|
1148
1554
|
};
|
|
1149
1555
|
if (args.encoder) {
|
|
1150
1556
|
node.tokens = countTokens(args.encoder, args.frontmatterRaw, args.body);
|
|
@@ -1165,24 +1571,88 @@ function canonicalFrontmatter(parsed, raw) {
|
|
|
1165
1571
|
if (!hasParsedKeys && hasRawText) {
|
|
1166
1572
|
return raw;
|
|
1167
1573
|
}
|
|
1168
|
-
return
|
|
1574
|
+
return yaml4.dump(parsed, {
|
|
1169
1575
|
sortKeys: true,
|
|
1170
1576
|
lineWidth: -1,
|
|
1171
1577
|
noRefs: true,
|
|
1172
1578
|
noCompatMode: true
|
|
1173
1579
|
});
|
|
1174
1580
|
}
|
|
1175
|
-
function
|
|
1176
|
-
const
|
|
1177
|
-
|
|
1581
|
+
function resolveAndApplySidecar(node, relativePath, roots, liveBodyHash, liveFrontmatterHash, sidecarRoots) {
|
|
1582
|
+
const issues = [];
|
|
1583
|
+
const mdAbs = resolveAbsoluteMdPath(relativePath, roots);
|
|
1584
|
+
if (mdAbs === null) {
|
|
1585
|
+
node.sidecar = { present: false };
|
|
1586
|
+
return issues;
|
|
1587
|
+
}
|
|
1588
|
+
const result = readSidecarFor(mdAbs);
|
|
1589
|
+
if (!result.present) {
|
|
1590
|
+
node.sidecar = { present: false };
|
|
1591
|
+
return issues;
|
|
1592
|
+
}
|
|
1593
|
+
if (result.parsed === null) {
|
|
1594
|
+
node.sidecar = { present: true, status: null, annotations: null, root: null };
|
|
1595
|
+
for (const parseIssue of result.issues) {
|
|
1596
|
+
issues.push({
|
|
1597
|
+
ruleId: "invalid-sidecar",
|
|
1598
|
+
severity: "warn",
|
|
1599
|
+
nodeIds: [node.path],
|
|
1600
|
+
message: parseIssue.message,
|
|
1601
|
+
data: { sidecarPath: relativePathFromRoots(mdAbs, roots) }
|
|
1602
|
+
});
|
|
1603
|
+
}
|
|
1604
|
+
return issues;
|
|
1605
|
+
}
|
|
1606
|
+
const status = computeDriftStatus({
|
|
1607
|
+
storedBodyHash: result.parsed.forBodyHash,
|
|
1608
|
+
storedFrontmatterHash: result.parsed.forFrontmatterHash,
|
|
1609
|
+
liveBodyHash,
|
|
1610
|
+
liveFrontmatterHash
|
|
1611
|
+
});
|
|
1612
|
+
applyAnnotationsOverlay(node, result.parsed);
|
|
1613
|
+
node.sidecar = {
|
|
1614
|
+
present: true,
|
|
1615
|
+
status,
|
|
1616
|
+
annotations: result.parsed.annotations,
|
|
1617
|
+
root: result.parsed.raw
|
|
1618
|
+
};
|
|
1619
|
+
sidecarRoots.set(node.path, result.parsed.raw);
|
|
1620
|
+
return issues;
|
|
1621
|
+
}
|
|
1622
|
+
function applyAnnotationsOverlay(node, parsed) {
|
|
1623
|
+
const annotations = parsed.annotations;
|
|
1624
|
+
if (annotations === null) return;
|
|
1625
|
+
const stability = annotations["stability"];
|
|
1626
|
+
if (stability === "experimental" || stability === "stable" || stability === "deprecated") {
|
|
1627
|
+
node.stability = stability;
|
|
1628
|
+
}
|
|
1629
|
+
const version = annotations["version"];
|
|
1630
|
+
if (typeof version === "number" && Number.isInteger(version) && version >= 1) {
|
|
1631
|
+
node.version = version;
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
function resolveAbsoluteMdPath(relativePath, roots) {
|
|
1635
|
+
if (isAbsolute2(relativePath)) {
|
|
1636
|
+
return existsSync6(relativePath) ? relativePath : null;
|
|
1637
|
+
}
|
|
1638
|
+
for (const root of roots) {
|
|
1639
|
+
const candidate = resolvePath(root, relativePath);
|
|
1640
|
+
if (existsSync6(candidate)) return candidate;
|
|
1641
|
+
}
|
|
1642
|
+
return null;
|
|
1643
|
+
}
|
|
1644
|
+
function relativePathFromRoots(absolutePath, roots) {
|
|
1645
|
+
for (const root of roots) {
|
|
1646
|
+
const abs = resolvePath(root);
|
|
1647
|
+
if (absolutePath.startsWith(`${abs}/`) || absolutePath.startsWith(`${abs}\\`)) {
|
|
1648
|
+
return absolutePath.slice(abs.length + 1).split(/[\\/]/).join("/");
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
return absolutePath;
|
|
1178
1652
|
}
|
|
1179
1653
|
function pickString(value) {
|
|
1180
1654
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
1181
1655
|
}
|
|
1182
|
-
function pickStability(value) {
|
|
1183
|
-
if (value === "experimental" || value === "stable" || value === "deprecated") return value;
|
|
1184
|
-
return null;
|
|
1185
|
-
}
|
|
1186
1656
|
function buildExtractorContext(extractor, node, body, frontmatter, emitLink, enrichNode, store) {
|
|
1187
1657
|
const scope = extractor.scope;
|
|
1188
1658
|
return {
|
|
@@ -1329,16 +1799,16 @@ function assignSafe(target, source) {
|
|
|
1329
1799
|
}
|
|
1330
1800
|
|
|
1331
1801
|
// kernel/scan/watcher.ts
|
|
1332
|
-
import { resolve as
|
|
1802
|
+
import { resolve as resolve6, relative as relative4, sep as sep3 } from "path";
|
|
1333
1803
|
import chokidar from "chokidar";
|
|
1334
1804
|
function createChokidarWatcher(opts) {
|
|
1335
|
-
const absRoots = opts.roots.map((r) =>
|
|
1805
|
+
const absRoots = opts.roots.map((r) => resolve6(opts.cwd, r));
|
|
1336
1806
|
const ignoreFilterOpt = opts.ignoreFilter;
|
|
1337
1807
|
const getFilter = ignoreFilterOpt === void 0 ? void 0 : typeof ignoreFilterOpt === "function" ? ignoreFilterOpt : () => ignoreFilterOpt;
|
|
1338
1808
|
const ignored = getFilter ? (path) => {
|
|
1339
1809
|
const filter = getFilter();
|
|
1340
1810
|
if (!filter) return false;
|
|
1341
|
-
const rel =
|
|
1811
|
+
const rel = relativePathFromRoots2(path, absRoots);
|
|
1342
1812
|
if (rel === null) return false;
|
|
1343
1813
|
return filter.ignores(rel);
|
|
1344
1814
|
} : void 0;
|
|
@@ -1422,12 +1892,12 @@ function createChokidarWatcher(opts) {
|
|
|
1422
1892
|
};
|
|
1423
1893
|
return { ready, close };
|
|
1424
1894
|
}
|
|
1425
|
-
function
|
|
1895
|
+
function relativePathFromRoots2(absolute, absRoots) {
|
|
1426
1896
|
for (const root of absRoots) {
|
|
1427
|
-
const rel =
|
|
1897
|
+
const rel = relative4(root, absolute);
|
|
1428
1898
|
if (rel === "" || rel === ".") return "";
|
|
1429
|
-
if (!rel.startsWith("..") && !rel.startsWith(`..${
|
|
1430
|
-
return rel.split(
|
|
1899
|
+
if (!rel.startsWith("..") && !rel.startsWith(`..${sep3}`)) {
|
|
1900
|
+
return rel.split(sep3).join("/");
|
|
1431
1901
|
}
|
|
1432
1902
|
}
|
|
1433
1903
|
return null;
|
|
@@ -1678,7 +2148,16 @@ function parseLogLevel(value) {
|
|
|
1678
2148
|
|
|
1679
2149
|
// kernel/index.ts
|
|
1680
2150
|
function createKernel() {
|
|
1681
|
-
|
|
2151
|
+
let annotationKeys = Object.freeze([]);
|
|
2152
|
+
return {
|
|
2153
|
+
registry: new Registry(),
|
|
2154
|
+
getRegisteredAnnotationKeys() {
|
|
2155
|
+
return annotationKeys;
|
|
2156
|
+
},
|
|
2157
|
+
setRegisteredAnnotationKeys(entries) {
|
|
2158
|
+
annotationKeys = Object.freeze([...entries]);
|
|
2159
|
+
}
|
|
2160
|
+
};
|
|
1682
2161
|
}
|
|
1683
2162
|
export {
|
|
1684
2163
|
DuplicateExtensionError,
|