release-skill 0.1.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 (125) hide show
  1. package/.agents/plugins/marketplace.json +23 -0
  2. package/.claude-plugin/marketplace.json +16 -0
  3. package/.claude-plugin/plugin.json +10 -0
  4. package/.codex-plugin/plugin.json +26 -0
  5. package/CHANGELOG.md +68 -0
  6. package/CODE_OF_CONDUCT.md +76 -0
  7. package/CONTRIBUTING.md +49 -0
  8. package/INSTALL.md +182 -0
  9. package/LICENSE +21 -0
  10. package/NOTICE +25 -0
  11. package/README.md +501 -0
  12. package/README.zh-CN.md +463 -0
  13. package/SECURITY.md +48 -0
  14. package/adapters/claude/.claude-plugin/marketplace.json +16 -0
  15. package/adapters/claude/.claude-plugin/plugin.json +10 -0
  16. package/adapters/claude/skills/release-assess/SKILL.md +52 -0
  17. package/adapters/claude/skills/release-help/SKILL.md +60 -0
  18. package/adapters/claude/skills/release-prepare/SKILL.md +71 -0
  19. package/adapters/claude/skills/release-publish/SKILL.md +55 -0
  20. package/adapters/claude/skills/release-reconcile/SKILL.md +73 -0
  21. package/adapters/claude/skills/release-verify/SKILL.md +70 -0
  22. package/adapters/codex/.codex-plugin/plugin.json +26 -0
  23. package/adapters/codex/skills/release-assess/SKILL.md +52 -0
  24. package/adapters/codex/skills/release-help/SKILL.md +60 -0
  25. package/adapters/codex/skills/release-prepare/SKILL.md +71 -0
  26. package/adapters/codex/skills/release-publish/SKILL.md +55 -0
  27. package/adapters/codex/skills/release-reconcile/SKILL.md +73 -0
  28. package/adapters/codex/skills/release-verify/SKILL.md +70 -0
  29. package/bin/release-skill.mjs +743 -0
  30. package/native/safe-write/binding.gyp +40 -0
  31. package/native/safe-write/prebuilds.json +4 -0
  32. package/native/safe-write/src/safe_write.cc +2023 -0
  33. package/package.json +75 -0
  34. package/references/.render-manifest.json +33 -0
  35. package/references/00-target-state.md +124 -0
  36. package/references/01-state-machine.md +155 -0
  37. package/references/02-project-config.md +217 -0
  38. package/references/03-readme-quality.md +136 -0
  39. package/references/04-supply-chain.md +147 -0
  40. package/references/05-evidence-and-errors.md +164 -0
  41. package/references/06-adapter-contract.md +178 -0
  42. package/schemas/.render-manifest.json +37 -0
  43. package/schemas/approval-record.schema.json +115 -0
  44. package/schemas/artifact-lock.schema.json +111 -0
  45. package/schemas/artifact-plan.schema.json +52 -0
  46. package/schemas/artifact-policy.schema.json +76 -0
  47. package/schemas/evidence-event.schema.json +89 -0
  48. package/schemas/release-plan.schema.json +369 -0
  49. package/schemas/release-project.schema.json +359 -0
  50. package/schemas/release-run.schema.json +195 -0
  51. package/skills/release-assess/SKILL.md +52 -0
  52. package/skills/release-help/SKILL.md +60 -0
  53. package/skills/release-prepare/SKILL.md +71 -0
  54. package/skills/release-publish/SKILL.md +55 -0
  55. package/skills/release-reconcile/SKILL.md +73 -0
  56. package/skills/release-verify/SKILL.md +70 -0
  57. package/skills-src/release-assess/SKILL.md +52 -0
  58. package/skills-src/release-help/SKILL.md +60 -0
  59. package/skills-src/release-prepare/SKILL.md +71 -0
  60. package/skills-src/release-publish/SKILL.md +55 -0
  61. package/skills-src/release-reconcile/SKILL.md +73 -0
  62. package/skills-src/release-verify/SKILL.md +70 -0
  63. package/src/adapters/contract.mjs +214 -0
  64. package/src/adapters/git-github.mjs +214 -0
  65. package/src/adapters/npm.mjs +947 -0
  66. package/src/adapters/plugin-marketplace.mjs +1365 -0
  67. package/src/adapters/push-snapshot.mjs +216 -0
  68. package/src/artifacts/adoption.mjs +743 -0
  69. package/src/artifacts/artifact-plan.mjs +162 -0
  70. package/src/artifacts/entry.mjs +240 -0
  71. package/src/artifacts/git-authority.mjs +637 -0
  72. package/src/artifacts/graph.mjs +189 -0
  73. package/src/artifacts/inspect.mjs +520 -0
  74. package/src/artifacts/inventory.mjs +192 -0
  75. package/src/artifacts/merge/binary.mjs +77 -0
  76. package/src/artifacts/merge/entry-merge.mjs +228 -0
  77. package/src/artifacts/merge/json.mjs +641 -0
  78. package/src/artifacts/merge/markdown.mjs +246 -0
  79. package/src/artifacts/merge/regions.mjs +156 -0
  80. package/src/artifacts/merge/text.mjs +432 -0
  81. package/src/artifacts/merge/tree.mjs +202 -0
  82. package/src/artifacts/merge/yaml.mjs +669 -0
  83. package/src/artifacts/path-key.mjs +94 -0
  84. package/src/artifacts/policy.mjs +319 -0
  85. package/src/artifacts/producer-registry.mjs +439 -0
  86. package/src/artifacts/project-lock.mjs +732 -0
  87. package/src/artifacts/resolution.mjs +658 -0
  88. package/src/artifacts/safe-fs-backend-internal.mjs +680 -0
  89. package/src/artifacts/safe-fs.mjs +72 -0
  90. package/src/artifacts/state.mjs +495 -0
  91. package/src/artifacts/transaction-journal.mjs +983 -0
  92. package/src/artifacts/transaction.mjs +1361 -0
  93. package/src/commands/approve.mjs +280 -0
  94. package/src/commands/artifacts.mjs +627 -0
  95. package/src/commands/assess.mjs +838 -0
  96. package/src/commands/prepare.mjs +1377 -0
  97. package/src/commands/publish.mjs +883 -0
  98. package/src/commands/reconcile.mjs +1255 -0
  99. package/src/commands/verify.mjs +915 -0
  100. package/src/core/approval.mjs +332 -0
  101. package/src/core/baseline.mjs +272 -0
  102. package/src/core/blackbox-hard-gates.mjs +142 -0
  103. package/src/core/config.mjs +448 -0
  104. package/src/core/digest.mjs +90 -0
  105. package/src/core/errors.mjs +113 -0
  106. package/src/core/evidence.mjs +167 -0
  107. package/src/core/hooks.mjs +241 -0
  108. package/src/core/node-version.mjs +64 -0
  109. package/src/core/plan.mjs +735 -0
  110. package/src/core/previous-public-baseline.mjs +204 -0
  111. package/src/core/run.mjs +681 -0
  112. package/src/core/state-machine.mjs +76 -0
  113. package/src/core/version-consistency.mjs +111 -0
  114. package/src/producers/build-adapters.mjs +231 -0
  115. package/src/producers/render-public-assets.mjs +152 -0
  116. package/src/producers/sync-skills.mjs +96 -0
  117. package/src/readme/contract.mjs +297 -0
  118. package/src/readme/examples.mjs +288 -0
  119. package/src/readme/parity.mjs +122 -0
  120. package/src/snapshot/export.mjs +99 -0
  121. package/src/snapshot/frozen.mjs +401 -0
  122. package/src/snapshot/manifest.mjs +207 -0
  123. package/src/snapshot/public-map.mjs +1459 -0
  124. package/src/snapshot/public-path.mjs +110 -0
  125. package/src/snapshot/scan.mjs +419 -0
