release-skill 0.2.3 → 0.2.5

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 (55) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codebuddy-plugin/plugin.json +1 -1
  4. package/.codex-plugin/plugin.json +2 -2
  5. package/.kimi-plugin/plugin.json +1 -1
  6. package/CHANGELOG.md +46 -0
  7. package/CONTRIBUTING.md +27 -0
  8. package/INSTALL.md +95 -139
  9. package/INSTALL.zh-CN.md +70 -121
  10. package/README.md +266 -913
  11. package/README.zh-CN.md +224 -535
  12. package/adapters/claude/.claude-plugin/marketplace.json +1 -1
  13. package/adapters/claude/.claude-plugin/plugin.json +1 -1
  14. package/adapters/claude/bin/release-skill.bundle.mjs +19805 -17556
  15. package/adapters/claude/schemas/release-plan.schema.json +228 -0
  16. package/adapters/claude/schemas/release-project.schema.json +93 -0
  17. package/adapters/claude/schemas/release-run.schema.json +155 -2
  18. package/adapters/codex/.codex-plugin/plugin.json +2 -2
  19. package/adapters/codex/bin/release-skill.bundle.mjs +19805 -17556
  20. package/adapters/codex/schemas/release-plan.schema.json +228 -0
  21. package/adapters/codex/schemas/release-project.schema.json +93 -0
  22. package/adapters/codex/schemas/release-run.schema.json +155 -2
  23. package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
  24. package/adapters/kimi/bin/release-skill.bundle.mjs +19805 -17556
  25. package/adapters/kimi/schemas/release-plan.schema.json +228 -0
  26. package/adapters/kimi/schemas/release-project.schema.json +93 -0
  27. package/adapters/kimi/schemas/release-run.schema.json +155 -2
  28. package/adapters/workbuddy/.codebuddy-plugin/plugin.json +1 -1
  29. package/adapters/workbuddy/bin/release-skill.bundle.mjs +19805 -17556
  30. package/adapters/workbuddy/schemas/release-plan.schema.json +228 -0
  31. package/adapters/workbuddy/schemas/release-project.schema.json +93 -0
  32. package/adapters/workbuddy/schemas/release-run.schema.json +155 -2
  33. package/bin/release-skill.bundle.mjs +19805 -17556
  34. package/package.json +1 -1
  35. package/schemas/release-plan.schema.json +228 -0
  36. package/schemas/release-project.schema.json +93 -0
  37. package/schemas/release-run.schema.json +155 -2
  38. package/scripts/sync-public-files.mjs +20 -9
  39. package/src/adapters/plugin-marketplace.mjs +1237 -403
  40. package/src/commands/prepare.mjs +454 -40
  41. package/src/commands/publish.mjs +169 -75
  42. package/src/commands/reconcile.mjs +92 -327
  43. package/src/commands/setup.mjs +148 -20
  44. package/src/commands/verify.mjs +454 -20
  45. package/src/core/baseline.mjs +8 -1
  46. package/src/core/checkpoints.mjs +50 -7
  47. package/src/core/config.mjs +15 -0
  48. package/src/core/errors.mjs +2 -0
  49. package/src/core/installation-contract.mjs +341 -0
  50. package/src/core/plan.mjs +158 -6
  51. package/src/core/skill-resource-closure.mjs +425 -0
  52. package/src/platforms/codebuddy.mjs +206 -280
  53. package/src/platforms/codex.mjs +369 -0
  54. package/src/platforms/kimi.mjs +191 -119
  55. package/src/platforms/registry.mjs +24 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
5
5
  "author": {
6
6
  "name": "广州市风荷科技有限公司"
@@ -420,6 +420,95 @@
420
420
  },
