release-skill 0.2.1 → 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 (54) 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 +21 -0
  7. package/INSTALL.md +183 -21
  8. package/INSTALL.zh-CN.md +160 -16
  9. package/README.md +112 -11
  10. package/README.zh-CN.md +73 -10
  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 +4 -2
  28. package/adapters/workbuddy/bin/release-skill.bundle.mjs +1718 -600
  29. package/adapters/workbuddy/schemas/release-plan.schema.json +44 -2
  30. package/adapters/workbuddy/schemas/release-project.schema.json +46 -4
  31. package/adapters/workbuddy/schemas/release-run.schema.json +1 -0
  32. package/bin/release-skill-cli.mjs +46 -4
  33. package/bin/release-skill.bundle.mjs +1718 -600
  34. package/package.json +1 -1
  35. package/references/02-project-config.md +7 -0
  36. package/references/06-adapter-contract.md +21 -2
  37. package/schemas/release-plan.schema.json +44 -2
  38. package/schemas/release-project.schema.json +46 -4
  39. package/schemas/release-run.schema.json +1 -0
  40. package/scripts/sync-public-files.mjs +8 -4
  41. package/src/adapters/contract.mjs +1 -0
  42. package/src/adapters/plugin-marketplace.mjs +536 -23
  43. package/src/commands/assess.mjs +50 -1
  44. package/src/commands/prepare.mjs +273 -9
  45. package/src/commands/publish.mjs +1 -0
  46. package/src/commands/reconcile.mjs +1 -0
  47. package/src/commands/setup.mjs +7 -3
  48. package/src/commands/verify.mjs +2 -0
  49. package/src/core/checkpoints.mjs +7 -2
  50. package/src/core/plan.mjs +97 -4
  51. package/src/core/verification-gates.mjs +1 -1
  52. package/src/platforms/codebuddy.mjs +618 -0
  53. package/src/platforms/registry.mjs +100 -5
  54. package/src/producers/build-adapters.mjs +21 -13
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Platform registry — the single source of truth for consumer-platform
3
- * knowledge (claude / codex / kimi).
3
+ * knowledge (claude / codex / kimi / codebuddy).
4
4
  *
5
5
  * T2.2 converges platform facts that were scattered across plugin-marketplace.mjs,
6
6
  * build-adapters.mjs, prepare.mjs, plan.mjs and project.yaml into this module.
@@ -23,6 +23,8 @@
23
23
  * file; kimi's side-effecting manual-requirement and manifest-reading
24
24
  * strategies live in ./kimi.mjs (§4.2's per-platform-module option — the only
25
25
  * non-trivial strategies) and are referenced from the kimi descriptor below.
26
+ * codebuddy's analogous human-attestation strategies live in ./codebuddy.mjs
27
+ * and are referenced from the codebuddy descriptor below.
26
28
  * plugin-marketplace.mjs consumes every platform difference through this
27
29
  * registry; see the t2-2 deviation record for the step-2 wiring details.
28
30
  *
@@ -36,6 +38,10 @@ import {
36
38
  readKimiManifest,
37
39
  KIMI_MANIFEST_CANDIDATES,
38
40
  } from './kimi.mjs';
41
+ import {
42
+ executeCodeBuddyManualRequirement,
43
+ readCodeBuddyManifest,
44
+ } from './codebuddy.mjs';
39
45
 
40
46
  // --- claude strategy -------------------------------------------------------
41
47
 
