@runbooks/schema 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +22 -0
  3. package/dist/agent-skills.test.d.ts +1 -0
  4. package/dist/agent-skills.test.js +71 -0
  5. package/dist/capabilities.d.ts +40 -0
  6. package/dist/capabilities.js +211 -0
  7. package/dist/capabilities.test.d.ts +1 -0
  8. package/dist/capabilities.test.js +119 -0
  9. package/dist/content-classes.test.d.ts +1 -0
  10. package/dist/content-classes.test.js +77 -0
  11. package/dist/generate.cli.d.ts +2 -0
  12. package/dist/generate.cli.js +27 -0
  13. package/dist/generate.d.ts +54 -0
  14. package/dist/generate.js +133 -0
  15. package/dist/generate.test.d.ts +1 -0
  16. package/dist/generate.test.js +85 -0
  17. package/dist/generated.d.ts +101 -0
  18. package/dist/generated.js +9 -0
  19. package/dist/generated.ts +82 -0
  20. package/dist/hash.d.ts +36 -0
  21. package/dist/hash.js +102 -0
  22. package/dist/hash.test.d.ts +1 -0
  23. package/dist/hash.test.js +54 -0
  24. package/dist/index.d.ts +58 -0
  25. package/dist/index.js +61 -0
  26. package/dist/index.test.d.ts +1 -0
  27. package/dist/index.test.js +236 -0
  28. package/dist/interpolation.d.ts +11 -0
  29. package/dist/interpolation.js +34 -0
  30. package/dist/node.d.ts +41 -0
  31. package/dist/node.js +111 -0
  32. package/dist/p1.test.d.ts +1 -0
  33. package/dist/p1.test.js +87 -0
  34. package/dist/run-report.test.d.ts +1 -0
  35. package/dist/run-report.test.js +145 -0
  36. package/dist/served.d.ts +36 -0
  37. package/dist/served.js +128 -0
  38. package/dist/stats.d.ts +17 -0
  39. package/dist/stats.js +23 -0
  40. package/dist/stats.test.d.ts +1 -0
  41. package/dist/stats.test.js +32 -0
  42. package/dist/validate.d.ts +16 -0
  43. package/dist/validate.js +46 -0
  44. package/dist/validate.test.d.ts +1 -0
  45. package/dist/validate.test.js +61 -0
  46. package/dist/vocabularies.test.d.ts +1 -0
  47. package/dist/vocabularies.test.js +77 -0
  48. package/package.json +50 -0
  49. package/spec/v1/schema/attestation.json +62 -0
  50. package/spec/v1/schema/p0.json +383 -0
  51. package/spec/v1/schema/p1.json +408 -0
  52. package/spec/v1/schema/record.json +908 -0
  53. package/spec/v1/schema/run-report-envelope.json +25 -0
  54. package/spec/v1/schema/run-report.json +121 -0