421
421
  "smokeExpectedJson": {
422
422
  "type": "object"
423
+ },
424
+ "installationContract": {
425
+ "type": "object",
426
+ "description": "可审计的安装契约规范对象",
427
+ "additionalProperties": false,
428
+ "properties": {
429
+ "algorithmVersion": {
430
+ "type": "integer",
431
+ "minimum": 1
432
+ },
433
+ "distributionType": {
434
+ "type": "string",
435
+ "minLength": 1
436
+ },
437
+ "manifestRelativePath": {
438
+ "type": "string",
439
+ "minLength": 1
440
+ },
441
+ "normalizedManifest": {
442
+ "type": "object"
443
+ },
444
+ "marketplaceSourceType": {
445
+ "type": "string",
446
+ "enum": [
447
+ "bundled-family",
448
+ "standalone-index"
449
+ ]
450
+ },
451
+ "includeMarketplaceEntry": {
452
+ "type": "boolean"
453
+ },
454
+ "marketplaceIndexRelativePath": {
455
+ "type": "string",
456
+ "minLength": 1
457
+ },
458
+ "normalizedSelectedEntry": {
459
+ "type": "object"
460
+ },
461
+ "verificationRecipeVersion": {
462
+ "type": "string",
463
+ "minLength": 1
464
+ }
465
+ },
466
+ "required": [
467
+ "algorithmVersion",
468
+ "distributionType",
469
+ "manifestRelativePath",
470
+ "normalizedManifest",
471
+ "marketplaceSourceType",
472
+ "includeMarketplaceEntry",
473
+ "verificationRecipeVersion"
474
+ ]
475
+ },
476
+ "installationContractDigest": {
477
+ "type": "string",
478
+ "pattern": "^[a-f0-9]{64}$",
479
+ "description": "安装契约摘要,用于在远端状态未变化时跳过重复验证"
480
+ },
481
+ "marketplaceSourceType": {
482
+ "type": "string",
483
+ "enum": [
484
+ "bundled-family",
485
+ "standalone-index"
486
+ ],
487
+ "description": "市场来源类型:bundled-family(技能族自带市场文件)或 standalone-index(独立市场仓库);每个平台每次发布只冻结一种来源"
488
+ },
489
+ "marketplaceCommitSha": {
490
+ "type": "string",
491
+ "pattern": "^[0-9a-f]{40}$",
492
+ "description": "独立市场仓库冻结提交 SHA(standalone-index 专用)"
493
+ },
494
+ "marketplaceRef": {
495
+ "type": "string",
496
+ "minLength": 1,
497
+ "description": "独立市场仓库冻结引用(standalone-index 专用)"
498
+ },
499
+ "marketplaceIndexPath": {
500
+ "type": "string",
501
+ "minLength": 1,
502
+ "description": "独立市场索引相对路径(standalone-index 专用)"
503
+ },
504
+ "marketplaceName": {
505
+ "type": "string",
506
+ "minLength": 1,
507
+ "description": "独立市场名称(standalone-index 专用)"
508
+ },
509
+ "selectedEntry": {
510
+ "type": "object",
511
+ "description": "冻结的唯一选中市场条目(standalone-index 专用)"
423
512
  }
424
513
  },
425
514
  "allOf": [
@@ -493,12 +582,35 @@
493
582
  "properties": {
494
583
  "type": {
495
584
  "enum": [
585
+ "claude-plugin",
586
+ "codex-plugin",
496
587
  "kimi-plugin",
497
588
  "codebuddy-plugin"
498
589
  ]
499
590
  }
500
591
  }
501
592
  },
