@skill-map/spec 0.52.0 → 0.54.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 +32 -0
- package/README.md +12 -10
- package/architecture.md +154 -150
- package/cli-contract.md +138 -141
- package/conformance/README.md +9 -9
- package/conformance/cases/sidecar-end-to-end.json +3 -5
- package/conformance/coverage.md +5 -5
- package/db-schema.md +72 -72
- package/index.json +20 -19
- package/interfaces/security-scanner.md +25 -25
- package/job-events.md +43 -43
- package/job-lifecycle.md +32 -36
- package/package.json +2 -1
- package/plugin-author-guide.md +97 -125
- package/plugin-kv-api.md +22 -23
- package/plugin-quickstart.md +96 -0
- package/prompt-preamble.md +6 -6
- package/schemas/extensions/action.schema.json +6 -0
- package/schemas/project-config.schema.json +4 -0
- package/telemetry.md +120 -136
- package/versioning.md +12 -12
package/telemetry.md
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
# Telemetry
|
|
2
2
|
|
|
3
|
-
skill-map is
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
**OFF by default**.
|
|
3
|
+
skill-map is local-first; by default it sends **nothing** off the operator's
|
|
4
|
+
machine. This is the normative contract for the optional exceptions: two
|
|
5
|
+
independently-consented, anonymous telemetry surfaces, both **OFF by default**.
|
|
7
6
|
|
|
8
|
-
- **Error reporting** (Sentry), so crashes
|
|
9
|
-
|
|
10
|
-
- **Usage analytics** (PostHog), so the maintainers
|
|
11
|
-
built-in extensions are
|
|
12
|
-
roadmap accordingly.
|
|
7
|
+
- **Error reporting** (Sentry), so crashes in installations the maintainers do
|
|
8
|
+
not control can be learned about and fixed.
|
|
9
|
+
- **Usage analytics** (PostHog), so the maintainers learn which verbs and
|
|
10
|
+
built-in extensions are used in the wild and prioritise the roadmap.
|
|
13
11
|
|
|
14
|
-
The two surfaces share one consent prompt, one kill switch, and one
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
The two surfaces share one consent prompt, one kill switch, and one scrubber,
|
|
13
|
+
but each has its own carrier, toggle, and stability contract. Either can be
|
|
14
|
+
shipped independently.
|
|
17
15
|
|
|
18
16
|
## Scope and non-goals
|
|
19
17
|
|
|
@@ -24,10 +22,10 @@ In scope:
|
|
|
24
22
|
runtime errors in the browser UI, plus a small fixed set of triage tags
|
|
25
23
|
(`surface`, `verb`, `phase`, `plugin_id` for built-ins, `extension_kind`,
|
|
26
24
|
`route`, `method`, `status`).
|
|
27
|
-
- **Usage.** Which `sm` verb ran and the NAMES of
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
- **Usage.** Which `sm` verb ran and the NAMES of its flags; the set of
|
|
26
|
+
built-in extension ids that executed during a scan (presence, not volume);
|
|
27
|
+
which UI view or feature was opened. Plus environment facts (`cli_version`,
|
|
28
|
+
`node_major`, `os`, `arch`).
|
|
31
29
|
|
|
32
30
|
Out of scope (MUST NOT be collected under this contract, on either surface):
|
|
33
31
|
|
|
@@ -40,82 +38,75 @@ Out of scope (MUST NOT be collected under this contract, on either surface):
|
|
|
40
38
|
- **Any cross-session or cross-install correlation identifier**, with one
|
|
41
39
|
documented exception: the single anonymous usage `distinct_id`
|
|
42
40
|
(`telemetry.anonymousId`, below), which carries no identity and exists only
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
to de-duplicate usage events from the same install. The error surface
|
|
42
|
+
carries no correlation id at all.
|
|
45
43
|
|
|
46
44
|
## Consent contract (shared)
|
|
47
45
|
|
|
48
|
-
Both surfaces are **OFF by default
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
Both surfaces are **OFF by default**, running only after the operator opts in.
|
|
47
|
+
Consent state lives in the user-settings file at `~/.skill-map/settings.json`
|
|
48
|
+
under the `telemetry` object (see
|
|
51
49
|
[`user-settings.schema.json`](./schemas/user-settings.schema.json) and the
|
|
52
50
|
narrow `$HOME` exception in [`cli-contract.md`](./cli-contract.md) §User-settings file):
|
|
53
51
|
|
|
54
|
-
- `telemetry.errorsEnabled`
|
|
55
|
-
`
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
- `telemetry.usageUiEnabled` (boolean). Opt-in for UI usage analytics. Absent
|
|
59
|
-
or `false` MUST be treated as OFF.
|
|
52
|
+
- `telemetry.errorsEnabled`, `telemetry.usageCliEnabled`,
|
|
53
|
+
`telemetry.usageUiEnabled` (booleans). Opt-in for error reporting, CLI usage
|
|
54
|
+
analytics, and UI usage analytics respectively. For each, absent or `false`
|
|
55
|
+
MUST be treated as OFF.
|
|
60
56
|
- `telemetry.anonymousId` (string UUID, or null). The PostHog `distinct_id`
|
|
61
57
|
for the usage surface. Minted once when any usage toggle first becomes
|
|
62
58
|
`true`; never regenerated. The single allowed anonymous correlation id,
|
|
63
59
|
scoped to usage only.
|
|
64
|
-
- `telemetry.firstRunAt` (integer milliseconds, or null).
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
consent prompt was shown so it is never shown twice.
|
|
60
|
+
- `telemetry.firstRunAt` (integer milliseconds, or null). The first run on
|
|
61
|
+
which the prompt was eligible, so it can be deferred to the next eligible run.
|
|
62
|
+
- `telemetry.promptedAt` (integer milliseconds, or null). When the consent
|
|
63
|
+
prompt was shown, so it is never shown twice.
|
|
69
64
|
|
|
70
65
|
Rules:
|
|
71
66
|
|
|
72
67
|
1. **Default OFF.** When a toggle is absent or `false`, the matching SDK is
|
|
73
68
|
not initialised, no endpoint is contacted, and there is zero added latency.
|
|
74
|
-
|
|
69
|
+
MUST hold on every surface (CLI, BFF, UI).
|
|
75
70
|
2. **One shared consent prompt, TTY only, deferred to the second eligible
|
|
76
71
|
run.** A run is "eligible" when the prompt could appear: an interactive
|
|
77
72
|
terminal (`process.stdout.isTTY` true), at least one carrier configured
|
|
78
73
|
(a Sentry DSN or the PostHog key non-empty), the kill switch unset, and
|
|
79
74
|
`promptedAt` absent. The CLI MUST NOT prompt on the FIRST eligible run, it
|
|
80
|
-
only stamps `firstRunAt
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
`
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
75
|
+
only stamps `firstRunAt`, so the operator's first `sm` invocation is not
|
|
76
|
+
asked two things at once (a first `sm scan` may already prompt for the
|
|
77
|
+
provider lens). The NEXT eligible run shows the interactive prompt
|
|
78
|
+
(yes (default) / no / details). A single **yes** sets `errorsEnabled`,
|
|
79
|
+
`usageCliEnabled`, and `usageUiEnabled` all to `true` and mints
|
|
80
|
+
`anonymousId`; a **no** sets all three to `false` and mints nothing. Either
|
|
81
|
+
way it stamps `promptedAt`. On a non-eligible run (non-TTY CI, pipes)
|
|
82
|
+
nothing is asked or recorded and every surface stays OFF.
|
|
88
83
|
3. **Asked once.** Once `promptedAt` is set, the prompt MUST NOT be shown
|
|
89
|
-
again
|
|
90
|
-
4. **Env override.**
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
all surfaces.
|
|
84
|
+
again; the persisted toggles are authoritative thereafter.
|
|
85
|
+
4. **Env override.** `SKILL_MAP_TELEMETRY=0` forces OFF on every surface
|
|
86
|
+
(errors and both usage toggles) regardless of persisted settings. It is a
|
|
87
|
+
kill switch, not a toggle: no value of it forces ON. Exactly one
|
|
88
|
+
kill-switch variable covers all surfaces.
|
|
95
89
|
5. **Independent toggles.** After the first run, the operator changes consent
|
|
96
|
-
through the Settings UI (persisted via the BFF), the
|
|
97
|
-
|
|
98
|
-
`
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
6. **Anonymous id.** `anonymousId` is a random UUID v4 with no personal data
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
same id; it MUST NOT be writable over the wire.
|
|
90
|
+
through the Settings UI (persisted via the BFF), like the update-check
|
|
91
|
+
toggle. The three toggles are independent: `usageCliEnabled` and
|
|
92
|
+
`usageUiEnabled` can each be turned off without affecting the other or
|
|
93
|
+
`errorsEnabled`. Because the CLI reads `~/.skill-map/settings.json` fresh
|
|
94
|
+
per invocation, turning CLI usage off from the browser is honoured on the
|
|
95
|
+
next `sm` run. There is intentionally no dedicated `sm config` key:
|
|
96
|
+
`sm config` writes project-local settings, these flags are per-machine.
|
|
97
|
+
A future `sm telemetry` verb family MAY expose status and toggling from
|
|
98
|
+
the CLI.
|
|
99
|
+
6. **Anonymous id.** `anonymousId` is a random UUID v4 with no personal data,
|
|
100
|
+
minted once the first time any usage toggle becomes `true` (consent prompt
|
|
101
|
+
or Settings enable), never regenerated for the life of the install. It is
|
|
102
|
+
the PostHog `distinct_id` shared by the CLI and UI usage surfaces. The BFF
|
|
103
|
+
exposes it read-only (see below) so the browser uses the same id; it MUST
|
|
104
|
+
NOT be writable over the wire.
|
|
112
105
|
|
|
113
106
|
## Surface: Errors (Sentry)
|
|
114
107
|
|
|
115
|
-
Three surfaces report independently so a crash
|
|
116
|
-
layer
|
|
117
|
-
BFF) share one project and are told apart by a `surface` tag, the browser UI
|
|
118
|
-
reports to its own project.
|
|
108
|
+
Three surfaces report independently so a crash is attributed to the right
|
|
109
|
+
layer, across **two** Sentry projects.
|
|
119
110
|
|
|
120
111
|
| Surface | Runtime | Discriminator | Project |
|
|
121
112
|
|---|---|---|---|
|
|
@@ -123,21 +114,19 @@ reports to its own project.
|
|
|
123
114
|
| `sm serve` BFF | Node (Hono) | `surface: bff` tag | shared Node project |
|
|
124
115
|
| UI | Browser (Angular) | own project | `skill-map-ui` |
|
|
125
116
|
|
|
126
|
-
The two Node surfaces share one project
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
for the UI), centralized in `src/public-config.ts` and
|
|
117
|
+
The two Node surfaces share one project (same workspace code, same runtime); the
|
|
118
|
+
`surface` tag plus the per-event `route` / `method` tags separate a CLI crash
|
|
119
|
+
from a BFF request-path crash. The UI has its own project and needs no `surface`
|
|
120
|
+
tag. Each project carries a hardcoded DSN (`SENTRY_DSN_NODE` for the shared Node
|
|
121
|
+
project, `SENTRY_DSN_UI` for the UI), centralized in `src/public-config.ts` and
|
|
132
122
|
`ui/src/app/core/public-config.ts`. Sentry DSNs are public by design (they
|
|
133
|
-
identify an ingest endpoint,
|
|
134
|
-
|
|
135
|
-
unhandled errors in the request path.
|
|
123
|
+
identify an ingest endpoint, not secrets) and safe to ship. The BFF MUST NOT
|
|
124
|
+
emit usage events; it reports only unhandled errors in the request path.
|
|
136
125
|
|
|
137
126
|
The error surfaces send **no proactive beacons**: no release-health sessions,
|
|
138
127
|
no transactions, no performance traces. An event leaves the machine ONLY when
|
|
139
|
-
an error is captured.
|
|
140
|
-
|
|
128
|
+
an error is captured. The browser SDK MUST drop the default session
|
|
129
|
+
integration so no session is sent on page load or route change.
|
|
141
130
|
|
|
142
131
|
### Error wire format
|
|
143
132
|
|
|
@@ -151,18 +140,17 @@ An error event MAY carry:
|
|
|
151
140
|
`verb`, `phase`, `plugin_id` (built-in ids only), `extension_kind`,
|
|
152
141
|
`route` (BFF), `method`, `status`.
|
|
153
142
|
- The error name, error code, and a scrubbed message.
|
|
154
|
-
- Breadcrumbs (a bounded recent-event trail)
|
|
143
|
+
- Breadcrumbs (a bounded recent-event trail), each message scrubbed.
|
|
155
144
|
|
|
156
145
|
## Surface: Usage (PostHog)
|
|
157
146
|
|
|
158
147
|
Usage analytics are carried by **PostHog Cloud (EU region)**, for data
|
|
159
148
|
residency parity with the Sentry `.de` projects. The public PostHog project
|
|
160
149
|
key is hardcoded and centralized in `src/public-config.ts` (`POSTHOG_KEY_NODE`)
|
|
161
|
-
and `ui/src/app/core/public-config.ts` (`POSTHOG_KEY_UI`). Like a Sentry DSN
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
the error surface uses.
|
|
150
|
+
and `ui/src/app/core/public-config.ts` (`POSTHOG_KEY_UI`). Like a Sentry DSN it
|
|
151
|
+
is a public ingest identifier, not a secret, and safe to ship. Setting a key to
|
|
152
|
+
`''` forces that surface dormant (no init, no network, SDK not even imported),
|
|
153
|
+
the same dormancy gate the error surface uses.
|
|
166
154
|
|
|
167
155
|
Only **two** runtimes emit usage events:
|
|
168
156
|
|
|
@@ -171,36 +159,35 @@ Only **two** runtimes emit usage events:
|
|
|
171
159
|
| `sm <verb>` | Node (CLI) | `usageCliEnabled` | PostHog (server SDK) |
|
|
172
160
|
| UI | Browser (Angular) | `usageUiEnabled` | PostHog (browser SDK) |
|
|
173
161
|
|
|
174
|
-
The **BFF MUST NOT emit usage events** (
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
162
|
+
The **BFF MUST NOT emit usage events** (its activity is the UI's, already
|
|
163
|
+
covered by the UI surface; double-emitting would double-count). The BFF
|
|
164
|
+
participates only by reading/writing consent and by exposing `anonymousId`
|
|
165
|
+
read-only on `GET /api/preferences` so the browser uses the same `distinct_id`
|
|
166
|
+
as the CLI.
|
|
179
167
|
|
|
180
|
-
Both usage SDKs
|
|
181
|
-
|
|
182
|
-
|
|
168
|
+
Both usage SDKs send nothing beyond the allow-list below: PostHog autocapture,
|
|
169
|
+
pageview/pageleave capture, session recording, and client IP / geo-IP
|
|
170
|
+
enrichment are all disabled.
|
|
183
171
|
|
|
184
172
|
## Usage event taxonomy
|
|
185
173
|
|
|
186
174
|
Usage collection is **deny by default**: only the events and properties named
|
|
187
175
|
here may be sent. Every event carries `distinct_id = telemetry.anonymousId`,
|
|
188
176
|
the common environment facts (`cli_version`, `node_major`, `os`, `arch`; the UI
|
|
189
|
-
|
|
190
|
-
`environment` (`dev` / `prod`, see below). The UI also attaches
|
|
191
|
-
|
|
192
|
-
`
|
|
193
|
-
|
|
194
|
-
|
|
177
|
+
also carries browser family/version where the SDK provides it), and
|
|
178
|
+
`environment` (`dev` / `prod`, see below). The UI also attaches the active
|
|
179
|
+
theme as super-properties on every event: `theme_base` (`light` / `dark`) and
|
|
180
|
+
`theme_extra` (the active extra theme id, or `none`); future extra themes flow
|
|
181
|
+
through by value with no spec change. No other identity property is ever
|
|
182
|
+
attached.
|
|
195
183
|
|
|
196
184
|
The `environment` tag lets the maintainers filter their own dogfooding out of
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
events.
|
|
185
|
+
real-world data. It is `dev` when `SKILL_MAP_TELEMETRY_ENV` is set to any
|
|
186
|
+
non-empty value other than a production marker (`prod` / `production`); the dev
|
|
187
|
+
tooling sets it. It is `prod` when the variable is absent, empty, or a
|
|
188
|
+
production marker. It is NOT a kill switch (it labels the source, never disables
|
|
189
|
+
telemetry) and rides on both surfaces: usage events as above, and Sentry's
|
|
190
|
+
native `environment` field on error events.
|
|
204
191
|
|
|
205
192
|
| Event | Surface | Properties |
|
|
206
193
|
|---|---|---|
|
|
@@ -214,30 +201,28 @@ Rules:
|
|
|
214
201
|
- **Flag names only, never values.** `--max-nodes 500` reports the name
|
|
215
202
|
`max-nodes`, never `500`.
|
|
216
203
|
- **Extractor ids are presence, not counts.** `extensions` is a set; it never
|
|
217
|
-
carries how many nodes an extractor processed or
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
204
|
+
carries how many nodes an extractor processed or project size. Only
|
|
205
|
+
extractors that ran in the walk appear (cached extractors on an incremental
|
|
206
|
+
scan do not), so the signal is "which extractors this project exercises",
|
|
207
|
+
aggregated across runs.
|
|
221
208
|
- **Third-party ids collapse.** Any extension id whose plugin is not a
|
|
222
209
|
built-in (`claude`, `antigravity`, `openai`, `agent-skills`, `core`) MUST be
|
|
223
|
-
replaced with
|
|
224
|
-
machine.
|
|
210
|
+
replaced with `external_plugin` before the event leaves the machine.
|
|
225
211
|
- **No node paths, titles, or content** in any UI event; the view / feature is
|
|
226
|
-
the event name,
|
|
212
|
+
the event name, from a closed set, and nothing else is attached.
|
|
227
213
|
|
|
228
214
|
## Scrubbing rules (shared)
|
|
229
215
|
|
|
230
|
-
Scrubbing is **deny by default
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
have the following removed or replaced:
|
|
216
|
+
Scrubbing is **deny by default**, applied client-side in each SDK's pre-send
|
|
217
|
+
hook (`beforeSend` for Sentry, `before_send` for PostHog) before any event
|
|
218
|
+
leaves the machine. It applies to error events AND usage event properties
|
|
219
|
+
(defense in depth: the usage collectors emit only names and enums, but every
|
|
220
|
+
payload is still walked). An event MUST have the following removed or replaced:
|
|
236
221
|
|
|
237
222
|
- **Absolute paths**, anywhere they appear (frame `abs_path`, frame
|
|
238
|
-
`filename`, inside the error message,
|
|
239
|
-
|
|
240
|
-
|
|
223
|
+
`filename`, inside the error message, breadcrumb messages, any nested event
|
|
224
|
+
or property field). The home directory is replaced with `<HOME>` and the OS
|
|
225
|
+
username with `<USER>`.
|
|
241
226
|
- **File names of user content** (scanned markdown files).
|
|
242
227
|
- **Markdown bodies, frontmatter values, annotation contents.** None of these
|
|
243
228
|
are ever attached to an event.
|
|
@@ -251,7 +236,7 @@ have the following removed or replaced:
|
|
|
251
236
|
The scrubber is a pure function with no SDK dependency, so it can be unit
|
|
252
237
|
tested against hostile inputs (Windows paths, symlinked paths, paths embedded
|
|
253
238
|
mid-message, nested `abs_path` fields, breadcrumb data, structured usage
|
|
254
|
-
|
|
239
|
+
properties) independently of SDK wiring.
|
|
255
240
|
|
|
256
241
|
## Server-side guarantees
|
|
257
242
|
|
|
@@ -262,10 +247,10 @@ As a second line of defense behind the client-side scrubber:
|
|
|
262
247
|
client scrubber. The UI error surface additionally restricts reporting to
|
|
263
248
|
loopback: Sentry retired its server-side allowed-domains setting, so this is
|
|
264
249
|
enforced client-side via the SDK `allowUrls` option pinned to `localhost` /
|
|
265
|
-
`127.0.0.1` (the UI is only
|
|
250
|
+
`127.0.0.1` (the UI is only served from loopback).
|
|
266
251
|
- The **PostHog** project MUST be configured to discard client IP addresses
|
|
267
|
-
and disable geo-IP enrichment (the client SDKs
|
|
268
|
-
|
|
252
|
+
and disable geo-IP enrichment (the client SDKs disable geo and autocapture
|
|
253
|
+
too, but the project setting is the backstop).
|
|
269
254
|
|
|
270
255
|
## Stability
|
|
271
256
|
|
|
@@ -275,20 +260,19 @@ kill switch, prompt-once semantics) is stable as of the spec minor in which it
|
|
|
275
260
|
lands. Loosening any default (anything other than OFF), removing the kill
|
|
276
261
|
switch, or removing the consent gate is a major bump.
|
|
277
262
|
|
|
278
|
-
The **two surfaces are independent.** Error
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
263
|
+
The **two surfaces are independent.** Error and usage scope each evolve on
|
|
264
|
+
their own minor bump. Adding a new usage event or property, or a new error tag
|
|
265
|
+
or environment fact, is a minor bump. Performance traces remain out of scope on
|
|
266
|
+
both and would be a third, separately-consented surface.
|
|
282
267
|
|
|
283
268
|
The **`anonymousId` exception** is normatively scoped to the usage surface
|
|
284
|
-
only:
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
bump.
|
|
269
|
+
only: the one anonymous correlation id the contract permits, and the error
|
|
270
|
+
surface MUST remain free of any cross-session or cross-install id. Widening it
|
|
271
|
+
beyond usage, or attaching any identity, is a major bump.
|
|
288
272
|
|
|
289
273
|
The scrubbing exclusion list (what MUST NOT leave the machine) is the stable,
|
|
290
274
|
normative core and may only grow, never shrink, without a major bump.
|
|
291
275
|
|
|
292
|
-
Consumers and alternate implementations MAY
|
|
293
|
-
|
|
294
|
-
|
|
276
|
+
Consumers and alternate implementations MAY ship neither surface; both are
|
|
277
|
+
optional. An implementation that ships a surface MUST honor the consent
|
|
278
|
+
contract and the scrubbing rules in full.
|
package/versioning.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Spec versioning
|
|
2
2
|
|
|
3
|
-
The skill-map **spec** and the skill-map **reference CLI** evolve on independent semver tracks
|
|
3
|
+
The skill-map **spec** and the skill-map **reference CLI** evolve on independent semver tracks, related through a `specCompat` range declared by each implementation and each plugin.
|
|
4
4
|
|
|
5
5
|
## Two tracks
|
|
6
6
|
|
|
@@ -9,11 +9,11 @@ The skill-map **spec** and the skill-map **reference CLI** evolve on independent
|
|
|
9
9
|
| Spec | `spec-v1.2.0` | Schemas + contracts in `spec/`. Consumed by any implementation. |
|
|
10
10
|
| Reference CLI | `cli-v0.8.3` | The `sm` binary and its built-in extensions in `src/`. |
|
|
11
11
|
|
|
12
|
-
A
|
|
12
|
+
A CLI release declares the spec range it implements (e.g. `"specCompat": "^1.0.0"`); a plugin declares the spec range it targets. At load time the implementation runs `semver.satisfies(specVersion, plugin.specCompat)`; mismatch → plugin disabled with reason `incompatible-spec`.
|
|
13
13
|
|
|
14
14
|
## Semver for the spec
|
|
15
15
|
|
|
16
|
-
Patch, minor, major have precise meaning for a specification,
|
|
16
|
+
Patch, minor, major have precise meaning for a specification, distinct from code.
|
|
17
17
|
|
|
18
18
|
| Bump | Allowed changes | Examples |
|
|
19
19
|
|---|---|---|
|
|
@@ -30,7 +30,7 @@ All of the following are normative and governed by this policy:
|
|
|
30
30
|
- Every JSON Schema in `schemas/` (fields, types, required, enums, defaults, `additionalProperties`).
|
|
31
31
|
- Every MUST / SHOULD / MAY statement in prose documents ([`architecture.md`](./architecture.md), [`cli-contract.md`](./cli-contract.md), [`job-events.md`](./job-events.md), [`prompt-preamble.md`](./prompt-preamble.md), [`db-schema.md`](./db-schema.md), [`plugin-kv-api.md`](./plugin-kv-api.md), [`job-lifecycle.md`](./job-lifecycle.md)).
|
|
32
32
|
- Exit codes, verb names, required flags, canonical error messages marked "normative".
|
|
33
|
-
- Conformance fixtures and cases
|
|
33
|
+
- Conformance fixtures and cases; removing or tightening a case is major.
|
|
34
34
|
|
|
35
35
|
The following are **non-normative** and can change at any time without a version bump:
|
|
36
36
|
|
|
@@ -41,7 +41,7 @@ The following are **non-normative** and can change at any time without a version
|
|
|
41
41
|
|
|
42
42
|
## Stability tags
|
|
43
43
|
|
|
44
|
-
Fields and features
|
|
44
|
+
Fields and features carry a stability tag. The tag drives what the version policy allows.
|
|
45
45
|
|
|
46
46
|
| Tag | Meaning | Policy |
|
|
47
47
|
|---|---|---|
|
|
@@ -55,7 +55,7 @@ Tags live inline in schema `description` fields and in prose via a leading `**St
|
|
|
55
55
|
|
|
56
56
|
- `stable` → `deprecated` requires a minor bump.
|
|
57
57
|
- `deprecated` → removed requires a major bump.
|
|
58
|
-
- Between the two, at least three minor releases must ship with the field marked `deprecated
|
|
58
|
+
- Between the two, at least three minor releases must ship with the field marked `deprecated`, giving plugin authors a window to migrate.
|
|
59
59
|
- Rationale for the deprecation and the replacement field/flag must live in `CHANGELOG.md`.
|
|
60
60
|
|
|
61
61
|
## Pre-1.0
|
|
@@ -63,23 +63,23 @@ Tags live inline in schema `description` fields and in prose via a leading `**St
|
|
|
63
63
|
While the spec is `0.Y.Z`:
|
|
64
64
|
|
|
65
65
|
- Minor bumps may contain breaking changes (documented as such in `CHANGELOG.md`).
|
|
66
|
-
- Conformance is advisory
|
|
66
|
+
- Conformance is advisory; failing a conformance case is a bug report, not a spec violation.
|
|
67
67
|
- `specCompat` in plugins should pin a minor range (`"^0.3.0"` means `>=0.3.0 <0.4.0`), not a major range.
|
|
68
68
|
|
|
69
69
|
The first stable commitment is `spec-v1.0.0`. In the current reference roadmap, that tag ships with `cli-v1.0.0`.
|
|
70
70
|
|
|
71
71
|
## Independence in practice
|
|
72
72
|
|
|
73
|
-
- **Spec `1.0.0` + CLI `0.1.0`**, spec
|
|
74
|
-
- **Spec `1.2.0` + CLI `0.8.0`**, spec gained an optional feature
|
|
73
|
+
- **Spec `1.0.0` + CLI `0.1.0`**, spec stabilized before the CLI ships its v1. Normal during early life of the project.
|
|
74
|
+
- **Spec `1.2.0` + CLI `0.8.0`**, spec gained an optional feature the CLI hasn't implemented yet. Fine. Plugins needing it must declare `"specCompat": "^1.2.0"`.
|
|
75
75
|
- **Spec `2.0.0` + CLI `1.4.0`**, CLI still targets spec v1. Operator must upgrade CLI before installing v2-targeting plugins.
|
|
76
76
|
|
|
77
77
|
## Change process
|
|
78
78
|
|
|
79
|
-
1. PR proposes a spec change
|
|
79
|
+
1. PR proposes a spec change with rationale and classification (patch/minor/major).
|
|
80
80
|
2. If major, PR includes a migration note draft for [`CHANGELOG.md`](./CHANGELOG.md).
|
|
81
81
|
3. If the change affects reference-impl behavior, a companion PR in `src/` lands the implementation behind the bumped `specCompat`.
|
|
82
|
-
4. Merge order: spec change first, implementation second. An implementation MUST NOT ship a feature
|
|
82
|
+
4. Merge order: spec change first, implementation second. An implementation MUST NOT ship a feature not yet in the spec (see [`../AGENTS.md`](../AGENTS.md): "Every feature: update spec/ first, then src/").
|
|
83
83
|
5. Tag spec release (`spec-vX.Y.Z`) independent from any CLI tag.
|
|
84
84
|
|
|
85
85
|
## Canonical URLs
|
|
@@ -91,4 +91,4 @@ https://skill-map.ai/spec/v1/node.schema.json
|
|
|
91
91
|
https://skill-map.ai/spec/v1.2/node.schema.json
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
The major version is always present in the path. Implementations MUST NOT rely on `latest`.
|