@skill-map/cli 0.22.0 → 0.23.1
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/README.md +4 -4
- package/bin/sm.js +3 -3
- package/dist/cli/tutorial/sm-tutorial.md +22 -4
- package/dist/cli.js +1450 -686
- package/dist/cli.js.map +1 -1
- package/dist/conformance/index.d.ts +1 -1
- package/dist/conformance/index.js.map +1 -1
- package/dist/index.js +155 -60
- package/dist/index.js.map +1 -1
- package/dist/kernel/index.d.ts +383 -247
- package/dist/kernel/index.js +155 -60
- package/dist/kernel/index.js.map +1 -1
- package/dist/ui/{chunk-GXRWH2VL.js → chunk-2TPMJJYQ.js} +1 -1
- package/dist/ui/chunk-3RAME7PF.js +251 -0
- package/dist/ui/chunk-4BVLXZO3.js +61 -0
- package/dist/ui/{chunk-MPMBTIUR.js → chunk-BMAKIDAV.js} +30 -30
- package/dist/ui/chunk-C7PRRCVD.js +123 -0
- package/dist/ui/{chunk-VVOEPDQD.js → chunk-GJJZ5QH6.js} +1 -1
- package/dist/ui/chunk-I7EELB7M.js +1 -0
- package/dist/ui/{chunk-OPPQMCMQ.js → chunk-KRNW54CI.js} +1 -1
- package/dist/ui/chunk-NJ4PSNK3.js +965 -0
- package/dist/ui/{chunk-W2EFGI3J.js → chunk-OU26UMVW.js} +1 -1
- package/dist/ui/chunk-SCSYN7U2.js +1 -0
- package/dist/ui/index.html +3 -3
- package/dist/ui/main-WQA6J5V5.js +2 -0
- package/dist/ui/{styles-M2FETVAG.css → styles-ALBMEXCF.css} +1 -1
- package/package.json +4 -4
- package/dist/ui/chunk-25AWRVIC.js +0 -965
- package/dist/ui/chunk-GETTEQ3S.js +0 -123
- package/dist/ui/chunk-HC6PNQMW.js +0 -251
- package/dist/ui/chunk-HJHWJTFH.js +0 -1
- package/dist/ui/chunk-MF2M6GYF.js +0 -1
- package/dist/ui/chunk-V3SZQETX.js +0 -61
- package/dist/ui/main-Q2WC254P.js +0 -2
package/dist/kernel/index.js
CHANGED
|
@@ -100,7 +100,7 @@ import cl100k_base from "js-tiktoken/ranks/cl100k_base";
|
|
|
100
100
|
// package.json
|
|
101
101
|
var package_default = {
|
|
102
102
|
name: "@skill-map/cli",
|
|
103
|
-
version: "0.
|
|
103
|
+
version: "0.23.1",
|
|
104
104
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
105
105
|
license: "MIT",
|
|
106
106
|
type: "module",
|
|
@@ -167,16 +167,16 @@ var package_default = {
|
|
|
167
167
|
},
|
|
168
168
|
dependencies: {
|
|
169
169
|
"@hono/node-server": "2.0.1",
|
|
170
|
-
"@skill-map/spec": "0.
|
|
170
|
+
"@skill-map/spec": "0.23.0",
|
|
171
171
|
ajv: "8.18.0",
|
|
172
172
|
"ajv-formats": "3.0.1",
|
|
173
173
|
chokidar: "5.0.0",
|
|
174
174
|
clipanion: "4.0.0-rc.4",
|
|
175
|
-
hono: "4.12.
|
|
175
|
+
hono: "4.12.18",
|
|
176
176
|
ignore: "7.0.5",
|
|
177
177
|
"js-tiktoken": "1.0.21",
|
|
178
178
|
"js-yaml": "4.1.1",
|
|
179
|
-
kysely: "0.28.
|
|
179
|
+
kysely: "0.28.17",
|
|
180
180
|
semver: "7.7.4",
|
|
181
181
|
typanion: "3.14.0",
|
|
182
182
|
ws: "8.20.0"
|
|
@@ -271,8 +271,8 @@ import { Ajv2020 as Ajv20202 } from "ajv/dist/2020.js";
|
|
|
271
271
|
|
|
272
272
|
// kernel/i18n/plugin-store.texts.ts
|
|
273
273
|
var PLUGIN_STORE_TEXTS = {
|
|
274
|
-
kvValidationFailed: "plugin '{{pluginId}}' ctx.store.set('{{key}}', value): value violates declared schema ({{schemaPath}})
|
|
275
|
-
dedicatedValidationFailed: "plugin '{{pluginId}}' ctx.store.write('{{table}}', row): row violates declared schema ({{schemaPath}})
|
|
274
|
+
kvValidationFailed: "plugin '{{pluginId}}' ctx.store.set('{{key}}', value): value violates declared schema ({{schemaPath}}): {{errors}}",
|
|
275
|
+
dedicatedValidationFailed: "plugin '{{pluginId}}' ctx.store.write('{{table}}', row): row violates declared schema ({{schemaPath}}): {{errors}}"
|
|
276
276
|
};
|
|
277
277
|
|
|
278
278
|
// kernel/adapters/plugin-store.ts
|
|
@@ -360,6 +360,27 @@ import { readFileSync as readFileSync3 } from "fs";
|
|
|
360
360
|
import { dirname, resolve as resolve4 } from "path";
|
|
361
361
|
import { createRequire as createRequire2 } from "module";
|
|
362
362
|
import { Ajv2020 as Ajv20203 } from "ajv/dist/2020.js";
|
|
363
|
+
|
|
364
|
+
// kernel/types/view-catalog.ts
|
|
365
|
+
var ALL_SLOT_NAMES = [
|
|
366
|
+
"card.title.right",
|
|
367
|
+
"card.subtitle.left",
|
|
368
|
+
"card.footer.left",
|
|
369
|
+
"card.footer.right",
|
|
370
|
+
"graph.node.alert",
|
|
371
|
+
"inspector.header.badge.counter",
|
|
372
|
+
"inspector.header.badge.tag",
|
|
373
|
+
"inspector.body.panel.breakdown",
|
|
374
|
+
"inspector.body.panel.records",
|
|
375
|
+
"inspector.body.panel.tree",
|
|
376
|
+
"inspector.body.panel.key-values",
|
|
377
|
+
"inspector.body.panel.link-list",
|
|
378
|
+
"inspector.body.panel.markdown",
|
|
379
|
+
"topbar.nav.start"
|
|
380
|
+
];
|
|
381
|
+
var KNOWN_SLOT_NAMES = new Set(ALL_SLOT_NAMES);
|
|
382
|
+
|
|
383
|
+
// kernel/adapters/schema-validators.ts
|
|
363
384
|
var SCHEMA_FILES = {
|
|
364
385
|
node: "schemas/node.schema.json",
|
|
365
386
|
link: "schemas/link.schema.json",
|
|
@@ -427,24 +448,8 @@ function buildSchemaValidators() {
|
|
|
427
448
|
});
|
|
428
449
|
const contributionValidators = /* @__PURE__ */ new Map();
|
|
429
450
|
const VIEW_SLOTS_ID = "https://skill-map.dev/spec/v0/view-slots.schema.json";
|
|
430
|
-
const KNOWN_SLOTS = /* @__PURE__ */ new Set([
|
|
431
|
-
"card.title.right",
|
|
432
|
-
"card.subtitle.left",
|
|
433
|
-
"card.footer.left",
|
|
434
|
-
"card.footer.right",
|
|
435
|
-
"graph.node.alert",
|
|
436
|
-
"inspector.header.badge.counter",
|
|
437
|
-
"inspector.header.badge.tag",
|
|
438
|
-
"inspector.body.panel.breakdown",
|
|
439
|
-
"inspector.body.panel.records",
|
|
440
|
-
"inspector.body.panel.tree",
|
|
441
|
-
"inspector.body.panel.key-values",
|
|
442
|
-
"inspector.body.panel.link-list",
|
|
443
|
-
"inspector.body.panel.markdown",
|
|
444
|
-
"topbar.nav.start"
|
|
445
|
-
]);
|
|
446
451
|
function getContributionValidator(slot) {
|
|
447
|
-
if (!
|
|
452
|
+
if (!KNOWN_SLOT_NAMES.has(slot)) return null;
|
|
448
453
|
const existing = contributionValidators.get(slot);
|
|
449
454
|
if (existing) return existing;
|
|
450
455
|
const ref = `${VIEW_SLOTS_ID}#/$defs/payloads/${slot}`;
|
|
@@ -542,7 +547,7 @@ function resolveSpecRoot() {
|
|
|
542
547
|
return dirname(indexPath);
|
|
543
548
|
} catch {
|
|
544
549
|
throw new Error(
|
|
545
|
-
"@skill-map/spec not resolvable
|
|
550
|
+
"@skill-map/spec not resolvable: ensure the workspace is linked or the package is installed."
|
|
546
551
|
);
|
|
547
552
|
}
|
|
548
553
|
}
|
|
@@ -675,13 +680,14 @@ function buildHookContext(_hook, trigger, event) {
|
|
|
675
680
|
// kernel/i18n/orchestrator.texts.ts
|
|
676
681
|
var ORCHESTRATOR_TEXTS = {
|
|
677
682
|
frontmatterInvalid: "Frontmatter for {{path}} ({{kind}}) failed schema validation: {{errors}}",
|
|
678
|
-
frontmatterMalformedPasteWithIndent: "Frontmatter fence in {{path}} appears indented; YAML frontmatter MUST start with `---` at column 0. The file was scanned as body-only
|
|
683
|
+
frontmatterMalformedPasteWithIndent: "Frontmatter fence in {{path}} appears indented; YAML frontmatter MUST start with `---` at column 0. The file was scanned as body-only; the metadata block was silently lost. Move the `---` lines to the start of the line.",
|
|
679
684
|
frontmatterMalformedByteOrderMark: "Frontmatter fence in {{path}} is preceded by a UTF-8 byte-order mark (BOM); the file was scanned as body-only. Re-save the file as UTF-8 without BOM. The metadata block was silently lost.",
|
|
680
|
-
frontmatterMalformedMissingClose: "Frontmatter in {{path}} opens with `---` but never closes
|
|
685
|
+
frontmatterMalformedMissingClose: "Frontmatter in {{path}} opens with `---` but never closes (no matching `---` line at column 0 was found). The file was scanned as body-only and every metadata field was silently lost. Add a closing `---` line below the metadata block.",
|
|
681
686
|
extensionErrorLinkKindNotDeclared: 'Extractor "{{extractorId}}" emitted a link of kind "{{linkKind}}" outside its declared `emitsLinkKinds` set [{{declaredKinds}}]. Link dropped.',
|
|
682
687
|
extensionErrorIssueInvalidSeverity: `Rule "{{analyzerId}}" emitted an issue with invalid severity {{severity}} (allowed: 'error' | 'warn' | 'info'). Issue dropped.`,
|
|
683
688
|
extensionErrorContributionUnknownId: 'Extractor "{{extractorId}}" emitted contribution "{{contributionId}}" on {{nodePath}} but did not declare it in its `viewContributions` map. Contribution dropped.',
|
|
684
689
|
extensionErrorContributionPayloadInvalid: 'Extractor "{{extractorId}}" emitted contribution "{{contributionId}}" on {{nodePath}}; payload failed the "{{slot}}" schema: {{errors}}. Contribution dropped.',
|
|
690
|
+
extensionErrorRecommendedActionMissing: 'Analyzer "{{analyzerId}}" declares recommendedAction "{{actionId}}" but no Action is registered under that qualified id. The analyzer stays registered; the recommendation will not surface in the inspector.',
|
|
685
691
|
runScanRootEmptyArray: "runScan: roots must contain at least one path (spec requires minItems: 1)",
|
|
686
692
|
runScanRootMissing: "runScan: root path '{{root}}' does not exist or is not a directory"
|
|
687
693
|
};
|
|
@@ -870,10 +876,11 @@ function isExternalUrlLink(link) {
|
|
|
870
876
|
}
|
|
871
877
|
|
|
872
878
|
// kernel/orchestrator/analyzers.ts
|
|
873
|
-
async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sidecarRoots, annotationContributions, viewContributions, orphanJobFiles, referenceablePaths, cwd, emitter, hookDispatcher) {
|
|
879
|
+
async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sidecarRoots, annotationContributions, viewContributions, orphanJobFiles, referenceablePaths, cwd, registeredActionIds, emitter, hookDispatcher) {
|
|
874
880
|
const issues = [];
|
|
875
881
|
const contributions = [];
|
|
876
882
|
const validators = loadSchemaValidators();
|
|
883
|
+
validateRecommendedActions(analyzers, registeredActionIds, emitter);
|
|
877
884
|
const analyzerOrphans = orphanSidecars.map((o) => ({
|
|
878
885
|
relativePath: o.relativePath,
|
|
879
886
|
expectedMdPath: o.expectedMdPath
|
|
@@ -945,6 +952,27 @@ async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sid
|
|
|
945
952
|
}
|
|
946
953
|
return { issues, contributions };
|
|
947
954
|
}
|
|
955
|
+
function validateRecommendedActions(analyzers, registeredActionIds, emitter) {
|
|
956
|
+
for (const analyzer of analyzers) {
|
|
957
|
+
const refs = analyzer.recommendedActions;
|
|
958
|
+
if (refs === void 0 || refs.length === 0) continue;
|
|
959
|
+
const analyzerId = qualifiedExtensionId(analyzer.pluginId, analyzer.id);
|
|
960
|
+
for (const actionId of refs) {
|
|
961
|
+
if (registeredActionIds.has(actionId)) continue;
|
|
962
|
+
emitter.emit(
|
|
963
|
+
makeEvent("extension.error", {
|
|
964
|
+
kind: "recommended-action-missing",
|
|
965
|
+
extensionId: analyzerId,
|
|
966
|
+
actionId,
|
|
967
|
+
message: tx(ORCHESTRATOR_TEXTS.extensionErrorRecommendedActionMissing, {
|
|
968
|
+
analyzerId,
|
|
969
|
+
actionId
|
|
970
|
+
})
|
|
971
|
+
})
|
|
972
|
+
);
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
}
|
|
948
976
|
function validateIssue(analyzer, issue, emitter) {
|
|
949
977
|
const severity = issue.severity;
|
|
950
978
|
if (severity !== "error" && severity !== "warn" && severity !== "info") {
|
|
@@ -994,9 +1022,20 @@ function indexPriorLinks(links, priorNodePaths, byOriginating) {
|
|
|
994
1022
|
else byOriginating.set(key, [link]);
|
|
995
1023
|
}
|
|
996
1024
|
}
|
|
1025
|
+
var FRONTMATTER_ISSUE_ANALYZERS = /* @__PURE__ */ new Set([
|
|
1026
|
+
"frontmatter-invalid",
|
|
1027
|
+
"frontmatter-malformed",
|
|
1028
|
+
// Audit L1: parser parse-error is emitted by
|
|
1029
|
+
// `buildFreshNodeAndValidateFrontmatter` from `raw.parseIssues`. The
|
|
1030
|
+
// raw.parseIssues only flows through the non-cache path; a cached
|
|
1031
|
+
// node skips the rebuild, so the prior issue MUST survive the
|
|
1032
|
+
// incremental scan or the warning silently disappears on a clean
|
|
1033
|
+
// re-scan of an unchanged file.
|
|
1034
|
+
"frontmatter-parse-error"
|
|
1035
|
+
]);
|
|
997
1036
|
function indexPriorFrontmatterIssues(issues, byNode) {
|
|
998
1037
|
for (const issue of issues) {
|
|
999
|
-
if (
|
|
1038
|
+
if (!FRONTMATTER_ISSUE_ANALYZERS.has(issue.analyzerId)) continue;
|
|
1000
1039
|
if (issue.nodeIds.length !== 1) continue;
|
|
1001
1040
|
const path = issue.nodeIds[0];
|
|
1002
1041
|
const list = byNode.get(path);
|
|
@@ -1195,7 +1234,7 @@ function flagAmbiguousRenames(opts) {
|
|
|
1195
1234
|
analyzerId: "auto-rename-ambiguous",
|
|
1196
1235
|
severity: "warn",
|
|
1197
1236
|
nodeIds: [toPath],
|
|
1198
|
-
message: `Auto-rename ambiguous: ${toPath} matches ${remaining.length} prior frontmatters
|
|
1237
|
+
message: `Auto-rename ambiguous: ${toPath} matches ${remaining.length} prior frontmatters; pick one with \`sm orphans undo-rename ${toPath} --from <old.path>\`.`,
|
|
1199
1238
|
data: { to: toPath, candidates: remaining }
|
|
1200
1239
|
});
|
|
1201
1240
|
}
|
|
@@ -1252,7 +1291,7 @@ function detectRenamesAndOrphans(prior, current, issues) {
|
|
|
1252
1291
|
}
|
|
1253
1292
|
|
|
1254
1293
|
// kernel/scan/walk-content.ts
|
|
1255
|
-
import { readFile, readdir,
|
|
1294
|
+
import { readFile, readdir, lstat } from "fs/promises";
|
|
1256
1295
|
import { join as join2, relative as relative2, sep } from "path";
|
|
1257
1296
|
|
|
1258
1297
|
// kernel/scan/ignore.ts
|
|
@@ -1310,8 +1349,30 @@ function readDefaultsFromDisk() {
|
|
|
1310
1349
|
|
|
1311
1350
|
// built-in-plugins/parsers/frontmatter-yaml/index.ts
|
|
1312
1351
|
import yaml from "js-yaml";
|
|
1352
|
+
|
|
1353
|
+
// kernel/util/strip-prototype-pollution.ts
|
|
1354
|
+
var FORBIDDEN_KEYS = /* @__PURE__ */ new Set([
|
|
1355
|
+
"__proto__",
|
|
1356
|
+
"constructor",
|
|
1357
|
+
"prototype"
|
|
1358
|
+
]);
|
|
1359
|
+
function stripPrototypePollution(value) {
|
|
1360
|
+
return strip(value);
|
|
1361
|
+
}
|
|
1362
|
+
function strip(value) {
|
|
1363
|
+
if (value === null || value === void 0) return value;
|
|
1364
|
+
if (typeof value !== "object") return value;
|
|
1365
|
+
if (Array.isArray(value)) return value.map(strip);
|
|
1366
|
+
const out = {};
|
|
1367
|
+
for (const [k, v] of Object.entries(value)) {
|
|
1368
|
+
if (FORBIDDEN_KEYS.has(k)) continue;
|
|
1369
|
+
out[k] = strip(v);
|
|
1370
|
+
}
|
|
1371
|
+
return out;
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
// built-in-plugins/parsers/frontmatter-yaml/index.ts
|
|
1313
1375
|
var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
1314
|
-
var FORBIDDEN_FRONTMATTER_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
1315
1376
|
var frontmatterYamlParser = {
|
|
1316
1377
|
id: "frontmatter-yaml",
|
|
1317
1378
|
parse(raw, _path) {
|
|
@@ -1319,20 +1380,30 @@ var frontmatterYamlParser = {
|
|
|
1319
1380
|
if (!match) return { frontmatterRaw: "", frontmatter: {}, body: raw };
|
|
1320
1381
|
const frontmatterRaw = match[1];
|
|
1321
1382
|
const body = match[2];
|
|
1322
|
-
|
|
1383
|
+
let parsed = {};
|
|
1384
|
+
const issues = [];
|
|
1323
1385
|
try {
|
|
1324
1386
|
const doc = yaml.load(frontmatterRaw, { schema: yaml.JSON_SCHEMA });
|
|
1325
1387
|
if (doc && typeof doc === "object" && !Array.isArray(doc)) {
|
|
1326
|
-
|
|
1327
|
-
if (FORBIDDEN_FRONTMATTER_KEYS.has(k)) continue;
|
|
1328
|
-
parsed[k] = v;
|
|
1329
|
-
}
|
|
1388
|
+
parsed = stripPrototypePollution(doc);
|
|
1330
1389
|
}
|
|
1331
|
-
} catch {
|
|
1390
|
+
} catch (err) {
|
|
1391
|
+
issues.push({
|
|
1392
|
+
code: "frontmatter-parse-error",
|
|
1393
|
+
message: sanitiseParseErrorMessage(err)
|
|
1394
|
+
});
|
|
1332
1395
|
}
|
|
1333
|
-
|
|
1396
|
+
const out = { frontmatterRaw, frontmatter: parsed, body };
|
|
1397
|
+
if (issues.length > 0) {
|
|
1398
|
+
return { ...out, issues };
|
|
1399
|
+
}
|
|
1400
|
+
return out;
|
|
1334
1401
|
}
|
|
1335
1402
|
};
|
|
1403
|
+
function sanitiseParseErrorMessage(err) {
|
|
1404
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
1405
|
+
return raw.replace(/[-]+/g, " ").replace(/\s+/g, " ").trim();
|
|
1406
|
+
}
|
|
1336
1407
|
|
|
1337
1408
|
// built-in-plugins/parsers/plain/index.ts
|
|
1338
1409
|
var plainParser = {
|
|
@@ -1378,7 +1449,12 @@ async function* walkContent(roots, options) {
|
|
|
1378
1449
|
path: relPath,
|
|
1379
1450
|
body: parsed.body,
|
|
1380
1451
|
frontmatterRaw: parsed.frontmatterRaw,
|
|
1381
|
-
frontmatter: parsed.frontmatter
|
|
1452
|
+
frontmatter: parsed.frontmatter,
|
|
1453
|
+
// Audit L1: forward parser diagnostics (e.g. malformed YAML)
|
|
1454
|
+
// through the IRawNode surface so the orchestrator can
|
|
1455
|
+
// convert them into warn-level kernel `Issue` rows. Omitted
|
|
1456
|
+
// when the parser reported no issues (happy path).
|
|
1457
|
+
...parsed.issues && parsed.issues.length > 0 ? { parseIssues: parsed.issues } : {}
|
|
1382
1458
|
};
|
|
1383
1459
|
}
|
|
1384
1460
|
}
|
|
@@ -1400,7 +1476,7 @@ async function* walkRoot(root, current, filter, extensions) {
|
|
|
1400
1476
|
yield* walkRoot(root, full, filter, extensions);
|
|
1401
1477
|
} else if (entry.isFile() && hasMatchingExtension(name, extensions)) {
|
|
1402
1478
|
try {
|
|
1403
|
-
const s = await
|
|
1479
|
+
const s = await lstat(full);
|
|
1404
1480
|
if (s.isFile()) yield full;
|
|
1405
1481
|
} catch {
|
|
1406
1482
|
}
|
|
@@ -1466,6 +1542,7 @@ function readSidecarFor(mdAbsolutePath) {
|
|
|
1466
1542
|
issues: [{ message: `malformed YAML in ${sidecarPath}: ${err.message}` }]
|
|
1467
1543
|
};
|
|
1468
1544
|
}
|
|
1545
|
+
parsedYaml = stripPrototypePollution(parsedYaml);
|
|
1469
1546
|
if (!isPlainObject(parsedYaml)) {
|
|
1470
1547
|
return {
|
|
1471
1548
|
parsed: null,
|
|
@@ -1531,7 +1608,7 @@ function resolveSpecRoot2() {
|
|
|
1531
1608
|
return dirname3(indexPath);
|
|
1532
1609
|
} catch {
|
|
1533
1610
|
throw new Error(
|
|
1534
|
-
"@skill-map/spec not resolvable
|
|
1611
|
+
"@skill-map/spec not resolvable: sidecar reader cannot load schemas."
|
|
1535
1612
|
);
|
|
1536
1613
|
}
|
|
1537
1614
|
}
|
|
@@ -1588,17 +1665,32 @@ function safeIsFile(path) {
|
|
|
1588
1665
|
}
|
|
1589
1666
|
|
|
1590
1667
|
// kernel/sidecar/store.ts
|
|
1591
|
-
import { existsSync as existsSync7, readFileSync as readFileSync8
|
|
1668
|
+
import { existsSync as existsSync7, readFileSync as readFileSync8 } from "fs";
|
|
1592
1669
|
import { dirname as dirname5, resolve as resolve9 } from "path";
|
|
1593
1670
|
import { createRequire as createRequire4 } from "module";
|
|
1594
1671
|
import { Ajv2020 as Ajv20205 } from "ajv/dist/2020.js";
|
|
1595
1672
|
import yaml3 from "js-yaml";
|
|
1596
1673
|
|
|
1674
|
+
// core/config/atomic-write.ts
|
|
1675
|
+
import {
|
|
1676
|
+
closeSync,
|
|
1677
|
+
constants as fsConstants,
|
|
1678
|
+
existsSync as existsSync5,
|
|
1679
|
+
mkdirSync,
|
|
1680
|
+
openSync,
|
|
1681
|
+
readFileSync as readFileSync6,
|
|
1682
|
+
renameSync,
|
|
1683
|
+
unlinkSync,
|
|
1684
|
+
writeSync
|
|
1685
|
+
} from "fs";
|
|
1686
|
+
import { randomBytes } from "crypto";
|
|
1687
|
+
import { dirname as dirname4 } from "path";
|
|
1688
|
+
|
|
1597
1689
|
// core/config/helper.ts
|
|
1598
1690
|
import { isAbsolute as isAbsolute2, resolve as resolve8 } from "path";
|
|
1599
1691
|
|
|
1600
1692
|
// kernel/config/loader.ts
|
|
1601
|
-
import { existsSync as
|
|
1693
|
+
import { existsSync as existsSync6, readFileSync as readFileSync7 } from "fs";
|
|
1602
1694
|
|
|
1603
1695
|
// kernel/util/skill-map-paths.ts
|
|
1604
1696
|
import { join as join5 } from "path";
|
|
@@ -1614,17 +1706,6 @@ var GITIGNORE_ENTRIES = [
|
|
|
1614
1706
|
`${SKILL_MAP_DIR}/${DB_FILENAME}`
|
|
1615
1707
|
];
|
|
1616
1708
|
|
|
1617
|
-
// core/config/atomic-write.ts
|
|
1618
|
-
import {
|
|
1619
|
-
existsSync as existsSync6,
|
|
1620
|
-
mkdirSync,
|
|
1621
|
-
readFileSync as readFileSync7,
|
|
1622
|
-
renameSync,
|
|
1623
|
-
unlinkSync,
|
|
1624
|
-
writeFileSync
|
|
1625
|
-
} from "fs";
|
|
1626
|
-
import { dirname as dirname4 } from "path";
|
|
1627
|
-
|
|
1628
1709
|
// kernel/orchestrator/node-build.ts
|
|
1629
1710
|
import { createHash } from "crypto";
|
|
1630
1711
|
import { existsSync as existsSync8 } from "fs";
|
|
@@ -1773,11 +1854,11 @@ function resolveSidecarOverlay(relativePath, nodePathForIssue, roots, liveBodyHa
|
|
|
1773
1854
|
liveFrontmatterHash
|
|
1774
1855
|
});
|
|
1775
1856
|
return {
|
|
1776
|
-
// R15 closure (2026-05-07)
|
|
1857
|
+
// R15 closure (2026-05-07), surface the full parsed root on the
|
|
1777
1858
|
// overlay so BFF consumers (UI inspector audit / plugin-contributions
|
|
1778
1859
|
// / debug panels) can read `for.*`, `audit.*`, `settings.*`, and
|
|
1779
1860
|
// plugin-namespaced sub-keys without re-reading the file. The
|
|
1780
|
-
// `annotations` field above stays
|
|
1861
|
+
// `annotations` field above stays, it duplicates `root.annotations`
|
|
1781
1862
|
// by design so existing consumers keep working unchanged.
|
|
1782
1863
|
overlay: {
|
|
1783
1864
|
present: true,
|
|
@@ -1821,6 +1902,16 @@ function buildFreshNodeAndValidateFrontmatter(opts) {
|
|
|
1821
1902
|
encoder: opts.encoder
|
|
1822
1903
|
});
|
|
1823
1904
|
const frontmatterIssues = [];
|
|
1905
|
+
if (opts.raw.parseIssues && opts.raw.parseIssues.length > 0) {
|
|
1906
|
+
for (const pi of opts.raw.parseIssues) {
|
|
1907
|
+
frontmatterIssues.push({
|
|
1908
|
+
analyzerId: pi.code,
|
|
1909
|
+
severity: opts.strict ? "error" : "warn",
|
|
1910
|
+
nodeIds: [opts.raw.path],
|
|
1911
|
+
message: pi.message
|
|
1912
|
+
});
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1824
1915
|
if (opts.raw.frontmatterRaw.length > 0) {
|
|
1825
1916
|
const fmIssue = validateFrontmatter(
|
|
1826
1917
|
opts.providerFrontmatter,
|
|
@@ -1847,10 +1938,9 @@ function mergeNodeWithEnrichments(node, enrichments, opts = {}) {
|
|
|
1847
1938
|
}
|
|
1848
1939
|
return base;
|
|
1849
1940
|
}
|
|
1850
|
-
var FORBIDDEN_MERGE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
1851
1941
|
function assignSafe(target, source) {
|
|
1852
|
-
|
|
1853
|
-
|
|
1942
|
+
const safe = stripPrototypePollution(source);
|
|
1943
|
+
for (const [k, v] of Object.entries(safe)) {
|
|
1854
1944
|
target[k] = v;
|
|
1855
1945
|
}
|
|
1856
1946
|
}
|
|
@@ -2129,6 +2219,9 @@ async function runScanInternal(_kernel, options) {
|
|
|
2129
2219
|
recomputeLinkCounts(walked.nodes, walked.internalLinks);
|
|
2130
2220
|
recomputeExternalRefsCount(walked.nodes, walked.externalLinks, walked.cachedPaths);
|
|
2131
2221
|
await dispatchExtractorCompleted(exts.extractors, emitter, hookDispatcher);
|
|
2222
|
+
const registeredActionIds = new Set(
|
|
2223
|
+
_kernel.registry.all("action").map((a) => qualifiedExtensionId(a.pluginId, a.id))
|
|
2224
|
+
);
|
|
2132
2225
|
const analyzerResult = await runAnalyzers(
|
|
2133
2226
|
exts.analyzers,
|
|
2134
2227
|
walked.nodes,
|
|
@@ -2140,6 +2233,7 @@ async function runScanInternal(_kernel, options) {
|
|
|
2140
2233
|
options.orphanJobFiles ?? [],
|
|
2141
2234
|
options.referenceablePaths,
|
|
2142
2235
|
options.cwd,
|
|
2236
|
+
registeredActionIds,
|
|
2143
2237
|
emitter,
|
|
2144
2238
|
hookDispatcher
|
|
2145
2239
|
);
|
|
@@ -2261,7 +2355,8 @@ function createChokidarWatcher(opts) {
|
|
|
2261
2355
|
const watcher = chokidar.watch(absRoots, {
|
|
2262
2356
|
ignoreInitial: true,
|
|
2263
2357
|
persistent: true,
|
|
2264
|
-
...ignored ? { ignored } : {}
|
|
2358
|
+
...ignored ? { ignored } : {},
|
|
2359
|
+
...opts.depth !== void 0 ? { depth: opts.depth } : {}
|
|
2265
2360
|
});
|
|
2266
2361
|
let pending = [];
|
|
2267
2362
|
let timer = null;
|