package/README.md ADDED
@@ -0,0 +1,501 @@
1
+ # release-skill
2
+
3
+ [简体中文](README.zh-CN.md)
4
+
5
+ Release preparation for Claude Code and Codex, with human-edited files kept intact.
6
+
7
+ release-skill helps a maintainer answer three questions: what will be released,
8
+ which checks still fail, and which exact bytes will reach users. It freezes the
9
+ reviewed artifacts first and publishes those same artifacts later; it does not
10
+ regenerate a README or re-pack the live workspace at the last step.
11
+
12
+ <!-- release-skill:capability:external-write-boundary -->
13
+ > **Current boundary:** read-only `assess`, offline `prepare`, frozen Git
14
+ > branch/tag, GitHub Release, npm tarball, and Claude/Codex marketplace consumer
15
+ > installation verification have passed a local production-equivalent protocol
16
+ > sandbox using the real release-skill CLI and frozen artifacts, local bare Git
17
+ > remotes, and protocol fakes for `gh`, `npm`, Claude, and Codex. Separate
18
+ > isolated local probes have exercised the installed Claude/Codex CLIs; no real
19
+ > marketplace or production API was contacted. The tests do not provide
20
+ > OS-level network isolation. We
21
+ > have not run a real production canary for you; treat the first real release as
22
+ > a monitored canary. Real APIs, auth, permissions, rate limits, and eventual
23
+ > consistency are outside this sandbox claim. `prepare --online` observes previous
24
+ > public baselines (bound mode) and fails closed on drift; remote uniqueness checks
25
+ > are deferred to publish global preflight.
26
+
27
+ <!-- release-skill:capability:safe-first-command -->
28
+ > **v0.1.1 release candidate:** until `npm view release-skill version` returns
29
+ > `0.1.1`, use the source-checkout command below; do not assume the npm command
30
+ > already exists.
31
+ >
32
+ > **Start here:**
33
+ > - published package: `release-skill help`
34
+ > - current release candidate: `node "$RELEASE_SKILL_HOME/packages/release-skill/bin/release-skill.mjs" help`
35
+
36
+ <!-- release-skill:maturity:v0.1-boundary -->
37
+ <!-- release-skill:maturity:boundary -->
38
+ > **Safe defaults:** the recommended path is `help → assess → prepare --offline →
39
+ > human review`. Production publishing adds `prepare --production → approve →
40
+ > publish --confirm-production <planDigest>`; a `bound` previous-public baseline
41
+ > specifically requires `prepare --online --production`. Without digest confirmation,
42
+ > no remote preflight or write starts.
43
+
44
+ ## Why this is safe for a hand-edited README
45
+
46
+ release-skill does not regenerate or rewrite project source files. `prepare` copies
47
+ each configured public file from the current workspace into an isolated local
48
+ snapshot and verifies the copied bytes. That includes the complete README:
49
+ slogans, examples, prose, formatting, and later human edits.
50
+
51
+ - A later prepare reads the current file again; it does not rebuild it from a template.
52
+ - The snapshot must match the source bytes exactly.
53
+ - A changed plan gets a new digest, so an old approval cannot authorize it.
54
+ - A source edit after prepare makes publish stop before remote writes. Preserve
55
+ the edit by preparing, reviewing, and approving a new plan.
56
+ - Tampering with a frozen snapshot, Git object, or tarball fails its digest gate.
57
+ - Existing remote branches, tags, releases, or npm versions require human
58
+ intervention; the tool does not force or overwrite them.
59
+ - Only files listed in `publicFiles` are copied. Add translated READMEs, images,
60
+ demos, and linked documents explicitly when they belong in the release.
61
+
62
+ This is the preservation contract: **copy current truth, freeze reviewed
63
+ truth, and never rewrite human truth.**
64
+
65
+ ## Quick start
66
+
67
+ ### Install / requirements
68
+
69
+ - Node.js 22+
70
+ - Git 2.30+
71
+ - A target Git repository with at least one commit
72
+
73
+ > **v0.1.1 release candidate:** before the production release completes, the
74
+ > npm registry may return 404. Use the source-checkout path below for review.
75
+ > After `npm view release-skill version` returns `0.1.1`, the npm-installed CLI
76
+ > is the supported user entry and the source checkout is a development fallback.
77
+
78
+ **Install from npm (supported after v0.1.1 publication):**
79
+
80
+ ```bash
81
+ npm install -g release-skill
82
+ ```
83
+
84
+ Or run directly without installing:
85
+
86
+ ```bash
87
+ npx release-skill help
88
+ ```
89
+
90
+ **Verify the install:**
91
+
92
+ ```bash
93
+ release-skill help
94
+ ```
95
+
96
+ **Development install (from source checkout):**
97
+
98
+ Set the checkout location and install dependencies:
99
+
100
+ ```bash
101
+ export RELEASE_SKILL_HOME=/absolute/path/to/release-skill
102
+ cd "$RELEASE_SKILL_HOME"
103
+ npm exec --yes pnpm@10.17.1 -- install --frozen-lockfile
104
+ ```
105
+
106
+ Then use the CLI via `node "$RELEASE_SKILL_HOME/packages/release-skill/bin/release-skill.mjs"`.
107
+
108
+ Create `.release-skill/project.yaml` in the target project:
109
+
110
+ First keep local plans, approvals, and frozen artifacts out of Git:
111
+
112
+ ```gitignore
113
+ .release-skill/*
114
+ !.release-skill/project.yaml
115
+ ```
116
+
117
+ Then create the configuration. npm visibility must be explicit:
118
+
119
+ ```yaml
120
+ apiVersion: release-skill/v1
121
+ kind: ReleaseProject
122
+
123
+ project:
124
+ name: my-project
125
+ defaultBranch: main
126
+
127
+ releaseUnits:
128
+ - id: my-project
129
+ source: .
130
+ publicRepo: owner/my-project
131
+ version:
132
+ source: package.json
133
+ tagTemplate: v{version}
134
+ publicFiles:
135
+ - from: README.md
136
+ to: README.md
137
+ mode: preserve
138
+ - from: package.json
139
+ to: package.json
140
+ mode: preserve
141
+ - from: LICENSE
142
+ to: LICENSE
143
+ mode: preserve
144
+ requiredPublicFiles: [README.md, LICENSE, package.json]
145
+ previousPublicBaseline:
146
+ mode: none # first release: no prior public version exists
147
+ distributions:
148
+ - type: npm
149
+ package: my-project
150
+ access: public # or restricted; choose the real package policy
151
+ provenance: false # use true only after CI/OIDC is configured
152
+ tag: latest
153
+ registry: https://registry.npmjs.org
154
+ publisher: my-npm-username
155
+ # Optional: CLI smoke verification. When smokeBin is set, verify
156
+ # installs the package in an isolated directory and runs the named
157
+ # binary. Without smokeBin, verify only confirms install + name/version.
158
+ # smokeBin: my-project
159
+ # smokeArgs: [help, --json]
160
+ # smokeExpectedJson:
161
+ # command: help
162
+ # status: READY
163
+ production:
164
+ branchTemplate: release/{tag}
165
+ releaseTitleTemplate: "{unit} {version}"
166
+ releaseNotes: "Human-maintained release notes"
167
+ ```
168
+
169
+ Every release unit must declare its previous public baseline. Use `mode: none`
170
+ only when you have verified that no earlier public version exists. For an
171
+ existing public repository, bind the exact immutable ref and commit instead:
172
+
173
+ ```yaml
174
+ previousPublicBaseline:
175
+ mode: bound
176
+ repo: owner/my-project
177
+ ref: release/v0.9.0
178
+ commit: 0123456789abcdef0123456789abcdef01234567
179
+ ```
180
+
181
+ `none` is not a conflict-check bypass: publish still checks target branch,
182
+ tag, GitHub Release, and npm version uniqueness before any write. A bound
183
+ production prepare must run online so the ref-to-commit mapping can be observed.
184
+ The default observer does not download remote file contents, so it reports a
185
+ mapping diff and marks content diff unavailable. On drift, stop and choose
186
+ `merge`, `adopt`, or `reject` manually. First obtain and review the actual remote
187
+ commit; the tool does not download or merge its files. `merge` keeps both local
188
+ and remote edits in the human-owned source. `adopt` copies the reviewed remote
189
+ bytes into that source. `reject` stops the release while the remote/ref is
190
+ investigated or corrected; never switch to `mode: none` to bypass the drift.
191
+ After `merge` or `adopt`, rebind `previousPublicBaseline` to the accepted
192
+ immutable `repo`/`ref`/`commit`, then run a new `prepare --online --production`,
193
+ review, and approval.
194
+
195
+ This is a mechanics-only local example, not a complete npm publication map.
196
+ Before a real release, enumerate every public runtime file, executable, type
197
+ declaration, image, and linked document. In a monorepo, set `source` to a path
198
+ such as `packages/my-plugin`, and keep each `from` path relative to the workspace
199
+ root, for example `packages/my-plugin/README.md`.
200
+
201
+ Before the first prepare, preferably commit `.gitignore`, `.release-skill/project.yaml`,
202
+ the README, version files, and all intended release content so the Git baseline
203
+ is easy to reproduce. Uncommitted edits that already exist at prepare time and
204
+ remain unchanged are included in the snapshot/baseline; only a later change
205
+ causes baseline validation to stop.
206
+
207
+ ### Main workflow
208
+
209
+ Run these steps in order. Steps 1–3 are safe default (read-only or local-only);
210
+ steps 4–8 are production publishing with explicit human gates.
211
+
212
+ ```bash
213
+ # Current v0.1.1 release candidate:
214
+ CLI=(node "$RELEASE_SKILL_HOME/packages/release-skill/bin/release-skill.mjs")
215
+ PROJECT=/absolute/path/to/my-project
216
+ # After npm view reports 0.1.1 and the package is installed:
217
+ # CLI=(release-skill)
218
+ ```
219
+
220
+ The source-checkout entry remains the candidate default until npm publication is
221
+ verified; after that, the installed npm entry is the supported user default.
222
+
223
+ 1. **Environment check:**
224
+ ```bash
225
+ "${CLI[@]}" help
226
+ ```
227
+ 2. **Readiness assessment (read-only):**
228
+ ```bash
229
+ "${CLI[@]}" assess --root "$PROJECT" --offline --json
230
+ ```
231
+ 3. **Local snapshot and plan freeze:**
232
+ ```bash
233
+ "${CLI[@]}" prepare --root "$PROJECT" --offline --json
234
+ ```
235
+ 4. **Human review:** inspect the returned `planPath`, `externalActions`,
236
+ `units[].targetVersion`, and `planDigest`. Each unit's snapshot is under
237
+ `<evidenceDir>/snapshots/<unit-id>/`. The command writes only local release
238
+ data under `.release-skill/`.
239
+ 5. **Production plan freeze:**
240
+ ```bash
241
+ "${CLI[@]}" prepare --root "$PROJECT" --online --production --json
242
+ ```
243
+ Review the new plan's externalActions, npm policy, branch/tag, and frozen
244
+ digests. `prepare --json` returns the immutable production authority as
245
+ `<project>/.release-skill/plans/<planDigest>.json`; always carry that returned
246
+ `planPath` forward. `.release-skill/release-plan.json` is only a mutable
247
+ convenience alias and must not be passed to production approve/publish/reconcile.
248
+ 6. **Approval:**
249
+ ```bash
250
+ "${CLI[@]}" approve --plan <planPath> --digest <planDigest> --actor <name> --json
251
+ ```
252
+ Returns the immutable production authority as `approvalPath` at
253
+ `<project>/.release-skill/approvals/<planDigest>/<approvalDigest>.json`.
254
+ `latestApprovalPath` points to `.release-skill/approval-record.json`, which is
255
+ only a mutable convenience alias and must not be passed to production
256
+ publish/reconcile. Approval expires after 24
257
+ hours; a PARTIAL recovery may create a new approval for the same plan while
258
+ preserving every earlier approval byte-for-byte. Use the returned
259
+ `approvalPath` and `expiresAt` as authority.
260
+ 7. **Publish (remote writes start here):**
261
+ ```bash
262
+ "${CLI[@]}" publish --root "$PROJECT" \
263
+ --plan <planPath> --approval <approvalPath> \
264
+ --confirm-production <planDigest> --json
265
+ ```
266
+ Save the returned `runPath`. `PUBLISHED` is **not** the terminal state.
267
+ 8. **Verify (consumer install check):**
268
+ ```bash
269
+ "${CLI[@]}" verify --root "$PROJECT" \
270
+ --plan <planPath> --run <publishRunPath> --json
271
+ ```
272
+
273
+ Production prepare seals a standalone Git commit/tree for every public snapshot
274
+ and creates a fixed tarball for every npm unit. Publish globally preflights all
275
+ actions, then executes and observes public branch, tag, npm, GitHub Release,
276
+ and configured Claude/Codex marketplace installation checkpoints. `verify`
277
+ installs every exact npm `package@version` in an isolated directory; when
278
+ `smokeBin` is configured it also runs the CLI and validates output. Only when
279
+ all evidence matches does the run reach `VERIFIED`.
280
+ Before a real release run `gh auth login`, `gh auth setup-git`, and
281
+ `npm login`, and confirm Git HTTPS credentials can access the target repository.
282
+ Version branches default to `release/<tag>` and can be configured per unit with
283
+ `production.branchTemplate`; any existing remote object stops for human review.
284
+
285
+ ### Parent workspace with npm + plugin sub-units
286
+
287
+ When a monorepo produces both an npm package and a Claude/Codex plugin from
288
+ different directories, define separate release units. Only add a plugin
289
+ distribution when the unit actually ships a plugin with manifest, marketplace,
290
+ and entry Skill:
291
+
292
+ Here `project` is the parent workspace's orchestration container, not a public
293
+ release unit. If the workspace root also publishes its own repository or
294
+ package, add another release unit with `source: .`.
295
+
296
+ ```yaml
297
+ apiVersion: release-skill/v1
298
+ kind: ReleaseProject
299
+ project:
300
+ name: my-workspace
301
+ defaultBranch: main
302
+
303
+ releaseUnits:
304
+ - id: my-app
305
+ source: packages/app
306
+ publicRepo: owner/my-app
307
+ version:
308
+ source: packages/app/package.json
309
+ tagTemplate: my-app-v{version}
310
+ distributions:
311
+ - type: npm
312
+ package: my-app
313
+ access: public
314
+ provenance: false
315
+ tag: latest
316
+ registry: https://registry.npmjs.org
317
+ publisher: my-npm-username
318
+ smokeBin: my-app
319
+ smokeArgs: [help, --json]
320
+ smokeExpectedJson:
321
+ command: help
322
+ status: READY
323
+ publicFiles:
324
+ - from: packages/app/README.md
325
+ to: README.md
326
+ mode: preserve
327
+ - from: packages/app/package.json
328
+ to: package.json
329
+ mode: preserve
330
+ - from: packages/app/LICENSE
331
+ to: LICENSE
332
+ mode: preserve
333
+ requiredPublicFiles: [README.md, package.json, LICENSE]
334
+ previousPublicBaseline:
335
+ mode: none
336
+ production:
337
+ branchTemplate: release/{tag}
338
+ releaseTitleTemplate: "{unit} {version}"
339
+
340
+ - id: my-plugin
341
+ source: packages/plugin
342
+ publicRepo: owner/my-plugin
343
+ version:
344
+ source: packages/plugin/package.json
345
+ tagTemplate: my-plugin-v{version}
346
+ distributions:
347
+ # Declare plugin consumers only when the unit ships a plugin.
348
+ # The CLI smoke is independent; only declare smokeBin when the plugin
349
+ # package also exposes a CLI binary.
350
+ - type: claude-plugin
351
+ plugin: my-plugin
352
+ marketplace: my-plugin
353
+ entrySkill: my-plugin-help
354
+ - type: codex-plugin
355
+ plugin: my-plugin
356
+ marketplace: my-plugin
357
+ entrySkill: my-plugin-help
358
+ publicFiles:
359
+ - from: packages/plugin/.claude-plugin/plugin.json
360
+ to: .claude-plugin/plugin.json
361
+ mode: preserve
362
+ - from: packages/plugin/.claude-plugin/marketplace.json
363
+ to: .claude-plugin/marketplace.json
364
+ mode: preserve
365
+ - from: packages/plugin/.codex-plugin/plugin.json
366
+ to: .codex-plugin/plugin.json
367
+ mode: preserve
368
+ - from: packages/plugin/.agents/plugins/marketplace.json
369
+ to: .agents/plugins/marketplace.json
370
+ mode: preserve
371
+ - from: packages/plugin/skills/my-plugin-help/SKILL.md
372
+ to: skills/my-plugin-help/SKILL.md
373
+ mode: preserve
374
+ - from: packages/plugin/README.md
375
+ to: README.md
376
+ mode: preserve
377
+ - from: packages/plugin/package.json
378
+ to: package.json
379
+ mode: preserve
380
+ - from: packages/plugin/LICENSE
381
+ to: LICENSE
382
+ mode: preserve
383
+ requiredPublicFiles:
384
+ - .claude-plugin/plugin.json
385
+ - .claude-plugin/marketplace.json
386
+ - .codex-plugin/plugin.json
387
+ - .agents/plugins/marketplace.json
388
+ - skills/my-plugin-help/SKILL.md
389
+ - README.md
390
+ - package.json
391
+ - LICENSE
392
+ previousPublicBaseline:
393
+ mode: none
394
+ production:
395
+ branchTemplate: release/{tag}
396
+ releaseTitleTemplate: "{unit} {version}"
397
+ ```
398
+
399
+ Each plugin unit **must** list its Claude/Codex `plugin.json`, `marketplace.json`,
400
+ the entry Skill, and all required public files. A CLI smoke (`smokeBin`) is
401
+ optional for plugin units and only applies when the published npm package
402
+ exposes a CLI binary.
403
+
404
+ ### PARTIAL recovery and reconcile
405
+
406
+ When `publish` succeeds at some checkpoints but fails at others, the run enters
407
+ `PARTIAL` status. **Do not restart from scratch and do not delete remote state**
408
+ (e.g., do not delete a tag that was already pushed, or unpublish a package).
409
+
410
+ Instead, use `reconcile` to inspect actual remote state, skip already-consistent
411
+ steps, and safely retry incomplete actions:
412
+
413
+ ```bash
414
+ "${CLI[@]}" reconcile --root "$PROJECT" \
415
+ --run <publishRunPath> \
416
+ --plan <planPath> \
417
+ --approval <approvalPath> \
418
+ --confirm-production <planDigest> \
419
+ --json
420
+ # Save reconcile's new runPath, then perform the fresh install verification.
421
+ "${CLI[@]}" verify --root "$PROJECT" \
422
+ --plan <planPath> --run <reconcileRunPath> --json
423
+ ```
424
+
425
+ `reconcile` queries the actual remote state (Git refs, npm version, GitHub
426
+ Release, marketplace install), skips any step whose evidence already matches
427
+ the frozen plan, and retries only safe and incomplete steps. Remote conflicts
428
+ (e.g., an unexpected tag or npm version) require human decision and cannot be
429
+ auto-resolved.
430
+ Successful reconcile returns `PUBLISHED`, not `VERIFIED`; only the fresh
431
+ `verify` run may produce the terminal `VERIFIED` state.
432
+
433
+ ## Accepted capabilities
434
+
435
+ - validates project configuration and release units;
436
+ - reports readiness without changing the project during `assess`;
437
+ - copies configured public files into an isolated snapshot;
438
+ - checks required files, path safety, exact bytes/modes, and obvious leaks;
439
+ - records Git/workspace identity and freezes a digest-bound release plan;
440
+ - binds approval to the plan digest, expiry, and explicit action allowlist;
441
+ - publishes only frozen Git objects and npm tarballs, then checks remote
442
+ commit/tree/tag/integrity;
443
+ - installs configured Claude/Codex plugins from the frozen Git ref and proves
444
+ the entry Skill and payload digest in fresh isolated consumer homes;
445
+ - distinguishes `PUBLISHED` (writes completed) from `VERIFIED` (remote and
446
+ consumer installation evidence completed);
447
+ - stops subsequent checkpoints on failure and writes a separate run record
448
+ without mutating the frozen plan or undoing successful remote actions.
449
+
450
+ ## What it does not do yet
451
+
452
+ <!-- release-skill:capability:unsupported-scope -->
453
+ - no automatic README generation or source-file overwrite;
454
+ - no automatic conflict merge or rollback workflow;
455
+ - no claim that a real production canary has run for marketplace verification;
456
+ - `prepare --online` observes previous public baselines (bound mode) and defers
457
+ remote uniqueness checks to publish global preflight;
458
+ - no force push, overwrite of branches/tags/releases, or npm unpublish;
459
+ - no promise of Windows or broad multi-platform native write support;
460
+ - no hidden commit, push, tag, release, or package publication.
461
+
462
+ ### Write Safety
463
+
464
+ `assess` is read-only unless an explicit report output is requested. `prepare`
465
+ writes local files under `.release-skill/`; it does not write project source
466
+ files or remote services. If hooks are configured, they are arbitrary local
467
+ processes and require `--acknowledge-hook-side-effects`; hooks may have their
468
+ own filesystem or network side effects. `publish` is the production write entry
469
+ and requires both approval and the current plan digest. Omit hooks and use local
470
+ sandbox targets for the smallest safe rehearsal.
471
+
472
+ ### If something fails
473
+
474
+ | Result | What to do |
475
+ |---|---|
476
+ | `CONFIG_INVALID` | Correct `.release-skill/project.yaml`, then rerun `assess`. |
477
+ | `PUBLIC_FILE_MISSING` | Add or correct the configured public file. |
478
+ | `FORBIDDEN_CONTENT_DETECTED` | Remove the leaked/private content, then prepare again. |
479
+ | `SNAPSHOT_FIDELITY_FAILED` | Inspect the source/snapshot path and rerun `prepare`. |
480
+ | `BASELINE_CHANGED` | Keep the human edit, then prepare, review, and approve again. |
481
+ | `GATE_FAILED` | Inspect frozen artifacts, auth, remote uniqueness, and digest confirmation. |
482
+ | `PARTIAL` | Do not restart or delete remote state; review the returned `runPath` and run `reconcile` (see above). |
483
+ | `PUBLISHED` | Run `verify --plan <planPath> --run <publishRunPath>`; this is not terminal success. |
484
+ | `VERIFIED` | Remote state, exact npm install, and configured plugin consumer installs all matched the frozen plan. |
485
+
486
+ ## Skills
487
+
488
+ - `release-help`: environment check and next-step guidance.
489
+ - `release-assess`: read-only release readiness report.
490
+ - `release-prepare`: local snapshot and reviewable release plan.
491
+ - `release-publish`: approved, digest-confirmed frozen GitHub+npm publishing.
492
+ - `release-reconcile`: evidence-based PARTIAL recovery with human intervention on conflicts.
493
+ - `release-verify`: post-publish verification; only `VERIFIED` is the happy end.
494
+
495
+ Conflicts still default to human intervention. Before v0.1.1 is published, use
496
+ the source CLI shown above; after registry verification, the supported user
497
+ entry is the npm-installed `release-skill` CLI.
498
+
499
+ ## License
500
+
501
+ MIT. See [LICENSE](LICENSE).