release-skill 0.2.0 → 0.2.2

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 (72) 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 +35 -0
  7. package/INSTALL.md +186 -4
  8. package/INSTALL.zh-CN.md +166 -4
  9. package/README.md +116 -13
  10. package/README.zh-CN.md +73 -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 +1718 -600
  14. package/adapters/claude/schemas/release-plan.schema.json +44 -2
  15. package/adapters/claude/schemas/release-project.schema.json +46 -4
  16. package/adapters/claude/schemas/release-run.schema.json +1 -0
  17. package/adapters/codex/.codex-plugin/plugin.json +2 -2
  18. package/adapters/codex/bin/release-skill.bundle.mjs +1718 -600
  19. package/adapters/codex/schemas/release-plan.schema.json +44 -2
  20. package/adapters/codex/schemas/release-project.schema.json +46 -4
  21. package/adapters/codex/schemas/release-run.schema.json +1 -0
  22. package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
  23. package/adapters/kimi/bin/release-skill.bundle.mjs +1718 -600
  24. package/adapters/kimi/schemas/release-plan.schema.json +44 -2
  25. package/adapters/kimi/schemas/release-project.schema.json +46 -4
  26. package/adapters/kimi/schemas/release-run.schema.json +1 -0
  27. package/adapters/workbuddy/.codebuddy-plugin/plugin.json +12 -0
  28. package/adapters/workbuddy/bin/release-skill.bundle.mjs +86481 -0
  29. package/adapters/workbuddy/bin/release-skill.mjs +54 -0
  30. package/adapters/workbuddy/native/safe-write/binding.gyp +41 -0
  31. package/adapters/workbuddy/native/safe-write/prebuilds/darwin-arm64/safe_write.node +0 -0
  32. package/adapters/workbuddy/native/safe-write/prebuilds.json +24 -0
  33. package/adapters/workbuddy/native/safe-write/src/safe_write.cc +2032 -0
  34. package/adapters/workbuddy/schemas/.render-manifest.json +37 -0
  35. package/adapters/workbuddy/schemas/approval-record.schema.json +115 -0
  36. package/adapters/workbuddy/schemas/artifact-lock.schema.json +111 -0
  37. package/adapters/workbuddy/schemas/artifact-plan.schema.json +52 -0
  38. package/adapters/workbuddy/schemas/artifact-policy.schema.json +76 -0
  39. package/adapters/workbuddy/schemas/evidence-event.schema.json +89 -0
  40. package/adapters/workbuddy/schemas/release-plan.schema.json +924 -0
  41. package/adapters/workbuddy/schemas/release-project.schema.json +951 -0
  42. package/adapters/workbuddy/schemas/release-run.schema.json +344 -0
  43. package/adapters/workbuddy/skills/release-assess/SKILL.md +51 -0
  44. package/adapters/workbuddy/skills/release-help/SKILL.md +77 -0
  45. package/adapters/workbuddy/skills/release-prepare/SKILL.md +92 -0
  46. package/adapters/workbuddy/skills/release-publish/SKILL.md +57 -0
  47. package/adapters/workbuddy/skills/release-reconcile/SKILL.md +73 -0
  48. package/adapters/workbuddy/skills/release-setup/SKILL.md +95 -0
  49. package/adapters/workbuddy/skills/release-verify/SKILL.md +70 -0
  50. package/bin/release-skill-cli.mjs +46 -4
  51. package/bin/release-skill.bundle.mjs +1718 -600
  52. package/package.json +2 -1
  53. package/references/02-project-config.md +7 -0
  54. package/references/06-adapter-contract.md +21 -2
  55. package/schemas/release-plan.schema.json +44 -2
  56. package/schemas/release-project.schema.json +46 -4
  57. package/schemas/release-run.schema.json +1 -0
  58. package/scripts/sync-public-files.mjs +27 -4
  59. package/src/adapters/contract.mjs +1 -0
  60. package/src/adapters/plugin-marketplace.mjs +536 -23
  61. package/src/commands/assess.mjs +50 -1
  62. package/src/commands/prepare.mjs +273 -9
  63. package/src/commands/publish.mjs +1 -0
  64. package/src/commands/reconcile.mjs +1 -0
  65. package/src/commands/setup.mjs +7 -3
  66. package/src/commands/verify.mjs +2 -0
  67. package/src/core/checkpoints.mjs +7 -2
  68. package/src/core/plan.mjs +97 -4
  69. package/src/core/verification-gates.mjs +1 -1
  70. package/src/platforms/codebuddy.mjs +618 -0
  71. package/src/platforms/registry.mjs +100 -5
  72. package/src/producers/build-adapters.mjs +48 -6
