@skill-map/cli 0.54.0 → 0.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/tutorial/sm-tutorial/SKILL.md +22 -24
- package/dist/cli/tutorial/sm-tutorial/references/_core.md +8 -7
- package/dist/cli/tutorial/sm-tutorial/references/_manifest.yml +21 -42
- package/dist/cli/tutorial/sm-tutorial/references/fixtures.md +15 -7
- package/dist/cli/tutorial/sm-tutorial/references/part-authoring.md +2 -2
- package/dist/cli/tutorial/sm-tutorial/references/part-cli.md +1 -1
- package/dist/cli/tutorial/sm-tutorial/references/part-connect-harness.md +9 -10
- package/dist/cli/tutorial/sm-tutorial/references/part-daily-loop.md +563 -0
- package/dist/cli/tutorial/sm-tutorial/references/part-mcp.md +5 -1
- package/dist/cli/tutorial/sm-tutorial/references/part-plugins.md +7 -7
- package/dist/cli/tutorial/sm-tutorial/references/part-project-kickoff.md +24 -12
- package/dist/cli/tutorial/sm-tutorial/references/part-settings.md +2 -2
- package/dist/cli.js +1785 -1102
- package/dist/index.js +148 -14
- package/dist/kernel/index.d.ts +229 -97
- package/dist/kernel/index.js +148 -14
- package/dist/migrations/001_initial.sql +5 -0
- package/dist/ui/chunk-4ITL7E6U.js +1 -0
- package/dist/ui/chunk-DWBJCNC7.js +2 -0
- package/dist/ui/{chunk-CXTU4HQV.js → chunk-GHOVZAAV.js} +1 -1
- package/dist/ui/{chunk-GBKHMJ4B.js → chunk-H6O2DYVT.js} +13 -13
- package/dist/ui/chunk-HDKR6XHG.js +917 -0
- package/dist/ui/{chunk-GEI6INVH.js → chunk-JA4Z74I3.js} +1 -1
- package/dist/ui/chunk-RS3ANRT5.js +1 -0
- package/dist/ui/chunk-VUNP5KNI.js +3 -0
- package/dist/ui/chunk-W3Z3CZL4.js +1844 -0
- package/dist/ui/chunk-YHJL5LP3.js +913 -0
- package/dist/ui/index.html +2 -2
- package/dist/ui/{main-HP3MOLI2.js → main-PL3BEVQI.js} +3 -3
- package/dist/ui/{styles-4SNVM34O.css → styles-RHEEXRHQ.css} +1 -1
- package/migrations/001_initial.sql +5 -0
- package/package.json +2 -2
- package/dist/cli/tutorial/sm-tutorial/references/part-live-site.md +0 -155
- package/dist/cli/tutorial/sm-tutorial/references/part-maintain.md +0 -284
- package/dist/cli/tutorial/sm-tutorial/references/part-run-harness.md +0 -181
- package/dist/ui/chunk-4CXAL43H.js +0 -1
- package/dist/ui/chunk-BUNPMGDX.js +0 -2205
- package/dist/ui/chunk-DSNBKMYU.js +0 -2
- package/dist/ui/chunk-JXRIGHET.js +0 -552
- package/dist/ui/chunk-MVRQGDZJ.js +0 -123
- package/dist/ui/chunk-WFLPMCK4.js +0 -392
package/dist/kernel/index.d.ts
CHANGED
|
@@ -1,87 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extension registry, six kinds, first-class, loaded through a single API.
|
|
3
|
-
*
|
|
4
|
-
* The `IExtension` shape is aligned with `spec/schemas/extensions/base.schema.json`.
|
|
5
|
-
* Kind-specific manifests (provider / extractor / analyzer / action / formatter /
|
|
6
|
-
* hook) extend this base structurally; the registry stores the base view
|
|
7
|
-
* and each kind's code carries its own fuller type where needed.
|
|
8
|
-
*
|
|
9
|
-
* **Spec § A.6, qualified ids.** Every extension is keyed in the registry
|
|
10
|
-
* by `<pluginId>/<id>` (e.g. `core/annotations`, `core/slash-command`,
|
|
11
|
-
* `my-plugin/my-extractor`). `IExtension.id` carries the **short** id as authored;
|
|
12
|
-
* `IExtension.pluginId` carries the namespace; the registry composes the
|
|
13
|
-
* qualifier internally and exposes lookup APIs that operate on either form
|
|
14
|
-
* (qualified for direct lookup, kind-scoped listing for enumeration).
|
|
15
|
-
*
|
|
16
|
-
* Boot invariant: `new Registry()` is empty. `registry.totalCount() === 0`
|
|
17
|
-
* when the kernel boots with zero extensions. This is the data side of the
|
|
18
|
-
* `kernel-empty-boot` conformance contract.
|
|
19
|
-
*/
|
|
20
|
-
type ExtensionKind = 'provider' | 'extractor' | 'analyzer' | 'action' | 'formatter' | 'hook';
|
|
21
|
-
declare const EXTENSION_KINDS: readonly ExtensionKind[];
|
|
22
|
-
interface IExtension {
|
|
23
|
-
/** Short (unqualified) extension id, injected by the loader from the leaf folder name. */
|
|
24
|
-
id: string;
|
|
25
|
-
/** Owning plugin namespace, injected by the loader from the plugin folder name. */
|
|
26
|
-
pluginId: string;
|
|
27
|
-
kind: ExtensionKind;
|
|
28
|
-
version: string;
|
|
29
|
-
/** Required short description; surfaced in `sm <kind>s list` and the UI. */
|
|
30
|
-
description: string;
|
|
31
|
-
entry?: string;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Compose the qualified registry key for an extension. Single source of
|
|
35
|
-
* truth so callers don't reinvent the format and a future change (e.g. a
|
|
36
|
-
* different separator) lands in one place.
|
|
37
|
-
*/
|
|
38
|
-
declare function qualifiedExtensionId(pluginId: string, id: string): string;
|
|
39
|
-
declare class DuplicateExtensionError extends Error {
|
|
40
|
-
constructor(kind: ExtensionKind, qualifiedId: string);
|
|
41
|
-
}
|
|
42
|
-
declare class Registry {
|
|
43
|
-
#private;
|
|
44
|
-
constructor();
|
|
45
|
-
register(ext: IExtension): void;
|
|
46
|
-
/**
|
|
47
|
-
* Lookup by qualified id (`<pluginId>/<id>`). Returns `undefined` when
|
|
48
|
-
* no extension of that kind is registered under the qualifier.
|
|
49
|
-
*/
|
|
50
|
-
get(kind: ExtensionKind, qualifiedId: string): IExtension | undefined;
|
|
51
|
-
/**
|
|
52
|
-
* Convenience wrapper that composes the qualified id for the caller.
|
|
53
|
-
* Equivalent to `get(kind, qualifiedExtensionId(pluginId, id))`.
|
|
54
|
-
*/
|
|
55
|
-
find(kind: ExtensionKind, pluginId: string, id: string): IExtension | undefined;
|
|
56
|
-
all(kind: ExtensionKind): IExtension[];
|
|
57
|
-
count(kind: ExtensionKind): number;
|
|
58
|
-
totalCount(): number;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Step 9.6.6, runtime annotation-contribution catalog types.
|
|
63
|
-
*
|
|
64
|
-
* Lives in its own module (rather than `kernel/index.ts`) so consumers
|
|
65
|
-
* deep inside the kernel, `IAnalyzerContext`, the BFF route factories,
|
|
66
|
-
* future Action contexts, can depend on the catalog shape without
|
|
67
|
-
* dragging the whole kernel barrel and risking a cycle.
|
|
68
|
-
*/
|
|
69
|
-
/**
|
|
70
|
-
* Single row of the runtime annotation-contribution catalog surfaced by
|
|
71
|
-
* `kernel.getRegisteredAnnotationKeys()`. One row per (plugin × key)
|
|
72
|
-
* tuple. Built-in catalog keys from `annotations.schema.json` are NOT
|
|
73
|
-
* included, this catalog is plugin-only; the UI knows the built-in
|
|
74
|
-
* catalog via the schema bundle.
|
|
75
|
-
*/
|
|
76
|
-
interface IRegisteredAnnotationKey {
|
|
77
|
-
pluginId: string;
|
|
78
|
-
key: string;
|
|
79
|
-
location: 'namespaced' | 'root';
|
|
80
|
-
ownership: 'exclusive' | 'shared';
|
|
81
|
-
/** Inline JSON Schema as declared in the manifest (not the AJV compiled validator). */
|
|
82
|
-
schema: Record<string, unknown>;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
1
|
/**
|
|
86
2
|
* Closed enum of view slot names. Mirror of
|
|
87
3
|
* `spec/schemas/view-slots.schema.json#/$defs/SlotName`.
|
|
@@ -91,7 +7,7 @@ type TSlotName = 'card.title.right' | 'card.subtitle.left' | 'card.footer.left'
|
|
|
91
7
|
* Closed enum of input-type names for plugin settings. Mirror of
|
|
92
8
|
* `spec/schemas/input-types.schema.json#/$defs/InputTypeName`.
|
|
93
9
|
*/
|
|
94
|
-
type TInputTypeName = 'string-list' | 'single-string' | 'boolean-flag' | 'integer' | 'enum-pick' | 'enum-multipick' | 'path-glob' | 'regex' | 'secret' | 'key-value-list';
|
|
10
|
+
type TInputTypeName = 'string-list' | 'single-string' | 'boolean-flag' | 'integer' | 'number' | 'enum-pick' | 'enum-multipick' | 'path-glob' | 'regex' | 'secret' | 'key-value-list';
|
|
95
11
|
/**
|
|
96
12
|
* Closed severity palette aligned with PrimeNG `<p-tag>` / `<p-message>` severities. Used by counter, tag, alert, and icon slots for color/contrast hints. The UI maps each severity to a theme-aware tint; plugins do not pick raw colors.
|
|
97
13
|
*/
|
|
@@ -199,7 +115,7 @@ interface ActionPrompt {
|
|
|
199
115
|
/**
|
|
200
116
|
* Input-type id from the closed catalog. The UI renders the matching control before dispatch (`single-string`, `enum-pick` and `string-list` today; other types degrade to a graceful 'unsupported' notice).
|
|
201
117
|
*/
|
|
202
|
-
inputType: ('string-list' | 'single-string' | 'boolean-flag' | 'integer' | 'enum-pick' | 'enum-multipick' | 'path-glob' | 'regex' | 'secret' | 'key-value-list') & string;
|
|
118
|
+
inputType: ('string-list' | 'single-string' | 'boolean-flag' | 'integer' | 'number' | 'enum-pick' | 'enum-multipick' | 'path-glob' | 'regex' | 'secret' | 'key-value-list') & string;
|
|
203
119
|
/**
|
|
204
120
|
* Key under which the collected value is placed in the dispatch `input` body.
|
|
205
121
|
*/
|
|
@@ -474,6 +390,13 @@ interface ISetting_Integer extends ISettingCommon {
|
|
|
474
390
|
max?: number;
|
|
475
391
|
step?: number;
|
|
476
392
|
}
|
|
393
|
+
interface ISetting_Number extends ISettingCommon {
|
|
394
|
+
type: 'number';
|
|
395
|
+
default?: number;
|
|
396
|
+
min?: number;
|
|
397
|
+
max?: number;
|
|
398
|
+
step?: number;
|
|
399
|
+
}
|
|
477
400
|
interface ISetting_EnumOption {
|
|
478
401
|
value: string;
|
|
479
402
|
label: string;
|
|
@@ -530,7 +453,7 @@ interface ISetting_KeyValueList extends ISettingCommon {
|
|
|
530
453
|
*
|
|
531
454
|
* Mirror of `input-types.schema.json#/$defs/ISettingDeclaration`.
|
|
532
455
|
*/
|
|
533
|
-
type TSettingDeclaration = ISetting_StringList | ISetting_SingleString | ISetting_BooleanFlag | ISetting_Integer | ISetting_EnumPick | ISetting_EnumMultipick | ISetting_PathGlob | ISetting_Regex | ISetting_Secret | ISetting_KeyValueList;
|
|
456
|
+
type TSettingDeclaration = ISetting_StringList | ISetting_SingleString | ISetting_BooleanFlag | ISetting_Integer | ISetting_Number | ISetting_EnumPick | ISetting_EnumMultipick | ISetting_PathGlob | ISetting_Regex | ISetting_Secret | ISetting_KeyValueList;
|
|
534
457
|
/**
|
|
535
458
|
* Runtime value type for a setting, derived from its declaration. The
|
|
536
459
|
* kernel exposes settings to extractors as `Record<string, TSettingValue>`
|
|
@@ -554,13 +477,24 @@ type TSettingValue = string | string[] | boolean | number | ISetting_KeyValueLis
|
|
|
554
477
|
*/
|
|
555
478
|
|
|
556
479
|
/**
|
|
557
|
-
* Lifecycle label an extension manifest MAY declare.
|
|
558
|
-
*
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
*
|
|
480
|
+
* Lifecycle label an extension manifest MAY declare. Renders as a badge
|
|
481
|
+
* next to the extension in `sm plugins list <id>` / `sm plugins show` and
|
|
482
|
+
* the Settings plugins panel for the non-default values.
|
|
483
|
+
*
|
|
484
|
+
* Two values ALSO change behaviour: `experimental` (not ready yet) and
|
|
485
|
+
* `deprecated` (on its way out) flip the extension's installed default
|
|
486
|
+
* to DISABLED, so the extension does not load (does not run, does not
|
|
487
|
+
* register) unless the operator opts in (`sm plugins enable
|
|
488
|
+
* <plugin>/<ext>`, the Settings toggle, or a `settings.json` /
|
|
489
|
+
* `config_plugins` override). The opt-in is a plain enable override,
|
|
490
|
+
* once set it wins over the installed default exactly like any other
|
|
491
|
+
* extension (so a deprecated extension can still be kept running during
|
|
492
|
+
* a migration). The remaining values are presentation-only and default
|
|
493
|
+
* to ENABLED: `beta` runs by default with a badge, `stable` (declared
|
|
494
|
+
* or defaulted) runs with no badge. Missing == `stable` == enabled, no
|
|
495
|
+
* badge. Mirrors
|
|
563
496
|
* `spec/schemas/extensions/base.schema.json#/properties/stability`.
|
|
497
|
+
*
|
|
564
498
|
* Deliberately a superset of the node-level annotations enum (which has
|
|
565
499
|
* no `beta`): this describes the maturity of the extension itself, not
|
|
566
500
|
* of a scanned node.
|
|
@@ -620,8 +554,9 @@ interface IExtensionBase {
|
|
|
620
554
|
description: string;
|
|
621
555
|
/**
|
|
622
556
|
* Optional lifecycle label (`experimental` / `beta` / `stable` /
|
|
623
|
-
* `deprecated`). Missing == `stable`, no badge rendered.
|
|
624
|
-
* `
|
|
557
|
+
* `deprecated`). Missing == `stable`, no badge rendered. `experimental`
|
|
558
|
+
* and `deprecated` additionally flip the installed default to disabled.
|
|
559
|
+
* See `TExtensionStability` for the full semantics.
|
|
625
560
|
*/
|
|
626
561
|
stability?: TExtensionStability;
|
|
627
562
|
/**
|
|
@@ -657,14 +592,107 @@ interface IExtensionBase {
|
|
|
657
592
|
* `viewContributions` with the structure-as-truth refactor. Each
|
|
658
593
|
* entry maps a local contribution id (kebab-case, unique within the
|
|
659
594
|
* extension) to an `IViewContribution` that picks a view slot by
|
|
660
|
-
* name from the closed catalog.
|
|
661
|
-
*
|
|
595
|
+
* name from the closed catalog. Declared by `extractor` and
|
|
596
|
+
* `analyzer` kinds (emitted during scan / graph evaluation) and by
|
|
597
|
+
* `action` kinds (emitted from the Action's scan-time `project()`
|
|
598
|
+
* self-projection, see `IActionProjectionContext`).
|
|
662
599
|
*/
|
|
663
600
|
ui?: Record<string, IViewContribution>;
|
|
664
601
|
/** Runtime-only, absolute path of the extension entry file. */
|
|
665
602
|
entry?: string;
|
|
666
603
|
}
|
|
667
604
|
|
|
605
|
+
/**
|
|
606
|
+
* Extension registry, six kinds, first-class, loaded through a single API.
|
|
607
|
+
*
|
|
608
|
+
* The `IExtension` shape is aligned with `spec/schemas/extensions/base.schema.json`.
|
|
609
|
+
* Kind-specific manifests (provider / extractor / analyzer / action / formatter /
|
|
610
|
+
* hook) extend this base structurally; the registry stores the base view
|
|
611
|
+
* and each kind's code carries its own fuller type where needed.
|
|
612
|
+
*
|
|
613
|
+
* **Spec § A.6, qualified ids.** Every extension is keyed in the registry
|
|
614
|
+
* by `<pluginId>/<id>` (e.g. `core/annotations`, `core/slash-command`,
|
|
615
|
+
* `my-plugin/my-extractor`). `IExtension.id` carries the **short** id as authored;
|
|
616
|
+
* `IExtension.pluginId` carries the namespace; the registry composes the
|
|
617
|
+
* qualifier internally and exposes lookup APIs that operate on either form
|
|
618
|
+
* (qualified for direct lookup, kind-scoped listing for enumeration).
|
|
619
|
+
*
|
|
620
|
+
* Boot invariant: `new Registry()` is empty. `registry.totalCount() === 0`
|
|
621
|
+
* when the kernel boots with zero extensions. This is the data side of the
|
|
622
|
+
* `kernel-empty-boot` conformance contract.
|
|
623
|
+
*/
|
|
624
|
+
|
|
625
|
+
type ExtensionKind = 'provider' | 'extractor' | 'analyzer' | 'action' | 'formatter' | 'hook';
|
|
626
|
+
declare const EXTENSION_KINDS: readonly ExtensionKind[];
|
|
627
|
+
interface IExtension {
|
|
628
|
+
/** Short (unqualified) extension id, injected by the loader from the leaf folder name. */
|
|
629
|
+
id: string;
|
|
630
|
+
/** Owning plugin namespace, injected by the loader from the plugin folder name. */
|
|
631
|
+
pluginId: string;
|
|
632
|
+
kind: ExtensionKind;
|
|
633
|
+
version: string;
|
|
634
|
+
/** Required short description; surfaced in `sm <kind>s list` and the UI. */
|
|
635
|
+
description: string;
|
|
636
|
+
/**
|
|
637
|
+
* Optional lifecycle label (`IExtensionBase.stability`). Carried on the
|
|
638
|
+
* registry view so the enabled-resolver can read it: `experimental`
|
|
639
|
+
* flips an extension's installed default to disabled. Absent == stable.
|
|
640
|
+
*/
|
|
641
|
+
stability?: TExtensionStability;
|
|
642
|
+
entry?: string;
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Compose the qualified registry key for an extension. Single source of
|
|
646
|
+
* truth so callers don't reinvent the format and a future change (e.g. a
|
|
647
|
+
* different separator) lands in one place.
|
|
648
|
+
*/
|
|
649
|
+
declare function qualifiedExtensionId(pluginId: string, id: string): string;
|
|
650
|
+
declare class DuplicateExtensionError extends Error {
|
|
651
|
+
constructor(kind: ExtensionKind, qualifiedId: string);
|
|
652
|
+
}
|
|
653
|
+
declare class Registry {
|
|
654
|
+
#private;
|
|
655
|
+
constructor();
|
|
656
|
+
register(ext: IExtension): void;
|
|
657
|
+
/**
|
|
658
|
+
* Lookup by qualified id (`<pluginId>/<id>`). Returns `undefined` when
|
|
659
|
+
* no extension of that kind is registered under the qualifier.
|
|
660
|
+
*/
|
|
661
|
+
get(kind: ExtensionKind, qualifiedId: string): IExtension | undefined;
|
|
662
|
+
/**
|
|
663
|
+
* Convenience wrapper that composes the qualified id for the caller.
|
|
664
|
+
* Equivalent to `get(kind, qualifiedExtensionId(pluginId, id))`.
|
|
665
|
+
*/
|
|
666
|
+
find(kind: ExtensionKind, pluginId: string, id: string): IExtension | undefined;
|
|
667
|
+
all(kind: ExtensionKind): IExtension[];
|
|
668
|
+
count(kind: ExtensionKind): number;
|
|
669
|
+
totalCount(): number;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* Step 9.6.6, runtime annotation-contribution catalog types.
|
|
674
|
+
*
|
|
675
|
+
* Lives in its own module (rather than `kernel/index.ts`) so consumers
|
|
676
|
+
* deep inside the kernel, `IAnalyzerContext`, the BFF route factories,
|
|
677
|
+
* future Action contexts, can depend on the catalog shape without
|
|
678
|
+
* dragging the whole kernel barrel and risking a cycle.
|
|
679
|
+
*/
|
|
680
|
+
/**
|
|
681
|
+
* Single row of the runtime annotation-contribution catalog surfaced by
|
|
682
|
+
* `kernel.getRegisteredAnnotationKeys()`. One row per (plugin × key)
|
|
683
|
+
* tuple. Built-in catalog keys from `annotations.schema.json` are NOT
|
|
684
|
+
* included, this catalog is plugin-only; the UI knows the built-in
|
|
685
|
+
* catalog via the schema bundle.
|
|
686
|
+
*/
|
|
687
|
+
interface IRegisteredAnnotationKey {
|
|
688
|
+
pluginId: string;
|
|
689
|
+
key: string;
|
|
690
|
+
location: 'namespaced' | 'root';
|
|
691
|
+
ownership: 'exclusive' | 'shared';
|
|
692
|
+
/** Inline JSON Schema as declared in the manifest (not the AJV compiled validator). */
|
|
693
|
+
schema: Record<string, unknown>;
|
|
694
|
+
}
|
|
695
|
+
|
|
668
696
|
/**
|
|
669
697
|
* Domain types, byte-aligned with `spec/schemas/{node,link,issue,scan-result}.schema.json`.
|
|
670
698
|
*
|
|
@@ -897,6 +925,16 @@ interface Node {
|
|
|
897
925
|
externalRefs?: IExternalRef[];
|
|
898
926
|
frontmatter?: Record<string, unknown>;
|
|
899
927
|
tokens?: TripleSplit;
|
|
928
|
+
/**
|
|
929
|
+
* File modification time (`mtime`) in Unix milliseconds, captured at
|
|
930
|
+
* scan time from the on-disk `lstat`. Absent for virtual / derived
|
|
931
|
+
* nodes (`virtual === true`, no backing file) and for nodes built by a
|
|
932
|
+
* Provider `walk()` that does not stat its sources. Persisted to
|
|
933
|
+
* `scan_nodes.modified_at_ms` and surfaced on `/api/nodes` /
|
|
934
|
+
* `/api/scan` so the UI can show and sort a "last modified" column.
|
|
935
|
+
* NOT content: never participates in `bodyHash` / `frontmatterHash`.
|
|
936
|
+
*/
|
|
937
|
+
modifiedAtMs?: number;
|
|
900
938
|
/**
|
|
901
939
|
* Step 9.6.2, sidecar denormalisation surface. Populated by the
|
|
902
940
|
* orchestrator at scan time; absent when the orchestrator did not
|
|
@@ -2190,6 +2228,15 @@ interface IRawNode {
|
|
|
2190
2228
|
frontmatterRaw: string;
|
|
2191
2229
|
/** Parsed frontmatter, or `{}` when absent / unparseable. */
|
|
2192
2230
|
frontmatter: Record<string, unknown>;
|
|
2231
|
+
/**
|
|
2232
|
+
* File modification time (`mtime`) in Unix milliseconds, captured by
|
|
2233
|
+
* the kernel walker from the same `lstat` that guards the read (zero
|
|
2234
|
+
* extra syscalls). Threaded onto the persisted `Node` as
|
|
2235
|
+
* `modifiedAtMs`. Optional: a Provider that ships its own `walk()` and
|
|
2236
|
+
* does not stat its sources MAY omit it; virtual / derived nodes carry
|
|
2237
|
+
* no file and never set it.
|
|
2238
|
+
*/
|
|
2239
|
+
modifiedAtMs?: number;
|
|
2193
2240
|
/**
|
|
2194
2241
|
* Parser diagnostics (audit L1). Populated by the walker when the
|
|
2195
2242
|
* parser surfaced `IParseIssue` entries (e.g. malformed YAML).
|
|
@@ -2893,6 +2940,12 @@ interface IAnalyzerOrphanSidecar {
|
|
|
2893
2940
|
interface IAnalyzerContext {
|
|
2894
2941
|
nodes: Node[];
|
|
2895
2942
|
links: Link[];
|
|
2943
|
+
/**
|
|
2944
|
+
* Resolved values of the analyzer's declared `settings`, populated
|
|
2945
|
+
* from project config + user overrides. Empty object when no settings
|
|
2946
|
+
* are declared.
|
|
2947
|
+
*/
|
|
2948
|
+
settings: Record<string, unknown>;
|
|
2896
2949
|
/**
|
|
2897
2950
|
* Step 9.6.2, orphaned sidecars discovered during the scan walk.
|
|
2898
2951
|
* Empty when sidecar discovery did not run (legacy callers) or
|
|
@@ -2984,6 +3037,20 @@ interface IAnalyzerContext {
|
|
|
2984
3037
|
* `runScan` sites that never wired the field through).
|
|
2985
3038
|
*/
|
|
2986
3039
|
reservedNodePaths?: ReadonlySet<string>;
|
|
3040
|
+
/**
|
|
3041
|
+
* Links the post-walk lift judged genuinely broken: target matches no
|
|
3042
|
+
* node `path` AND the stripped trigger matches no entry in the cross-
|
|
3043
|
+
* kind name index (`spec/architecture.md` §Provider · resolution
|
|
3044
|
+
* rules). Computed once per scan by the orchestrator from the same
|
|
3045
|
+
* `deriveNodeIdentifiers`-backed index the confidence-lift transform
|
|
3046
|
+
* uses, so a link that resolves only via a filename / dirname
|
|
3047
|
+
* identifier is NOT in the set. Membership is by object identity (the
|
|
3048
|
+
* orchestrator threads the SAME link objects). The single consumer is
|
|
3049
|
+
* `core/reference-broken`, which projects one issue per member (after
|
|
3050
|
+
* its `referenceablePaths` escape hatch). Absent for legacy callers
|
|
3051
|
+
* that never wired the field through, the rule then emits nothing.
|
|
3052
|
+
*/
|
|
3053
|
+
brokenLinks?: ReadonlySet<Link>;
|
|
2987
3054
|
/**
|
|
2988
3055
|
* Absolute path of the scan's project root (cwd of the invocation).
|
|
2989
3056
|
* Threaded into the analyzer pass so an analyzer that needs to
|
|
@@ -3126,6 +3193,32 @@ interface IActionContext {
|
|
|
3126
3193
|
*/
|
|
3127
3194
|
settings: Record<string, unknown>;
|
|
3128
3195
|
}
|
|
3196
|
+
/**
|
|
3197
|
+
* Read-only graph context handed to an Action's scan-time `project()`
|
|
3198
|
+
* method. Mirrors the Analyzer emit path (`IAnalyzerContext`): the
|
|
3199
|
+
* Action sees the full merged graph (`nodes` + `links`) and emits its
|
|
3200
|
+
* own per-node view contributions via `emitContribution`, supplying the
|
|
3201
|
+
* target node path explicitly because, like the Analyzer, it walks the
|
|
3202
|
+
* whole graph rather than running per-node.
|
|
3203
|
+
*
|
|
3204
|
+
* The contribution is declared in the Action's manifest `ui` map and
|
|
3205
|
+
* passed BY REFERENCE (same object-identity model as Extractor /
|
|
3206
|
+
* Analyzer emit). The orchestrator validates the payload against the
|
|
3207
|
+
* slot's schema at call time, dropping invalid emissions with an
|
|
3208
|
+
* `extension.error` event.
|
|
3209
|
+
*
|
|
3210
|
+
* `project()` is strictly DETERMINISTIC and side-effect-free: no writes,
|
|
3211
|
+
* no runner, no IO. It runs during the scan's contribution phase on
|
|
3212
|
+
* EVERY scan, exactly like an Analyzer's emit path, so its cost is the
|
|
3213
|
+
* same per-scan cost as today's projector analyzers. Even an Action
|
|
3214
|
+
* whose `invoke` is `mode: 'probabilistic'` MUST keep `project()`
|
|
3215
|
+
* deterministic, only `invoke` may be probabilistic.
|
|
3216
|
+
*/
|
|
3217
|
+
interface IActionProjectionContext {
|
|
3218
|
+
readonly nodes: readonly Node[];
|
|
3219
|
+
readonly links: readonly Link[];
|
|
3220
|
+
emitContribution(nodePath: string, ref: IViewContribution, payload: unknown): void;
|
|
3221
|
+
}
|
|
3129
3222
|
/**
|
|
3130
3223
|
* Declarative filter applied by `--all` fan-out, UI button gating, and
|
|
3131
3224
|
* `sm actions show`. Same shape used by Extractor and Analyzer so the
|
|
@@ -3182,6 +3275,23 @@ interface IAction extends IExtensionBase {
|
|
|
3182
3275
|
* kernel materialises any returned `writes` after the call.
|
|
3183
3276
|
*/
|
|
3184
3277
|
invoke?: <TInput, TReport>(input: TInput, ctx: IActionContext) => IActionResult<TReport>;
|
|
3278
|
+
/**
|
|
3279
|
+
* Optional scan-time self-projection. When present, the orchestrator
|
|
3280
|
+
* calls it during the contribution phase (right after the analyzer
|
|
3281
|
+
* pass) with read-only graph access, and the Action emits its OWN
|
|
3282
|
+
* `inspector.action.button` (or any declared `ui` contribution) per
|
|
3283
|
+
* node. This replaces the former "projector analyzer" pattern: the
|
|
3284
|
+
* button now lives with the Action that dispatches it, not in a
|
|
3285
|
+
* sibling Analyzer.
|
|
3286
|
+
*
|
|
3287
|
+
* MUST be deterministic and side-effect-free (no writes, no runner,
|
|
3288
|
+
* no IO), exactly like an Analyzer's emit path. The button declares
|
|
3289
|
+
* its own qualified id as `actionId` in the payload. Actions that ship
|
|
3290
|
+
* for the future probabilistic runner / record path leave it absent;
|
|
3291
|
+
* an Action MAY declare both `project` and `invoke` (advertiser +
|
|
3292
|
+
* executor), or only one.
|
|
3293
|
+
*/
|
|
3294
|
+
project?(ctx: IActionProjectionContext): void;
|
|
3185
3295
|
}
|
|
3186
3296
|
|
|
3187
3297
|
/**
|
|
@@ -3202,6 +3312,12 @@ interface IFormatterContext {
|
|
|
3202
3312
|
nodes: Node[];
|
|
3203
3313
|
links: Link[];
|
|
3204
3314
|
issues: Issue[];
|
|
3315
|
+
/**
|
|
3316
|
+
* Resolved values of the formatter's declared `settings`, populated
|
|
3317
|
+
* from project config + user overrides. Empty object when no settings
|
|
3318
|
+
* are declared.
|
|
3319
|
+
*/
|
|
3320
|
+
settings: Record<string, unknown>;
|
|
3205
3321
|
/**
|
|
3206
3322
|
* Full persisted scan, when the caller has it on hand. Optional so
|
|
3207
3323
|
* formatters that only consume (nodes, links, issues) keep working
|
|
@@ -3305,6 +3421,12 @@ declare const HOOK_TRIGGERS: readonly THookTrigger[];
|
|
|
3305
3421
|
* Deterministic hooks SHOULD ignore the field.
|
|
3306
3422
|
*/
|
|
3307
3423
|
interface IHookContext {
|
|
3424
|
+
/**
|
|
3425
|
+
* Resolved values of the hook's declared `settings`, populated from
|
|
3426
|
+
* project config + user overrides. Empty object when no settings are
|
|
3427
|
+
* declared.
|
|
3428
|
+
*/
|
|
3429
|
+
settings: Record<string, unknown>;
|
|
3308
3430
|
/** The raw event the dispatcher matched. */
|
|
3309
3431
|
event: {
|
|
3310
3432
|
type: THookTrigger;
|
|
@@ -3648,6 +3770,16 @@ interface IScanExtensions {
|
|
|
3648
3770
|
* advisory until the job subsystem ships once the job subsystem ships.
|
|
3649
3771
|
*/
|
|
3650
3772
|
hooks?: IHook[];
|
|
3773
|
+
/**
|
|
3774
|
+
* Optional enabled actions. When supplied, the orchestrator runs the
|
|
3775
|
+
* action-projection pass right after the analyzer pass: every action
|
|
3776
|
+
* carrying a scan-time `project()` self-projection emits its own view
|
|
3777
|
+
* contributions (e.g. `inspector.action.button`) onto the merged
|
|
3778
|
+
* graph. Actions without `project` (only `invoke`) ride along inert.
|
|
3779
|
+
* Absent → no projection pass runs (the gate is the composed enabled
|
|
3780
|
+
* set, so a disabled / experimental action never reaches here).
|
|
3781
|
+
*/
|
|
3782
|
+
actions?: IAction[];
|
|
3651
3783
|
}
|
|
3652
3784
|
interface RunScanOptions {
|
|
3653
3785
|
/**
|