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.
- package/.agents/plugins/marketplace.json +23 -0
- package/.claude-plugin/marketplace.json +16 -0
- package/.claude-plugin/plugin.json +10 -0
- package/.codex-plugin/plugin.json +26 -0
- package/CHANGELOG.md +68 -0
- package/CODE_OF_CONDUCT.md +76 -0
- package/CONTRIBUTING.md +49 -0
- package/INSTALL.md +182 -0
- package/LICENSE +21 -0
- package/NOTICE +25 -0
- package/README.md +501 -0
- package/README.zh-CN.md +463 -0
- package/SECURITY.md +48 -0
- package/adapters/claude/.claude-plugin/marketplace.json +16 -0
- package/adapters/claude/.claude-plugin/plugin.json +10 -0
- package/adapters/claude/skills/release-assess/SKILL.md +52 -0
- package/adapters/claude/skills/release-help/SKILL.md +60 -0
- package/adapters/claude/skills/release-prepare/SKILL.md +71 -0
- package/adapters/claude/skills/release-publish/SKILL.md +55 -0
- package/adapters/claude/skills/release-reconcile/SKILL.md +73 -0
- package/adapters/claude/skills/release-verify/SKILL.md +70 -0
- package/adapters/codex/.codex-plugin/plugin.json +26 -0
- package/adapters/codex/skills/release-assess/SKILL.md +52 -0
- package/adapters/codex/skills/release-help/SKILL.md +60 -0
- package/adapters/codex/skills/release-prepare/SKILL.md +71 -0
- package/adapters/codex/skills/release-publish/SKILL.md +55 -0
- package/adapters/codex/skills/release-reconcile/SKILL.md +73 -0
- package/adapters/codex/skills/release-verify/SKILL.md +70 -0
- package/bin/release-skill.mjs +743 -0
- package/native/safe-write/binding.gyp +40 -0
- package/native/safe-write/prebuilds.json +4 -0
- package/native/safe-write/src/safe_write.cc +2023 -0
- package/package.json +75 -0
- package/references/.render-manifest.json +33 -0
- package/references/00-target-state.md +124 -0
- package/references/01-state-machine.md +155 -0
- package/references/02-project-config.md +217 -0
- package/references/03-readme-quality.md +136 -0
- package/references/04-supply-chain.md +147 -0
- package/references/05-evidence-and-errors.md +164 -0
- package/references/06-adapter-contract.md +178 -0
- package/schemas/.render-manifest.json +37 -0
- package/schemas/approval-record.schema.json +115 -0
- package/schemas/artifact-lock.schema.json +111 -0
- package/schemas/artifact-plan.schema.json +52 -0
- package/schemas/artifact-policy.schema.json +76 -0
- package/schemas/evidence-event.schema.json +89 -0
- package/schemas/release-plan.schema.json +369 -0
- package/schemas/release-project.schema.json +359 -0
- package/schemas/release-run.schema.json +195 -0
- package/skills/release-assess/SKILL.md +52 -0
- package/skills/release-help/SKILL.md +60 -0
- package/skills/release-prepare/SKILL.md +71 -0
- package/skills/release-publish/SKILL.md +55 -0
- package/skills/release-reconcile/SKILL.md +73 -0
- package/skills/release-verify/SKILL.md +70 -0
- package/skills-src/release-assess/SKILL.md +52 -0
- package/skills-src/release-help/SKILL.md +60 -0
- package/skills-src/release-prepare/SKILL.md +71 -0
- package/skills-src/release-publish/SKILL.md +55 -0
- package/skills-src/release-reconcile/SKILL.md +73 -0
- package/skills-src/release-verify/SKILL.md +70 -0
- package/src/adapters/contract.mjs +214 -0
- package/src/adapters/git-github.mjs +214 -0
- package/src/adapters/npm.mjs +947 -0
- package/src/adapters/plugin-marketplace.mjs +1365 -0
- package/src/adapters/push-snapshot.mjs +216 -0
- package/src/artifacts/adoption.mjs +743 -0
- package/src/artifacts/artifact-plan.mjs +162 -0
- package/src/artifacts/entry.mjs +240 -0
- package/src/artifacts/git-authority.mjs +637 -0
- package/src/artifacts/graph.mjs +189 -0
- package/src/artifacts/inspect.mjs +520 -0
- package/src/artifacts/inventory.mjs +192 -0
- package/src/artifacts/merge/binary.mjs +77 -0
- package/src/artifacts/merge/entry-merge.mjs +228 -0
- package/src/artifacts/merge/json.mjs +641 -0
- package/src/artifacts/merge/markdown.mjs +246 -0
- package/src/artifacts/merge/regions.mjs +156 -0
- package/src/artifacts/merge/text.mjs +432 -0
- package/src/artifacts/merge/tree.mjs +202 -0
- package/src/artifacts/merge/yaml.mjs +669 -0
- package/src/artifacts/path-key.mjs +94 -0
- package/src/artifacts/policy.mjs +319 -0
- package/src/artifacts/producer-registry.mjs +439 -0
- package/src/artifacts/project-lock.mjs +732 -0
- package/src/artifacts/resolution.mjs +658 -0
- package/src/artifacts/safe-fs-backend-internal.mjs +680 -0
- package/src/artifacts/safe-fs.mjs +72 -0
- package/src/artifacts/state.mjs +495 -0
- package/src/artifacts/transaction-journal.mjs +983 -0
- package/src/artifacts/transaction.mjs +1361 -0
- package/src/commands/approve.mjs +280 -0
- package/src/commands/artifacts.mjs +627 -0
- package/src/commands/assess.mjs +838 -0
- package/src/commands/prepare.mjs +1377 -0
- package/src/commands/publish.mjs +883 -0
- package/src/commands/reconcile.mjs +1255 -0
- package/src/commands/verify.mjs +915 -0
- package/src/core/approval.mjs +332 -0
- package/src/core/baseline.mjs +272 -0
- package/src/core/blackbox-hard-gates.mjs +142 -0
- package/src/core/config.mjs +448 -0
- package/src/core/digest.mjs +90 -0
- package/src/core/errors.mjs +113 -0
- package/src/core/evidence.mjs +167 -0
- package/src/core/hooks.mjs +241 -0
- package/src/core/node-version.mjs +64 -0
- package/src/core/plan.mjs +735 -0
- package/src/core/previous-public-baseline.mjs +204 -0
- package/src/core/run.mjs +681 -0
- package/src/core/state-machine.mjs +76 -0
- package/src/core/version-consistency.mjs +111 -0
- package/src/producers/build-adapters.mjs +231 -0
- package/src/producers/render-public-assets.mjs +152 -0
- package/src/producers/sync-skills.mjs +96 -0
- package/src/readme/contract.mjs +297 -0
- package/src/readme/examples.mjs +288 -0
- package/src/readme/parity.mjs +122 -0
- package/src/snapshot/export.mjs +99 -0
- package/src/snapshot/frozen.mjs +401 -0
- package/src/snapshot/manifest.mjs +207 -0
- package/src/snapshot/public-map.mjs +1459 -0
- package/src/snapshot/public-path.mjs +110 -0
- 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).
|