@skill-map/cli 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +4 -0
  2. package/dist/cli/tutorial/sm-tutorial.md +6 -7
  3. package/dist/cli.js +7011 -4047
  4. package/dist/cli.js.map +1 -1
  5. package/dist/index.d.ts +1 -1
  6. package/dist/index.js +277 -42
  7. package/dist/index.js.map +1 -1
  8. package/dist/kernel/index.d.ts +566 -68
  9. package/dist/kernel/index.js +277 -42
  10. package/dist/kernel/index.js.map +1 -1
  11. package/dist/migrations/001_initial.sql +122 -12
  12. package/dist/ui/chunk-7CAK6MVK.js +2638 -0
  13. package/dist/ui/chunk-BORRASJB.js +247 -0
  14. package/dist/ui/chunk-CZSS4D6J.js +454 -0
  15. package/dist/ui/chunk-EQD7AYYJ.js +227 -0
  16. package/dist/ui/chunk-ETTRVTFV.js +1 -0
  17. package/dist/ui/chunk-LFIE4SCX.js +965 -0
  18. package/dist/ui/chunk-OKO3QOH6.js +1 -0
  19. package/dist/ui/chunk-PMIMYHBM.js +61 -0
  20. package/dist/ui/chunk-UHFGCO24.js +1 -0
  21. package/dist/ui/chunk-VHIPW3TH.js +1 -0
  22. package/dist/ui/chunk-VWAUXWQX.js +237 -0
  23. package/dist/ui/index.html +10 -2
  24. package/dist/ui/main-BSYMJKTL.js +1 -0
  25. package/dist/ui/{styles-CBPFNGXA.css → styles-UAABA7VK.css} +1 -1
  26. package/migrations/001_initial.sql +122 -12
  27. package/package.json +2 -2
  28. package/dist/migrations/002_sidecar_columns.sql +0 -53
  29. package/dist/migrations/003_drop_node_author.sql +0 -20
  30. package/dist/migrations/004_sidecar_root_json.sql +0 -23
  31. package/dist/migrations/005_node_favorites.sql +0 -20
  32. package/dist/ui/chunk-JKJGGXCS.js +0 -1025
  33. package/dist/ui/chunk-SX2A3WBX.js +0 -247
  34. package/dist/ui/chunk-TWZHUCAT.js +0 -237
  35. package/dist/ui/chunk-WTAL2RK4.js +0 -1
  36. package/dist/ui/chunk-Z3UJHHTC.js +0 -3091
  37. package/dist/ui/main-AAYGMON4.js +0 -1
  38. package/migrations/002_sidecar_columns.sql +0 -53
  39. package/migrations/003_drop_node_author.sql +0 -20
  40. package/migrations/004_sidecar_root_json.sql +0 -23
  41. package/migrations/005_node_favorites.sql +0 -20
