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
@@ -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
  }
@@ -2,10 +2,12 @@
2
2
  * Pure producer: build adapters from skills and plugin templates.
3
3
  *
4
4
  * Reads skill metadata from skills-src/ and plugin.json templates,
5
- * generates self-contained adapter directories for each platform (claude, codex, kimi).
5
+ * generates self-contained adapter directories for each platform
6
+ * (claude, codex, kimi, and the build-only workbuddy adapter).
6
7
  *
7
8
  * Each adapter root contains:
8
- * - Plugin manifest (.claude-plugin/, .codex-plugin/, or .kimi-plugin/)
9
+ * - Plugin manifest (.claude-plugin/, .codex-plugin/, .kimi-plugin/, or
10
+ * .codebuddy-plugin/)
9
11
  * - Skills with host-specific root resolution
10
12
  * - bin/release-skill.mjs (wrapper) + bin/release-skill.bundle.mjs (self-contained bundle)
11
13
  * - schemas/ (JSON Schema files)
@@ -195,8 +197,15 @@ export function computeBuildAdaptersDigest(sourceBytes) {
195
197
  // of platform knowledge). The build shape mirrors the legacy inline table
196
198
  // byte-for-byte: marketplaceFileName is present only when the platform
197
199
  // co-locates a marketplace manifest in its plugin dir (claude).
198
- export const PLATFORMS = PLATFORM_REGISTRY.map((platform) => ({
199
- name: platform.id,
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).
207
+ const REGISTRY_PLATFORMS = PLATFORM_REGISTRY.map((platform) => ({
208
+ name: platform.buildAdapter?.name ?? platform.id,
200
209
  pluginDirName: platform.buildAdapter.pluginDirName,
201
210
  templateFileName: platform.buildAdapter.templateFileName,
202
211
  ...(platform.buildAdapter.hasMarketplace
@@ -205,6 +214,28 @@ export const PLATFORMS = PLATFORM_REGISTRY.map((platform) => ({
205
214
  hasMarketplace: platform.buildAdapter.hasMarketplace,
206
215
  }));
207
216
 
217
+ /**
218
+ * Build-only distribution adapters: generated, self-contained plugin trees
219
+ * that are NOT wired into the automated publish/reconcile/verify pipeline —
220
+ * no registry PLATFORMS membership, no distributionType/actionType in the
221
+ * plan schemas, no automated install checkpoint. A host joins the pipeline
222
+ * only with a full registry descriptor (strategy, CLI protocol, schema enum);
223
+ * until then a build-only entry lets the build emit an installable adapter
224
+ * tree without fabricating an unverified install protocol.
225
+ *
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.
234
+ */
235
+ export const BUILD_ONLY_ADAPTERS = Object.freeze([]);
236
+
237
+ export const PLATFORMS = Object.freeze([...REGISTRY_PLATFORMS, ...BUILD_ONLY_ADAPTERS]);
238
+
208
239
  const REQUIRED_SCHEMA_FILES = Object.freeze([
209
240
  'approval-record.schema.json',
210
241
  'artifact-policy.schema.json',
@@ -316,14 +347,22 @@ const KIMI_PREAMBLE = `\
316
347
  * - Codex: replaces the Claude-only path with $RELEASE_SKILL_ENTRY,
317
348
  * and prepends the path resolution protocol preamble.
318
349
  * - Kimi: same substitution as Codex, with the Kimi Code preamble.
350
+ * - WorkBuddy: pure variable substitution (${CLAUDE_PLUGIN_ROOT} ->
351
+ * ${CODEBUDDY_PLUGIN_ROOT}); CodeBuddy expands the variable inline in
352
+ * skill content (official plugin reference), the same mechanism Claude
353
+ * uses, so no entry-resolution preamble is needed.
319
354
  *
320
355
  * @param {string} content - Canonical SKILL.md content.
321
- * @param {string} platformName - 'claude', 'codex', or 'kimi'.
356
+ * @param {string} platformName - 'claude', 'codex', 'kimi', or 'workbuddy'.
322
357
  * @returns {string}
323
358
  */
324
359
  function renderSkillForPlatform(content, platformName) {
325
360
  if (platformName === 'claude') return content;
326
361
 
362
+ if (platformName === 'workbuddy') {
363
+ return content.replaceAll('${CLAUDE_PLUGIN_ROOT}', '${CODEBUDDY_PLUGIN_ROOT}');
364
+ }
365
+
327
366
  if (platformName === 'codex' || platformName === 'kimi') {
328
367
  const hostLabel = platformName === 'codex' ? 'Codex' : 'Kimi';
329
368
  const preamble = platformName === 'codex' ? CODEX_PREAMBLE : KIMI_PREAMBLE;
@@ -393,8 +432,11 @@ async function generateAdapterFiles(platform, skills, templateJson, root, market
393
432
  const adapted = JSON.parse(JSON.stringify(templateJson));
394
433
 
395
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.
396
438
  if (typeof adapted.skills === 'string') {
397
- adapted.skills = './skills/';
439
+ adapted.skills = platform.name === 'workbuddy' ? ['./skills/'] : './skills/';
398
440
  } else if (Array.isArray(adapted.skills)) {
399
441
  for (const skill of adapted.skills) {
400
442
  skill.source = `../skills/${skill.name}/SKILL.md`;