@skill-map/cli 0.52.0 → 0.53.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/SKILL.md +239 -1659
- package/dist/cli/tutorial/sm-tutorial/references/_core.md +332 -0
- package/dist/cli/tutorial/sm-tutorial/references/_manifest.yml +175 -0
- package/dist/cli/tutorial/sm-tutorial/references/fixtures.md +251 -0
- package/dist/cli/tutorial/{sm-master/references/tour-authoring.md → sm-tutorial/references/part-authoring.md} +14 -15
- package/dist/cli/tutorial/sm-tutorial/references/part-cli.md +267 -0
- package/dist/cli/tutorial/sm-tutorial/references/part-connect-harness.md +180 -0
- package/dist/cli/tutorial/sm-tutorial/references/part-fundamentals.md +424 -0
- package/dist/cli/tutorial/sm-tutorial/references/part-live-site.md +156 -0
- package/dist/cli/tutorial/sm-tutorial/references/part-maintain.md +286 -0
- package/dist/cli/tutorial/sm-tutorial/references/part-mcp.md +78 -0
- package/dist/cli/tutorial/{sm-master/references/tour-plugins.md → sm-tutorial/references/part-plugins.md} +11 -11
- package/dist/cli/tutorial/sm-tutorial/references/part-project-kickoff.md +186 -0
- package/dist/cli/tutorial/{sm-master/references/tour-settings.md → sm-tutorial/references/part-settings.md} +22 -24
- package/dist/cli.js +1213 -550
- package/dist/index.d.ts +1 -1
- package/dist/index.js +334 -207
- package/dist/kernel/index.d.ts +320 -15
- package/dist/kernel/index.js +334 -207
- package/dist/migrations/001_initial.sql +36 -0
- package/dist/ui/chunk-EQ72PEHT.js +1 -0
- package/dist/ui/chunk-GBKHMJ4B.js +1110 -0
- package/dist/ui/chunk-GEI6INVH.js +515 -0
- package/dist/ui/chunk-JXRIGHET.js +552 -0
- package/dist/ui/{chunk-WQMZOINB.js → chunk-K2MAVAHG.js} +1 -1
- package/dist/ui/{chunk-BV323KTK.js → chunk-KHARMPTZ.js} +1 -1
- package/dist/ui/chunk-L4NIF75A.js +2 -0
- package/dist/ui/chunk-LCOYSPKE.js +1 -0
- package/dist/ui/chunk-OFDQMBSJ.js +1 -0
- package/dist/ui/chunk-P2DAPRK7.js +2 -0
- package/dist/ui/chunk-Q2A6FWC7.js +4 -0
- package/dist/ui/{chunk-ZNDMBION.js → chunk-TXTY24G4.js} +28 -30
- package/dist/ui/chunk-UBQUCSQ4.js +1 -0
- package/dist/ui/chunk-WFLPMCK4.js +392 -0
- package/dist/ui/chunk-YQFIXHKM.js +123 -0
- package/dist/ui/index.html +2 -2
- package/dist/ui/{main-2DWVSRRX.js → main-OYITFJ7B.js} +3 -3
- package/dist/ui/{styles-QBTVKEVX.css → styles-Q4NCOJQY.css} +1 -1
- package/migrations/001_initial.sql +36 -0
- package/package.json +10 -8
- package/dist/cli/tutorial/sm-master/SKILL.md +0 -688
- package/dist/cli/tutorial/sm-master/references/fixture-templates.md +0 -212
- package/dist/ui/chunk-5MCXQKRN.js +0 -1066
- package/dist/ui/chunk-6B5EAHIM.js +0 -1110
- package/dist/ui/chunk-AEA5GIA7.js +0 -1
- package/dist/ui/chunk-AQN27TN2.js +0 -123
- package/dist/ui/chunk-CAJ7ZI44.js +0 -1
- package/dist/ui/chunk-E2XO4JVD.js +0 -1
- package/dist/ui/chunk-VJ57LHDR.js +0 -4
- package/dist/ui/chunk-WMGW2UAL.js +0 -2
package/dist/kernel/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// kernel/i18n/registry.texts.ts
|
|
2
2
|
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="5a40a4c9-3996-540c-b687-874d383944d0")}catch(e){}}();
|
|
4
4
|
var REGISTRY_TEXTS = {
|
|
5
5
|
duplicateExtension: "Extension already registered: {{kind}}:{{qualifiedId}}",
|
|
6
6
|
unknownKind: "Unknown extension kind: {{kind}}",
|
|
@@ -102,7 +102,7 @@ import { Tiktoken as Tiktoken2 } from "js-tiktoken/lite";
|
|
|
102
102
|
// package.json
|
|
103
103
|
var package_default = {
|
|
104
104
|
name: "@skill-map/cli",
|
|
105
|
-
version: "0.
|
|
105
|
+
version: "0.53.0",
|
|
106
106
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
107
107
|
license: "MIT",
|
|
108
108
|
type: "module",
|
|
@@ -160,15 +160,16 @@ var package_default = {
|
|
|
160
160
|
prebuild: "pnpm build-built-ins",
|
|
161
161
|
validate: "pnpm validate:compile && pnpm validate:test",
|
|
162
162
|
"validate:compile": "pnpm typecheck && pnpm lint && pnpm build && pnpm built-ins:check && pnpm view-catalog:check",
|
|
163
|
-
"validate:test": "pnpm test:ci",
|
|
163
|
+
"validate:test": "pnpm test:ci && pnpm conformance",
|
|
164
|
+
conformance: "SKILL_MAP_TELEMETRY=0 SM_NO_UPDATE_CHECK=1 node --import tsx cli/entry.ts conformance run",
|
|
164
165
|
pretest: "tsup",
|
|
165
166
|
"pretest:coverage": "tsup",
|
|
166
167
|
"pretest:coverage:html": "tsup",
|
|
167
|
-
test: "tsc --noEmit && SKILL_MAP_TELEMETRY=0 node --import tsx --test --test-reporter=./scripts/test-reporter.js --test-reporter-destination=stdout '__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:ci": "FORCE_COLOR=1 SKILL_MAP_TELEMETRY=0 node --import tsx --test --test-reporter=./scripts/test-reporter.js --test-reporter-destination=stdout '__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'",
|
|
169
|
-
"test:spec": "SKILL_MAP_TELEMETRY=0 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'",
|
|
170
|
-
"test:coverage": "tsc --noEmit && SKILL_MAP_TELEMETRY=0 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'",
|
|
171
|
-
"test:coverage:html": "tsc --noEmit && SKILL_MAP_TELEMETRY=0 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'",
|
|
168
|
+
test: "tsc --noEmit && SKILL_MAP_TELEMETRY=0 SM_NO_UPDATE_CHECK=1 node --import tsx --test --test-reporter=./scripts/test-reporter.js --test-reporter-destination=stdout '__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'",
|
|
169
|
+
"test:ci": "FORCE_COLOR=1 SKILL_MAP_TELEMETRY=0 SM_NO_UPDATE_CHECK=1 node --import tsx --test --test-reporter=./scripts/test-reporter.js --test-reporter-destination=stdout '__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'",
|
|
170
|
+
"test:spec": "SKILL_MAP_TELEMETRY=0 SM_NO_UPDATE_CHECK=1 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'",
|
|
171
|
+
"test:coverage": "tsc --noEmit && SKILL_MAP_TELEMETRY=0 SM_NO_UPDATE_CHECK=1 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'",
|
|
172
|
+
"test:coverage:html": "tsc --noEmit && SKILL_MAP_TELEMETRY=0 SM_NO_UPDATE_CHECK=1 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'",
|
|
172
173
|
clean: "rm -rf dist coverage"
|
|
173
174
|
},
|
|
174
175
|
dependencies: {
|
|
@@ -200,6 +201,7 @@ var package_default = {
|
|
|
200
201
|
c8: "11.0.0",
|
|
201
202
|
eslint: "10.2.1",
|
|
202
203
|
"eslint-plugin-import-x": "4.16.2",
|
|
204
|
+
"json-schema-to-typescript": "15.0.4",
|
|
203
205
|
tsup: "8.5.1",
|
|
204
206
|
tsx: "4.22.3",
|
|
205
207
|
typescript: "5.9.3",
|
|
@@ -228,150 +230,54 @@ var InMemoryProgressEmitter = class {
|
|
|
228
230
|
};
|
|
229
231
|
|
|
230
232
|
// kernel/adapters/plugin-loader/index.ts
|
|
231
|
-
import { createRequire } from "module";
|
|
232
|
-
import { existsSync as existsSync2, readFileSync as
|
|
233
|
-
import { join as join2, resolve as
|
|
233
|
+
import { createRequire as createRequire2 } from "module";
|
|
234
|
+
import { existsSync as existsSync2, readFileSync as readFileSync4, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
235
|
+
import { join as join2, resolve as resolve4 } from "path";
|
|
234
236
|
import { pathToFileURL } from "url";
|
|
235
237
|
import semver from "semver";
|
|
236
238
|
|
|
237
|
-
// kernel/
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
//
|
|
254
|
-
|
|
255
|
-
"
|
|
256
|
-
"
|
|
257
|
-
"
|
|
258
|
-
"
|
|
259
|
-
"
|
|
260
|
-
"
|
|
261
|
-
"
|
|
262
|
-
"
|
|
263
|
-
"
|
|
264
|
-
"
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
"
|
|
270
|
-
"
|
|
271
|
-
"
|
|
272
|
-
"action",
|
|
273
|
-
"formatter",
|
|
274
|
-
"hook"
|
|
275
|
-
]);
|
|
276
|
-
var KNOWN_KINDS_LIST = [...KNOWN_KINDS].join(" / ");
|
|
277
|
-
var HOOKABLE_TRIGGERS_LIST = HOOK_TRIGGERS.join(", ");
|
|
278
|
-
|
|
279
|
-
// kernel/adapters/plugin-loader/storage-schemas.ts
|
|
280
|
-
import { readFileSync as readFileSync2 } from "fs";
|
|
281
|
-
import { resolve as resolve2 } from "path";
|
|
282
|
-
import { Ajv2020 as Ajv20202 } from "ajv/dist/2020.js";
|
|
283
|
-
|
|
284
|
-
// kernel/i18n/plugin-store.texts.ts
|
|
285
|
-
var PLUGIN_STORE_TEXTS = {
|
|
286
|
-
kvValidationFailed: "plugin '{{pluginId}}' ctx.store.set('{{key}}', value): value violates declared schema ({{schemaPath}}): {{errors}}",
|
|
287
|
-
dedicatedValidationFailed: "plugin '{{pluginId}}' ctx.store.write('{{table}}', row): row violates declared schema ({{schemaPath}}): {{errors}}"
|
|
239
|
+
// kernel/i18n/plugin-loader.texts.ts
|
|
240
|
+
var SPEC_GITHUB_BASE = "https://github.com/crystian/skill-map/blob/main";
|
|
241
|
+
var PLUGIN_LOADER_TEXTS = {
|
|
242
|
+
invalidManifestJsonParse: "{{manifestPath}}: {{errDescription}}. Validate the JSON (e.g. `npx jsonlint plugin.json`).",
|
|
243
|
+
invalidManifestAjv: `{{manifestPath}}: {{errors}}. See ${SPEC_GITHUB_BASE}/spec/schemas/plugins-registry.schema.json#/$defs/PluginManifest.`,
|
|
244
|
+
invalidSpecCompat: 'specCompat "{{specCompat}}" is not a valid semver range. Use a range like "^1.0.0".',
|
|
245
|
+
incompatibleSpec: `@skill-map/spec {{installedSpecVersion}} does not satisfy specCompat "{{specCompat}}". Either update the plugin's specCompat (and re-test) or pin sm to a compatible spec version.`,
|
|
246
|
+
loadErrorFileNotFound: "extension file not found: {{relEntry}} (resolved to {{abs}}). Check plugin.json#/extensions paths.",
|
|
247
|
+
loadErrorImportFailed: "{{relEntry}}: import failed: {{errDescription}}",
|
|
248
|
+
loadErrorMissingKind: "{{relEntry}}: default export missing a string `kind` field. Expected one of: {{knownKindsList}}.",
|
|
249
|
+
loadErrorUnknownKind: '{{relEntry}}: unknown extension kind "{{kindReceived}}". Expected one of: {{knownKindsList}}.',
|
|
250
|
+
// No "manifest invalid" framing here: the warning wrapper already
|
|
251
|
+
// carries the `(invalid-manifest)` status, so this reason is just the
|
|
252
|
+
// file + the specific error + the doc link. `{{docUrl}}` is chosen by
|
|
253
|
+
// the caller: a bad view-slot value points to the slot catalog
|
|
254
|
+
// (`spec/view-slots.md`), every other manifest-shape error to the kind
|
|
255
|
+
// schema. Both are GitHub blob URLs.
|
|
256
|
+
invalidManifestExtensionShape: "{{relEntry}}: {{errors}}. See {{docUrl}}.",
|
|
257
|
+
importExceededTimeout: "import exceeded {{timeoutMs}}ms; likely a top-level side effect (network call, infinite loop, large blocking work). Move side effects into the runtime methods (`detect` / `evaluate` / `render` / etc.).",
|
|
258
|
+
disabledByConfig: "disabled by config_plugins or settings.json",
|
|
259
|
+
invalidManifestDirMismatch: "directory name '{{dirName}}' does not match manifest id '{{manifestId}}'. Rename the directory to match the id, or update the manifest id to match the directory.",
|
|
260
|
+
idCollision: "Plugin '{{id}}' at {{pathA}} collides with the plugin at {{pathB}}. Rename one and rerun.",
|
|
261
|
+
loadErrorPluginIdMismatch: "{{relEntry}}: extension declares pluginId '{{declared}}' but its plugin.json declares id '{{manifestId}}'. Remove the explicit pluginId from the extension; the loader injects it from plugin.json#/id.",
|
|
262
|
+
invalidManifestRedeclaredField: "{{relEntry}}: extension manifest declares {{fields}}, derived from the folder layout (structure-as-truth) and not a manifest field. Remove it: id is the leaf folder, kind the parent folder, provider kinds the `kinds/` catalog, formatter formatId the formatter folder name.",
|
|
263
|
+
loadErrorStorageSchemaRead: "plugin '{{pluginId}}' failed to load schema for table '{{table}}': {{schemaPath}}: {{errDescription}}",
|
|
264
|
+
loadErrorStorageSchemaCompile: "plugin '{{pluginId}}' failed to compile schema for table '{{table}}': {{schemaPath}}: {{errDescription}}",
|
|
265
|
+
loadErrorStorageKvSchemaRead: "plugin '{{pluginId}}' failed to load KV schema: {{schemaPath}}: {{errDescription}}",
|
|
266
|
+
loadErrorStorageKvSchemaCompile: "plugin '{{pluginId}}' failed to compile KV schema: {{schemaPath}}: {{errDescription}}",
|
|
267
|
+
invalidManifestHookUnknownTrigger: "Hook '{{hookId}}' declares unknown trigger '{{trigger}}'. Hookable triggers: {{hookableList}}.",
|
|
268
|
+
invalidManifestHookEmptyTriggers: "Hook '{{hookId}}' declares no triggers. At least one entry from the curated set is required.",
|
|
269
|
+
loadErrorPathEscapesPlugin: "extension entry '{{relEntry}}' resolves outside the plugin directory ({{pluginPath}}). Plugin entries must be relative paths inside the plugin tree.",
|
|
270
|
+
loadErrorSchemaPathEscapesPlugin: "schema path '{{relPath}}' resolves outside the plugin directory ({{pluginPath}}). Plugin schemas must be relative paths inside the plugin tree.",
|
|
271
|
+
invalidManifestRootSharedAnnotation: "{{relEntry}}: annotationContributions['{{key}}'] declares location: 'root' with ownership: '{{ownership}}'; root keys MUST be 'exclusive' (a top-level reserved key cannot be silently shared between plugins).",
|
|
272
|
+
invalidManifestAnnotationSchemaCompile: "{{relEntry}}: annotationContributions['{{key}}'].schema is not a valid JSON Schema: {{errDescription}}",
|
|
273
|
+
fatalAnnotationRootCollision: "Annotation root-key collision: '{{key}}' is claimed with ownership: 'exclusive' by multiple plugins ({{plugins}}). The kernel cannot boot with this configuration. Rename or merge the contributions and rerun."
|
|
288
274
|
};
|
|
289
275
|
|
|
290
|
-
// kernel/adapters/plugin-store.ts
|
|
291
|
-
var KV_SCHEMA_KEY = "__kv__";
|
|
292
|
-
function makeKvStoreWrapper(opts) {
|
|
293
|
-
const { pluginId, schema, persist } = opts;
|
|
294
|
-
return {
|
|
295
|
-
async set(key, value) {
|
|
296
|
-
if (schema) {
|
|
297
|
-
if (!schema.validate(value)) {
|
|
298
|
-
throw new Error(
|
|
299
|
-
tx(PLUGIN_STORE_TEXTS.kvValidationFailed, {
|
|
300
|
-
pluginId,
|
|
301
|
-
schemaPath: schema.schemaPath,
|
|
302
|
-
key,
|
|
303
|
-
errors: formatAjvErrors(schema.validate.errors ?? null)
|
|
304
|
-
})
|
|
305
|
-
);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
await persist(key, value);
|
|
309
|
-
}
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
function makeDedicatedStoreWrapper(opts) {
|
|
313
|
-
const { pluginId, schemas, persist } = opts;
|
|
314
|
-
return {
|
|
315
|
-
async write(table, row) {
|
|
316
|
-
const schema = schemas?.[table];
|
|
317
|
-
if (schema) {
|
|
318
|
-
if (!schema.validate(row)) {
|
|
319
|
-
throw new Error(
|
|
320
|
-
tx(PLUGIN_STORE_TEXTS.dedicatedValidationFailed, {
|
|
321
|
-
pluginId,
|
|
322
|
-
table,
|
|
323
|
-
schemaPath: schema.schemaPath,
|
|
324
|
-
errors: formatAjvErrors(schema.validate.errors ?? null)
|
|
325
|
-
})
|
|
326
|
-
);
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
await persist(table, row);
|
|
330
|
-
}
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
function makePluginStore(opts) {
|
|
334
|
-
const manifest = opts.plugin.manifest;
|
|
335
|
-
if (!manifest?.storage) return void 0;
|
|
336
|
-
const storageSchemas = opts.plugin.storageSchemas;
|
|
337
|
-
if (manifest.storage.mode === "kv") {
|
|
338
|
-
if (!opts.persistKv) return void 0;
|
|
339
|
-
const schema = storageSchemas?.[KV_SCHEMA_KEY];
|
|
340
|
-
return makeKvStoreWrapper({
|
|
341
|
-
pluginId: opts.plugin.id,
|
|
342
|
-
schema,
|
|
343
|
-
persist: opts.persistKv
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
if (manifest.storage.mode === "dedicated") {
|
|
347
|
-
if (!opts.persistDedicated) return void 0;
|
|
348
|
-
return makeDedicatedStoreWrapper({
|
|
349
|
-
pluginId: opts.plugin.id,
|
|
350
|
-
schemas: storageSchemas,
|
|
351
|
-
persist: opts.persistDedicated
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
|
-
return void 0;
|
|
355
|
-
}
|
|
356
|
-
function formatAjvErrors(errors) {
|
|
357
|
-
if (!errors || errors.length === 0) return "(no AJV details)";
|
|
358
|
-
return errors.map((e) => `${e.instancePath || "(root)"} ${e.message ?? e.keyword}`).join("; ");
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
// kernel/adapters/plugin-loader/index.ts
|
|
362
|
-
function installedSpecVersion() {
|
|
363
|
-
const require2 = createRequire(import.meta.url);
|
|
364
|
-
const indexPath = require2.resolve("@skill-map/spec/index.json");
|
|
365
|
-
const pkgPath = resolve3(indexPath, "..", "package.json");
|
|
366
|
-
const pkg = JSON.parse(readFileSync3(pkgPath, "utf8"));
|
|
367
|
-
return pkg.version;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
276
|
// kernel/adapters/schema-validators.ts
|
|
371
|
-
import { readFileSync
|
|
372
|
-
import { dirname
|
|
373
|
-
import { createRequire
|
|
374
|
-
import { Ajv2020
|
|
277
|
+
import { readFileSync } from "fs";
|
|
278
|
+
import { dirname, resolve } from "path";
|
|
279
|
+
import { createRequire } from "module";
|
|
280
|
+
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
375
281
|
|
|
376
282
|
// kernel/types/view-catalog.generated.ts
|
|
377
283
|
var ALL_SLOT_NAMES = [
|
|
@@ -380,8 +286,8 @@ var ALL_SLOT_NAMES = [
|
|
|
380
286
|
"card.footer.left",
|
|
381
287
|
"card.footer.right",
|
|
382
288
|
"graph.node.alert",
|
|
383
|
-
"inspector.header.badge
|
|
384
|
-
"inspector.
|
|
289
|
+
"inspector.header.badge",
|
|
290
|
+
"inspector.action.button",
|
|
385
291
|
"inspector.body.panel.breakdown",
|
|
386
292
|
"inspector.body.panel.records",
|
|
387
293
|
"inspector.body.panel.tree",
|
|
@@ -392,6 +298,13 @@ var ALL_SLOT_NAMES = [
|
|
|
392
298
|
];
|
|
393
299
|
var KNOWN_SLOT_NAMES = new Set(ALL_SLOT_NAMES);
|
|
394
300
|
|
|
301
|
+
// kernel/util/ajv-interop.ts
|
|
302
|
+
import addFormatsModule from "ajv-formats";
|
|
303
|
+
var addFormats = addFormatsModule.default ?? addFormatsModule;
|
|
304
|
+
function applyAjvFormats(ajv) {
|
|
305
|
+
addFormats(ajv);
|
|
306
|
+
}
|
|
307
|
+
|
|
395
308
|
// kernel/adapters/schema-validators.ts
|
|
396
309
|
var SCHEMA_FILES = {
|
|
397
310
|
node: "schemas/node.schema.json",
|
|
@@ -430,22 +343,22 @@ function loadSchemaValidators() {
|
|
|
430
343
|
}
|
|
431
344
|
function buildSchemaValidators() {
|
|
432
345
|
const specRoot = resolveSpecRoot();
|
|
433
|
-
const ajv = new
|
|
346
|
+
const ajv = new Ajv2020({
|
|
434
347
|
strict: false,
|
|
435
348
|
allErrors: true,
|
|
436
349
|
allowUnionTypes: true
|
|
437
350
|
});
|
|
438
351
|
applyAjvFormats(ajv);
|
|
439
352
|
for (const rel of SUPPORTING_SCHEMAS) {
|
|
440
|
-
const file =
|
|
353
|
+
const file = resolve(specRoot, rel);
|
|
441
354
|
if (!existsSyncSafe(file)) continue;
|
|
442
|
-
const schema = JSON.parse(
|
|
355
|
+
const schema = JSON.parse(readFileSync(file, "utf8"));
|
|
443
356
|
ajv.addSchema(schema);
|
|
444
357
|
}
|
|
445
358
|
const validators = /* @__PURE__ */ new Map();
|
|
446
359
|
for (const [name, rel] of Object.entries(SCHEMA_FILES)) {
|
|
447
|
-
const file =
|
|
448
|
-
const schema = JSON.parse(
|
|
360
|
+
const file = resolve(specRoot, rel);
|
|
361
|
+
const schema = JSON.parse(readFileSync(file, "utf8"));
|
|
449
362
|
const byId = typeof schema.$id === "string" ? ajv.getSchema(schema.$id) : void 0;
|
|
450
363
|
validators.set(name, byId ?? ajv.compile(schema));
|
|
451
364
|
}
|
|
@@ -489,12 +402,12 @@ function buildSchemaValidators() {
|
|
|
489
402
|
const v = validators.get(name);
|
|
490
403
|
if (!v) throw new Error(`Unknown schema: ${name}`);
|
|
491
404
|
if (v(data)) return { ok: true, data };
|
|
492
|
-
const errors = (v.errors
|
|
405
|
+
const errors = formatAjvErrors(v.errors);
|
|
493
406
|
return { ok: false, errors };
|
|
494
407
|
},
|
|
495
408
|
validatePluginManifest(data) {
|
|
496
409
|
if (pluginManifestValidator(data)) return { ok: true, data };
|
|
497
|
-
const errors = (pluginManifestValidator.errors
|
|
410
|
+
const errors = formatAjvErrors(pluginManifestValidator.errors);
|
|
498
411
|
return { ok: false, errors };
|
|
499
412
|
},
|
|
500
413
|
validateContributionPayload(slot, payload) {
|
|
@@ -503,21 +416,21 @@ function buildSchemaValidators() {
|
|
|
503
416
|
return { ok: false, errors: "unknown-slot" };
|
|
504
417
|
}
|
|
505
418
|
if (validator(payload)) return { ok: true };
|
|
506
|
-
const errors = (validator.errors
|
|
419
|
+
const errors = formatAjvErrors(validator.errors);
|
|
507
420
|
return { ok: false, errors };
|
|
508
421
|
}
|
|
509
422
|
};
|
|
510
423
|
}
|
|
511
424
|
function buildProviderFrontmatterValidator(providers) {
|
|
512
425
|
const specRoot = resolveSpecRoot();
|
|
513
|
-
const ajv = new
|
|
426
|
+
const ajv = new Ajv2020({
|
|
514
427
|
strict: false,
|
|
515
428
|
allErrors: true,
|
|
516
429
|
allowUnionTypes: true
|
|
517
430
|
});
|
|
518
431
|
applyAjvFormats(ajv);
|
|
519
|
-
const baseFile =
|
|
520
|
-
const baseSchema = JSON.parse(
|
|
432
|
+
const baseFile = resolve(specRoot, "schemas/frontmatter/base.schema.json");
|
|
433
|
+
const baseSchema = JSON.parse(readFileSync(baseFile, "utf8"));
|
|
521
434
|
ajv.addSchema(baseSchema);
|
|
522
435
|
registerProviderAuxiliarySchemas(ajv, providers);
|
|
523
436
|
const compiled = /* @__PURE__ */ new Map();
|
|
@@ -535,7 +448,7 @@ function buildProviderFrontmatterValidator(providers) {
|
|
|
535
448
|
const v = compiled.get(key);
|
|
536
449
|
if (!v) return { ok: false, errors: "no-schema" };
|
|
537
450
|
if (v(data)) return { ok: true };
|
|
538
|
-
const errors = (v.errors
|
|
451
|
+
const errors = formatAjvErrors(v.errors);
|
|
539
452
|
return { ok: false, errors };
|
|
540
453
|
}
|
|
541
454
|
};
|
|
@@ -544,6 +457,47 @@ function formatError(err) {
|
|
|
544
457
|
const path = err.instancePath || "(root)";
|
|
545
458
|
return `${path} ${err.message ?? err.keyword}`;
|
|
546
459
|
}
|
|
460
|
+
function formatAjvErrors(errors) {
|
|
461
|
+
const list = errors ?? [];
|
|
462
|
+
if (list.length === 0) return "";
|
|
463
|
+
const byPath2 = /* @__PURE__ */ new Map();
|
|
464
|
+
for (const e of list) {
|
|
465
|
+
const path = e.instancePath || "(root)";
|
|
466
|
+
const bucket = byPath2.get(path);
|
|
467
|
+
if (bucket) bucket.push(e);
|
|
468
|
+
else byPath2.set(path, [e]);
|
|
469
|
+
}
|
|
470
|
+
const parts = [];
|
|
471
|
+
for (const [path, errs] of byPath2) parts.push(...formatPathErrors(path, errs));
|
|
472
|
+
return [...new Set(parts)].join("; ");
|
|
473
|
+
}
|
|
474
|
+
function constBranchValues(errs) {
|
|
475
|
+
let count = 0;
|
|
476
|
+
for (const e of errs) {
|
|
477
|
+
const isConst = e.keyword === "const" && typeof e.params === "object" && e.params !== null && "allowedValue" in e.params;
|
|
478
|
+
if (isConst) count += 1;
|
|
479
|
+
}
|
|
480
|
+
return count;
|
|
481
|
+
}
|
|
482
|
+
function formatPathErrors(path, errs) {
|
|
483
|
+
if (constBranchValues(errs) >= 2) {
|
|
484
|
+
const parts2 = [`${path} is not a valid value`];
|
|
485
|
+
for (const e of errs) {
|
|
486
|
+
if (e.keyword !== "const" && e.keyword !== "oneOf") parts2.push(formatError(e));
|
|
487
|
+
}
|
|
488
|
+
return parts2;
|
|
489
|
+
}
|
|
490
|
+
const seen = /* @__PURE__ */ new Set();
|
|
491
|
+
const parts = [];
|
|
492
|
+
for (const e of errs) {
|
|
493
|
+
const msg = formatError(e);
|
|
494
|
+
if (!seen.has(msg)) {
|
|
495
|
+
seen.add(msg);
|
|
496
|
+
parts.push(msg);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return parts;
|
|
500
|
+
}
|
|
547
501
|
function registerProviderAuxiliarySchemas(ajv, providers) {
|
|
548
502
|
for (const provider of providers) {
|
|
549
503
|
if (!provider.schemas) continue;
|
|
@@ -555,10 +509,10 @@ function registerProviderAuxiliarySchemas(ajv, providers) {
|
|
|
555
509
|
}
|
|
556
510
|
}
|
|
557
511
|
function resolveSpecRoot() {
|
|
558
|
-
const require2 =
|
|
512
|
+
const require2 = createRequire(import.meta.url);
|
|
559
513
|
try {
|
|
560
514
|
const indexPath = require2.resolve("@skill-map/spec/index.json");
|
|
561
|
-
return
|
|
515
|
+
return dirname(indexPath);
|
|
562
516
|
} catch {
|
|
563
517
|
throw new Error(
|
|
564
518
|
"@skill-map/spec not resolvable: ensure the workspace is linked or the package is installed."
|
|
@@ -567,13 +521,139 @@ function resolveSpecRoot() {
|
|
|
567
521
|
}
|
|
568
522
|
function existsSyncSafe(path) {
|
|
569
523
|
try {
|
|
570
|
-
|
|
524
|
+
readFileSync(path, "utf8");
|
|
571
525
|
return true;
|
|
572
526
|
} catch {
|
|
573
527
|
return false;
|
|
574
528
|
}
|
|
575
529
|
}
|
|
576
530
|
|
|
531
|
+
// kernel/adapters/plugin-loader/id-utils.ts
|
|
532
|
+
import { isAbsolute, relative, resolve as resolve2 } from "path";
|
|
533
|
+
|
|
534
|
+
// kernel/adapters/plugin-loader/validation.ts
|
|
535
|
+
import * as nodeFs from "fs";
|
|
536
|
+
import { existsSync } from "fs";
|
|
537
|
+
import { dirname as dirname2, join } from "path";
|
|
538
|
+
import { Ajv2020 as Ajv20202 } from "ajv/dist/2020.js";
|
|
539
|
+
|
|
540
|
+
// kernel/extensions/hook.ts
|
|
541
|
+
var HOOK_TRIGGERS = Object.freeze([
|
|
542
|
+
"boot",
|
|
543
|
+
"scan.started",
|
|
544
|
+
"scan.completed",
|
|
545
|
+
"extractor.completed",
|
|
546
|
+
"analyzer.completed",
|
|
547
|
+
"action.completed",
|
|
548
|
+
"job.spawning",
|
|
549
|
+
"job.completed",
|
|
550
|
+
"job.failed",
|
|
551
|
+
"shutdown"
|
|
552
|
+
]);
|
|
553
|
+
|
|
554
|
+
// kernel/adapters/plugin-loader/validation.ts
|
|
555
|
+
var KNOWN_KINDS = /* @__PURE__ */ new Set([
|
|
556
|
+
"provider",
|
|
557
|
+
"extractor",
|
|
558
|
+
"analyzer",
|
|
559
|
+
"action",
|
|
560
|
+
"formatter",
|
|
561
|
+
"hook"
|
|
562
|
+
]);
|
|
563
|
+
var KNOWN_KINDS_LIST = [...KNOWN_KINDS].join(" / ");
|
|
564
|
+
var HOOKABLE_TRIGGERS_LIST = HOOK_TRIGGERS.join(", ");
|
|
565
|
+
|
|
566
|
+
// kernel/adapters/plugin-loader/storage-schemas.ts
|
|
567
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
568
|
+
import { resolve as resolve3 } from "path";
|
|
569
|
+
import { Ajv2020 as Ajv20203 } from "ajv/dist/2020.js";
|
|
570
|
+
|
|
571
|
+
// kernel/i18n/plugin-store.texts.ts
|
|
572
|
+
var PLUGIN_STORE_TEXTS = {
|
|
573
|
+
kvValidationFailed: "plugin '{{pluginId}}' ctx.store.set('{{key}}', value): value violates declared schema ({{schemaPath}}): {{errors}}",
|
|
574
|
+
dedicatedValidationFailed: "plugin '{{pluginId}}' ctx.store.write('{{table}}', row): row violates declared schema ({{schemaPath}}): {{errors}}"
|
|
575
|
+
};
|
|
576
|
+
|
|
577
|
+
// kernel/adapters/plugin-store.ts
|
|
578
|
+
var KV_SCHEMA_KEY = "__kv__";
|
|
579
|
+
function makeKvStoreWrapper(opts) {
|
|
580
|
+
const { pluginId, schema, persist } = opts;
|
|
581
|
+
return {
|
|
582
|
+
async set(key, value) {
|
|
583
|
+
if (schema) {
|
|
584
|
+
if (!schema.validate(value)) {
|
|
585
|
+
throw new Error(
|
|
586
|
+
tx(PLUGIN_STORE_TEXTS.kvValidationFailed, {
|
|
587
|
+
pluginId,
|
|
588
|
+
schemaPath: schema.schemaPath,
|
|
589
|
+
key,
|
|
590
|
+
errors: formatAjvErrors2(schema.validate.errors ?? null)
|
|
591
|
+
})
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
await persist(key, value);
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
function makeDedicatedStoreWrapper(opts) {
|
|
600
|
+
const { pluginId, schemas, persist } = opts;
|
|
601
|
+
return {
|
|
602
|
+
async write(table, row) {
|
|
603
|
+
const schema = schemas?.[table];
|
|
604
|
+
if (schema) {
|
|
605
|
+
if (!schema.validate(row)) {
|
|
606
|
+
throw new Error(
|
|
607
|
+
tx(PLUGIN_STORE_TEXTS.dedicatedValidationFailed, {
|
|
608
|
+
pluginId,
|
|
609
|
+
table,
|
|
610
|
+
schemaPath: schema.schemaPath,
|
|
611
|
+
errors: formatAjvErrors2(schema.validate.errors ?? null)
|
|
612
|
+
})
|
|
613
|
+
);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
await persist(table, row);
|
|
617
|
+
}
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
function makePluginStore(opts) {
|
|
621
|
+
const manifest = opts.plugin.manifest;
|
|
622
|
+
if (!manifest?.storage) return void 0;
|
|
623
|
+
const storageSchemas = opts.plugin.storageSchemas;
|
|
624
|
+
if (manifest.storage.mode === "kv") {
|
|
625
|
+
if (!opts.persistKv) return void 0;
|
|
626
|
+
const schema = storageSchemas?.[KV_SCHEMA_KEY];
|
|
627
|
+
return makeKvStoreWrapper({
|
|
628
|
+
pluginId: opts.plugin.id,
|
|
629
|
+
schema,
|
|
630
|
+
persist: opts.persistKv
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
if (manifest.storage.mode === "dedicated") {
|
|
634
|
+
if (!opts.persistDedicated) return void 0;
|
|
635
|
+
return makeDedicatedStoreWrapper({
|
|
636
|
+
pluginId: opts.plugin.id,
|
|
637
|
+
schemas: storageSchemas,
|
|
638
|
+
persist: opts.persistDedicated
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
return void 0;
|
|
642
|
+
}
|
|
643
|
+
function formatAjvErrors2(errors) {
|
|
644
|
+
if (!errors || errors.length === 0) return "(no AJV details)";
|
|
645
|
+
return errors.map((e) => `${e.instancePath || "(root)"} ${e.message ?? e.keyword}`).join("; ");
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// kernel/adapters/plugin-loader/index.ts
|
|
649
|
+
function installedSpecVersion() {
|
|
650
|
+
const require2 = createRequire2(import.meta.url);
|
|
651
|
+
const indexPath = require2.resolve("@skill-map/spec/index.json");
|
|
652
|
+
const pkgPath = resolve4(indexPath, "..", "package.json");
|
|
653
|
+
const pkg = JSON.parse(readFileSync4(pkgPath, "utf8"));
|
|
654
|
+
return pkg.version;
|
|
655
|
+
}
|
|
656
|
+
|
|
577
657
|
// kernel/util/format-error.ts
|
|
578
658
|
function formatErrorMessage(err) {
|
|
579
659
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -691,7 +771,7 @@ var ORCHESTRATOR_TEXTS = {
|
|
|
691
771
|
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.",
|
|
692
772
|
extensionErrorLinkKindNotDeclared: 'Extractor "{{extractorId}}" emitted a link of kind "{{linkKind}}" outside its declared `emitsLinkKinds` set [{{declaredKinds}}]. Link dropped.',
|
|
693
773
|
extensionErrorIssueInvalidSeverity: `Rule "{{analyzerId}}" emitted an issue with invalid severity {{severity}} (allowed: 'error' | 'warn' | 'info'). Issue dropped.`,
|
|
694
|
-
|
|
774
|
+
extensionErrorContributionUndeclaredRef: 'Extension "{{extractorId}}" emitted a view contribution on {{nodePath}} whose object is not one declared in its `ui` map (pass the declared const by reference, do not spread or inline it). Contribution dropped.',
|
|
695
775
|
extensionErrorContributionPayloadInvalid: 'Extractor "{{extractorId}}" emitted contribution "{{contributionId}}" on {{nodePath}}; payload failed the "{{slot}}" schema: {{errors}}. Contribution dropped.',
|
|
696
776
|
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.',
|
|
697
777
|
runScanRootEmptyArray: "runScan: roots must contain at least one path (spec requires minItems: 1)",
|
|
@@ -728,6 +808,7 @@ async function runExtractorsForNode(opts) {
|
|
|
728
808
|
const externalLinks = [];
|
|
729
809
|
const enrichmentBuffer = /* @__PURE__ */ new Map();
|
|
730
810
|
const contributions = [];
|
|
811
|
+
const contributionErrors = [];
|
|
731
812
|
const signals = [];
|
|
732
813
|
const virtualNodes = [];
|
|
733
814
|
const virtualNodePaths = /* @__PURE__ */ new Set();
|
|
@@ -759,36 +840,54 @@ async function runExtractorsForNode(opts) {
|
|
|
759
840
|
});
|
|
760
841
|
}
|
|
761
842
|
};
|
|
762
|
-
const declaredContributions =
|
|
763
|
-
const emitContribution = (
|
|
764
|
-
const declared = declaredContributions.get(
|
|
843
|
+
const declaredContributions = readDeclaredContributionRefs(extractor);
|
|
844
|
+
const emitContribution = (ref, payload) => {
|
|
845
|
+
const declared = typeof ref === "object" && ref !== null ? declaredContributions.get(ref) : void 0;
|
|
765
846
|
if (!declared) {
|
|
847
|
+
const message = tx(ORCHESTRATOR_TEXTS.extensionErrorContributionUndeclaredRef, {
|
|
848
|
+
extractorId: qualifiedId,
|
|
849
|
+
nodePath: opts.node.path
|
|
850
|
+
});
|
|
766
851
|
emitExtensionError(opts.emitter, qualifiedId, opts.node.path, {
|
|
767
852
|
phase: "emitContribution",
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
853
|
+
reason: "undeclared-contribution-ref",
|
|
854
|
+
message
|
|
855
|
+
});
|
|
856
|
+
contributionErrors.push({
|
|
857
|
+
pluginId: extractor.pluginId,
|
|
858
|
+
extensionId: extractor.id,
|
|
859
|
+
nodePath: opts.node.path,
|
|
860
|
+
reason: "undeclared-contribution-ref",
|
|
861
|
+
message,
|
|
862
|
+
emittedAt: Date.now()
|
|
775
863
|
});
|
|
776
864
|
return;
|
|
777
865
|
}
|
|
778
866
|
const result = validators.validateContributionPayload(declared.slot, payload);
|
|
779
867
|
if (!result.ok) {
|
|
868
|
+
const message = tx(ORCHESTRATOR_TEXTS.extensionErrorContributionPayloadInvalid, {
|
|
869
|
+
extractorId: qualifiedId,
|
|
870
|
+
contributionId: declared.id,
|
|
871
|
+
nodePath: opts.node.path,
|
|
872
|
+
slot: declared.slot,
|
|
873
|
+
errors: result.errors
|
|
874
|
+
});
|
|
780
875
|
emitExtensionError(opts.emitter, qualifiedId, opts.node.path, {
|
|
781
876
|
phase: "emitContribution",
|
|
782
|
-
contributionId,
|
|
877
|
+
contributionId: declared.id,
|
|
783
878
|
slot: declared.slot,
|
|
784
879
|
reason: result.errors,
|
|
785
|
-
message
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
880
|
+
message
|
|
881
|
+
});
|
|
882
|
+
contributionErrors.push({
|
|
883
|
+
pluginId: extractor.pluginId,
|
|
884
|
+
extensionId: extractor.id,
|
|
885
|
+
nodePath: opts.node.path,
|
|
886
|
+
reason: result.errors,
|
|
887
|
+
message,
|
|
888
|
+
contributionId: declared.id,
|
|
889
|
+
slot: declared.slot,
|
|
890
|
+
emittedAt: Date.now()
|
|
792
891
|
});
|
|
793
892
|
return;
|
|
794
893
|
}
|
|
@@ -796,7 +895,7 @@ async function runExtractorsForNode(opts) {
|
|
|
796
895
|
pluginId: extractor.pluginId,
|
|
797
896
|
extensionId: extractor.id,
|
|
798
897
|
nodePath: opts.node.path,
|
|
799
|
-
contributionId,
|
|
898
|
+
contributionId: declared.id,
|
|
800
899
|
slot: declared.slot,
|
|
801
900
|
payload,
|
|
802
901
|
emittedAt: Date.now()
|
|
@@ -834,11 +933,12 @@ async function runExtractorsForNode(opts) {
|
|
|
834
933
|
externalLinks,
|
|
835
934
|
enrichments: Array.from(enrichmentBuffer.values()),
|
|
836
935
|
contributions,
|
|
936
|
+
contributionErrors,
|
|
837
937
|
signals,
|
|
838
938
|
virtualNodes
|
|
839
939
|
};
|
|
840
940
|
}
|
|
841
|
-
function
|
|
941
|
+
function readDeclaredContributionRefs(extension) {
|
|
842
942
|
const out = /* @__PURE__ */ new Map();
|
|
843
943
|
const raw = extension.ui;
|
|
844
944
|
if (typeof raw !== "object" || raw === null) return out;
|
|
@@ -846,7 +946,7 @@ function readDeclaredContributions(extension) {
|
|
|
846
946
|
if (typeof value !== "object" || value === null) continue;
|
|
847
947
|
const slot = value.slot;
|
|
848
948
|
if (typeof slot !== "string") continue;
|
|
849
|
-
out.set(
|
|
949
|
+
out.set(value, { id, slot });
|
|
850
950
|
}
|
|
851
951
|
return out;
|
|
852
952
|
}
|
|
@@ -1094,6 +1194,7 @@ function isExternalUrlLink(link) {
|
|
|
1094
1194
|
async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sidecarRoots, annotationContributions, viewContributions, orphanJobFiles, referenceablePaths, cwd, registeredActionIds, emitter, hookDispatcher, reservedNodePaths, signals, seedIssues = []) {
|
|
1095
1195
|
const issues = [...seedIssues];
|
|
1096
1196
|
const contributions = [];
|
|
1197
|
+
const contributionErrors = [];
|
|
1097
1198
|
const validators = loadSchemaValidators();
|
|
1098
1199
|
void registeredActionIds;
|
|
1099
1200
|
const analyzerOrphans = orphanSidecars.map((o) => ({
|
|
@@ -1103,36 +1204,54 @@ async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sid
|
|
|
1103
1204
|
const scheduled = orderAnalyzersByPhase(analyzers);
|
|
1104
1205
|
for (const analyzer of scheduled) {
|
|
1105
1206
|
const qualifiedId = qualifiedExtensionId(analyzer.pluginId, analyzer.id);
|
|
1106
|
-
const declaredContributions =
|
|
1107
|
-
const emitContribution = (nodePath,
|
|
1108
|
-
const declared = declaredContributions.get(
|
|
1207
|
+
const declaredContributions = readDeclaredContributionRefs(analyzer);
|
|
1208
|
+
const emitContribution = (nodePath, ref, payload) => {
|
|
1209
|
+
const declared = typeof ref === "object" && ref !== null ? declaredContributions.get(ref) : void 0;
|
|
1109
1210
|
if (!declared) {
|
|
1211
|
+
const message = tx(ORCHESTRATOR_TEXTS.extensionErrorContributionUndeclaredRef, {
|
|
1212
|
+
extractorId: qualifiedId,
|
|
1213
|
+
nodePath
|
|
1214
|
+
});
|
|
1110
1215
|
emitExtensionError(emitter, qualifiedId, nodePath, {
|
|
1111
1216
|
phase: "emitContribution",
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1217
|
+
reason: "undeclared-contribution-ref",
|
|
1218
|
+
message
|
|
1219
|
+
});
|
|
1220
|
+
contributionErrors.push({
|
|
1221
|
+
pluginId: analyzer.pluginId,
|
|
1222
|
+
extensionId: analyzer.id,
|
|
1223
|
+
nodePath,
|
|
1224
|
+
reason: "undeclared-contribution-ref",
|
|
1225
|
+
message,
|
|
1226
|
+
emittedAt: Date.now()
|
|
1119
1227
|
});
|
|
1120
1228
|
return;
|
|
1121
1229
|
}
|
|
1122
1230
|
const result = validators.validateContributionPayload(declared.slot, payload);
|
|
1123
1231
|
if (!result.ok) {
|
|
1232
|
+
const message = tx(ORCHESTRATOR_TEXTS.extensionErrorContributionPayloadInvalid, {
|
|
1233
|
+
extractorId: qualifiedId,
|
|
1234
|
+
contributionId: declared.id,
|
|
1235
|
+
nodePath,
|
|
1236
|
+
slot: declared.slot,
|
|
1237
|
+
errors: result.errors
|
|
1238
|
+
});
|
|
1124
1239
|
emitExtensionError(emitter, qualifiedId, nodePath, {
|
|
1125
1240
|
phase: "emitContribution",
|
|
1126
|
-
contributionId,
|
|
1241
|
+
contributionId: declared.id,
|
|
1127
1242
|
slot: declared.slot,
|
|
1128
1243
|
reason: result.errors,
|
|
1129
|
-
message
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1244
|
+
message
|
|
1245
|
+
});
|
|
1246
|
+
contributionErrors.push({
|
|
1247
|
+
pluginId: analyzer.pluginId,
|
|
1248
|
+
extensionId: analyzer.id,
|
|
1249
|
+
nodePath,
|
|
1250
|
+
reason: result.errors,
|
|
1251
|
+
message,
|
|
1252
|
+
contributionId: declared.id,
|
|
1253
|
+
slot: declared.slot,
|
|
1254
|
+
emittedAt: Date.now()
|
|
1136
1255
|
});
|
|
1137
1256
|
return;
|
|
1138
1257
|
}
|
|
@@ -1140,7 +1259,7 @@ async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sid
|
|
|
1140
1259
|
pluginId: analyzer.pluginId,
|
|
1141
1260
|
extensionId: analyzer.id,
|
|
1142
1261
|
nodePath,
|
|
1143
|
-
contributionId,
|
|
1262
|
+
contributionId: declared.id,
|
|
1144
1263
|
slot: declared.slot,
|
|
1145
1264
|
payload,
|
|
1146
1265
|
emittedAt: Date.now()
|
|
@@ -1173,7 +1292,7 @@ async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sid
|
|
|
1173
1292
|
emitter.emit(evt);
|
|
1174
1293
|
await hookDispatcher.dispatch("analyzer.completed", evt);
|
|
1175
1294
|
}
|
|
1176
|
-
return { issues, contributions };
|
|
1295
|
+
return { issues, contributions, contributionErrors };
|
|
1177
1296
|
}
|
|
1178
1297
|
function orderAnalyzersByPhase(analyzers) {
|
|
1179
1298
|
return analyzers.slice().sort((a, b) => phaseRank(a) - phaseRank(b));
|
|
@@ -2589,6 +2708,7 @@ async function walkAndExtract(opts) {
|
|
|
2589
2708
|
enrichments: [...accum.enrichmentBuffer.values()],
|
|
2590
2709
|
extractorRuns: accum.extractorRuns,
|
|
2591
2710
|
contributions: accum.contributionsBuffer,
|
|
2711
|
+
contributionErrors: accum.contributionErrorsBuffer,
|
|
2592
2712
|
freshlyRunTuples: accum.freshlyRunTuples,
|
|
2593
2713
|
orphanSidecars,
|
|
2594
2714
|
sidecarRoots: accum.sidecarRoots,
|
|
@@ -2605,6 +2725,7 @@ function createWalkAccumulators() {
|
|
|
2605
2725
|
frontmatterIssues: [],
|
|
2606
2726
|
enrichmentBuffer: /* @__PURE__ */ new Map(),
|
|
2607
2727
|
contributionsBuffer: [],
|
|
2728
|
+
contributionErrorsBuffer: [],
|
|
2608
2729
|
freshlyRunTuples: /* @__PURE__ */ new Set(),
|
|
2609
2730
|
extractorRuns: [],
|
|
2610
2731
|
sidecarRoots: /* @__PURE__ */ new Map()
|
|
@@ -2755,7 +2876,11 @@ function mergeExtractResult(extractResult, accum) {
|
|
|
2755
2876
|
accum.enrichmentBuffer.set(`${enr.nodePath}\0${enr.extractorId}`, enr);
|
|
2756
2877
|
}
|
|
2757
2878
|
for (const c of extractResult.contributions) accum.contributionsBuffer.push(c);
|
|
2758
|
-
for (const
|
|
2879
|
+
for (const e of extractResult.contributionErrors) accum.contributionErrorsBuffer.push(e);
|
|
2880
|
+
mergeVirtualNodes(extractResult.virtualNodes, accum);
|
|
2881
|
+
}
|
|
2882
|
+
function mergeVirtualNodes(virtualNodes, accum) {
|
|
2883
|
+
for (const vn of virtualNodes) {
|
|
2759
2884
|
if (accum.nodes.some((n) => n.path === vn.path)) continue;
|
|
2760
2885
|
accum.nodes.push(vn);
|
|
2761
2886
|
}
|
|
@@ -3031,6 +3156,7 @@ async function dispatchExtractorCompleted(extractors, emitter, hookDispatcher) {
|
|
|
3031
3156
|
}
|
|
3032
3157
|
function mergeAnalyzerEmissions(walked, analyzerResult, analyzers) {
|
|
3033
3158
|
for (const c of analyzerResult.contributions) walked.contributions.push(c);
|
|
3159
|
+
for (const e of analyzerResult.contributionErrors) walked.contributionErrors.push(e);
|
|
3034
3160
|
for (const analyzer of analyzers ?? []) {
|
|
3035
3161
|
if (analyzer.ui === void 0) continue;
|
|
3036
3162
|
for (const node of walked.nodes) {
|
|
@@ -3076,6 +3202,7 @@ function buildScanReturn(walked, issues, renameOps, stats, options, setup) {
|
|
|
3076
3202
|
extractorRuns: walked.extractorRuns,
|
|
3077
3203
|
enrichments: walked.enrichments,
|
|
3078
3204
|
contributions: walked.contributions,
|
|
3205
|
+
contributionErrors: walked.contributionErrors,
|
|
3079
3206
|
freshlyRunTuples: walked.freshlyRunTuples
|
|
3080
3207
|
};
|
|
3081
3208
|
}
|
|
@@ -3505,4 +3632,4 @@ export {
|
|
|
3505
3632
|
runScanWithRenames
|
|
3506
3633
|
};
|
|
3507
3634
|
//# sourceMappingURL=index.js.map
|
|
3508
|
-
//# debugId=
|
|
3635
|
+
//# debugId=5a40a4c9-3996-540c-b687-874d383944d0
|