@@ -0,0 +1,924 @@
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
+ "codebuddy-plugin"
358
+ ]
359
+ },
360
+ "package": {
361
+ "type": "string",
362
+ "maxLength": 214,
363
+ "pattern": "^(?:@[a-z0-9][a-z0-9._-]*/[a-z0-9][a-z0-9._-]*|[a-z0-9][a-z0-9._-]*)$"
364
+ },
365
+ "access": {
366
+ "type": "string",
367
+ "enum": [
368
+ "public",
369
+ "restricted"
370
+ ]
371
+ },
372
+ "provenance": {
373
+ "type": "boolean"
374
+ },
375
+ "tag": {
376
+ "type": "string",
377
+ "minLength": 1
378
+ },
379
+ "registry": {
380
+ "type": "string",
381
+ "minLength": 1,
382
+ "pattern": "^https://[^\\s]+$",
383
+ "description": "Normalized HTTPS URL of the npm registry"
384
+ },
385
+ "publisher": {
386
+ "type": "string",
387
+ "minLength": 1,
388
+ "pattern": "^[a-z0-9][a-z0-9._-]*$",
389
+ "description": "Expected npm whoami username for this registry"
390
+ },
391
+ "plugin": {
392
+ "type": "string",
393
+ "minLength": 1,
394
+ "pattern": "^[a-z0-9][a-z0-9._-]*$"
395
+ },
396
+ "marketplace": {
397
+ "type": "string",
398
+ "minLength": 1,
399
+ "pattern": "^[a-z0-9][a-z0-9._-]*$"
400
+ },
401
+ "marketplaceRepo": {
402
+ "type": "string",
403
+ "pattern": "^[a-z0-9][a-z0-9._-]*/[a-z0-9][a-z0-9._-]*$",
404
+ "description": "外部独立市场仓库 owner/name;存在即启用外部市场形态"
405
+ },
406
+ "entrySkill": {
407
+ "type": "string",
408
+ "minLength": 1,
409
+ "pattern": "^[a-z0-9][a-z0-9-]*$"
410
+ },
411
+ "smokeBin": {
412
+ "type": "string",
413
+ "minLength": 1
414
+ },
415
+ "smokeArgs": {
416
+ "type": "array",
417
+ "items": {
418
+ "type": "string"
419
+ }
420
+ },
421
+ "smokeExpectedJson": {
422
+ "type": "object"
423
+ }
424
+ },
425
+ "allOf": [
426
+ {
427
+ "if": {
428
+ "properties": {
429
+ "type": {
430
+ "const": "npm"
431
+ }
432
+ }
433
+ },
434
+ "then": {
435
+ "required": [
436
+ "package",
437
+ "registry",
438
+ "publisher"
439
+ ]
440
+ }
441
+ },
442
+ {
443
+ "if": {
444
+ "properties": {
445
+ "type": {
446
+ "enum": [
447
+ "claude-plugin",
448
+ "codex-plugin"
449
+ ]
450
+ }
451
+ }
452
+ },
453
+ "then": {
454
+ "required": [
455
+ "plugin",
456
+ "marketplace",
457
+ "entrySkill"
458
+ ]
459
+ }
460
+ },
461
+ {
462
+ "if": {
463
+ "properties": {
464
+ "type": {
465
+ "const": "kimi-plugin"
466
+ }
467
+ }
468
+ },
469
+ "then": {
470
+ "required": [
471
+ "plugin",
472
+ "entrySkill"
473
+ ]
474
+ }
475
+ },
476
+ {
477
+ "if": {
478
+ "properties": {
479
+ "type": {
480
+ "const": "codebuddy-plugin"
481
+ }
482
+ }
483
+ },
484
+ "then": {
485
+ "required": [
486
+ "plugin",
487
+ "entrySkill"
488
+ ]
489
+ }
490
+ },
491
+ {
492
+ "if": {
493
+ "properties": {
494
+ "type": {
495
+ "enum": [
496
+ "kimi-plugin",
497
+ "codebuddy-plugin"
498
+ ]
499
+ }
500
+ }
501
+ },
502
+ "then": {
503
+ "not": {
504
+ "required": [
505
+ "marketplaceRepo"
506
+ ]
507
+ }
508
+ }
509
+ },
510
+ {
511
+ "if": {
512
+ "required": [
513
+ "smokeExpectedJson"
514
+ ],
515
+ "properties": {
516
+ "smokeBin": {
517
+ "minLength": 1
518
+ }
519
+ }
520
+ },
521
+ "then": {
522
+ "required": [
523
+ "smokeBin"
524
+ ]
525
+ }
526
+ },
527
+ {
528
+ "if": {
529
+ "required": [
530
+ "smokeArgs"
531
+ ],
532
+ "properties": {
533
+ "smokeBin": {
534
+ "minLength": 1
535
+ }
536
+ }
537
+ },
538
+ "then": {
539
+ "required": [
540
+ "smokeBin"
541
+ ]
542
+ }
543
+ }
544
+ ]
545
+ }
546
+ },
547
+ "previousPublicBaseline": {
548
+ "type": "object",
549
+ "required": [
550
+ "mode",
551
+ "status"
552
+ ],
553
+ "additionalProperties": false,
554
+ "properties": {
555
+ "mode": {
556
+ "type": "string",
557
+ "enum": [
558
+ "none",
559
+ "bound"
560
+ ]
561
+ },
562
+ "githubHost": {
563
+ "type": "string"
564
+ },
565
+ "repo": {
566
+ "type": "string"
567
+ },
568
+ "ref": {
569
+ "type": "string"
570
+ },
571
+ "commit": {
572
+ "type": "string"
573
+ },
574
+ "tree": {
575
+ "type": "string"
576
+ },
577
+ "manifestDigest": {
578
+ "type": "string"
579
+ },
580
+ "observedCommit": {
581
+ "type": "string"
582
+ },
583
+ "observedAt": {
584
+ "type": "string",
585
+ "format": "date-time"
586
+ },
587
+ "status": {
588
+ "type": "string",
589
+ "enum": [
590
+ "consistent",
591
+ "drifted",
592
+ "unknown",
593
+ "unobserved-offline",
594
+ "blocking"
595
+ ]
596
+ }
597
+ },
598
+ "if": {
599
+ "properties": {
600
+ "mode": {
601
+ "const": "bound"
602
+ }
603
+ }
604
+ },
605
+ "then": {
606
+ "required": [
607
+ "repo",
608
+ "ref",
609
+ "commit"
610
+ ]
611
+ },
612
+ "else": {
613
+ "allOf": [
614
+ {
615
+ "not": {
616
+ "required": [
617
+ "repo"
618
+ ]
619
+ }
620
+ },
621
+ {
622
+ "not": {
623
+ "required": [
624
+ "githubHost"
625
+ ]
626
+ }
627
+ },
628
+ {
629
+ "not": {
630
+ "required": [
631
+ "ref"
632
+ ]
633
+ }
634
+ },
635
+ {
636
+ "not": {
637
+ "required": [
638
+ "commit"
639
+ ]
640
+ }
641
+ },
642
+ {
643
+ "not": {
644
+ "required": [
645
+ "tree"
646
+ ]
647
+ }
648
+ },
649
+ {
650
+ "not": {
651
+ "required": [
652
+ "manifestDigest"
653
+ ]
654
+ }
655
+ },
656
+ {
657
+ "not": {
658
+ "required": [
659
+ "observedCommit"
660
+ ]
661
+ }
662
+ },
663
+ {
664
+ "not": {
665
+ "required": [
666
+ "observedAt"
667
+ ]
668
+ }
669
+ }
670
+ ]
671
+ }
672
+ }
673
+ }
674
+ }
675
+ },
676
+ "configDigest": {
677
+ "type": "string",
678
+ "minLength": 1,
679
+ "description": "Digest of the project configuration at plan freeze time"
680
+ },
681
+ "verificationGates": {
682
+ "type": "array",
683
+ "items": {
684
+ "$ref": "#/definitions/verificationGate"
685
+ }
686
+ },
687
+ "externalActions": {
688
+ "type": "array",
689
+ "minItems": 1,
690
+ "items": {
691
+ "type": "object",
692
+ "required": [
693
+ "id",
694
+ "type",
695
+ "adapter"
696
+ ],
697
+ "additionalProperties": false,
698
+ "properties": {
699
+ "id": {
700
+ "type": "string",
701
+ "minLength": 1
702
+ },
703
+ "type": {
704
+ "type": "string",
705
+ "enum": [
706
+ "push-commit",
707
+ "push-snapshot",
708
+ "create-tag",
709
+ "npm-publish",
710
+ "github-release",
711
+ "claude-marketplace-install",
712
+ "codex-marketplace-install",
713
+ "kimi-marketplace-install",
714
+ "codebuddy-marketplace-install",
715
+ "set-default-branch"
716
+ ]
717
+ },
718
+ "adapter": {
719
+ "type": "string",
720
+ "minLength": 1
721
+ },
722
+ "unitId": {
723
+ "type": "string"
724
+ },
725
+ "parameters": {
726
+ "type": "object"
727
+ },
728
+ "expected": {
729
+ "type": "object",
730
+ "description": "Expected observation state for verification"
731
+ },
732
+ "status": {
733
+ "type": "string",
734
+ "enum": [
735
+ "PENDING",
736
+ "SUCCEEDED",
737
+ "FAILED",
738
+ "SKIPPED"
739
+ ],
740
+ "description": "Action execution status"
741
+ }
742
+ }
743
+ }
744
+ },
745
+ "createdAt": {
746
+ "type": "string",
747
+ "format": "date-time"
748
+ },
749
+ "publishedAt": {
750
+ "type": "string",
751
+ "format": "date-time",
752
+ "description": "ISO 8601 timestamp when the plan was published"
753
+ },
754
+ "reconciledAt": {
755
+ "type": "string",
756
+ "format": "date-time",
757
+ "description": "ISO 8601 timestamp when the plan was last reconciled"
758
+ },
759
+ "snapshotDigest": {
760
+ "type": "string",
761
+ "description": "Overall snapshot digest across all units"
762
+ },
763
+ "digest": {
764
+ "type": "string",
765
+ "minLength": 1
766
+ },
767
+ "waivers": {
768
+ "type": "array",
769
+ "items": {
770
+ "type": "object",
771
+ "required": [
772
+ "rule",
773
+ "reason",
774
+ "responsible",
775
+ "expiresAt"
776
+ ],
777
+ "additionalProperties": false,
778
+ "properties": {
779
+ "rule": {
780
+ "type": "string",
781
+ "minLength": 1
782
+ },
783
+ "reason": {
784
+ "type": "string",
785
+ "minLength": 1
786
+ },
787
+ "responsible": {
788
+ "type": "string",
789
+ "minLength": 1
790
+ },
791
+ "expiresAt": {
792
+ "type": "string",
793
+ "format": "date-time"
794
+ }
795
+ }
796
+ }
797
+ }
798
+ },
799
+ "definitions": {
800
+ "verificationGate": {
801
+ "type": "object",
802
+ "required": [
803
+ "id",
804
+ "phase",
805
+ "scope",
806
+ "command",
807
+ "cwd",
808
+ "timeoutMs",
809
+ "envAllowlist"
810
+ ],
811
+ "additionalProperties": false,
812
+ "properties": {
813
+ "id": {
814
+ "type": "string",
815
+ "pattern": "^[a-z0-9][a-z0-9._-]*$"
816
+ },
817
+ "phase": {
818
+ "type": "string",
819
+ "enum": [
820
+ "snapshot-verify",
821
+ "consumer-verify"
822
+ ]
823
+ },
824
+ "scope": {
825
+ "type": "object",
826
+ "required": [
827
+ "unit"
828
+ ],
829
+ "additionalProperties": false,
830
+ "properties": {
831
+ "unit": {
832
+ "type": "string",
833
+ "pattern": "^(?!\\.{1,2}$)[A-Za-z0-9][A-Za-z0-9._-]*$"
834
+ },
835
+ "distribution": {
836
+ "type": "string",
837
+ "enum": [
838
+ "npm",
839
+ "claude-plugin",
840
+ "codex-plugin",
841
+ "kimi-plugin",
842
+ "codebuddy-plugin"
843
+ ]
844
+ }
845
+ }
846
+ },
847
+ "command": {
848
+ "type": "array",
849
+ "minItems": 1,
850
+ "items": {
851
+ "type": "string"
852
+ }
853
+ },
854
+ "cwd": {
855
+ "type": "string",
856
+ "pattern": "^(?:\\.$|(?!\\/)(?!\\.\\/)(?!.*\\\\)(?!.*:)(?!\\.\\.(?:\\/|$))(?!.*\\/\\.\\.\\/)(?!.*\\/\\.\\.$)(?!.*\\/\\.\\/)(?!.*\\/\\/)(?!.*\\0)(?!.*\\/\\.$)(?!.*\\/\\/$)(?!.*\\/$).*)$"
857
+ },
858
+ "timeoutMs": {
859
+ "type": "integer",
860
+ "minimum": 1000,
861
+ "maximum": 7200000
862
+ },
863
+ "envAllowlist": {
864
+ "type": "array",
865
+ "items": {
866
+ "type": "string",
867
+ "pattern": "^[A-Z_][A-Z0-9_]*$"
868
+ },
869
+ "uniqueItems": true
870
+ },
871
+ "expectedJson": {
872
+ "type": "object"
873
+ }
874
+ },
875
+ "allOf": [
876
+ {
877
+ "if": {
878
+ "properties": {
879
+ "phase": {
880
+ "const": "consumer-verify"
881
+ }
882
+ },
883
+ "required": [
884
+ "phase"
885
+ ]
886
+ },
887
+ "then": {
888
+ "properties": {
889
+ "scope": {
890
+ "required": [
891
+ "unit",
892
+ "distribution"
893
+ ]
894
+ }
895
+ }
896
+ }
897
+ },
898
+ {
899
+ "if": {
900
+ "properties": {
901
+ "phase": {
902
+ "const": "snapshot-verify"
903
+ }
904
+ },
905
+ "required": [
906
+ "phase"
907
+ ]
908
+ },
909
+ "then": {
910
+ "properties": {
911
+ "scope": {
912
+ "not": {
913
+ "required": [
914
+ "distribution"
915
+ ]
916
+ }
917
+ }
918
+ }
919
+ }
920
+ }
921
+ ]
922
+ }
923
+ }
924
+ }