@skill-map/cli 0.20.0 → 0.21.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 (37) hide show
  1. package/dist/cli/tutorial/sm-tutorial.md +93 -14
  2. package/dist/cli.js +1332 -339
  3. package/dist/cli.js.map +1 -1
  4. package/dist/index.js +300 -238
  5. package/dist/index.js.map +1 -1
  6. package/dist/kernel/index.d.ts +91 -11
  7. package/dist/kernel/index.js +300 -238
  8. package/dist/kernel/index.js.map +1 -1
  9. package/dist/migrations/001_initial.sql +13 -0
  10. package/dist/ui/chunk-25AWRVIC.js +965 -0
  11. package/dist/ui/chunk-6FTVUS57.js +123 -0
  12. package/dist/ui/{chunk-LQTUSDHD.js → chunk-GXRWH2VL.js} +1 -1
  13. package/dist/ui/chunk-MF2M6GYF.js +1 -0
  14. package/dist/ui/{chunk-2W62S3FU.js → chunk-MPMBTIUR.js} +2 -2
  15. package/dist/ui/chunk-N366HMME.js +1 -0
  16. package/dist/ui/{chunk-QICH7GU2.js → chunk-OPPQMCMQ.js} +1 -1
  17. package/dist/ui/chunk-V3SZQETX.js +61 -0
  18. package/dist/ui/{chunk-HJSRMZTK.js → chunk-VVOEPDQD.js} +1 -1
  19. package/dist/ui/{chunk-DLT5AP43.js → chunk-W2EFGI3J.js} +1 -1
  20. package/dist/ui/chunk-W62WVNU4.js +251 -0
  21. package/dist/ui/index.html +2 -10
  22. package/dist/ui/main-NIYE2VFS.js +2 -0
  23. package/dist/ui/media/fa-brands-400-AHOAZHCU.woff2 +0 -0
  24. package/dist/ui/media/fa-regular-400-VRZYIBIZ.woff2 +0 -0
  25. package/dist/ui/media/fa-solid-900-MDEYK55F.woff2 +0 -0
  26. package/dist/ui/media/fa-v4compatibility-ETEVP6IB.woff2 +0 -0
  27. package/dist/ui/styles-M2FETVAG.css +1 -0
  28. package/migrations/001_initial.sql +13 -0
  29. package/package.json +2 -2
  30. package/dist/ui/chunk-C7QWBAYP.js +0 -247
  31. package/dist/ui/chunk-HOBQ4G4O.js +0 -125
  32. package/dist/ui/chunk-IBUV6OG2.js +0 -1
  33. package/dist/ui/chunk-UJRROL5X.js +0 -1
  34. package/dist/ui/chunk-VLNLJAUB.js +0 -61
  35. package/dist/ui/chunk-W3JLG7BI.js +0 -965
  36. package/dist/ui/main-QHE47BCM.js +0 -1
  37. package/dist/ui/styles-VJ5Q6D2X.css +0 -1
