release-skill 0.1.1 → 0.1.4
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +3 -3
- package/CHANGELOG.md +89 -0
- package/INSTALL.md +216 -5
- package/INSTALL.zh-CN.md +358 -0
- package/README.md +411 -67
- package/README.zh-CN.md +377 -59
- package/adapters/claude/.claude-plugin/marketplace.json +1 -1
- package/adapters/claude/.claude-plugin/plugin.json +1 -1
- package/adapters/claude/bin/release-skill.bundle.mjs +79284 -0
- package/adapters/claude/bin/release-skill.mjs +34 -0
- package/adapters/claude/native/safe-write/binding.gyp +40 -0
- package/adapters/claude/native/safe-write/prebuilds/darwin-arm64/safe_write.node +0 -0
- package/adapters/claude/native/safe-write/prebuilds.json +24 -0
- package/adapters/claude/native/safe-write/src/safe_write.cc +2032 -0
- package/adapters/claude/schemas/.render-manifest.json +37 -0
- package/adapters/claude/schemas/approval-record.schema.json +115 -0
- package/adapters/claude/schemas/artifact-lock.schema.json +111 -0
- package/adapters/claude/schemas/artifact-plan.schema.json +52 -0
- package/adapters/claude/schemas/artifact-policy.schema.json +76 -0
- package/adapters/claude/schemas/evidence-event.schema.json +89 -0
- package/adapters/claude/schemas/release-plan.schema.json +860 -0
- package/adapters/claude/schemas/release-project.schema.json +736 -0
- package/adapters/claude/schemas/release-run.schema.json +342 -0
- package/adapters/claude/skills/release-assess/SKILL.md +5 -6
- package/adapters/claude/skills/release-help/SKILL.md +14 -18
- package/adapters/claude/skills/release-prepare/SKILL.md +16 -6
- package/adapters/claude/skills/release-publish/SKILL.md +7 -7
- package/adapters/claude/skills/release-reconcile/SKILL.md +6 -6
- package/adapters/claude/skills/release-setup/SKILL.md +95 -0
- package/adapters/claude/skills/release-verify/SKILL.md +7 -7
- package/adapters/codex/.codex-plugin/plugin.json +2 -2
- package/adapters/codex/bin/release-skill.bundle.mjs +79284 -0
- package/adapters/codex/bin/release-skill.mjs +34 -0
- package/adapters/codex/native/safe-write/binding.gyp +40 -0
- package/adapters/codex/native/safe-write/prebuilds/darwin-arm64/safe_write.node +0 -0
- package/adapters/codex/native/safe-write/prebuilds.json +24 -0
- package/adapters/codex/native/safe-write/src/safe_write.cc +2032 -0
- package/adapters/codex/schemas/.render-manifest.json +37 -0
- package/adapters/codex/schemas/approval-record.schema.json +115 -0
- package/adapters/codex/schemas/artifact-lock.schema.json +111 -0
- package/adapters/codex/schemas/artifact-plan.schema.json +52 -0
- package/adapters/codex/schemas/artifact-policy.schema.json +76 -0
- package/adapters/codex/schemas/evidence-event.schema.json +89 -0
- package/adapters/codex/schemas/release-plan.schema.json +860 -0
- package/adapters/codex/schemas/release-project.schema.json +736 -0
- package/adapters/codex/schemas/release-run.schema.json +342 -0
- package/adapters/codex/skills/release-assess/SKILL.md +12 -6
- package/adapters/codex/skills/release-help/SKILL.md +21 -18
- package/adapters/codex/skills/release-prepare/SKILL.md +23 -6
- package/adapters/codex/skills/release-publish/SKILL.md +14 -7
- package/adapters/codex/skills/release-reconcile/SKILL.md +13 -6
- package/adapters/codex/skills/release-setup/SKILL.md +102 -0
- package/adapters/codex/skills/release-verify/SKILL.md +14 -7
- package/bin/release-skill-cli.mjs +807 -0
- package/bin/release-skill.bundle.mjs +79284 -0
- package/bin/release-skill.mjs +23 -732
- package/native/safe-write/prebuilds/darwin-arm64/safe_write.node +0 -0
- package/native/safe-write/prebuilds.json +22 -2
- package/native/safe-write/src/safe_write.cc +11 -2
- package/package.json +8 -2
- package/references/02-project-config.md +55 -4
- package/references/05-evidence-and-errors.md +6 -2
- package/schemas/release-plan.schema.json +556 -65
- package/schemas/release-project.schema.json +406 -29
- package/schemas/release-run.schema.json +165 -18
- package/scripts/build-bundle.mjs +133 -0
- package/skills/release-assess/SKILL.md +5 -6
- package/skills/release-help/SKILL.md +14 -18
- package/skills/release-prepare/SKILL.md +16 -6
- package/skills/release-publish/SKILL.md +7 -7
- package/skills/release-reconcile/SKILL.md +6 -6
- package/skills/release-setup/SKILL.md +95 -0
- package/skills/release-verify/SKILL.md +7 -7
- package/skills-src/release-assess/SKILL.md +5 -6
- package/skills-src/release-help/SKILL.md +14 -18
- package/skills-src/release-prepare/SKILL.md +16 -6
- package/skills-src/release-publish/SKILL.md +7 -7
- package/skills-src/release-reconcile/SKILL.md +6 -6
- package/skills-src/release-setup/SKILL.md +95 -0
- package/skills-src/release-verify/SKILL.md +7 -7
- package/src/adapters/contract.mjs +3 -0
- package/src/adapters/git-github.mjs +84 -2
- package/src/adapters/npm.mjs +5 -13
- package/src/adapters/plugin-marketplace.mjs +132 -52
- package/src/adapters/push-snapshot.mjs +84 -17
- package/src/artifacts/policy.mjs +4 -7
- package/src/artifacts/safe-fs-backend-internal.mjs +69 -21
- package/src/commands/prepare.mjs +244 -20
- package/src/commands/publish.mjs +46 -0
- package/src/commands/reconcile.mjs +152 -0
- package/src/commands/setup.mjs +1525 -0
- package/src/commands/verify.mjs +122 -26
- package/src/core/approval.mjs +4 -6
- package/src/core/config.mjs +42 -8
- package/src/core/errors.mjs +4 -0
- package/src/core/pkg-root.mjs +22 -0
- package/src/core/plan.mjs +132 -4
- package/src/core/previous-public-baseline.mjs +21 -1
- package/src/core/run.mjs +4 -4
- package/src/core/trusted-resource.mjs +96 -0
- package/src/core/verification-gates.mjs +451 -0
- package/src/docs/version-gate.mjs +164 -0
- package/src/producers/build-adapters.mjs +512 -55
- package/src/snapshot/frozen.mjs +221 -7
- package/src/snapshot/public-map.mjs +7 -4
- package/src/snapshot/scan.mjs +2 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-skill",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "release-skill contributors"
|
|
7
7
|
},
|
|
8
8
|
"license": "MIT",
|
|
9
|
-
"skills": "./skills/"
|
|
9
|
+
"skills": "./adapters/claude/skills/"
|
|
10
10
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-skill",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "release-skill contributors"
|
|
7
7
|
},
|
|
8
8
|
"license": "MIT",
|
|
9
|
-
"skills": "./skills/",
|
|
9
|
+
"skills": "./adapters/codex/skills/",
|
|
10
10
|
"interface": {
|
|
11
11
|
"displayName": "Release Skill",
|
|
12
12
|
"shortDescription": "Safe preparation and frozen GitHub/npm publishing",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
],
|
|
20
20
|
"defaultPrompt": [
|
|
21
21
|
"Assess this project for release readiness.",
|
|
22
|
-
"Prepare a release plan for version 0.1.
|
|
22
|
+
"Prepare a release plan for version 0.1.4.",
|
|
23
23
|
"Help me understand the release workflow."
|
|
24
24
|
]
|
|
25
25
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,95 @@
|
|
|
3
3
|
All notable changes to the `release-skill` plugin will be documented in this
|
|
4
4
|
file. The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
5
5
|
|
|
6
|
+
## [0.1.4] - 2026-07-19
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- **Docs version hard gate**: the English and Chinese README and INSTALL each
|
|
11
|
+
carry a machine-readable `release-skill:release-version` marker that must
|
|
12
|
+
equal the `package.json` version, and the CHANGELOG must carry a formal
|
|
13
|
+
heading for the current version. Any drift fails closed in
|
|
14
|
+
`pnpm test:release` before prepare. A release freezes only the current
|
|
15
|
+
truth: human docs are never auto-refreshed and must be updated, reviewed,
|
|
16
|
+
and approved first.
|
|
17
|
+
- **Auditable frozen commit timestamps**: production `prepare` samples the
|
|
18
|
+
plan freeze time once, validates it before any Git write, and binds it to
|
|
19
|
+
`GIT_AUTHOR_DATE`/`GIT_COMMITTER_DATE` and each unit's
|
|
20
|
+
`frozenSnapshot.commitTimestamp` (schema-required); plans missing the field
|
|
21
|
+
are rejected instead of silently rebuilt.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- **Self-contained installed CLI smoke**: the v0.1.3 self-release selected
|
|
26
|
+
`help --json`, which correctly treats Git as a required environment
|
|
27
|
+
dependency, while npm smoke intentionally exposes only the Node runtime.
|
|
28
|
+
The CLI now supports `--version --json`, and self-release verification uses
|
|
29
|
+
that dependency-free entry to bind the installed CLI name and exact version
|
|
30
|
+
without widening the isolated process `PATH`.
|
|
31
|
+
- Added a real subprocess regression that runs the installed-style version
|
|
32
|
+
entry with the Node-only `PATH` and proves an unrelated injected path is not
|
|
33
|
+
inherited.
|
|
34
|
+
|
|
35
|
+
## [0.1.3] - 2026-07-19
|
|
36
|
+
|
|
37
|
+
> `0.1.2` was an internal release candidate and was never published to npm or
|
|
38
|
+
> GitHub Releases. Its fixes are included here; `0.1.3` is the next public
|
|
39
|
+
> release after `0.1.1`.
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
|
|
43
|
+
- **Create-once first-use setup**: `release-skill setup` performs deterministic,
|
|
44
|
+
read-only discovery of packages, plugin manifests, Git remotes, legacy
|
|
45
|
+
`public-release.json`, public-file hints, and project quality scripts. It
|
|
46
|
+
reports `NEEDS_INPUT` or `LOCAL_ONLY_DETECTED` honestly and writes only an
|
|
47
|
+
absent `.release-skill/project.yaml` after answers and the exact
|
|
48
|
+
`setupDigest` are confirmed.
|
|
49
|
+
- **Discoverable `release-setup` skill**: Claude and Codex adapters now guide
|
|
50
|
+
users through candidate review, explicit gate selection, fact-drift handling,
|
|
51
|
+
and the safe handoff to `release-assess` without regenerating human content.
|
|
52
|
+
- **Project verification gates**: `snapshot-verify` runs selected commands in a
|
|
53
|
+
disposable writable copy of the frozen public snapshot;
|
|
54
|
+
`consumer-verify` runs after an exact isolated npm/Claude/Codex installation.
|
|
55
|
+
Gate definitions, exact execution-input digests, and bounded output digests
|
|
56
|
+
are frozen into plan/run evidence.
|
|
57
|
+
- **Identity-bound create-once setup**: the final facts/answers digest and
|
|
58
|
+
config bytes are bound immediately before a directory-handle-relative,
|
|
59
|
+
no-follow create. v0.1.3 ships a digest-registered `darwin-arm64` prebuild;
|
|
60
|
+
unsupported platforms fail closed instead of using pathname writes.
|
|
61
|
+
- **Explicit production branch strategies**: projects can create an immutable
|
|
62
|
+
release branch, fast-forward an existing branch from an exact bound baseline,
|
|
63
|
+
or initialize an absent standard branch and make a separately approved,
|
|
64
|
+
observable, reconcilable default-branch change.
|
|
65
|
+
|
|
66
|
+
### Changed
|
|
67
|
+
|
|
68
|
+
- Existing `public-release.json` snapshot commands are surfaced only as
|
|
69
|
+
migration candidates. Discovery never grants execution authority; gate and
|
|
70
|
+
legacy-hook side effects still require separate explicit acknowledgements.
|
|
71
|
+
- Compatibility configurations for artifact-graph, flow-architect, loop-agent,
|
|
72
|
+
and agent-method-registry now bind real tag/channel/baseline semantics and
|
|
73
|
+
project-owned verification behavior. glaf4-test is represented as local-only
|
|
74
|
+
instead of receiving an invented remote channel.
|
|
75
|
+
- README and installation guidance now begin with safe setup, explain the three
|
|
76
|
+
branch strategies, and distinguish pre-freeze hooks from frozen-snapshot and
|
|
77
|
+
installed-consumer gates.
|
|
78
|
+
|
|
79
|
+
### Fixed
|
|
80
|
+
|
|
81
|
+
- **GitHub CLI Release-missing plain text compatibility**: `gh release view`
|
|
82
|
+
returns plain text `release not found` when the target release does not
|
|
83
|
+
exist; the previous implementation only recognized an HTTP 404 exit code.
|
|
84
|
+
The adapter now maps that specific plain text to a missing-release
|
|
85
|
+
decision without misclassifying `repository not found` or permission
|
|
86
|
+
errors as a target release absence.
|
|
87
|
+
- **Plugin consumer install verification transport semantics**: frozen
|
|
88
|
+
snapshots are sealed as read-only, but Git and plugin installation
|
|
89
|
+
transport restores owner write permission on extraction. Verification
|
|
90
|
+
now normalizes ordinary write permission from transport semantics and
|
|
91
|
+
continues to strictly verify path, type, content, size, and executable
|
|
92
|
+
intent. The frozen source digest is still compared against the plan and
|
|
93
|
+
must not be back-filled from observed results.
|
|
94
|
+
|
|
6
95
|
## [0.1.1] - 2026-07-18
|
|
7
96
|
|
|
8
97
|
### Fixed
|
package/INSTALL.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# Installation Guide
|
|
2
2
|
|
|
3
|
+
[简体中文](INSTALL.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
<!-- release-skill:release-version: 0.1.4 -->
|
|
3
6
|
## Prerequisites
|
|
4
7
|
|
|
5
8
|
- Node.js 22.0.0 or later
|
|
@@ -7,9 +10,10 @@
|
|
|
7
10
|
|
|
8
11
|
## Install from npm (recommended)
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
A public version is complete only after its immutable production plan has been
|
|
14
|
+
approved, published, and reached `VERIFIED`. For a newer source checkout, use
|
|
15
|
+
the npm path only after `npm view release-skill version` returns that exact
|
|
16
|
+
version; before then, use the source checkout instructions below.
|
|
13
17
|
|
|
14
18
|
```bash
|
|
15
19
|
npm install -g release-skill
|
|
@@ -61,7 +65,124 @@ instructions above; do not mix the two entry paths in one run.
|
|
|
61
65
|
"${CLI[@]}" help
|
|
62
66
|
```
|
|
63
67
|
|
|
64
|
-
|
|
68
|
+
If `.release-skill/project.yaml` is absent, keep the full read-only report in a
|
|
69
|
+
temporary file and inspect only its deterministic `compactSummary`:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
PROJECT=/path/to/your/project
|
|
73
|
+
SETUP_SESSION="$(mktemp -d "${TMPDIR:-/tmp}/release-setup.XXXXXX")"
|
|
74
|
+
REPORT="$SETUP_SESSION/discovery.json"
|
|
75
|
+
ANSWERS="$SETUP_SESSION/answers.json"
|
|
76
|
+
BOUND_REPORT="$SETUP_SESSION/bound.json"
|
|
77
|
+
printf 'SETUP_SESSION=%s\nPROJECT=%s\n' "$SETUP_SESSION" "$PROJECT"
|
|
78
|
+
|
|
79
|
+
"${CLI[@]}" setup --root "$PROJECT" --json > "$REPORT" || test "$?" -eq 2
|
|
80
|
+
node -e 'const fs=require("node:fs");const r=JSON.parse(fs.readFileSync(process.argv[1],"utf8"));if(!r.compactSummary){console.error("compactSummary missing");process.exit(2)}process.stdout.write(JSON.stringify(r.compactSummary,null,2)+"\n")' "$REPORT"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The summary is a review view, not authorization; `setupDigest` binds the full
|
|
84
|
+
facts, candidates, and answers. If `proposalConflicts` is non-empty, a human
|
|
85
|
+
must correct the conflicting repository/mapping authority and rerun setup.
|
|
86
|
+
Do not guess. With no conflicts, mechanically extract the proposal:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
SETUP_SESSION='/session-directory-absolute-path-printed-above'
|
|
90
|
+
PROJECT='/project-absolute-path-printed-above'
|
|
91
|
+
REPORT="$SETUP_SESSION/discovery.json"
|
|
92
|
+
ANSWERS="$SETUP_SESSION/answers.json"
|
|
93
|
+
BOUND_REPORT="$SETUP_SESSION/bound.json"
|
|
94
|
+
node -e 'const fs=require("node:fs");const r=JSON.parse(fs.readFileSync(process.argv[1],"utf8"));if((r.proposalConflicts??[]).length){console.error("proposal conflicts require human resolution");process.exit(2)}if(!r.recommendedAnswers){console.error("recommendedAnswers missing");process.exit(2)}fs.writeFileSync(process.argv[2],JSON.stringify(r.recommendedAnswers,null,2)+"\n",{flag:"wx",mode:0o600})' "$REPORT" "$ANSWERS"
|
|
95
|
+
"${CLI[@]}" setup --root "$PROJECT" --answers "$ANSWERS" --json > "$BOUND_REPORT"
|
|
96
|
+
node -e 'const fs=require("node:fs");const r=JSON.parse(fs.readFileSync(process.argv[1],"utf8"));if(!r.compactSummary||!r.setupDigest){console.error("bound setup report incomplete");process.exit(2)}process.stdout.write(JSON.stringify({compactSummary:r.compactSummary,setupDigest:r.setupDigest},null,2)+"\n")' "$BOUND_REPORT"
|
|
97
|
+
printf 'SETUP_SESSION=%s\nPROJECT=%s\n' "$SETUP_SESSION" "$PROJECT"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
After one explicit human confirmation of the bound summary and exact digest,
|
|
101
|
+
create once with that confirmed digest literal. The result must be
|
|
102
|
+
`CONFIG_CREATED`; a second setup must be `ALREADY_CONFIGURED`, then run assess.
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
SETUP_SESSION=<session-directory-absolute-path-printed-above>
|
|
106
|
+
PROJECT=<project-absolute-path-printed-above>
|
|
107
|
+
ANSWERS="$SETUP_SESSION/answers.json"
|
|
108
|
+
CREATED_REPORT="$SETUP_SESSION/created.json"
|
|
109
|
+
POST_REPORT="$SETUP_SESSION/post-setup.json"
|
|
110
|
+
ASSESS_REPORT="$SETUP_SESSION/assess.json"
|
|
111
|
+
"${CLI[@]}" setup --root "$PROJECT" --answers "$ANSWERS" \
|
|
112
|
+
--write --confirm-setup <confirmed-setupDigest> --json > "$CREATED_REPORT"
|
|
113
|
+
"${CLI[@]}" setup --root "$PROJECT" --json > "$POST_REPORT"
|
|
114
|
+
set +e
|
|
115
|
+
"${CLI[@]}" assess --root "$PROJECT" --offline --json > "$ASSESS_REPORT"
|
|
116
|
+
ASSESS_EXIT=$?
|
|
117
|
+
set -e
|
|
118
|
+
[ "$ASSESS_EXIT" -eq 0 ] || [ "$ASSESS_EXIT" -eq 1 ] || exit "$ASSESS_EXIT"
|
|
119
|
+
node -e 'const fs=require("node:fs");const [c,p,a]=process.argv.slice(1).map(x=>JSON.parse(fs.readFileSync(x,"utf8")));if(c.status!=="CONFIG_CREATED"||p.status!=="ALREADY_CONFIGURED"||!["ASSESSED","NEEDS_INPUT","BLOCKED"].includes(a.status)){process.exit(2)}process.stdout.write(JSON.stringify({created:c.status,postSetup:p.status,assessment:{status:a.status,summary:a.summary,gapCount:(a.gaps??[]).length,blockingCodes:(a.gaps??[]).filter(g=>g.severity==="error").map(g=>g.code)}},null,2)+"\n")' "$CREATED_REPORT" "$POST_REPORT" "$ASSESS_REPORT"
|
|
120
|
+
node -e 'require("node:fs").rmSync(process.argv[1],{recursive:true,force:false})' "$SETUP_SESSION"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Indirect interpreter/package-manager scripts are `SIDE_EFFECTS_UNPROVEN` and
|
|
124
|
+
remain unselected. Register a project-specific hook/gate only through a reviewed
|
|
125
|
+
incremental edit: edit `projectConfig.hooks`, or edit `verificationGates` and
|
|
126
|
+
add the same id to `selectedGateIds`, then rerun the bound dry-run. Human files use `mode: preserve`; explicit cross-unit shared
|
|
127
|
+
sources use `sourceScope: workspace`.
|
|
128
|
+
|
|
129
|
+
### Advanced schema reference—not the first-run path
|
|
130
|
+
|
|
131
|
+
The following wrapper documents the schema. Do not hand-write it during normal
|
|
132
|
+
setup; use the mechanically extracted `recommendedAnswers`.
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"projectConfig": {
|
|
137
|
+
"apiVersion": "release-skill/v1",
|
|
138
|
+
"kind": "ReleaseProject",
|
|
139
|
+
"project": { "name": "my-project", "defaultBranch": "main" },
|
|
140
|
+
"releaseUnits": [{
|
|
141
|
+
"id": "my-project",
|
|
142
|
+
"source": ".",
|
|
143
|
+
"publicRepo": "owner/my-project",
|
|
144
|
+
"version": { "source": "package.json", "tagTemplate": "v{version}" },
|
|
145
|
+
"distributions": [{
|
|
146
|
+
"type": "npm",
|
|
147
|
+
"package": "my-project",
|
|
148
|
+
"access": "public",
|
|
149
|
+
"provenance": false,
|
|
150
|
+
"tag": "latest",
|
|
151
|
+
"registry": "https://registry.npmjs.org",
|
|
152
|
+
"publisher": "my-npm-username"
|
|
153
|
+
}],
|
|
154
|
+
"publicFiles": [
|
|
155
|
+
{ "from": "README.md", "to": "README.md", "mode": "preserve" },
|
|
156
|
+
{ "from": "package.json", "to": "package.json", "mode": "preserve" }
|
|
157
|
+
],
|
|
158
|
+
"requiredPublicFiles": ["README.md", "package.json"],
|
|
159
|
+
"previousPublicBaseline": { "mode": "none" },
|
|
160
|
+
"production": {
|
|
161
|
+
"branchTemplate": "release/{tag}",
|
|
162
|
+
"branchStrategy": "create-release-branch"
|
|
163
|
+
}
|
|
164
|
+
}]
|
|
165
|
+
},
|
|
166
|
+
"selectedGateIds": []
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
This wrapper is reference data only. Normal setup uses the machine proposal;
|
|
171
|
+
`mode: none` is valid only when no public version exists. When a reviewed gate
|
|
172
|
+
is added incrementally, its id must exactly match `selectedGateIds`, and a
|
|
173
|
+
snapshot gate plus its dependencies must be present in `publicFiles`. See the
|
|
174
|
+
[README setup section](README.md#first-use-deterministic-setup-without-loading-the-full-report).
|
|
175
|
+
|
|
176
|
+
An existing config is never regenerated or overwritten. A project with no
|
|
177
|
+
discoverable GitHub/npm channel reports `LOCAL_ONLY_DETECTED` rather than
|
|
178
|
+
claiming production readiness.
|
|
179
|
+
|
|
180
|
+
The automatic create-once write uses the digest-registered `darwin-arm64`
|
|
181
|
+
native prebuild shipped in v0.1.3. Other platforms fail closed with
|
|
182
|
+
`SAFE_WRITE_UNAVAILABLE`; keep the dry-run report and create the reviewed file
|
|
183
|
+
manually instead of enabling an unsafe pathname fallback.
|
|
184
|
+
|
|
185
|
+
After the config exists, check release readiness:
|
|
65
186
|
|
|
66
187
|
```bash
|
|
67
188
|
"${CLI[@]}" assess --root /path/to/your/project --offline --json
|
|
@@ -139,12 +260,100 @@ hooks:
|
|
|
139
260
|
build:
|
|
140
261
|
command: [npm, run, build]
|
|
141
262
|
test:
|
|
142
|
-
command:
|
|
263
|
+
command:
|
|
264
|
+
- node
|
|
265
|
+
- -e
|
|
266
|
+
- "const p=require('./package.json'); if (!p.name) process.exit(1)"
|
|
143
267
|
```
|
|
144
268
|
|
|
145
269
|
See the [full README](README.md) for hook parameter constraints and safety
|
|
146
270
|
requirements.
|
|
147
271
|
|
|
272
|
+
### Advanced: verification gates (optional)
|
|
273
|
+
|
|
274
|
+
Use a `snapshot-verify` gate for checks that should run against a disposable
|
|
275
|
+
writable copy of the frozen public snapshot. Use `consumer-verify` for commands
|
|
276
|
+
that must run from an exact isolated npm/Claude/Codex installation root. Gate
|
|
277
|
+
commands are executable arrays, not shell strings, and must declare unit,
|
|
278
|
+
distribution when applicable, cwd, timeout, and environment allowlist.
|
|
279
|
+
|
|
280
|
+
```yaml
|
|
281
|
+
verificationGates:
|
|
282
|
+
- id: package-contract
|
|
283
|
+
phase: snapshot-verify
|
|
284
|
+
scope: { unit: my-project }
|
|
285
|
+
command: [node, -e, "const p=require('./package.json');if(!p.name)process.exit(1)"]
|
|
286
|
+
cwd: .
|
|
287
|
+
timeoutMs: 30000
|
|
288
|
+
envAllowlist: []
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
This self-contained example reads only a mapped public file. A replacement
|
|
292
|
+
script and every dependency it needs must exist in the frozen public snapshot;
|
|
293
|
+
the gate cannot borrow tests, development dependencies, or `node_modules` from
|
|
294
|
+
the parent workspace.
|
|
295
|
+
|
|
296
|
+
Prepare and verify require `--acknowledge-gate-side-effects` whenever their
|
|
297
|
+
planned phase contains gates. Hooks and gates are project processes without a
|
|
298
|
+
network sandbox; release-skill limits their inputs and evidence but cannot
|
|
299
|
+
guarantee that a custom command will not modify files or access the network.
|
|
300
|
+
Never register Git push, tag, default-branch changes, GitHub Releases, or npm
|
|
301
|
+
publish as a hook/gate; those are controlled plan actions.
|
|
302
|
+
|
|
303
|
+
### Production branch strategy
|
|
304
|
+
|
|
305
|
+
Every production unit selects one explicit strategy:
|
|
306
|
+
|
|
307
|
+
- `create-release-branch` creates an absent immutable release branch;
|
|
308
|
+
- `advance-existing-branch` fast-forwards an existing branch from the exact
|
|
309
|
+
bound public baseline using an ordinary non-force push;
|
|
310
|
+
- `initialize-default-branch` creates an absent standard branch and may add an
|
|
311
|
+
explicit default-branch action only when `setAsDefaultBranch` and
|
|
312
|
+
`expectedCurrentDefaultBranch` are both reviewed.
|
|
313
|
+
|
|
314
|
+
Remote drift, a non-fast-forward update, or an unexpected default branch stops
|
|
315
|
+
for human intervention. No strategy overwrites remote history. Create-only refs
|
|
316
|
+
use `--force-with-lease=<ref>:` solely as an atomic absence assertion; advancing
|
|
317
|
+
an existing branch uses an ordinary non-force push.
|
|
318
|
+
|
|
319
|
+
```yaml
|
|
320
|
+
# create-release-branch: target must be absent
|
|
321
|
+
previousPublicBaseline: { mode: none } # true first public release only
|
|
322
|
+
production:
|
|
323
|
+
branchTemplate: release/{tag}
|
|
324
|
+
branchStrategy: create-release-branch
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
```yaml
|
|
328
|
+
# advance-existing-branch: ref must exactly equal refs/heads/<target>
|
|
329
|
+
previousPublicBaseline:
|
|
330
|
+
mode: bound
|
|
331
|
+
repo: owner/my-project
|
|
332
|
+
ref: refs/heads/main
|
|
333
|
+
commit: 0123456789abcdef0123456789abcdef01234567
|
|
334
|
+
production:
|
|
335
|
+
branchTemplate: main
|
|
336
|
+
branchStrategy: advance-existing-branch
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
```yaml
|
|
340
|
+
# initialize-default-branch: main must be absent; current default must match
|
|
341
|
+
previousPublicBaseline:
|
|
342
|
+
mode: bound
|
|
343
|
+
repo: owner/my-project
|
|
344
|
+
ref: refs/heads/old-public-branch
|
|
345
|
+
commit: 0123456789abcdef0123456789abcdef01234567
|
|
346
|
+
production:
|
|
347
|
+
branchTemplate: main
|
|
348
|
+
branchStrategy: initialize-default-branch
|
|
349
|
+
setAsDefaultBranch: true
|
|
350
|
+
expectedCurrentDefaultBranch: old-public-branch
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
The last two strategies require online production prepare. Any mismatch stops
|
|
354
|
+
for review; update the human-owned config only after inspecting real remote
|
|
355
|
+
state, and never force-push or weaken the baseline.
|
|
356
|
+
|
|
148
357
|
## Protect Human-Owned Content
|
|
149
358
|
|
|
150
359
|
README text, slogans, examples, layout, and other manually curated source files
|
|
@@ -167,6 +376,8 @@ When an existing public copy has drifted, choose explicitly:
|
|
|
167
376
|
## Next Steps
|
|
168
377
|
|
|
169
378
|
- Read the [full README](README.md) for the complete workflow guide.
|
|
379
|
+
- Run `"${CLI[@]}" setup --root <your-project> --json` when the project has no
|
|
380
|
+
configuration; keep its default dry-run behavior until human decisions are complete.
|
|
170
381
|
- Run `"${CLI[@]}" assess --root <your-project> --offline` to evaluate your project's release readiness.
|
|
171
382
|
- Run `"${CLI[@]}" prepare --root <your-project> --offline` (release-skill pipeline writes
|
|
172
383
|
locally only; user-configured hooks may perform remote operations) to generate
|