593
+ "then": {}
594
+ },
595
+ {
596
+ "if": {
597
+ "properties": {
598
+ "type": {
599
+ "enum": [
600
+ "claude-plugin",
601
+ "codex-plugin",
602
+ "kimi-plugin",
603
+ "codebuddy-plugin"
604
+ ]
605
+ },
606
+ "marketplaceSourceType": {
607
+ "const": "bundled-family"
608
+ }
609
+ },
610
+ "required": [
611
+ "marketplaceSourceType"
612
+ ]
613
+ },
502
614
  "then": {
503
615
  "not": {
504
616
  "required": [
@@ -507,6 +619,31 @@
507
619
  }
508
620
  }
509
621
  },
622
+ {
623
+ "if": {
624
+ "properties": {
625
+ "type": {
626
+ "enum": [
627
+ "claude-plugin",
628
+ "codex-plugin",
629
+ "kimi-plugin",
630
+ "codebuddy-plugin"
631
+ ]
632
+ },
633
+ "marketplaceSourceType": {
634
+ "const": "standalone-index"
635
+ }
636
+ },
637
+ "required": [
638
+ "marketplaceSourceType"
639
+ ]
640
+ },
641
+ "then": {
642
+ "required": [
643
+ "marketplaceRepo"
644
+ ]
645
+ }
646
+ },
510
647
  {
511
648
  "if": {
512
649
  "required": [
@@ -678,6 +815,97 @@
678
815
  "minLength": 1,
679
816
  "description": "Digest of the project configuration at plan freeze time"
680
817
  },
818
+ "skillResourceClosure": {
819
+ "type": "object",
820
+ "description": "Skill resource closure gate receipts from prepare phase (per-unit bound)",
821
+ "additionalProperties": false,
822
+ "properties": {
823
+ "unitReceipts": {
824
+ "type": "array",
825
+ "minItems": 1,
826
+ "items": {
827
+ "type": "object",
828
+ "additionalProperties": false,
829
+ "properties": {
830
+ "unitId": {
831
+ "type": "string",
832
+ "minLength": 1
833
+ },
834
+ "checkerVersion": {
835
+ "type": "string",
836
+ "minLength": 1
837
+ },
838
+ "inputDigest": {
839
+ "type": "string",
840
+ "pattern": "^[a-f0-9]{64}$"
841
+ },
842
+ "surfaceCount": {
843
+ "type": "integer",
844
+ "minimum": 0
845
+ },
846
+ "skillCount": {
847
+ "type": "integer",
848
+ "minimum": 0
849
+ },
850
+ "referenceCount": {
851
+ "type": "integer",
852
+ "minimum": 0
853
+ },
854
+ "sourceOnlyCount": {
855
+ "type": "integer",
856
+ "minimum": 0
857
+ },
858
+ "findingCount": {
859
+ "const": 0
860
+ },
861
+ "receiptDigest": {
862
+ "type": "string",
863
+ "pattern": "^[a-f0-9]{64}$"
864
+ }
865
+ },
866
+ "required": [
867
+ "unitId",
868
+ "checkerVersion",
869
+ "inputDigest",
870
+ "surfaceCount",
871
+ "skillCount",
872
+ "referenceCount",
873
+ "sourceOnlyCount",
874
+ "findingCount",
875
+ "receiptDigest"
876
+ ]
877
+ }
878
+ },
879
+ "checkerVersion": {
880
+ "type": "string",
881
+ "minLength": 1
882
+ },
883
+ "totalSkillCount": {
884
+ "type": "integer",
885
+ "minimum": 0
886
+ },
887
+ "totalReferenceCount": {
888
+ "type": "integer",
889
+ "minimum": 0
890
+ },
891
+ "totalSourceOnlyCount": {
892
+ "type": "integer",
893
+ "minimum": 0
894
+ },
895
+ "totalFindingCount": {
896
+ "type": "integer",
897
+ "minimum": 0
898
+ }
899
+ },
900
+ "required": [
901
+ "unitReceipts",
902
+ "checkerVersion",
903
+ "totalSkillCount",
904
+ "totalReferenceCount",
905
+ "totalSourceOnlyCount",
906
+ "totalFindingCount"
907
+ ]
908
+ },
681
909
  "verificationGates": {
682
910
  "type": "array",
683
911
  "items": {
@@ -213,6 +213,20 @@
213
213
  "minimum": 30000,
214
214
  "maximum": 900000,
215
215
  "description": "Timeout in milliseconds for plugin marketplace install commands (claude-plugin, codex-plugin). Kimi Code has no scriptable install command, so for kimi-plugin this bounds the read-only observation/verification only, not an install command. CodeBuddy/WorkBuddy has no scriptable install command that can pin a frozen ref, so for codebuddy-plugin this likewise bounds the read-only observation/verification only. Only valid for claude-plugin, codex-plugin, kimi-plugin, and codebuddy-plugin distributions."
216
+ },
217
+ "marketplaceSourceType": {
218
+ "type": "string",
219
+ "enum": [
220
+ "bundled-family",
221
+ "standalone-index"
222
+ ],
223
+ "description": "市场来源类型:bundled-family(技能族自带市场文件)或 standalone-index(独立市场仓库);每个平台每次发布只冻结一种来源"
224
+ },
225
+ "marketplaceIndexPath": {
226
+ "type": "string",
227
+ "minLength": 1,
228
+ "pattern": "^(?!/)(?!\\.\\/)(?!.*\\\\)(?!.*:)(?!\\.\\.(/|$))(?!\\.$)(?!.*\\/\\.\\.\\/)(?!.*\\/\\.\\.$)(?!.*\\/\\.\\/)(?!.*\\/\\/)(?!.*\\0)(?!.*\\/\\.$)(?!.*\\/$).*$",
229
+ "description": "Bundled marketplace index relative path override;仅插件 distribution 允许"
216
230
  }
217
231
  },
218
232
  "allOf": [
@@ -305,12 +319,39 @@
305
319
  "properties": {
306
320
  "type": {
307
321
  "enum": [
322
+ "claude-plugin",
323
+ "codex-plugin",
308
324
  "kimi-plugin",
309
325
  "codebuddy-plugin"
310
326
  ]
311
327
  }
312
328
  }
313
329
  },
330
+ "then": {
331
+ "required": [
332
+ "marketplaceSourceType"
333
+ ]
334
+ }
335
+ },
336
+ {
337
+ "if": {
338
+ "properties": {
339
+ "type": {
340
+ "enum": [
341
+ "claude-plugin",
342
+ "codex-plugin",
343
+ "kimi-plugin",
344
+ "codebuddy-plugin"
345
+ ]
346
+ },
347
+ "marketplaceSourceType": {
348
+ "const": "bundled-family"
349
+ }
350
+ },
351
+ "required": [
352
+ "marketplaceSourceType"
353
+ ]
354
+ },
314
355
  "then": {
315
356
  "not": {
316
357
  "required": [
@@ -319,6 +360,58 @@
319
360
  }
320
361
  }
321
362
  },
363
+ {
364
+ "if": {
365
+ "properties": {
366
+ "type": {
367
+ "enum": [
368
+ "claude-plugin",
369
+ "codex-plugin",
370
+ "kimi-plugin",
371
+ "codebuddy-plugin"
372
+ ]
373
+ },
374
+ "marketplaceSourceType": {
375
+ "const": "bundled-family"
376
+ }
377
+ },
378
+ "required": [
379
+ "marketplaceSourceType"
380
+ ]
381
+ },
382
+ "then": {
383
+ "not": {
384
+ "required": [
385
+ "marketplaceRepo"
386
+ ]
387
+ }
388
+ }
389
+ },
390
+ {
391
+ "if": {
392
+ "properties": {
393
+ "type": {
394
+ "enum": [
395
+ "claude-plugin",
396
+ "codex-plugin",
397
+ "kimi-plugin",
398
+ "codebuddy-plugin"
399
+ ]
400
+ },
401
+ "marketplaceSourceType": {
402
+ "const": "standalone-index"
403
+ }
404
+ },
405
+ "required": [
406
+ "marketplaceSourceType"
407
+ ]
408
+ },
409
+ "then": {
410
+ "required": [
411
+ "marketplaceRepo"
412
+ ]
413
+ }
414
+ },
322
415
  {
323
416
  "if": {
324
417
  "required": [
@@ -139,9 +139,13 @@
139
139
  "failed",
140
140
  "skipped",
141
141
  "pending",
142
- "uncertain"
142
+ "uncertain",
143
+ "deferred",
144
+ "PASSED_AUTOMATIC",
145
+ "PASSED_MANUAL",
146
+ "NOT_REQUIRED_UNCHANGED"
143
147
  ],
144
- "description": "Result status of this checkpoint (uncertain = started, result unknown)"
148
+ "description": "Result status of this checkpoint (uncertain = started, result unknown; deferred = marketplace action postponed to verify phase; PASSED_AUTOMATIC/PASSED_MANUAL/NOT_REQUIRED_UNCHANGED 为验证阶段专用状态)"
145
149
  },
146
150
  "preObserve": {
147
151
  "type": "string",
@@ -211,6 +215,70 @@
211
215
  "type": "string"
212
216
  }
213
217
  }
218
+ },
219
+ "reason": {
220
+ "type": "string",
221
+ "description": "Stable reason code for deferred checkpoints (e.g. CONSUMER_VERIFICATION_DEFERRED)"
222
+ },
223
+ "phase": {
224
+ "type": "string",
225
+ "description": "Phase identifier for deferred checkpoints (e.g. post-publish-verification)"
226
+ }
227
+ }
228
+ }
229
+ },
230
+ "consumerVerificationReceipts": {
231
+ "type": "array",
232
+ "description": "消费端验证收据,每个 marketplace action 一条记录",
233
+ "items": {
234
+ "type": "object",
235
+ "required": [
236
+ "actionId",
237
+ "unitId",
238
+ "platform",
239
+ "result",
240
+ "installationContractDigest",
241
+ "algorithmVersion",
242
+ "planDigest",
243
+ "verifiedAt"
244
+ ],
245
+ "additionalProperties": false,
246
+ "properties": {
247
+ "actionId": {
248
+ "type": "string",
249
+ "minLength": 1
250
+ },
251
+ "unitId": {
252
+ "type": "string",
253
+ "minLength": 1
254
+ },
255
+ "platform": {
256
+ "type": "string",
257
+ "minLength": 1
258
+ },
259
+ "result": {
260
+ "type": "string",
261
+ "enum": [
262
+ "PASSED_AUTOMATIC",
263
+ "PASSED_MANUAL",
264
+ "NOT_REQUIRED_UNCHANGED"
265
+ ]
266
+ },
267
+ "installationContractDigest": {
268
+ "type": "string",
269
+ "pattern": "^[a-f0-9]{64}$"
270
+ },
271
+ "algorithmVersion": {
272
+ "type": "integer",
273
+ "minimum": 1
274
+ },
275
+ "planDigest": {
276
+ "type": "string",
277
+ "minLength": 1
278
+ },
279
+ "verifiedAt": {
280
+ "type": "string",
281
+ "format": "date-time"
214
282
  }
215
283
  }
216
284
  }
@@ -298,6 +366,91 @@
298
366
  }
