@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.
- package/README.md +4 -0
- package/dist/cli/tutorial/sm-tutorial.md +6 -7
- package/dist/cli.js +7011 -4047
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +277 -42
- package/dist/index.js.map +1 -1
- package/dist/kernel/index.d.ts +566 -68
- package/dist/kernel/index.js +277 -42
- package/dist/kernel/index.js.map +1 -1
- package/dist/migrations/001_initial.sql +122 -12
- package/dist/ui/chunk-7CAK6MVK.js +2638 -0
- package/dist/ui/chunk-BORRASJB.js +247 -0
- package/dist/ui/chunk-CZSS4D6J.js +454 -0
- package/dist/ui/chunk-EQD7AYYJ.js +227 -0
- package/dist/ui/chunk-ETTRVTFV.js +1 -0
- package/dist/ui/chunk-LFIE4SCX.js +965 -0
- package/dist/ui/chunk-OKO3QOH6.js +1 -0
- package/dist/ui/chunk-PMIMYHBM.js +61 -0
- package/dist/ui/chunk-UHFGCO24.js +1 -0
- package/dist/ui/chunk-VHIPW3TH.js +1 -0
- package/dist/ui/chunk-VWAUXWQX.js +237 -0
- package/dist/ui/index.html +10 -2
- package/dist/ui/main-BSYMJKTL.js +1 -0
- package/dist/ui/{styles-CBPFNGXA.css → styles-UAABA7VK.css} +1 -1
- package/migrations/001_initial.sql +122 -12
- package/package.json +2 -2
- package/dist/migrations/002_sidecar_columns.sql +0 -53
- package/dist/migrations/003_drop_node_author.sql +0 -20
- package/dist/migrations/004_sidecar_root_json.sql +0 -23
- package/dist/migrations/005_node_favorites.sql +0 -20
- package/dist/ui/chunk-JKJGGXCS.js +0 -1025
- package/dist/ui/chunk-SX2A3WBX.js +0 -247
- package/dist/ui/chunk-TWZHUCAT.js +0 -237
- package/dist/ui/chunk-WTAL2RK4.js +0 -1
- package/dist/ui/chunk-Z3UJHHTC.js +0 -3091
- package/dist/ui/main-AAYGMON4.js +0 -1
- package/migrations/002_sidecar_columns.sql +0 -53
- package/migrations/003_drop_node_author.sql +0 -20
- package/migrations/004_sidecar_root_json.sql +0 -23
- package/migrations/005_node_favorites.sql +0 -20
package/dist/kernel/index.d.ts
CHANGED
|
@@ -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/
|
|
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
|
|
1168
|
-
*
|
|
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
|
|
1250
|
-
*
|
|
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
|
|
1934
|
-
*
|
|
1935
|
-
*
|
|
1936
|
-
*
|
|
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`.
|
|
2041
|
-
*
|
|
2042
|
-
*
|
|
2043
|
-
*
|
|
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 };
|