bigpowers 2.34.1 → 2.34.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.
- package/.pi/package.json +2 -2
- package/.pi/prompts/deploy.md +53 -28
- package/.pi/prompts/develop-tdd.md +5 -80
- package/.pi/prompts/migrate-spec.md +273 -197
- package/.pi/prompts/publish-package.md +125 -67
- package/.pi/prompts/release-branch.md +85 -69
- package/.pi/prompts/smoke-test.md +98 -58
- package/.pi/prompts/using-bigpowers.md +2 -2
- package/.pi/prompts/validate-contracts.md +169 -54
- package/.pi/prompts/wire-ci.md +147 -89
- package/.pi/skills/deploy/SKILL.md +53 -28
- package/.pi/skills/develop-tdd/SKILL.md +5 -80
- package/.pi/skills/migrate-spec/SKILL.md +273 -197
- package/.pi/skills/publish-package/SKILL.md +125 -67
- package/.pi/skills/release-branch/SKILL.md +85 -69
- package/.pi/skills/smoke-test/SKILL.md +98 -58
- package/.pi/skills/using-bigpowers/SKILL.md +2 -2
- package/.pi/skills/validate-contracts/SKILL.md +169 -54
- package/.pi/skills/wire-ci/SKILL.md +147 -89
- package/CHANGELOG.md +7 -0
- package/README.md +4 -4
- package/SKILL-INDEX.md +1 -1
- package/deploy/REFERENCE.md +82 -0
- package/deploy/SKILL.md +3 -63
- package/develop-tdd/SKILL.md +5 -80
- package/migrate-spec/REFERENCE.md +268 -0
- package/migrate-spec/SKILL.md +5 -199
- package/package.json +2 -2
- package/publish-package/REFERENCE.md +239 -0
- package/publish-package/SKILL.md +8 -192
- package/release-branch/REFERENCE.md +83 -0
- package/release-branch/SKILL.md +2 -69
- package/scripts/generate-reference-tables.sh +1 -0
- package/scripts/sync-skills.sh +4 -1
- package/skills-lock.json +9 -9
- package/smoke-test/REFERENCE.md +162 -0
- package/smoke-test/SKILL.md +5 -130
- package/using-bigpowers/SKILL.md +2 -2
- package/validate-contracts/REFERENCE.md +183 -0
- package/validate-contracts/SKILL.md +6 -77
- package/wire-ci/REFERENCE.md +257 -0
- package/wire-ci/SKILL.md +8 -210
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bigpowers",
|
|
3
|
-
"version": "2.34.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.34.2",
|
|
4
|
+
"description": "70 agent skills for spec-driven, test-first software development by solo developers",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"compliance": "bash scripts/audit-compliance.sh specs/verifications/features && bash scripts/validate-doctrine.sh",
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# Publish Package — Reference
|
|
2
|
+
|
|
3
|
+
## Options
|
|
4
|
+
|
|
5
|
+
| Flag | Description |
|
|
6
|
+
|------|-------------|
|
|
7
|
+
| `--dry-run` | Verify prerequisites and show publish command without executing |
|
|
8
|
+
| `--registry <type>` | Force registry type (skip auto-detection) |
|
|
9
|
+
| `--otp <code>` | One-time password for npm 2FA |
|
|
10
|
+
| `--no-verify` | Skip prerequisite checks (use with caution) |
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Examples
|
|
16
|
+
|
|
17
|
+
### Publish an npm package
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Verify first
|
|
21
|
+
publish-package --dry-run
|
|
22
|
+
|
|
23
|
+
# Publish
|
|
24
|
+
publish-package
|
|
25
|
+
|
|
26
|
+
# Output:
|
|
27
|
+
# [npm] Publishing my-package v0.4.0...
|
|
28
|
+
# OK: npm publish confirmed (my-package@0.4.0 on registry)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Publish a Rust crate
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
export CARGO_REGISTRY_TOKEN=<token>
|
|
35
|
+
publish-package --dry-run
|
|
36
|
+
publish-package
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Missing token scenario
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
$ publish-package
|
|
43
|
+
FAIL: NPM_TOKEN not set. Set via: export NPM_TOKEN=<token> or add to .npmrc
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Integration with release-branch
|
|
50
|
+
|
|
51
|
+
When wired into `release-branch`, add a step after git push:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
6a. Run publish-package to publish to package registries
|
|
55
|
+
→ verify: publish-package --dry-run && publish-package
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Reference block 1
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Check auth token exists
|
|
64
|
+
if [ -z "${NPM_TOKEN:-}" ]; then
|
|
65
|
+
if [ ! -f ~/.npmrc ] || ! grep -q "_authToken" ~/.npmrc; then
|
|
66
|
+
echo "FAIL: NPM_TOKEN not set. Set via: export NPM_TOKEN=<token> or add //registry.npmjs.org/:_authToken=<token> to .npmrc"
|
|
67
|
+
exit 1
|
|
68
|
+
fi
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# Check version not already published
|
|
72
|
+
PACKAGE_NAME=$(node -p "require('./package.json').name")
|
|
73
|
+
CURRENT_VER=$(node -p "require('./package.json').version")
|
|
74
|
+
if npm view "$PACKAGE_NAME@$CURRENT_VER" version 2>/dev/null; then
|
|
75
|
+
echo "FAIL: Version $CURRENT_VER already published for $PACKAGE_NAME. Bump version first."
|
|
76
|
+
exit 1
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# Check build artifacts are fresh
|
|
80
|
+
if [ -d dist ] || [ -d lib ]; then
|
|
81
|
+
LATEST_BUILD=$(find dist lib 2>/dev/null -name "*.js" -o -name "*.cjs" -o -name "*.mjs" | xargs ls -t 2>/dev/null | head -1)
|
|
82
|
+
PACKAGE_MODIFIED=$(stat -f %m package.json 2>/dev/null || stat -c %Y package.json 2>/dev/null)
|
|
83
|
+
if [ -n "$LATEST_BUILD" ] && [ -n "$PACKAGE_MODIFIED" ]; then
|
|
84
|
+
BUILD_TIME=$(stat -f %m "$LATEST_BUILD" 2>/dev/null || stat -c %Y "$LATEST_BUILD" 2>/dev/null)
|
|
85
|
+
if [ "$BUILD_TIME" -lt "$PACKAGE_MODIFIED" ]; then
|
|
86
|
+
echo "WARNING: Build artifacts may be stale (package.json modified after last build). Run npm run build first."
|
|
87
|
+
fi
|
|
88
|
+
fi
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# Check CHANGELOG is updated
|
|
92
|
+
if [ -f CHANGELOG.md ]; then
|
|
93
|
+
if ! grep -q "$CURRENT_VER" CHANGELOG.md 2>/dev/null; then
|
|
94
|
+
echo "WARNING: Version $CURRENT_VER not found in CHANGELOG.md. Update changelog before publish."
|
|
95
|
+
fi
|
|
96
|
+
fi
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Reference block 2
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Check auth token exists
|
|
105
|
+
if [ -z "${CARGO_REGISTRY_TOKEN:-}" ]; then
|
|
106
|
+
if [ ! -f ~/.cargo/config.toml ] || ! grep -q "token" ~/.cargo/config.toml; then
|
|
107
|
+
echo "FAIL: CARGO_REGISTRY_TOKEN not set. Set via: export CARGO_REGISTRY_TOKEN=<token> or add to ~/.cargo/config.toml"
|
|
108
|
+
exit 1
|
|
109
|
+
fi
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
# Check version not already published
|
|
113
|
+
CRATE_NAME=$(grep '^name' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')
|
|
114
|
+
CURRENT_VER=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')
|
|
115
|
+
if cargo search "$CRATE_NAME" 2>/dev/null | grep -q "^${CRATE_NAME}.*\"$CURRENT_VER\""; then
|
|
116
|
+
echo "FAIL: Version $CURRENT_VER already published for $CRATE_NAME. Bump version in Cargo.toml first."
|
|
117
|
+
exit 1
|
|
118
|
+
fi
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Reference block 3
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Check auth token exists
|
|
127
|
+
if [ -z "${TWINE_PASSWORD:-}" ] && [ -z "${POETRY_PYPI_TOKEN_PYPI:-}" ]; then
|
|
128
|
+
if [ ! -f ~/.pypirc ]; then
|
|
129
|
+
echo "FAIL: PyPI token not configured. Set TWINE_PASSWORD or create ~/.pypirc"
|
|
130
|
+
exit 1
|
|
131
|
+
fi
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
# Check for build artifacts
|
|
135
|
+
if [ ! -d dist ] || [ -z "$(ls dist/*.whl 2>/dev/null)" ]; then
|
|
136
|
+
echo "WARNING: No .whl files found in dist/. Run: python -m build"
|
|
137
|
+
fi
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Reference block 4
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# npm
|
|
146
|
+
npm publish --access public
|
|
147
|
+
|
|
148
|
+
# crates.io
|
|
149
|
+
cargo publish
|
|
150
|
+
|
|
151
|
+
# PyPI
|
|
152
|
+
python -m twine upload dist/* # or: poetry publish
|
|
153
|
+
|
|
154
|
+
# Homebrew (opens PR, does not publish directly)
|
|
155
|
+
brew bump-formula-pr --url=<tarball-url> <formula-name>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Reference block 5
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# npm
|
|
164
|
+
npm view "$PACKAGE_NAME" versions --json 2>/dev/null | grep -q "\"$CURRENT_VER\"" && echo "OK: npm publish confirmed"
|
|
165
|
+
|
|
166
|
+
# crates.io
|
|
167
|
+
cargo search "$CRATE_NAME" 2>/dev/null | grep -q "^${CRATE_NAME}.*\"$CURRENT_VER\"" && echo "OK: crates.io publish confirmed"
|
|
168
|
+
|
|
169
|
+
# PyPI
|
|
170
|
+
pip index versions "$PACKAGE_NAME" 2>/dev/null | grep -q "$CURRENT_VER" && echo "OK: PyPI publish confirmed"
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Reference block 6
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Generic failure handler
|
|
179
|
+
if [ $? -ne 0 ]; then
|
|
180
|
+
case "$REGISTRY" in
|
|
181
|
+
npm)
|
|
182
|
+
echo "FAIL: npm publish failed."
|
|
183
|
+
echo " Common causes:"
|
|
184
|
+
echo " - NPM_TOKEN not set in secrets: add to GitHub repo secrets"
|
|
185
|
+
echo " - Version already published: bump version in package.json"
|
|
186
|
+
echo " - Two-factor auth required: use --otp=<code> flag"
|
|
187
|
+
echo " - Package scoped but not public: add --access public"
|
|
188
|
+
;;
|
|
189
|
+
crates.io)
|
|
190
|
+
echo "FAIL: cargo publish failed."
|
|
191
|
+
echo " Common causes:"
|
|
192
|
+
echo " - CARGO_REGISTRY_TOKEN not configured: see ~/.cargo/config.toml"
|
|
193
|
+
echo " - Version already published: bump version in Cargo.toml"
|
|
194
|
+
echo " - Local changes not committed: cargo publish requires clean working tree"
|
|
195
|
+
;;
|
|
196
|
+
pypi)
|
|
197
|
+
echo "FAIL: PyPI publish failed."
|
|
198
|
+
echo " Common causes:"
|
|
199
|
+
echo " - TWINE_PASSWORD not configured: set env var or ~/.pypirc"
|
|
200
|
+
echo " - Build artifacts missing: run python -m build first"
|
|
201
|
+
echo " - Version conflict: version already exists on PyPI"
|
|
202
|
+
;;
|
|
203
|
+
esac
|
|
204
|
+
exit 1
|
|
205
|
+
fi
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Reference block 7
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
# Example output
|
|
214
|
+
$ publish-package --dry-run
|
|
215
|
+
|
|
216
|
+
[DRY-RUN] Detected package type: npm
|
|
217
|
+
[DRY-RUN] Package: my-package v0.4.0
|
|
218
|
+
[DRY-RUN] Checking NPM_TOKEN... OK
|
|
219
|
+
[DRY-RUN] Checking version 0.4.0 not already published... OK
|
|
220
|
+
[DRY-RUN] Checking build artifacts... WARNING: package.json modified after build
|
|
221
|
+
[DRY-RUN] Checking CHANGELOG... OK
|
|
222
|
+
[DRY-RUN] Would run: npm publish --access public
|
|
223
|
+
[DRY-RUN] Exiting without publishing.
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Reference block 8
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# npm dry-run
|
|
232
|
+
npm publish --access public --dry-run
|
|
233
|
+
|
|
234
|
+
# crates.io dry-run (cargo does not have a publish dry-run; use --dry-run flag for validation only)
|
|
235
|
+
cargo package --list 2>/dev/null
|
|
236
|
+
|
|
237
|
+
# PyPI dry-run
|
|
238
|
+
python -m twine upload --repository testpypi dist/* # test.pypi.org
|
|
239
|
+
```
|
package/publish-package/SKILL.md
CHANGED
|
@@ -33,225 +33,41 @@ If no manifest is found, prompt the user to specify the type or pass `--type <np
|
|
|
33
33
|
Before attempting any publish, run all applicable checks:
|
|
34
34
|
|
|
35
35
|
**npm (`package.json`):**
|
|
36
|
-
|
|
37
|
-
# Check auth token exists
|
|
38
|
-
if [ -z "${NPM_TOKEN:-}" ]; then
|
|
39
|
-
if [ ! -f ~/.npmrc ] || ! grep -q "_authToken" ~/.npmrc; then
|
|
40
|
-
echo "FAIL: NPM_TOKEN not set. Set via: export NPM_TOKEN=<token> or add //registry.npmjs.org/:_authToken=<token> to .npmrc"
|
|
41
|
-
exit 1
|
|
42
|
-
fi
|
|
43
|
-
fi
|
|
44
|
-
|
|
45
|
-
# Check version not already published
|
|
46
|
-
PACKAGE_NAME=$(node -p "require('./package.json').name")
|
|
47
|
-
CURRENT_VER=$(node -p "require('./package.json').version")
|
|
48
|
-
if npm view "$PACKAGE_NAME@$CURRENT_VER" version 2>/dev/null; then
|
|
49
|
-
echo "FAIL: Version $CURRENT_VER already published for $PACKAGE_NAME. Bump version first."
|
|
50
|
-
exit 1
|
|
51
|
-
fi
|
|
52
|
-
|
|
53
|
-
# Check build artifacts are fresh
|
|
54
|
-
if [ -d dist ] || [ -d lib ]; then
|
|
55
|
-
LATEST_BUILD=$(find dist lib 2>/dev/null -name "*.js" -o -name "*.cjs" -o -name "*.mjs" | xargs ls -t 2>/dev/null | head -1)
|
|
56
|
-
PACKAGE_MODIFIED=$(stat -f %m package.json 2>/dev/null || stat -c %Y package.json 2>/dev/null)
|
|
57
|
-
if [ -n "$LATEST_BUILD" ] && [ -n "$PACKAGE_MODIFIED" ]; then
|
|
58
|
-
BUILD_TIME=$(stat -f %m "$LATEST_BUILD" 2>/dev/null || stat -c %Y "$LATEST_BUILD" 2>/dev/null)
|
|
59
|
-
if [ "$BUILD_TIME" -lt "$PACKAGE_MODIFIED" ]; then
|
|
60
|
-
echo "WARNING: Build artifacts may be stale (package.json modified after last build). Run npm run build first."
|
|
61
|
-
fi
|
|
62
|
-
fi
|
|
63
|
-
fi
|
|
64
|
-
|
|
65
|
-
# Check CHANGELOG is updated
|
|
66
|
-
if [ -f CHANGELOG.md ]; then
|
|
67
|
-
if ! grep -q "$CURRENT_VER" CHANGELOG.md 2>/dev/null; then
|
|
68
|
-
echo "WARNING: Version $CURRENT_VER not found in CHANGELOG.md. Update changelog before publish."
|
|
69
|
-
fi
|
|
70
|
-
fi
|
|
71
|
-
```
|
|
36
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
72
37
|
|
|
73
38
|
**crates.io (`Cargo.toml`):**
|
|
74
|
-
|
|
75
|
-
# Check auth token exists
|
|
76
|
-
if [ -z "${CARGO_REGISTRY_TOKEN:-}" ]; then
|
|
77
|
-
if [ ! -f ~/.cargo/config.toml ] || ! grep -q "token" ~/.cargo/config.toml; then
|
|
78
|
-
echo "FAIL: CARGO_REGISTRY_TOKEN not set. Set via: export CARGO_REGISTRY_TOKEN=<token> or add to ~/.cargo/config.toml"
|
|
79
|
-
exit 1
|
|
80
|
-
fi
|
|
81
|
-
fi
|
|
82
|
-
|
|
83
|
-
# Check version not already published
|
|
84
|
-
CRATE_NAME=$(grep '^name' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')
|
|
85
|
-
CURRENT_VER=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')
|
|
86
|
-
if cargo search "$CRATE_NAME" 2>/dev/null | grep -q "^${CRATE_NAME}.*\"$CURRENT_VER\""; then
|
|
87
|
-
echo "FAIL: Version $CURRENT_VER already published for $CRATE_NAME. Bump version in Cargo.toml first."
|
|
88
|
-
exit 1
|
|
89
|
-
fi
|
|
90
|
-
```
|
|
39
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
91
40
|
|
|
92
41
|
**PyPI (`setup.py` / `pyproject.toml`):**
|
|
93
|
-
|
|
94
|
-
# Check auth token exists
|
|
95
|
-
if [ -z "${TWINE_PASSWORD:-}" ] && [ -z "${POETRY_PYPI_TOKEN_PYPI:-}" ]; then
|
|
96
|
-
if [ ! -f ~/.pypirc ]; then
|
|
97
|
-
echo "FAIL: PyPI token not configured. Set TWINE_PASSWORD or create ~/.pypirc"
|
|
98
|
-
exit 1
|
|
99
|
-
fi
|
|
100
|
-
fi
|
|
101
|
-
|
|
102
|
-
# Check for build artifacts
|
|
103
|
-
if [ ! -d dist ] || [ -z "$(ls dist/*.whl 2>/dev/null)" ]; then
|
|
104
|
-
echo "WARNING: No .whl files found in dist/. Run: python -m build"
|
|
105
|
-
fi
|
|
106
|
-
```
|
|
42
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
107
43
|
|
|
108
44
|
### 3. Run publish
|
|
109
45
|
|
|
110
46
|
After all prerequisite checks pass, run the registry-specific command:
|
|
111
47
|
|
|
112
|
-
|
|
113
|
-
# npm
|
|
114
|
-
npm publish --access public
|
|
115
|
-
|
|
116
|
-
# crates.io
|
|
117
|
-
cargo publish
|
|
118
|
-
|
|
119
|
-
# PyPI
|
|
120
|
-
python -m twine upload dist/* # or: poetry publish
|
|
121
|
-
|
|
122
|
-
# Homebrew (opens PR, does not publish directly)
|
|
123
|
-
brew bump-formula-pr --url=<tarball-url> <formula-name>
|
|
124
|
-
```
|
|
48
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
125
49
|
|
|
126
50
|
### 4. Verify publish success
|
|
127
51
|
|
|
128
52
|
After publish, confirm the version appears on the registry:
|
|
129
53
|
|
|
130
|
-
|
|
131
|
-
# npm
|
|
132
|
-
npm view "$PACKAGE_NAME" versions --json 2>/dev/null | grep -q "\"$CURRENT_VER\"" && echo "OK: npm publish confirmed"
|
|
133
|
-
|
|
134
|
-
# crates.io
|
|
135
|
-
cargo search "$CRATE_NAME" 2>/dev/null | grep -q "^${CRATE_NAME}.*\"$CURRENT_VER\"" && echo "OK: crates.io publish confirmed"
|
|
136
|
-
|
|
137
|
-
# PyPI
|
|
138
|
-
pip index versions "$PACKAGE_NAME" 2>/dev/null | grep -q "$CURRENT_VER" && echo "OK: PyPI publish confirmed"
|
|
139
|
-
```
|
|
54
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
140
55
|
|
|
141
56
|
### 5. Error handling
|
|
142
57
|
|
|
143
58
|
On failure, surface actionable hints:
|
|
144
59
|
|
|
145
|
-
|
|
146
|
-
# Generic failure handler
|
|
147
|
-
if [ $? -ne 0 ]; then
|
|
148
|
-
case "$REGISTRY" in
|
|
149
|
-
npm)
|
|
150
|
-
echo "FAIL: npm publish failed."
|
|
151
|
-
echo " Common causes:"
|
|
152
|
-
echo " - NPM_TOKEN not set in secrets: add to GitHub repo secrets"
|
|
153
|
-
echo " - Version already published: bump version in package.json"
|
|
154
|
-
echo " - Two-factor auth required: use --otp=<code> flag"
|
|
155
|
-
echo " - Package scoped but not public: add --access public"
|
|
156
|
-
;;
|
|
157
|
-
crates.io)
|
|
158
|
-
echo "FAIL: cargo publish failed."
|
|
159
|
-
echo " Common causes:"
|
|
160
|
-
echo " - CARGO_REGISTRY_TOKEN not configured: see ~/.cargo/config.toml"
|
|
161
|
-
echo " - Version already published: bump version in Cargo.toml"
|
|
162
|
-
echo " - Local changes not committed: cargo publish requires clean working tree"
|
|
163
|
-
;;
|
|
164
|
-
pypi)
|
|
165
|
-
echo "FAIL: PyPI publish failed."
|
|
166
|
-
echo " Common causes:"
|
|
167
|
-
echo " - TWINE_PASSWORD not configured: set env var or ~/.pypirc"
|
|
168
|
-
echo " - Build artifacts missing: run python -m build first"
|
|
169
|
-
echo " - Version conflict: version already exists on PyPI"
|
|
170
|
-
;;
|
|
171
|
-
esac
|
|
172
|
-
exit 1
|
|
173
|
-
fi
|
|
174
|
-
```
|
|
60
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
175
61
|
|
|
176
62
|
### 6. Dry-run mode (`--dry-run`)
|
|
177
63
|
|
|
178
64
|
Run `--dry-run` to verify all prerequisites without actually publishing:
|
|
179
65
|
|
|
180
|
-
|
|
181
|
-
# Example output
|
|
182
|
-
$ publish-package --dry-run
|
|
183
|
-
|
|
184
|
-
[DRY-RUN] Detected package type: npm
|
|
185
|
-
[DRY-RUN] Package: my-package v0.4.0
|
|
186
|
-
[DRY-RUN] Checking NPM_TOKEN... OK
|
|
187
|
-
[DRY-RUN] Checking version 0.4.0 not already published... OK
|
|
188
|
-
[DRY-RUN] Checking build artifacts... WARNING: package.json modified after build
|
|
189
|
-
[DRY-RUN] Checking CHANGELOG... OK
|
|
190
|
-
[DRY-RUN] Would run: npm publish --access public
|
|
191
|
-
[DRY-RUN] Exiting without publishing.
|
|
192
|
-
```
|
|
66
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
193
67
|
|
|
194
68
|
### 7. Dry-run mode per registry
|
|
195
69
|
|
|
196
|
-
|
|
197
|
-
# npm dry-run
|
|
198
|
-
npm publish --access public --dry-run
|
|
199
|
-
|
|
200
|
-
# crates.io dry-run (cargo does not have a publish dry-run; use --dry-run flag for validation only)
|
|
201
|
-
cargo package --list 2>/dev/null
|
|
202
|
-
|
|
203
|
-
# PyPI dry-run
|
|
204
|
-
python -m twine upload --repository testpypi dist/* # test.pypi.org
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
## Options
|
|
208
|
-
|
|
209
|
-
| Flag | Description |
|
|
210
|
-
|------|-------------|
|
|
211
|
-
| `--dry-run` | Verify prerequisites and show publish command without executing |
|
|
212
|
-
| `--registry <type>` | Force registry type (skip auto-detection) |
|
|
213
|
-
| `--otp <code>` | One-time password for npm 2FA |
|
|
214
|
-
| `--no-verify` | Skip prerequisite checks (use with caution) |
|
|
215
|
-
|
|
216
|
-
## Examples
|
|
217
|
-
|
|
218
|
-
### Publish an npm package
|
|
219
|
-
|
|
220
|
-
```bash
|
|
221
|
-
# Verify first
|
|
222
|
-
publish-package --dry-run
|
|
223
|
-
|
|
224
|
-
# Publish
|
|
225
|
-
publish-package
|
|
226
|
-
|
|
227
|
-
# Output:
|
|
228
|
-
# [npm] Publishing my-package v0.4.0...
|
|
229
|
-
# OK: npm publish confirmed (my-package@0.4.0 on registry)
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
### Publish a Rust crate
|
|
233
|
-
|
|
234
|
-
```bash
|
|
235
|
-
export CARGO_REGISTRY_TOKEN=<token>
|
|
236
|
-
publish-package --dry-run
|
|
237
|
-
publish-package
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
### Missing token scenario
|
|
241
|
-
|
|
242
|
-
```bash
|
|
243
|
-
$ publish-package
|
|
244
|
-
FAIL: NPM_TOKEN not set. Set via: export NPM_TOKEN=<token> or add to .npmrc
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
## Integration with release-branch
|
|
248
|
-
|
|
249
|
-
When wired into `release-branch`, add a step after git push:
|
|
250
|
-
|
|
251
|
-
```
|
|
252
|
-
6a. Run publish-package to publish to package registries
|
|
253
|
-
→ verify: publish-package --dry-run && publish-package
|
|
254
|
-
```
|
|
70
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
255
71
|
|
|
256
72
|
## Verify
|
|
257
73
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Release Branch — Reference
|
|
2
2
|
|
|
3
|
+
# Release Branch — Reference
|
|
4
|
+
|
|
3
5
|
## PR body template (team-pr mode)
|
|
4
6
|
|
|
5
7
|
```bash
|
|
@@ -53,3 +55,84 @@ After landing the branch, record delivery metrics for this story:
|
|
|
53
55
|
cycle_minutes: 90
|
|
54
56
|
bcp_per_hour: 2.0
|
|
55
57
|
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Solo-local fallback detail
|
|
62
|
+
|
|
63
|
+
The fallback sequence (Path B above) handles the "remote has moved" case with `git pull --rebase`. Use when `scripts/land-branch.sh` is absent.
|
|
64
|
+
|
|
65
|
+
**Acceptance:** When fallback runs, main is updated, feature branch is deleted locally, and output states `"used fallback merge (land-branch.sh not found)"`.
|
|
66
|
+
|
|
67
|
+
## Handoff
|
|
68
|
+
|
|
69
|
+
Gate: READY -> next: survey-context
|
|
70
|
+
Writes: state.yaml handoff.next_skill = survey-context
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Reference block 1
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Fallback: manual squash-merge when land-branch.sh is absent
|
|
78
|
+
FEATURE_BRANCH=<task-slug>
|
|
79
|
+
DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' || echo main)
|
|
80
|
+
|
|
81
|
+
# Ensure we're on the feature branch
|
|
82
|
+
if [ "$(git branch --show-current)" != "$FEATURE_BRANCH" ]; then
|
|
83
|
+
git checkout "$FEATURE_BRANCH"
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# Checkout default branch and update
|
|
87
|
+
git checkout "$DEFAULT_BRANCH"
|
|
88
|
+
git pull --rebase origin "$DEFAULT_BRANCH" 2>/dev/null || git pull origin "$DEFAULT_BRANCH"
|
|
89
|
+
|
|
90
|
+
# Squash-merge the feature branch
|
|
91
|
+
git merge --no-ff "$FEATURE_BRANCH" -m "<conventional-commit-message>"
|
|
92
|
+
|
|
93
|
+
# Push
|
|
94
|
+
git push origin "$DEFAULT_BRANCH"
|
|
95
|
+
|
|
96
|
+
# Clean up local feature branch
|
|
97
|
+
git branch -d "$FEATURE_BRANCH"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Reference block 2
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
echo "==> Polling CI for main branch..."
|
|
106
|
+
TIMEOUT=600 # 10 minutes
|
|
107
|
+
INTERVAL=30 # poll every 30 seconds
|
|
108
|
+
ELAPSED=0
|
|
109
|
+
|
|
110
|
+
while [ $ELAPSED -lt $TIMEOUT ]; do
|
|
111
|
+
CI_JSON=$(gh run list --limit 1 --branch main --workflow CI --json status,conclusion,headSha,databaseId 2>/dev/null)
|
|
112
|
+
CI_STATUS=$(echo "$CI_JSON" | jq -r '.[0].status // "unknown"')
|
|
113
|
+
CI_CONCLUSION=$(echo "$CI_JSON" | jq -r '.[0].conclusion // ""')
|
|
114
|
+
CI_SHA=$(echo "$CI_JSON" | jq -r '.[0].headSha // ""')
|
|
115
|
+
CI_ID=$(echo "$CI_JSON" | jq -r '.[0].databaseId // ""')
|
|
116
|
+
|
|
117
|
+
if [ "$CI_STATUS" = "completed" ] && [ "$CI_CONCLUSION" = "success" ]; then
|
|
118
|
+
echo "OK: CI passed for $(git rev-parse --short HEAD)"
|
|
119
|
+
bp-yaml-set.sh specs/state.yaml release.ci_verified true 2>/dev/null || \
|
|
120
|
+
echo " (bp-yaml-set not available — manually set release.ci_verified: true in state.yaml)"
|
|
121
|
+
break
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
if [ "$CI_STATUS" = "completed" ] && [ "$CI_CONCLUSION" = "failure" ]; then
|
|
125
|
+
echo "FAIL: CI failed for $(git rev-parse --short HEAD)"
|
|
126
|
+
echo " Run URL: https://github.com/$(gh repo view --json nameWithOwner -q .nameWithOwner)/actions/runs/$CI_ID"
|
|
127
|
+
echo " Handoff to fix-bug with the failure URL above."
|
|
128
|
+
return 1
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
sleep $INTERVAL
|
|
132
|
+
ELAPSED=$((ELAPSED + INTERVAL))
|
|
133
|
+
echo " Waiting... (${ELAPSED}s / ${TIMEOUT}s)"
|
|
134
|
+
done
|
|
135
|
+
|
|
136
|
+
echo "FAIL: CI did not complete within ${TIMEOUT}s timeout"
|
|
137
|
+
return 1
|
|
138
|
+
```
|
package/release-branch/SKILL.md
CHANGED
|
@@ -63,29 +63,7 @@ bash scripts/land-branch.sh <task-slug> "feat(scope): description"
|
|
|
63
63
|
```
|
|
64
64
|
|
|
65
65
|
**Path B — `scripts/land-branch.sh` missing (fallback):**
|
|
66
|
-
|
|
67
|
-
# Fallback: manual squash-merge when land-branch.sh is absent
|
|
68
|
-
FEATURE_BRANCH=<task-slug>
|
|
69
|
-
DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' || echo main)
|
|
70
|
-
|
|
71
|
-
# Ensure we're on the feature branch
|
|
72
|
-
if [ "$(git branch --show-current)" != "$FEATURE_BRANCH" ]; then
|
|
73
|
-
git checkout "$FEATURE_BRANCH"
|
|
74
|
-
fi
|
|
75
|
-
|
|
76
|
-
# Checkout default branch and update
|
|
77
|
-
git checkout "$DEFAULT_BRANCH"
|
|
78
|
-
git pull --rebase origin "$DEFAULT_BRANCH" 2>/dev/null || git pull origin "$DEFAULT_BRANCH"
|
|
79
|
-
|
|
80
|
-
# Squash-merge the feature branch
|
|
81
|
-
git merge --no-ff "$FEATURE_BRANCH" -m "<conventional-commit-message>"
|
|
82
|
-
|
|
83
|
-
# Push
|
|
84
|
-
git push origin "$DEFAULT_BRANCH"
|
|
85
|
-
|
|
86
|
-
# Clean up local feature branch
|
|
87
|
-
git branch -d "$FEATURE_BRANCH"
|
|
88
|
-
```
|
|
66
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
89
67
|
|
|
90
68
|
**Report which path was taken.** Print exactly:
|
|
91
69
|
- `"used land-branch.sh"` if Path A
|
|
@@ -117,41 +95,7 @@ mv specs/epics/eNN-slug specs/epics/archive/
|
|
|
117
95
|
|
|
118
96
|
After push (solo-local step 5 or team-pr step 7), verify the CI workflow completes successfully:
|
|
119
97
|
|
|
120
|
-
|
|
121
|
-
echo "==> Polling CI for main branch..."
|
|
122
|
-
TIMEOUT=600 # 10 minutes
|
|
123
|
-
INTERVAL=30 # poll every 30 seconds
|
|
124
|
-
ELAPSED=0
|
|
125
|
-
|
|
126
|
-
while [ $ELAPSED -lt $TIMEOUT ]; do
|
|
127
|
-
CI_JSON=$(gh run list --limit 1 --branch main --workflow CI --json status,conclusion,headSha,databaseId 2>/dev/null)
|
|
128
|
-
CI_STATUS=$(echo "$CI_JSON" | jq -r '.[0].status // "unknown"')
|
|
129
|
-
CI_CONCLUSION=$(echo "$CI_JSON" | jq -r '.[0].conclusion // ""')
|
|
130
|
-
CI_SHA=$(echo "$CI_JSON" | jq -r '.[0].headSha // ""')
|
|
131
|
-
CI_ID=$(echo "$CI_JSON" | jq -r '.[0].databaseId // ""')
|
|
132
|
-
|
|
133
|
-
if [ "$CI_STATUS" = "completed" ] && [ "$CI_CONCLUSION" = "success" ]; then
|
|
134
|
-
echo "OK: CI passed for $(git rev-parse --short HEAD)"
|
|
135
|
-
bp-yaml-set.sh specs/state.yaml release.ci_verified true 2>/dev/null || \
|
|
136
|
-
echo " (bp-yaml-set not available — manually set release.ci_verified: true in state.yaml)"
|
|
137
|
-
break
|
|
138
|
-
fi
|
|
139
|
-
|
|
140
|
-
if [ "$CI_STATUS" = "completed" ] && [ "$CI_CONCLUSION" = "failure" ]; then
|
|
141
|
-
echo "FAIL: CI failed for $(git rev-parse --short HEAD)"
|
|
142
|
-
echo " Run URL: https://github.com/$(gh repo view --json nameWithOwner -q .nameWithOwner)/actions/runs/$CI_ID"
|
|
143
|
-
echo " Handoff to fix-bug with the failure URL above."
|
|
144
|
-
return 1
|
|
145
|
-
fi
|
|
146
|
-
|
|
147
|
-
sleep $INTERVAL
|
|
148
|
-
ELAPSED=$((ELAPSED + INTERVAL))
|
|
149
|
-
echo " Waiting... (${ELAPSED}s / ${TIMEOUT}s)"
|
|
150
|
-
done
|
|
151
|
-
|
|
152
|
-
echo "FAIL: CI did not complete within ${TIMEOUT}s timeout"
|
|
153
|
-
return 1
|
|
154
|
-
```
|
|
98
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
155
99
|
|
|
156
100
|
- [ ] CI workflow passes after push
|
|
157
101
|
- [ ] `release.ci_verified: true` documented in state.yaml
|
|
@@ -176,14 +120,3 @@ git checkout main && git status && pwd
|
|
|
176
120
|
```
|
|
177
121
|
|
|
178
122
|
Report: "Branch released. Integrate mode: <solo-local|team-pr>. cwd: $(pwd) on $(git branch --show-current)."
|
|
179
|
-
|
|
180
|
-
## Solo-local fallback detail
|
|
181
|
-
|
|
182
|
-
The fallback sequence (Path B above) handles the "remote has moved" case with `git pull --rebase`. Use when `scripts/land-branch.sh` is absent.
|
|
183
|
-
|
|
184
|
-
**Acceptance:** When fallback runs, main is updated, feature branch is deleted locally, and output states `"used fallback merge (land-branch.sh not found)"`.
|
|
185
|
-
|
|
186
|
-
## Handoff
|
|
187
|
-
|
|
188
|
-
Gate: READY -> next: survey-context
|
|
189
|
-
Writes: state.yaml handoff.next_skill = survey-context
|
package/scripts/sync-skills.sh
CHANGED
|
@@ -231,6 +231,9 @@ if [[ -f "$validate_script" ]] && command -v python3 &>/dev/null; then
|
|
|
231
231
|
fi
|
|
232
232
|
|
|
233
233
|
# Regenerate derived reference tables from live SKILL.md frontmatter
|
|
234
|
-
|
|
234
|
+
# Only in dev context (with .git) — not during consumer npm install where docs/ is excluded
|
|
235
|
+
if [[ -d "$REPO_ROOT/.git" ]]; then
|
|
236
|
+
bash "$REPO_ROOT/scripts/generate-reference-tables.sh"
|
|
237
|
+
fi
|
|
235
238
|
|
|
236
239
|
exit 0
|