299
367
  }
300
368
  }
369
+ },
370
+ "skillResourceClosureReceipts": {
371
+ "type": "array",
372
+ "description": "Per-surface skill resource closure verification receipts from verify phase",
373
+ "items": {
374
+ "type": "object",
375
+ "required": [
376
+ "host",
377
+ "distribution",
378
+ "unitId",
379
+ "checkerVersion",
380
+ "inputDigest",
381
+ "surfaceCount",
382
+ "skillCount",
383
+ "referenceCount",
384
+ "sourceOnlyCount",
385
+ "findingCount",
386
+ "receiptDigest",
387
+ "checkedAt",
388
+ "exitCode"
389
+ ],
390
+ "additionalProperties": false,
391
+ "properties": {
392
+ "host": {
393
+ "type": "string",
394
+ "minLength": 1
395
+ },
396
+ "unitId": {
397
+ "type": "string",
398
+ "minLength": 1
399
+ },
400
+ "distribution": {
401
+ "type": "string",
402
+ "enum": [
403
+ "npm",
404
+ "claude-plugin",
405
+ "codex-plugin",
406
+ "kimi-plugin",
407
+ "codebuddy-plugin"
408
+ ]
409
+ },
410
+ "actionId": {
411
+ "type": "string",
412
+ "minLength": 1
413
+ },
414
+ "checkerVersion": {
415
+ "type": "string",
416
+ "minLength": 1
417
+ },
418
+ "inputDigest": {
419
+ "type": "string",
420
+ "pattern": "^[a-f0-9]{64}$"
421
+ },
422
+ "surfaceCount": {
423
+ "type": "integer",
424
+ "minimum": 0
425
+ },
426
+ "skillCount": {
427
+ "type": "integer",
428
+ "minimum": 0
429
+ },
430
+ "referenceCount": {
431
+ "type": "integer",
432
+ "minimum": 0
433
+ },
434
+ "sourceOnlyCount": {
435
+ "type": "integer",
436
+ "minimum": 0
437
+ },
438
+ "findingCount": {
439
+ "const": 0
440
+ },
441
+ "receiptDigest": {
442
+ "type": "string",
443
+ "pattern": "^[a-f0-9]{64}$"
444
+ },
445
+ "checkedAt": {
446
+ "type": "string",
447
+ "format": "date-time"
448
+ },
449
+ "exitCode": {
450
+ "const": 0
451
+ }
452
+ }
453
+ }
301
454
  }
