@skill-map/spec 0.1.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 +96 -0
- package/README.md +105 -0
- package/architecture.md +218 -0
- package/cli-contract.md +336 -0
- package/conformance/README.md +140 -0
- package/conformance/cases/basic-scan.json +17 -0
- package/conformance/cases/kernel-empty-boot.json +24 -0
- package/conformance/fixtures/minimal-claude/agents/reviewer.md +16 -0
- package/conformance/fixtures/minimal-claude/commands/status.md +17 -0
- package/conformance/fixtures/minimal-claude/hooks/pre-commit.md +13 -0
- package/conformance/fixtures/minimal-claude/notes/architecture.md +11 -0
- package/conformance/fixtures/minimal-claude/skills/hello.md +22 -0
- package/conformance/fixtures/preamble-v1.txt +54 -0
- package/db-schema.md +359 -0
- package/dispatch-lifecycle.md +213 -0
- package/index.json +205 -0
- package/interfaces/security-scanner.md +233 -0
- package/job-events.md +322 -0
- package/package.json +49 -0
- package/plugin-kv-api.md +208 -0
- package/prompt-preamble.md +152 -0
- package/schemas/conformance-case.schema.json +185 -0
- package/schemas/execution-record.schema.json +88 -0
- package/schemas/frontmatter/agent.schema.json +22 -0
- package/schemas/frontmatter/base.schema.json +136 -0
- package/schemas/frontmatter/command.schema.json +39 -0
- package/schemas/frontmatter/hook.schema.json +29 -0
- package/schemas/frontmatter/note.schema.json +11 -0
- package/schemas/frontmatter/skill.schema.json +37 -0
- package/schemas/issue.schema.json +54 -0
- package/schemas/job.schema.json +75 -0
- package/schemas/link.schema.json +66 -0
- package/schemas/node.schema.json +95 -0
- package/schemas/plugins-registry.schema.json +99 -0
- package/schemas/project-config.schema.json +87 -0
- package/schemas/report-base.schema.json +41 -0
- package/schemas/scan-result.schema.json +71 -0
- package/schemas/summaries/agent.schema.json +46 -0
- package/schemas/summaries/command.schema.json +50 -0
- package/schemas/summaries/hook.schema.json +43 -0
- package/schemas/summaries/note.schema.json +37 -0
- package/schemas/summaries/skill.schema.json +57 -0
- package/versioning.md +94 -0
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://skill-map.dev/spec/v0/issue.schema.json",
|
|
4
|
+
"title": "Issue",
|
|
5
|
+
"description": "Deterministic finding emitted by a rule when evaluating the graph. Not to be confused with `Finding`, which is probabilistic (LLM-produced).",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["ruleId", "severity", "nodeIds", "message"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"ruleId": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"pattern": "^[a-z][a-z0-9]*(-[a-z0-9]+)*$",
|
|
13
|
+
"description": "Kebab-case identifier of the rule that emitted this issue (e.g. `trigger-collision`, `broken-ref`, `superseded`)."
|
|
14
|
+
},
|
|
15
|
+
"severity": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"enum": ["error", "warn", "info"],
|
|
18
|
+
"description": "Severity level. `info` is emitted by `--strict` mode for recommendations."
|
|
19
|
+
},
|
|
20
|
+
"nodeIds": {
|
|
21
|
+
"type": "array",
|
|
22
|
+
"description": "`node.path` values involved in this issue. Most rules emit 1 or 2; trigger-collision may emit N. Field name uses `id` generically to remain stable across future identifier changes.",
|
|
23
|
+
"minItems": 1,
|
|
24
|
+
"items": { "type": "string" }
|
|
25
|
+
},
|
|
26
|
+
"linkIndices": {
|
|
27
|
+
"type": "array",
|
|
28
|
+
"description": "Optional indices into the sibling `links[]` array (in the same scan result) that the issue refers to.",
|
|
29
|
+
"items": { "type": "integer", "minimum": 0 }
|
|
30
|
+
},
|
|
31
|
+
"message": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"description": "Short one-line description, human-readable."
|
|
34
|
+
},
|
|
35
|
+
"detail": {
|
|
36
|
+
"type": ["string", "null"],
|
|
37
|
+
"description": "Longer explanation, markdown-friendly. Optional."
|
|
38
|
+
},
|
|
39
|
+
"fix": {
|
|
40
|
+
"type": ["object", "null"],
|
|
41
|
+
"description": "Machine-readable fix hint. Stability: experimental — shape may change before v1.",
|
|
42
|
+
"additionalProperties": false,
|
|
43
|
+
"properties": {
|
|
44
|
+
"summary": { "type": "string" },
|
|
45
|
+
"autofixable": { "type": "boolean" }
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"data": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"description": "Rule-specific structured payload (e.g. the colliding trigger string, the missing target). Free-form.",
|
|
51
|
+
"additionalProperties": true
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://skill-map.dev/spec/v0/job.schema.json",
|
|
4
|
+
"title": "Job",
|
|
5
|
+
"description": "Row in `state_jobs`. Non-terminal state until it reaches `completed` or `failed`, at which point an `ExecutionRecord` is also written.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["id", "actionId", "actionVersion", "nodeId", "contentHash", "nonce", "status", "ttlSeconds", "createdAt"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"id": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"pattern": "^d-\\d{8}-\\d{6}-[0-9a-f]{4}$",
|
|
13
|
+
"description": "Job id: `d-YYYYMMDD-HHMMSS-XXXX`. Human-readable, sortable."
|
|
14
|
+
},
|
|
15
|
+
"actionId": {
|
|
16
|
+
"type": "string"
|
|
17
|
+
},
|
|
18
|
+
"actionVersion": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"description": "Semver of the action implementation at submit time. Frozen for this job."
|
|
21
|
+
},
|
|
22
|
+
"nodeId": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"description": "Target `node.path`. `--all` submissions fan out into one job per node."
|
|
25
|
+
},
|
|
26
|
+
"contentHash": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"pattern": "^[a-f0-9]{64}$",
|
|
29
|
+
"description": "sha256(actionId + actionVersion + bodyHash + frontmatterHash + promptTemplateHash). Duplicate detection key."
|
|
30
|
+
},
|
|
31
|
+
"nonce": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"description": "Unique per-job token. `sm record` requires it to close the job — mismatch rejects with exit code 4."
|
|
34
|
+
},
|
|
35
|
+
"priority": {
|
|
36
|
+
"type": "integer",
|
|
37
|
+
"description": "Higher = claimed first. Default 0.",
|
|
38
|
+
"default": 0
|
|
39
|
+
},
|
|
40
|
+
"status": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"enum": ["queued", "running", "completed", "failed"],
|
|
43
|
+
"description": "Lifecycle state. See `dispatch-lifecycle.md` for allowed transitions."
|
|
44
|
+
},
|
|
45
|
+
"failureReason": {
|
|
46
|
+
"type": ["string", "null"],
|
|
47
|
+
"enum": ["runner-error", "report-invalid", "timeout", "abandoned", "job-file-missing", "user-cancelled", null],
|
|
48
|
+
"description": "Populated when `status = failed`."
|
|
49
|
+
},
|
|
50
|
+
"runner": {
|
|
51
|
+
"type": ["string", "null"],
|
|
52
|
+
"enum": ["cli", "skill", "in-process", null]
|
|
53
|
+
},
|
|
54
|
+
"ttlSeconds": {
|
|
55
|
+
"type": "integer",
|
|
56
|
+
"minimum": 1,
|
|
57
|
+
"description": "Resolved TTL at submit time: max(expectedDurationSeconds × graceMultiplier, minimumTtlSeconds). Frozen."
|
|
58
|
+
},
|
|
59
|
+
"filePath": {
|
|
60
|
+
"type": ["string", "null"],
|
|
61
|
+
"description": "Relative path to the rendered job file (usually `.skill-map/jobs/<id>.md`). Null before rendering."
|
|
62
|
+
},
|
|
63
|
+
"createdAt": { "type": "integer", "description": "Unix ms. Submit time." },
|
|
64
|
+
"claimedAt": { "type": ["integer", "null"], "description": "Unix ms. Null while queued." },
|
|
65
|
+
"finishedAt": { "type": ["integer", "null"], "description": "Unix ms. Null while not terminal." },
|
|
66
|
+
"expiresAt": {
|
|
67
|
+
"type": ["integer", "null"],
|
|
68
|
+
"description": "Derived = claimedAt + ttlSeconds × 1000. Used by auto-reap. Null while queued."
|
|
69
|
+
},
|
|
70
|
+
"submittedBy": {
|
|
71
|
+
"type": ["string", "null"],
|
|
72
|
+
"description": "Free-form: username, CI job id, or `skill:<skill-id>`. Optional provenance."
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://skill-map.dev/spec/v0/link.schema.json",
|
|
4
|
+
"title": "Link",
|
|
5
|
+
"description": "Directed relation between two nodes, produced by one or more detectors during a scan.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["source", "target", "kind", "confidence", "sources"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"source": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "`node.path` of the origin."
|
|
13
|
+
},
|
|
14
|
+
"target": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "`node.path` of the destination. MAY point to a missing node; rules detect broken refs."
|
|
17
|
+
},
|
|
18
|
+
"kind": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"enum": ["invokes", "references", "mentions", "supersedes"],
|
|
21
|
+
"description": "Nature of the relation. `invokes` = execution-level call (e.g. slash command). `references` = explicit link (e.g. wikilink, @-directive). `mentions` = informal textual mention. `supersedes` = replaces another node (from `metadata.supersedes`)."
|
|
22
|
+
},
|
|
23
|
+
"confidence": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"enum": ["high", "medium", "low"],
|
|
26
|
+
"description": "Detector's self-assessed confidence. Rules MAY filter by confidence."
|
|
27
|
+
},
|
|
28
|
+
"sources": {
|
|
29
|
+
"type": "array",
|
|
30
|
+
"description": "Detector ids that produced this link. At least one. Multiple detectors may converge on the same link; kernel merges them.",
|
|
31
|
+
"minItems": 1,
|
|
32
|
+
"items": { "type": "string" }
|
|
33
|
+
},
|
|
34
|
+
"trigger": {
|
|
35
|
+
"type": ["object", "null"],
|
|
36
|
+
"description": "Trigger-style link metadata (e.g. slash-command keyword, @-directive keyword). Null for links without a textual trigger.",
|
|
37
|
+
"required": ["originalTrigger", "normalizedTrigger"],
|
|
38
|
+
"additionalProperties": false,
|
|
39
|
+
"properties": {
|
|
40
|
+
"originalTrigger": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"description": "Exact string as it appears in the source body."
|
|
43
|
+
},
|
|
44
|
+
"normalizedTrigger": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"description": "NFD → strip diacritics → lowercase → hyphen/underscore → space → collapse whitespace → trim. Used for collision detection and lookup."
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"location": {
|
|
51
|
+
"type": ["object", "null"],
|
|
52
|
+
"description": "Where in the source body the link was found. Null if the detector didn't track location.",
|
|
53
|
+
"required": ["line"],
|
|
54
|
+
"additionalProperties": false,
|
|
55
|
+
"properties": {
|
|
56
|
+
"line": { "type": "integer", "minimum": 1 },
|
|
57
|
+
"column": { "type": "integer", "minimum": 1 },
|
|
58
|
+
"offset": { "type": "integer", "minimum": 0 }
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"raw": {
|
|
62
|
+
"type": ["string", "null"],
|
|
63
|
+
"description": "Verbatim matched substring from the source body. Optional, for debugging and UI display."
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://skill-map.dev/spec/v0/node.schema.json",
|
|
4
|
+
"title": "Node",
|
|
5
|
+
"description": "A single markdown file in the graph (skill, agent, command, hook, note). Identified by its relative path from the scope root.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["path", "kind", "adapter", "bodyHash", "frontmatterHash", "bytes", "linksOutCount", "linksInCount", "externalRefsCount"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"path": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Relative path from the scope root. Canonical node identifier in v0. Survives frontmatter edits; breaks on file moves (rare enough). FUTURE: a sibling `id` field (UUID stored in frontmatter) lands with write-back to decouple identity from location; `path` will remain as display metadata at that point. Stability: stable."
|
|
13
|
+
},
|
|
14
|
+
"kind": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"enum": ["skill", "agent", "command", "hook", "note"],
|
|
17
|
+
"description": "Category assigned by the adapter. Stability: stable. New kinds may be added in a minor bump."
|
|
18
|
+
},
|
|
19
|
+
"adapter": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "Identifier of the adapter extension that classified this node (e.g. `claude`)."
|
|
22
|
+
},
|
|
23
|
+
"title": {
|
|
24
|
+
"type": ["string", "null"],
|
|
25
|
+
"description": "Human-readable title. Sourced from frontmatter `name` or falls back to filename. Null if neither is usable."
|
|
26
|
+
},
|
|
27
|
+
"description": {
|
|
28
|
+
"type": ["string", "null"],
|
|
29
|
+
"description": "Short description from frontmatter `description`. Null if absent."
|
|
30
|
+
},
|
|
31
|
+
"stability": {
|
|
32
|
+
"type": ["string", "null"],
|
|
33
|
+
"enum": ["experimental", "stable", "deprecated", null],
|
|
34
|
+
"description": "Denormalized from `metadata.stability` for fast queries."
|
|
35
|
+
},
|
|
36
|
+
"version": {
|
|
37
|
+
"type": ["string", "null"],
|
|
38
|
+
"description": "Denormalized from `metadata.version` for fast queries. Must be a valid semver if present."
|
|
39
|
+
},
|
|
40
|
+
"author": {
|
|
41
|
+
"type": ["string", "null"],
|
|
42
|
+
"description": "Denormalized from `metadata.author` for fast queries."
|
|
43
|
+
},
|
|
44
|
+
"frontmatter": {
|
|
45
|
+
"type": "object",
|
|
46
|
+
"description": "Full parsed frontmatter. See `frontmatter/base.schema.json` and `frontmatter/<kind>.schema.json`.",
|
|
47
|
+
"additionalProperties": true
|
|
48
|
+
},
|
|
49
|
+
"bodyHash": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"pattern": "^[a-f0-9]{64}$",
|
|
52
|
+
"description": "sha256 of the body content (post-frontmatter), hex-encoded lowercase. Used for rename heuristic (high confidence) and stale detection."
|
|
53
|
+
},
|
|
54
|
+
"frontmatterHash": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"pattern": "^[a-f0-9]{64}$",
|
|
57
|
+
"description": "sha256 of the raw frontmatter block, hex-encoded lowercase. Used for rename heuristic (medium confidence)."
|
|
58
|
+
},
|
|
59
|
+
"bytes": {
|
|
60
|
+
"$ref": "#/$defs/tripleSplit",
|
|
61
|
+
"description": "Size breakdown in bytes: frontmatter, body, total."
|
|
62
|
+
},
|
|
63
|
+
"tokens": {
|
|
64
|
+
"$ref": "#/$defs/tripleSplit",
|
|
65
|
+
"description": "Size breakdown in tokens (via `js-tiktoken`): frontmatter, body, total. Optional; MAY be absent if tokenization was disabled."
|
|
66
|
+
},
|
|
67
|
+
"linksOutCount": {
|
|
68
|
+
"type": "integer",
|
|
69
|
+
"minimum": 0,
|
|
70
|
+
"description": "Outgoing links from this node to other graph nodes."
|
|
71
|
+
},
|
|
72
|
+
"linksInCount": {
|
|
73
|
+
"type": "integer",
|
|
74
|
+
"minimum": 0,
|
|
75
|
+
"description": "Incoming links from other graph nodes to this one."
|
|
76
|
+
},
|
|
77
|
+
"externalRefsCount": {
|
|
78
|
+
"type": "integer",
|
|
79
|
+
"minimum": 0,
|
|
80
|
+
"description": "http/https URLs in the body after normalization and exact-match dedup."
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"$defs": {
|
|
84
|
+
"tripleSplit": {
|
|
85
|
+
"type": "object",
|
|
86
|
+
"required": ["frontmatter", "body", "total"],
|
|
87
|
+
"additionalProperties": false,
|
|
88
|
+
"properties": {
|
|
89
|
+
"frontmatter": { "type": "integer", "minimum": 0 },
|
|
90
|
+
"body": { "type": "integer", "minimum": 0 },
|
|
91
|
+
"total": { "type": "integer", "minimum": 0 }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://skill-map.dev/spec/v0/plugins-registry.schema.json",
|
|
4
|
+
"title": "PluginsRegistry",
|
|
5
|
+
"description": "Two shapes in one file: (1) the per-plugin manifest that authors ship as `plugin.json` (see `$defs/PluginManifest`); (2) the aggregate registry the implementation produces on disk (e.g. `~/.skill-map/plugins.json`), which lists all discovered plugins with their compat status. Both shapes are normative. camelCase keys throughout.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"oneOf": [
|
|
8
|
+
{ "$ref": "#/$defs/PluginsRegistry" },
|
|
9
|
+
{ "$ref": "#/$defs/PluginManifest" }
|
|
10
|
+
],
|
|
11
|
+
"$defs": {
|
|
12
|
+
"PluginManifest": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"required": ["id", "version", "specCompat", "extensions"],
|
|
15
|
+
"additionalProperties": false,
|
|
16
|
+
"properties": {
|
|
17
|
+
"id": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"pattern": "^[a-z][a-z0-9]*(-[a-z0-9]+)*$",
|
|
20
|
+
"description": "Kebab-case, globally unique plugin identifier."
|
|
21
|
+
},
|
|
22
|
+
"version": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"description": "Plugin semver."
|
|
25
|
+
},
|
|
26
|
+
"specCompat": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"description": "Semver range this plugin is compatible with (e.g. `^1.0.0`, `>=0.3.0 <0.4.0`). Checked via `semver.satisfies(specVersion, this)` at load time."
|
|
29
|
+
},
|
|
30
|
+
"description": {
|
|
31
|
+
"type": "string"
|
|
32
|
+
},
|
|
33
|
+
"extensions": {
|
|
34
|
+
"type": "array",
|
|
35
|
+
"description": "Relative paths to extension files, resolved from the plugin directory.",
|
|
36
|
+
"minItems": 1,
|
|
37
|
+
"items": { "type": "string" }
|
|
38
|
+
},
|
|
39
|
+
"storage": {
|
|
40
|
+
"type": "object",
|
|
41
|
+
"description": "Persistence mode for this plugin. Absent = plugin does not persist state.",
|
|
42
|
+
"oneOf": [
|
|
43
|
+
{
|
|
44
|
+
"required": ["mode"],
|
|
45
|
+
"additionalProperties": false,
|
|
46
|
+
"properties": {
|
|
47
|
+
"mode": { "const": "kv", "description": "Shared `state_plugin_kv` table, scoped by plugin id." }
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"required": ["mode", "tables", "migrations"],
|
|
52
|
+
"additionalProperties": false,
|
|
53
|
+
"properties": {
|
|
54
|
+
"mode": { "const": "dedicated", "description": "Plugin-owned tables, prefixed `plugin_<normalizedId>_`." },
|
|
55
|
+
"tables": { "type": "array", "minItems": 1, "items": { "type": "string" } },
|
|
56
|
+
"migrations": { "type": "array", "minItems": 1, "items": { "type": "string" }, "description": "Relative paths to `.sql` migration files." }
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
"author": { "type": "string" },
|
|
62
|
+
"license": { "type": "string", "description": "SPDX identifier." },
|
|
63
|
+
"homepage": { "type": "string", "format": "uri" },
|
|
64
|
+
"repository": { "type": "string", "format": "uri" }
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"PluginsRegistry": {
|
|
68
|
+
"type": "object",
|
|
69
|
+
"required": ["schemaVersion", "plugins"],
|
|
70
|
+
"additionalProperties": false,
|
|
71
|
+
"properties": {
|
|
72
|
+
"schemaVersion": { "type": "integer", "const": 1 },
|
|
73
|
+
"plugins": {
|
|
74
|
+
"type": "array",
|
|
75
|
+
"items": { "$ref": "#/$defs/DiscoveredPlugin" }
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"DiscoveredPlugin": {
|
|
80
|
+
"type": "object",
|
|
81
|
+
"required": ["id", "path", "manifest", "status"],
|
|
82
|
+
"additionalProperties": false,
|
|
83
|
+
"properties": {
|
|
84
|
+
"id": { "type": "string" },
|
|
85
|
+
"path": { "type": "string", "description": "Absolute path to the plugin directory." },
|
|
86
|
+
"manifest": { "$ref": "#/$defs/PluginManifest" },
|
|
87
|
+
"status": {
|
|
88
|
+
"type": "string",
|
|
89
|
+
"enum": ["enabled", "disabled", "incompatible-spec", "invalid-manifest", "load-error"],
|
|
90
|
+
"description": "Resolved state after discovery. `disabled` = user-disabled via config; others = automatic."
|
|
91
|
+
},
|
|
92
|
+
"statusReason": {
|
|
93
|
+
"type": ["string", "null"],
|
|
94
|
+
"description": "Human-readable detail when status is anything other than `enabled`."
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://skill-map.dev/spec/v0/project-config.schema.json",
|
|
4
|
+
"title": "ProjectConfig",
|
|
5
|
+
"description": "Shape of `.skill-map.json` at the project root. All fields optional; defaults apply when absent. camelCase keys throughout — consistent with the rest of the spec.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"properties": {
|
|
9
|
+
"schemaVersion": {
|
|
10
|
+
"type": "integer",
|
|
11
|
+
"const": 1,
|
|
12
|
+
"description": "Config file shape version. Bumped on breaking changes to this schema."
|
|
13
|
+
},
|
|
14
|
+
"adapters": {
|
|
15
|
+
"type": "array",
|
|
16
|
+
"description": "Adapter ids to enable, in priority order when multiple match. Empty/absent = use all registered.",
|
|
17
|
+
"items": { "type": "string" }
|
|
18
|
+
},
|
|
19
|
+
"roots": {
|
|
20
|
+
"type": "array",
|
|
21
|
+
"description": "Directories (relative to the config file) to scan. Defaults to the scope root.",
|
|
22
|
+
"items": { "type": "string" }
|
|
23
|
+
},
|
|
24
|
+
"ignore": {
|
|
25
|
+
"type": "array",
|
|
26
|
+
"description": "Glob patterns to exclude, in addition to `.skill-mapignore`.",
|
|
27
|
+
"items": { "type": "string" }
|
|
28
|
+
},
|
|
29
|
+
"scan": {
|
|
30
|
+
"type": "object",
|
|
31
|
+
"additionalProperties": false,
|
|
32
|
+
"properties": {
|
|
33
|
+
"tokenize": { "type": "boolean", "description": "Whether to compute token counts. Default true." },
|
|
34
|
+
"strict": { "type": "boolean", "description": "Promote frontmatter warnings to errors. Default false." },
|
|
35
|
+
"followSymlinks": { "type": "boolean", "description": "Default false." }
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"plugins": {
|
|
39
|
+
"type": "object",
|
|
40
|
+
"description": "Per-plugin enable/disable overrides. Keys are plugin ids. Absent = use installed default (enabled).",
|
|
41
|
+
"additionalProperties": {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"additionalProperties": false,
|
|
44
|
+
"properties": {
|
|
45
|
+
"enabled": { "type": "boolean" },
|
|
46
|
+
"config": { "type": "object", "description": "Plugin-specific config passed to extensions at load time. Shape defined by the plugin.", "additionalProperties": true }
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"history": {
|
|
51
|
+
"type": "object",
|
|
52
|
+
"additionalProperties": false,
|
|
53
|
+
"properties": {
|
|
54
|
+
"share": {
|
|
55
|
+
"type": "boolean",
|
|
56
|
+
"description": "When true, `./.skill-map/history.json` is intended to be committed. Stability: experimental. Default false."
|
|
57
|
+
},
|
|
58
|
+
"retentionDays": {
|
|
59
|
+
"type": "integer",
|
|
60
|
+
"minimum": 1,
|
|
61
|
+
"description": "How long to keep execution records before GC."
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"jobs": {
|
|
66
|
+
"type": "object",
|
|
67
|
+
"additionalProperties": false,
|
|
68
|
+
"properties": {
|
|
69
|
+
"graceMultiplier": { "type": "number", "minimum": 1, "description": "Default grace multiplier applied to `expectedDurationSeconds`. Default 3." },
|
|
70
|
+
"minimumTtlSeconds": { "type": "integer", "minimum": 1, "description": "Floor for computed TTL. Default 60." },
|
|
71
|
+
"perActionTtl": {
|
|
72
|
+
"type": "object",
|
|
73
|
+
"description": "Per-action TTL overrides (seconds). Keys are action ids.",
|
|
74
|
+
"additionalProperties": { "type": "integer", "minimum": 1 }
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"i18n": {
|
|
79
|
+
"type": "object",
|
|
80
|
+
"description": "Stability: experimental.",
|
|
81
|
+
"additionalProperties": false,
|
|
82
|
+
"properties": {
|
|
83
|
+
"locale": { "type": "string", "description": "BCP-47 tag. Default `en`." }
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://skill-map.dev/spec/v0/report-base.schema.json",
|
|
4
|
+
"title": "ReportBase",
|
|
5
|
+
"description": "Base shape for any probabilistic report produced by an LLM-backed action (summarizers, `sm what`, `sm cluster-triggers`, etc.). All per-kind summary schemas under `summaries/` extend this. Kernel validates the `confidence` and `safety` fields regardless of action-specific extensions.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["confidence", "safety"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"confidence": {
|
|
10
|
+
"type": "number",
|
|
11
|
+
"minimum": 0,
|
|
12
|
+
"maximum": 1,
|
|
13
|
+
"description": "Model's self-assessed confidence in its own output, 0–1. Not calibrated across models; compare within the same action."
|
|
14
|
+
},
|
|
15
|
+
"safety": {
|
|
16
|
+
"type": "object",
|
|
17
|
+
"required": ["injectionDetected", "contentQuality"],
|
|
18
|
+
"additionalProperties": false,
|
|
19
|
+
"properties": {
|
|
20
|
+
"injectionDetected": {
|
|
21
|
+
"type": "boolean",
|
|
22
|
+
"description": "True when the model flagged a prompt-injection attempt inside the node content. See `prompt-preamble.md` for the contract the model was primed with."
|
|
23
|
+
},
|
|
24
|
+
"injectionType": {
|
|
25
|
+
"type": ["string", "null"],
|
|
26
|
+
"enum": ["direct-override", "role-swap", "hidden-instruction", "other", null],
|
|
27
|
+
"description": "Classification. Null when `injectionDetected = false`."
|
|
28
|
+
},
|
|
29
|
+
"injectionDetails": {
|
|
30
|
+
"type": ["string", "null"],
|
|
31
|
+
"description": "Free-form notes from the model about the injection attempt."
|
|
32
|
+
},
|
|
33
|
+
"contentQuality": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"enum": ["clean", "suspicious", "malformed"],
|
|
36
|
+
"description": "`clean` = normal input. `suspicious` = unusual patterns without a concrete injection. `malformed` = unparseable or structurally broken."
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://skill-map.dev/spec/v0/scan-result.schema.json",
|
|
4
|
+
"title": "ScanResult",
|
|
5
|
+
"description": "Canonical output of `sm scan --json` (and the data shape sent over WebSocket scan events). Self-describing and versioned; consumers MUST check `schemaVersion` before parsing.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["schemaVersion", "scannedAt", "scope", "roots", "nodes", "links", "issues", "stats"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"schemaVersion": {
|
|
11
|
+
"type": "integer",
|
|
12
|
+
"const": 1,
|
|
13
|
+
"description": "Scan result shape version. Bumped only on breaking changes to this schema."
|
|
14
|
+
},
|
|
15
|
+
"scannedAt": {
|
|
16
|
+
"type": "integer",
|
|
17
|
+
"description": "Unix milliseconds when the scan started."
|
|
18
|
+
},
|
|
19
|
+
"scannedBy": {
|
|
20
|
+
"type": ["object", "null"],
|
|
21
|
+
"description": "Implementation metadata. Optional so that synthetic fixtures can omit it.",
|
|
22
|
+
"additionalProperties": false,
|
|
23
|
+
"properties": {
|
|
24
|
+
"name": { "type": "string", "description": "Implementation name (e.g. `skill-map`)." },
|
|
25
|
+
"version": { "type": "string", "description": "Implementation semver." },
|
|
26
|
+
"specVersion": { "type": "string", "description": "Spec version that this scan conforms to (e.g. `0.1.0`)." }
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"scope": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"enum": ["project", "global"],
|
|
32
|
+
"description": "Scan scope. `project` walks the cwd repo; `global` walks user-level skill directories."
|
|
33
|
+
},
|
|
34
|
+
"roots": {
|
|
35
|
+
"type": "array",
|
|
36
|
+
"description": "Filesystem roots that were walked during this scan, as absolute or scope-root-relative paths.",
|
|
37
|
+
"minItems": 1,
|
|
38
|
+
"items": { "type": "string" }
|
|
39
|
+
},
|
|
40
|
+
"adapters": {
|
|
41
|
+
"type": "array",
|
|
42
|
+
"description": "Adapter ids that participated in classification. Empty if no adapter matched.",
|
|
43
|
+
"items": { "type": "string" }
|
|
44
|
+
},
|
|
45
|
+
"nodes": {
|
|
46
|
+
"type": "array",
|
|
47
|
+
"items": { "$ref": "node.schema.json" }
|
|
48
|
+
},
|
|
49
|
+
"links": {
|
|
50
|
+
"type": "array",
|
|
51
|
+
"items": { "$ref": "link.schema.json" }
|
|
52
|
+
},
|
|
53
|
+
"issues": {
|
|
54
|
+
"type": "array",
|
|
55
|
+
"items": { "$ref": "issue.schema.json" }
|
|
56
|
+
},
|
|
57
|
+
"stats": {
|
|
58
|
+
"type": "object",
|
|
59
|
+
"required": ["filesWalked", "filesSkipped", "nodesCount", "linksCount", "issuesCount", "durationMs"],
|
|
60
|
+
"additionalProperties": false,
|
|
61
|
+
"properties": {
|
|
62
|
+
"filesWalked": { "type": "integer", "minimum": 0 },
|
|
63
|
+
"filesSkipped": { "type": "integer", "minimum": 0, "description": "Files walked but not classified by any adapter." },
|
|
64
|
+
"nodesCount": { "type": "integer", "minimum": 0 },
|
|
65
|
+
"linksCount": { "type": "integer", "minimum": 0 },
|
|
66
|
+
"issuesCount": { "type": "integer", "minimum": 0 },
|
|
67
|
+
"durationMs": { "type": "integer", "minimum": 0 }
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|