release-skill 0.1.3 → 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 (95) 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 +29 -0
  5. package/INSTALL.md +69 -32
  6. package/INSTALL.zh-CN.md +64 -26
  7. package/README.md +101 -37
  8. package/README.zh-CN.md +87 -28
  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 +11 -18
  28. package/adapters/claude/skills/release-prepare/SKILL.md +6 -6
  29. package/adapters/claude/skills/release-publish/SKILL.md +1 -4
  30. package/adapters/claude/skills/release-reconcile/SKILL.md +5 -5
  31. package/adapters/claude/skills/release-setup/SKILL.md +64 -80
  32. package/adapters/claude/skills/release-verify/SKILL.md +4 -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 +18 -18
  51. package/adapters/codex/skills/release-prepare/SKILL.md +13 -6
  52. package/adapters/codex/skills/release-publish/SKILL.md +8 -4
  53. package/adapters/codex/skills/release-reconcile/SKILL.md +12 -5
  54. package/adapters/codex/skills/release-setup/SKILL.md +71 -80
  55. package/adapters/codex/skills/release-verify/SKILL.md +11 -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 -788
  59. package/package.json +6 -2
  60. package/references/02-project-config.md +2 -2
  61. package/schemas/release-plan.schema.json +7 -1
  62. package/schemas/release-project.schema.json +8 -0
  63. package/scripts/build-bundle.mjs +133 -0
  64. package/skills/release-assess/SKILL.md +5 -6
  65. package/skills/release-help/SKILL.md +11 -18
  66. package/skills/release-prepare/SKILL.md +6 -6
  67. package/skills/release-publish/SKILL.md +1 -4
  68. package/skills/release-reconcile/SKILL.md +5 -5
  69. package/skills/release-setup/SKILL.md +64 -80
  70. package/skills/release-verify/SKILL.md +4 -7
  71. package/skills-src/release-assess/SKILL.md +5 -6
  72. package/skills-src/release-help/SKILL.md +11 -18
  73. package/skills-src/release-prepare/SKILL.md +6 -6
  74. package/skills-src/release-publish/SKILL.md +1 -4
  75. package/skills-src/release-reconcile/SKILL.md +5 -5
  76. package/skills-src/release-setup/SKILL.md +64 -80
  77. package/skills-src/release-verify/SKILL.md +4 -7
  78. package/src/adapters/npm.mjs +5 -13
  79. package/src/adapters/plugin-marketplace.mjs +67 -31
  80. package/src/artifacts/policy.mjs +4 -7
  81. package/src/artifacts/safe-fs-backend-internal.mjs +69 -21
  82. package/src/commands/prepare.mjs +22 -1
  83. package/src/commands/publish.mjs +1 -0
  84. package/src/commands/setup.mjs +667 -28
  85. package/src/core/approval.mjs +4 -6
  86. package/src/core/config.mjs +8 -8
  87. package/src/core/pkg-root.mjs +22 -0
  88. package/src/core/plan.mjs +9 -4
  89. package/src/core/run.mjs +4 -4
  90. package/src/core/trusted-resource.mjs +96 -0
  91. package/src/docs/version-gate.mjs +164 -0
  92. package/src/producers/build-adapters.mjs +512 -55
  93. package/src/snapshot/frozen.mjs +133 -3
  94. package/src/snapshot/public-map.mjs +7 -4
  95. package/src/snapshot/scan.mjs +2 -1