@@ -151,17 +151,6 @@ interface Node {
151
151
  linksOutCount: number;
152
152
  linksInCount: number;
153
153
  externalRefsCount: number;
154
- title?: string | null;
155
- description?: string | null;
156
- stability?: Stability | null;
157
- /**
158
- * Monotonic version counter sourced from the sidecar's
159
- * `annotations.version` (Step 9.6.2). `null` when no sidecar accompanies
160
- * the node, or when the sidecar omits `version`. Pre-9.6.2 the field
161
- * was a semver string sourced from `frontmatter.metadata.version`;
162
- * see migration `002_sidecar_columns.sql` and Decision #125.
163
- */
164
- version?: number | null;
165
154
  frontmatter?: Record<string, unknown>;
166
155
  tokens?: TripleSplit;
167
156
  /**
@@ -386,7 +375,7 @@ interface ScanResult {
386
375
  * and each kind's code carries its own fuller type where needed.
387
376
  *
388
377
  * **Spec § A.6 — qualified ids.** Every extension is keyed in the registry
389
- * by `<pluginId>/<id>` (e.g. `core/frontmatter`, `claude/slash`,
378
+ * by `<pluginId>/<id>` (e.g. `core/annotations`, `core/slash`,
390
379
  * `hello-world/greet`). `Extension.id` carries the **short** id as authored;
391
380
  * `Extension.pluginId` carries the namespace; the registry composes the
392
381
  * qualifier internally and exposes lookup APIs that operate on either form
@@ -463,6 +452,226 @@ interface IRegisteredAnnotationKey {
463
452
  schema: Record<string, unknown>;
464
453
  }
465
454
 
455
+ /**
456
+ * Step 11.x — runtime view-contribution catalog types.
457
+ *
458
+ * Lives in its own module (rather than `kernel/index.ts`) so consumers
459
+ * deep inside the kernel — `IRuleContext`, the BFF route factories,
460
+ * future Action contexts — can depend on the catalog shape without
461
+ * dragging the whole kernel barrel and risking a cycle.
462
+ *
463
+ * Mirrors `annotation-catalog.ts` for the annotation contribution side
464
+ * (Step 9.6.6). The two systems share the "plugin contributes data,
465
+ * kernel exposes catalog, UI renders" pattern but never overlap in
466
+ * storage or routing — see `architecture.md` §View contribution system
467
+ * for the comparison table.
468
+ *
469
+ * **Closed catalog by design.** Both `TContractName` and `TInputTypeName`
470
+ * mirror the closed enums in `spec/schemas/view-contracts.schema.json`
471
+ * and `spec/schemas/input-types.schema.json`. Adding a member is a
472
+ * coordinated kernel + spec + UI + scaffolder change. The closed-enum
473
+ * shape lets TypeScript surface unknown contracts at author time
474
+ * (in plugin authors' editors when their plugin imports `@skill-map/cli`)
475
+ * AND lets the runtime exhaustively dispatch contract → renderer in the
476
+ * UI without `default:` fallbacks.
477
+ */
478
+ /**
479
+ * Closed enum of view contract names. Mirror of
480
+ * `spec/schemas/view-contracts.schema.json#/$defs/ContractName`.
481
+ *
482
+ * Plugins pick one of these by name in their extension manifest's
483
+ * `viewContributions[<contributionId>].contract` field. The kernel
484
+ * validates each pick at load time (`invalid-manifest` on miss); the
485
+ * UI maps each contract to one or more slots and a renderer.
486
+ */
487
+ type TContractName = 'node-counter' | 'node-tag' | 'node-breakdown' | 'node-records' | 'node-tree' | 'node-key-values' | 'node-link-list' | 'node-markdown' | 'node-alert' | 'scope-stat';
488
+ /**
489
+ * Closed enum of input-type names for plugin settings. Mirror of
490
+ * `spec/schemas/input-types.schema.json#/$defs/InputTypeName`.
491
+ *
492
+ * Plugins pick one of these by name in their plugin manifest's
493
+ * `settings[<settingId>].type` field. The kernel exposes the resolved
494
+ * value via `ctx.settings.<settingId>` typed per the input-type's
495
+ * value-type promise.
496
+ */
497
+ type TInputTypeName = 'string-list' | 'single-string' | 'boolean-flag' | 'integer' | 'enum-pick' | 'enum-multipick' | 'path-glob' | 'regex' | 'secret' | 'key-value-list';
498
+ /** Closed severity palette aligned with PrimeNG `<p-tag>` / `<p-message>`. */
499
+ type TSeverity = 'info' | 'warn' | 'success' | 'danger';
500
+ /**
501
+ * Manifest-side declaration of a single view contribution. The plugin
502
+ * author writes one of these per Record key in
503
+ * `IExtensionBase.viewContributions[<contributionId>]`.
504
+ *
505
+ * Mirror of `view-contracts.schema.json#/$defs/IViewContribution`.
506
+ */
507
+ interface IViewContribution {
508
+ /**
509
+ * Required. Closed-catalog contract name. Unknown name rejects the
510
+ * extension as `invalid-manifest` at load.
511
+ */
512
+ contract: TContractName;
513
+ /**
514
+ * Optional human-readable label. English-only per `AGENTS.md`
515
+ * (`Externalized texts, not internationalized`).
516
+ */
517
+ label?: string;
518
+ /** Optional hover tooltip. English-only. */
519
+ tooltip?: string;
520
+ /**
521
+ * Optional emoji codepoint OR PrimeIcons class id (without the
522
+ * `pi-` prefix). The UI discriminates: matches Unicode
523
+ * `\p{Extended_Pictographic}` → emoji text, otherwise → PrimeIcon.
524
+ */
525
+ icon?: string;
526
+ /**
527
+ * Optional empty placeholder text shown when the payload is empty
528
+ * AND `emitWhenEmpty` is true. Falls back to a UI-supplied generic
529
+ * 'No data.' string. English-only.
530
+ */
531
+ emptyText?: string;
532
+ /**
533
+ * When false (default), the kernel drops emissions whose payload is
534
+ * structurally empty so the slot stays silent. When true, the
535
+ * renderer surfaces an empty placeholder. Per-contract definition
536
+ * of "empty" lives in the contract's payload schema.
537
+ */
538
+ emitWhenEmpty?: boolean;
539
+ /**
540
+ * Optional ordering hint (default 100). Slots configured with
541
+ * `order: 'priority'` sort contributions ASC by this value, with
542
+ * alphabetical tie-break by qualified id. The plugin uses this to
543
+ * suggest where its contribution belongs relative to others sharing
544
+ * the same slot — the slot has the final say.
545
+ */
546
+ priority?: number;
547
+ }
548
+ /**
549
+ * Single row of the runtime view-contribution catalog surfaced by
550
+ * `kernel.getRegisteredViewContributions()`. One row per
551
+ * `(pluginId × extensionId × contributionId)` tuple. Composed at boot
552
+ * by `loadPluginRuntime` from every loaded extension's
553
+ * `viewContributions` map.
554
+ *
555
+ * The qualified id is `<pluginId>/<extensionId>/<contributionId>` —
556
+ * matches the qualified id pattern used elsewhere in the kernel
557
+ * (`<pluginId>/<extensionId>` for extensions; this adds the third
558
+ * segment for per-contribution identity).
559
+ */
560
+ interface IRegisteredViewContribution {
561
+ pluginId: string;
562
+ extensionId: string;
563
+ contributionId: string;
564
+ contract: TContractName;
565
+ /** Optional manifest-declared label (English-only). */
566
+ label?: string;
567
+ tooltip?: string;
568
+ icon?: string;
569
+ emptyText?: string;
570
+ emitWhenEmpty: boolean;
571
+ /** Manifest-declared ordering hint (default 100). See `IViewContribution.priority`. */
572
+ priority?: number;
573
+ }
574
+ /**
575
+ * Common fields on every setting declaration. The discriminated union
576
+ * `ISettingDeclaration` extends one of these per `type` value.
577
+ */
578
+ interface ISettingCommon {
579
+ /** Required. Short human-readable label. English-only. */
580
+ label: string;
581
+ /** Optional helper text shown below the control. English-only. */
582
+ description?: string;
583
+ }
584
+ interface ISetting_StringList extends ISettingCommon {
585
+ type: 'string-list';
586
+ default?: string[];
587
+ min?: number;
588
+ max?: number;
589
+ itemMaxLength?: number;
590
+ }
591
+ interface ISetting_SingleString extends ISettingCommon {
592
+ type: 'single-string';
593
+ default?: string;
594
+ minLength?: number;
595
+ maxLength?: number;
596
+ /** Optional ECMAScript regex pattern (no flags). */
597
+ pattern?: string;
598
+ }
599
+ interface ISetting_BooleanFlag extends ISettingCommon {
600
+ type: 'boolean-flag';
601
+ default?: boolean;
602
+ }
603
+ interface ISetting_Integer extends ISettingCommon {
604
+ type: 'integer';
605
+ default?: number;
606
+ min?: number;
607
+ max?: number;
608
+ step?: number;
609
+ }
610
+ interface ISetting_EnumOption {
611
+ value: string;
612
+ label: string;
613
+ }
614
+ interface ISetting_EnumPick extends ISettingCommon {
615
+ type: 'enum-pick';
616
+ options: ISetting_EnumOption[];
617
+ default?: string;
618
+ }
619
+ interface ISetting_EnumMultipick extends ISettingCommon {
620
+ type: 'enum-multipick';
621
+ options: ISetting_EnumOption[];
622
+ default?: string[];
623
+ min?: number;
624
+ max?: number;
625
+ }
626
+ interface ISetting_PathGlob extends ISettingCommon {
627
+ type: 'path-glob';
628
+ default?: string;
629
+ /** When true, accepts string[]; when false (default), single string. */
630
+ multiple?: boolean;
631
+ }
632
+ interface ISetting_Regex extends ISettingCommon {
633
+ type: 'regex';
634
+ default?: string;
635
+ /** Subset of `gimsuy`. Default `''`. */
636
+ flags?: string;
637
+ }
638
+ interface ISetting_Secret extends ISettingCommon {
639
+ type: 'secret';
640
+ /**
641
+ * Optional uppercase-ASCII identifier. When set in the process
642
+ * environment, that value wins over any stored value (lets CI
643
+ * inject without writing to disk).
644
+ */
645
+ envVar?: string;
646
+ }
647
+ interface ISetting_KeyValueListEntry {
648
+ key: string;
649
+ value: string;
650
+ }
651
+ interface ISetting_KeyValueList extends ISettingCommon {
652
+ type: 'key-value-list';
653
+ keyLabel?: string;
654
+ valueLabel?: string;
655
+ default?: ISetting_KeyValueListEntry[];
656
+ min?: number;
657
+ max?: number;
658
+ }
659
+ /**
660
+ * Discriminated union of every setting declaration shape. The plugin
661
+ * author NEVER writes JSON Schema for settings — they pick one of
662
+ * these `type` values and supply per-type parameters.
663
+ *
664
+ * Mirror of `input-types.schema.json#/$defs/ISettingDeclaration`.
665
+ */
666
+ type ISettingDeclaration = ISetting_StringList | ISetting_SingleString | ISetting_BooleanFlag | ISetting_Integer | ISetting_EnumPick | ISetting_EnumMultipick | ISetting_PathGlob | ISetting_Regex | ISetting_Secret | ISetting_KeyValueList;
667
+ /**
668
+ * Runtime value type for a setting, derived from its declaration. The
669
+ * kernel exposes settings to extractors as `Record<string, TSettingValue>`
670
+ * via `ctx.settings.<settingId>`; consumers that want narrow typing
671
+ * narrow at the call site by reading `manifest.settings[id].type`.
672
+ */
673
+ type TSettingValue = string | string[] | boolean | number | ISetting_KeyValueListEntry[];
674
+
466
675
  /**
467
676
  * Base manifest shape shared by every extension kind. Mirrors
468
677
  * `spec/schemas/extensions/base.schema.json` at the TypeScript level.
@@ -529,6 +738,21 @@ interface IExtensionBase {
529
738
  * `plugin-author-guide.md` §Annotation contributions for examples.
530
739
  */
531
740
  annotationContributions?: Record<string, IAnnotationContribution>;
741
+ /**
742
+ * Plugin-contributed view contributions. Each entry maps a local
743
+ * contribution id (kebab-case, unique within the extension) to a
744
+ * `IViewContribution` declaration that picks a view contract by name
745
+ * from the closed kernel catalog (`view-catalog.ts#TContractName`).
746
+ * The kernel validates each `contract` pick at load time
747
+ * (`invalid-manifest` on miss); the plugin emits per-node payloads
748
+ * via `ctx.emitContribution(<contributionId>, payload)` during scan;
749
+ * the runtime validates payloads against the contract's payload
750
+ * schema. The aggregate runtime catalog is exposed via
751
+ * `kernel.getRegisteredViewContributions()`. The plugin author
752
+ * NEVER picks a UI slot — slot mapping is owned by the UI driving
753
+ * adapter. See `architecture.md` §View contribution system.
754
+ */
755
+ viewContributions?: Record<string, IViewContribution>;
532
756
  }
