release-skill 0.2.0 → 0.2.1

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