@skill-map/spec 0.17.0 → 0.18.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 +334 -0
- package/README.md +1 -1
- package/architecture.md +69 -0
- package/cli-contract.md +109 -0
- package/conformance/cases/plugin-missing-ui-rejected.json +3 -1
- package/conformance/cases/sidecar-end-to-end.json +26 -0
- package/conformance/coverage.md +6 -2
- package/conformance/fixtures/plugin-missing-ui/.skill-map/plugins/bad-provider/provider.js +6 -6
- package/conformance/fixtures/sidecar-end-to-end/.claude/agents/orphan.sm +12 -0
- package/conformance/fixtures/sidecar-end-to-end/.claude/agents/stale.md +8 -0
- package/conformance/fixtures/sidecar-end-to-end/.claude/agents/stale.sm +20 -0
- package/conformance/fixtures/sidecar-example/agent-example.md +17 -0
- package/conformance/fixtures/sidecar-example/agent-example.sm +53 -0
- package/db-schema.md +17 -3
- package/index.json +33 -15
- package/package.json +1 -1
- package/plugin-author-guide.md +125 -0
- package/schemas/annotations.schema.json +79 -0
- package/schemas/api/rest-envelope.schema.json +111 -42
- package/schemas/bump-report.schema.json +29 -0
- package/schemas/extensions/base.schema.json +25 -0
- package/schemas/extensions/provider.schema.json +22 -0
- package/schemas/node.schema.json +39 -8
- package/schemas/report-base-deterministic.schema.json +15 -0
- package/schemas/sidecar.schema.json +96 -0
- package/schemas/summaries/{note.schema.json → markdown.schema.json} +5 -5
package/cli-contract.md
CHANGED
|
@@ -234,6 +234,115 @@ Exit: 0 on clean (or clean watcher shutdown), 1 if error-severity issues exist (
|
|
|
234
234
|
|
|
235
235
|
Actions are not invoked via `sm actions`; invocation is via `sm job submit` (see below).
|
|
236
236
|
|
|
237
|
+
#### Sidecar bump (Step 9.6.4)
|
|
238
|
+
|
|
239
|
+
The built-in deterministic `core/bump` Action is the canonical write channel for `<basename>.sm` annotation sidecars; the verbs below are its CLI surface plus a few sidecar-management helpers. The `bump` verb stays top-level (high frequency, ROADMAP-named); the administrative helpers live under the `sm sidecar` sub-namespace to avoid colliding with the existing `sm refresh` (which targets the enrichment layer, not sidecars). All sidecar-touching verbs are deterministic — they invoke `core/bump` (or the `FilesystemSidecarStore` directly) in-process and never queue jobs.
|
|
240
|
+
|
|
241
|
+
| Command | Purpose |
|
|
242
|
+
|---|---|
|
|
243
|
+
| `sm bump <node.path> [--force]` | Single-node bump. Wraps `core/bump`. Refuses on a fresh node (`{ ok: false, reason: 'fresh' }`, exit `2`) unless `--force` is passed; with `--force` on a fresh node the verb is a silent no-op (exit `0`, no stdout). On a stale node (or first-time creation) increments `annotations.version`, refreshes `for.{bodyHash, frontmatterHash}`, and stamps the audit block (`audit.lastBumpedAt` + `audit.lastBumpedBy: 'cli'`; on first creation also `audit.createdAt` + `audit.createdBy: 'cli'`). Exit `5` if the node is not in the persisted scan. `--json` emits the report shape declared by `bump-report.schema.json`. |
|
|
244
|
+
| `sm bump --pending [--staged] [--force]` | Batch bump. Walks every node whose sidecar overlay reports drift in `node.path` ASC order and bumps each. `--staged` runs `git add <sidecar-path>` after each successful bump so the new content lands in the same commit; `git add` failure degrades to a stderr warning, the batch keeps running. Empty stale set → exit `0` with a "nothing to do" advisory. `--json` envelope: `{ bumped, refused, skipped, errors[], elapsedMs }`. Exit `0` on a clean run; `1` when at least one per-node error landed in `errors[]`. **Git error matrix for `--staged`**: not inside a git repo (no `.git/` parent of `cwd`) → exit `5`; `git` binary not on PATH (spawn ENOENT) → exit `2`. Both checks run BEFORE any sidecar write so a misconfigured environment never produces partial state. |
|
|
245
|
+
| `sm sidecar refresh <node.path>` | Hash-only update on the sidecar. Refreshes `for.{bodyHash, frontmatterHash}` to match the live node WITHOUT bumping `annotations.version` and WITHOUT touching the audit block. Useful when the user knows a body change is editorial-only and doesn't want to spend a version increment. Distinct from the top-level `sm refresh` (which targets the enrichment layer at Step A.8) — different storage, different concept; the sub-namespace prefix prevents the collision. Exit `5` if the node has no sidecar or is not in the persisted scan. No-op on a fresh node (informational stderr, exit `0`). |
|
|
246
|
+
| `sm sidecar prune [--dry-run] [--yes]` | Delete orphan `.sm` files (sidecars whose accompanying `<basename>.md` does not exist on disk). Destructive — without `--dry-run` prompts for interactive confirmation listing every file to be deleted (per the §Dry-run rule for destructive verbs). `--yes` (alias `--force`) bypasses the prompt for non-interactive callers (CI, the pre-commit hook, scripts). With `--dry-run` reports what would be deleted without touching disk and never prompts. Different domain from `sm orphans` — that verb operates on the node graph (rename heuristic); this one operates on the filesystem layer. `--json` envelope: `{ deleted, wouldDelete, errors, items[], elapsedMs }`. Exit `1` when delete failures landed in `errors`. |
|
|
247
|
+
| `sm sidecar annotate <node.path> [--force]` | Pure scaffolding. Writes a minimal `.sm` next to the `.md` with the identity (`for:`) block populated and an empty `annotations: {}` block, ready for editing. Refuses if the file exists; `--force` overwrites. The optional legacy-frontmatter migration helper (`--from-frontmatter`) is deferred — no released consumer demands it. |
|
|
248
|
+
| `sm hooks install pre-commit-bump [--dry-run]` | Install (or chain into) a git pre-commit hook that runs `sm bump --pending --staged` so any staged drift in `.sm` sidecars auto-bumps before the commit lands. Idempotent: re-running detects the skill-map marker and no-ops. When the repo already has a custom `pre-commit`, the verb appends the skill-map block to the existing file rather than replacing it. `--dry-run` prints the planned content with `--- target: <path> ---` markers and writes nothing. Exit `5` if no `.git/` parent is found at or above `cwd`; exit `2` on write failures or unknown hook flavours. |
|
|
249
|
+
|
|
250
|
+
**`.sm` round-trip contract.** The `bump` verb, `sm sidecar refresh`, and `sm sidecar annotate` write through `FilesystemSidecarStore`, which re-serialises the merged result via `js-yaml` `dump` with `sortKeys: true`. **`.sm` files are managed artifacts; comments and key order are not preserved on round-trip.** Author commentary belongs in the markdown body or in a separate documentation file, not inside `.sm`. The integrity guarantee is that the merged YAML always validates against `sidecar.schema.json` + `annotations.schema.json` and that the file is written atomically (`.tmp + rename`).
|
|
251
|
+
|
|
252
|
+
Concretely, a hand-edited sidecar like this:
|
|
253
|
+
|
|
254
|
+
```yaml
|
|
255
|
+
for:
|
|
256
|
+
path: agents/reviewer.md
|
|
257
|
+
bodyHash: 3dd7d0...
|
|
258
|
+
frontmatterHash: 271d1e...
|
|
259
|
+
|
|
260
|
+
annotations:
|
|
261
|
+
version: 3
|
|
262
|
+
# Deprecated because v0.6 architecture supersedes this skill.
|
|
263
|
+
# See decision #142 in ROADMAP for context.
|
|
264
|
+
stability: deprecated
|
|
265
|
+
supersededBy: agents/reviewer-v2.md
|
|
266
|
+
tags:
|
|
267
|
+
- review
|
|
268
|
+
- typescript # only TS, not JS
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
…becomes the following after one `sm bump`:
|
|
272
|
+
|
|
273
|
+
```yaml
|
|
274
|
+
annotations:
|
|
275
|
+
stability: deprecated
|
|
276
|
+
supersededBy: agents/reviewer-v2.md
|
|
277
|
+
tags:
|
|
278
|
+
- review
|
|
279
|
+
- typescript
|
|
280
|
+
version: 4
|
|
281
|
+
audit:
|
|
282
|
+
createdAt: '2026-05-07T10:00:00.000Z'
|
|
283
|
+
createdBy: cli
|
|
284
|
+
lastBumpedAt: '2026-05-07T10:00:00.000Z'
|
|
285
|
+
lastBumpedBy: cli
|
|
286
|
+
for:
|
|
287
|
+
bodyHash: 3dd7d0...
|
|
288
|
+
frontmatterHash: 271d1e...
|
|
289
|
+
path: agents/reviewer.md
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
Comments dropped, keys re-sorted alphabetically. **`.sm` files cannot preserve free-form commentary across bumps — narrative documentation lives in the `.md` body, which is never touched.** The `sm sidecar annotate` scaffold prints a banner reminding the author of this contract on first creation; that banner itself is dropped on the first bump.
|
|
293
|
+
|
|
294
|
+
Tracked as **R6** in the §Step 9.6 review queue: open by design, defer the `js-yaml` → `yaml` (eemeli) swap that would preserve comments + key order until a user complaint surfaces. The swap is a small piece of work (one new dep, one Document-aware merge helper); the bias is to ship simple now and add fidelity when there is concrete demand.
|
|
295
|
+
|
|
296
|
+
##### BFF endpoint — `POST /api/sidecar/bump` (Step 9.6.5, BFF half)
|
|
297
|
+
|
|
298
|
+
The Hono BFF exposes the single-node bump flow over REST so the UI can drive the same Action / Store the CLI uses. Behaviour mirrors `sm bump <node.path> [--force]` 1:1: same `core/bump` Action, same `FilesystemSidecarStore`, same fresh-vs-stale refusal semantics. The only differences from the CLI verb are the invoker label (`'ui'` vs `'cli'` — Decision A5 of 9.6.4 left this as a literal) and the wire shape. Batch (`--pending`) is intentionally CLI-only at 9.6.5 — surfacing it over REST needs a job-style progress channel and lands later.
|
|
299
|
+
|
|
300
|
+
| Field | Value |
|
|
301
|
+
|---|---|
|
|
302
|
+
| Method + path | `POST /api/sidecar/bump` |
|
|
303
|
+
| Request body | `{ "nodePath": <string, required>, "force"?: <boolean, default false> }` (JSON). `nodePath` is the canonical scope-root-relative `Node.path`. |
|
|
304
|
+
| 200 envelope | `{ "schemaVersion": "1", "kind": "sidecar.bumped", "value": { "nodePath": <string>, "version": <int|null>, "status": "fresh" }, "elapsedMs": <int> }`. The `kind` value is part of the canonical `rest-envelope.schema.json#/properties/kind/enum` and validates under the action-result `oneOf` variant (`value` + `elapsedMs` siblings, no `filters` / `counts` / `kindRegistry`). |
|
|
305
|
+
| 409 envelope | `{ "ok": false, "error": { "code": "sidecar-fresh", "message": <string>, "details": null } }`. Returned when the target node is fresh and `force !== true`. The `'sidecar-fresh'` code is added to `app.ts`'s `TErrorCode` union. |
|
|
306
|
+
| 404 envelope | Standard `'not-found'` envelope. Returned when the DB is missing OR `nodePath` is not in the persisted scan. |
|
|
307
|
+
| 400 envelope | Standard `'bad-query'` envelope. Body must be a JSON object with `nodePath` (non-empty string); `force` (when present) must be a boolean. |
|
|
308
|
+
| 200 force-on-fresh | Per the Action spec, `force: true` on a fresh node is a silent no-op — the response carries the existing `version` (read off the sidecar overlay) and `status: 'fresh'`. **No WS broadcast** is emitted in this case (decision: no-op = no event; nothing changed on disk, sending `sidecar.bumped` would tell every connected UI to refresh state that hasn't moved). |
|
|
309
|
+
|
|
310
|
+
**WS event — `sidecar.bumped`** (Step 9.6.5; canonical envelope shape locked in 9.6.7 / R9). After every successful bump that materialises a write, the BFF broadcasts a `sidecar.bumped` event over `/ws` so all connected clients refresh in lockstep. The event uses the canonical `IWsEventEnvelope` wire shape (matches every other kernel→broadcaster bridge — `scan.*`, `watcher.*`, etc.):
|
|
311
|
+
|
|
312
|
+
```jsonc
|
|
313
|
+
{
|
|
314
|
+
"type": "sidecar.bumped",
|
|
315
|
+
"timestamp": "<ISO 8601 string>", // server wall-clock at broadcast time
|
|
316
|
+
"data": {
|
|
317
|
+
"nodePath": "<scope-root-relative path>",
|
|
318
|
+
"version": <int|null>, // new value of annotations.version (`null` if absent)
|
|
319
|
+
"status": "fresh" // status after the bump
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Emission rules:
|
|
325
|
+
|
|
326
|
+
- Emitted on a successful 200 bump (stale → fresh, or first-time-create → fresh).
|
|
327
|
+
- **NOT** emitted on a force-on-fresh no-op 200 (nothing changed on disk).
|
|
328
|
+
- **NOT** emitted on 409 / 404 / 400 (no write happened).
|
|
329
|
+
|
|
330
|
+
The `type` value is a normative addition to the event-type registry — if a future spec section catalogues every WS event type, `sidecar.bumped` joins `scan.started` / `scan.completed` / `watcher.error` / `emitter.error` there.
|
|
331
|
+
|
|
332
|
+
##### BFF endpoint — `GET /api/annotations/registered` (Step 9.6.6, BFF half)
|
|
333
|
+
|
|
334
|
+
Read-only catalog of plugin-contributed annotation keys. The endpoint is a pure projection of `kernel.getRegisteredAnnotationKeys()` — populated once by `registerEnabledExtensions` at server boot, frozen, surfaced unchanged. Built-in catalog keys (from `annotations.schema.json`) are NOT included; the UI knows the built-in set via the bundled spec. The endpoint exists so a future UI autocomplete can offer plugin-namespaced and root-exclusive contributions the UI can't otherwise discover at runtime.
|
|
335
|
+
|
|
336
|
+
| Field | Value |
|
|
337
|
+
|---|---|
|
|
338
|
+
| Method + path | `GET /api/annotations/registered` |
|
|
339
|
+
| Request | None — no query params, no body, no auth (matches `/api/plugins`, `/api/config`). |
|
|
340
|
+
| 200 envelope | `{ "schemaVersion": "1", "kind": "annotations.registered", "items": IRegisteredAnnotationKey[], "counts": { "total": <int> } }`. The `kind` value is part of the canonical `rest-envelope.schema.json#/properties/kind/enum` and validates under the catalog `oneOf` variant (`items` + `counts.total` only, no `filters` / `kindRegistry` / `returned` — the catalog ships in its entirety on every response and does not paginate). |
|
|
341
|
+
| Item shape | `IRegisteredAnnotationKey` per `src/kernel/types/annotation-catalog.ts`: `{ pluginId: string, key: string, location: 'namespaced' \| 'root', ownership: 'exclusive' \| 'shared', schema: Record<string, unknown> }`. The inline JSON Schema as declared in the contributing plugin's manifest (NOT the AJV-compiled validator). |
|
|
342
|
+
| Invariants | Read-only, no side effects, never throws after kernel boot. The catalog is small (typically 0–50 entries); no pagination, no filters, no caching headers. Mutating the returned `items` array does not affect subsequent calls — the kernel's view is frozen. |
|
|
343
|
+
| Empty case | When the kernel was booted with no plugin contributions (or `--no-plugins`): `{ "items": [], "counts": { "total": 0 } }`. |
|
|
344
|
+
| Refresh policy | Same as the rest of the BFF's plugin surface — discovery happens once at `sm serve` boot. An operator that installs a new plugin restarts the server (matches the watcher's "loaded ONCE at boot" contract). |
|
|
345
|
+
|
|
237
346
|
---
|
|
238
347
|
|
|
239
348
|
### Jobs
|
|
@@ -10,8 +10,10 @@
|
|
|
10
10
|
"assertions": [
|
|
11
11
|
{ "type": "exit-code", "value": 0 },
|
|
12
12
|
{ "type": "stderr-matches", "pattern": "plugin bad-provider:.*invalid.*must have required property 'ui'" },
|
|
13
|
-
{ "type": "json-path", "path": "$.providers.length", "equals":
|
|
13
|
+
{ "type": "json-path", "path": "$.providers.length", "equals": 3 },
|
|
14
14
|
{ "type": "json-path", "path": "$.providers[0]", "equals": "claude" },
|
|
15
|
+
{ "type": "json-path", "path": "$.providers[1]", "equals": "gemini" },
|
|
16
|
+
{ "type": "json-path", "path": "$.providers[2]", "equals": "agent-skills" },
|
|
15
17
|
{ "type": "json-path", "path": "$.nodes.length", "equals": 1 }
|
|
16
18
|
]
|
|
17
19
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://skill-map.dev/spec/v0/conformance-case.schema.json",
|
|
3
|
+
"id": "sidecar-end-to-end",
|
|
4
|
+
"description": "Step 9.6.6 — co-located `.sm` sidecar end-to-end. Scanning a fixture that carries a stale sidecar (wrong `for.{bodyHash,frontmatterHash}`) plus an orphan sidecar (no sibling `.md`) MUST surface `sidecar_status` queryable on the node, denormalise `annotations.version` into the node row, and emit both `annotation-stale` (per stale node) and `annotation-orphan` (per orphan `.sm`) issues from the built-in core rules.",
|
|
5
|
+
"fixture": "sidecar-end-to-end",
|
|
6
|
+
"invoke": {
|
|
7
|
+
"verb": "scan",
|
|
8
|
+
"flags": ["--json"]
|
|
9
|
+
},
|
|
10
|
+
"assertions": [
|
|
11
|
+
{ "type": "exit-code", "value": 0 },
|
|
12
|
+
{ "type": "json-path", "path": "$.schemaVersion", "equals": 1 },
|
|
13
|
+
{ "type": "json-path", "path": "$.stats.nodesCount", "equals": 1 },
|
|
14
|
+
{ "type": "json-path", "path": "$.nodes[0].path", "equals": ".claude/agents/stale.md" },
|
|
15
|
+
{ "type": "json-path", "path": "$.nodes[0].version", "equals": 7 },
|
|
16
|
+
{ "type": "json-path", "path": "$.nodes[0].sidecar.present", "equals": true },
|
|
17
|
+
{ "type": "json-path", "path": "$.nodes[0].sidecar.status", "matches": "^stale-(body|frontmatter|both)$" },
|
|
18
|
+
{ "type": "json-path", "path": "$.nodes[0].sidecar.annotations.version", "equals": 7 },
|
|
19
|
+
{ "type": "json-path", "path": "$.stats.issuesCount", "equals": 2 },
|
|
20
|
+
{ "type": "json-path", "path": "$.issues[0].ruleId", "equals": "annotation-stale" },
|
|
21
|
+
{ "type": "json-path", "path": "$.issues[0].severity", "equals": "warn" },
|
|
22
|
+
{ "type": "json-path", "path": "$.issues[1].ruleId", "equals": "annotation-orphan" },
|
|
23
|
+
{ "type": "json-path", "path": "$.issues[1].severity", "equals": "warn" },
|
|
24
|
+
{ "type": "json-path", "path": "$.issues[1].data.expectedMdPath", "equals": ".claude/agents/orphan.md" }
|
|
25
|
+
]
|
|
26
|
+
}
|
package/conformance/coverage.md
CHANGED
|
@@ -18,12 +18,12 @@ This file is hand-maintained. A CI check before spec release compares the schema
|
|
|
18
18
|
| 8 | `job.schema.json` | — | 🔴 missing | Blocked by Step 10 (job system). Needs a case that submits a local action (no LLM), inspects `sm job show --json`. |
|
|
19
19
|
| 9 | `report-base.schema.json` | — | 🔴 missing | Indirect coverage once any summarizer case lands. Direct contract case: validate a handcrafted minimal report ({confidence, safety}) against the base schema. |
|
|
20
20
|
| 10 | `conformance-case.schema.json` | — | 🔴 missing | Self-referential: every `*.json` under `cases/` MUST validate against this schema. Add a meta-case that enumerates + validates all cases. |
|
|
21
|
-
| 11 | `frontmatter/base.schema.json` | — | 🔴 missing | Universal frontmatter shape — `name` + `description` only, `additionalProperties: true`. Per-kind schemas (`skill` / `agent` / `command` / `
|
|
21
|
+
| 11 | `frontmatter/base.schema.json` | — | 🔴 missing | Universal frontmatter shape — `name` + `description` only, `additionalProperties: true`. Per-kind schemas (`skill` / `agent` / `command` / `markdown`) live with the Provider that emits them (the Claude Provider ships them under `src/extensions/providers/claude/schemas/`) and extend this base via `$ref`-by-`$id`. Direct spec-level case still pending: fixture with min-required frontmatter only, no Provider needed (Provider-disabled mode + a single `notes/<file>.md` with `name: ...` + `description: ...`). |
|
|
22
22
|
| 12 | `summaries/skill.schema.json` | — | 🔴 missing | Blocked by Step 10 (`skill-summarizer`). Case: submit summarizer, validate report. |
|
|
23
23
|
| 13 | `summaries/agent.schema.json` | — | 🔴 missing | Blocked by Step 11. |
|
|
24
24
|
| 14 | `summaries/command.schema.json` | — | 🔴 missing | Blocked by Step 11. |
|
|
25
25
|
| 15 | `summaries/hook.schema.json` | — | 🔴 missing | Blocked by Step 11. |
|
|
26
|
-
| 16 | `summaries/
|
|
26
|
+
| 16 | `summaries/markdown.schema.json` | — | 🔴 missing | Blocked by Step 11. |
|
|
27
27
|
| 17 | `extensions/base.schema.json` | — | 🔴 missing | Meta-case: every manifest under `src/extensions/` validates against the appropriate kind schema (which extends base via `allOf`). |
|
|
28
28
|
| 18 | `extensions/provider.schema.json` | `plugin-missing-ui-rejected` | 🟡 partial | A drop-in Provider whose `kinds[*]` entry omits the required `ui` block fails AJV validation with `invalid-manifest` while the rest of the pipeline keeps running (built-in Claude Provider, exit 0). The complementary positive case (canonical Claude Provider manifest validates) lives in `provider:claude` conformance. Direct cases for missing `kinds` / `explorationDir` rejection still pending. |
|
|
29
29
|
| 19 | `extensions/extractor.schema.json` | — | 🔴 missing | Case: `frontmatter` + `slash` + `at-directive` extractor manifests validate; an extractor emitting a disallowed `emitsLinkKinds` value fails. |
|
|
@@ -33,6 +33,10 @@ This file is hand-maintained. A CI check before spec release compares the schema
|
|
|
33
33
|
| 23 | `history-stats.schema.json` | — | 🔴 missing | Blocked by Step 5 (history). Case: seed `state_executions` with a deterministic fixture, run `sm history stats --json --since <T0> --until <T1> --period month --top 5`, assert the document validates and that `totals.executionsCount == sum(perAction.executionsCount)` and `errorRates.global == totals.failedCount / totals.executionsCount`. Percentiles (`p95`/`p99`) intentionally omitted in v1 — add later as a minor bump without breaking consumers. |
|
|
34
34
|
| 24 | `extensions/hook.schema.json` | — | 🔴 missing | Case: a `deterministic` hook manifest with `triggers: ['scan.completed']` validates; a hook declaring an unknown trigger (e.g. `scan.progress`) fails with `invalid-manifest` at load time. |
|
|
35
35
|
| 25 | `api/rest-envelope.schema.json` | — | 🔴 missing | Step 14.2 BFF list-envelope shape (`{ schemaVersion, kind, items \| item \| value, filters, counts }`). Case: hit `GET /api/nodes` against a primed scope, validate the response against the schema; assert the `oneOf` rejects an envelope that carries both `items` and `item`. Implementation-side coverage exists today (`src/test/server-endpoints.test.ts`) but a kernel-agnostic conformance case is required before v1.0.0 ships. |
|
|
36
|
+
| 26 | `sidecar.schema.json` | `sidecar-end-to-end` | 🟢 covered | Co-located YAML sidecar (`<basename>.sm`) root shape: reserved blocks `for` / `annotations` / `settings` / `audit` plus opt-in plugin namespacing. Step 9.6.2 (2026-05-05) shipped the kernel reader; Step 9.6.3 (2026-05-05) formalised the `audit:` sub-shape populated by the built-in `bump` Action; Step 9.6.6 (2026-05-06) flips this row 🟢 with the end-to-end `sidecar-end-to-end` case (fixture `sidecar-end-to-end/`): a scan over a stale-`.sm` + orphan-`.sm` corpus produces a populated `Node.sidecar` overlay with `present: true` and `status: stale-*`, denormalises `annotations.version` into the node row, and emits both `annotation-stale` and `annotation-orphan` issues from the built-in core rules. Structural sample (untouched) at `fixtures/sidecar-example/agent-example.sm`. |
|
|
37
|
+
| 27 | `annotations.schema.json` | `sidecar-end-to-end` | 🟢 covered | Curated catalog of 15 conventional skill-map annotation fields (versioning, supersession, provenance, lifecycle, taxonomy, display, docs). `additionalProperties: true` so users / plugins extend without coordination; the `unknown-field` Tier-1 rule shipped in Step 9.6.6 emits warnings on truly unrecognized keys. Step 9.6.2 (2026-05-05) wired the kernel reader; Step 9.6.6 (2026-05-06) flips this row 🟢 via `sidecar-end-to-end`, which asserts that an `annotations.version: 7` value round-trips through `state_scan_nodes.annotations_json` and surfaces in the node's `sidecar.annotations` overlay AND in the denormalised `Node.version` column. Structural sample at `fixtures/sidecar-example/agent-example.sm`. Catalog trimmed from 31 to 15 fields on 2026-05-07 after UX review. |
|
|
38
|
+
| 28 | `bump-report.schema.json` | — | 🔴 missing | Report shape produced by the built-in deterministic `bump` Action (Step 9.6.3, Decision #125). Extends `report-base-deterministic.schema.json` (row 29) — the deterministic counterpart to `report-base.schema.json` (which is LLM-specific via `confidence` + `safety`). Three concrete shapes: success-with-write, silent-no-op (under `force`), and refusal (`fresh`). Direct conformance case lands together with the `sm bump` CLI verb in Step 9.6.4 — it'll exercise all three branches via `sm bump --json` against a primed fixture. Implementation tests at `src/test/bump-action.test.ts` cover the runtime behaviour today. |
|
|
39
|
+
| 29 | `report-base-deterministic.schema.json` | — (indirect via row 28) | 🟡 partial | Deterministic counterpart to `report-base.schema.json`; every deterministic Action's report extends this base. Direct contract case still pending — landed when first conformance case directly validates a deterministic report against this schema. |
|
|
36
40
|
|
|
37
41
|
> **Note on Provider-owned schemas.** Per-kind frontmatter schemas (`skill`, `agent`, `command`, `note` for the built-in Claude Provider; other Providers MAY declare different kinds) live with the Provider that emits them — for the built-in Claude Provider, under `src/extensions/providers/claude/schemas/`. Those schemas are NOT counted in the spec's coverage matrix above; they belong to the Provider's own conformance suite at `src/extensions/providers/claude/conformance/coverage.md`. The same split applies to the cases that exercise Provider-specific kinds (`basic-scan`, `rename-high`, `orphan-detection`) — they live in the Provider's `cases/` directory.
|
|
38
42
|
|
|
@@ -9,23 +9,23 @@ export default {
|
|
|
9
9
|
kind: 'provider',
|
|
10
10
|
id: 'bad-provider-provider',
|
|
11
11
|
version: '0.1.0',
|
|
12
|
-
description: 'provider whose
|
|
12
|
+
description: 'provider whose markdown kind is missing the ui block',
|
|
13
13
|
stability: 'experimental',
|
|
14
14
|
explorationDir: '~/.bad',
|
|
15
15
|
kinds: {
|
|
16
|
-
|
|
17
|
-
schema: './schemas/
|
|
16
|
+
markdown: {
|
|
17
|
+
schema: './schemas/markdown.schema.json',
|
|
18
18
|
schemaJson: {
|
|
19
|
-
$id: 'urn:test:bad-provider/
|
|
19
|
+
$id: 'urn:test:bad-provider/markdown',
|
|
20
20
|
type: 'object',
|
|
21
21
|
additionalProperties: true,
|
|
22
22
|
},
|
|
23
|
-
defaultRefreshAction: 'bad-provider/summarize-
|
|
23
|
+
defaultRefreshAction: 'bad-provider/summarize-markdown',
|
|
24
24
|
// NOTE: deliberately no `ui` — this is what the case asserts.
|
|
25
25
|
},
|
|
26
26
|
},
|
|
27
27
|
async *walk() {},
|
|
28
28
|
classify() {
|
|
29
|
-
return '
|
|
29
|
+
return 'markdown';
|
|
30
30
|
},
|
|
31
31
|
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Orphan sidecar — no sibling `agents/orphan.md` exists. The kernel walker
|
|
2
|
+
# discovers this via `discoverOrphanSidecars` and the built-in
|
|
3
|
+
# `core/annotation-orphan` rule emits one `warn` issue per orphan.
|
|
4
|
+
|
|
5
|
+
for:
|
|
6
|
+
path: agents/orphan.md
|
|
7
|
+
bodyHash: '1111111111111111111111111111111111111111111111111111111111111111'
|
|
8
|
+
frontmatterHash: '1111111111111111111111111111111111111111111111111111111111111111'
|
|
9
|
+
|
|
10
|
+
annotations:
|
|
11
|
+
version: 1
|
|
12
|
+
stability: deprecated
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: stale-agent
|
|
3
|
+
description: A node with a deliberately stale sidecar — body hash in .sm does not match the live body, so the kernel must emit annotation-stale.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Stale agent
|
|
7
|
+
|
|
8
|
+
This body has been edited since the sidecar was last bumped. The sidecar's `for.bodyHash` will not match the live sha256 of this content.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# End-to-end sidecar fixture (Step 9.6.6 conformance case sidecar-end-to-end).
|
|
2
|
+
# Hashes are intentionally placeholders that do NOT match the live body /
|
|
3
|
+
# frontmatter — the conformance runner asserts that the kernel emits an
|
|
4
|
+
# `annotation-stale` issue when the stored hashes drift from the live ones.
|
|
5
|
+
#
|
|
6
|
+
# `annotations.version: 7` exists so the assertion can verify that the
|
|
7
|
+
# `annotations:` block denormalises through the SQLite scan — the value
|
|
8
|
+
# survives a round-trip through `state_scan_nodes.annotations_json`.
|
|
9
|
+
|
|
10
|
+
for:
|
|
11
|
+
path: agents/stale.md
|
|
12
|
+
bodyHash: '0000000000000000000000000000000000000000000000000000000000000000'
|
|
13
|
+
frontmatterHash: '0000000000000000000000000000000000000000000000000000000000000000'
|
|
14
|
+
|
|
15
|
+
annotations:
|
|
16
|
+
version: 7
|
|
17
|
+
stability: stable
|
|
18
|
+
tags:
|
|
19
|
+
- conformance
|
|
20
|
+
- sidecar
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-reviewer
|
|
3
|
+
description: Reviews TypeScript code for clarity, type safety, and idiom drift before PR submission.
|
|
4
|
+
model: sonnet
|
|
5
|
+
tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Grep
|
|
8
|
+
- Bash
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Code reviewer
|
|
12
|
+
|
|
13
|
+
Walks the diff, flags type holes, suggests idiomatic refactors. Pairs with the local lint suite — never duplicates rules a linter already enforces.
|
|
14
|
+
|
|
15
|
+
## When to invoke
|
|
16
|
+
|
|
17
|
+
After staging changes and before opening a PR. The reviewer reads the diff against `main`, plus any file the diff touches in full.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Sample sidecar matching agent-example.md.
|
|
2
|
+
# Validates against:
|
|
3
|
+
# - https://skill-map.dev/spec/v0/sidecar.schema.json (root shape)
|
|
4
|
+
# - https://skill-map.dev/spec/v0/annotations.schema.json (annotations block)
|
|
5
|
+
# Hashes are sha256 over the kernel's canonical forms (body bytes; canonical YAML
|
|
6
|
+
# of the frontmatter via `js-yaml` dump with sortKeys+noCompatMode). Regenerate
|
|
7
|
+
# when agent-example.md changes (the fixture is meant to be drift-free).
|
|
8
|
+
|
|
9
|
+
for:
|
|
10
|
+
# Scope-root-relative — when this fixture is treated as its own
|
|
11
|
+
# mini-scope (the typical reading), the .md sits in the same
|
|
12
|
+
# directory as this .sm, so `for.path` is just the filename.
|
|
13
|
+
path: agent-example.md
|
|
14
|
+
bodyHash: 3dd7d0dff35d7aa882af1617e675f9100cb815ba6206826a9a8b929b9364f6ce
|
|
15
|
+
frontmatterHash: 271d1ef97087db79d7f3a6d3b27abf96bcc31852d9dbc756cfeb2417dfad55b6
|
|
16
|
+
resolvedAs:
|
|
17
|
+
provider: claude
|
|
18
|
+
kind: agent
|
|
19
|
+
|
|
20
|
+
annotations:
|
|
21
|
+
version: 1
|
|
22
|
+
stability: stable
|
|
23
|
+
authors:
|
|
24
|
+
- skill-map-team
|
|
25
|
+
- crystian
|
|
26
|
+
license: MIT
|
|
27
|
+
source: https://github.com/example/code-reviewer/blob/main/agent.md
|
|
28
|
+
sourceVersion: v1.0.0
|
|
29
|
+
tags:
|
|
30
|
+
- review
|
|
31
|
+
- typescript
|
|
32
|
+
- quality
|
|
33
|
+
hidden: false
|
|
34
|
+
docsUrl: https://skill-map.dev/examples/code-reviewer
|
|
35
|
+
requires:
|
|
36
|
+
- .skill-map/agents/diff-reader.md
|
|
37
|
+
related:
|
|
38
|
+
- .skill-map/agents/security-reviewer.md
|
|
39
|
+
|
|
40
|
+
settings: {}
|
|
41
|
+
|
|
42
|
+
audit:
|
|
43
|
+
createdAt: '2026-05-05T10:00:00Z'
|
|
44
|
+
createdBy: cli
|
|
45
|
+
lastBumpedAt: '2026-05-05T10:30:00Z'
|
|
46
|
+
lastBumpedBy: cli
|
|
47
|
+
|
|
48
|
+
# Plugin-namespaced block (default location for plugin annotation contributions).
|
|
49
|
+
# This is illustrative — no `example-plugin` exists. Plugins may write here without
|
|
50
|
+
# coordination; the schema permits unknown root keys via additionalProperties: true.
|
|
51
|
+
example-plugin:
|
|
52
|
+
reviewedBy: agent-example
|
|
53
|
+
lastReviewedAt: 2026-05-05T10:30:00Z
|
package/db-schema.md
CHANGED
|
@@ -72,13 +72,12 @@ One row per detected node, matching [`schemas/node.schema.json`](./schemas/node.
|
|
|
72
72
|
| Column | Type | Constraint | Notes |
|
|
73
73
|
|---|---|---|---|
|
|
74
74
|
| `path` | TEXT | PRIMARY KEY | Relative path from scope root. Canonical node identifier. |
|
|
75
|
-
| `kind` | TEXT | NOT NULL | Open-by-design (`node.schema.json#/properties/kind`): the value is whatever the classifying Provider declares. Built-in Claude Provider catalog: `skill` / `agent` / `command` / `
|
|
75
|
+
| `kind` | TEXT | NOT NULL | Open-by-design (`node.schema.json#/properties/kind`): the value is whatever the classifying Provider declares. Built-in Claude Provider catalog: `skill` / `agent` / `command` / `markdown` (the last is the format-named generic fallback). External Providers MAY emit their own. |
|
|
76
76
|
| `provider` | TEXT | NOT NULL | Provider extension id. |
|
|
77
77
|
| `title` | TEXT | NULL | |
|
|
78
78
|
| `description` | TEXT | NULL | |
|
|
79
79
|
| `stability` | TEXT | CHECK in (`experimental`, `stable`, `deprecated`) OR NULL | Denormalized from frontmatter. |
|
|
80
80
|
| `version` | TEXT | NULL | Denormalized from frontmatter. |
|
|
81
|
-
| `author` | TEXT | NULL | Denormalized. |
|
|
82
81
|
| `frontmatter_json` | TEXT | NOT NULL | Full parsed frontmatter as JSON. |
|
|
83
82
|
| `body_hash` | TEXT | NOT NULL | sha256, hex. |
|
|
84
83
|
| `frontmatter_hash` | TEXT | NOT NULL | sha256, hex. |
|
|
@@ -335,6 +334,21 @@ Shared key-value store for plugins that declared storage mode `kv`. See [`plugin
|
|
|
335
334
|
|
|
336
335
|
Primary key: `(plugin_id, node_id, key)` with `node_id` using a sentinel empty string when NULL to satisfy PK constraints on engines that reject NULL in PK columns. Indexes: `ix_state_plugin_kvs_plugin_id`.
|
|
337
336
|
|
|
337
|
+
### `state_node_favorites`
|
|
338
|
+
|
|
339
|
+
Per-node "favorite" flag set by the local user from the UI. The set is small (typical projects pin a handful of skills/agents/commands), so the table degenerates to one row per favorited node — absence of a row means "not favorited". Exists in zone `state_` because it is user-authored preference, not regenerable scan output: it must survive `sm scan` truncation and `sm db reset` (which drops only `scan_*`).
|
|
340
|
+
|
|
341
|
+
| Column | Type | Constraint |
|
|
342
|
+
|---|---|---|
|
|
343
|
+
| `node_path` | TEXT | PRIMARY KEY |
|
|
344
|
+
| `favorited_at` | INTEGER | NOT NULL | Unix milliseconds when the user marked the node. |
|
|
345
|
+
|
|
346
|
+
No indexes (PK already covers lookup by path; the table is keyed-by-path exclusively).
|
|
347
|
+
|
|
348
|
+
`node_path` is FK-semantic to `scan_nodes.path`. Per `§ Rename detection` below, the rename heuristic MUST migrate rows in this table when a path is renamed (same protocol as `state_jobs` / `state_summaries` / `state_enrichments` / `state_plugin_kvs`). A simple PK update suffices — there is no composite key, so collisions cannot occur (the destination path either has a row already, in which case the migrating row is dropped to preserve the live one, or it does not).
|
|
349
|
+
|
|
350
|
+
The BFF's `/api/nodes` route loads the full set of favorited paths once per request (`SELECT node_path FROM state_node_favorites`) and decorates each emitted `Node` with a derived `isFavorite` boolean by Set membership — no SQL JOIN against `scan_nodes` is required, and the table participates in zero of the per-scan persistence transactions.
|
|
351
|
+
|
|
338
352
|
---
|
|
339
353
|
|
|
340
354
|
## Table catalog: zone `config_`
|
|
@@ -453,7 +467,7 @@ Backups include `state_*` + `config_*` only; `scan_*` is regenerated after resto
|
|
|
453
467
|
|
|
454
468
|
## Rename detection (automatic)
|
|
455
469
|
|
|
456
|
-
`scan_nodes.path` is the canonical node identifier in v0. Moving a file therefore rewrites the primary key, which would orphan every `state_*` row referencing the old path (`state_executions.node_ids_json`, `state_jobs.node_id`, `state_summaries.node_id`, `state_enrichments.node_id`).
|
|
470
|
+
`scan_nodes.path` is the canonical node identifier in v0. Moving a file therefore rewrites the primary key, which would orphan every `state_*` row referencing the old path (`state_executions.node_ids_json`, `state_jobs.node_id`, `state_summaries.node_id`, `state_enrichments.node_id`, `state_plugin_kvs.node_id`, `state_node_favorites.node_path`).
|
|
457
471
|
|
|
458
472
|
Implementations MUST apply a rename heuristic at scan time **before** committing the new scan transaction:
|
|
459
473
|
|
package/index.json
CHANGED
|
@@ -47,6 +47,14 @@
|
|
|
47
47
|
{
|
|
48
48
|
"id": "history-stats",
|
|
49
49
|
"path": "schemas/history-stats.schema.json"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"id": "sidecar",
|
|
53
|
+
"path": "schemas/sidecar.schema.json"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"id": "annotations",
|
|
57
|
+
"path": "schemas/annotations.schema.json"
|
|
50
58
|
}
|
|
51
59
|
],
|
|
52
60
|
"extensions": [
|
|
@@ -166,53 +174,63 @@
|
|
|
166
174
|
}
|
|
167
175
|
]
|
|
168
176
|
},
|
|
169
|
-
"specPackageVersion": "0.
|
|
177
|
+
"specPackageVersion": "0.18.0",
|
|
170
178
|
"integrity": {
|
|
171
179
|
"algorithm": "sha256",
|
|
172
180
|
"files": {
|
|
173
|
-
"CHANGELOG.md": "
|
|
174
|
-
"README.md": "
|
|
175
|
-
"architecture.md": "
|
|
176
|
-
"cli-contract.md": "
|
|
181
|
+
"CHANGELOG.md": "5cff1602344521d5266635f89d3e778362b7a7b386983b776dfaf6f44125ae83",
|
|
182
|
+
"README.md": "3ffd34a0d55c76d53777d47244c727e2262bf5d8bcde21035e9ec0154640cee7",
|
|
183
|
+
"architecture.md": "ed307b35a0a1cd321c2ecaccd4d77943809cd926d3d39ff9f25123446e610026",
|
|
184
|
+
"cli-contract.md": "8e88126a5dc146e9928141eae61b58348fb9563a7d1e41064a8711810234f1ba",
|
|
177
185
|
"conformance/README.md": "5f94a6ac637b7c992fcd7e53d32eed1b8887eeef05eb6ca3b5ec8a0b5045cd21",
|
|
178
186
|
"conformance/cases/kernel-empty-boot.json": "ad4bbe9d637537625025c8bdb61285b1433568a2544b1ce0248f304ccff8c350",
|
|
179
|
-
"conformance/cases/plugin-missing-ui-rejected.json": "
|
|
180
|
-
"conformance/
|
|
187
|
+
"conformance/cases/plugin-missing-ui-rejected.json": "192a6f13b7d492e843f5ac3294a03a47585061b36ff41e1d80e5e836cf15e854",
|
|
188
|
+
"conformance/cases/sidecar-end-to-end.json": "dc3409d7bf4ec1d89d458ec49cdf843ca4931f910493e2d4a1939603cf786132",
|
|
189
|
+
"conformance/coverage.md": "1bd1f6e6e681ed23f02a4dad0ad2c23cf9ed2f76bbc647fb229cdec6aed3c945",
|
|
181
190
|
"conformance/fixtures/plugin-missing-ui/.skill-map/plugins/bad-provider/plugin.json": "4d78af6f12faa9d131e2a19f1dbb8f250baacc525978f3a8c858932b95da4ff6",
|
|
182
|
-
"conformance/fixtures/plugin-missing-ui/.skill-map/plugins/bad-provider/provider.js": "
|
|
191
|
+
"conformance/fixtures/plugin-missing-ui/.skill-map/plugins/bad-provider/provider.js": "d1f4898b43201d24f048171ce84d433b68694457452fbc64498857f5da3e9bbb",
|
|
183
192
|
"conformance/fixtures/plugin-missing-ui/notes/example.md": "55767f0aa1b6774546a99f28c58e7b732aa9cfa5dfce8d0326470f7f622f577e",
|
|
184
193
|
"conformance/fixtures/preamble-v1.txt": "1e0aeef224b64477bdc13a949c3ad402e68249caf499ecdba1302371677c068b",
|
|
185
|
-
"
|
|
194
|
+
"conformance/fixtures/sidecar-end-to-end/.claude/agents/orphan.sm": "53448213a36fe1b645903c025ddaeefc73ad58f41d2d370a7be84e5e0c964154",
|
|
195
|
+
"conformance/fixtures/sidecar-end-to-end/.claude/agents/stale.md": "cb3a95777cba530d47e6040c5601b6dcd34b5fc653dd69f183369eb6bdd956b5",
|
|
196
|
+
"conformance/fixtures/sidecar-end-to-end/.claude/agents/stale.sm": "50b7776099587decbb9f3b243d1314c7e10da8a9d0f0182043c692b637bf630e",
|
|
197
|
+
"conformance/fixtures/sidecar-example/agent-example.md": "1343ebc245e1fde415c16320ce53bcfad366ae2be1bcc7084337cfceaacdad38",
|
|
198
|
+
"conformance/fixtures/sidecar-example/agent-example.sm": "054aca442f9a11b02e5bb38d2847fe8730df1fb5f48e3d296af1592e902a7232",
|
|
199
|
+
"db-schema.md": "1e6480cf312e957619860fda9be9c2bf38de3392ef71eef94e755f987b667a55",
|
|
186
200
|
"interfaces/security-scanner.md": "4a982667008f233656f44c61ce9948e062432d3debdcbf7a134da03bd4139d7d",
|
|
187
201
|
"job-events.md": "8f371e0991816eca2e1a55cbd8a50733546ca5e7c861588048c18be1d22dbd57",
|
|
188
202
|
"job-lifecycle.md": "12bfc27690c92cf93682a3b6fbfeb7e2d252d33f704fd2d7de9a13db713e6281",
|
|
189
|
-
"plugin-author-guide.md": "
|
|
203
|
+
"plugin-author-guide.md": "f92e2d767e30bd6da36922105380475ae55831f64106f55b07f27a74389f138e",
|
|
190
204
|
"plugin-kv-api.md": "04b2178f46fb88adeae9240df9c9e1761b660396072001dac32cd402e11a2d7d",
|
|
191
205
|
"prompt-preamble.md": "fb40ab510234383326f198dec82cd6d744f28b7432eebac6cbfbb7ca1c483b7d",
|
|
192
|
-
"schemas/
|
|
206
|
+
"schemas/annotations.schema.json": "a500d61b638b013bc96e51530617e32c043a6e4f04ea39cc2f86bf355fef6fb0",
|
|
207
|
+
"schemas/api/rest-envelope.schema.json": "af631d809a98f9077d25cb5eb5a09d41d7d86d0e553c7ddbc3b3de275d782c2f",
|
|
208
|
+
"schemas/bump-report.schema.json": "c2d853715d5f50098567bc23382a4e81baf78d589c6e1baf67d3b841e7f7d8ae",
|
|
193
209
|
"schemas/conformance-case.schema.json": "7cd0f3aae5124f24be57cddb213d002d0466f79d06fd3da896075c8b28650410",
|
|
194
210
|
"schemas/execution-record.schema.json": "9628fa557cb856402f3a5f1d1167c609e46a197c850fe8171abfddd46c1028a8",
|
|
195
211
|
"schemas/extensions/action.schema.json": "262272175c06a2e33c08f819a45c3ef8260276c91a9d0542fdffc932aeb32db7",
|
|
196
|
-
"schemas/extensions/base.schema.json": "
|
|
212
|
+
"schemas/extensions/base.schema.json": "1e1ceed58e73155f79128f5f002a0b40982e20ace1f4618d4c5e4098af83aa82",
|
|
197
213
|
"schemas/extensions/extractor.schema.json": "122d3f81ef91edcde9798e7dc8fcbf442a2996deea65aa4b03c9d5cb01ba2519",
|
|
198
214
|
"schemas/extensions/formatter.schema.json": "2ab092aa37ae349c69b93071ed4f0e131affb7bb5799516ca82c721262631b36",
|
|
199
215
|
"schemas/extensions/hook.schema.json": "7465c38e0765edf23e49d4f96c539d04323f1cf564af1c60ee637c79a6d39239",
|
|
200
|
-
"schemas/extensions/provider.schema.json": "
|
|
216
|
+
"schemas/extensions/provider.schema.json": "599b6dabe26c65f67a53fb1ea59124bbbf52d3337a29303b6b0292a4ad58eb1a",
|
|
201
217
|
"schemas/extensions/rule.schema.json": "8ff420bde498f50db114c352305d487c71aef2dd746fd0c24976ff6a09865c22",
|
|
202
218
|
"schemas/frontmatter/base.schema.json": "88d906ec15e94543b919dd22b4ea4053e40024dc14068e6c7df09662db2f3350",
|
|
203
219
|
"schemas/history-stats.schema.json": "23f472d1de06d23fc775aabba821f8375f347af4dc8d89ba567980d61a11f9de",
|
|
204
220
|
"schemas/issue.schema.json": "40f6f8abadcce0fd8eac9df27ffcc20b2fc9fda6970142ddb8e7e56b1760b9b1",
|
|
205
221
|
"schemas/job.schema.json": "ffbdd51c54b487c44eb57fabd07f624ac1030c14ef69b46933c154092853a84c",
|
|
206
222
|
"schemas/link.schema.json": "0a95a24849a38b9ef5bad5361519a9f9e012b5bc3001289fad29d0851fceff6b",
|
|
207
|
-
"schemas/node.schema.json": "
|
|
223
|
+
"schemas/node.schema.json": "dea07210a2b97df7f3e5d1f7aa29a0b426ef276c7606e6c2f83192c4954a92c3",
|
|
208
224
|
"schemas/plugins-registry.schema.json": "5ca1d4970ae64f064f05c237a649d9f82d5edbeb7c121ec50cb4aaca13f4bc51",
|
|
209
225
|
"schemas/project-config.schema.json": "923aca314c40b3d0026bdf61a5c926a97170cd88e35627c51056e55b5ca6a6e4",
|
|
226
|
+
"schemas/report-base-deterministic.schema.json": "6f8b38c097994ee87e0639935c42b5e85d8ea4244959ca397978171b0d7d2222",
|
|
210
227
|
"schemas/report-base.schema.json": "a1021e9a59b4df9f99cd92454d797e88469766e7d49f52d231c4645ffdfdad8f",
|
|
211
228
|
"schemas/scan-result.schema.json": "d1a8782e198bc9bb92dad247437aefa1b02f92ff8dca8562eaf2348fd7c5cf0c",
|
|
229
|
+
"schemas/sidecar.schema.json": "418fe79eecd517df685e202b5ef29cf633256fd9f2d39130cf59033a30d1b270",
|
|
212
230
|
"schemas/summaries/agent.schema.json": "3d22558eeb170e00c4fc32018a810d27333cc632c9e528ff386100cfdfded087",
|
|
213
231
|
"schemas/summaries/command.schema.json": "2bffd606b24f7df9ccd13890af8725adfbfb8a2d7782fee1e0ac5250b9059117",
|
|
214
232
|
"schemas/summaries/hook.schema.json": "36f876f3b1a60d45be97a0848c79fd18744b434dfdcefc366f033b253d56268c",
|
|
215
|
-
"schemas/summaries/
|
|
233
|
+
"schemas/summaries/markdown.schema.json": "df8a4a883fc6674cbae93cbefffa3b115e00c0dd490e113e42e65a09cb0865d2",
|
|
216
234
|
"schemas/summaries/skill.schema.json": "f01bab92c51d64ee23e61587e42cf0dc5b37a2f518f5b12b3d1d456390338aa8",
|
|
217
235
|
"versioning.md": "996e62006423edc01151a6f7869605f76c5e1454cc30b38d9f616925b5bcfb64"
|
|
218
236
|
}
|