@skill-map/spec 0.22.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/README.md +4 -4
  3. package/architecture.md +130 -119
  4. package/cli-contract.md +102 -96
  5. package/conformance/README.md +13 -13
  6. package/conformance/coverage.md +41 -38
  7. package/db-schema.md +45 -45
  8. package/index.json +40 -37
  9. package/interfaces/security-scanner.md +20 -20
  10. package/job-events.md +21 -21
  11. package/job-lifecycle.md +21 -21
  12. package/package.json +1 -1
  13. package/plugin-author-guide.md +133 -108
  14. package/plugin-kv-api.md +10 -10
  15. package/prompt-preamble.md +8 -8
  16. package/schemas/annotations.schema.json +3 -3
  17. package/schemas/api/rest-envelope.schema.json +10 -10
  18. package/schemas/conformance-result.schema.json +120 -0
  19. package/schemas/execution-record.schema.json +2 -2
  20. package/schemas/extensions/analyzer.schema.json +9 -0
  21. package/schemas/extensions/base.schema.json +4 -4
  22. package/schemas/extensions/extractor.schema.json +4 -4
  23. package/schemas/extensions/formatter.schema.json +1 -1
  24. package/schemas/extensions/hook.schema.json +3 -3
  25. package/schemas/extensions/provider.schema.json +5 -5
  26. package/schemas/frontmatter/base.schema.json +1 -1
  27. package/schemas/history-stats.schema.json +4 -4
  28. package/schemas/input-types.schema.json +3 -3
  29. package/schemas/issue.schema.json +1 -1
  30. package/schemas/job.schema.json +2 -2
  31. package/schemas/node.schema.json +5 -5
  32. package/schemas/plugins-doctor.schema.json +97 -0
  33. package/schemas/plugins-registry.schema.json +2 -2
  34. package/schemas/project-config.schema.json +9 -9
  35. package/schemas/refresh-report.schema.json +52 -0
  36. package/schemas/report-base-deterministic.schema.json +1 -1
  37. package/schemas/sidecar.schema.json +3 -3
  38. package/schemas/summaries/markdown.schema.json +1 -1
  39. package/schemas/summaries/skill.schema.json +1 -1
  40. package/schemas/view-slots.schema.json +7 -7
  41. package/versioning.md +7 -7
package/index.json CHANGED
@@ -174,20 +174,20 @@
174
174
  }
175
175
  ]
176
176
  },
