@skill-map/spec 0.21.0 → 0.23.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 +127 -0
- package/README.md +4 -4
- package/architecture.md +134 -128
- package/cli-contract.md +107 -104
- package/conformance/README.md +13 -13
- package/conformance/coverage.md +42 -39
- package/conformance/fixtures/plugin-missing-ui/.skill-map/plugins/bad-provider/provider.js +0 -1
- package/db-schema.md +45 -45
- package/index.json +41 -38
- package/interfaces/security-scanner.md +20 -20
- package/job-events.md +21 -21
- package/job-lifecycle.md +21 -21
- package/package.json +3 -2
- package/plugin-author-guide.md +135 -111
- package/plugin-kv-api.md +10 -10
- package/prompt-preamble.md +8 -8
- package/schemas/annotations.schema.json +3 -3
- package/schemas/api/rest-envelope.schema.json +15 -11
- package/schemas/conformance-result.schema.json +120 -0
- package/schemas/execution-record.schema.json +2 -2
- package/schemas/extensions/analyzer.schema.json +9 -0
- package/schemas/extensions/base.schema.json +4 -4
- package/schemas/extensions/extractor.schema.json +4 -4
- package/schemas/extensions/formatter.schema.json +1 -1
- package/schemas/extensions/hook.schema.json +3 -3
- package/schemas/extensions/provider.schema.json +6 -11
- package/schemas/frontmatter/base.schema.json +1 -1
- package/schemas/history-stats.schema.json +4 -4
- package/schemas/input-types.schema.json +3 -3
- package/schemas/issue.schema.json +1 -1
- package/schemas/job.schema.json +2 -2
- package/schemas/node.schema.json +5 -5
- package/schemas/plugins-doctor.schema.json +97 -0
- package/schemas/plugins-registry.schema.json +2 -2
- package/schemas/project-config.schema.json +10 -14
- package/schemas/refresh-report.schema.json +52 -0
- package/schemas/report-base-deterministic.schema.json +1 -1
- package/schemas/sidecar.schema.json +3 -3
- package/schemas/summaries/markdown.schema.json +1 -1
- package/schemas/summaries/skill.schema.json +1 -1
- package/schemas/view-slots.schema.json +7 -7
- package/versioning.md +7 -7
package/index.json
CHANGED
|
@@ -174,24 +174,24 @@
|
|
|
174
174
|
}
|
|
175
175
|
]
|
|
176
176
|
},
|
|
177
|
-
"specPackageVersion": "0.
|
|
177
|
+
"specPackageVersion": "0.23.0",
|
|
178
178
|
"integrity": {
|
|
179
179
|
"algorithm": "sha256",
|
|
180
180
|
"files": {
|
|
181
|
-
"CHANGELOG.md": "
|
|
182
|
-
"README.md": "
|
|
183
|
-
"architecture.md": "
|
|
184
|
-
"cli-contract.md": "
|
|
185
|
-
"conformance/README.md": "
|
|
181
|
+
"CHANGELOG.md": "f654250a3481270a0b853b937e804988eb3db289aa8338a407f1f2ff0cd32735",
|
|
182
|
+
"README.md": "76c5d5afa1c08dbfe9206e141c810ea063f5bcb2f2069d80ace311905ca3c2c3",
|
|
183
|
+
"architecture.md": "ebb5370040cc72300803c4f153512127e21279c80834f701f722e72411e5b8ed",
|
|
184
|
+
"cli-contract.md": "7a36ad793a86bef058dafdc9657bd2dfa4d1e1f88ff8b782aaf216f442ebfa86",
|
|
185
|
+
"conformance/README.md": "7a0f6d6a4057349d35004c68c92bacd6528bb7489ad942406a035be1b84bf360",
|
|
186
186
|
"conformance/cases/kernel-empty-boot.json": "2a5be9c93143d07a16d998df09dcc8fa4ea2d2f9a0bff6417573ed5a770352c1",
|
|
187
187
|
"conformance/cases/orphan-markdown-fallback.json": "8ef6e49b7e6532bd845d9f54974a16e537cf98d355f0c5e4f4fb06abac3adcc5",
|
|
188
188
|
"conformance/cases/plugin-missing-ui-rejected.json": "bdebee810436e6be88edf2fe38ddc6939fd3f53e6a12dc1d66da051c4922f1e9",
|
|
189
189
|
"conformance/cases/sidecar-end-to-end.json": "24a73e7c857709d001cf7013b8fe5ccad4027e064b39533dda33697d80b56e7a",
|
|
190
|
-
"conformance/coverage.md": "
|
|
190
|
+
"conformance/coverage.md": "bdf0043707d447417d2a0d03b97fdc30e5335759b4b82a1e894c2ffb00fb7940",
|
|
191
191
|
"conformance/fixtures/orphan-markdown/.claude/agents/reviewer.md": "7f062731106f2d9811e4fffcf6ab44b8dfff4cfb16536a469514cc0664e832bf",
|
|
192
192
|
"conformance/fixtures/orphan-markdown/ARCHITECTURE.md": "d6b6e18d4b963b26a292de73348c3396fd4710ab4c4bdd6cf094e581f99ec8d6",
|
|
193
193
|
"conformance/fixtures/plugin-missing-ui/.skill-map/plugins/bad-provider/plugin.json": "4d78af6f12faa9d131e2a19f1dbb8f250baacc525978f3a8c858932b95da4ff6",
|
|
194
|
-
"conformance/fixtures/plugin-missing-ui/.skill-map/plugins/bad-provider/provider.js": "
|
|
194
|
+
"conformance/fixtures/plugin-missing-ui/.skill-map/plugins/bad-provider/provider.js": "45843e8e1a679482a17e01dcd43e1800e1d3148f4ac2cd6ab8a29ef0430b6152",
|
|
195
195
|
"conformance/fixtures/plugin-missing-ui/notes/example.md": "55767f0aa1b6774546a99f28c58e7b732aa9cfa5dfce8d0326470f7f622f577e",
|
|
196
196
|
"conformance/fixtures/preamble-v1.txt": "1e0aeef224b64477bdc13a949c3ad402e68249caf499ecdba1302371677c068b",
|
|
197
197
|
"conformance/fixtures/sidecar-end-to-end/.claude/agents/orphan.sm": "3102ff10a0f08f60c014f82409d45ad4faf2cefa04d652a87676d3557ad64944",
|
|
@@ -199,45 +199,48 @@
|
|
|
199
199
|
"conformance/fixtures/sidecar-end-to-end/.claude/agents/stale.sm": "cb04f7f3103b4218b09fd4da92f7ea429588b04c1dac6a9547ce362263b11224",
|
|
200
200
|
"conformance/fixtures/sidecar-example/agent-example.md": "741131403e8c9580d0b7a8c2446cb4502d01f80053b7a2092663de92431aaa82",
|
|
201
201
|
"conformance/fixtures/sidecar-example/agent-example.sm": "41200387e74a120c554a34dfabc50dd2151067a1c6599695c59412d8eab38bb4",
|
|
202
|
-
"db-schema.md": "
|
|
203
|
-
"interfaces/security-scanner.md": "
|
|
204
|
-
"job-events.md": "
|
|
205
|
-
"job-lifecycle.md": "
|
|
206
|
-
"plugin-author-guide.md": "
|
|
207
|
-
"plugin-kv-api.md": "
|
|
208
|
-
"prompt-preamble.md": "
|
|
209
|
-
"schemas/annotations.schema.json": "
|
|
210
|
-
"schemas/api/rest-envelope.schema.json": "
|
|
202
|
+
"db-schema.md": "ff792e4b8d4fcd122e43cf7718b72b7780aaefadc6f839441bdc06fa89197d7c",
|
|
203
|
+
"interfaces/security-scanner.md": "e8049712b9cf7a07c786bf19f8f775f8ef9638f063f7fba5c7a8b1431b92f38e",
|
|
204
|
+
"job-events.md": "84206168ac12b536d34470d62f8c8cba95dab181fee66d23203c2cf5dfbee716",
|
|
205
|
+
"job-lifecycle.md": "9c429121f98a07c8795f8979ed1abc5e5334e3f89db51585a8da55c527ef855b",
|
|
206
|
+
"plugin-author-guide.md": "4612258f05b57c60a0f660bc86d20677bcc8403be3659d93101d966c4bc17e4d",
|
|
207
|
+
"plugin-kv-api.md": "1acc69ed82433a74e35ada61d63a6d7379fb61046ff83de1e0facbe884c64704",
|
|
208
|
+
"prompt-preamble.md": "9dd4f6d1bc6a425f8782fcee10cbe75909e8d64e28781fda56c2fae909b02f40",
|
|
209
|
+
"schemas/annotations.schema.json": "a446a03ffc5df443c10464caee547014533f56c2106bf897f204ca7247876431",
|
|
210
|
+
"schemas/api/rest-envelope.schema.json": "bf735dbea44725545a33c001c08bf9b0395995f71c70d46a4cc215d276e19038",
|
|
211
211
|
"schemas/bump-report.schema.json": "c2d853715d5f50098567bc23382a4e81baf78d589c6e1baf67d3b841e7f7d8ae",
|
|
212
212
|
"schemas/conformance-case.schema.json": "f6d4c9fb92e79cb516eeeb9d042223572a3bd5ff8e7871a0becce13916f20cf6",
|
|
213
|
-
"schemas/
|
|
213
|
+
"schemas/conformance-result.schema.json": "426998e4f5cb079778ca7d0233634667d4fbc5a7e399cc41211fabd768db8ee0",
|
|
214
|
+
"schemas/execution-record.schema.json": "0d61e33f2dc1aaa4cc7337b5eac4ea8b9034022ce24bae9156c3c9f33204c250",
|
|
214
215
|
"schemas/extensions/action.schema.json": "262272175c06a2e33c08f819a45c3ef8260276c91a9d0542fdffc932aeb32db7",
|
|
215
|
-
"schemas/extensions/analyzer.schema.json": "
|
|
216
|
-
"schemas/extensions/base.schema.json": "
|
|
217
|
-
"schemas/extensions/extractor.schema.json": "
|
|
218
|
-
"schemas/extensions/formatter.schema.json": "
|
|
219
|
-
"schemas/extensions/hook.schema.json": "
|
|
220
|
-
"schemas/extensions/provider.schema.json": "
|
|
221
|
-
"schemas/frontmatter/base.schema.json": "
|
|
222
|
-
"schemas/history-stats.schema.json": "
|
|
223
|
-
"schemas/input-types.schema.json": "
|
|
224
|
-
"schemas/issue.schema.json": "
|
|
225
|
-
"schemas/job.schema.json": "
|
|
216
|
+
"schemas/extensions/analyzer.schema.json": "c3c5fc7de89318c178d170629dc9aecd6bcce9418e9ce7cc2f8d4f5ea8db99a6",
|
|
217
|
+
"schemas/extensions/base.schema.json": "5a593f74678485b2e2dc5b92ba9a345d6290ef7381921758a852934e09db7a64",
|
|
218
|
+
"schemas/extensions/extractor.schema.json": "38000aea61c4d06cd136ccbcf740d3608b2c5586c7a0ff93a75e75f0df09f018",
|
|
219
|
+
"schemas/extensions/formatter.schema.json": "816136b9b933a93fde6859110d1d68dafe39099dea589786282b90627b464f7c",
|
|
220
|
+
"schemas/extensions/hook.schema.json": "abfa75881a4bd20c367f1eada29fb577b89752920c9f9351f8247e1340f5f2ca",
|
|
221
|
+
"schemas/extensions/provider.schema.json": "e9f026b7c6c3a167a55c581ebb92425e10563cc3b1864b18f48462b813d01ff3",
|
|
222
|
+
"schemas/frontmatter/base.schema.json": "df0056a9478514a0db7a705e59868fa4f67673ac1cc9c9da979de4237cdd62a1",
|
|
223
|
+
"schemas/history-stats.schema.json": "5170dec0299f3d04382a38079a27b1f26300a6b95fdb1ea0fae11050ad9f0574",
|
|
224
|
+
"schemas/input-types.schema.json": "c713b768d0b0e3d0c764afb401189f7fb624a82b4e988b73aab015cf9c67c01f",
|
|
225
|
+
"schemas/issue.schema.json": "fa3344e75f1c3a5304291ca355bb973046552a68871ad6eb4edafca1cd9e1be8",
|
|
226
|
+
"schemas/job.schema.json": "e43e1761c99920beffe1de12ef8f32fe29f97838bd8686742b637c19c4dbb395",
|
|
226
227
|
"schemas/link.schema.json": "7fc429d03aca7e4c0b9a28241712c1aa2a5275870cea5ed938c2f97e8cccb081",
|
|
227
|
-
"schemas/node.schema.json": "
|
|
228
|
-
"schemas/plugins-
|
|
229
|
-
"schemas/
|
|
230
|
-
"schemas/
|
|
228
|
+
"schemas/node.schema.json": "0371eb471301947cb8c9489082c380bb01f7426b0b7d9aa96a6e05803fc7cf00",
|
|
229
|
+
"schemas/plugins-doctor.schema.json": "c1d92f30fdb0080e8cd8f7dc5d43e01aae02a16640bc5eb04811c337a275de58",
|
|
230
|
+
"schemas/plugins-registry.schema.json": "c79b134e25575b0046fd583b5b8fd8fc3413ca91502002cf556ac0fe4217d4a0",
|
|
231
|
+
"schemas/project-config.schema.json": "c866a64282199fd9ead5dc2b889e6cca27ffb289e656fafa0a22d1b715c86e95",
|
|
232
|
+
"schemas/refresh-report.schema.json": "54519b8caf86ba84c182f9565be9b5084bc1631ae05e9217ee18f34c0039fff3",
|
|
233
|
+
"schemas/report-base-deterministic.schema.json": "9d318d0181d121097c906ef3af1c52d71c782740bd04cf23418d7627ce2c3ed5",
|
|
231
234
|
"schemas/report-base.schema.json": "a1021e9a59b4df9f99cd92454d797e88469766e7d49f52d231c4645ffdfdad8f",
|
|
232
235
|
"schemas/scan-result.schema.json": "d1a8782e198bc9bb92dad247437aefa1b02f92ff8dca8562eaf2348fd7c5cf0c",
|
|
233
|
-
"schemas/sidecar.schema.json": "
|
|
236
|
+
"schemas/sidecar.schema.json": "8856c387477340efbdd0a585d74bfb07a99ba15b9ce593cc67d9efebc67c6bfc",
|
|
234
237
|
"schemas/summaries/agent.schema.json": "bf540f9a804f2b43756ab33b7deb0462620d26e88cc9379c75a5f87d3b1b47d8",
|
|
235
238
|
"schemas/summaries/command.schema.json": "c26f6965f77c5058608feb5e7b9f807395de8e015b0dea5efcdb44cb1820551a",
|
|
236
239
|
"schemas/summaries/hook.schema.json": "58420ec485e152fdd21fa3d87337ad74b0d81a48d3b83dd072d4a2d196f78573",
|
|
237
|
-
"schemas/summaries/markdown.schema.json": "
|
|
238
|
-
"schemas/summaries/skill.schema.json": "
|
|
239
|
-
"schemas/view-slots.schema.json": "
|
|
240
|
-
"versioning.md": "
|
|
240
|
+
"schemas/summaries/markdown.schema.json": "f7b2b5ae9e4836c94bb6a84edc730412f19296a6ef13552016690d7ba6f5391d",
|
|
241
|
+
"schemas/summaries/skill.schema.json": "a2e23e35fe1545fb7bb8a6bb87dcad2248afa5a0f23aebc089eb5464201f4654",
|
|
242
|
+
"schemas/view-slots.schema.json": "b151740016585ab2ba6cde376b071fc79ef1a1b484032216d841afeb593d06fd",
|
|
243
|
+
"versioning.md": "bab36cda6deb3edc29d7d40d97399ea4a213551257b0dd3321ddf95e2a60bff2"
|
|
241
244
|
}
|
|
242
245
|
}
|
|
243
246
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Security scanner interface
|
|
2
2
|
|
|
3
|
-
Normative contract for third-party security-scanning plugins (Snyk, Socket, custom rulesets, and similar). A security scanner is NOT a new extension kind
|
|
3
|
+
Normative contract for third-party security-scanning plugins (Snyk, Socket, custom rulesets, and similar). A security scanner is NOT a new extension kind, it is a **convention over the existing `Action` kind**. This document defines the convention so that:
|
|
4
4
|
|
|
5
5
|
- Multiple vendors can ship interoperable scanners.
|
|
6
6
|
- `sm findings` can aggregate findings across scanners uniformly.
|
|
@@ -33,7 +33,7 @@ Example manifest:
|
|
|
33
33
|
}
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
The kernel does NOT enforce the `security-` prefix
|
|
36
|
+
The kernel does NOT enforce the `security-` prefix, any Action may produce findings that conform to this schema. But `sm findings --security` and the UI's Security panel filter by prefix **OR** the `tags` label.
|
|
37
37
|
|
|
38
38
|
---
|
|
39
39
|
|
|
@@ -49,7 +49,7 @@ The Action receives a standard invocation: a single node, or (via `--all`) a set
|
|
|
49
49
|
|
|
50
50
|
i.e. applies to every node. A scanner MAY narrow to specific kinds if the vendor's check only applies to, for example, shell-hook content.
|
|
51
51
|
|
|
52
|
-
Scanners are **deterministic-mode** Actions by default: no LLM involvement. The Action runs its own logic (HTTP request to a vendor API, local regex scan, dependency check) and writes a report. Scanners MAY also be `probabilistic` Actions if the scanner relies on model analysis
|
|
52
|
+
Scanners are **deterministic-mode** Actions by default: no LLM involvement. The Action runs its own logic (HTTP request to a vendor API, local regex scan, dependency check) and writes a report. Scanners MAY also be `probabilistic` Actions if the scanner relies on model analysis, the same report shape applies.
|
|
53
53
|
|
|
54
54
|
---
|
|
55
55
|
|
|
@@ -105,7 +105,7 @@ Every scanner MUST produce a report conforming to this shape. It extends [`repor
|
|
|
105
105
|
|
|
106
106
|
### Field reference
|
|
107
107
|
|
|
108
|
-
**Scanner envelope** (`scanner.*`)
|
|
108
|
+
**Scanner envelope** (`scanner.*`), REQUIRED:
|
|
109
109
|
|
|
110
110
|
| Field | Type | Meaning |
|
|
111
111
|
|---|---|---|
|
|
@@ -115,7 +115,7 @@ Every scanner MUST produce a report conforming to this shape. It extends [`repor
|
|
|
115
115
|
| `ranAt` | integer | Unix ms. |
|
|
116
116
|
| `durationMs` | integer | How long the scan took. |
|
|
117
117
|
|
|
118
|
-
**Finding** (`findings[]`)
|
|
118
|
+
**Finding** (`findings[]`), ZERO OR MORE. Each finding MUST include:
|
|
119
119
|
|
|
120
120
|
| Field | Type | Meaning |
|
|
121
121
|
|---|---|---|
|
|
@@ -127,10 +127,10 @@ Every scanner MUST produce a report conforming to this shape. It extends [`repor
|
|
|
127
127
|
| `nodePath` | string | The `node.path` this finding references. |
|
|
128
128
|
| `locations` | array\|null | Optional in-file locations. Each has `line` (required), `column`, `length`, `raw`. |
|
|
129
129
|
| `references` | array\|null | External URLs (CVE, advisory, blog post). |
|
|
130
|
-
| `remediation` | object\|null | `summary` (string), `autofixable` (boolean). Autofix is advisory
|
|
130
|
+
| `remediation` | object\|null | `summary` (string), `autofixable` (boolean). Autofix is advisory, the kernel does not invoke it. |
|
|
131
131
|
| `meta` | object\|null | Vendor-specific free-form. CVSS, CWE, CPE, etc. |
|
|
132
132
|
|
|
133
|
-
**Stats** (`stats.*`)
|
|
133
|
+
**Stats** (`stats.*`), REQUIRED summary:
|
|
134
134
|
|
|
135
135
|
| Field | Type | Meaning |
|
|
136
136
|
|---|---|---|
|
|
@@ -141,13 +141,13 @@ Every scanner MUST produce a report conforming to this shape. It extends [`repor
|
|
|
141
141
|
|
|
142
142
|
A `category` value SHOULD be one of these for interoperability:
|
|
143
143
|
|
|
144
|
-
- `vulnerability
|
|
145
|
-
- `misconfiguration
|
|
146
|
-
- `credential-leak
|
|
147
|
-
- `injection-risk
|
|
148
|
-
- `license-violation
|
|
149
|
-
- `outdated
|
|
150
|
-
- `policy-violation
|
|
144
|
+
- `vulnerability`, known CVE, dependency advisory, version range with known exploit.
|
|
145
|
+
- `misconfiguration`, insecure default, exposed secret, weak permission, missing header.
|
|
146
|
+
- `credential-leak`, secret material (API key, token, password) detected in content.
|
|
147
|
+
- `injection-risk`, pattern likely to enable prompt injection, SQL injection, command injection.
|
|
148
|
+
- `license-violation`, incompatible license terms for a dependency or referenced asset.
|
|
149
|
+
- `outdated`, version pinned well below current, not exploited but due for upgrade.
|
|
150
|
+
- `policy-violation`, organization-level analyzer (naming, banned words, required disclaimer).
|
|
151
151
|
|
|
152
152
|
Vendors MAY introduce their own category with the prefix `vendor:<slug>` (e.g. `vendor:socket:supply-chain`). Consumers that don't understand a vendor category MUST treat it as opaque but still display it.
|
|
153
153
|
|
|
@@ -210,7 +210,7 @@ This is the only `summaries/*` schema that does NOT correspond to a node kind; i
|
|
|
210
210
|
|
|
211
211
|
## Compliance
|
|
212
212
|
|
|
213
|
-
A scanner that produces a report NOT conforming to `SecurityReport` is still a valid Action
|
|
213
|
+
A scanner that produces a report NOT conforming to `SecurityReport` is still a valid Action, but it does NOT show up in `sm findings --security` or the UI Security panel. Conforming is what unlocks the aggregation surface.
|
|
214
214
|
|
|
215
215
|
`sm plugins doctor` MAY emit a warning for Actions prefixed `security-` whose most recent report does not parse as `SecurityReport`.
|
|
216
216
|
|
|
@@ -218,10 +218,10 @@ A scanner that produces a report NOT conforming to `SecurityReport` is still a v
|
|
|
218
218
|
|
|
219
219
|
## See also
|
|
220
220
|
|
|
221
|
-
- [`../architecture.md`](../architecture.md)
|
|
222
|
-
- [`../job-lifecycle.md`](../job-lifecycle.md)
|
|
223
|
-
- [`../prompt-preamble.md`](../prompt-preamble.md)
|
|
224
|
-
- [`../db-schema.md`](../db-schema.md)
|
|
221
|
+
- [`../architecture.md`](../architecture.md), extension kinds (Action) and the kernel contract.
|
|
222
|
+
- [`../job-lifecycle.md`](../job-lifecycle.md), job submit/claim/record flow for scanner invocations.
|
|
223
|
+
- [`../prompt-preamble.md`](../prompt-preamble.md), `report-base` shape (safety + confidence) that scanner reports extend.
|
|
224
|
+
- [`../db-schema.md`](../db-schema.md), `state_executions` where scanner reports are persisted.
|
|
225
225
|
|
|
226
226
|
---
|
|
227
227
|
|
|
@@ -237,6 +237,6 @@ Locked for v0:
|
|
|
237
237
|
|
|
238
238
|
Open (may change pre-v1.0):
|
|
239
239
|
|
|
240
|
-
- The exact category enum
|
|
240
|
+
- The exact category enum, may grow or consolidate.
|
|
241
241
|
- Whether `tags: ["kind:scanner"]` in the manifest becomes normative (vs. just recommended).
|
|
242
242
|
- Whether scanners gain a dedicated CLI verb (`sm security scan`) in addition to `sm job submit security-<id>`.
|
package/job-events.md
CHANGED
|
@@ -161,9 +161,9 @@ Emitted when the runner is about to execute the job content.
|
|
|
161
161
|
}
|
|
162
162
|
```
|
|
163
163
|
|
|
164
|
-
`command` is implementation-defined free-form; it is descriptive, not invokable. `contentHash` references the row in `state_job_contents` the runner is about to execute against
|
|
164
|
+
`command` is implementation-defined free-form; it is descriptive, not invokable. `contentHash` references the row in `state_job_contents` the runner is about to execute against, useful for downstream observers that want to correlate the spawn with the rendered content (which is in DB, not on disk).
|
|
165
165
|
|
|
166
|
-
> **Hookable
|
|
166
|
+
> **Hookable**, see [`architecture.md` §Hook · curated trigger set](./architecture.md#hook--curated-trigger-set). Plugins MAY subscribe a `hook` extension to this event for pre-flight checks or audit logging. Reactions only, hooks cannot block the spawn.
|
|
167
167
|
|
|
168
168
|
### `model.delta`
|
|
169
169
|
|
|
@@ -204,14 +204,14 @@ Emitted inside `sm record` when the callback arrives and passes nonce validation
|
|
|
204
204
|
|
|
205
205
|
`executionId` references the just-written `state_executions` row whose `report_json` carries the report payload. Consumers that need the content fetch it via `sm history --json` or directly from the DB; the event itself stays small.
|
|
206
206
|
|
|
207
|
-
`runId` on this event is the run that originally claimed the job. If the record is called from outside a CLI run
|
|
207
|
+
`runId` on this event is the run that originally claimed the job. If the record is called from outside a CLI run, the canonical case being a Skill agent that called `sm job claim` + `sm record` without ever entering `sm job run`, the kernel MUST synthesize a `runId` of the form `r-ext-YYYYMMDD-HHMMSS-XXXX` (same timestamp + 4-hex shape as real run ids, with the `r-ext-` prefix reserved for externally-driven claims).
|
|
208
208
|
|
|
209
|
-
Synthetic-run envelope: when a Skill agent claims a job, the kernel MUST emit
|
|
209
|
+
Synthetic-run envelope: when a Skill agent claims a job, the kernel MUST emit, on the server's WebSocket and in the `--json` ndjson stream if active, a full envelope covering that claim:
|
|
210
210
|
|
|
211
211
|
```
|
|
212
212
|
run.started (mode="external")
|
|
213
213
|
→ job.claimed
|
|
214
|
-
→ (no job.spawning
|
|
214
|
+
→ (no job.spawning, the claim itself is the spawn signal for external runs)
|
|
215
215
|
→ job.callback.received
|
|
216
216
|
→ (job.completed | job.failed)
|
|
217
217
|
→ run.summary
|
|
@@ -239,9 +239,9 @@ Emitted when a job transitions to `completed`.
|
|
|
239
239
|
}
|
|
240
240
|
```
|
|
241
241
|
|
|
242
|
-
`executionId` references the `state_executions` row that holds the report payload (in `report_json`). The full report is intentionally NOT inlined in the event
|
|
242
|
+
`executionId` references the `state_executions` row that holds the report payload (in `report_json`). The full report is intentionally NOT inlined in the event, keep events small and let consumers query the row when they want the body.
|
|
243
243
|
|
|
244
|
-
> **Hookable
|
|
244
|
+
> **Hookable**, see [`architecture.md` §Hook · curated trigger set](./architecture.md#hook--curated-trigger-set). The most common hookable event: notification, billing, downstream dispatch.
|
|
245
245
|
|
|
246
246
|
### `job.failed`
|
|
247
247
|
|
|
@@ -264,7 +264,7 @@ Emitted when a job transitions to `failed` by any path.
|
|
|
264
264
|
|
|
265
265
|
`reason` enum matches [`execution-record.schema.json`](./schemas/execution-record.schema.json) `failureReason`. `message` is human-readable free-form; MAY be truncated for display.
|
|
266
266
|
|
|
267
|
-
> **Hookable
|
|
267
|
+
> **Hookable**, see [`architecture.md` §Hook · curated trigger set](./architecture.md#hook--curated-trigger-set). Hook subscribers commonly use this event for alerting and retry triggers. Filter by `data.reason` to narrow to a specific failure mode.
|
|
268
268
|
|
|
269
269
|
### `run.summary`
|
|
270
270
|
|
|
@@ -310,13 +310,13 @@ run.started
|
|
|
310
310
|
|
|
311
311
|
A parallel implementation MAY interleave per-job sequences across different `jobId` values, but MUST preserve ordering within a single `jobId`.
|
|
312
312
|
|
|
313
|
-
`job.failed` with reason `abandoned` MAY appear without a matching `job.claimed` in the current run
|
|
313
|
+
`job.failed` with reason `abandoned` MAY appear without a matching `job.claimed` in the current run, it refers to a job claimed in a previous run that expired before the next reap.
|
|
314
314
|
|
|
315
315
|
---
|
|
316
316
|
|
|
317
317
|
## Non-job events (Stability: experimental)
|
|
318
318
|
|
|
319
|
-
These event families cover kernel activity other than job execution. They share the common envelope (`type`, `timestamp`, `runId`, `jobId`, `data`). For non-job events `jobId` is always `null`; `runId` identifies the invocation that produced the event
|
|
319
|
+
These event families cover kernel activity other than job execution. They share the common envelope (`type`, `timestamp`, `runId`, `jobId`, `data`). For non-job events `jobId` is always `null`; `runId` identifies the invocation that produced the event, a scan gets an `r-scan-YYYYMMDD-HHMMSS-XXXX` id, an issue recomputation outside a scan gets an `r-check-...` id, following the same `r-<mode>-...` shape as the external-Skill synthetic envelope (`r-ext-...`).
|
|
320
320
|
|
|
321
321
|
The **shapes below are experimental through spec v0.x**. The reference impl starts emitting them at Step 13 alongside the WebSocket broadcaster; once real consumers exercise the stream, the fields lock. Bumping them to `stable` is a minor spec bump; changes to field shapes before `stable` are allowed without a major bump (per [`versioning.md`](./versioning.md) §Pre-1.0).
|
|
322
322
|
|
|
@@ -340,7 +340,7 @@ Emitted once when a scan begins (full, `--changed`, or `-n <node.path>`).
|
|
|
340
340
|
}
|
|
341
341
|
```
|
|
342
342
|
|
|
343
|
-
> **Hookable
|
|
343
|
+
> **Hookable**, see [`architecture.md` §Hook · curated trigger set](./architecture.md#hook--curated-trigger-set). Pre-scan setup, telemetry init.
|
|
344
344
|
|
|
345
345
|
#### `scan.progress`
|
|
346
346
|
|
|
@@ -379,11 +379,11 @@ Emitted once at scan end.
|
|
|
379
379
|
}
|
|
380
380
|
```
|
|
381
381
|
|
|
382
|
-
> **Hookable
|
|
382
|
+
> **Hookable**, see [`architecture.md` §Hook · curated trigger set](./architecture.md#hook--curated-trigger-set). Post-scan reaction (Slack notification, CI gate, summary email).
|
|
383
383
|
|
|
384
384
|
#### `extractor.completed`
|
|
385
385
|
|
|
386
|
-
Emitted once per registered Extractor, after the full walk completes. Aggregated, NOT per-node
|
|
386
|
+
Emitted once per registered Extractor, after the full walk completes. Aggregated, NOT per-node, per-node fan-out lives in `scan.progress`, which is intentionally not hookable.
|
|
387
387
|
|
|
388
388
|
```json
|
|
389
389
|
{
|
|
@@ -399,7 +399,7 @@ Emitted once per registered Extractor, after the full walk completes. Aggregated
|
|
|
399
399
|
|
|
400
400
|
`extractorId` is the qualified extension id (`<plugin-id>/<id>`).
|
|
401
401
|
|
|
402
|
-
> **Hookable
|
|
402
|
+
> **Hookable**, see [`architecture.md` §Hook · curated trigger set](./architecture.md#hook--curated-trigger-set). Per-Extractor metrics, audit. Filter by `data.extractorId` to scope to a single Extractor.
|
|
403
403
|
|
|
404
404
|
#### `analyzer.completed`
|
|
405
405
|
|
|
@@ -419,7 +419,7 @@ Emitted once per registered Analyzer, after every issue has been validated.
|
|
|
419
419
|
|
|
420
420
|
`analyzerId` is the qualified extension id.
|
|
421
421
|
|
|
422
|
-
> **Hookable
|
|
422
|
+
> **Hookable**, see [`architecture.md` §Hook · curated trigger set](./architecture.md#hook--curated-trigger-set). Per-Analyzer alerting, downstream tooling. Filter by `data.analyzerId`.
|
|
423
423
|
|
|
424
424
|
#### `action.completed`
|
|
425
425
|
|
|
@@ -441,7 +441,7 @@ Emitted once per Action invocation, after the report has been recorded.
|
|
|
441
441
|
|
|
442
442
|
`actionId` is the qualified extension id; `node` carries the target node summary (full `Node` shape per [`schemas/node.schema.json`](./schemas/node.schema.json) is forward-compatible). Lands alongside the job subsystem at Step 10.
|
|
443
443
|
|
|
444
|
-
> **Hookable
|
|
444
|
+
> **Hookable**, see [`architecture.md` §Hook · curated trigger set](./architecture.md#hook--curated-trigger-set). Per-Action notification, integration glue. Filter by `data.actionId`.
|
|
445
445
|
|
|
446
446
|
### Issue events
|
|
447
447
|
|
|
@@ -481,7 +481,7 @@ Emitted when an issue present in the previous scan is absent from the new one.
|
|
|
481
481
|
}
|
|
482
482
|
```
|
|
483
483
|
|
|
484
|
-
Issue diffing is keyed on `(analyzerId, nodeIds sorted, message)
|
|
484
|
+
Issue diffing is keyed on `(analyzerId, nodeIds sorted, message)`, same key → same issue. A payload change on the same key emits no event; consumers re-read full issue detail from `sm check` when needed.
|
|
485
485
|
|
|
486
486
|
---
|
|
487
487
|
|
|
@@ -507,9 +507,9 @@ Consumers MAY treat `emitter.error` as a soft failure (log and continue). Implem
|
|
|
507
507
|
|
|
508
508
|
## See also
|
|
509
509
|
|
|
510
|
-
- [`architecture.md`](./architecture.md)
|
|
511
|
-
- [`job-lifecycle.md`](./job-lifecycle.md)
|
|
512
|
-
- [`cli-contract.md`](./cli-contract.md)
|
|
510
|
+
- [`architecture.md`](./architecture.md), `ProgressEmitterPort` definition.
|
|
511
|
+
- [`job-lifecycle.md`](./job-lifecycle.md), state machine that drives these events.
|
|
512
|
+
- [`cli-contract.md`](./cli-contract.md), `--json` and `--stream-output` flag semantics.
|
|
513
513
|
|
|
514
514
|
---
|
|
515
515
|
|
|
@@ -525,4 +525,4 @@ The envelope (`type`, `timestamp`, `runId`, `jobId`, `data`) is stable. Adding a
|
|
|
525
525
|
|
|
526
526
|
The **non-job event families** (`scan.*`, `issue.*`, `extractor.completed`, `analyzer.completed`, `action.completed`) are marked **experimental** across spec v0.x. They ship alongside the WebSocket broadcaster at Step 13 of the reference impl; shapes may tighten before a stable tag lands. Once promoted to `stable` (a minor spec bump), the same add/remove/rename semantics as the job events apply.
|
|
527
527
|
|
|
528
|
-
The **Hook curated trigger set** (eight hookable lifecycle events; see [`architecture.md` §Hook · curated trigger set](./architecture.md#hook--curated-trigger-set)) is itself stable as of the same minor in which it lands: adding a hookable trigger is a minor bump, removing or renaming one is a major bump. The curation policy ("a hook subscribes only to a deliberately small set") is normative
|
|
528
|
+
The **Hook curated trigger set** (eight hookable lifecycle events; see [`architecture.md` §Hook · curated trigger set](./architecture.md#hook--curated-trigger-set)) is itself stable as of the same minor in which it lands: adding a hookable trigger is a minor bump, removing or renaming one is a major bump. The curation policy ("a hook subscribes only to a deliberately small set") is normative, surface noise reduction is the entire point.
|
package/job-lifecycle.md
CHANGED
|
@@ -39,7 +39,7 @@ Terminal states: `completed`, `failed`. Once terminal, a job MUST NOT transition
|
|
|
39
39
|
| `queued` | `running` | Atomic claim by a runner. |
|
|
40
40
|
| `queued` | `failed` | `sm job cancel <id>` (reason `user-cancelled`). |
|
|
41
41
|
| `running` | `completed` | `sm record --status completed` with valid nonce. |
|
|
42
|
-
| `running` | `failed` | `sm record --status failed`, OR TTL expired (reason `abandoned`), OR runner subprocess returned non-zero (reason `runner-error`), OR report failed schema validation (reason `report-invalid`), OR rendered content row missing at runtime (reason `job-file-missing
|
|
42
|
+
| `running` | `failed` | `sm record --status failed`, OR TTL expired (reason `abandoned`), OR runner subprocess returned non-zero (reason `runner-error`), OR report failed schema validation (reason `report-invalid`), OR rendered content row missing at runtime (reason `job-file-missing`, historically named for the on-disk artifact; now refers to a missing `state_job_contents` row, a DB-corruption-only state since the runtime invariant is that `state_jobs.content_hash` always resolves). |
|
|
43
43
|
|
|
44
44
|
Any other transition attempt MUST be rejected and MUST NOT mutate state. Implementations SHOULD log the attempt.
|
|
45
45
|
|
|
@@ -56,7 +56,7 @@ Any other transition attempt MUST be rejected and MUST NOT mutate state. Impleme
|
|
|
56
56
|
5. Compute `ttlSeconds` per §TTL resolution below. Frozen on `state_jobs.ttlSeconds` for the life of this job.
|
|
57
57
|
6. Resolve `priority` (integer, default `0`). Precedence (lowest → highest): action manifest `defaultPriority` → user config `jobs.perActionPriority.<actionId>` → flag `--priority <n>`. Higher runs first; ties broken by `createdAt ASC`. Negative values are permitted and run after the default bucket. The resolved value is frozen on `state_jobs.priority` at submit time and is immutable for the life of the job.
|
|
58
58
|
7. Generate `nonce` (implementation-chosen; MUST be cryptographically random, ≥ 128 bits of entropy).
|
|
59
|
-
8. Render the rendered job content (canonical preamble + action template + interpolated user content per [`prompt-preamble.md`](./prompt-preamble.md)) and write it to `state_job_contents` via `INSERT OR IGNORE` keyed by `content_hash`. Multiple `state_jobs` rows MAY share the same `content_hash` row: the content is stored exactly once and refcounted by reference. Implementations MUST NOT persist the rendered content to a filesystem path
|
|
59
|
+
8. Render the rendered job content (canonical preamble + action template + interpolated user content per [`prompt-preamble.md`](./prompt-preamble.md)) and write it to `state_job_contents` via `INSERT OR IGNORE` keyed by `content_hash`. Multiple `state_jobs` rows MAY share the same `content_hash` row: the content is stored exactly once and refcounted by reference. Implementations MUST NOT persist the rendered content to a filesystem path, the DB row is the canonical artifact.
|
|
60
60
|
9. Insert a row in `state_jobs` with `status = 'queued'`, `createdAt = now`. The row's `content_hash` references the just-stored `state_job_contents.content_hash`. Steps 8 and 9 MUST run inside one transaction.
|
|
61
61
|
10. Return the job id.
|
|
62
62
|
|
|
@@ -87,7 +87,7 @@ UPDATE state_jobs
|
|
|
87
87
|
|
|
88
88
|
The second `AND status = 'queued'` guards against a race where two runners select the same id at the same instant; only one succeeds.
|
|
89
89
|
|
|
90
|
-
**Non-SQLite implementations**: MUST provide an equivalent single-statement atomic transition. A two-step `SELECT then UPDATE` is NOT acceptable
|
|
90
|
+
**Non-SQLite implementations**: MUST provide an equivalent single-statement atomic transition. A two-step `SELECT then UPDATE` is NOT acceptable, it is observable as a double-claim bug.
|
|
91
91
|
|
|
92
92
|
`sm job claim` exposes this primitive to Skill agents (and any driving adapter that wants to drain from outside a CLI-runner loop): returns the id on stdout (exit 0) or exits 1 if the queue is empty.
|
|
93
93
|
|
|
@@ -120,7 +120,7 @@ Implementations MAY expose `sm job reap` as an explicit verb for diagnostics, bu
|
|
|
120
120
|
|
|
121
121
|
The kernel resolves the effective TTL for a new job in three conceptual steps. The resolved value is written to `state_jobs.ttlSeconds` at submit time and is immutable for the life of the job.
|
|
122
122
|
|
|
123
|
-
#### Step 1
|
|
123
|
+
#### Step 1, Base duration
|
|
124
124
|
|
|
125
125
|
A seconds integer that represents how long the action is expected to run before the grace multiplier kicks in:
|
|
126
126
|
|
|
@@ -129,7 +129,7 @@ A seconds integer that represents how long the action is expected to run before
|
|
|
129
129
|
|
|
130
130
|
The base duration exists even for actions that cannot estimate their own runtime (typically `mode: local`); the global config value ensures the formula below is always well-defined.
|
|
131
131
|
|
|
132
|
-
#### Step 2
|
|
132
|
+
#### Step 2, Computed TTL
|
|
133
133
|
|
|
134
134
|
```
|
|
135
135
|
computed = max(base × jobs.graceMultiplier, jobs.minimumTtlSeconds)
|
|
@@ -139,12 +139,12 @@ Config defaults: `jobs.graceMultiplier = 3`, `jobs.minimumTtlSeconds = 60`.
|
|
|
139
139
|
|
|
140
140
|
`minimumTtlSeconds` is a **floor**, not a default. It guarantees no job is claimed with a sub-minute deadline regardless of how small the base duration is. It never participates as an initial value.
|
|
141
141
|
|
|
142
|
-
#### Step 3
|
|
142
|
+
#### Step 3, User overrides
|
|
143
143
|
|
|
144
144
|
Two optional overrides, evaluated in order; the later one wins and replaces everything above it:
|
|
145
145
|
|
|
146
|
-
1. Config `jobs.perActionTtl.<actionId
|
|
147
|
-
2. Flag `sm job submit --ttl <seconds
|
|
146
|
+
1. Config `jobs.perActionTtl.<actionId>`, integer seconds. Replaces the computed TTL entirely; the formula is skipped for that action id.
|
|
147
|
+
2. Flag `sm job submit --ttl <seconds>`, integer seconds. Highest precedence. Replaces anything.
|
|
148
148
|
|
|
149
149
|
Negative or zero values MUST be rejected with exit 2 at submit time.
|
|
150
150
|
|
|
@@ -152,10 +152,10 @@ Negative or zero values MUST be rejected with exit 2 at submit time.
|
|
|
152
152
|
|
|
153
153
|
| Action manifest | Config | Flag | Result |
|
|
154
154
|
|---|---|---|---|
|
|
155
|
-
| `expectedDurationSeconds: 120` | defaults
|
|
156
|
-
| none | defaults
|
|
157
|
-
| `expectedDurationSeconds: 10` | defaults
|
|
158
|
-
| `expectedDurationSeconds: 120` | `jobs.perActionTtl.foo: 900`
|
|
155
|
+
| `expectedDurationSeconds: 120` | defaults |, | `max(120 × 3, 60) = 360` |
|
|
156
|
+
| none | defaults |, | `max(3600 × 3, 60) = 10800` |
|
|
157
|
+
| `expectedDurationSeconds: 10` | defaults |, | `max(10 × 3, 60) = 60` (floor bites) |
|
|
158
|
+
| `expectedDurationSeconds: 120` | `jobs.perActionTtl.foo: 900` |, | `900` (override skips formula) |
|
|
159
159
|
| any | any | `--ttl 45` | `45` (flag wins outright) |
|
|
160
160
|
|
|
161
161
|
---
|
|
@@ -167,14 +167,14 @@ Negative or zero values MUST be rejected with exit 2 at submit time.
|
|
|
167
167
|
1. Load the job by id. If not found → exit 5.
|
|
168
168
|
2. Compare the supplied nonce against `state_jobs.nonce`. Mismatch → exit 4 without mutation.
|
|
169
169
|
3. If `state_jobs.status != 'running'` → exit 2 with message "job not in running state". This catches late callbacks after a reap.
|
|
170
|
-
4. If `--status completed`: read the report payload from the path passed to `--report` (the path is implementation-input only; the kernel reads its contents and stores them inline
|
|
170
|
+
4. If `--status completed`: read the report payload from the path passed to `--report` (the path is implementation-input only; the kernel reads its contents and stores them inline, there is no canonical on-disk report artifact), validate the parsed JSON against the action's declared report schema. On validation failure → transition to `failed` with reason `report-invalid`; DO NOT stay `running`.
|
|
171
171
|
5. Write the execution record (see [`schemas/execution-record.schema.json`](./schemas/execution-record.schema.json)) with the full metrics. The report payload (if any) is stored inline in `state_executions.report_json` as the parsed JSON; the input path is NOT retained.
|
|
172
172
|
6. Transition the job to the terminal state.
|
|
173
173
|
7. Emit `job.callback.received` followed by `job.completed` or `job.failed` (see [`job-events.md`](./job-events.md)).
|
|
174
174
|
|
|
175
175
|
The nonce is the sole authentication factor. A compromised nonce allows forged callbacks for that single job. Nonces MUST be generated per-job; never reused; never logged at info level or above.
|
|
176
176
|
|
|
177
|
-
`--report` accepts either a file path or `-` (stdin). Drivers MAY choose either form; the kernel ingests both into `report_json` identically. The on-disk file the runner authored is ephemeral
|
|
177
|
+
`--report` accepts either a file path or `-` (stdin). Drivers MAY choose either form; the kernel ingests both into `report_json` identically. The on-disk file the runner authored is ephemeral, implementations SHOULD remove it after the kernel acknowledges the callback (this is a courtesy GC, not a normative requirement).
|
|
178
178
|
|
|
179
179
|
---
|
|
180
180
|
|
|
@@ -194,7 +194,7 @@ Post-completion, the check is NOT performed: resubmitting a completed job is alw
|
|
|
194
194
|
|
|
195
195
|
## Concurrency
|
|
196
196
|
|
|
197
|
-
Through `v1.0` (spec `v0.x`): **one job at a time**. `sm job run --all` drains sequentially. Enforced by the claim semantics above
|
|
197
|
+
Through `v1.0` (spec `v0.x`): **one job at a time**. `sm job run --all` drains sequentially. Enforced by the claim semantics above, there is no pool or scheduler.
|
|
198
198
|
|
|
199
199
|
The event schema carries a `jobId` on every event specifically so that parallel execution becomes a non-breaking extension. A future implementation MAY spawn multiple claim/run loops concurrently and interleave events; consumers identify which job an event belongs to by `jobId`.
|
|
200
200
|
|
|
@@ -208,7 +208,7 @@ Implementations MUST handle each of the following:
|
|
|
208
208
|
|
|
209
209
|
| Scenario | Required handling |
|
|
210
210
|
|---|---|
|
|
211
|
-
| `state_jobs` row exists but its `content_hash` is missing from `state_job_contents` (DB corruption
|
|
211
|
+
| `state_jobs` row exists but its `content_hash` is missing from `state_job_contents` (DB corruption, the content row was deleted by external means). | Mark `failed` with `failureReason = job-file-missing`. `sm doctor` MUST report these proactively. The kernel does NOT itself produce this state under normal operation; the contract is that submit and prune both keep the two tables consistent. The legacy enum name `job-file-missing` is preserved across the disk-to-DB shift to keep the failure-reason vocabulary backward-compatible, the semantic now refers to a missing content row rather than a missing on-disk file. |
|
|
212
212
|
| `state_job_contents` row references no live `state_jobs` row (GC straggler). | `sm doctor` MUST list them. `sm job prune` MUST collect them in the same transaction that prunes terminal jobs. |
|
|
213
213
|
| Runner crashes between `claim` and reading the content. | Covered by TTL/reap: when `expiresAt` passes, the next reap marks the job `failed` with `abandoned`. |
|
|
214
214
|
| Callback arrives after reap already failed the job. | Reject with exit 2 (see Record step 3). The runner should treat this as an error and log it. |
|
|
@@ -242,11 +242,11 @@ Config controls (`jobs.retention.completed`, `jobs.retention.failed`):
|
|
|
242
242
|
|
|
243
243
|
## See also
|
|
244
244
|
|
|
245
|
-
- [`architecture.md`](./architecture.md)
|
|
246
|
-
- [`job-events.md`](./job-events.md)
|
|
247
|
-
- [`prompt-preamble.md`](./prompt-preamble.md)
|
|
248
|
-
- [`db-schema.md`](./db-schema.md)
|
|
249
|
-
- [`cli-contract.md`](./cli-contract.md)
|
|
245
|
+
- [`architecture.md`](./architecture.md), `RunnerPort` definition; driving-adapter peer analyzer for Skill agents.
|
|
246
|
+
- [`job-events.md`](./job-events.md), canonical event stream emitted during job execution.
|
|
247
|
+
- [`prompt-preamble.md`](./prompt-preamble.md), verbatim preamble prepended to every rendered job content row.
|
|
248
|
+
- [`db-schema.md`](./db-schema.md), `state_jobs` and `state_executions` table catalogs.
|
|
249
|
+
- [`cli-contract.md`](./cli-contract.md), `sm job` verb surface and exit codes.
|
|
250
250
|
|
|
251
251
|
---
|
|
252
252
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skill-map/spec",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "JSON Schemas, prose contracts, and conformance suite for the skill-map specification.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -49,7 +49,8 @@
|
|
|
49
49
|
"spec:check": "node scripts/build-index.js --check && node scripts/check-coverage.js",
|
|
50
50
|
"pin": "node scripts/sync-pin.js",
|
|
51
51
|
"pin:check": "node scripts/sync-pin.js --check",
|
|
52
|
-
"validate": "npm run
|
|
52
|
+
"validate": "npm run validate:compile",
|
|
53
|
+
"validate:compile": "npm run spec:check && npm run pin:check"
|
|
53
54
|
},
|
|
54
55
|
"publishConfig": {
|
|
55
56
|
"access": "public"
|