@@ -484,7 +484,7 @@ interface IRegisteredAnnotationKey {
484
484
  * validates each pick at load time (`invalid-manifest` on miss); the
485
485
  * slot fixes both the renderer and the payload shape.
486
486
  */
487
- type TSlotName = 'card.title.right' | 'card.subtitle.left' | 'card.footer.left.counter' | 'card.footer.right' | 'graph.node.alert' | 'inspector.header.badge.counter' | 'inspector.header.badge.tag' | 'inspector.body.panel.breakdown' | 'inspector.body.panel.records' | 'inspector.body.panel.tree' | 'inspector.body.panel.key-values' | 'inspector.body.panel.link-list' | 'inspector.body.panel.markdown' | 'topbar.actions.indicator';
487
+ type TSlotName = 'card.title.right' | 'card.subtitle.left' | 'card.footer.left' | 'card.footer.right' | 'graph.node.alert' | 'inspector.header.badge.counter' | 'inspector.header.badge.tag' | 'inspector.body.panel.breakdown' | 'inspector.body.panel.records' | 'inspector.body.panel.tree' | 'inspector.body.panel.key-values' | 'inspector.body.panel.link-list' | 'inspector.body.panel.markdown' | 'topbar.nav.start';
488
488
  /**
489
489
  * Closed enum of input-type names for plugin settings. Mirror of
490
490
  * `spec/schemas/input-types.schema.json#/$defs/InputTypeName`.
@@ -1191,6 +1191,67 @@ interface IPersistedContribution {
1191
1191
  emittedAt: number;
1192
1192
  }
1193
1193
 
1194
+ /**
1195
+ * `loadScanResult` — driving inverse of `persistScanResult`. Reads the
1196
+ * `scan_*` tables and reconstructs a `ScanResult` shape so the
1197
+ * orchestrator can run an incremental scan (`sm scan --changed`) on
1198
+ * top of a prior snapshot.
1199
+ *
1200
+ * The reconstruction is faithful for everything that was actually
1201
+ * persisted: nodes (with triple-split bytes / tokens, denormalised
1202
+ * counts, JSON frontmatter), internal links (with regrouped
1203
+ * `trigger` / `location`, parsed `sources[]`), and issues
1204
+ * (with parsed `nodeIds` / `linkIndices` / `fix` / `data`).
1205
+ *
1206
+ * **Documented omission**: external pseudo-links (those whose target is
1207
+ * an `http://` / `https://` URL emitted by the external-url-counter
1208
+ * extractor) are NEVER persisted to `scan_links` — only their per-node
1209
+ * count survives in `scan_nodes.external_refs_count`. Therefore the
1210
+ * `result.links` returned by `loadScanResult` contains only internal
1211
+ * graph links, and `node.externalRefsCount` is the authoritative count
1212
+ * carried over from the prior scan. The orchestrator's incremental path
1213
+ * preserves that count for "unchanged" nodes and re-derives it for
1214
+ * new / modified nodes from a fresh extractor pass.
1215
+ *
1216
+ * Meta envelope: the `scan_meta` table persists `scope` / `roots` /
1217
+ * `scannedAt` / `scannedBy` / `providers` / `stats.filesWalked` /
1218
+ * `stats.filesSkipped` / `stats.durationMs`. When the row exists,
1219
+ * those fields come back authoritatively. When it does not (DB
1220
+ * freshly migrated but never scanned, or a legacy DB never
1221
+ * re-persisted), the loader degrades to a synthetic envelope:
1222
+ *
1223
+ * - `scannedAt` ← max(`scan_nodes.scanned_at`); falls back to `Date.now()`
1224
+ * for empty snapshots so the field stays a positive integer.
1225
+ * - `scope` ← `'project'`.
1226
+ * - `roots` ← `['.']` to satisfy spec's `minItems: 1`. NOT
1227
+ * load-bearing: the orchestrator's incremental path only reads
1228
+ * `nodes` / `links` / `issues` from the prior; it never reuses the
1229
+ * prior `roots`.
1230
+ * - `providers` ← `[]`.
1231
+ * - `stats` ← zeros for `filesWalked` / `filesSkipped` /
1232
+ * `durationMs`; the three count fields derive from row counts.
1233
+ *
1234
+ * Both branches keep `nodesCount` / `linksCount` / `issuesCount` derived
1235
+ * from `COUNT(*)` of the loaded rows — never persisted, always recomputed.
1236
+ */
1237
+
1238
+ /**
1239
+ * Spec § A.9 — load the fine-grained Extractor cache as a per-node map
1240
+ * from qualified extractor id (`<pluginId>/<id>`) to the run-time
1241
+ * hashes the extractor recorded on its last run. Empty map is the
1242
+ * default when the table is empty (fresh DB, never-scanned scope, or
1243
+ * every extractor has been uninstalled since the last scan).
1244
+ *
1245
+ * Returned shape: `Map<nodePath, Map<extractorId, IPriorExtractorRun>>`.
1246
+ * The inner value carries the body hash AND the sidecar-annotations
1247
+ * hash so the orchestrator can apply the widened cache key (both must
1248
+ * match for a cache hit).
1249
+ */
1250
+ interface IPriorExtractorRun {
1251
+ bodyHash: string;
1252
+ sidecarAnnotationsHash: string;
1253
+ }
1254
+
1194
1255
  /**
1195
1256
  * Provider runtime contract. Walks filesystem roots and emits raw node
1196
1257
  * records; classification maps path conventions to a node kind.
@@ -2266,7 +2327,7 @@ interface RunScanOptions {
2266
2327
  strict?: boolean;
2267
2328
  /**
2268
2329
  * Spec § A.9 — fine-grained Extractor cache breadcrumbs from the
2269
- * prior scan. Shape: `Map<nodePath, Map<qualifiedExtractorId, bodyHashAtRun>>`.
2330
+ * prior scan. Shape: `Map<nodePath, Map<qualifiedExtractorId, IPriorExtractorRun>>`.
2270
2331
  * Loaded from the `scan_extractor_runs` table by the CLI before
2271
2332
  * invoking `runScan`; absent / empty for a fresh DB or an out-of-band
2272
2333
  * caller that does not maintain a cache. Decoupled from `priorSnapshot`
@@ -2278,11 +2339,12 @@ interface RunScanOptions {
2278
2339
  * registered extractor that applies to this kind has a matching
2279
2340
  * row → full skip, all prior outbound links reused.
2280
2341
  * - some applicable extractor lacks a matching row (newly registered,
2281
- * or its prior run targeted a different body hash) run only the
2282
- * missing extractors, drop prior links whose `sources` map to any
2283
- * missing extractor or to an extractor that is no longer registered.
2342
+ * or its prior run targeted a different body hash or sidecar
2343
+ * annotations hash) run only the missing extractors, drop prior
2344
+ * links whose `sources` map to any missing extractor or to an
2345
+ * extractor that is no longer registered.
2284
2346
  */
2285
- priorExtractorRuns?: Map<string, Map<string, string>>;
2347
+ priorExtractorRuns?: Map<string, Map<string, IPriorExtractorRun>>;
2286
2348
  /**
2287
2349
  * Spec § A.12 — per-plugin storage wrappers exposed to extractors via
2288
2350
  * `ctx.store`. Keyed by `pluginId`; absent / missing entry leaves
@@ -2345,6 +2407,14 @@ interface IExtractorRunRecord {
2345
2407
  extractorId: string;
2346
2408
  bodyHashAtRun: string;
2347
2409
  ranAt: number;
2410
+ /**
2411
+ * sha256 of the canonical-form sidecar annotations the Extractor saw
2412
+ * at run time. Always populated (an absent sidecar canonicalises to
2413
+ * `{}` so the hash is stable). Used unconditionally by the cache
2414
+ * decision alongside `bodyHashAtRun`: a sidecar-only edit invalidates
2415
+ * the cached run for every applicable Extractor on that node.
2416
+ */
2417
+ sidecarAnnotationsHashAtRun: string;
2348
2418
  }
