@skill-map/spec 0.24.3 → 0.26.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 +52 -0
- package/README.md +1 -1
- package/architecture.md +1 -1
- package/cli-contract.md +14 -7
- package/conformance/fixtures/sidecar-example/agent-example.sm +0 -4
- package/index.json +8 -8
- package/package.json +1 -1
- package/plugin-author-guide.md +1 -1
- package/schemas/annotations.schema.json +1 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,57 @@
|
|
|
1
1
|
# Spec changelog
|
|
2
2
|
|
|
3
|
+
## 0.26.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 48800d4: Drop `requires`, `related`, and `conflictsWith` from the curated annotation catalog.
|
|
8
|
+
|
|
9
|
+
The three fields collapsed into the same edge kind (`references`), which made it impossible to tell from the graph whether an arrow meant "depends on", "is in conflict with", or "soft-related". The catalog now ships 10 fields instead of 13: versioning + supersession (`version`, `stability`, `supersedes`, `supersededBy`), provenance (`authors`, `license`, `source`, `sourceVersion`), taxonomy (`tags`), and docs (`docsUrl`).
|
|
10
|
+
|
|
11
|
+
The extractor `core/annotations` now declares `emitsLinkKinds: ['supersedes']` (no longer emits `references` from the sidecar). Path-style `references` edges still surface from `core/markdown-link` over `[text](path)` syntax in the body.
|
|
12
|
+
|
|
13
|
+
The schema keeps `additionalProperties: true`, so sidecars that still carry `requires` / `related` / `conflictsWith` continue to parse without errors, but those keys produce no edges and the built-in `unknown-field` analyzer surfaces them as warnings.
|
|
14
|
+
|
|
15
|
+
## User-facing
|
|
16
|
+
|
|
17
|
+
The `.sm` annotation catalog shrinks from 13 to 10 fields. `requires`, `related`, and `conflictsWith` were dropped, their edges all rendered as plain `references` and added no extra meaning. Existing sidecars keep working; the three keys are now flagged by `unknown-field`.
|
|
18
|
+
|
|
19
|
+
## 0.25.0
|
|
20
|
+
|
|
21
|
+
### Minor Changes
|
|
22
|
+
|
|
23
|
+
- a53532b: Replace BYTES with TOKENS in the human-mode output of `sm list` and `sm show`. Tokens are the metric users actually care about for LLM budgeting; bytes were a leftover from the early file-size mental model.
|
|
24
|
+
|
|
25
|
+
**CLI changes (`@skill-map/cli`)**:
|
|
26
|
+
|
|
27
|
+
- `sm list` table swaps the `BYTES` column for `TOKENS`. The value comes from `node.tokens?.total` (cl100k_base counts already populated by the kernel during `sm scan`). Nodes scanned with `--no-tokens` render the cell as `-`.
|
|
28
|
+
- `sm list --sort-by bytes_total` is **removed**, renamed to `--sort-by tokens_total`. Passing the old key now fails fast with the standard "invalid sort field" error listing the allowed values. The defensive whitelist in `kernel/adapters/sqlite/storage-adapter.ts` (`SORT_BY_COLUMNS` / `SORT_BY_DEFAULT_DIRECTION`) follows the same rename.
|
|
29
|
+
- `sm show` no longer renders the `Bytes:` field. The `Tokens:` field is now always present (`-` when the scan ran with `--no-tokens`) instead of being conditional on token availability. Field-block doc comments updated.
|
|
30
|
+
- Help text and the `examples` array on `sm list` reworded ("Top 5 by total tokens").
|
|
31
|
+
|
|
32
|
+
**Untouched surfaces** (DB shape, JSON output, internal tie-breakers):
|
|
33
|
+
|
|
34
|
+
- `scan_nodes.bytes_*` columns stay in the schema, no migration.
|
|
35
|
+
- `node-build.ts` still computes both `bytes` and `tokens` on every scan.
|
|
36
|
+
- `sm list --json` and `sm show --json` keep emitting Node objects conforming to `node.schema.json`, which still carries both `bytes` and `tokens`. Only the human-mode rendering changed.
|
|
37
|
+
- `sm export` keeps using `bytes` as the deterministic internal tie-breaker (invisible to the user).
|
|
38
|
+
|
|
39
|
+
**Spec change (`@skill-map/spec`)**:
|
|
40
|
+
|
|
41
|
+
- `spec/cli-contract.md` (`sm show` row): "weight (bytes/tokens triple-split)" → "weight (tokens triple-split)". A conforming implementation no longer has to render the `Bytes:` field on `sm show`. Pre-1.0 breaking, treated as minor per `spec/versioning.md` § Pre-1.0.
|
|
42
|
+
|
|
43
|
+
Tests updated: `src/test/scan-readers.test.ts` swaps `sortBy: 'bytes_total'` for `'tokens_total'` and asserts `\bTokens\b` (instead of `\bBytes\b`) in the `sm show` human output.
|
|
44
|
+
|
|
45
|
+
## User-facing
|
|
46
|
+
|
|
47
|
+
**`sm list` and `sm show` now report tokens, not bytes.** The `BYTES` column on `sm list` is now `TOKENS` (cl100k_base, frontmatter + body), and `sm show` lists `Tokens:` instead of `Bytes:`. Sort with `--sort-by tokens_total`. `--json` is unchanged.
|
|
48
|
+
|
|
49
|
+
- 2129b40: Add an optional positional `variant` argument to `sm tutorial`. Default (no argument) keeps the previous behaviour and materializes `<cwd>/sm-tutorial.md` (the basic walkthrough). Passing `master` materializes `<cwd>/sm-master.md` (the advanced walkthrough: plugin tour, plugin authoring, settings + view-slots) through the same channel. The value is validated against the closed set `{ tutorial, master }`; anything else exits with code 2 and an `invalidVariant` error pointing at the valid values. The build pipeline (`tsup.config.ts → onSuccess`) now copies both SKILL.md sources into `dist/cli/tutorial/`, and the runtime resolver caches each variant independently. CLI i18n strings under `tutorial.texts.ts` were parameterized with a `{{filename}}` placeholder so the success block points the tester at whichever file was materialised. Spec § `sm tutorial` was rewritten to document the new positional and exit-code rule.
|
|
50
|
+
|
|
51
|
+
## User-facing
|
|
52
|
+
|
|
53
|
+
**`sm tutorial master`** materializes the advanced tester walkthrough (`sm-master.md`) in your cwd. Trigger it from Claude Code with `ejecutá @sm-master.md`. Bare `sm tutorial` keeps its previous behaviour and writes `sm-tutorial.md`.
|
|
54
|
+
|
|
3
55
|
## 0.24.3
|
|
4
56
|
|
|
5
57
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ These are implementation decisions. The reference impl picks them (see [`../AGEN
|
|
|
39
39
|
Two analyzers govern every identifier in the spec. They are **normative**.
|
|
40
40
|
|
|
41
41
|
- **Filesystem artefacts use kebab-case.** Every file and directory in `spec/` (and in any conforming implementation), `scan-result.schema.json`, `job-lifecycle.md`, `report-base.schema.json`, `auto-rename-medium` (as an `issue.analyzerId` value), `direct-override` (as a `safety.injectionType` enum value), and so on, is kebab-case lowercase. Enum values and issue analyzer ids follow the same convention so they can be echoed back into URLs, filenames, and log keys without escaping.
|
|
42
|
-
- **JSON content uses camelCase.** Every key inside a JSON Schema, frontmatter block, config file, plugin manifest, action manifest, job record, report, event payload, or API response is camelCase: `whatItDoes`, `injectionDetected`, `expectedTools`, `
|
|
42
|
+
- **JSON content uses camelCase.** Every key inside a JSON Schema, frontmatter block, config file, plugin manifest, action manifest, job record, report, event payload, or API response is camelCase: `whatItDoes`, `injectionDetected`, `expectedTools`, `supersededBy`, `docsUrl`, `examplesUrl`, `ttlSeconds`, `runId`, `jobId`. This matches the JS/TS ecosystem the reference impl ships in and the Kysely `CamelCasePlugin` that bridges to the `snake_case` SQL layer, but the analyzer is spec-level, not implementation-level: an alternative implementation in any language still exposes camelCase JSON keys.
|
|
43
43
|
|
|
44
44
|
The SQL persistence layer is the sole exception: tables, columns, and migration filenames use `snake_case` (see `db-schema.md`). That boundary is crossed only inside a storage adapter; nothing that leaves the kernel should ever be `snake_case`.
|
|
45
45
|
|
package/architecture.md
CHANGED
|
@@ -476,7 +476,7 @@ Skill-map's own metadata layer (versioning, supersession, provenance, taxonomy,
|
|
|
476
476
|
Two schemas describe the wire shape:
|
|
477
477
|
|
|
478
478
|
- [`schemas/sidecar.schema.json`](./schemas/sidecar.schema.json), root shape with reserved blocks `identity` (anchor + drift hashes), `annotations` (the conventional catalog), `settings` (reserved), `audit` (write trail), plus opt-in `<plugin-id>:` namespacing.
|
|
479
|
-
- [`schemas/annotations.schema.json`](./schemas/annotations.schema.json), curated
|
|
479
|
+
- [`schemas/annotations.schema.json`](./schemas/annotations.schema.json), curated 10-field catalog: 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:`. `additionalProperties: true` so plugins or users add custom keys without coordination; the built-in `unknown-field` analyzer warns on truly unrecognized keys (typo guard).
|
|
480
480
|
|
|
481
481
|
### Identity and drift
|
|
482
482
|
|
package/cli-contract.md
CHANGED
|
@@ -104,18 +104,25 @@ Flags: `--no-scan` (skip the first scan), `--force` (rewrite an existing config)
|
|
|
104
104
|
|
|
105
105
|
Exit: 0 on success, 2 on failure.
|
|
106
106
|
|
|
107
|
-
#### `sm tutorial`
|
|
107
|
+
#### `sm tutorial [variant]`
|
|
108
108
|
|
|
109
|
-
Materialize
|
|
109
|
+
Materialize an interactive tester tutorial as a single `.md` file in the current working directory. Companion to the `sm-tutorial` and `sm-master` Claude Code skills: a tester drops into an empty directory, runs `sm tutorial` (or `sm tutorial master`) to seed the tutorial source, then opens Claude Code there and triggers the skill (which reads the file as its onboarding payload).
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
The optional positional `variant` argument selects which skill gets materialised. Valid values are:
|
|
112
|
+
|
|
113
|
+
- `tutorial` (default, also the behaviour when no argument is passed): writes `<cwd>/sm-tutorial.md`, the basic onboarding walkthrough.
|
|
114
|
+
- `master`: writes `<cwd>/sm-master.md`, the advanced walkthrough (plugin tour, plugin authoring, settings + view-slots).
|
|
115
|
+
|
|
116
|
+
Common behaviour for both variants:
|
|
117
|
+
|
|
118
|
+
- Writes the chosen file at the top level (single file, no subdirectory).
|
|
119
|
+
- Content is the canonical `SKILL.md` shipped with the implementation. Any conforming implementation MUST embed equivalent tutorial sources (the prose itself is informative; what is normative is that the verb produces a single readable file at the chosen path that a Claude Code skill can consume).
|
|
113
120
|
- Does NOT require an initialized project, runs in any directory, including empty ones, and never reads or writes `.skill-map/`.
|
|
114
121
|
- Is NOT scope-aware: `-g` is accepted (inherited global flag) but has no effect; the file is always written under the cwd.
|
|
115
122
|
|
|
116
|
-
Flags: `--force` (overwrite
|
|
123
|
+
Flags: `--force` (overwrite the existing target file, whichever variant was selected, without prompting).
|
|
117
124
|
|
|
118
|
-
Exit: `0` on success; `2` if
|
|
125
|
+
Exit: `0` on success; `2` if the target file already exists and `--force` was not passed (operational error, refusing to clobber); `2` if the positional `variant` is set to a value other than `tutorial` or `master`; `2` on any I/O failure.
|
|
119
126
|
|
|
120
127
|
#### `sm version`
|
|
121
128
|
|
|
@@ -239,7 +246,7 @@ Exit: 0 on clean (or clean watcher shutdown), 1 if error-severity issues exist (
|
|
|
239
246
|
| Command | Purpose |
|
|
240
247
|
|---|---|
|
|
241
248
|
| `sm list [--kind <k>] [--issue] [--sort-by ...] [--limit N]` | Tabular listing. `--json` emits an array conforming to `node.schema.json`. |
|
|
242
|
-
| `sm show <node.path>` | Node detail: weight (
|
|
249
|
+
| `sm show <node.path>` | Node detail: weight (tokens triple-split), frontmatter, links in/out, issues, findings, summary. `--json` emits a detail object with the raw link rows. Pretty output groups identical-shape links (same endpoint, kind, normalized trigger) onto one line and lists the union of extractor ids in a `sources:` field; the section header reports both the raw row count and the unique-after-grouping count, e.g. `Links out (12, 9 unique)`. Storage keeps one row per extractor (`scan_links` is unchanged), the grouping is purely a read-time presentation choice. |
|
|
243
250
|
| `sm check [-n <node.path>] [--analyzers <ids>] [--include-prob] [--async]` | Print all current issues. Equivalent to `sm scan --json \| jq '.issues'` but faster (reads from DB). `-n` restricts to issues whose `nodeIds` include the path; `--analyzers <ids>` accepts a comma-separated list of qualified or short analyzer ids and restricts the issue read accordingly. Default behaviour is deterministic-only (CI-safe, status quo). `--include-prob` is the opt-in flag for probabilistic Analyzer dispatch (spec § A.7): the verb loads the plugin runtime, finds Analyzers with `mode === 'probabilistic'` (filtered by `--analyzers` if set), and emits a stderr advisory naming the analyzer ids. Full prob dispatch requires the job subsystem (Step 10); until then `--include-prob` is a stub, prob analyzers never produce issues, never alter the exit code, and `--async` (reserved companion: returns job ids without waiting once jobs land) is a no-op the advisory simply mentions. The flag does NOT extend to `sm scan` or `sm list`. |
|
|
244
251
|
| `sm findings [--kind ...] [--since ...] [--threshold <n>]` | Probabilistic findings (injection, stale summaries, low confidence). `--json` emits an array of finding objects. |
|
|
245
252
|
| `sm graph [--format ascii\|mermaid\|dot\|json]` | Render the full graph via the named formatter. `--format json` is the built-in JSON formatter: stringifies the persisted `ScanResult` ([`scan-result.schema.json`](./schemas/scan-result.schema.json)), byte-equivalent to `sm scan --json` modulo whitespace. The global `--json` flag is ignored on `sm graph` (formats are picked via `--format`, never via the global flag). |
|
package/index.json
CHANGED
|
@@ -174,14 +174,14 @@
|
|
|
174
174
|
}
|
|
175
175
|
]
|
|
176
176
|
},
|
|
177
|
-
"specPackageVersion": "0.
|
|
177
|
+
"specPackageVersion": "0.26.0",
|
|
178
178
|
"integrity": {
|
|
179
179
|
"algorithm": "sha256",
|
|
180
180
|
"files": {
|
|
181
|
-
"CHANGELOG.md": "
|
|
182
|
-
"README.md": "
|
|
183
|
-
"architecture.md": "
|
|
184
|
-
"cli-contract.md": "
|
|
181
|
+
"CHANGELOG.md": "bf7a717c1172be2c19399c578d7e49a0b1ca9f007e7cf7dd24e0b15f450fb2ef",
|
|
182
|
+
"README.md": "54c4649fa9742bf2f74423ea78788a7474ce09649cbe1e72a270b606cf16a0a5",
|
|
183
|
+
"architecture.md": "9b6bf2b964d5969da395596d29e332b0f59e4d258802ae2204afee6b01ad3a5d",
|
|
184
|
+
"cli-contract.md": "461e8eaa29600edaf2637ef1fa5fda1412efdd3c7b253e5c7aacb7ce8d414f0c",
|
|
185
185
|
"conformance/README.md": "7a0f6d6a4057349d35004c68c92bacd6528bb7489ad942406a035be1b84bf360",
|
|
186
186
|
"conformance/cases/kernel-empty-boot.json": "2a5be9c93143d07a16d998df09dcc8fa4ea2d2f9a0bff6417573ed5a770352c1",
|
|
187
187
|
"conformance/cases/orphan-markdown-fallback.json": "8ef6e49b7e6532bd845d9f54974a16e537cf98d355f0c5e4f4fb06abac3adcc5",
|
|
@@ -198,15 +198,15 @@
|
|
|
198
198
|
"conformance/fixtures/sidecar-end-to-end/.claude/agents/stale.md": "cb3a95777cba530d47e6040c5601b6dcd34b5fc653dd69f183369eb6bdd956b5",
|
|
199
199
|
"conformance/fixtures/sidecar-end-to-end/.claude/agents/stale.sm": "cb04f7f3103b4218b09fd4da92f7ea429588b04c1dac6a9547ce362263b11224",
|
|
200
200
|
"conformance/fixtures/sidecar-example/agent-example.md": "741131403e8c9580d0b7a8c2446cb4502d01f80053b7a2092663de92431aaa82",
|
|
201
|
-
"conformance/fixtures/sidecar-example/agent-example.sm": "
|
|
201
|
+
"conformance/fixtures/sidecar-example/agent-example.sm": "8329950d49c69a1199bbe6c06e32b8513973e64207b0db8756b67301e6a1f1e2",
|
|
202
202
|
"db-schema.md": "ff792e4b8d4fcd122e43cf7718b72b7780aaefadc6f839441bdc06fa89197d7c",
|
|
203
203
|
"interfaces/security-scanner.md": "e8049712b9cf7a07c786bf19f8f775f8ef9638f063f7fba5c7a8b1431b92f38e",
|
|
204
204
|
"job-events.md": "84206168ac12b536d34470d62f8c8cba95dab181fee66d23203c2cf5dfbee716",
|
|
205
205
|
"job-lifecycle.md": "9c429121f98a07c8795f8979ed1abc5e5334e3f89db51585a8da55c527ef855b",
|
|
206
|
-
"plugin-author-guide.md": "
|
|
206
|
+
"plugin-author-guide.md": "baf6f97b24b2376fb1abe6561c0ab000f0cc7772a2a022bd977f16cb6887ad43",
|
|
207
207
|
"plugin-kv-api.md": "1acc69ed82433a74e35ada61d63a6d7379fb61046ff83de1e0facbe884c64704",
|
|
208
208
|
"prompt-preamble.md": "9dd4f6d1bc6a425f8782fcee10cbe75909e8d64e28781fda56c2fae909b02f40",
|
|
209
|
-
"schemas/annotations.schema.json": "
|
|
209
|
+
"schemas/annotations.schema.json": "e39990d47f53e25a1b3a5587a5714486d0b819b8eeaac10d42783a675296aee1",
|
|
210
210
|
"schemas/api/rest-envelope.schema.json": "bf735dbea44725545a33c001c08bf9b0395995f71c70d46a4cc215d276e19038",
|
|
211
211
|
"schemas/bump-report.schema.json": "c2d853715d5f50098567bc23382a4e81baf78d589c6e1baf67d3b841e7f7d8ae",
|
|
212
212
|
"schemas/conformance-case.schema.json": "f6d4c9fb92e79cb516eeeb9d042223572a3bd5ff8e7871a0becce13916f20cf6",
|
package/package.json
CHANGED
package/plugin-author-guide.md
CHANGED
|
@@ -815,7 +815,7 @@ This is the only fatal path on the plugin-load surface. Every other failure mode
|
|
|
815
815
|
|
|
816
816
|
The built-in `core/unknown-field` Analyzer walks every parsed `.sm` and emits a `warn` issue per truly-unknown key. Three surfaces are checked:
|
|
817
817
|
|
|
818
|
-
1. Inside `annotations:`, keys not in `annotations.schema.json`'s curated catalog (the
|
|
818
|
+
1. Inside `annotations:`, keys not in `annotations.schema.json`'s curated catalog (the 10 conventional fields). Plugins do NOT contribute to `annotations:`; that block is skill-map-curated.
|
|
819
819
|
2. At the sidecar root, keys outside the four reserved blocks (`for`, `annotations`, `settings`, `audit`) that are also NOT a registered plugin namespace `<plugin-id>:` AND NOT a registered `location: 'root'` contribution.
|
|
820
820
|
3. Inside a registered `<plugin-id>:` namespace, values that fail the schema declared by the owning plugin's `annotationContributions[<key>].schema`.
|
|
821
821
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://skill-map.dev/spec/v0/annotations.schema.json",
|
|
4
4
|
"title": "Annotations",
|
|
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
|
|
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",
|
|
7
7
|
"additionalProperties": true,
|
|
8
8
|
"properties": {
|
|
@@ -26,21 +26,6 @@
|
|
|
26
26
|
"minLength": 1,
|
|
27
27
|
"description": "Path (relative to scope root) of the node that replaces this one. When set, the current node is end-of-life and consumers should migrate."
|
|
28
28
|
},
|
|
29
|
-
"requires": {
|
|
30
|
-
"type": "array",
|
|
31
|
-
"items": { "type": "string", "minLength": 1 },
|
|
32
|
-
"description": "Paths (relative to scope root) of nodes this node depends on. Surfaces in the dependency graph; the `broken-ref` analyzer flags missing targets."
|
|
33
|
-
},
|
|
34
|
-
"conflictsWith": {
|
|
35
|
-
"type": "array",
|
|
36
|
-
"items": { "type": "string", "minLength": 1 },
|
|
37
|
-
"description": "Paths (relative to scope root) of nodes that cannot be active alongside this one. Surfaces in conflict detection (post-v0.5.0)."
|
|
38
|
-
},
|
|
39
|
-
"related": {
|
|
40
|
-
"type": "array",
|
|
41
|
-
"items": { "type": "string", "minLength": 1 },
|
|
42
|
-
"description": "Paths (relative to scope root) of conceptually related nodes. Soft link for navigation; no strong semantics, no analyzer enforcement."
|
|
43
|
-
},
|
|
44
29
|
"authors": {
|
|
45
30
|
"type": "array",
|
|
46
31
|
"items": { "type": "string", "minLength": 1 },
|