release-skill 0.1.1 → 0.1.4

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 (108) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +2 -2
  3. package/.codex-plugin/plugin.json +3 -3
  4. package/CHANGELOG.md +89 -0
  5. package/INSTALL.md +216 -5
  6. package/INSTALL.zh-CN.md +358 -0
  7. package/README.md +411 -67
  8. package/README.zh-CN.md +377 -59
  9. package/adapters/claude/.claude-plugin/marketplace.json +1 -1
  10. package/adapters/claude/.claude-plugin/plugin.json +1 -1
  11. package/adapters/claude/bin/release-skill.bundle.mjs +79284 -0
  12. package/adapters/claude/bin/release-skill.mjs +34 -0
  13. package/adapters/claude/native/safe-write/binding.gyp +40 -0
  14. package/adapters/claude/native/safe-write/prebuilds/darwin-arm64/safe_write.node +0 -0
  15. package/adapters/claude/native/safe-write/prebuilds.json +24 -0
  16. package/adapters/claude/native/safe-write/src/safe_write.cc +2032 -0
  17. package/adapters/claude/schemas/.render-manifest.json +37 -0
  18. package/adapters/claude/schemas/approval-record.schema.json +115 -0
  19. package/adapters/claude/schemas/artifact-lock.schema.json +111 -0
  20. package/adapters/claude/schemas/artifact-plan.schema.json +52 -0
  21. package/adapters/claude/schemas/artifact-policy.schema.json +76 -0
  22. package/adapters/claude/schemas/evidence-event.schema.json +89 -0
  23. package/adapters/claude/schemas/release-plan.schema.json +860 -0
  24. package/adapters/claude/schemas/release-project.schema.json +736 -0
  25. package/adapters/claude/schemas/release-run.schema.json +342 -0
  26. package/adapters/claude/skills/release-assess/SKILL.md +5 -6
  27. package/adapters/claude/skills/release-help/SKILL.md +14 -18
  28. package/adapters/claude/skills/release-prepare/SKILL.md +16 -6
  29. package/adapters/claude/skills/release-publish/SKILL.md +7 -7
  30. package/adapters/claude/skills/release-reconcile/SKILL.md +6 -6
  31. package/adapters/claude/skills/release-setup/SKILL.md +95 -0
  32. package/adapters/claude/skills/release-verify/SKILL.md +7 -7
  33. package/adapters/codex/.codex-plugin/plugin.json +2 -2
  34. package/adapters/codex/bin/release-skill.bundle.mjs +79284 -0
  35. package/adapters/codex/bin/release-skill.mjs +34 -0
  36. package/adapters/codex/native/safe-write/binding.gyp +40 -0
  37. package/adapters/codex/native/safe-write/prebuilds/darwin-arm64/safe_write.node +0 -0
  38. package/adapters/codex/native/safe-write/prebuilds.json +24 -0
  39. package/adapters/codex/native/safe-write/src/safe_write.cc +2032 -0
  40. package/adapters/codex/schemas/.render-manifest.json +37 -0
  41. package/adapters/codex/schemas/approval-record.schema.json +115 -0
  42. package/adapters/codex/schemas/artifact-lock.schema.json +111 -0
  43. package/adapters/codex/schemas/artifact-plan.schema.json +52 -0
  44. package/adapters/codex/schemas/artifact-policy.schema.json +76 -0
  45. package/adapters/codex/schemas/evidence-event.schema.json +89 -0
  46. package/adapters/codex/schemas/release-plan.schema.json +860 -0
  47. package/adapters/codex/schemas/release-project.schema.json +736 -0
  48. package/adapters/codex/schemas/release-run.schema.json +342 -0
  49. package/adapters/codex/skills/release-assess/SKILL.md +12 -6
  50. package/adapters/codex/skills/release-help/SKILL.md +21 -18
  51. package/adapters/codex/skills/release-prepare/SKILL.md +23 -6
  52. package/adapters/codex/skills/release-publish/SKILL.md +14 -7
  53. package/adapters/codex/skills/release-reconcile/SKILL.md +13 -6
  54. package/adapters/codex/skills/release-setup/SKILL.md +102 -0
  55. package/adapters/codex/skills/release-verify/SKILL.md +14 -7
  56. package/bin/release-skill-cli.mjs +807 -0
  57. package/bin/release-skill.bundle.mjs +79284 -0
  58. package/bin/release-skill.mjs +23 -732
  59. package/native/safe-write/prebuilds/darwin-arm64/safe_write.node +0 -0
  60. package/native/safe-write/prebuilds.json +22 -2
  61. package/native/safe-write/src/safe_write.cc +11 -2
  62. package/package.json +8 -2
  63. package/references/02-project-config.md +55 -4
  64. package/references/05-evidence-and-errors.md +6 -2
  65. package/schemas/release-plan.schema.json +556 -65
  66. package/schemas/release-project.schema.json +406 -29
  67. package/schemas/release-run.schema.json +165 -18
  68. package/scripts/build-bundle.mjs +133 -0
  69. package/skills/release-assess/SKILL.md +5 -6
  70. package/skills/release-help/SKILL.md +14 -18
  71. package/skills/release-prepare/SKILL.md +16 -6
  72. package/skills/release-publish/SKILL.md +7 -7
  73. package/skills/release-reconcile/SKILL.md +6 -6
  74. package/skills/release-setup/SKILL.md +95 -0
  75. package/skills/release-verify/SKILL.md +7 -7
  76. package/skills-src/release-assess/SKILL.md +5 -6
  77. package/skills-src/release-help/SKILL.md +14 -18
  78. package/skills-src/release-prepare/SKILL.md +16 -6
  79. package/skills-src/release-publish/SKILL.md +7 -7
  80. package/skills-src/release-reconcile/SKILL.md +6 -6
  81. package/skills-src/release-setup/SKILL.md +95 -0
  82. package/skills-src/release-verify/SKILL.md +7 -7
  83. package/src/adapters/contract.mjs +3 -0
  84. package/src/adapters/git-github.mjs +84 -2
  85. package/src/adapters/npm.mjs +5 -13
  86. package/src/adapters/plugin-marketplace.mjs +132 -52
  87. package/src/adapters/push-snapshot.mjs +84 -17
  88. package/src/artifacts/policy.mjs +4 -7
  89. package/src/artifacts/safe-fs-backend-internal.mjs +69 -21
  90. package/src/commands/prepare.mjs +244 -20
  91. package/src/commands/publish.mjs +46 -0
  92. package/src/commands/reconcile.mjs +152 -0
  93. package/src/commands/setup.mjs +1525 -0
  94. package/src/commands/verify.mjs +122 -26
  95. package/src/core/approval.mjs +4 -6
  96. package/src/core/config.mjs +42 -8
  97. package/src/core/errors.mjs +4 -0
  98. package/src/core/pkg-root.mjs +22 -0
  99. package/src/core/plan.mjs +132 -4
  100. package/src/core/previous-public-baseline.mjs +21 -1
  101. package/src/core/run.mjs +4 -4
  102. package/src/core/trusted-resource.mjs +96 -0
  103. package/src/core/verification-gates.mjs +451 -0
  104. package/src/docs/version-gate.mjs +164 -0
  105. package/src/producers/build-adapters.mjs +512 -55
  106. package/src/snapshot/frozen.mjs +221 -7
  107. package/src/snapshot/public-map.mjs +7 -4
  108. package/src/snapshot/scan.mjs +2 -1
