@skill-map/spec 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +788 -26
  2. package/README.md +11 -13
  3. package/architecture.md +118 -35
  4. package/cli-contract.md +38 -25
  5. package/conformance/README.md +42 -13
  6. package/conformance/cases/kernel-empty-boot.json +2 -2
  7. package/conformance/coverage.md +19 -23
  8. package/db-schema.md +61 -6
  9. package/index.json +34 -76
  10. package/job-events.md +75 -1
  11. package/package.json +1 -1
  12. package/plugin-author-guide.md +409 -51
  13. package/schemas/conformance-case.schema.json +3 -3
  14. package/schemas/execution-record.schema.json +8 -8
  15. package/schemas/extensions/action.schema.json +2 -2
  16. package/schemas/extensions/base.schema.json +5 -5
  17. package/schemas/extensions/extractor.schema.json +48 -0
  18. package/schemas/extensions/formatter.schema.json +29 -0
  19. package/schemas/extensions/hook.schema.json +44 -0
  20. package/schemas/extensions/provider.schema.json +51 -0
  21. package/schemas/extensions/rule.schema.json +1 -1
  22. package/schemas/frontmatter/base.schema.json +2 -2
  23. package/schemas/link.schema.json +4 -4
  24. package/schemas/node.schema.json +4 -4
  25. package/schemas/plugins-registry.schema.json +19 -4
  26. package/schemas/project-config.schema.json +2 -2
  27. package/schemas/scan-result.schema.json +3 -3
  28. package/conformance/cases/basic-scan.json +0 -17
  29. package/conformance/cases/orphan-detection.json +0 -22
  30. package/conformance/cases/rename-high.json +0 -21
  31. package/conformance/fixtures/minimal-claude/agents/reviewer.md +0 -16
  32. package/conformance/fixtures/minimal-claude/commands/status.md +0 -17
  33. package/conformance/fixtures/minimal-claude/hooks/pre-commit.md +0 -13
  34. package/conformance/fixtures/minimal-claude/notes/architecture.md +0 -11
  35. package/conformance/fixtures/minimal-claude/skills/hello.md +0 -22
  36. package/conformance/fixtures/orphan-after/skills/keep.md +0 -13
  37. package/conformance/fixtures/orphan-before/skills/keep.md +0 -13
  38. package/conformance/fixtures/orphan-before/skills/lonely.md +0 -13
  39. package/conformance/fixtures/rename-high-after/skills/bar.md +0 -14
  40. package/conformance/fixtures/rename-high-before/skills/foo.md +0 -14
  41. package/schemas/extensions/adapter.schema.json +0 -40
  42. package/schemas/extensions/audit.schema.json +0 -47
  43. package/schemas/extensions/detector.schema.json +0 -41
  44. package/schemas/extensions/renderer.schema.json +0 -29
  45. package/schemas/frontmatter/agent.schema.json +0 -17
  46. package/schemas/frontmatter/command.schema.json +0 -39
  47. package/schemas/frontmatter/hook.schema.json +0 -29
  48. package/schemas/frontmatter/note.schema.json +0 -11
  49. package/schemas/frontmatter/skill.schema.json +0 -37