177
- "specPackageVersion": "0.22.0",
177
+ "specPackageVersion": "0.23.0",
178
178
  "integrity": {
179
179
  "algorithm": "sha256",
180
180
  "files": {
181
- "CHANGELOG.md": "8e8333f49fecfe1b7a36efe23ede8ca17edc6caa5123b9a816b693feaa913e56",
182
- "README.md": "b551522ab0c7f5ef702e9ea4d4f67fd7ad838b080d85975c2834d8d40af14a00",
183
- "architecture.md": "ca37e20cbe61a52c156a34f5ea2d660c3b920dfcda40cdb5601b5eac11f8fc21",
184
- "cli-contract.md": "49a2f8042868f32f42a2504bc1c7e07d14642dc4f354c8ff6833d3a5a97a9a76",
185
- "conformance/README.md": "70e3101104765ef359d5322d0a7c9248d2157f78a510fb2cc8005b4eba3173d6",
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": "c35846bea401fcb1f4fd6e26f6ef8f6459ab46b48757f9b3f39c137636628260",
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",
@@ -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": "8d0725443ae4cf1231378b8bbadcae46b32cb1b6cae06fb98865005debb080a1",
203
- "interfaces/security-scanner.md": "aefe9f02f190615ba18649df03c1bdd79d98691039563c659e90f34362e5f1d5",
204
- "job-events.md": "b223bf0e576cbd481688e163ab3ce0a6e952a8a4a3912f1342237b664984e388",
205
- "job-lifecycle.md": "1d9c42632f8e77ef58ff47ae6d9680e7ed5939760627c75253aab8c80f728fd1",
206
- "plugin-author-guide.md": "c77d5ac616d0f8ce029ef183cc4d29a480ffc50a0910320ed95a26cf1b33bce9",
207
- "plugin-kv-api.md": "673e0a65825ba1aabf9b4ba0b4e0d5baf8e81dc5de1c13bee9532fbb33e7b440",
208
- "prompt-preamble.md": "4860c310ccf2823870d318993ad8f067571799dade90bddb6634c3dbedd636b7",
209
- "schemas/annotations.schema.json": "b3a9aa66de17058ccfd890ea9ff1b9ee315a0877e9dd4a58fd8b76e26a99d00e",
210
- "schemas/api/rest-envelope.schema.json": "80d5480ebb96d41de497f35e4e5415025e0b69d1b424435c6b0d3a45945e2f63",
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/execution-record.schema.json": "9628fa557cb856402f3a5f1d1167c609e46a197c850fe8171abfddd46c1028a8",
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": "6272e5959f3c94e109e6116f7ed6b5ae35e4e3aea821a3c30742d11c5ab5838f",
216
- "schemas/extensions/base.schema.json": "528083fb7db8bd064147224999e1bb3959ee2061863f55f48e928c27222cf957",
217
- "schemas/extensions/extractor.schema.json": "a859a53a7a5b009b1fe20d322bc1a8ff62e4b91ef938e98b1c80c802bd734b37",
218
- "schemas/extensions/formatter.schema.json": "2ab092aa37ae349c69b93071ed4f0e131affb7bb5799516ca82c721262631b36",
219
- "schemas/extensions/hook.schema.json": "a55cec50f6fda5b924de86359b910d22548d0a5bb61b2051edb82a80d3b36a2b",
220
- "schemas/extensions/provider.schema.json": "c33219571b7bf5a80f8424c302e85f779895fd6a71daec58d0948be609b1310a",
221
- "schemas/frontmatter/base.schema.json": "ec4abde950c31639974fc078e6bdc74ed48da4d2c0a996f5248684406910a178",
222
- "schemas/history-stats.schema.json": "23f472d1de06d23fc775aabba821f8375f347af4dc8d89ba567980d61a11f9de",
223
- "schemas/input-types.schema.json": "f1f51ccda746ea3c8a404757f60c89e403619e88ec4137a50af100ec89f8f4b5",
224
- "schemas/issue.schema.json": "0bbc1783ad07cb5c3c2399d7a560f57314a9ff76ed061b4a198ddf7ce74dad78",
225
- "schemas/job.schema.json": "ffbdd51c54b487c44eb57fabd07f624ac1030c14ef69b46933c154092853a84c",
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": "2ede4385e796cbf416c494d810dcb6d6036b35e71561efee46f5675bf0a015fe",
228
- "schemas/plugins-registry.schema.json": "678f476cf460d0b5876a92e72e0d572b6db265dd9fad6e95db553c56f77db5d9",
229
- "schemas/project-config.schema.json": "a34fc136e606fe9700228a836d1211add068613226ef16239af1101843aef76e",
230
- "schemas/report-base-deterministic.schema.json": "6f8b38c097994ee87e0639935c42b5e85d8ea4244959ca397978171b0d7d2222",
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": "119f71e943a3d9305e25e26e1d8b3b525a391af0a7547d8f8a79de96b016e07c",
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": "33e2a1a11ec08a860c0c220609235c6fbdfda9ce19b6d65238f467f132ed4e54",
238
- "schemas/summaries/skill.schema.json": "f01bab92c51d64ee23e61587e42cf0dc5b37a2f518f5b12b3d1d456390338aa8",
239
- "schemas/view-slots.schema.json": "59a6fd09af79d38dd16ae90dd3fe2965069335941909bc5b7f78110f3ec019fd",
240
- "versioning.md": "996e62006423edc01151a6f7869605f76c5e1454cc30b38d9f616925b5bcfb64"
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 it is a **convention over the existing `Action` kind**. This document defines the convention so that:
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 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.
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 the same report shape applies.
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.*`) REQUIRED:
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[]`) ZERO OR MORE. Each finding MUST include:
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 the kernel does not invoke it. |
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.*`) REQUIRED summary:
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` 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).
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 but it does NOT show up in `sm findings --security` or the UI Security panel. Conforming is what unlocks the aggregation surface.
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) 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.
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 may grow or consolidate.
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 useful for downstream observers that want to correlate the spawn with the rendered content (which is in DB, not on disk).
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** 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.
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 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).
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 on the server's WebSocket and in the `--json` ndjson stream if active a full envelope covering that claim:
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 the claim itself is the spawn signal for external runs)
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 keep events small and let consumers query the row when they want the body.
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** see [`architecture.md` §Hook · curated trigger set](./architecture.md#hook--curated-trigger-set). The most common hookable event: notification, billing, downstream dispatch.
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** 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.
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 it refers to a job claimed in a previous run that expired before the next reap.
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 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-...`).
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** see [`architecture.md` §Hook · curated trigger set](./architecture.md#hook--curated-trigger-set). Pre-scan setup, telemetry init.
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** see [`architecture.md` §Hook · curated trigger set](./architecture.md#hook--curated-trigger-set). Post-scan reaction (Slack notification, CI gate, summary email).
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 per-node fan-out lives in `scan.progress`, which is intentionally not hookable.
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** 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.
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** see [`architecture.md` §Hook · curated trigger set](./architecture.md#hook--curated-trigger-set). Per-Analyzer alerting, downstream tooling. Filter by `data.analyzerId`.
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** see [`architecture.md` §Hook · curated trigger set](./architecture.md#hook--curated-trigger-set). Per-Action notification, integration glue. Filter by `data.actionId`.
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)` 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.
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) `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.
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 surface noise reduction is the entire point.
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` 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). |
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 the DB row is the canonical artifact.
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 it is observable as a double-claim bug.
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 Base duration
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 Computed TTL
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 User overrides
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>` 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.
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 | | `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) |
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 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`.
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 implementations SHOULD remove it after the kernel acknowledges the callback (this is a courtesy GC, not a normative requirement).
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 there is no pool or scheduler.
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 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. |
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) `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.
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.22.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",