2349
2419
  /**
2350
2420
  * Spec § A.8 — universal enrichment layer.
@@ -3170,9 +3240,11 @@ interface StoragePort {
3170
3240
  load(): Promise<ScanResult>;
3171
3241
  /**
3172
3242
  * Spec § A.9 — fine-grained extractor-runs cache breadcrumbs.
3173
- * Returns `Map<nodePath, Map<qualifiedExtractorId, bodyHashAtRun>>`.
3243
+ * Returns `Map<nodePath, Map<qualifiedExtractorId, IPriorExtractorRun>>`.
3244
+ * Inner value carries `bodyHash` AND `sidecarAnnotationsHash`; both
3245
+ * participate in the cache hit condition for every Extractor.
3174
3246
  */
3175
- loadExtractorRuns(): Promise<Map<string, Map<string, string>>>;
3247
+ loadExtractorRuns(): Promise<Map<string, Map<string, IPriorExtractorRun>>>;
3176
3248
  /** Universal enrichment layer — every persisted `(node, extractor)` pair. */
3177
3249
  loadNodeEnrichments(): Promise<IPersistedEnrichment[]>;
3178
3250
  /**
@@ -3190,9 +3262,10 @@ interface StoragePort {
3190
3262
  };
3191
3263
  /**
3192
3264
  * Phase 3 / View contribution system — read access to
3193
- * `scan_contributions`. Writes happen exclusively via
3194
- * `scans.persist({ contributions })` to keep the replace-all
3195
- * semantics intact; this namespace is read-only.
3265
+ * `scan_contributions`, plus the targeted purge used by
3266
+ * `sm plugins disable` to clear stale rows immediately at toggle time.
3267
+ * Bulk writes still happen exclusively via
3268
+ * `scans.persist({ contributions })` (replace-all semantics).
3196
3269
  */
3197
3270
  contributions: {
3198
3271
  /** Every contribution row for a single node. Stable order. */
@@ -3208,6 +3281,13 @@ interface StoragePort {
3208
3281
  * `GET /api/contributions/:pluginId/:contributionId?path=...`.
3209
3282
  */
3210
3283
  lookup(pluginId: string, contributionId: string, nodePath: string, extensionId?: string): Promise<IPersistedContribution[]>;
3284
+ /**
3285
+ * Drop rows for a plugin (optionally narrowed to a single
3286
+ * extension within the bundle). Returns the number of deleted
3287
+ * rows. Called by `sm plugins disable` so the UI stops rendering
3288
+ * the disabled plugin's chips before the next scan.
3289
+ */
3290
+ purgeByPlugin(pluginId: string, extensionId?: string): Promise<number>;
3211
3291
  };
3212
3292
  /**
3213
3293
  * Read-only access to `scan_node_tags`. Writes happen exclusively