302
455
  },
303
456
  "allOf": [
@@ -208,9 +208,9 @@ function buildRequiredPublicFilesYaml(entries, indent = 6) {
208
208
  // Entry collection
209
209
  // ---------------------------------------------------------------------------
210
210
 
211
- async function collectEntries() {
211
+ async function collectEntries(packageRoot) {
212
212
  // 1. Scan all files in the package directory
213
- const allFiles = await scanFiles(PKG_ROOT);
213
+ const allFiles = await scanFiles(packageRoot);
214
214
  const allSet = new Set(allFiles);
215
215
 
216
216
  // 2. Build the adapter exclusion set (all files under adapters/)
@@ -303,8 +303,8 @@ async function collectEntries() {
303
303
  // Check / write
304
304
  // ---------------------------------------------------------------------------
305
305
 
306
- async function readProjectYaml() {
307
- return await readFile(PROJECT_YAML, 'utf8');
306
+ async function readProjectYaml(projectPath) {
307
+ return await readFile(projectPath, 'utf8');
308
308
  }
309
309
 
310
310
  function extractExistingEntries(yamlText, key) {
@@ -369,18 +369,29 @@ function replaceArrayInYaml(yamlText, key, newContent) {
369
369
  *
370
370
  * @param {object} options
371
371
  * @param {string} options.packageDir - Package directory.
372
+ * @param {string} [options.projectPath] - Project config path. Defaults to the
373
+ * real workspace config; tests may provide an isolated copy.
372
374
  * @param {boolean} [options.check] - Read-only drift detection.
373
375
  * @returns {Promise<{mode: string, clean?: boolean, diff?: object}>}
374
376
  */
375
- export async function syncPublicFiles({ packageDir, check = false } = {}) {
377
+ export async function syncPublicFiles({
378
+ packageDir,
379
+ projectPath = PROJECT_YAML,
380
+ check = false,
381
+ } = {}) {
376
382
  if (typeof packageDir !== 'string' || packageDir.length === 0) {
377
383
  const err = new Error('sync-public-files: packageDir is required');
378
384
  err.code = 'SYNC_PUBLIC_FILES_INVALID_ARGUMENT';
379
385
  throw err;
380
386
  }
387
+ if (typeof projectPath !== 'string' || projectPath.length === 0) {
388
+ const err = new Error('sync-public-files: projectPath must be a non-empty string');
389
+ err.code = 'SYNC_PUBLIC_FILES_INVALID_ARGUMENT';
390
+ throw err;
391
+ }
381
392
 
382
- const entries = await collectEntries();
383
- const yamlText = await readProjectYaml();
393
+ const entries = await collectEntries(packageDir);
394
+ const yamlText = await readProjectYaml(projectPath);
384
395
 
385
396
  const existingPublic = extractExistingEntries(yamlText, 'publicFiles');
386
397
  const existingRequired = extractExistingEntries(yamlText, 'requiredPublicFiles');
@@ -422,10 +433,10 @@ export async function syncPublicFiles({ packageDir, check = false } = {}) {
422
433
  let newYaml = replaceArrayInYaml(yamlText, 'publicFiles', publicYaml);
423
434
  newYaml = replaceArrayInYaml(newYaml, 'requiredPublicFiles', requiredYaml);
424
435
 
425
- await writeFile(PROJECT_YAML, newYaml, 'utf8');
436
+ await writeFile(projectPath, newYaml, 'utf8');
426
437
 
427
438
  // Verify write
428
- const reread = await readFile(PROJECT_YAML, 'utf8');
439
+ const reread = await readFile(projectPath, 'utf8');
429
440
  if (reread !== newYaml) {
430
441
  const err = new Error('sync-public-files: post-write verification failed');
431
442
  err.code = 'SYNC_PUBLIC_FILES_WRITE_VERIFY_FAILED';