533
757
 
534
758
  /**
@@ -643,6 +867,16 @@ interface IPluginManifest {
643
867
  id: string;
644
868
  version: string;
645
869
  specCompat: string;
870
+ /**
871
+ * Optional semver range against the kernel's view-contracts +
872
+ * input-types catalog version. Independent from `specCompat` because
873
+ * the catalog evolves on its own cadence (see `architecture.md`
874
+ * §View contribution system → Catalog versioning). Mismatch surfaces
875
+ * as `incompatible-catalog`. Absent = the plugin opts out of catalog
876
+ * checking; `sm plugins doctor` warns if such a plugin actually
877
+ * declares `viewContributions` or `settings`.
878
+ */
879
+ catalogCompat?: string;
646
880
  extensions: string[];
647
881
  description?: string;
648
882
  storage?: TPluginStorage;
@@ -652,6 +886,18 @@ interface IPluginManifest {
652
886
  * the default.
653
887
  */
654
888
  granularity?: TGranularity;
889
+ /**
890
+ * Plugin user-configurable settings. Each entry picks an `input-type`
891
+ * from the closed catalog at
892
+ * `spec/schemas/input-types.schema.json#/$defs/InputTypeName`.
893
+ * The plugin author NEVER writes JSON Schema — they pick `type` by
894
+ * name and supply per-type parameters. The kernel exposes resolved
895
+ * settings to extractors via `ctx.settings.<settingId>`; settings
896
+ * are read once at extractor invocation; changing a setting requires
897
+ * `sm scan` to re-emit. See `architecture.md` §View contribution
898
+ * system → Settings.
899
+ */
900
+ settings?: Record<string, ISettingDeclaration>;
655
901
  author?: string;
656
902
  license?: string;
657
903
  homepage?: string;
@@ -692,7 +938,7 @@ interface IPluginManifest {
692
938
  * precedence rule applies. The user resolves
693
939
  * by renaming one of them and rerunning.
694
940
  */
695
- type TPluginLoadStatus = 'enabled' | 'disabled' | 'incompatible-spec' | 'invalid-manifest' | 'load-error' | 'id-collision';
941
+ type TPluginLoadStatus = 'enabled' | 'disabled' | 'incompatible-spec' | 'incompatible-catalog' | 'invalid-manifest' | 'load-error' | 'id-collision';
696
942
  interface ILoadedExtension {
697
943
  kind: ExtensionKind;
698
944
  id: string;
@@ -884,6 +1130,63 @@ declare function makePluginStore(opts: {
884
1130
  persistDedicated?: IDedicatedStorePersist;
885
1131
  }): IPluginStore | undefined;
886
1132
 
1133
+ /**
1134
+ * `scan_contributions` adapter — replace-all writer used by
1135
+ * `persistScanResult`, plus read helpers consumed by the BFF
1136
+ * (`/api/contributions/...`) and rules (`core/contribution-orphan`).
1137
+ *
1138
+ * One row per `(plugin_id, extension_id, node_path, contribution_id)`
1139
+ * tuple. See `spec/architecture.md` § View contribution system →
1140
+ * Persistence and `migrations/001_initial.sql` § View contribution
1141
+ * layer for the normative shape.
1142
+ *
1143
+ * Replace-all semantics mirror the rest of the `scan_*` zone: every
1144
+ * scan is a fresh snapshot, so prior rows are deleted before insert.
1145
+ * Wrapped in the same transaction `persistScanResult` opens.
1146
+ *
1147
+ * The rename heuristic does NOT need to migrate `node_path` here —
1148
+ * because of replace-all, every contribution is re-emitted on the new
1149
+ * path automatically. Keeping the rename path lighter than `state_*`
1150
+ * (which IS rename-migrated because state survives across scans).
1151
+ */
1152
+
1153
+ /**
1154
+ * In-memory contribution record buffered during scan and flushed to
1155
+ * `scan_contributions` by `persistScanResult`. One entry per accepted
1156
+ * `ctx.emitContribution(id, payload)` call. Payload validation against
1157
+ * the contract's payload schema happens at emit time (orchestrator);
1158
+ * by the time records reach this adapter they are wire-shape clean.
1159
+ */
1160
+ interface IContributionRecord {
1161
+ pluginId: string;
1162
+ extensionId: string;
1163
+ nodePath: string;
1164
+ contributionId: string;
1165
+ /**
1166
+ * Closed enum value mirroring `view-contracts.schema.json#/$defs/ContractName`.
1167
+ * Persisted as TEXT (no SQL CHECK by design — see migration comment).
1168
+ */
1169
+ contract: string;
1170
+ /** Already-validated payload. Serialised via `JSON.stringify` at write. */
1171
+ payload: unknown;
1172
+ emittedAt: number;
1173
+ }
1174
+ /**
1175
+ * Single contribution row as returned to callers. The payload is
1176
+ * `unknown` because the contract space is open at the type layer
1177
+ * (catalog evolution is a kernel + spec concern); narrow at the call
1178
+ * site by reading `contract`.
1179
+ */
1180
+ interface IPersistedContribution {
1181
+ pluginId: string;
1182
+ extensionId: string;
1183
+ nodePath: string;
1184
+ contributionId: string;
1185
+ contract: string;
1186
+ payload: unknown;
1187
+ emittedAt: number;
1188
+ }
1189
+
887
1190
  /**
888
1191
  * Provider runtime contract. Walks filesystem roots and emits raw node
889
1192
  * records; classification maps path conventions to a node kind.
@@ -1157,6 +1460,11 @@ interface IProviderReadConfig {
1157
1460
  * a return value. Extractors run in isolation: they MUST NOT read other
1158
1461
  * nodes, the graph, or the DB. Cross-node reasoning lives in rules.
1159
1462
  *
1463
+ * Extractors are deterministic-only. They run synchronously inside the
1464
+ * scan loop; LLM-driven enrichment of a node is an Action concern, not
1465
+ * an Extractor concern. The Extractor context therefore exposes no
1466
+ * `RunnerPort` — see spec `architecture.md` §Execution modes.
1467
+ *
1160
1468
  * Output channels (all on the context):
1161
1469
  *
1162
1470
  * - `ctx.emitLink(link)` — persist a link in the kernel's `links` table.
@@ -1164,14 +1472,12 @@ interface IProviderReadConfig {
1164
1472
  * kind drops the link and surfaces an `extension.error` event.
1165
1473
  * - `ctx.enrichNode(partial)` — merge canonical, kernel-curated properties
1166
1474
  * onto the node. Strictly separate from the author-supplied frontmatter
1167
- * (the latter remains immutable and survives verbatim). Persistence and
1168
- * stale-tracking are spec'd in § A.8.
1475
+ * (the latter remains immutable and survives verbatim). Persistence
1476
+ * is spec'd in § A.8.
1169
1477
  * - `ctx.store` — plugin-scoped persistence. Present only when the
1170
1478
  * plugin declares `storage.mode` in `plugin.json`; shape depends on the
1171
1479
  * mode (`KvStore` for mode A, scoped `Database` for mode B). See
1172
1480
  * `plugin-kv-api.md` for the contract.
1173
- * - `ctx.runner` — `RunnerPort` injection for `probabilistic` extractors.
1174
- * `undefined` for the default `deterministic` mode.
1175
1481
  *
1176
1482
  * The manifest's `scope` field tells the orchestrator which parts to feed:
1177
1483
  * `frontmatter` extractors receive an empty string for body and vice versa.
@@ -1202,6 +1508,21 @@ interface IExtractorCallbacks {
1202
1508
  * partials and `persistScanResult` upserts them.
1203
1509
  */
1204
1510
  enrichNode(partial: Partial<Node>): void;
1511
+ /**
1512
+ * Emit a per-node view contribution. The first argument is the
1513
+ * extension-local Record key declared under
1514
+ * `extension.viewContributions[<contributionId>]`; the second is a
1515
+ * payload that conforms to the contract's payload schema in
1516
+ * `spec/schemas/view-contracts.schema.json#/$defs/payloads/<contract>`.
1517
+ * The orchestrator validates the payload against the contract schema
1518
+ * before persisting to `scan_contributions`; off-contract payloads
1519
+ * are silently dropped with an `extension.error` event (mirror of
1520
+ * `emitLink` rejecting off-`emitsLinkKinds` links). Calling
1521
+ * `emitContribution` with a `contributionId` that is not declared in
1522
+ * the manifest is also dropped with an `extension.error`. See
1523
+ * `architecture.md` §View contribution system → Emit path.
1524
+ */
1525
+ emitContribution(contributionId: string, payload: unknown): void;
1205
1526
  }
1206
1527
  interface IExtractorContext extends IExtractorCallbacks {
1207
1528
  node: Node;
@@ -1222,33 +1543,17 @@ interface IExtractorContext extends IExtractorCallbacks {
1222
1543
  * it here.
1223
1544
  */
1224
1545
  store?: unknown;
1225
- /**
1226
- * `RunnerPort` injection for `probabilistic` extractors. `undefined`
1227
- * for `deterministic` mode (the default). The kernel rejects
1228
- * probabilistic extractors that try to register scan-time hooks at
1229
- * load time.
1230
- */
1231
- runner?: unknown;
1232
1546
  }
1233
1547
  interface IExtractor extends IExtensionBase {
1234
1548
  kind: 'extractor';
1235
- /**
1236
- * Execution mode. Optional in the manifest with a default of
1237
- * `deterministic` per `spec/schemas/extensions/extractor.schema.json`.
1238
- * `probabilistic` extractors invoke an LLM through the kernel's
1239
- * `RunnerPort` and never participate in scan-time pipelines —
1240
- * they dispatch only as queued jobs.
1241
- */
1242
- mode?: TExecutionMode;
1243
1549
  emitsLinkKinds: LinkKind[];
1244
1550
  defaultConfidence: Confidence;
1245
1551
  scope: 'frontmatter' | 'body' | 'both';
1246
1552
  /**
1247
1553
  * Optional opt-in filter on `node.kind`. When declared, the orchestrator
1248
1554
  * skips invocation of `extract()` for any node whose `kind` is NOT in
1249
- * this list — fail-fast, before context construction, so a
1250
- * probabilistic extractor wastes zero LLM cost on inapplicable nodes
1251
- * and a deterministic extractor wastes zero CPU.
1555
+ * this list — fail-fast, before context construction, so the extractor
1556
+ * wastes zero CPU on inapplicable nodes.
1252
1557
  *
1253
1558
  * Absent (`undefined`) is the default: the extractor applies to every
1254
1559
  * kind. There are no wildcards — the absence of the field already
@@ -1320,6 +1625,36 @@ interface IRuleContext {
1320
1625
  * sites that never wired the catalog through).
1321
1626
  */
1322
1627
  annotationContributions?: readonly IRegisteredAnnotationKey[];
1628
+ /**
1629
+ * Step 11.x — runtime catalog of plugin-contributed view contributions,
1630
+ * as exposed by `kernel.getRegisteredViewContributions()`. Threaded
1631
+ * through so rules can reason about emissions without reaching back
1632
+ * into the kernel: built-in `core/unknown-contract` walks this list to
1633
+ * detect deprecated contracts in use, and `core/contribution-orphan`
1634
+ * joins it with the live node set to flag dangling emissions. Empty
1635
+ * array when no extension declares view contributions; absent for
1636
+ * legacy callers (older runScan sites that never wired the catalog
1637
+ * through).
1638
+ */
1639
+ viewContributions?: readonly IRegisteredViewContribution[];
1640
+ /**
1641
+ * Emit a per-node view contribution declared in this rule's manifest
1642
+ * `viewContributions` map. Sync, void return; the orchestrator
1643
+ * validates the payload against the contract schema at call time and
1644
+ * silently drops invalid emissions with a logged `extension.error`
1645
+ * event (parallel to `IExtractorCallbacks.emitContribution`).
1646
+ *
1647
+ * Unlike Extractor's emit (which binds `nodePath` from `ctx.node.path`
1648
+ * implicitly because Extractors run per-node), Rule's `evaluate()`
1649
+ * sees the full graph at once. The rule walks `ctx.nodes` itself and
1650
+ * MUST supply the target node path explicitly per emission.
1651
+ *
1652
+ * Calling `emitContribution` with a `contributionId` that is not
1653
+ * declared in the manifest is dropped with an `extension.error`. The
1654
+ * kernel routes emitted contributions to the same persistence
1655
+ * pipeline as Extractor emissions (`scan_contributions`).
1656
+ */
1657
+ emitContribution(nodePath: string, contributionId: string, payload: unknown): void;
1323
1658
  }
1324
1659
  interface IRule extends IExtensionBase {
1325
1660
  kind: 'rule';
@@ -1800,6 +2135,20 @@ interface RunScanOptions {
1800
2135
  * inside the rule.
1801
2136
  */
1802
2137
  annotationContributions?: readonly IRegisteredAnnotationKey[];
2138
+ /**
2139
+ * Runtime catalog of plugin-contributed view contributions (the same
2140
+ * shape `kernel.getRegisteredViewContributions()` returns). Threaded
2141
+ * into the rule pass so:
2142
+ * - `core/unknown-contract` and `core/contribution-orphan` can
2143
+ * introspect the catalog (read-only).
2144
+ * - The orchestrator's per-rule emit closure can look up each
2145
+ * declared `(contributionId → contract)` pairing for AJV
2146
+ * payload validation.
2147
+ * Absent → empty catalog. Rules that emit contributions silently
2148
+ * drop emissions when the catalog has no entry for the rule's
2149
+ * declared contributionId.
2150
+ */
2151
+ viewContributions?: readonly IRegisteredViewContribution[];
1803
2152
  /**
1804
2153
  * Scan scope. Defaults to `'project'`. The CLI flag wiring lands in
1805
2154
  * the config layer wiring; `runScan` already accepts the override
@@ -1919,8 +2268,6 @@ interface IExtractorRunRecord {
1919
2268
  *
1920
2269
  * - upsert a single row per pair (stable PRIMARY KEY conflict on
1921
2270
  * re-extract);
1922
- * - flag probabilistic rows `stale = 1` when the body changes between
1923
- * scans (preserving the prior LLM cost);
1924
2271
  * - feed `mergeNodeWithEnrichments` with `enrichedAt`-sorted partials
1925
2272
  * for last-write-wins per field at read time.
1926
2273
  *
@@ -1930,10 +2277,12 @@ interface IExtractorRunRecord {
1930
2277
  * fold into a single row, but two different Extractors hitting the
1931
2278
  * same node yield two distinct rows.
1932
2279
  *
1933
- * `isProbabilistic` is denormalised so the persistence layer's stale
1934
- * flag query stays a single-table read; recomputing from the live
1935
- * registry would force every read-path to thread the runtime extension
1936
- * set through.
2280
+ * `isProbabilistic` is reserved: Extractors are deterministic-only, so
2281
+ * every record produced by the orchestrator sets it to `false`. The
2282
+ * field is kept on the record (and the row in `node_enrichments`) so a
2283
+ * future Action-issued enrichment can populate it without reshaping
2284
+ * the persistence contract — see spec `architecture.md`
2285
+ * §Extractor · enrichment layer.
1937
2286
  */
1938
2287
  interface IEnrichmentRecord {
1939
2288
  nodePath: string;
@@ -1961,6 +2310,7 @@ declare function runScanWithRenames(_kernel: Kernel, options: RunScanOptions): P
1961
2310
  renameOps: RenameOp[];
1962
2311
  extractorRuns: IExtractorRunRecord[];
1963
2312
  enrichments: IEnrichmentRecord[];
2313
+ contributions: IContributionRecord[];
1964
2314
  }>;
1965
2315
  declare function runScan(_kernel: Kernel, options: RunScanOptions): Promise<ScanResult>;
1966
2316
  /**
@@ -1997,6 +2347,7 @@ declare function runExtractorsForNode(opts: {
1997
2347
  internalLinks: Link[];
1998
2348
  externalLinks: Link[];
1999
2349
  enrichments: IEnrichmentRecord[];
2350
+ contributions: IContributionRecord[];
2000
2351
  }>;
2001
2352
  /**
2002
2353
  * Pure rename / orphan classification per `spec/db-schema.md` §Rename
@@ -2037,10 +2388,11 @@ declare function detectRenamesAndOrphans(prior: ScanResult, current: Node[], iss
2037
2388
  * Algorithm:
2038
2389
  *
2039
2390
  * 1. Filter `enrichments` down to rows targeting this node AND not
2040
- * flagged `stale`. Stale rows (probabilistic enrichments whose
2041
- * body changed since their last run) are excluded by default —
2042
- * stale visibility belongs to the UI layer where the marker is
2043
- * shown next to the value.
2391
+ * flagged `stale`. With Extractors deterministic-only no row is
2392
+ * stale-flagged in this revision; the filter is preserved for the
2393
+ * future Action-issued enrichment revision (queued LLM jobs whose
2394
+ * output must survive body changes), where stale visibility
2395
+ * belongs to the UI layer next to the value.
2044
2396
  * 2. Sort the survivors by `enrichedAt` ASC so iteration order is
2045
2397
  * "oldest first". This makes the spread merge below
2046
2398
  * last-write-wins per field — the freshest Extractor's value
@@ -2334,6 +2686,72 @@ declare function applyExportQuery(scan: {
2334
2686
  issues: Issue[];
2335
2687
  }, query: IExportQuery): IExportSubset;
2336
2688
 
2689
+ /**
2690
+ * `scan_node_tags` adapter — tags · dual-source persistence layer.
2691
+ *
2692
+ * One row per `(node_path, tag, source)` triple. Projected at persist
2693
+ * time from BOTH `frontmatter.tags` (with `source='author'`) and
2694
+ * `sidecar.annotations.tags` (with `source='user'`). The same tag
2695
+ * string MAY appear under both sources for the same node — the PK
2696
+ * accepts the pair; search returns the node once via DISTINCT, the
2697
+ * UI renders both chips with their attribution.
2698
+ *
2699
+ * Belongs to the `scan_*` family — replaced wholesale per scan.
2700
+ * Cached nodes' tag rows are projected from the cached
2701
+ * `node.frontmatter.tags` / `node.sidecar.annotations.tags` (both
2702
+ * already in memory at persist time), so the rebuild is cheap
2703
+ * regardless of cache hit / miss. See `spec/db-schema.md`
2704
+ * § scan_node_tags for the normative shape and replace-all semantics.
2705
+ */
2706
+
2707
+ /**
2708
+ * In-memory tag record buffered during scan and flushed to
2709
+ * `scan_node_tags` by `persistScanResult`. One entry per
2710
+ * `(node_path, tag, source)` projected from a node's frontmatter tags
2711
+ * (`source: 'author'`) or sidecar annotations tags
2712
+ * (`source: 'user'`).
2713
+ */
2714
+ interface ITagRecord {
2715
+ nodePath: string;
2716
+ tag: string;
2717
+ source: 'author' | 'user';
2718
+ }
2719
+
2720
+ /**
2721
+ * Pure helpers for the "update available" notification feature.
2722
+ *
2723
+ * Three responsibilities:
2724
+ * - `fetchLatestVersion` — query `https://registry.npmjs.org/<pkg>/latest`
2725
+ * with `AbortController` + timeout. Throws on
2726
+ * non-200 / parse failure / abort.
2727
+ * - `compareVersions` — semver compare (-1 / 0 / 1). Pre-1.0 aware:
2728
+ * treats prereleases via the standard rules
2729
+ * (release > prerelease at the same triple).
2730
+ * - `isOutdated` — sugar over `compareVersions` for the common
2731
+ * "is `latest` strictly greater than `current`"
2732
+ * check the banner runs against.
2733
+ *
2734
+ * Pure kernel module — NO `process.env` reads, NO Node globals beyond the
2735
+ * built-in `fetch` / `AbortController` (Node 22+). Every env / settings
2736
+ * lookup happens in `src/cli/util/update-check-banner.ts`, the CLI-side
2737
+ * adapter that owns side effects.
2738
+ *
2739
+ * The shared cache type (`IUpdateCheckCache`) is used by the storage
2740
+ * helpers under `kernel/storage/update-check.ts` and by the BFF's
2741
+ * `GET /api/update-status` projection. A second type
2742
+ * (`IUpdateStatus`) shapes the BFF response — it merges `current`
2743
+ * (from `VERSION`) into the cache so the UI can render without a
2744
+ * second lookup. Both stay flat — no nested objects — so JSON
2745
+ * serialization is trivial.
2746
+ */
2747
+ interface IUpdateCheckCache {
2748
+ latestVersion: string;
2749
+ /** Epoch ms — when the registry was last successfully probed. */
2750
+ checkedAt: number;
2751
+ /** Epoch ms — when the banner was last printed; null = never shown yet. */
2752
+ shownAt: number | null;
2753
+ }
2754
+
2337
2755
  /**
2338
2756
  * `PluginLoaderPort` — discovers plugin directories and loads their
2339
2757
  * extensions. The shape mirrors what the concrete loader actually
@@ -2427,6 +2845,19 @@ interface IPersistOptions {
2427
2845
  renameOps?: RenameOp[];
2428
2846
  extractorRuns?: IExtractorRunRecord[];
2429
2847
  enrichments?: IEnrichmentRecord[];
2848
+ contributions?: IContributionRecord[];
2849
+ /**
2850
+ * Phase 3 / View contribution system — active runtime catalog of
2851
+ * registered view contributions, keyed by qualified id
2852
+ * `<pluginId>/<extensionId>/<contributionId>`. Passed to the
2853
+ * `scan_contributions` upsert so the catalog sweep can drop rows
2854
+ * belonging to plugins / extensions that are no longer in the
2855
+ * catalog (uninstalled plugins, disabled bundles, removed
2856
+ * contributions). Empty / absent set = no catalog sweep (legacy
2857
+ * behaviour, leaves disabled-plugin rows stale per design F24
2858
+ * pre-fix).
2859
+ */
2860
+ registeredContributionKeys?: ReadonlySet<string>;
2430
2861
  }
2431
2862
  /**
2432
2863
  * Issue row as the storage layer sees it — paired with its DB-assigned
@@ -2567,28 +2998,6 @@ interface IPluginApplyResult {
2567
2998
  intrusions: string[];
2568
2999
  }
2569
3000
 
2570
- /**
2571
- * `StoragePort` — the kernel's persistence boundary. Driving adapters
2572
- * (CLI, future server, in-memory test harness) consume this surface
2573
- * exclusively; nothing in `cli/**` should reach into the SQLite
2574
- * adapter's internal helpers (free functions on
2575
- * `kernel/adapters/sqlite/*`) directly. Phase F of the
2576
- * storage-port-promotion refactor finishes that hardening; A-E grow
2577
- * the port enough that the CLI has somewhere to land.
2578
- *
2579
- * The port is namespaced by domain (`scans`, `issues`, `enrichments`,
2580
- * etc.) — explicitly NOT a generic `port.query<T>(sql)`. Each
2581
- * namespace's methods name an operation the kernel cares about; the
2582
- * adapter translates to its persistence engine's idioms.
2583
- *
2584
- * Phase A lands the **scans / issues / enrichments / transaction**
2585
- * namespaces — the core scan pipeline. The remaining namespaces
2586
- * (history / jobs / pluginConfig / migrations / pluginMigrations)
2587
- * arrive in subsequent phases. The port shape declared here is the
2588
- * Phase A subset; later phases extend it without reshaping what
2589
- * lands today.
2590
- */
2591
-
2592
3001
  /**
2593
3002
  * Subset of `StoragePort` exposed inside a `transaction(fn)` callback.
2594
3003
  * Lifecycle methods are intentionally omitted — a transaction that
@@ -2665,6 +3074,50 @@ interface StoragePort {
2665
3074
  */
2666
3075
  findNode(path: string): Promise<INodeBundle | null>;
2667
3076
  };
3077
+ /**
3078
+ * Phase 3 / View contribution system — read access to
3079
+ * `scan_contributions`. Writes happen exclusively via
3080
+ * `scans.persist({ contributions })` to keep the replace-all
3081
+ * semantics intact; this namespace is read-only.
3082
+ */
3083
+ contributions: {
3084
+ /** Every contribution row for a single node. Stable order. */
3085
+ listForNode(nodePath: string): Promise<IPersistedContribution[]>;
3086
+ /**
3087
+ * Bulk variant for the BFF nodes-list route. Returns rows for
3088
+ * every path in `paths`, sorted `nodePath` ASC, then qualified-id
3089
+ * ASC. Empty `paths` returns `[]` without a query.
3090
+ */
3091
+ listForPaths(paths: readonly string[]): Promise<IPersistedContribution[]>;
3092
+ /**
3093
+ * Lookup by qualified id + path. Used by
3094
+ * `GET /api/contributions/:pluginId/:contributionId?path=...`.
3095
+ */
3096
+ lookup(pluginId: string, contributionId: string, nodePath: string, extensionId?: string): Promise<IPersistedContribution[]>;
3097
+ };
3098
+ /**
3099
+ * Read-only access to `scan_node_tags`. Writes happen exclusively
3100
+ * via `scans.persist({...})` (the persistence layer projects from
3101
+ * `node.frontmatter.tags` and `node.sidecar.annotations.tags`); this
3102
+ * namespace is read-only.
3103
+ */
3104
+ tags: {
3105
+ /** Every tag row for a single node. Author entries first, then user. */
3106
+ listForNode(nodePath: string): Promise<ITagRecord[]>;
3107
+ /**
3108
+ * Bulk variant for the BFF nodes-list route. Returns rows for every
3109
+ * path in `paths`, sorted `nodePath` ASC, then `source` ASC, then
3110
+ * `tag` ASC. Empty `paths` returns `[]` without a query.
3111
+ */
3112
+ listForPaths(paths: readonly string[]): Promise<ITagRecord[]>;
3113
+ /**
3114
+ * Find every node carrying `tag`. Optional `source` narrows to one
3115
+ * side of the dual surface (matches `sm list --tag <name>
3116
+ * --tag-source author|user`); absent matches the union (default
3117
+ * `sm list --tag`).
3118
+ */
3119
+ findNodes(tag: string, source?: 'author' | 'user'): Promise<string[]>;
3120
+ };
2668
3121
  issues: {
2669
3122
  /** Every issue from the latest scan, in insertion order. */
2670
3123
  listAll(): Promise<Issue[]>;
@@ -2721,6 +3174,36 @@ interface StoragePort {
2721
3174
  */
2722
3175
  listReferencedFilePaths(): Promise<Set<string>>;
2723
3176
  };
3177
+ /**
3178
+ * Generic key/value preferences keyed by a stable string. Backs the
3179
+ * `config_preferences` table — one row per `key`, `value_json` is a
3180
+ * single JSON blob the caller serialises. Keys with the `_kernel.`
3181
+ * prefix are reserved for kernel-managed entries (today: the
3182
+ * update-check cache); user-set preferences land under unprefixed
3183
+ * keys when those ship.
3184
+ *
3185
+ * Read-only by design at the port level — the only writer is the
3186
+ * CLI's post-run hook (`cli/util/update-check-banner.ts`), which
3187
+ * reaches the persistence helpers directly. The port surfaces the
3188
+ * read so the BFF's `GET /api/update-status` projection can stay
3189
+ * inside the abstract contract.
3190
+ */
3191
+ preferences: {
3192
+ /**
3193
+ * Load the update-check cache row. Returns `null` when the row
3194
+ * is absent, malformed JSON, or fails the shape guard. Never
3195
+ * throws — read failures degrade silently because the banner is
3196
+ * a non-essential surface.
3197
+ */
3198
+ loadUpdateCheckCache(): Promise<IUpdateCheckCache | null>;
3199
+ /**
3200
+ * Upsert the update-check cache row. Always overwrites the
3201
+ * existing JSON blob in place. `updated_at` tracks wall-clock
3202
+ * now — separate from the embedded `checkedAt` field, which
3203
+ * the caller controls.
3204
+ */
3205
+ saveUpdateCheckCache(cache: IUpdateCheckCache): Promise<void>;
3206
+ };
2724
3207
  favorites: {
2725
3208
  /**
2726
3209
  * Mark `path` as favorited. Idempotent — a second call refreshes
@@ -2961,7 +3444,22 @@ interface Kernel {
2961
3444
  * MUST treat the resulting array as immutable.
2962
3445
  */
2963
3446
  setRegisteredAnnotationKeys: (entries: readonly IRegisteredAnnotationKey[]) => void;
3447
+ /**
3448
+ * Step 11.x — read-only catalog of plugin-contributed view
3449
+ * contributions, keyed by `(pluginId, extensionId, contributionId)`.
3450
+ * Populated at plugin-load time; pure read with no side effects.
3451
+ * Mirror of `getRegisteredAnnotationKeys` for the view contribution
3452
+ * surface (see `architecture.md` §View contribution system →
3453
+ * Runtime catalog).
3454
+ */
3455
+ getRegisteredViewContributions: () => readonly IRegisteredViewContribution[];
3456
+ /**
3457
+ * Internal — replace the frozen view-contribution catalog. Called
3458
+ * once by the plugin runtime composer after every plugin has loaded;
3459
+ * consumers MUST treat the resulting array as immutable.
3460
+ */
3461
+ setRegisteredViewContributions: (entries: readonly IRegisteredViewContribution[]) => void;
2964
3462
  }
2965
3463
  declare function createKernel(): Kernel;
2966
3464
 
2967
- export { type Confidence, DuplicateExtensionError, EXTENSION_KINDS, type ExecutionFailureReason, type ExecutionKind, type ExecutionRecord, type ExecutionRunner, type ExecutionStatus, ExportQueryError, type Extension, type ExtensionKind, type FilesystemPort, HOOK_TRIGGERS, type HistoryStats, type HistoryStatsErrorRates, type HistoryStatsExecutionsPerPeriod, type HistoryStatsPerActionRate, type HistoryStatsTokensPerAction, type HistoryStatsTopNode, type HistoryStatsTotals, type IAction, type IActionContext, type IActionPrecondition, type IActionResult, type IAnnotationContribution, type ICreateFsWatcherOptions, type IDedicatedStorePersist, type IDedicatedStoreWrapper, type IDiscoveredPlugin, type IEnrichmentRecord, type IExportQuery, type IExportSubset, type IExtensionBase, type IExtractor, type IExtractorCallbacks, type IExtractorContext, type IExtractorRunRecord, type IFormatter, type IFormatterContext, type IFsWatcher, type IHook, type IHookContext, type IIssueRow, type IKvStorePersist, type IKvStoreWrapper, type ILoadedExtension, type INodeBundle, type INodeChange, type INodeCounts, type INodeFilter, type IPersistOptions, type IPersistedEnrichment, type IPluginManifest, type IPluginStorageSchema, type IPluginStore, type IProvider, type IRawNode, type IRegisteredAnnotationKey, type IRule, type IRuleContext, type IRunOptions, type IRunResult, type IScanDelta, type ITransactionalStorage, type IWalkOptions, type IWatchBatch, type IWatchEvent, InMemoryProgressEmitter, type Issue, type IssueFix, KV_SCHEMA_KEY, type Kernel, LOG_LEVELS, type Link, type LinkKind, type LinkLocation, type LinkTrigger, type LogRecord, type LoggerPort, type Node, type NodeKind, type NodeStat, type PluginLoaderPort, type ProgressEmitterPort, type ProgressEvent, Registry, type RenameOp, type RunScanOptions, type RunnerPort, type ScanResult, type ScanScannedBy, type ScanStats, type Severity, SilentLogger, type Stability, type StoragePort, type TActionWrite, type TExecutionMode, type TGranularity, type THookFilter, type THookTrigger, type TLogLevel, type TLogMethodLevel, type TNodeChangeReason, type TPluginLoadStatus, type TPluginStorage, type TProgressListener, type TWatchEventKind, type TripleSplit, applyExportQuery, computeScanDelta, configureLogger, createChokidarWatcher, createKernel, detectRenamesAndOrphans, getActiveLogger, isEmptyDelta, isLogLevel, log, logLevelRank, makeDedicatedStoreWrapper, makeKvStoreWrapper, makePluginStore, mergeNodeWithEnrichments, parseExportQuery, parseLogLevel, qualifiedExtensionId, resetLogger, runExtractorsForNode, runScan, runScanWithRenames };
3465
+ export { type Confidence, DuplicateExtensionError, EXTENSION_KINDS, type ExecutionFailureReason, type ExecutionKind, type ExecutionRecord, type ExecutionRunner, type ExecutionStatus, ExportQueryError, type Extension, type ExtensionKind, type FilesystemPort, HOOK_TRIGGERS, type HistoryStats, type HistoryStatsErrorRates, type HistoryStatsExecutionsPerPeriod, type HistoryStatsPerActionRate, type HistoryStatsTokensPerAction, type HistoryStatsTopNode, type HistoryStatsTotals, type IAction, type IActionContext, type IActionPrecondition, type IActionResult, type IAnnotationContribution, type ICreateFsWatcherOptions, type IDedicatedStorePersist, type IDedicatedStoreWrapper, type IDiscoveredPlugin, type IEnrichmentRecord, type IExportQuery, type IExportSubset, type IExtensionBase, type IExtractor, type IExtractorCallbacks, type IExtractorContext, type IExtractorRunRecord, type IFormatter, type IFormatterContext, type IFsWatcher, type IHook, type IHookContext, type IIssueRow, type IKvStorePersist, type IKvStoreWrapper, type ILoadedExtension, type INodeBundle, type INodeChange, type INodeCounts, type INodeFilter, type IPersistOptions, type IPersistedEnrichment, type IPluginManifest, type IPluginStorageSchema, type IPluginStore, type IProvider, type IRawNode, type IRegisteredAnnotationKey, type IRegisteredViewContribution, type IRule, type IRuleContext, type IRunOptions, type IRunResult, type IScanDelta, type ISettingDeclaration, type ITransactionalStorage, type IViewContribution, type IWalkOptions, type IWatchBatch, type IWatchEvent, InMemoryProgressEmitter, type Issue, type IssueFix, KV_SCHEMA_KEY, type Kernel, LOG_LEVELS, type Link, type LinkKind, type LinkLocation, type LinkTrigger, type LogRecord, type LoggerPort, type Node, type NodeKind, type NodeStat, type PluginLoaderPort, type ProgressEmitterPort, type ProgressEvent, Registry, type RenameOp, type RunScanOptions, type RunnerPort, type ScanResult, type ScanScannedBy, type ScanStats, type Severity, SilentLogger, type Stability, type StoragePort, type TActionWrite, type TContractName, type TExecutionMode, type TGranularity, type THookFilter, type THookTrigger, type TInputTypeName, type TLogLevel, type TLogMethodLevel, type TNodeChangeReason, type TPluginLoadStatus, type TPluginStorage, type TProgressListener, type TSettingValue, type TSeverity, type TWatchEventKind, type TripleSplit, applyExportQuery, computeScanDelta, configureLogger, createChokidarWatcher, createKernel, detectRenamesAndOrphans, getActiveLogger, isEmptyDelta, isLogLevel, log, logLevelRank, makeDedicatedStoreWrapper, makeKvStoreWrapper, makePluginStore, mergeNodeWithEnrichments, parseExportQuery, parseLogLevel, qualifiedExtensionId, resetLogger, runExtractorsForNode, runScan, runScanWithRenames };