@@ -0,0 +1,408 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://runbooks.directory/spec/v1/schema/p1.json",
4
+ "title": "Runbook, profile P1",
5
+ "description": "P0 plus a steps[] block. Five step kinds, deliberately few: enough to describe an ops procedure, and few enough that the mapping to an execution DSL is unambiguous (RUNBOOK.md 5). This schema defines a step in isolation. Anything spanning steps - reachability, cycles, explicit terminals, a decision's default branch - is a graph invariant (section 6) checked by the linter, not here.",
6
+ "$defs": {
7
+ "stepId": {
8
+ "type": "string",
9
+ "pattern": "^[a-z][a-z0-9_]{0,31}$",
10
+ "description": "Unique within a version. Referenced by on_fail, branches and rollback_ref."
11
+ },
12
+ "toolRef": {
13
+ "type": "string",
14
+ "pattern": "^(mcp:[a-z0-9][a-z0-9-]*|cli:[a-z0-9][a-z0-9._-]*|iam:[a-z0-9-]+:[A-Za-z0-9*]+)$",
15
+ "description": "Same grammar as runbook.capabilities. A step may name a tool absent from capabilities[]: the schema permits it and the linter rejects it as a blocking T2 error (RUNBOOK.md 12). Schema and linter have different jobs."
16
+ },
17
+ "title": {
18
+ "type": "string",
19
+ "minLength": 3,
20
+ "maxLength": 48,
21
+ "description": "An imperative verb phrase (RUNBOOK.md 18.6): 'Capture current lag', not 'Lag problem'. The 48-character cap is what keeps a node label to two lines."
22
+ },
23
+ "step": {
24
+ "type": "object",
25
+ "required": [
26
+ "id",
27
+ "kind",
28
+ "title"
29
+ ],
30
+ "additionalProperties": false,
31
+ "properties": {
32
+ "id": {
33
+ "$ref": "#/$defs/stepId"
34
+ },
35
+ "kind": {
36
+ "enum": [
37
+ "check",
38
+ "action",
39
+ "decision",
40
+ "wait",
41
+ "escalate"
42
+ ]
43
+ },
44
+ "title": {
45
+ "$ref": "#/$defs/title"
46
+ },
47
+ "tool": {
48
+ "$ref": "#/$defs/toolRef"
49
+ },
50
+ "command": {
51
+ "type": "string",
52
+ "description": "May interpolate {{inputs.<name>}}, and only names declared in runbook.inputs. The reference check is semantic, not structural, so it lives in the linter."
53
+ },
54
+ "expect": {
55
+ "type": "string",
56
+ "minLength": 3
57
+ },
58
+ "assert": {
59
+ "type": "object",
60
+ "additionalProperties": false,
61
+ "minProperties": 1,
62
+ "description": "A machine-checkable postcondition, required by R2 supervision. `expect` stays prose for the reader; this is what a supervisor evaluates. A step with only prose is unevaluable at R2 - a first-class outcome in which the supervisor halts and asks a human rather than guessing (docs/decisions/Q12-expect-evaluability.md).",
63
+ "properties": {
64
+ "exit_code": {
65
+ "type": "integer",
66
+ "minimum": 0,
67
+ "maximum": 255
68
+ },
69
+ "stdout_matches": {
70
+ "type": "string",
71
+ "description": "Regular expression."
72
+ },
73
+ "stdout_not_matches": {
74
+ "type": "string"
75
+ },
76
+ "stderr_empty": {
77
+ "type": "boolean"
78
+ },
79
+ "json_path": {
80
+ "type": "object",
81
+ "additionalProperties": false,
82
+ "required": [
83
+ "path",
84
+ "equals"
85
+ ],
86
+ "properties": {
87
+ "path": {
88
+ "type": "string"
89
+ },
90
+ "equals": {}
91
+ }
92
+ }
93
+ }
94
+ },
95
+ "on_fail": {
96
+ "type": "string",
97
+ "pattern": "^(escalate:)?([a-z][a-z0-9_]{0,31}|end:(success|failed|aborted))$"
98
+ },
99
+ "question": {
100
+ "type": "string",
101
+ "minLength": 3
102
+ },
103
+ "branches": {
104
+ "type": "object",
105
+ "minProperties": 2,
106
+ "additionalProperties": {
107
+ "$ref": "#/$defs/stepId"
108
+ },
109
+ "description": "Label to step id. Two or more is structural and checked here; that one of them is a default is graph invariant 3, checked by the linter."
110
+ },
111
+ "risk": {
112
+ "enum": [
113
+ "read-only",
114
+ "reversible-write",
115
+ "destructive",
116
+ "irreversible"
117
+ ]
118
+ },
119
+ "requires_approval": {
120
+ "type": "boolean"
121
+ },
122
+ "rollback_ref": {
123
+ "type": "string",
124
+ "pattern": "^(rb_[0-9A-HJKMNP-TV-Z]{26}|[a-z][a-z0-9_]{0,31})$",
125
+ "description": "A step in this runbook, or another runbook. Cross-runbook resolution is not in v1; until then a rollback_ref to another runbook is documentation for a human, not a route a supervisor can take."
126
+ },
127
+ "duration": {
128
+ "type": "string",
129
+ "pattern": "^[0-9]+(s|m|h)$"
130
+ },
131
+ "until": {
132
+ "type": "string",
133
+ "minLength": 3
134
+ },
135
+ "timeout": {
136
+ "type": "string",
137
+ "pattern": "^[0-9]+(s|m|h)$"
138
+ },
139
+ "retry": {
140
+ "type": "object",
141
+ "additionalProperties": false,
142
+ "required": [
143
+ "max"
144
+ ],
145
+ "properties": {
146
+ "max": {
147
+ "type": "integer",
148
+ "minimum": 1,
149
+ "maximum": 20
150
+ },
151
+ "target": {
152
+ "$ref": "#/$defs/stepId"
153
+ }
154
+ },
155
+ "description": "The only permitted cycle, and it must be finite: an unbounded loop in an autonomous agent costs money and causes incidents (invariant 6)."
156
+ },
157
+ "to": {
158
+ "type": "string",
159
+ "minLength": 2
160
+ },
161
+ "next": {
162
+ "type": "string",
163
+ "pattern": "^([a-z][a-z0-9_]{0,31}|end:(success|failed|aborted))$",
164
+ "description": "The next step, or an explicit terminal. Invariant 7 requires every terminal to be explicit: a graph may not end by running out of next node."
165
+ },
166
+ "x-layout": {
167
+ "type": "object",
168
+ "additionalProperties": false,
169
+ "required": [
170
+ "x",
171
+ "y"
172
+ ],
173
+ "properties": {
174
+ "x": {
175
+ "type": "number"
176
+ },
177
+ "y": {
178
+ "type": "number"
179
+ }
180
+ },
181
+ "description": "An authoring-time position from the constructor. Accepted so that a draft laid out by hand can be submitted, and stripped on publish: auto-layout is canonical, the catalog stores no positions, and every reader of a version sees the same graph (docs/decisions/Q8-layout.md). It never participates in content_hash, so re-laying-out a graph is not a new version."
182
+ }
183
+ },
184
+ "allOf": [
185
+ {
186
+ "description": "A check without expect and on_fail cannot be evaluated or routed, so a supervisor would have to improvise both (invariant 4).",
187
+ "if": {
188
+ "properties": {
189
+ "kind": {
190
+ "const": "check"
191
+ }
192
+ },
193
+ "required": [
194
+ "kind"
195
+ ]
196
+ },
197
+ "then": {
198
+ "properties": {
199
+ "expect": {
200
+ "type": "string"
201
+ },
202
+ "on_fail": {
203
+ "type": "string"
204
+ }
205
+ },
206
+ "required": [
207
+ "expect",
208
+ "on_fail"
209
+ ]
210
+ }
211
+ },
212
+ {
213
+ "description": "An action must state its risk. Unstated risk defaults to nothing safe.",
214
+ "if": {
215
+ "properties": {
216
+ "kind": {
217
+ "const": "action"
218
+ }
219
+ },
220
+ "required": [
221
+ "kind"
222
+ ]
223
+ },
224
+ "then": {
225
+ "properties": {
226
+ "risk": {
227
+ "type": "string"
228
+ }
229
+ },
230
+ "required": [
231
+ "risk"
232
+ ]
233
+ }
234
+ },
235
+ {
236
+ "description": "Invariant 5: a destructive or irreversible action is always paired - an approval gate before it, or a rollback after it. This is the one rule the whole product exists to enforce, so it is structural rather than advisory.",
237
+ "if": {
238
+ "properties": {
239
+ "kind": {
240
+ "const": "action"
241
+ },
242
+ "risk": {
243
+ "enum": [
244
+ "destructive",
245
+ "irreversible"
246
+ ]
247
+ }
248
+ },
249
+ "required": [
250
+ "kind",
251
+ "risk"
252
+ ]
253
+ },
254
+ "then": {
255
+ "anyOf": [
256
+ {
257
+ "properties": {
258
+ "requires_approval": {
259
+ "const": true
260
+ }
261
+ },
262
+ "required": [
263
+ "requires_approval"
264
+ ]
265
+ },
266
+ {
267
+ "properties": {
268
+ "rollback_ref": {
269
+ "type": "string"
270
+ }
271
+ },
272
+ "required": [
273
+ "rollback_ref"
274
+ ]
275
+ }
276
+ ]
277
+ }
278
+ },
279
+ {
280
+ "description": "A decision needs a question and at least two branches.",
281
+ "if": {
282
+ "properties": {
283
+ "kind": {
284
+ "const": "decision"
285
+ }
286
+ },
287
+ "required": [
288
+ "kind"
289
+ ]
290
+ },
291
+ "then": {
292
+ "properties": {
293
+ "question": {
294
+ "type": "string"
295
+ },
296
+ "branches": {
297
+ "type": "object"
298
+ }
299
+ },
300
+ "required": [
301
+ "question",
302
+ "branches"
303
+ ]
304
+ }
305
+ },
306
+ {
307
+ "description": "A wait must be bounded: either a duration, or a condition with a timeout. An unbounded wait is a hang with better manners.",
308
+ "if": {
309
+ "properties": {
310
+ "kind": {
311
+ "const": "wait"
312
+ }
313
+ },
314
+ "required": [
315
+ "kind"
316
+ ]
317
+ },
318
+ "then": {
319
+ "anyOf": [
320
+ {
321
+ "properties": {
322
+ "duration": {
323
+ "type": "string"
324
+ }
325
+ },
326
+ "required": [
327
+ "duration"
328
+ ]
329
+ },
330
+ {
331
+ "properties": {
332
+ "until": {
333
+ "type": "string"
334
+ },
335
+ "timeout": {
336
+ "type": "string"
337
+ }
338
+ },
339
+ "required": [
340
+ "until",
341
+ "timeout"
342
+ ]
343
+ }
344
+ ]
345
+ }
346
+ },
347
+ {
348
+ "description": "Escalation is an exit from the workflow, so it must say where it goes.",
349
+ "if": {
350
+ "properties": {
351
+ "kind": {
352
+ "const": "escalate"
353
+ }
354
+ },
355
+ "required": [
356
+ "kind"
357
+ ]
358
+ },
359
+ "then": {
360
+ "properties": {
361
+ "to": {
362
+ "type": "string"
363
+ }
364
+ },
365
+ "required": [
366
+ "to"
367
+ ]
368
+ }
369
+ }
370
+ ]
371
+ }
372
+ },
373
+ "allOf": [
374
+ {
375
+ "$ref": "https://runbooks.directory/spec/v1/schema/p0.json"
376
+ },
377
+ {
378
+ "type": "object",
379
+ "required": [
380
+ "runbook"
381
+ ],
382
+ "properties": {
383
+ "runbook": {
384
+ "type": "object",
385
+ "required": [
386
+ "profile",
387
+ "steps"
388
+ ],
389
+ "properties": {
390
+ "profile": {
391
+ "enum": [
392
+ "P1",
393
+ "P2"
394
+ ]
395
+ },
396
+ "steps": {
397
+ "type": "array",
398
+ "minItems": 1,
399
+ "items": {
400
+ "$ref": "#/$defs/step"
401
+ }
402
+ }
403
+ }
404
+ }
405
+ }
406
+ }
407
+ ]
408
+ }