@@ -0,0 +1,860 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://release-skill.dev/schemas/release-plan/v1",
4
+ "title": "Release Plan",
5
+ "description": "Schema for frozen release plan produced by the prepare phase",
6
+ "type": "object",
7
+ "required": [
8
+ "planVersion",
9
+ "status",
10
+ "baseline",
11
+ "units",
12
+ "externalActions"
13
+ ],
14
+ "additionalProperties": false,
15
+ "properties": {
16
+ "planVersion": {
17
+ "type": "integer",
18
+ "const": 1
19
+ },
20
+ "status": {
21
+ "type": "string",
22
+ "enum": [
23
+ "DISCOVERED",
24
+ "ASSESSED",
25
+ "PREPARED",
26
+ "APPROVED",
27
+ "PUBLISHING",
28
+ "PUBLISHED",
29
+ "VERIFIED",
30
+ "NEEDS_INPUT",
31
+ "BLOCKED",
32
+ "PARTIAL"
33
+ ]
34
+ },
35
+ "production": {
36
+ "type": "object",
37
+ "required": [
38
+ "mode",
39
+ "assetRoot"
40
+ ],
41
+ "additionalProperties": false,
42
+ "properties": {
43
+ "mode": {
44
+ "const": "github-npm-v1"
45
+ },
46
+ "assetRoot": {
47
+ "type": "string",
48
+ "minLength": 1
49
+ }
50
+ }
51
+ },
52
+ "baseline": {
53
+ "type": "object",
54
+ "required": [
55
+ "gitTreeHash"
56
+ ],
57
+ "additionalProperties": false,
58
+ "properties": {
59
+ "gitTreeHash": {
60
+ "type": "string",
61
+ "minLength": 1
62
+ },
63
+ "workspaceDigest": {
64
+ "type": "string",
65
+ "minLength": 1,
66
+ "description": "Deterministic digest of workspace file state at plan freeze time"
67
+ },
68
+ "workspaceDigestAlgorithm": {
69
+ "type": "string",
70
+ "const": "git-workspace-v2",
71
+ "description": "Versioned algorithm authority for workspaceDigest"
72
+ },
73
+ "headCommit": {
74
+ "type": "string"
75
+ },
76
+ "dirtyFiles": {
77
+ "type": "array",
78
+ "items": {
79
+ "type": "string"
80
+ }
81
+ },
82
+ "capturedAt": {
83
+ "type": "string",
84
+ "format": "date-time"
85
+ }
86
+ }
87
+ },
88
+ "units": {
89
+ "type": "array",
90
+ "minItems": 1,
91
+ "items": {
92
+ "type": "object",
93
+ "required": [
94
+ "id",
95
+ "targetVersion",
96
+ "previousPublicBaseline"
97
+ ],
98
+ "additionalProperties": false,
99
+ "properties": {
100
+ "id": {
101
+ "type": "string",
102
+ "minLength": 1,
103
+ "pattern": "^(?!\\.{1,2}$)[A-Za-z0-9][A-Za-z0-9._-]*$"
104
+ },
105
+ "targetVersion": {
106
+ "type": "string",
107
+ "minLength": 1
108
+ },
109
+ "source": {
110
+ "type": "string"
111
+ },
112
+ "publicRepo": {
113
+ "type": "string"
114
+ },
115
+ "tagTemplate": {
116
+ "type": "string"
117
+ },
118
+ "snapshotDigest": {
119
+ "type": "string",
120
+ "description": "SHA-256 digest of the snapshot content"
121
+ },
122
+ "productionConfig": {
123
+ "type": "object",
124
+ "required": [
125
+ "githubHost",
126
+ "branchTemplate",
127
+ "branchStrategy"
128
+ ],
129
+ "additionalProperties": false,
130
+ "properties": {
131
+ "githubHost": {
132
+ "type": "string"
133
+ },
134
+ "branchTemplate": {
135
+ "type": "string"
136
+ },
137
+ "releaseTitleTemplate": {
138
+ "type": "string"
139
+ },
140
+ "releaseNotes": {
141
+ "type": "string"
142
+ },
143
+ "branchStrategy": {
144
+ "type": "string",
145
+ "enum": [
146
+ "create-release-branch",
147
+ "advance-existing-branch",
148
+ "initialize-default-branch"
149
+ ]
150
+ },
151
+ "setAsDefaultBranch": {
152
+ "type": "boolean"
153
+ },
154
+ "expectedCurrentDefaultBranch": {
155
+ "type": "string",
156
+ "minLength": 1
157
+ }
158
+ },
159
+ "allOf": [
160
+ {
161
+ "if": {
162
+ "properties": {
163
+ "branchStrategy": {
164
+ "const": "initialize-default-branch"
165
+ }
166
+ },
167
+ "required": [
168
+ "branchStrategy"
169
+ ]
170
+ },
171
+ "then": {
172
+ "required": [
173
+ "setAsDefaultBranch",
174
+ "expectedCurrentDefaultBranch"
175
+ ],
176
+ "properties": {
177
+ "setAsDefaultBranch": {
178
+ "const": true
179
+ }
180
+ }
181
+ }
182
+ },
183
+ {
184
+ "if": {
185
+ "properties": {
186
+ "setAsDefaultBranch": {
187
+ "const": true
188
+ }
189
+ },
190
+ "required": [
191
+ "setAsDefaultBranch"
192
+ ]
193
+ },
194
+ "then": {
195
+ "properties": {
196
+ "branchStrategy": {
197
+ "const": "initialize-default-branch"
198
+ }
199
+ }
200
+ }
201
+ }
202
+ ]
203
+ },
204
+ "frozenSnapshot": {
205
+ "type": "object",
206
+ "required": [
207
+ "path",
208
+ "manifestDigest",
209
+ "gitObjectDir",
210
+ "branch",
211
+ "branchStrategy",
212
+ "commit",
213
+ "tree",
214
+ "commitTimestamp"
215
+ ],
216
+ "additionalProperties": false,
217
+ "properties": {
218
+ "path": {
219
+ "type": "string",
220
+ "minLength": 1
221
+ },
222
+ "manifestDigest": {
223
+ "type": "string",
224
+ "pattern": "^[a-f0-9]{64}$"
225
+ },
226
+ "gitObjectDir": {
227
+ "type": "string",
228
+ "minLength": 1
229
+ },
230
+ "branch": {
231
+ "type": "string",
232
+ "minLength": 1
233
+ },
234
+ "commit": {
235
+ "type": "string",
236
+ "pattern": "^[a-f0-9]{40,64}$"
237
+ },
238
+ "tree": {
239
+ "type": "string",
240
+ "pattern": "^[a-f0-9]{40,64}$"
241
+ },
242
+ "commitTimestamp": {
243
+ "type": "string",
244
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+00:00$",
245
+ "description": "Plan freeze timestamp sampled exactly once during production prepare, in canonical UTC second precision. Written verbatim to GIT_AUTHOR_DATE and GIT_COMMITTER_DATE of the frozen release commit, so it always equals the commit's %aI and %cI byte-for-byte, and must equal the plan's createdAt."
246
+ },
247
+ "parentCommit": {
248
+ "type": "string",
249
+ "pattern": "^[a-f0-9]{40,64}$"
250
+ },
251
+ "branchStrategy": {
252
+ "type": "string",
253
+ "enum": [
254
+ "create-release-branch",
255
+ "advance-existing-branch",
256
+ "initialize-default-branch"
257
+ ]
258
+ },
259
+ "npm": {
260
+ "anyOf": [
261
+ {
262
+ "type": "null"
263
+ },
264
+ {
265
+ "type": "object",
266
+ "required": [
267
+ "tarballPath",
268
+ "tarballSha256",
269
+ "integrity",
270
+ "size"
271
+ ],
272
+ "additionalProperties": false,
273
+ "properties": {
274
+ "tarballPath": {
275
+ "type": "string",
276
+ "minLength": 1
277
+ },
278
+ "tarballSha256": {
279
+ "type": "string",
280
+ "pattern": "^[a-f0-9]{64}$"
281
+ },
282
+ "integrity": {
283
+ "type": "string",
284
+ "minLength": 1
285
+ },
286
+ "size": {
287
+ "type": "integer",
288
+ "minimum": 1
289
+ }
290
+ }
291
+ }
292
+ ]
293
+ }
294
+ },
295
+ "allOf": [
296
+ {
297
+ "if": {
298
+ "properties": {
299
+ "branchStrategy": {
300
+ "enum": [
301
+ "advance-existing-branch",
302
+ "initialize-default-branch"
303
+ ]
304
+ }
305
+ },
306
+ "required": [
307
+ "branchStrategy"
308
+ ]
309
+ },
310
+ "then": {
311
+ "required": [
312
+ "parentCommit"
313
+ ]
314
+ }
315
+ },
316
+ {
317
+ "if": {
318
+ "properties": {
319
+ "branchStrategy": {
320
+ "const": "create-release-branch"
321
+ }
322
+ },
323
+ "required": [
324
+ "branchStrategy"
325
+ ]
326
+ },
327
+ "then": {
328
+ "not": {
329
+ "required": [
330
+ "parentCommit"
331
+ ]
332
+ }
333
+ }
334
+ }
335
+ ]
336
+ },
337
+ "distributions": {
338
+ "type": "array",
339
+ "items": {
340
+ "type": "object",
341
+ "required": [
342
+ "type"
343
+ ],
344
+ "additionalProperties": false,
345
+ "properties": {
346
+ "type": {
347
+ "type": "string",
348
+ "enum": [
349
+ "npm",
350
+ "claude-plugin",
351
+ "codex-plugin"
352
+ ]
353
+ },
354
+ "package": {
355
+ "type": "string",
356
+ "maxLength": 214,
357
+ "pattern": "^(?:@[a-z0-9][a-z0-9._-]*/[a-z0-9][a-z0-9._-]*|[a-z0-9][a-z0-9._-]*)$"
358
+ },
359
+ "access": {
360
+ "type": "string",
361
+ "enum": [
362
+ "public",
363
+ "restricted"
364
+ ]
365
+ },
366
+ "provenance": {
367
+ "type": "boolean"
368
+ },
369
+ "tag": {
370
+ "type": "string",
371
+ "minLength": 1
372
+ },
373
+ "registry": {
374
+ "type": "string",
375
+ "minLength": 1,
376
+ "pattern": "^https://[^\\s]+$",
377
+ "description": "Normalized HTTPS URL of the npm registry"
378
+ },
379
+ "publisher": {
380
+ "type": "string",
381
+ "minLength": 1,
382
+ "pattern": "^[a-z0-9][a-z0-9._-]*$",
383
+ "description": "Expected npm whoami username for this registry"
384
+ },
385
+ "plugin": {
386
+ "type": "string",
387
+ "minLength": 1,
388
+ "pattern": "^[a-z0-9][a-z0-9._-]*$"
389
+ },
390
+ "marketplace": {
391
+ "type": "string",
392
+ "minLength": 1,
393
+ "pattern": "^[a-z0-9][a-z0-9._-]*$"
394
+ },
395
+ "entrySkill": {
396
+ "type": "string",
397
+ "minLength": 1,
398
+ "pattern": "^[a-z0-9][a-z0-9-]*$"
399
+ },
400
+ "smokeBin": {
401
+ "type": "string",
402
+ "minLength": 1
403
+ },
404
+ "smokeArgs": {
405
+ "type": "array",
406
+ "items": {
407
+ "type": "string"
408
+ }
409
+ },
410
+ "smokeExpectedJson": {
411
+ "type": "object"
412
+ }
413
+ },
414
+ "allOf": [
415
+ {
416
+ "if": {
417
+ "properties": {
418
+ "type": {
419
+ "const": "npm"
420
+ }
421
+ }
422
+ },
423
+ "then": {
424
+ "required": [
425
+ "package",
426
+ "registry",
427
+ "publisher"
428
+ ]
429
+ }
430
+ },
431
+ {
432
+ "if": {
433
+ "properties": {
434
+ "type": {
435
+ "enum": [
436
+ "claude-plugin",
437
+ "codex-plugin"
438
+ ]
439
+ }
440
+ }
441
+ },
442
+ "then": {
443
+ "required": [
444
+ "plugin",
445
+ "marketplace",
446
+ "entrySkill"
447
+ ]
448
+ }
449
+ },
450
+ {
451
+ "if": {
452
+ "required": [
453
+ "smokeExpectedJson"
454
+ ],
455
+ "properties": {
456
+ "smokeBin": {
457
+ "minLength": 1
458
+ }
459
+ }
460
+ },
461
+ "then": {
462
+ "required": [
463
+ "smokeBin"
464
+ ]
465
+ }
466
+ },
467
+ {
468
+ "if": {
469
+ "required": [
470
+ "smokeArgs"
471
+ ],
472
+ "properties": {
473
+ "smokeBin": {
474
+ "minLength": 1
475
+ }
476
+ }
477
+ },
478
+ "then": {
479
+ "required": [
480
+ "smokeBin"
481
+ ]
482
+ }
483
+ }
484
+ ]
485
+ }
486
+ },
487
+ "previousPublicBaseline": {
488
+ "type": "object",
489
+ "required": [
490
+ "mode",
491
+ "status"
492
+ ],
493
+ "additionalProperties": false,
494
+ "properties": {
495
+ "mode": {
496
+ "type": "string",
497
+ "enum": [
498
+ "none",
499
+ "bound"
500
+ ]
501
+ },
502
+ "githubHost": {
503
+ "type": "string"
504
+ },
505
+ "repo": {
506
+ "type": "string"
507
+ },
508
+ "ref": {
509
+ "type": "string"
510
+ },
511
+ "commit": {
512
+ "type": "string"
513
+ },
514
+ "tree": {
515
+ "type": "string"
516
+ },
517
+ "manifestDigest": {
518
+ "type": "string"
519
+ },
520
+ "observedCommit": {
521
+ "type": "string"
522
+ },
523
+ "observedAt": {
524
+ "type": "string",
525
+ "format": "date-time"
526
+ },
527
+ "status": {
528
+ "type": "string",
529
+ "enum": [
530
+ "consistent",
531
+ "drifted",
532
+ "unknown",
533
+ "unobserved-offline",
534
+ "blocking"
535
+ ]
536
+ }
537
+ },
538
+ "if": {
539
+ "properties": {
540
+ "mode": {
541
+ "const": "bound"
542
+ }
543
+ }
544
+ },
545
+ "then": {
546
+ "required": [
547
+ "repo",
548
+ "ref",
549
+ "commit"
550
+ ]
551
+ },
552
+ "else": {
553
+ "allOf": [
554
+ {
555
+ "not": {
556
+ "required": [
557
+ "repo"
558
+ ]
559
+ }
560
+ },
561
+ {
562
+ "not": {
563
+ "required": [
564
+ "githubHost"
565
+ ]
566
+ }
567
+ },
568
+ {
569
+ "not": {
570
+ "required": [
571
+ "ref"
572
+ ]
573
+ }
574
+ },
575
+ {
576
+ "not": {
577
+ "required": [
578
+ "commit"
579
+ ]
580
+ }
581
+ },
582
+ {
583
+ "not": {
584
+ "required": [
585
+ "tree"
586
+ ]
587
+ }
588
+ },
589
+ {
590
+ "not": {
591
+ "required": [
592
+ "manifestDigest"
593
+ ]
594
+ }
595
+ },
596
+ {
597
+ "not": {
598
+ "required": [
599
+ "observedCommit"
600
+ ]
601
+ }
602
+ },
603
+ {
604
+ "not": {
605
+ "required": [
606
+ "observedAt"
607
+ ]
608
+ }
609
+ }
610
+ ]
611
+ }
612
+ }
613
+ }
614
+ }
615
+ },
616
+ "configDigest": {
617
+ "type": "string",
618
+ "minLength": 1,
619
+ "description": "Digest of the project configuration at plan freeze time"
620
+ },
621
+ "verificationGates": {
622
+ "type": "array",
623
+ "items": {
624
+ "$ref": "#/definitions/verificationGate"
625
+ }
626
+ },
627
+ "externalActions": {
628
+ "type": "array",
629
+ "minItems": 1,
630
+ "items": {
631
+ "type": "object",
632
+ "required": [
633
+ "id",
634
+ "type",
635
+ "adapter"
636
+ ],
637
+ "additionalProperties": false,
638
+ "properties": {
639
+ "id": {
640
+ "type": "string",
641
+ "minLength": 1
642
+ },
643
+ "type": {
644
+ "type": "string",
645
+ "enum": [
646
+ "push-commit",
647
+ "push-snapshot",
648
+ "create-tag",
649
+ "npm-publish",
650
+ "github-release",
651
+ "claude-marketplace-install",
652
+ "codex-marketplace-install",
653
+ "set-default-branch"
654
+ ]
655
+ },
656
+ "adapter": {
657
+ "type": "string",
658
+ "minLength": 1
659
+ },
660
+ "unitId": {
661
+ "type": "string"
662
+ },
663
+ "parameters": {
664
+ "type": "object"
665
+ },
666
+ "expected": {
667
+ "type": "object",
668
+ "description": "Expected observation state for verification"
669
+ },
670
+ "status": {
671
+ "type": "string",
672
+ "enum": [
673
+ "PENDING",
674
+ "SUCCEEDED",
675
+ "FAILED",
676
+ "SKIPPED"
677
+ ],
678
+ "description": "Action execution status"
679
+ }
680
+ }
681
+ }
682
+ },
683
+ "createdAt": {
684
+ "type": "string",
685
+ "format": "date-time"
686
+ },
687
+ "publishedAt": {
688
+ "type": "string",
689
+ "format": "date-time",
690
+ "description": "ISO 8601 timestamp when the plan was published"
691
+ },
692
+ "reconciledAt": {
693
+ "type": "string",
694
+ "format": "date-time",
695
+ "description": "ISO 8601 timestamp when the plan was last reconciled"
696
+ },
697
+ "snapshotDigest": {
698
+ "type": "string",
699
+ "description": "Overall snapshot digest across all units"
700
+ },
701
+ "digest": {
702
+ "type": "string",
703
+ "minLength": 1
704
+ },
705
+ "waivers": {
706
+ "type": "array",
707
+ "items": {
708
+ "type": "object",
709
+ "required": [
710
+ "rule",
711
+ "reason",
712
+ "responsible",
713
+ "expiresAt"
714
+ ],
715
+ "additionalProperties": false,
716
+ "properties": {
717
+ "rule": {
718
+ "type": "string",
719
+ "minLength": 1
720
+ },
721
+ "reason": {
722
+ "type": "string",
723
+ "minLength": 1
724
+ },
725
+ "responsible": {
726
+ "type": "string",
727
+ "minLength": 1
728
+ },
729
+ "expiresAt": {
730
+ "type": "string",
731
+ "format": "date-time"
732
+ }
733
+ }
734
+ }
735
+ }
736
+ },
737
+ "definitions": {
738
+ "verificationGate": {
739
+ "type": "object",
740
+ "required": [
741
+ "id",
742
+ "phase",
743
+ "scope",
744
+ "command",
745
+ "cwd",
746
+ "timeoutMs",
747
+ "envAllowlist"
748
+ ],
749
+ "additionalProperties": false,
750
+ "properties": {
751
+ "id": {
752
+ "type": "string",
753
+ "pattern": "^[a-z0-9][a-z0-9._-]*$"
754
+ },
755
+ "phase": {
756
+ "type": "string",
757
+ "enum": [
758
+ "snapshot-verify",
759
+ "consumer-verify"
760
+ ]
761
+ },
762
+ "scope": {
763
+ "type": "object",
764
+ "required": [
765
+ "unit"
766
+ ],
767
+ "additionalProperties": false,
768
+ "properties": {
769
+ "unit": {
770
+ "type": "string",
771
+ "pattern": "^(?!\\.{1,2}$)[A-Za-z0-9][A-Za-z0-9._-]*$"
772
+ },
773
+ "distribution": {
774
+ "type": "string",
775
+ "enum": [
776
+ "npm",
777
+ "claude-plugin",
778
+ "codex-plugin"
779
+ ]
780
+ }
781
+ }
782
+ },
783
+ "command": {
784
+ "type": "array",
785
+ "minItems": 1,
786
+ "items": {
787
+ "type": "string"
788
+ }
789
+ },
790
+ "cwd": {
791
+ "type": "string",
792
+ "pattern": "^(?:\\.$|(?!\\/)(?!\\.\\/)(?!.*\\\\)(?!.*:)(?!\\.\\.(?:\\/|$))(?!.*\\/\\.\\.\\/)(?!.*\\/\\.\\.$)(?!.*\\/\\.\\/)(?!.*\\/\\/)(?!.*\\0)(?!.*\\/\\.$)(?!.*\\/\\/$)(?!.*\\/$).*)$"
793
+ },
794
+ "timeoutMs": {
795
+ "type": "integer",
796
+ "minimum": 1000,
797
+ "maximum": 7200000
798
+ },
799
+ "envAllowlist": {
800
+ "type": "array",
801
+ "items": {
802
+ "type": "string",
803
+ "pattern": "^[A-Z_][A-Z0-9_]*$"
804
+ },
805
+ "uniqueItems": true
806
+ },
807
+ "expectedJson": {
808
+ "type": "object"
809
+ }
810
+ },
811
+ "allOf": [
812
+ {
813
+ "if": {
814
+ "properties": {
815
+ "phase": {
816
+ "const": "consumer-verify"
817
+ }
818
+ },
819
+ "required": [
820
+ "phase"
821
+ ]
822
+ },
823
+ "then": {
824
+ "properties": {
825
+ "scope": {
826
+ "required": [
827
+ "unit",
828
+ "distribution"
829
+ ]
830
+ }
831
+ }
832
+ }
833
+ },
834
+ {
835
+ "if": {
836
+ "properties": {
837
+ "phase": {
838
+ "const": "snapshot-verify"
839
+ }
840
+ },
841
+ "required": [
842
+ "phase"
843
+ ]
844
+ },
845
+ "then": {
846
+ "properties": {
847
+ "scope": {
848
+ "not": {
849
+ "required": [
850
+ "distribution"
851
+ ]
852
+ }
853
+ }
854
+ }
855
+ }
856
+ }
857
+ ]
858
+ }
859
+ }
860
+ }