@@ -0,0 +1,736 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://release-skill.dev/schemas/release-project/v1",
4
+ "title": "Release Project Configuration",
5
+ "description": "Schema for .release-skill/project.yaml project configuration file",
6
+ "type": "object",
7
+ "required": [
8
+ "apiVersion",
9
+ "kind",
10
+ "project",
11
+ "releaseUnits"
12
+ ],
13
+ "additionalProperties": false,
14
+ "properties": {
15
+ "apiVersion": {
16
+ "type": "string",
17
+ "const": "release-skill/v1"
18
+ },
19
+ "kind": {
20
+ "type": "string",
21
+ "const": "ReleaseProject"
22
+ },
23
+ "project": {
24
+ "type": "object",
25
+ "required": [
26
+ "name",
27
+ "defaultBranch"
28
+ ],
29
+ "additionalProperties": false,
30
+ "properties": {
31
+ "name": {
32
+ "type": "string",
33
+ "minLength": 1
34
+ },
35
+ "defaultBranch": {
36
+ "type": "string",
37
+ "minLength": 1
38
+ }
39
+ }
40
+ },
41
+ "releaseUnits": {
42
+ "type": "array",
43
+ "minItems": 1,
44
+ "items": {
45
+ "type": "object",
46
+ "required": [
47
+ "id",
48
+ "source",
49
+ "publicRepo",
50
+ "version",
51
+ "distributions",
52
+ "publicFiles",
53
+ "requiredPublicFiles",
54
+ "previousPublicBaseline"
55
+ ],
56
+ "additionalProperties": false,
57
+ "properties": {
58
+ "id": {
59
+ "type": "string",
60
+ "minLength": 1,
61
+ "pattern": "^(?!\\.{1,2}$)[A-Za-z0-9][A-Za-z0-9._-]*$"
62
+ },
63
+ "source": {
64
+ "type": "string",
65
+ "minLength": 1,
66
+ "pattern": "^(?:\\.$|(?!\\/)(?!\\.\\/)(?!.*\\\\)(?!.*:)(?!\\.\\.(?:\\/|$))(?!.*\\/\\.\\.\\/)(?!.*\\/\\.\\.$)(?!.*\\/\\.\\/)(?!.*\\/\\/)(?!.*\\0)(?!.*\\/\\.$)(?!.*\\/\\/$)(?!.*\\/$).*)$"
67
+ },
68
+ "publicRepo": {
69
+ "type": "string",
70
+ "pattern": "^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$"
71
+ },
72
+ "production": {
73
+ "type": "object",
74
+ "additionalProperties": false,
75
+ "properties": {
76
+ "githubHost": {
77
+ "type": "string",
78
+ "pattern": "^[a-zA-Z0-9.-]+$"
79
+ },
80
+ "branchTemplate": {
81
+ "type": "string",
82
+ "minLength": 1
83
+ },
84
+ "releaseTitleTemplate": {
85
+ "type": "string",
86
+ "minLength": 1
87
+ },
88
+ "releaseNotes": {
89
+ "type": "string"
90
+ },
91
+ "branchStrategy": {
92
+ "type": "string",
93
+ "enum": [
94
+ "create-release-branch",
95
+ "advance-existing-branch",
96
+ "initialize-default-branch"
97
+ ]
98
+ },
99
+ "setAsDefaultBranch": {
100
+ "type": "boolean"
101
+ },
102
+ "expectedCurrentDefaultBranch": {
103
+ "type": "string",
104
+ "minLength": 1
105
+ }
106
+ }
107
+ },
108
+ "version": {
109
+ "type": "object",
110
+ "required": [
111
+ "source",
112
+ "tagTemplate"
113
+ ],
114
+ "additionalProperties": false,
115
+ "properties": {
116
+ "source": {
117
+ "type": "string",
118
+ "minLength": 1
119
+ },
120
+ "tagTemplate": {
121
+ "type": "string",
122
+ "minLength": 1
123
+ }
124
+ }
125
+ },
126
+ "distributions": {
127
+ "type": "array",
128
+ "minItems": 1,
129
+ "items": {
130
+ "type": "object",
131
+ "required": [
132
+ "type"
133
+ ],
134
+ "additionalProperties": false,
135
+ "properties": {
136
+ "type": {
137
+ "type": "string",
138
+ "enum": [
139
+ "npm",
140
+ "claude-plugin",
141
+ "codex-plugin"
142
+ ]
143
+ },
144
+ "package": {
145
+ "type": "string",
146
+ "minLength": 1,
147
+ "maxLength": 214,
148
+ "pattern": "^(?:@[a-z0-9][a-z0-9._-]*/[a-z0-9][a-z0-9._-]*|[a-z0-9][a-z0-9._-]*)$"
149
+ },
150
+ "access": {
151
+ "type": "string",
152
+ "enum": [
153
+ "public",
154
+ "restricted"
155
+ ]
156
+ },
157
+ "provenance": {
158
+ "type": "boolean"
159
+ },
160
+ "tag": {
161
+ "type": "string",
162
+ "minLength": 1
163
+ },
164
+ "registry": {
165
+ "type": "string",
166
+ "minLength": 1,
167
+ "pattern": "^https://[^\\s]+$",
168
+ "description": "Normalized HTTPS URL of the npm registry"
169
+ },
170
+ "publisher": {
171
+ "type": "string",
172
+ "minLength": 1,
173
+ "pattern": "^[a-z0-9][a-z0-9._-]*$",
174
+ "description": "Expected npm whoami username for this registry"
175
+ },
176
+ "plugin": {
177
+ "type": "string",
178
+ "minLength": 1,
179
+ "pattern": "^[a-z0-9][a-z0-9._-]*$"
180
+ },
181
+ "marketplace": {
182
+ "type": "string",
183
+ "minLength": 1,
184
+ "pattern": "^[a-z0-9][a-z0-9._-]*$"
185
+ },
186
+ "entrySkill": {
187
+ "type": "string",
188
+ "minLength": 1,
189
+ "pattern": "^[a-z0-9][a-z0-9-]*$"
190
+ },
191
+ "smokeBin": {
192
+ "type": "string",
193
+ "minLength": 1
194
+ },
195
+ "smokeArgs": {
196
+ "type": "array",
197
+ "items": {
198
+ "type": "string"
199
+ }
200
+ },
201
+ "smokeExpectedJson": {
202
+ "type": "object"
203
+ }
204
+ },
205
+ "allOf": [
206
+ {
207
+ "if": {
208
+ "properties": {
209
+ "type": {
210
+ "const": "npm"
211
+ }
212
+ }
213
+ },
214
+ "then": {
215
+ "required": [
216
+ "package",
217
+ "registry",
218
+ "publisher"
219
+ ]
220
+ }
221
+ },
222
+ {
223
+ "if": {
224
+ "properties": {
225
+ "type": {
226
+ "enum": [
227
+ "claude-plugin",
228
+ "codex-plugin"
229
+ ]
230
+ }
231
+ }
232
+ },
233
+ "then": {
234
+ "required": [
235
+ "plugin",
236
+ "marketplace",
237
+ "entrySkill"
238
+ ]
239
+ }
240
+ },
241
+ {
242
+ "if": {
243
+ "required": [
244
+ "smokeExpectedJson"
245
+ ],
246
+ "properties": {
247
+ "smokeBin": {
248
+ "minLength": 1
249
+ }
250
+ }
251
+ },
252
+ "then": {
253
+ "required": [
254
+ "smokeBin"
255
+ ]
256
+ }
257
+ },
258
+ {
259
+ "if": {
260
+ "required": [
261
+ "smokeArgs"
262
+ ],
263
+ "properties": {
264
+ "smokeBin": {
265
+ "minLength": 1
266
+ }
267
+ }
268
+ },
269
+ "then": {
270
+ "required": [
271
+ "smokeBin"
272
+ ]
273
+ }
274
+ }
275
+ ]
276
+ }
277
+ },
278
+ "publicFiles": {
279
+ "type": "array",
280
+ "minItems": 1,
281
+ "items": {
282
+ "type": "object",
283
+ "required": [
284
+ "from",
285
+ "to",
286
+ "mode"
287
+ ],
288
+ "additionalProperties": false,
289
+ "properties": {
290
+ "sourceScope": {
291
+ "type": "string",
292
+ "enum": [
293
+ "unit",
294
+ "workspace"
295
+ ],
296
+ "default": "unit"
297
+ },
298
+ "from": {
299
+ "type": "string",
300
+ "minLength": 1,
301
+ "pattern": "^(?!/)(?!\\.\\/)(?!.*\\\\)(?!.*:)(?!\\.\\.(/|$))(?!\\.$)(?!.*\\/\\.\\.\\/)(?!.*\\/\\.\\.$)(?!.*\\/\\.\\/)(?!.*\\/\\/)(?!.*\\0)(?!.*\\/\\.$)(?!.*\\/$).*$"
302
+ },
303
+ "to": {
304
+ "type": "string",
305
+ "minLength": 1,
306
+ "pattern": "^(?!/)(?!\\.\\/)(?!.*\\\\)(?!.*:)(?!\\.\\.(/|$))(?!\\.$)(?!.*\\/\\.\\.\\/)(?!.*\\/\\.\\.$)(?!.*\\/\\.\\/)(?!.*\\/\\/)(?!.*\\0)(?!.*\\/\\.$)(?!.*\\/$).*$"
307
+ },
308
+ "mode": {
309
+ "type": "string",
310
+ "enum": [
311
+ "preserve"
312
+ ]
313
+ }
314
+ }
315
+ }
316
+ },
317
+ "requiredPublicFiles": {
318
+ "type": "array",
319
+ "uniqueItems": true,
320
+ "items": {
321
+ "type": "string",
322
+ "minLength": 1,
323
+ "pattern": "^(?!/)(?!\\.\\/)(?!.*\\\\)(?!.*:)(?!\\.\\.(/|$))(?!\\.$)(?!.*\\/\\.\\.\\/)(?!.*\\/\\.\\.$)(?!.*\\/\\.\\/)(?!.*\\/\\/)(?!.*\\0)(?!.*\\/\\.$)(?!.*\\/$).*$"
324
+ }
325
+ },
326
+ "previousPublicBaseline": {
327
+ "type": "object",
328
+ "required": [
329
+ "mode"
330
+ ],
331
+ "additionalProperties": false,
332
+ "properties": {
333
+ "mode": {
334
+ "type": "string",
335
+ "enum": [
336
+ "none",
337
+ "bound"
338
+ ]
339
+ },
340
+ "githubHost": {
341
+ "type": "string",
342
+ "pattern": "^[a-zA-Z0-9.-]+$"
343
+ },
344
+ "repo": {
345
+ "type": "string",
346
+ "pattern": "^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$"
347
+ },
348
+ "ref": {
349
+ "type": "string",
350
+ "minLength": 1
351
+ },
352
+ "commit": {
353
+ "type": "string",
354
+ "pattern": "^[a-f0-9]{40,64}$"
355
+ },
356
+ "tree": {
357
+ "type": "string",
358
+ "pattern": "^[a-f0-9]{40,64}$"
359
+ },
360
+ "manifestDigest": {
361
+ "type": "string",
362
+ "pattern": "^[a-f0-9]{64}$"
363
+ }
364
+ },
365
+ "if": {
366
+ "properties": {
367
+ "mode": {
368
+ "const": "bound"
369
+ }
370
+ }
371
+ },
372
+ "then": {
373
+ "required": [
374
+ "repo",
375
+ "ref",
376
+ "commit"
377
+ ]
378
+ },
379
+ "else": {
380
+ "allOf": [
381
+ {
382
+ "not": {
383
+ "required": [
384
+ "repo"
385
+ ]
386
+ }
387
+ },
388
+ {
389
+ "not": {
390
+ "required": [
391
+ "githubHost"
392
+ ]
393
+ }
394
+ },
395
+ {
396
+ "not": {
397
+ "required": [
398
+ "ref"
399
+ ]
400
+ }
401
+ },
402
+ {
403
+ "not": {
404
+ "required": [
405
+ "commit"
406
+ ]
407
+ }
408
+ },
409
+ {
410
+ "not": {
411
+ "required": [
412
+ "tree"
413
+ ]
414
+ }
415
+ },
416
+ {
417
+ "not": {
418
+ "required": [
419
+ "manifestDigest"
420
+ ]
421
+ }
422
+ }
423
+ ]
424
+ }
425
+ }
426
+ },
427
+ "allOf": [
428
+ {
429
+ "if": {
430
+ "required": [
431
+ "production"
432
+ ],
433
+ "properties": {
434
+ "production": {
435
+ "required": [
436
+ "branchStrategy"
437
+ ],
438
+ "properties": {
439
+ "branchStrategy": {
440
+ "enum": [
441
+ "advance-existing-branch",
442
+ "initialize-default-branch"
443
+ ]
444
+ }
445
+ }
446
+ }
447
+ }
448
+ },
449
+ "then": {
450
+ "properties": {
451
+ "previousPublicBaseline": {
452
+ "properties": {
453
+ "mode": {
454
+ "const": "bound"
455
+ }
456
+ },
457
+ "required": [
458
+ "mode"
459
+ ]
460
+ }
461
+ }
462
+ }
463
+ },
464
+ {
465
+ "if": {
466
+ "required": [
467
+ "production"
468
+ ],
469
+ "properties": {
470
+ "production": {
471
+ "required": [
472
+ "branchStrategy"
473
+ ],
474
+ "properties": {
475
+ "branchStrategy": {
476
+ "const": "initialize-default-branch"
477
+ }
478
+ }
479
+ }
480
+ }
481
+ },
482
+ "then": {
483
+ "properties": {
484
+ "production": {
485
+ "required": [
486
+ "setAsDefaultBranch",
487
+ "expectedCurrentDefaultBranch"
488
+ ],
489
+ "properties": {
490
+ "setAsDefaultBranch": {
491
+ "const": true
492
+ }
493
+ }
494
+ }
495
+ }
496
+ }
497
+ },
498
+ {
499
+ "if": {
500
+ "required": [
501
+ "production"
502
+ ],
503
+ "properties": {
504
+ "production": {
505
+ "required": [
506
+ "setAsDefaultBranch"
507
+ ],
508
+ "properties": {
509
+ "setAsDefaultBranch": {
510
+ "const": true
511
+ }
512
+ }
513
+ }
514
+ }
515
+ },
516
+ "then": {
517
+ "properties": {
518
+ "production": {
519
+ "required": [
520
+ "branchStrategy"
521
+ ],
522
+ "properties": {
523
+ "branchStrategy": {
524
+ "const": "initialize-default-branch"
525
+ }
526
+ }
527
+ }
528
+ }
529
+ }
530
+ }
531
+ ]
532
+ }
533
+ },
534
+ "verificationGates": {
535
+ "type": "array",
536
+ "items": {
537
+ "$ref": "#/definitions/verificationGate"
538
+ }
539
+ },
540
+ "hooks": {
541
+ "type": "object",
542
+ "additionalProperties": false,
543
+ "properties": {
544
+ "docs": {
545
+ "$ref": "#/definitions/hook"
546
+ },
547
+ "build": {
548
+ "$ref": "#/definitions/hook"
549
+ },
550
+ "test": {
551
+ "$ref": "#/definitions/hook"
552
+ },
553
+ "typecheck": {
554
+ "$ref": "#/definitions/hook"
555
+ },
556
+ "lint": {
557
+ "$ref": "#/definitions/hook"
558
+ }
559
+ }
560
+ },
561
+ "policy": {
562
+ "type": "object",
563
+ "additionalProperties": false,
564
+ "properties": {
565
+ "forbiddenPaths": {
566
+ "type": "array",
567
+ "items": {
568
+ "type": "string"
569
+ }
570
+ },
571
+ "forbiddenContentPatterns": {
572
+ "type": "array",
573
+ "items": {
574
+ "type": "string"
575
+ }
576
+ }
577
+ }
578
+ }
579
+ },
580
+ "definitions": {
581
+ "hook": {
582
+ "type": "object",
583
+ "required": [
584
+ "command"
585
+ ],
586
+ "additionalProperties": false,
587
+ "properties": {
588
+ "command": {
589
+ "type": "array",
590
+ "minItems": 1,
591
+ "items": {
592
+ "type": "string"
593
+ }
594
+ },
595
+ "cwd": {
596
+ "type": "string",
597
+ "pattern": "^(?:\\.$|(?!\\/)(?!\\.\\/)(?!.*\\\\)(?!.*:)(?!\\.\\.(?:\\/|$))(?!.*\\/\\.\\.\\/)(?!.*\\/\\.\\.$)(?!.*\\/\\.\\/)(?!.*\\/\\/)(?!.*\\0)(?!.*\\/\\.$)(?!.*\\/\\/$)(?!.*\\/$).*)$"
598
+ },
599
+ "timeoutMs": {
600
+ "type": "integer",
601
+ "minimum": 1000,
602
+ "maximum": 7200000
603
+ },
604
+ "envAllowlist": {
605
+ "type": "array",
606
+ "items": {
607
+ "type": "string",
608
+ "pattern": "^[A-Z_][A-Z0-9_]*$"
609
+ },
610
+ "uniqueItems": true
611
+ }
612
+ }
613
+ },
614
+ "verificationGate": {
615
+ "type": "object",
616
+ "required": [
617
+ "id",
618
+ "phase",
619
+ "scope",
620
+ "command",
621
+ "cwd",
622
+ "timeoutMs",
623
+ "envAllowlist"
624
+ ],
625
+ "additionalProperties": false,
626
+ "properties": {
627
+ "id": {
628
+ "type": "string",
629
+ "pattern": "^[a-z0-9][a-z0-9._-]*$"
630
+ },
631
+ "phase": {
632
+ "type": "string",
633
+ "enum": [
634
+ "snapshot-verify",
635
+ "consumer-verify"
636
+ ]
637
+ },
638
+ "scope": {
639
+ "type": "object",
640
+ "required": [
641
+ "unit"
642
+ ],
643
+ "additionalProperties": false,
644
+ "properties": {
645
+ "unit": {
646
+ "type": "string",
647
+ "pattern": "^(?!\\.{1,2}$)[A-Za-z0-9][A-Za-z0-9._-]*$"
648
+ },
649
+ "distribution": {
650
+ "type": "string",
651
+ "enum": [
652
+ "npm",
653
+ "claude-plugin",
654
+ "codex-plugin"
655
+ ]
656
+ }
657
+ }
658
+ },
659
+ "command": {
660
+ "type": "array",
661
+ "minItems": 1,
662
+ "items": {
663
+ "type": "string"
664
+ }
665
+ },
666
+ "cwd": {
667
+ "type": "string",
668
+ "pattern": "^(?:\\.$|(?!\\/)(?!\\.\\/)(?!.*\\\\)(?!.*:)(?!\\.\\.(?:\\/|$))(?!.*\\/\\.\\.\\/)(?!.*\\/\\.\\.$)(?!.*\\/\\.\\/)(?!.*\\/\\/)(?!.*\\0)(?!.*\\/\\.$)(?!.*\\/\\/$)(?!.*\\/$).*)$"
669
+ },
670
+ "timeoutMs": {
671
+ "type": "integer",
672
+ "minimum": 1000,
673
+ "maximum": 7200000
674
+ },
675
+ "envAllowlist": {
676
+ "type": "array",
677
+ "items": {
678
+ "type": "string",
679
+ "pattern": "^[A-Z_][A-Z0-9_]*$"
680
+ },
681
+ "uniqueItems": true
682
+ },
683
+ "expectedJson": {
684
+ "type": "object"
685
+ }
686
+ },
687
+ "allOf": [
688
+ {
689
+ "if": {
690
+ "properties": {
691
+ "phase": {
692
+ "const": "consumer-verify"
693
+ }
694
+ },
695
+ "required": [
696
+ "phase"
697
+ ]
698
+ },
699
+ "then": {
700
+ "properties": {
701
+ "scope": {
702
+ "required": [
703
+ "unit",
704
+ "distribution"
705
+ ]
706
+ }
707
+ }
708
+ }
709
+ },
710
+ {
711
+ "if": {
712
+ "properties": {
713
+ "phase": {
714
+ "const": "snapshot-verify"
715
+ }
716
+ },
717
+ "required": [
718
+ "phase"
719
+ ]
720
+ },
721
+ "then": {
722
+ "properties": {
723
+ "scope": {
724
+ "not": {
725
+ "required": [
726
+ "distribution"
727
+ ]
728
+ }
729
+ }
730
+ }
731
+ }
732
+ }
733
+ ]
734
+ }
735
+ }
736
+ }