@@ -1,22 +0,0 @@
1
- ---
2
- name: hello-skill
3
- description: A minimal skill that greets the user by name.
4
- metadata:
5
- version: 1.0.0
6
- stability: stable
7
- author: conformance
8
- tags: [example, greeting]
9
- ---
10
-
11
- # Hello skill
12
-
13
- This skill does one thing: it greets the user.
14
-
15
- ## Recipe
16
-
17
- 1. Ask the user's name.
18
- 2. Respond with "Hello, <name>".
19
-
20
- ## Preconditions
21
-
22
- - None.
@@ -1,13 +0,0 @@
1
- ---
2
- name: orphan-keep
3
- description: Fixture node that survives across before/after, so the after-state still has at least one node.
4
- metadata:
5
- version: 1.0.0
6
- stability: stable
7
- author: conformance
8
- ---
9
-
10
- # Survivor
11
-
12
- Keeps the after-state graph non-empty so we can assert that the orphan
13
- issue is the only one emitted.
@@ -1,13 +0,0 @@
1
- ---
2
- name: orphan-keep
3
- description: Fixture node that survives across before/after, so the after-state still has at least one node.
4
- metadata:
5
- version: 1.0.0
6
- stability: stable
7
- author: conformance
8
- ---
9
-
10
- # Survivor
11
-
12
- Keeps the after-state graph non-empty so we can assert that the orphan
13
- issue is the only one emitted.
@@ -1,13 +0,0 @@
1
- ---
2
- name: orphan-lonely
3
- description: Fixture node that gets deleted in the after-state to trigger the orphan path.
4
- metadata:
5
- version: 1.0.0
6
- stability: stable
7
- author: conformance
8
- ---
9
-
10
- # Orphan lonely body
11
-
12
- This file disappears in `orphan-after`. With no replacement matching
13
- its hashes, the rename heuristic emits an `orphan` issue.
@@ -1,14 +0,0 @@
1
- ---
2
- name: rename-high-foo
3
- description: Fixture node for the high-confidence rename conformance case.
4
- metadata:
5
- version: 1.0.0
6
- stability: stable
7
- author: conformance
8
- ---
9
-
10
- # Rename high body
11
-
12
- Body content kept identical between the before and after fixtures so
13
- the body hash matches across the rename. Move it to `bar.md` to trigger
14
- a high-confidence auto-rename.
@@ -1,14 +0,0 @@
1
- ---
2
- name: rename-high-foo
3
- description: Fixture node for the high-confidence rename conformance case.
4
- metadata:
5
- version: 1.0.0
6
- stability: stable
7
- author: conformance
8
- ---
9
-
10
- # Rename high body
11
-
12
- Body content kept identical between the before and after fixtures so
13
- the body hash matches across the rename. Move it to `bar.md` to trigger
14
- a high-confidence auto-rename.
@@ -1,40 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://skill-map.dev/spec/v0/extensions/adapter.schema.json",
4
- "title": "ExtensionAdapter",
5
- "description": "Manifest shape for an `Adapter` extension. An adapter recognizes a platform (Claude Code, Codex, Gemini, Obsidian vault, generic MD) and classifies each candidate file into a node `kind`. Exactly zero or one adapter MUST match any given file; multiple matches → the kernel emits an issue `adapter-ambiguous` and the file is left unclassified. Adapters are deterministic-only — they sit at the filesystem boundary and run during boot; probabilistic classification would make boot slow, costly, and non-reproducible. The `mode` field MUST NOT appear in adapter manifests. If you need LLM-assisted classification, write a probabilistic Detector that emits classification hints as `Link[]`. Stability: stable as of spec v1.0.0 except where noted.",
6
- "allOf": [
7
- { "$ref": "base.schema.json" }
8
- ],
9
- "type": "object",
10
- "required": ["id", "kind", "version", "emits", "defaultRefreshAction"],
11
- "unevaluatedProperties": false,
12
- "properties": {
13
- "kind": { "const": "adapter" },
14
- "emits": {
15
- "type": "array",
16
- "description": "Node kinds this adapter may classify files into.",
17
- "minItems": 1,
18
- "items": {
19
- "type": "string",
20
- "enum": ["skill", "agent", "command", "hook", "note"]
21
- }
22
- },
23
- "roots": {
24
- "type": "array",
25
- "description": "Path globs (relative to scope root) that this adapter SHOULD be consulted for. Advisory — the kernel walks all roots and consults every adapter regardless, but this field lets `sm doctor` warn when no file matched a specific adapter (i.e. the adapter was loaded for a platform that isn't in this scope).",
26
- "items": { "type": "string" }
27
- },
28
- "defaultRefreshAction": {
29
- "type": "object",
30
- "description": "Map from node `kind` to the action id the UI's probabilistic-refresh surface (`🧠 prob`) submits for that kind. MUST cover every kind listed in `emits`. Referenced action ids MUST resolve at load time; a dangling reference disables the adapter with status `invalid-manifest`.",
31
- "propertyNames": {
32
- "enum": ["skill", "agent", "command", "hook", "note"]
33
- },
34
- "additionalProperties": {
35
- "type": "string",
36
- "pattern": "^[a-z][a-z0-9]*(-[a-z0-9]+)*$"
37
- }
38
- }
39
- }
40
- }
@@ -1,47 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://skill-map.dev/spec/v0/extensions/audit.schema.json",
4
- "title": "ExtensionAudit",
5
- "description": "Manifest shape for an `Audit` extension. An audit is a hardcoded workflow that composes rules and actions into a single report. The audit's execution mode is NOT declared in the manifest — it is **derived** from the modes of the primitives it composes: if every composed primitive is `deterministic`, the audit's effective mode is `deterministic` and runs synchronously inside `sm audit <id>`; if any composed primitive is `probabilistic`, the audit's effective mode is `probabilistic` and dispatches as a queued job (`sm job submit audit:<id>`). Declaring `mode` in the manifest is a load-time error. See `architecture.md` §Execution modes for the full derivation contract.",
6
- "allOf": [
7
- { "$ref": "base.schema.json" }
8
- ],
9
- "type": "object",
10
- "required": ["id", "kind", "version", "composes", "reportSchemaRef"],
11
- "unevaluatedProperties": false,
12
- "properties": {
13
- "kind": { "const": "audit" },
14
- "composes": {
15
- "type": "array",
16
- "description": "Ordered list of rule and action references the audit executes in sequence. The kernel resolves each reference in the registry at load time; a dangling reference (id not found, kind mismatch, or primitive disabled) disables the audit with status `invalid-manifest`. Each composed primitive's `mode` participates in the audit's mode derivation.",
17
- "minItems": 1,
18
- "items": {
19
- "type": "object",
20
- "required": ["kind", "id"],
21
- "unevaluatedProperties": false,
22
- "properties": {
23
- "kind": { "type": "string", "enum": ["rule", "action"] },
24
- "id": { "type": "string" },
25
- "failFast": {
26
- "type": "boolean",
27
- "default": false,
28
- "description": "If true, the audit stops at the first error-severity issue this step emits. Default: collect everything and continue."
29
- }
30
- }
31
- }
32
- },
33
- "reportSchemaRef": {
34
- "type": "string",
35
- "description": "Reference to the JSON Schema of the audit's report shape. Probabilistic audits MUST extend `report-base.schema.json` (carries `safety` / `confidence` per the report-base contract). Deterministic audits MAY extend it but are not required to."
36
- },
37
- "exitCodeMap": {
38
- "type": "object",
39
- "description": "How the audit report maps to CLI exit codes. Absent → standard behaviour: exit 0 on pass, 1 on any error-severity issue, 2 on operational error.",
40
- "unevaluatedProperties": false,
41
- "properties": {
42
- "pass": { "type": "integer", "default": 0 },
43
- "fail": { "type": "integer", "default": 1 }
44
- }
45
- }
46
- }
47
- }
@@ -1,41 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://skill-map.dev/spec/v0/extensions/detector.schema.json",
4
- "title": "ExtensionDetector",
5
- "description": "Manifest shape for a `Detector` extension. A detector consumes a parsed node (frontmatter + body) and emits `Link[]` pointing to other nodes or to external URLs (the latter only if it is the designated URL-counter detector). Detectors run in isolation: they MUST NOT read other nodes, the graph, or the DB. Cross-node reasoning lives in Rules. Detectors are dual-mode: `deterministic` detectors run synchronously inside `sm scan`; `probabilistic` detectors invoke an LLM through the kernel's `RunnerPort` and execute only as queued jobs (never during scan). See `architecture.md` §Execution modes for the full contract.",
6
- "allOf": [
7
- { "$ref": "base.schema.json" }
8
- ],
9
- "type": "object",
10
- "required": ["id", "kind", "version", "emitsLinkKinds", "defaultConfidence"],
11
- "unevaluatedProperties": false,
12
- "properties": {
13
- "kind": { "const": "detector" },
14
- "mode": {
15
- "type": "string",
16
- "enum": ["deterministic", "probabilistic"],
17
- "default": "deterministic",
18
- "description": "`deterministic` (default): pure code, runs synchronously during `sm scan`. Same input → same output, every run. `probabilistic`: invokes an LLM via `ctx.runner` and runs only as a queued job (`sm job submit detector:<id>`); never participates in `sm scan`. The kernel rejects probabilistic detectors that try to register scan-time hooks at load time. Omitting the field is equivalent to declaring `deterministic`."
19
- },
20
- "emitsLinkKinds": {
21
- "type": "array",
22
- "description": "Subset of `Link.kind` values this detector is allowed to emit. Emitting an unlisted kind at runtime → kernel rejects the link and logs `detector-kind-violation`.",
23
- "minItems": 1,
24
- "items": {
25
- "type": "string",
26
- "enum": ["invokes", "references", "mentions", "supersedes"]
27
- }
28
- },
29
- "defaultConfidence": {
30
- "type": "string",
31
- "enum": ["high", "medium", "low"],
32
- "description": "Confidence attached to emitted links by default. Detectors MAY override per-link at emission time."
33
- },
34
- "scope": {
35
- "type": "string",
36
- "enum": ["frontmatter", "body", "both"],
37
- "default": "both",
38
- "description": "Which part of the node this detector consumes. The kernel passes only the declared scope to the detector — a `frontmatter` detector that tries to read `body` receives an empty string."
39
- }
40
- }
41
- }
@@ -1,29 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://skill-map.dev/spec/v0/extensions/renderer.schema.json",
4
- "title": "ExtensionRenderer",
5
- "description": "Manifest shape for a `Renderer` extension. A renderer serializes the graph (or a filtered subgraph) into a string in a declared format. Renderers are invoked by `sm graph --format <format>` and `sm export`. Renderers are deterministic-only — they sit at the graph-to-string boundary and their output MUST be byte-deterministic for the same input graph (the snapshot-test suite relies on this). The `mode` field MUST NOT appear in renderer manifests. Probabilistic narrators of the graph are a valid product but they live in jobs and emit Findings, not in renderers.",
6
- "allOf": [
7
- { "$ref": "base.schema.json" }
8
- ],
9
- "type": "object",
10
- "required": ["id", "kind", "version", "format"],
11
- "unevaluatedProperties": false,
12
- "properties": {
13
- "kind": { "const": "renderer" },
14
- "format": {
15
- "type": "string",
16
- "description": "Format identifier consumed by `--format`. Built-in set: `ascii`, `mermaid`, `dot`, `json`. Third-party renderers MAY register new format ids; collisions are a load-time error."
17
- },
18
- "contentType": {
19
- "type": "string",
20
- "description": "MIME-like hint used by the Server when streaming rendered output over HTTP (e.g. `text/plain`, `image/svg+xml`, `application/json`). Advisory.",
21
- "default": "text/plain"
22
- },
23
- "supportsFilter": {
24
- "type": "boolean",
25
- "default": true,
26
- "description": "If true, the renderer accepts the `--filter` expression used by `sm export`. If false, `sm export --format <this>` rejects `--filter` with exit 2."
27
- }
28
- }
29
- }
@@ -1,17 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://skill-map.dev/spec/v0/frontmatter/agent.schema.json",
4
- "title": "FrontmatterAgent",
5
- "description": "Frontmatter shape for nodes classified as `agent`. Extends `base.schema.json`. Kind-specific field: `model`. The `tools` and `allowedTools` fields live on `base` and apply here unchanged (see `base.schema.json`). Color, when needed, lives in `metadata.color` (inherited from base).",
6
- "allOf": [
7
- { "$ref": "base.schema.json" }
8
- ],
9
- "type": "object",
10
- "additionalProperties": true,
11
- "properties": {
12
- "model": {
13
- "type": "string",
14
- "description": "Model identifier for this agent (e.g. `sonnet`, `opus`, `haiku`, or a full `claude-*` id). Free-form string; adapters MAY validate against a platform-specific enum."
15
- }
16
- }
17
- }
@@ -1,39 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://skill-map.dev/spec/v0/frontmatter/command.schema.json",
4
- "title": "FrontmatterCommand",
5
- "description": "Frontmatter shape for nodes classified as `command`. Extends `base.schema.json`. Kind-specific fields: `args`, `shortcut`.",
6
- "allOf": [
7
- { "$ref": "base.schema.json" }
8
- ],
9
- "type": "object",
10
- "additionalProperties": true,
11
- "properties": {
12
- "args": {
13
- "type": "array",
14
- "description": "Declared positional / named arguments for this command.",
15
- "items": { "$ref": "#/$defs/CommandArg" }
16
- },
17
- "shortcut": {
18
- "type": "string",
19
- "description": "Keyboard shortcut hint. Platform-specific notation (e.g. `cmd+shift+k`, `ctrl+alt+m`). Purely advisory."
20
- }
21
- },
22
- "$defs": {
23
- "CommandArg": {
24
- "type": "object",
25
- "required": ["name"],
26
- "additionalProperties": true,
27
- "properties": {
28
- "name": { "type": "string", "minLength": 1 },
29
- "type": {
30
- "type": "string",
31
- "description": "Free-form type hint (e.g. `string`, `integer`, `path`, `boolean`, `enum:a|b|c`)."
32
- },
33
- "required": { "type": "boolean", "default": false },
34
- "description": { "type": "string" },
35
- "default": { "description": "Any JSON value." }
36
- }
37
- }
38
- }
39
- }
@@ -1,29 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://skill-map.dev/spec/v0/frontmatter/hook.schema.json",
4
- "title": "FrontmatterHook",
5
- "description": "Frontmatter shape for nodes classified as `hook`. Extends `base.schema.json`. Kind-specific fields: `event`, `condition`, `blocking`, `idempotent`.",
6
- "allOf": [
7
- { "$ref": "base.schema.json" }
8
- ],
9
- "type": "object",
10
- "additionalProperties": true,
11
- "properties": {
12
- "event": {
13
- "type": "string",
14
- "description": "Event name this hook reacts to (e.g. `PreToolUse`, `PostToolUse`, `SubagentStop`, `SessionStart`). Platform-specific enum; adapters MAY validate."
15
- },
16
- "condition": {
17
- "type": "string",
18
- "description": "Free-form predicate expression evaluated by the host. Syntax is platform-specific; the spec does not constrain it."
19
- },
20
- "blocking": {
21
- "type": "boolean",
22
- "description": "When true, the host MUST wait for the hook to finish before proceeding. When false, the hook runs fire-and-forget."
23
- },
24
- "idempotent": {
25
- "type": "boolean",
26
- "description": "Author-declared: executing twice with the same inputs produces the same result. Consumed by runners for retry and dedup."
27
- }
28
- }
29
- }
@@ -1,11 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://skill-map.dev/spec/v0/frontmatter/note.schema.json",
4
- "title": "FrontmatterNote",
5
- "description": "Frontmatter shape for nodes classified as `note`. Extends `base.schema.json` with no additional fields. Exists so that every kind has a matching schema for uniform routing.",
6
- "allOf": [
7
- { "$ref": "base.schema.json" }
8
- ],
9
- "type": "object",
10
- "additionalProperties": true
11
- }
@@ -1,37 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://skill-map.dev/spec/v0/frontmatter/skill.schema.json",
4
- "title": "FrontmatterSkill",
5
- "description": "Frontmatter shape for nodes classified as `skill`. Extends `base.schema.json`. Kind-specific fields: `inputs`, `outputs`. Stability: experimental — the parameter shape may tighten once summarizer needs emerge.",
6
- "allOf": [
7
- { "$ref": "base.schema.json" }
8
- ],
9
- "type": "object",
10
- "additionalProperties": true,
11
- "properties": {
12
- "inputs": {
13
- "type": "array",
14
- "description": "Declared inputs for this skill. Optional structured. Stability: experimental.",
15
- "items": { "$ref": "#/$defs/Parameter" }
16
- },
17
- "outputs": {
18
- "type": "array",
19
- "description": "Declared outputs. Optional structured. Stability: experimental.",
20
- "items": { "$ref": "#/$defs/Parameter" }
21
- }
22
- },
23
- "$defs": {
24
- "Parameter": {
25
- "type": "object",
26
- "required": ["name"],
27
- "additionalProperties": true,
28
- "properties": {
29
- "name": { "type": "string", "minLength": 1 },
30
- "type": { "type": "string", "description": "Free-form type hint (e.g. `string`, `integer`, `path`, `glob`)." },
31
- "description": { "type": "string" },
32
- "required": { "type": "boolean", "default": false },
33
- "default": { "description": "Any JSON value, or a templated string." }
34
- }
35
- }
36
- }
37
- }