@skill-map/spec 0.38.0 → 0.40.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/CHANGELOG.md +48 -2302
- package/README.md +2 -2
- package/architecture.md +11 -14
- package/cli-contract.md +5 -1
- package/conformance/README.md +1 -1
- package/conformance/cases/extractor-emits-signal.json +1 -1
- package/conformance/cases/kernel-empty-boot.json +1 -1
- package/conformance/cases/no-global-scope.json +1 -1
- package/conformance/cases/orphan-markdown-fallback.json +1 -1
- package/conformance/cases/plugin-missing-ui-rejected.json +1 -1
- package/conformance/cases/sidecar-end-to-end.json +1 -1
- package/conformance/cases/signal-collision-detection.json +1 -1
- package/conformance/fixtures/plugin-missing-ui/.skill-map/plugins/bad-provider/providers/bad-provider/index.js +4 -0
- package/conformance/fixtures/sidecar-example/agent-example.sm +3 -3
- package/db-schema.md +19 -5
- package/index.json +55 -55
- package/package.json +2 -2
- package/schemas/annotations.schema.json +2 -2
- package/schemas/api/rest-envelope.schema.json +57 -12
- package/schemas/bump-report.schema.json +1 -1
- package/schemas/conformance-case.schema.json +1 -1
- package/schemas/conformance-result.schema.json +1 -1
- package/schemas/execution-record.schema.json +1 -1
- package/schemas/extensions/action.schema.json +1 -1
- package/schemas/extensions/analyzer.schema.json +1 -1
- package/schemas/extensions/base.schema.json +1 -1
- package/schemas/extensions/extractor.schema.json +1 -1
- package/schemas/extensions/formatter.schema.json +1 -1
- package/schemas/extensions/hook.schema.json +1 -1
- package/schemas/extensions/provider-kind.schema.json +1 -1
- package/schemas/extensions/provider.schema.json +80 -2
- package/schemas/frontmatter/base.schema.json +2 -7
- package/schemas/history-stats.schema.json +1 -1
- package/schemas/input-types.schema.json +1 -1
- package/schemas/issue.schema.json +1 -1
- package/schemas/job.schema.json +1 -1
- package/schemas/link.schema.json +1 -1
- package/schemas/node.schema.json +1 -1
- package/schemas/plugins-doctor.schema.json +1 -1
- package/schemas/plugins-registry.schema.json +1 -1
- package/schemas/project-config.schema.json +1 -1
- package/schemas/refresh-report.schema.json +1 -1
- package/schemas/report-base-deterministic.schema.json +1 -1
- package/schemas/report-base.schema.json +1 -1
- package/schemas/scan-result.schema.json +1 -1
- package/schemas/sidecar.schema.json +1 -1
- package/schemas/signal.schema.json +1 -1
- package/schemas/summaries/agent.schema.json +1 -1
- package/schemas/summaries/command.schema.json +1 -1
- package/schemas/summaries/hook.schema.json +1 -1
- package/schemas/summaries/markdown.schema.json +1 -1
- package/schemas/summaries/skill.schema.json +1 -1
- package/schemas/user-settings.schema.json +1 -1
- package/schemas/view-slots.schema.json +1 -1
- package/versioning.md +2 -2
package/README.md
CHANGED
|
@@ -140,7 +140,7 @@ import nodeSchema from '@skill-map/spec/schemas/node.schema.json' with { type: '
|
|
|
140
140
|
console.log(specIndex.specPackageVersion); // → "0.2.0" (npm package version; source of truth for `spec` in `sm version`)
|
|
141
141
|
console.log(specIndex.indexPayloadVersion); // → "0.0.1" (payload shape of `index.json` itself; bumps only when this manifest's structure changes)
|
|
142
142
|
console.log(specIndex.integrity.algorithm); // → "sha256"
|
|
143
|
-
console.log(nodeSchema.$id); // → "https://skill-map.
|
|
143
|
+
console.log(nodeSchema.$id); // → "https://skill-map.ai/spec/v0/node.schema.json"
|
|
144
144
|
```
|
|
145
145
|
|
|
146
146
|
Every JSON Schema is exported individually via `@skill-map/spec/schemas/*.json`. Prose documents ship in the tarball for reference but are not `exports`-surfaced.
|
|
@@ -161,7 +161,7 @@ console.log(actual === index.integrity.files[file] ? 'ok' : 'drift');
|
|
|
161
161
|
|
|
162
162
|
### JSON Schema Store
|
|
163
163
|
|
|
164
|
-
The schemas will be registered on JSON Schema Store once the canonical URLs under `skill-map.
|
|
164
|
+
The schemas will be registered on JSON Schema Store once the canonical URLs under `skill-map.ai/spec/v0/` are stable (Step 14).
|
|
165
165
|
|
|
166
166
|
## License
|
|
167
167
|
|
package/architecture.md
CHANGED
|
@@ -43,7 +43,7 @@ Any conforming implementation, reference or third-party, MUST respect these boun
|
|
|
43
43
|
|
|
44
44
|
A skill-map project sees its filesystem through exactly one **active provider lens** at any time. The lens is the provider whose extractors, classifiers, and resolution rules apply to the whole project during a scan. All other enabled providers stay registered but their provider-specific extractors are skipped.
|
|
45
45
|
|
|
46
|
-
The lens is project-scope state. It lives in `.skill-map/settings.json` as the `activeProvider` key (see [`project-config.schema.json`](./schemas/project-config.schema.json#/properties/activeProvider)). When absent, the kernel auto-detects on first scan from filesystem
|
|
46
|
+
The lens is project-scope state. It lives in `.skill-map/settings.json` as the `activeProvider` key (see [`project-config.schema.json`](./schemas/project-config.schema.json#/properties/activeProvider)). When absent, the kernel auto-detects on first scan from filesystem markers and persists the result; if the heuristic is ambiguous or yields no result, the CLI and UI prompt the user to pick one of the enabled providers. **The marker set is provider-owned**: each Provider declares its own detection markers in its manifest `detect.markers` block (see [`provider.schema.json`](./schemas/extensions/provider.schema.json#/properties/detect)), e.g. `claude` → `.claude/`, `openai` → `.codex/` or root `AGENTS.md`, `agent-skills` → `.agents/`. There is no central hardcoded detection table; the detectable set derives from the registered Providers, so adding a Provider with a marker makes it auto-detectable without touching the resolver. When several markers match, the resolver returns the full candidate list in Provider iteration order and the first match is the default suggestion. A Provider with no `detect` block is never auto-suggested but can still be selected manually, Google's Antigravity CLI (which replaced the retired Gemini CLI on 2026-05-19) adopted the open-standard `.agents/` rather than a vendor-specific marker, so a Google project auto-detects as the universal `agent-skills` lens and the `antigravity` lens is set manually via `sm config set activeProvider antigravity`.
|
|
47
47
|
|
|
48
48
|
### Consequence: one graph per project at a time
|
|
49
49
|
|
|
@@ -271,7 +271,9 @@ Each `kinds[*].ui` entry declares how the UI renders nodes of that kind:
|
|
|
271
271
|
|
|
272
272
|
The `ui` block is required (not optional) by design: making it optional would force the UI to invent visuals for missing entries, silently collapsing unknown kinds to a default rendering and hiding manifest gaps. Forcing the Provider to declare presentation up-front means the UI never guesses.
|
|
273
273
|
|
|
274
|
-
The kernel ships every Provider's `ui` block to the BFF at boot; the BFF aggregates them into a `kindRegistry` map and embeds it in every payload-bearing REST envelope (see [`cli-contract.md` §Server](./cli-contract.md#server)). The UI consumes `kindRegistry` directly, built-in and user-plugin kinds render identically.
|
|
274
|
+
The kernel ships every Provider's per-kind `ui` block to the BFF at boot; the BFF aggregates them into a `kindRegistry` map and embeds it in every payload-bearing REST envelope (see [`cli-contract.md` §Server](./cli-contract.md#server)). The UI consumes `kindRegistry` directly, built-in and user-plugin kinds render identically.
|
|
275
|
+
|
|
276
|
+
Each Provider ALSO declares a top-level `presentation` block (`provider.schema.json#/properties/presentation`: `label`, `color`, optional `colorDark` / `icon` / `emoji` / `hideChip`) describing the Provider's own identity, distinct from its kinds' visuals. (It is named `presentation`, not `ui`, because the shared extension `ui` key is the view-contributions map declared only by extractor / analyzer kinds.) The BFF aggregates these into a sibling `providerRegistry` map (keyed by Provider id) embedded on the same envelopes. The UI consumes `providerRegistry` to render the active-lens dropdown, the topbar lens chip, and the per-node provider chip on cards from the real registered-Provider set, never a hardcoded list. `hideChip: true` (set by the universal `markdown` fallback) suppresses only the per-card chip; the Provider still appears in the lens surfaces. Unlike kind colors (normalised across Providers so every `agent` paints the same), Provider colors are deliberately distinct so the chip tells the user at a glance which platform a node came from.
|
|
275
277
|
|
|
276
278
|
### Provider · dispatch order and the universal markdown fallback
|
|
277
279
|
|
|
@@ -652,22 +654,17 @@ Two columns on `scan_nodes` source from the sidecar's `annotations:` block when
|
|
|
652
654
|
|
|
653
655
|
A `scan_nodes.annotations_json` column carries the full parsed `annotations:` block; `sidecar_present` and `sidecar_status` carry the drift-detection state. The full sidecar overlay (parsed `annotations`, `status`, `present`) is exposed on `Node.sidecar` so REST and UI consumers see it as part of the canonical wire shape.
|
|
654
656
|
|
|
655
|
-
### Tags
|
|
656
|
-
|
|
657
|
-
Skill-map's tag system is **dual-source** by design:
|
|
657
|
+
### Tags
|
|
658
658
|
|
|
659
|
-
|
|
660
|
-
- **User tags** live in `sidecar.annotations.tags` (in the `.sm`). Curated annotation field declared on [`schemas/annotations.schema.json`](./schemas/annotations.schema.json). These represent the post-hoc tags whoever curates the project assigned to the node from their sidecar.
|
|
659
|
+
Tags are a **skill-map concept**, not a vendor field: no agent format (Claude, Cursor, Obsidian, the Agent Skills open standard, …) carries `tags` in its frontmatter, so skill-map keeps them where it owns the surface, the `.sm` sidecar.
|
|
661
660
|
|
|
662
|
-
|
|
661
|
+
- **Tags** live in `sidecar.annotations.tags` (in the `.sm`). Curated annotation field declared on [`schemas/annotations.schema.json`](./schemas/annotations.schema.json). These are the tags whoever curates the project assigned to the node from their sidecar.
|
|
663
662
|
|
|
664
|
-
|
|
665
|
-
- The optional `--tag-source author|user` flag filters one source.
|
|
666
|
-
- The UI distinguishes them visually so the attribution stays explicit (different chip style; author chips render first, user chips after).
|
|
663
|
+
Search and listings (`sm list --tag <name>`, UI faceted search) match this field: a hit returns the node. The UI renders them as chips on the node card and in the inspector.
|
|
667
664
|
|
|
668
|
-
Persistence layer projects rows into a normalized [`scan_node_tags`](./db-schema.md#scan_node_tags) table at write time, one row per `(node_path, tag
|
|
665
|
+
Persistence layer projects rows into a normalized [`scan_node_tags`](./db-schema.md#scan_node_tags) table at write time, one row per `(node_path, tag)` pair, so SQL queries can index on `(tag)` for `O(log n)` lookup. Replace-all per scan keeps the table in sync with the live sidecar state; deleting a tag from a sidecar removes its row on the next scan.
|
|
669
666
|
|
|
670
|
-
The wire shape (`/api/nodes` and `/api/nodes/:pathB64`) projects `node.tags =
|
|
667
|
+
The wire shape (`/api/nodes` and `/api/nodes/:pathB64`) projects `node.tags = string[]`. The kernel `Node` interface (TypeScript) does NOT carry `tags`, consumers that walk the canonical source read `node.sidecar.annotations.tags` directly (consistent with the post-decision-#2 posture of "no Node-level denormalisations").
|
|
671
668
|
|
|
672
669
|
### Stability
|
|
673
670
|
|
|
@@ -806,7 +803,7 @@ Endpoints under `/api/contributions/*`:
|
|
|
806
803
|
|
|
807
804
|
Plus catalog embedding into every payload-bearing envelope:
|
|
808
805
|
|
|
809
|
-
- `kindRegistry` and `contributionsRegistry` are siblings on the envelope (see schema). Built once per server boot, embedded into list (`nodes` / `links` / `issues` / `plugins`), single (`node`), and value (`config`) envelopes. Sentinel envelopes (`health` / `scan` / `graph`) and action-result envelopes (`sidecar.bumped`) and the catalog envelopes themselves (`annotations.registered` / `contributions.registered`) carry
|
|
806
|
+
- `kindRegistry`, `providerRegistry`, and `contributionsRegistry` are siblings on the envelope (see schema). Built once per server boot, embedded into list (`nodes` / `links` / `issues` / `plugins`), single (`node`), and value (`config`) envelopes. Sentinel envelopes (`health` / `scan` / `graph`) and action-result envelopes (`sidecar.bumped`) and the catalog envelopes themselves (`annotations.registered` / `contributions.registered`) carry none of them. `providerRegistry` is the static boot catalog of registered Providers' identity; the dynamic active lens (current value + filesystem-detected candidates) is served separately by `GET /api/active-provider`.
|
|
810
807
|
|
|
811
808
|
Plus per-node embedding on node responses:
|
|
812
809
|
|
package/cli-contract.md
CHANGED
|
@@ -82,7 +82,7 @@ The project sees its filesystem through exactly one **active provider lens** at
|
|
|
82
82
|
|
|
83
83
|
CLI surfaces:
|
|
84
84
|
|
|
85
|
-
- **Auto-detect on first scan**: when `activeProvider` is absent, `sm scan` and `sm watch` run a filesystem heuristic (`.claude/` → `claude`, `.codex/` or root `AGENTS.md` → `openai`, `.
|
|
85
|
+
- **Auto-detect on first scan**: when `activeProvider` is absent, `sm scan` and `sm watch` run a filesystem heuristic driven by each Provider's manifest `detect.markers` (e.g. `.claude/` → `claude`, `.codex/` or root `AGENTS.md` → `openai`, `.agents/` → `agent-skills`). The marker set is provider-owned, not a central hardcoded table, so the detectable set derives from the registered Providers. On unambiguous match, the result is persisted to `settings.json` and the scan proceeds; on no match, the CLI exits non-zero with a "no provider detected, set `activeProvider` in settings or install a provider plugin" message. On ambiguous match (multiple providers detected), the CLI prompts the user interactively (or fails with exit code 2 under `--yes` if no default is configured). Google's Antigravity CLI does not declare a vendor-specific marker (it adopted the open-standard `.agents/` layout, which auto-detects as the universal `agent-skills` lens); the `antigravity` lens is set manually via `sm config set activeProvider antigravity`.
|
|
86
86
|
- **Manual override**: `sm config set activeProvider <id>` switches the lens. The verb drops the `scan_*` zone atomically (see [`db-schema.md`](./db-schema.md#zones)) and triggers an immediate rescan under the new lens. `state_*` and `config_*` zones survive.
|
|
87
87
|
- **No per-scan flag**: there is no `sm scan --provider=<id>` flag. The lens is a project-level decision, not a per-invocation parameter. The drop+rescan cost makes per-invocation switching the wrong default UX.
|
|
88
88
|
|
|
@@ -285,6 +285,8 @@ The watcher subscribes to the same roots that `sm scan` walks and respects `.ski
|
|
|
285
285
|
|
|
286
286
|
**Node cap** (`--max-nodes <N>`): on `sm scan` and `sm watch` (alias `sm scan --watch`), a hard cap on the number of files the walker accepts after `.skillmapignore` filtering, before extractors run. Default comes from `scan.maxNodes` (default 256). The flag is a full override of the setting and is **bidirectional**: it can raise the cap (`--max-nodes 1000` on a 312-file repo) or lower it (`--max-nodes 100` cuts deeper than the default). When the walker reaches the cap, additional files are dropped in stable provider-walker order and the scan is marked oversized in `scan_meta` (columns `recommended_node_limit` and `override_max_nodes`), the resulting `ScanResult` envelope carries `recommendedNodeLimit` and `overrideMaxNodes` so the UI raises a persistent banner pointing at the `.skillmapignore` editor in Settings → Project. The CLI prints a human-mode notice naming both escapes: edit `.skillmapignore` (preferred, trims permanently) or re-run with `--max-nodes <N>` (force, graph quality may degrade past the recommended limit). `sm refresh` operates on a single already-classified node, so the cap does not apply there. Validation: integer ≥ 1, anything else exits `2` operational.
|
|
287
287
|
|
|
288
|
+
**Schema-drift rebuild (pre-1.0)**: before persisting, `sm scan` and `sm watch` compare `scan_meta.scanned_by_version` against the running CLI. A minor or major difference means the local cache predates a schema change, so the DB is deleted and rebuilt from scratch by this run (`.sm` sidecars are untouched, they are the source of truth). On an interactive terminal the rebuild is confirmed first; `--yes` (and every non-interactive caller: piped stdin, CI, the BFF, the watcher) rebuilds without prompting. Declining aborts the scan (exit `2`) without deleting anything. Patch-level differences are compatible and never trigger a rebuild. Read-only verbs keep the version-skew advisory instead of rebuilding. See [`db-schema.md` §Schema drift (pre-1.0)](./db-schema.md#schema-drift-pre-10).
|
|
289
|
+
|
|
288
290
|
Exit: 0 on clean (or clean watcher shutdown), 1 if error-severity issues exist (one-shot scan only, the watcher does not flip exit code based on per-batch issues), 2 on operational error.
|
|
289
291
|
|
|
290
292
|
---
|
|
@@ -581,6 +583,8 @@ List endpoints conform to [`schemas/api/rest-envelope.schema.json`](schemas/api/
|
|
|
581
583
|
|
|
582
584
|
**`kindRegistry` envelope field.** Every payload-bearing variant of the REST envelope (`nodes` / `links` / `issues` / `plugins` lists, the `node` single, the `config` value envelope) embeds a required `kindRegistry: { [kindName]: { providerId, label, color, colorDark?, emoji?, icon? } }` field. Sentinel envelopes (`health`, `scan`, `graph`) are exempt, they carry no payload at the wire level. The BFF assembles the registry once at boot from EVERY built-in Provider's `kinds[*].ui` block (regardless of the boot-time enabled verdict, their module code is statically imported by `built-in-bundles.ts` and always in memory) PLUS every drop-in user Provider that loaded successfully at boot (see [`architecture.md` §Provider · `ui` presentation](architecture.md#provider--ui-presentation)). The registry is then attached to every applicable response. Built-ins are listed unconditionally because a user re-enabling one mid-session expects its kinds to render on the next scan; the runtime enabled/disabled axis is enforced at SCAN-TIME by `composeScanExtensions` reading the fresh resolver, not by hiding kinds from the registry. Drop-ins that loaded as `disabled` carry `startsAsDisabled: true` on `GET /api/plugins` and need `sm serve` restart to register, their module code was never imported. The UI consumes `kindRegistry` directly to render kind palettes, list rows, and inspector headers, built-in and user-plugin kinds render identically. A kind appearing in a response payload (e.g. `node.kind`) without a matching `kindRegistry` entry is a contract violation; the kernel rejects Providers without a `ui` block at load time so the registry is always complete for whatever kinds appear in the response.
|
|
583
585
|
|
|
586
|
+
**`providerRegistry` envelope field.** The same payload-bearing envelopes also embed a required `providerRegistry: { [providerId]: { label, color, colorDark?, emoji?, icon?, hideChip? } }` field (sibling of `kindRegistry`). Sentinel envelopes (`health`, `scan`, `graph`), action-result envelopes (`sidecar.bumped`), and the catalog envelopes (`annotations.registered`, `contributions.registered`) are exempt. Same boot-time assembly discipline as `kindRegistry`: assembled once from EVERY built-in Provider's top-level `presentation` block (regardless of enabled verdict) PLUS every drop-in user Provider that loaded at boot. The UI consumes `providerRegistry` to render the active-lens dropdown, the topbar lens chip, and the per-node provider chip from the real registered-Provider set, never a hardcoded list; `hideChip: true` (the universal `markdown` fallback) suppresses only the per-card chip. This is the static boot catalog of Provider identity; the dynamic active lens (current value + filesystem-detected candidates) is served separately by `GET /api/active-provider`.
|
|
587
|
+
|
|
584
588
|
**`contributionsRegistry` envelope field.** Same payload-bearing envelopes also embed `contributionsRegistry: { "<pluginId>/<extensionId>/<contributionId>": { pluginId, extensionId, contributionId, slot, label?, tooltip?, icon?, emptyText?, emitWhenEmpty } }`. Same boot-time assembly discipline as `kindRegistry`: ALL built-in declarations are listed regardless of enabled state (so re-enabling a built-in mid-session renders correctly on the next scan), plus drop-in user plugins that loaded at boot. The `slot` value comes from the closed catalog in `spec/schemas/view-slots.schema.json`. A view contribution emitted by an extension whose qualified id is missing from the registry is dropped by the UI's slot host (mirrors the kindRegistry contract, `startsAsDisabled` drop-ins illustrate the absence path).
|
|
585
589
|
|
|
586
590
|
**Error envelope** (mirrors `§Machine-readable output analyzers`):
|
package/conformance/README.md
CHANGED
|
@@ -51,7 +51,7 @@ Fixtures are read-only inputs. Cases declare what to invoke and what to assert.
|
|
|
51
51
|
|
|
52
52
|
## Case format
|
|
53
53
|
|
|
54
|
-
Cases are validated against [`conformance-case.schema.json`](../schemas/conformance-case.schema.json). That file is the normative shape; this section is the human-readable walkthrough. Include `"$schema": "https://skill-map.
|
|
54
|
+
Cases are validated against [`conformance-case.schema.json`](../schemas/conformance-case.schema.json). That file is the normative shape; this section is the human-readable walkthrough. Include `"$schema": "https://skill-map.ai/spec/v0/conformance-case.schema.json"` in every case file for IDE support.
|
|
55
55
|
|
|
56
56
|
A case is a JSON document with this shape:
|
|
57
57
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "https://skill-map.
|
|
2
|
+
"$schema": "https://skill-map.ai/spec/v0/conformance-case.schema.json",
|
|
3
3
|
"id": "extractor-emits-signal",
|
|
4
4
|
"description": "Signal IR resolver phase, end-to-end. A body that contains a single `[text](path)` markdown link MUST flow through the Signal IR resolver (Phase 2 of the active-lens migration): `core/markdown-link` emits a single-candidate Signal, the resolver materialises the winning candidate as a Link, and the result lands in `scan.links` with the same shape a direct `emitLink` call would have produced. Locks the contract that the Signal IR path coexists with the direct-emit path and produces indistinguishable Link rows.",
|
|
5
5
|
"fixture": "signal-ir-single-signal",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "https://skill-map.
|
|
2
|
+
"$schema": "https://skill-map.ai/spec/v0/conformance-case.schema.json",
|
|
3
3
|
"id": "kernel-empty-boot",
|
|
4
4
|
"description": "With every Provider, extractor, and analyzer disabled, scanning an empty scope MUST return a valid, zero-filled ScanResult. Enforces the kernel boot invariant from architecture.md.",
|
|
5
5
|
"setup": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "https://skill-map.
|
|
2
|
+
"$schema": "https://skill-map.ai/spec/v0/conformance-case.schema.json",
|
|
3
3
|
"id": "no-global-scope",
|
|
4
4
|
"description": "Skill-map operates exclusively on the project scope. Implementations MUST NOT expose a `-g/--global` flag (the historical opt-in for a global / user scope) on any verb. Passing the flag to any verb MUST be rejected as an unknown option (exit `2`, usage error) without writing any state. Guards the principle declared in `cli-contract.md` §Scope is always project-local.",
|
|
5
5
|
"invoke": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "https://skill-map.
|
|
2
|
+
"$schema": "https://skill-map.ai/spec/v0/conformance-case.schema.json",
|
|
3
3
|
"id": "orphan-markdown-fallback",
|
|
4
4
|
"description": "spec 0.18.0 universal markdown fallback. A `.md` file no vendor-specific Provider classifies (e.g. `ARCHITECTURE.md` at the project root) MUST be picked up by the built-in `core/markdown` Provider, classified as kind `markdown`, and attributed to the `markdown` provider id. The orchestrator's path-dedup ensures vendor Providers retain priority on files inside their territory (`.claude/agents/reviewer.md` here stays with `claude` as `agent`). Locks the contract that markdown is provider-agnostic and the kernel emits no privileged kinds.",
|
|
5
5
|
"fixture": "orphan-markdown",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "https://skill-map.
|
|
2
|
+
"$schema": "https://skill-map.ai/spec/v0/conformance-case.schema.json",
|
|
3
3
|
"id": "plugin-missing-ui-rejected",
|
|
4
4
|
"description": "A drop-in Provider plugin whose `kinds[*]` entry omits the required `ui` block (Step 14.5.d) MUST be rejected by the loader with a clear `missing required property 'ui'` diagnostic on stderr, AND `sm scan` MUST exit cleanly with the rest of the pipeline (built-in Claude Provider) still running. Locks the contract that one bad plugin does not take down the scan.",
|
|
5
5
|
"fixture": "plugin-missing-ui",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "https://skill-map.
|
|
2
|
+
"$schema": "https://skill-map.ai/spec/v0/conformance-case.schema.json",
|
|
3
3
|
"id": "sidecar-end-to-end",
|
|
4
4
|
"description": "Step 9.6.6 — co-located `.sm` sidecar end-to-end. Scanning a fixture that carries a stale sidecar (wrong `identity.{bodyHash,frontmatterHash}`) plus an orphan sidecar (no sibling `.md`) MUST surface `sidecar.status` on the node and emit both `annotation-stale` (per stale node) and `annotation-orphan` (per orphan `.sm`) issues from the built-in core analyzers.",
|
|
5
5
|
"fixture": "sidecar-end-to-end",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "https://skill-map.
|
|
2
|
+
"$schema": "https://skill-map.ai/spec/v0/conformance-case.schema.json",
|
|
3
3
|
"id": "signal-collision-detection",
|
|
4
4
|
"description": "Signal IR resolver phase, range-overlap collision. A body that contains `[@./api.md](./api.md)` triggers a cross-extractor range overlap: `core/markdown-link` matches the whole bracketed-and-parenthesised span; `claude/at-directive` matches the `@./api.md` token INSIDE the bracket text. The two byte ranges overlap (the at-directive range is a strict subset of the markdown-link range). The kernel resolver picks ONE winner per the four-step tiebreak (`kind-priority` -> `higher-confidence` -> `longer-range` -> `earlier-declaration`); markdown-link wins on confidence (1.0 vs 0.85). The resolver materialises the winner as a Link, marks the loser's `resolution.outcome === 'rejected'` with `rejectedBy` naming the winner, and the built-in `core/signal-collision` analyzer surfaces the rejection as ONE `warn` issue attached to the source node. Locks the contract that range-overlap collisions surface to the operator instead of being silently merged.",
|
|
5
5
|
"fixture": "signal-ir-collision",
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
export default {
|
|
11
11
|
version: '0.1.0',
|
|
12
12
|
description: 'provider whose markdown kind is missing the ui block',
|
|
13
|
+
// Provider-level `presentation` is present and valid, so the loader
|
|
14
|
+
// gets past manifest validation and fails specifically on the KIND's
|
|
15
|
+
// missing `ui` block (the focus of this case).
|
|
16
|
+
presentation: { label: 'Bad', color: '#000000' },
|
|
13
17
|
async *walk() {},
|
|
14
18
|
classify() {
|
|
15
19
|
return 'markdown';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Sample sidecar matching agent-example.md.
|
|
2
2
|
# Validates against:
|
|
3
|
-
# - https://skill-map.
|
|
4
|
-
# - https://skill-map.
|
|
3
|
+
# - https://skill-map.ai/spec/v0/sidecar.schema.json (root shape)
|
|
4
|
+
# - https://skill-map.ai/spec/v0/annotations.schema.json (annotations block)
|
|
5
5
|
# Hashes are sha256 over the kernel's canonical forms (body bytes; canonical YAML
|
|
6
6
|
# of the frontmatter via `js-yaml` dump with sortKeys+noCompatMode). Regenerate
|
|
7
7
|
# when agent-example.md changes (the fixture is meant to be drift-free).
|
|
@@ -31,7 +31,7 @@ annotations:
|
|
|
31
31
|
- typescript
|
|
32
32
|
- quality
|
|
33
33
|
hidden: false
|
|
34
|
-
docsUrl: https://skill-map.
|
|
34
|
+
docsUrl: https://skill-map.ai/examples/code-reviewer
|
|
35
35
|
|
|
36
36
|
settings: {}
|
|
37
37
|
|
package/db-schema.md
CHANGED
|
@@ -246,19 +246,18 @@ NOT analogous to `state_plugin_kvs` (which is plugin-managed). Belongs to the `s
|
|
|
246
246
|
|
|
247
247
|
### `scan_node_tags`
|
|
248
248
|
|
|
249
|
-
Tags
|
|
249
|
+
Tags. One row per `(node_path, tag)` pair, projected at persist time from `sidecar.annotations.tags`. Tags are a skill-map concept (no vendor carries `tags` in frontmatter), so the sidecar is the single source. Drives `sm list --tag <name>` and the UI's tag-faceted search; the `(tag)` index keeps "find all nodes with tag X" `O(log n)`.
|
|
250
250
|
|
|
251
251
|
| Column | Type | Constraint |
|
|
252
252
|
|---|---|---|
|
|
253
253
|
| `node_path` | TEXT | NOT NULL | FK semantically to `scan_nodes.path`; orphan-swept on persist when the parent node disappears. |
|
|
254
254
|
| `tag` | TEXT | NOT NULL | Free-form; case-preserving. Empty strings rejected upstream by the schema's `minLength: 1` on each item. |
|
|
255
|
-
| `source` | TEXT | NOT NULL CHECK (source IN ('author','user')) | Hard split: `'author'` = `frontmatter.tags`, `'user'` = `sidecar.annotations.tags`. The same tag string MAY appear under both sources for the same node (the PK accepts the pair); `sm list --tag X` returns the node once via DISTINCT, the UI renders both chips with their attribution. |
|
|
256
255
|
|
|
257
|
-
Primary key: `(node_path, tag
|
|
256
|
+
Primary key: `(node_path, tag)`. Indexes: `ix_scan_node_tags_tag` (search by tag), `ix_scan_node_tags_node_path` (per-node lookup, e.g. inspector projection).
|
|
258
257
|
|
|
259
|
-
**Persistence, replace-all per scan.** Every persisted scan rebuilds the table for the live node set: rows whose `node_path` is NOT in `livePaths` are dropped (orphan sweep, same as the contributions table); rows for nodes in the live set are wiped and re-inserted from the projected
|
|
258
|
+
**Persistence, replace-all per scan.** Every persisted scan rebuilds the table for the live node set: rows whose `node_path` is NOT in `livePaths` are dropped (orphan sweep, same as the contributions table); rows for nodes in the live set are wiped and re-inserted from the projected sidecar state. Cached nodes' tag rows are projected from the cached `node.sidecar.annotations.tags` (already in memory), so the rebuild is cheap regardless of cache hit / miss. Storage is small, a 50-node project with avg 3 tags/node is ~150 rows ≈ 7.5 KB.
|
|
260
259
|
|
|
261
|
-
The wire shape on `/api/nodes` joins this table to project `node.tags =
|
|
260
|
+
The wire shape on `/api/nodes` joins this table to project `node.tags = string[]`. The kernel `Node` interface (TypeScript) does NOT carry `tags`, consumers walking the canonical source read `node.sidecar.annotations.tags` directly (consistent with the post-decision-#2 posture).
|
|
262
261
|
|
|
263
262
|
---
|
|
264
263
|
|
|
@@ -464,6 +463,21 @@ The kernel ALSO maintains `PRAGMA user_version` (or the engine equivalent) as a
|
|
|
464
463
|
|
|
465
464
|
---
|
|
466
465
|
|
|
466
|
+
## Schema drift (pre-1.0)
|
|
467
|
+
|
|
468
|
+
The project DB is a derived cache: every `scan_*` row is regenerable, and the operator's authored data lives in `.sm` sidecars, not in the DB. While the kernel stays in `0.Y.Z` (see [`versioning.md` §Pre-1.0](./versioning.md#pre-10)) it does NOT ship incremental migrations to carry an existing DB across a schema change. Instead, a write-side open (`sm scan`, `sm watch`, and the BFF watcher) compares `scan_meta.scanned_by_version` against the running CLI version:
|
|
469
|
+
|
|
470
|
+
- **Same `major.minor`** (patch differences ignored): the cache is compatible. The open proceeds untouched.
|
|
471
|
+
- **Any minor or major difference**: the on-disk schema is treated as drifted. The entire DB file (plus its `-wal` / `-shm` sidecars) is deleted and recreated from the current `001_initial.sql`; the scan then repopulates it. No backup is written (the cache is derived). `state_*` and `config_*` are wiped along with `scan_*`; pre-1.0 they are accepted as transient. `.sm` sidecars are never touched.
|
|
472
|
+
|
|
473
|
+
The rebuild is confirmed interactively on a TTY `sm scan` unless `--yes` is passed; non-interactive callers (piped stdin, CI, the BFF scan route, the watcher) rebuild without prompting. Declining the prompt aborts the scan (exit `2`) without deleting anything.
|
|
474
|
+
|
|
475
|
+
Read-side verbs (`sm check`, `sm list`, `sm show`, ...) do NOT rebuild. They keep the version-skew advisory (warn on an older DB, refuse on a newer or different-major DB) so a read never silently discards the cache.
|
|
476
|
+
|
|
477
|
+
This is a pre-1.0 affordance. The first `1.0.0` replaces it with real up-only migrations (see §Migrations): drift detection by version becomes drift repair by migration, and `state_*` / `config_*` stop being disposable.
|
|
478
|
+
|
|
479
|
+
---
|
|
480
|
+
|
|
467
481
|
## Plugin storage
|
|
468
482
|
|
|
469
483
|
Two modes declared in `plugin.json` (see [`schemas/plugins-registry.schema.json`](./schemas/plugins-registry.schema.json)).
|
package/index.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"indexPayloadVersion": "0.0.1",
|
|
3
3
|
"dialect": "https://json-schema.org/draft/2020-12/schema",
|
|
4
|
-
"canonicalUrlPrefix": "https://skill-map.
|
|
4
|
+
"canonicalUrlPrefix": "https://skill-map.ai/spec/v0",
|
|
5
5
|
"schemas": {
|
|
6
6
|
"topLevel": [
|
|
7
7
|
{
|
|
@@ -174,85 +174,85 @@
|
|
|
174
174
|
}
|
|
175
175
|
]
|
|
176
176
|
},
|
|
177
|
-
"specPackageVersion": "0.
|
|
177
|
+
"specPackageVersion": "0.40.0",
|
|
178
178
|
"integrity": {
|
|
179
179
|
"algorithm": "sha256",
|
|
180
180
|
"files": {
|
|
181
|
-
"CHANGELOG.md": "
|
|
182
|
-
"README.md": "
|
|
183
|
-
"architecture.md": "
|
|
184
|
-
"cli-contract.md": "
|
|
185
|
-
"conformance/README.md": "
|
|
186
|
-
"conformance/cases/extractor-emits-signal.json": "
|
|
187
|
-
"conformance/cases/kernel-empty-boot.json": "
|
|
188
|
-
"conformance/cases/no-global-scope.json": "
|
|
189
|
-
"conformance/cases/orphan-markdown-fallback.json": "
|
|
190
|
-
"conformance/cases/plugin-missing-ui-rejected.json": "
|
|
191
|
-
"conformance/cases/sidecar-end-to-end.json": "
|
|
192
|
-
"conformance/cases/signal-collision-detection.json": "
|
|
181
|
+
"CHANGELOG.md": "bf36e063acb6ee636f39cd461c461a4cb9c2cc20d4097f8d1fffc803d99277df",
|
|
182
|
+
"README.md": "936d8e20cd46dc535ab46f19812749df2ee9b81dda3062cda2995bdc292a7a7f",
|
|
183
|
+
"architecture.md": "870446e462a0c06162528bbd496a2095f6d7e6aec620427a76648337dd524003",
|
|
184
|
+
"cli-contract.md": "aacf84d3314df36f127696b36bc0bdd47111c5c09d57b51d8e3859ea263ec9da",
|
|
185
|
+
"conformance/README.md": "0c69bd9becf511ada9175b1e428ba183e31d1c8a49ff09eedf4c950bb831ec4d",
|
|
186
|
+
"conformance/cases/extractor-emits-signal.json": "0115c7bb62a7a705f72e9d8048b3f0396e5caaeb3d04dea204415e279e58479d",
|
|
187
|
+
"conformance/cases/kernel-empty-boot.json": "9b51b85ff62479cd0eee37cad260245208d94f6d79644f7ee40945a934960913",
|
|
188
|
+
"conformance/cases/no-global-scope.json": "1c83343422144be2ad9e3d27d2062e61af87c7c1c1f3b051b6b9f687d845ac7b",
|
|
189
|
+
"conformance/cases/orphan-markdown-fallback.json": "506119323ddde85c1fb4c986c7f6f40a345d44adb06de8d84002591df0e479ee",
|
|
190
|
+
"conformance/cases/plugin-missing-ui-rejected.json": "7c910b74e6f718ab5c1a590cd3544602f056559251d18995a26bca0a0648a2fa",
|
|
191
|
+
"conformance/cases/sidecar-end-to-end.json": "2de448c52a93139143e5290df2842d898b3984c91fbee315d7a26157efd9b123",
|
|
192
|
+
"conformance/cases/signal-collision-detection.json": "c5e39a406ded6928a14c1a22b84f7b3cd49805bec56bd65de83130d9e419c09e",
|
|
193
193
|
"conformance/coverage.md": "106468a6d9a65e5fdefbf75c8de4abecf35d5c08f2b6c44423741c60b723baea",
|
|
194
194
|
"conformance/fixtures/orphan-markdown/.claude/agents/reviewer.md": "7f062731106f2d9811e4fffcf6ab44b8dfff4cfb16536a469514cc0664e832bf",
|
|
195
195
|
"conformance/fixtures/orphan-markdown/ARCHITECTURE.md": "ec903666440bae65da3796b1158c92cfcdce22e0e09c3b20bb690176881a6ac4",
|
|
196
196
|
"conformance/fixtures/plugin-missing-ui/.skill-map/plugins/bad-provider/kinds/markdown/kind.json": "6676a89bae5197e23cf50f1c11d596db558ac80f7334a7208fe57d8b92422251",
|
|
197
197
|
"conformance/fixtures/plugin-missing-ui/.skill-map/plugins/bad-provider/kinds/markdown/schema.json": "42795e7f1759fa25115a426edf5cd1b0c91b091b408aeee3f4f9fbc8f89f32bc",
|
|
198
198
|
"conformance/fixtures/plugin-missing-ui/.skill-map/plugins/bad-provider/plugin.json": "15164a6bc9e3ad21cefa532af3d4edff1b10cf6140d7f576332dc38800512e35",
|
|
199
|
-
"conformance/fixtures/plugin-missing-ui/.skill-map/plugins/bad-provider/providers/bad-provider/index.js": "
|
|
199
|
+
"conformance/fixtures/plugin-missing-ui/.skill-map/plugins/bad-provider/providers/bad-provider/index.js": "df0d9f200e401b6b13115d6e97e5a00a78074229bd86c22ec5321accf5673c01",
|
|
200
200
|
"conformance/fixtures/plugin-missing-ui/notes/example.md": "55767f0aa1b6774546a99f28c58e7b732aa9cfa5dfce8d0326470f7f622f577e",
|
|
201
201
|
"conformance/fixtures/preamble-v1.txt": "1e0aeef224b64477bdc13a949c3ad402e68249caf499ecdba1302371677c068b",
|
|
202
202
|
"conformance/fixtures/sidecar-end-to-end/.claude/agents/orphan.sm": "3102ff10a0f08f60c014f82409d45ad4faf2cefa04d652a87676d3557ad64944",
|
|
203
203
|
"conformance/fixtures/sidecar-end-to-end/.claude/agents/stale.md": "cb3a95777cba530d47e6040c5601b6dcd34b5fc653dd69f183369eb6bdd956b5",
|
|
204
204
|
"conformance/fixtures/sidecar-end-to-end/.claude/agents/stale.sm": "cb04f7f3103b4218b09fd4da92f7ea429588b04c1dac6a9547ce362263b11224",
|
|
205
205
|
"conformance/fixtures/sidecar-example/agent-example.md": "741131403e8c9580d0b7a8c2446cb4502d01f80053b7a2092663de92431aaa82",
|
|
206
|
-
"conformance/fixtures/sidecar-example/agent-example.sm": "
|
|
206
|
+
"conformance/fixtures/sidecar-example/agent-example.sm": "fba04f4d81c6c3308316dca9bb5cdd72471052df577ed939c1c1915deeb5dd0f",
|
|
207
207
|
"conformance/fixtures/signal-ir-collision/.claude/agents/api.md": "7bdd260d82c2bf1ffc3324820e1b806684674981f9234f7c9f4f6aa61dd1cec5",
|
|
208
208
|
"conformance/fixtures/signal-ir-collision/.claude/agents/architect.md": "acc46b5b2dff73d98a354e4d53b5041164595deae466a4e2ce41d7c5a72f28fb",
|
|
209
209
|
"conformance/fixtures/signal-ir-single-signal/source.md": "1eda417b4c6eed372b66870e385c8d8cd631372b77cab7e996bb711e22218f89",
|
|
210
210
|
"conformance/fixtures/signal-ir-single-signal/target.md": "527137f2b4f46c0034b0edc8932cf8613d2bf22ffaaf78f01085c82a3baaebe3",
|
|
211
|
-
"db-schema.md": "
|
|
211
|
+
"db-schema.md": "f05c72ea74f8b32cc9909a02db1b8c93aefdf10ee804892449cab4d72a158ce9",
|
|
212
212
|
"interfaces/security-scanner.md": "e8049712b9cf7a07c786bf19f8f775f8ef9638f063f7fba5c7a8b1431b92f38e",
|
|
213
213
|
"job-events.md": "9d5b35d4c451a7f8eef9915d85316d924ac52f1c026a316cdda5f1099d496854",
|
|
214
214
|
"job-lifecycle.md": "9c429121f98a07c8795f8979ed1abc5e5334e3f89db51585a8da55c527ef855b",
|
|
215
215
|
"plugin-author-guide.md": "f0039397cd19d1f0a02c4e0691f213514216188d001cf56f287e69f6631fd39e",
|
|
216
216
|
"plugin-kv-api.md": "1acc69ed82433a74e35ada61d63a6d7379fb61046ff83de1e0facbe884c64704",
|
|
217
217
|
"prompt-preamble.md": "9dd4f6d1bc6a425f8782fcee10cbe75909e8d64e28781fda56c2fae909b02f40",
|
|
218
|
-
"schemas/annotations.schema.json": "
|
|
219
|
-
"schemas/api/rest-envelope.schema.json": "
|
|
220
|
-
"schemas/bump-report.schema.json": "
|
|
221
|
-
"schemas/conformance-case.schema.json": "
|
|
222
|
-
"schemas/conformance-result.schema.json": "
|
|
223
|
-
"schemas/execution-record.schema.json": "
|
|
224
|
-
"schemas/extensions/action.schema.json": "
|
|
225
|
-
"schemas/extensions/analyzer.schema.json": "
|
|
226
|
-
"schemas/extensions/base.schema.json": "
|
|
227
|
-
"schemas/extensions/extractor.schema.json": "
|
|
228
|
-
"schemas/extensions/formatter.schema.json": "
|
|
229
|
-
"schemas/extensions/hook.schema.json": "
|
|
230
|
-
"schemas/extensions/provider-kind.schema.json": "
|
|
231
|
-
"schemas/extensions/provider.schema.json": "
|
|
232
|
-
"schemas/frontmatter/base.schema.json": "
|
|
233
|
-
"schemas/history-stats.schema.json": "
|
|
234
|
-
"schemas/input-types.schema.json": "
|
|
235
|
-
"schemas/issue.schema.json": "
|
|
236
|
-
"schemas/job.schema.json": "
|
|
237
|
-
"schemas/link.schema.json": "
|
|
238
|
-
"schemas/node.schema.json": "
|
|
239
|
-
"schemas/plugins-doctor.schema.json": "
|
|
240
|
-
"schemas/plugins-registry.schema.json": "
|
|
241
|
-
"schemas/project-config.schema.json": "
|
|
242
|
-
"schemas/refresh-report.schema.json": "
|
|
243
|
-
"schemas/report-base-deterministic.schema.json": "
|
|
244
|
-
"schemas/report-base.schema.json": "
|
|
245
|
-
"schemas/scan-result.schema.json": "
|
|
246
|
-
"schemas/sidecar.schema.json": "
|
|
247
|
-
"schemas/signal.schema.json": "
|
|
248
|
-
"schemas/summaries/agent.schema.json": "
|
|
249
|
-
"schemas/summaries/command.schema.json": "
|
|
250
|
-
"schemas/summaries/hook.schema.json": "
|
|
251
|
-
"schemas/summaries/markdown.schema.json": "
|
|
252
|
-
"schemas/summaries/skill.schema.json": "
|
|
253
|
-
"schemas/user-settings.schema.json": "
|
|
254
|
-
"schemas/view-slots.schema.json": "
|
|
255
|
-
"versioning.md": "
|
|
218
|
+
"schemas/annotations.schema.json": "8c639b149cad675fdd4e7d6be2b47e920cfdd24087b41361d6e1b8280f646322",
|
|
219
|
+
"schemas/api/rest-envelope.schema.json": "19cd02c96faa12b59768cd9e2e74b8830a07fbcba104de797345b6a61c0f44c3",
|
|
220
|
+
"schemas/bump-report.schema.json": "c763e1f89f2665c479d6a4985c1d324c65e5278331ebab82220287a07e4c4429",
|
|
221
|
+
"schemas/conformance-case.schema.json": "958b316d646d0c64a715a7a28cee66d2c2d2498a60dbfc5ae8970687c2a96954",
|
|
222
|
+
"schemas/conformance-result.schema.json": "14f983a8f4e62cd4ff964688c9b2b026a3bee3a0b762b64091c8c34db5b75777",
|
|
223
|
+
"schemas/execution-record.schema.json": "db0eb16153493ad9f13ea0ecede44191e4a8536979adffd17ca278ddf8786c77",
|
|
224
|
+
"schemas/extensions/action.schema.json": "dc4f52d23c163c6239a487fa1c1ad9c09685cf38833d3962c604d5872716cff9",
|
|
225
|
+
"schemas/extensions/analyzer.schema.json": "8def4a5ca4934197c34abde97da70704b2751041a443c859eddd4b783e2fe1db",
|
|
226
|
+
"schemas/extensions/base.schema.json": "ee0f54acc769cc8e5295d703e69fd806f041b326a774dc8aaffab3380ed6906b",
|
|
227
|
+
"schemas/extensions/extractor.schema.json": "ee44bf562b19318c93116c574a811857cdef1f4119326a9a604fa408889dd230",
|
|
228
|
+
"schemas/extensions/formatter.schema.json": "880dc379ad545a62404403533a01eda5171edba0390561fc46ec6e986e0b9bd3",
|
|
229
|
+
"schemas/extensions/hook.schema.json": "f56aef59e9986ffdf7d86aa2e048dccccf217000a358b8c64737cbd911c48dad",
|
|
230
|
+
"schemas/extensions/provider-kind.schema.json": "499b2418bbe6d8a84a1608e26c56b52c2652a30ce314bc2989094418797dc1e6",
|
|
231
|
+
"schemas/extensions/provider.schema.json": "e536c3376ee5a04b6d4e971b6133a5af36e6f7e05973d88bb7236d4ab908830d",
|
|
232
|
+
"schemas/frontmatter/base.schema.json": "cff81510ed94824dfd12ab8b30ce9fbac65e42d61ae0edf3fbb6bbb6bb8bcb8c",
|
|
233
|
+
"schemas/history-stats.schema.json": "436aa0ffe744bdb699000447e86b45724fbd2cc4642781074eb1527522b9058c",
|
|
234
|
+
"schemas/input-types.schema.json": "cc9739aedcfdc72c1fa1285547e1392f9582169d578d72737918099acc721de0",
|
|
235
|
+
"schemas/issue.schema.json": "d173aa5c5312b3d2a2cd249f55c10943c8f3cd5799e4645ae3c66316221e12d1",
|
|
236
|
+
"schemas/job.schema.json": "dbcedf137de03fde38f74686f594e600c627bf808f2aad23511a26617a663a02",
|
|
237
|
+
"schemas/link.schema.json": "10f700feb3e23d89453d4d11cbe559bcc0b31f6edf08fffbe9e6773e58120512",
|
|
238
|
+
"schemas/node.schema.json": "14ed2e4c44d01e3f662e240219819895cca06dead374a5cadccfd423c520ed69",
|
|
239
|
+
"schemas/plugins-doctor.schema.json": "51e9087f4e4a20352dfba1c26e40e45eee5620e65db817241960e41fd5710d1c",
|
|
240
|
+
"schemas/plugins-registry.schema.json": "6d850d06cdf70e233f20d0d7968bb0c34306f11f30ce2505cec173cd9fa784e5",
|
|
241
|
+
"schemas/project-config.schema.json": "1403813ed7796d300634dc31aec9c2f0897da364febd5debcfa8af37da31ad81",
|
|
242
|
+
"schemas/refresh-report.schema.json": "47184d4f6b15e9b7671dc178b3b3886a64422da198898508ecdb2cb27876db04",
|
|
243
|
+
"schemas/report-base-deterministic.schema.json": "59785fe6f3ceb34814bbbd03d10fa7336a32835ce598946f2923d469b32aa32a",
|
|
244
|
+
"schemas/report-base.schema.json": "e4d25f055e24f18ae0f77c24661c1bddc87ff2e43b001b6a827fcb14f9753f44",
|
|
245
|
+
"schemas/scan-result.schema.json": "f9fafd6052c2a780cb5977a4bdd45d4890874443ae6551627c2e37f49500f14b",
|
|
246
|
+
"schemas/sidecar.schema.json": "f23dfe3ba7f71a1af2cc5cd26b57d5e057e56438655f750c1895d35061efe80a",
|
|
247
|
+
"schemas/signal.schema.json": "3f93a3641fbcf95586c52b97f15292cb1fffecef31db8aed642cd1574c2f3a0b",
|
|
248
|
+
"schemas/summaries/agent.schema.json": "5b26b95fb082b73d302c8aa6489ab09488a155ccfbb8943dfc47079509d35122",
|
|
249
|
+
"schemas/summaries/command.schema.json": "7f522c682d0fdf5a40172c7fc8fcd23e60a0ab0253354146525bd3a3d417f1f8",
|
|
250
|
+
"schemas/summaries/hook.schema.json": "6a1ceecda7a7173dfcd8b5f705d84be1792c4bb5a2269ff666088128c02c888a",
|
|
251
|
+
"schemas/summaries/markdown.schema.json": "369d75a18710eb6c7ee4220b2899767ddbc07dada24f81b611827fe2e3a2977a",
|
|
252
|
+
"schemas/summaries/skill.schema.json": "85d68056054bade62391948cc038fcfa70cdcf465e2b295f69cd520bbdba0134",
|
|
253
|
+
"schemas/user-settings.schema.json": "b94c5235c8723a8ee023ec71b4ffd7094100cbaeccbb648712ebc331fc879ef5",
|
|
254
|
+
"schemas/view-slots.schema.json": "f78d0c5f0414f01dc045680b655b3d636373048eae4b75cc9dbd0fe0babd60bc",
|
|
255
|
+
"versioning.md": "28a13f165f837921fe5066f4bfce61012cd9f1b7c451f88eeb67252e39a0981a"
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
258
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skill-map/spec",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.40.0",
|
|
4
4
|
"description": "JSON Schemas, prose contracts, and conformance suite for the skill-map specification.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"homepage": "https://skill-map.
|
|
7
|
+
"homepage": "https://skill-map.ai",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "git+https://github.com/crystian/skill-map.git",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://skill-map.
|
|
3
|
+
"$id": "https://skill-map.ai/spec/v0/annotations.schema.json",
|
|
4
4
|
"title": "Annotations",
|
|
5
5
|
"description": "Catalog of conventional annotation fields skill-map ships out of the box, written into the `annotations:` block of a sidecar (`<basename>.sm`). Every field is OPTIONAL, a sidecar with an empty `annotations: {}` is valid. Schema is `additionalProperties: true` so users / plugins can add custom keys without coordination; the built-in `unknown-field` analyzer emits a warning on unrecognized keys (typo guard). The curated catalog is the load-bearing 10 fields below, versioning + supersession (`version`, `stability`, `supersedes`, `supersededBy`), provenance (`authors`, `license`, `source`, `sourceVersion`), taxonomy (`tags`), docs (`docsUrl`). The activity timestamp lives in the reserved `audit:` block (`audit.lastBumpedAt`), not in `annotations:`. Plugins that want first-class custom keys with their own validation declare `annotationContributions` in their manifest (see Step 9.6.6).",
|
|
6
6
|
"type": "object",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"tags": {
|
|
50
50
|
"type": "array",
|
|
51
51
|
"items": { "type": "string", "minLength": 1 },
|
|
52
|
-
"description": "
|
|
52
|
+
"description": "Taxonomy tags for this node. Tags are a **skill-map concept**, not a vendor field: no agent format carries `tags` in frontmatter, so they live here in the `.sm` sidecar. Written by whoever curates the project. `sm list --tag <name>` and the UI's faceted search match this field; the UI renders them as chips on the node card and inspector. Empty array and missing field are equivalent."
|
|
53
53
|
},
|
|
54
54
|
"docsUrl": {
|
|
55
55
|
"type": "string",
|