@@ -155,6 +161,10 @@ const CLAUDE = Object.freeze({
155
161
  // Claude carries the authoritative version in the marketplace entry: the
156
162
  // preflight binds entry.version to the action version.
157
163
  marketplaceEntryCarriesVersion: true,
164
+ // External marketplace form: `claude plugin marketplace add repo@<ref>` can
165
+ // only pin a branch/tag NAME (a bare commit sha fails to clone and the
166
+ // resolved sha is not recorded locally) — name-form weak freeze.
167
+ marketplaceRefForm: 'name',
158
168
  knownHostArtifacts: Object.freeze(['.in_use']),
159
169
  schemaRequiredFields: Object.freeze(['plugin', 'marketplace', 'entrySkill']),
160
170
  skillRendering: Object.freeze({ mode: 'verbatim', preamble: null, placeholder: '${CLAUDE_PLUGIN_ROOT}' }),
@@ -204,6 +214,9 @@ const CODEX = Object.freeze({
204
214
  // Codex keeps the authoritative version in .codex-plugin/plugin.json; the
205
215
  // marketplace entry version is not bound to the action version.
206
216
  marketplaceEntryCarriesVersion: false,
217
+ // External marketplace form: `codex plugin marketplace add repo --ref <ref>`
218
+ // accepts a bare commit sha — sha-form strong freeze.
219
+ marketplaceRefForm: 'sha',
207
220
  knownHostArtifacts: Object.freeze(['.git', '.codex-plugin/migrated-command-skills']),
208
221
  schemaRequiredFields: Object.freeze(['plugin', 'marketplace', 'entrySkill']),
209
222
  skillRendering: Object.freeze({ mode: 'substitute', preamble: 'codex', placeholder: '${CLAUDE_PLUGIN_ROOT}' }),
@@ -251,6 +264,9 @@ const KIMI = Object.freeze({
251
264
  // apply (null = N/A, never consulted: kimi preflight reads its manifest via
252
265
  // strategy.readManifest).
253
266
  marketplaceEntryCarriesVersion: null,
267
+ // kimi has no marketplace add at all, so the marketplace ref form does not
268
+ // apply (null = N/A, never consulted).
269
+ marketplaceRefForm: null,
254
270
  knownHostArtifacts: Object.freeze(['.git']),
255
271
  schemaRequiredFields: Object.freeze(['plugin', 'entrySkill']),
256
272
  skillRendering: Object.freeze({ mode: 'substitute', preamble: 'kimi', placeholder: '${CLAUDE_PLUGIN_ROOT}' }),
@@ -272,12 +288,88 @@ const KIMI = Object.freeze({
272
288
  }),
273
289
  });
274
290
 
275
- /** Ordered platform registry. Order is significant (claude, codex, kimi). */
276
- export const PLATFORMS = Object.freeze([CLAUDE, CODEX, KIMI]);
291
+ // CodeBuddy (desktop product WorkBuddy) is a NON-automatable human-attestation
292
+ // platform like kimi: the codebuddy CLI's marketplace add/install cannot pin a
293
+ // frozen ref (no ref option; the install tracks the default branch / latest),
294
+ // so an automated install checkpoint cannot guarantee frozen-artifact identity.
295
+ // Install state has a stable on-disk layout, so the closed loop is proven by a
296
+ // human attestation + read-only verification (./codebuddy.mjs), fail-closed at
297
+ // the same severity as kimi.
298
+ //
299
+ // NAMING MAPPING: the platform id is `codebuddy`, but its BUILD adapter keeps
300
+ // the historical directory name `workbuddy` (`adapters/workbuddy/`, manifest
301
+ // `.codebuddy-plugin/plugin.json`). `buildAdapter.name = 'workbuddy'` drives
302
+ // the build-adapters producer + public-file collection; the pipeline identity
303
+ // (distributionType/actionType/consumer) stays `codebuddy`.
304
+ const CODEBUDDY = Object.freeze({
305
+ id: 'codebuddy',
306
+ distributionType: 'codebuddy-plugin',
307
+ actionType: 'codebuddy-marketplace-install',
308
+ adapter: 'plugin-marketplace',
309
+ automatable: false,
310
+ cli: null,
311
+ jsonProtocol: Object.freeze({
312
+ listOutput: null,
313
+ installPathSource: null,
314
+ marketplaceAddOutput: null,
315
+ pluginInstallOutput: null,
316
+ }),
317
+ // The closed loop never execs the codebuddy CLI; HOME is the only isolation
318
+ // input and exists solely so the attestation's isolated cli-channel home has
319
+ // a base. No unverified host env vars are fabricated.
320
+ isolationEnv: (home) => ({ HOME: home }),
321
+ // codebuddy never execs a CLI; its isolated cli home is created by the
322
+ // manual-requirement strategy under the attestation authority.
323
+ isolationSubdirs: Object.freeze([]),
324
+ manifestPaths: Object.freeze({
325
+ // Single authoritative manifest (no precedence chain, unlike kimi).
326
+ plugin: '.codebuddy-plugin/plugin.json',
327
+ marketplace: null,
328
+ }),
329
+ marketplaceSourceForm: null,
330
+ // codebuddy installs from a unified marketplace but carries no marketplace
331
+ // identity in the action (the marketplace is a fixed constant in
332
+ // ./codebuddy.mjs); the entry-version binding does not apply (null = N/A).
333
+ marketplaceEntryCarriesVersion: null,
334
+ // codebuddy has no marketplace add that can pin a frozen ref (attestation
335
+ // loop instead), so the marketplace ref form does not apply (null = N/A).
336
+ marketplaceRefForm: null,
337
+ knownHostArtifacts: Object.freeze(['.git']),
338
+ schemaRequiredFields: Object.freeze(['plugin', 'entrySkill']),
339
+ // Declarative rendering intent (the build-adapters producer keys on
340
+ // buildAdapter.name = 'workbuddy'): pure ${CLAUDE_PLUGIN_ROOT} ->
341
+ // ${CODEBUDDY_PLUGIN_ROOT} substitution, no entry-resolution preamble
342
+ // (CodeBuddy expands the variable inline in skill content).
343
+ skillRendering: Object.freeze({ mode: 'substitute', preamble: null, placeholder: '${CODEBUDDY_PLUGIN_ROOT}' }),
344
+ buildAdapter: Object.freeze({
345
+ // Build adapter keeps the historical `workbuddy` directory name; the fields
346
+ // are byte-for-byte the legacy BUILD_ONLY workbuddy entry so the generated
347
+ // adapters/workbuddy/ tree is unchanged.
348
+ name: 'workbuddy',
349
+ pluginDirName: '.codebuddy-plugin',
350
+ templateFileName: 'plugin.json',
351
+ marketplaceFileName: null,
352
+ hasMarketplace: false,
353
+ }),
354
+ strategy: Object.freeze({
355
+ parseListOutput: null,
356
+ extractInstallPath: null,
357
+ extractListIdentity: null,
358
+ crossValidateListEntry: null,
359
+ // codebuddy's side-effecting manual-requirement builder and manifest reader
360
+ // live in ./codebuddy.mjs (per-platform-module option, mirroring kimi).
361
+ buildManualRequirement: executeCodeBuddyManualRequirement,
362
+ readManifest: readCodeBuddyManifest,
363
+ }),
364
+ });
277
365
 
278
- const VALID_DISTRIBUTION_TYPES = new Set(['claude-plugin', 'codex-plugin', 'kimi-plugin']);
279
- const VALID_ACTION_TYPES = new Set(['claude-marketplace-install', 'codex-marketplace-install', 'kimi-marketplace-install']);
366
+ /** Ordered platform registry. Order is significant (claude, codex, kimi, codebuddy). */
367
+ export const PLATFORMS = Object.freeze([CLAUDE, CODEX, KIMI, CODEBUDDY]);
368
+
369
+ const VALID_DISTRIBUTION_TYPES = new Set(['claude-plugin', 'codex-plugin', 'kimi-plugin', 'codebuddy-plugin']);
370
+ const VALID_ACTION_TYPES = new Set(['claude-marketplace-install', 'codex-marketplace-install', 'kimi-marketplace-install', 'codebuddy-marketplace-install']);
280
371
  const VALID_SOURCE_FORMS = new Set(['string', 'local-path-object', null]);
372
+ const VALID_MARKETPLACE_REF_FORMS = new Set(['sha', 'name', null]);
281
373
  const VALID_LIST_OUTPUTS = new Set(['array', 'installed-object', null]);
282
374
  const VALID_CLI_OUTPUTS = new Set(['json', null]);
283
375
  const VALID_ENTRY_VERSION_BINDING = new Set([true, false, null]);
@@ -333,6 +425,9 @@ export function assertRegistry(registry = PLATFORMS) {
333
425
  if (!VALID_SOURCE_FORMS.has(platform.marketplaceSourceForm)) {
334
426
  throw new Error(`platform registry: ${label} has illegal marketplaceSourceForm "${platform.marketplaceSourceForm}"`);
335
427
  }
428
+ if (!VALID_MARKETPLACE_REF_FORMS.has(platform.marketplaceRefForm)) {
429
+ throw new Error(`platform registry: ${label} has illegal marketplaceRefForm "${platform.marketplaceRefForm}"`);
430
+ }
336
431
  if (!Array.isArray(platform.knownHostArtifacts)) {
337
432
  throw new Error(`platform registry: ${label} knownHostArtifacts must be an array`);
338
433
  }
@@ -197,8 +197,15 @@ export function computeBuildAdaptersDigest(sourceBytes) {
197
197
  // of platform knowledge). The build shape mirrors the legacy inline table
198
198
  // byte-for-byte: marketplaceFileName is present only when the platform
199
199
  // co-locates a marketplace manifest in its plugin dir (claude).
200
+ //
201
+ // The build adapter NAME defaults to the platform id, but a platform may keep a
202
+ // historical directory name distinct from its pipeline id via
203
+ // `buildAdapter.name`: codebuddy (pipeline id) builds the `workbuddy` adapter
204
+ // tree (adapters/workbuddy/, manifest .codebuddy-plugin/plugin.json). This is
205
+ // what lets codebuddy join the publish pipeline WITHOUT changing a single byte
206
+ // of the generated workbuddy adapter (the former BUILD_ONLY workbuddy entry).
200
207
  const REGISTRY_PLATFORMS = PLATFORM_REGISTRY.map((platform) => ({
201
- name: platform.id,
208
+ name: platform.buildAdapter?.name ?? platform.id,
202
209
  pluginDirName: platform.buildAdapter.pluginDirName,
203
210
  templateFileName: platform.buildAdapter.templateFileName,
204
211
  ...(platform.buildAdapter.hasMarketplace
@@ -216,18 +223,16 @@ const REGISTRY_PLATFORMS = PLATFORM_REGISTRY.map((platform) => ({
216
223
  * until then a build-only entry lets the build emit an installable adapter
217
224
  * tree without fabricating an unverified install protocol.
218
225
  *
219
- * workbuddy: CodeBuddy/WorkBuddy plugin (official plugin reference:
220
- * `.codebuddy-plugin/plugin.json`, components at the plugin root,
221
- * `${CODEBUDDY_PLUGIN_ROOT}` expanded inline in skill content).
226
+ * Currently EMPTY: every platform the build emits now has a full registry
227
+ * descriptor. workbuddy (the CodeBuddy/WorkBuddy plugin, manifest
228
+ * `.codebuddy-plugin/plugin.json`, `${CODEBUDDY_PLUGIN_ROOT}` expanded inline
229
+ * in skill content) moved into the registry as the `codebuddy` platform with
230
+ * `buildAdapter.name = 'workbuddy'`, so its adapter tree is still produced —
231
+ * byte-for-byte unchanged — via REGISTRY_PLATFORMS. This constant is retained
232
+ * (still exported and consumed below) for future build-only hosts that have an
233
+ * installable adapter tree but no verified install protocol yet.
222
234
  */
223
- export const BUILD_ONLY_ADAPTERS = Object.freeze([
224
- Object.freeze({
225
- name: 'workbuddy',
226
- pluginDirName: '.codebuddy-plugin',
227
- templateFileName: 'plugin.json',
228
- hasMarketplace: false,
229
- }),
230
- ]);
235
+ export const BUILD_ONLY_ADAPTERS = Object.freeze([]);
231
236
 
232
237
  export const PLATFORMS = Object.freeze([...REGISTRY_PLATFORMS, ...BUILD_ONLY_ADAPTERS]);
233
238
 
@@ -427,8 +432,11 @@ async function generateAdapterFiles(platform, skills, templateJson, root, market
427
432
  const adapted = JSON.parse(JSON.stringify(templateJson));
428
433
 
429
434
  // Preserve platform-supported directory auto-discovery in generated adapters.
435
+ // The CodeBuddy server-side validator (`codebuddy plugin validate`) requires
436
+ // `skills` to be an array of component paths, so the workbuddy adapter emits
437
+ // ["./skills/"]; claude/codex/kimi hosts keep the directory-string form.
430
438
  if (typeof adapted.skills === 'string') {
431
- adapted.skills = './skills/';
439
+ adapted.skills = platform.name === 'workbuddy' ? ['./skills/'] : './skills/';
432
440
  } else if (Array.isArray(adapted.skills)) {
433
441
  for (const skill of adapted.skills) {
434
442
  skill.source = `../skills/${skill.name}/SKILL.md`;