bigpowers 2.7.5 → 2.9.0

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.
@@ -0,0 +1,262 @@
1
+ ---
2
+ name: publish-package
3
+ description: "\"Package registry publishing for npm, crates.io, PyPI, and Homebrew. Verifies prerequisites, runs the publish command, confirms success, and surfaces actionable error hints on failure.\""
4
+ model: sonnet
5
+ ---
6
+
7
+
8
+ # Publish Package
9
+
10
+ > **HARD GATE** — Do not attempt to publish without verifying prerequisites. Missing auth tokens, stale builds, or duplicate versions cause CI failures that are hard to debug post-push.
11
+ >
12
+ > **HARD GATE** — Always run `--dry-run` first. Package registries are append-only — a bad publish cannot be fully undone on most registries.
13
+
14
+ Publish packages to language-specific registries. Detects package type from manifest files, verifies publish prerequisites, runs the registry-specific publish command, and confirms the version appears on the registry.
15
+
16
+ ## Process
17
+
18
+ ### 1. Detect package type
19
+
20
+ Read the project root for manifest files to determine the package type:
21
+
22
+ | Manifest | Registry | Publish command |
23
+ |----------|----------|----------------|
24
+ | `package.json` | npm | `npm publish --access public` |
25
+ | `Cargo.toml` | crates.io | `cargo publish` |
26
+ | `setup.py` / `pyproject.toml` | PyPI | `twine upload dist/*` or `flit publish` |
27
+ | `Formula/<name>.rb` | Homebrew | `brew bump-formula-pr` |
28
+ | Multiple detected | Polyglot | Error: specify registry with `--registry <npm|crates.io|pypi|brew>` |
29
+
30
+ If no manifest is found, prompt the user to specify the type or pass `--type <npm|crates.io|pypi|brew>`.
31
+
32
+ ### 2. Verify prerequisites
33
+
34
+ Before attempting any publish, run all applicable checks:
35
+
36
+ **npm (`package.json`):**
37
+ ```bash
38
+ # Check auth token exists
39
+ if [ -z "${NPM_TOKEN:-}" ]; then
40
+ if [ ! -f ~/.npmrc ] || ! grep -q "_authToken" ~/.npmrc; then
41
+ echo "FAIL: NPM_TOKEN not set. Set via: export NPM_TOKEN=<token> or add //registry.npmjs.org/:_authToken=<token> to .npmrc"
42
+ exit 1
43
+ fi
44
+ fi
45
+
46
+ # Check version not already published
47
+ PACKAGE_NAME=$(node -p "require('./package.json').name")
48
+ CURRENT_VER=$(node -p "require('./package.json').version")
49
+ if npm view "$PACKAGE_NAME@$CURRENT_VER" version 2>/dev/null; then
50
+ echo "FAIL: Version $CURRENT_VER already published for $PACKAGE_NAME. Bump version first."
51
+ exit 1
52
+ fi
53
+
54
+ # Check build artifacts are fresh
55
+ if [ -d dist ] || [ -d lib ]; then
56
+ LATEST_BUILD=$(find dist lib 2>/dev/null -name "*.js" -o -name "*.cjs" -o -name "*.mjs" | xargs ls -t 2>/dev/null | head -1)
57
+ PACKAGE_MODIFIED=$(stat -f %m package.json 2>/dev/null || stat -c %Y package.json 2>/dev/null)
58
+ if [ -n "$LATEST_BUILD" ] && [ -n "$PACKAGE_MODIFIED" ]; then
59
+ BUILD_TIME=$(stat -f %m "$LATEST_BUILD" 2>/dev/null || stat -c %Y "$LATEST_BUILD" 2>/dev/null)
60
+ if [ "$BUILD_TIME" -lt "$PACKAGE_MODIFIED" ]; then
61
+ echo "WARNING: Build artifacts may be stale (package.json modified after last build). Run npm run build first."
62
+ fi
63
+ fi
64
+ fi
65
+
66
+ # Check CHANGELOG is updated
67
+ if [ -f CHANGELOG.md ]; then
68
+ if ! grep -q "$CURRENT_VER" CHANGELOG.md 2>/dev/null; then
69
+ echo "WARNING: Version $CURRENT_VER not found in CHANGELOG.md. Update changelog before publish."
70
+ fi
71
+ fi
72
+ ```
73
+
74
+ **crates.io (`Cargo.toml`):**
75
+ ```bash
76
+ # Check auth token exists
77
+ if [ -z "${CARGO_REGISTRY_TOKEN:-}" ]; then
78
+ if [ ! -f ~/.cargo/config.toml ] || ! grep -q "token" ~/.cargo/config.toml; then
79
+ echo "FAIL: CARGO_REGISTRY_TOKEN not set. Set via: export CARGO_REGISTRY_TOKEN=<token> or add to ~/.cargo/config.toml"
80
+ exit 1
81
+ fi
82
+ fi
83
+
84
+ # Check version not already published
85
+ CRATE_NAME=$(grep '^name' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')
86
+ CURRENT_VER=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')
87
+ if cargo search "$CRATE_NAME" 2>/dev/null | grep -q "^${CRATE_NAME}.*\"$CURRENT_VER\""; then
88
+ echo "FAIL: Version $CURRENT_VER already published for $CRATE_NAME. Bump version in Cargo.toml first."
89
+ exit 1
90
+ fi
91
+ ```
92
+
93
+ **PyPI (`setup.py` / `pyproject.toml`):**
94
+ ```bash
95
+ # Check auth token exists
96
+ if [ -z "${TWINE_PASSWORD:-}" ] && [ -z "${POETRY_PYPI_TOKEN_PYPI:-}" ]; then
97
+ if [ ! -f ~/.pypirc ]; then
98
+ echo "FAIL: PyPI token not configured. Set TWINE_PASSWORD or create ~/.pypirc"
99
+ exit 1
100
+ fi
101
+ fi
102
+
103
+ # Check for build artifacts
104
+ if [ ! -d dist ] || [ -z "$(ls dist/*.whl 2>/dev/null)" ]; then
105
+ echo "WARNING: No .whl files found in dist/. Run: python -m build"
106
+ fi
107
+ ```
108
+
109
+ ### 3. Run publish
110
+
111
+ After all prerequisite checks pass, run the registry-specific command:
112
+
113
+ ```bash
114
+ # npm
115
+ npm publish --access public
116
+
117
+ # crates.io
118
+ cargo publish
119
+
120
+ # PyPI
121
+ python -m twine upload dist/* # or: poetry publish
122
+
123
+ # Homebrew (opens PR, does not publish directly)
124
+ brew bump-formula-pr --url=<tarball-url> <formula-name>
125
+ ```
126
+
127
+ ### 4. Verify publish success
128
+
129
+ After publish, confirm the version appears on the registry:
130
+
131
+ ```bash
132
+ # npm
133
+ npm view "$PACKAGE_NAME" versions --json 2>/dev/null | grep -q "\"$CURRENT_VER\"" && echo "OK: npm publish confirmed"
134
+
135
+ # crates.io
136
+ cargo search "$CRATE_NAME" 2>/dev/null | grep -q "^${CRATE_NAME}.*\"$CURRENT_VER\"" && echo "OK: crates.io publish confirmed"
137
+
138
+ # PyPI
139
+ pip index versions "$PACKAGE_NAME" 2>/dev/null | grep -q "$CURRENT_VER" && echo "OK: PyPI publish confirmed"
140
+ ```
141
+
142
+ ### 5. Error handling
143
+
144
+ On failure, surface actionable hints:
145
+
146
+ ```bash
147
+ # Generic failure handler
148
+ if [ $? -ne 0 ]; then
149
+ case "$REGISTRY" in
150
+ npm)
151
+ echo "FAIL: npm publish failed."
152
+ echo " Common causes:"
153
+ echo " - NPM_TOKEN not set in secrets: add to GitHub repo secrets"
154
+ echo " - Version already published: bump version in package.json"
155
+ echo " - Two-factor auth required: use --otp=<code> flag"
156
+ echo " - Package scoped but not public: add --access public"
157
+ ;;
158
+ crates.io)
159
+ echo "FAIL: cargo publish failed."
160
+ echo " Common causes:"
161
+ echo " - CARGO_REGISTRY_TOKEN not configured: see ~/.cargo/config.toml"
162
+ echo " - Version already published: bump version in Cargo.toml"
163
+ echo " - Local changes not committed: cargo publish requires clean working tree"
164
+ ;;
165
+ pypi)
166
+ echo "FAIL: PyPI publish failed."
167
+ echo " Common causes:"
168
+ echo " - TWINE_PASSWORD not configured: set env var or ~/.pypirc"
169
+ echo " - Build artifacts missing: run python -m build first"
170
+ echo " - Version conflict: version already exists on PyPI"
171
+ ;;
172
+ esac
173
+ exit 1
174
+ fi
175
+ ```
176
+
177
+ ### 6. Dry-run mode (`--dry-run`)
178
+
179
+ Run `--dry-run` to verify all prerequisites without actually publishing:
180
+
181
+ ```bash
182
+ # Example output
183
+ $ publish-package --dry-run
184
+
185
+ [DRY-RUN] Detected package type: npm
186
+ [DRY-RUN] Package: my-package v0.4.0
187
+ [DRY-RUN] Checking NPM_TOKEN... OK
188
+ [DRY-RUN] Checking version 0.4.0 not already published... OK
189
+ [DRY-RUN] Checking build artifacts... WARNING: package.json modified after build
190
+ [DRY-RUN] Checking CHANGELOG... OK
191
+ [DRY-RUN] Would run: npm publish --access public
192
+ [DRY-RUN] Exiting without publishing.
193
+ ```
194
+
195
+ ### 7. Dry-run mode per registry
196
+
197
+ ```bash
198
+ # npm dry-run
199
+ npm publish --access public --dry-run
200
+
201
+ # crates.io dry-run (cargo does not have a publish dry-run; use --dry-run flag for validation only)
202
+ cargo package --list 2>/dev/null
203
+
204
+ # PyPI dry-run
205
+ python -m twine upload --repository testpypi dist/* # test.pypi.org
206
+ ```
207
+
208
+ ## Options
209
+
210
+ | Flag | Description |
211
+ |------|-------------|
212
+ | `--dry-run` | Verify prerequisites and show publish command without executing |
213
+ | `--registry <type>` | Force registry type (skip auto-detection) |
214
+ | `--otp <code>` | One-time password for npm 2FA |
215
+ | `--no-verify` | Skip prerequisite checks (use with caution) |
216
+
217
+ ## Examples
218
+
219
+ ### Publish an npm package
220
+
221
+ ```bash
222
+ # Verify first
223
+ publish-package --dry-run
224
+
225
+ # Publish
226
+ publish-package
227
+
228
+ # Output:
229
+ # [npm] Publishing my-package v0.4.0...
230
+ # OK: npm publish confirmed (my-package@0.4.0 on registry)
231
+ ```
232
+
233
+ ### Publish a Rust crate
234
+
235
+ ```bash
236
+ export CARGO_REGISTRY_TOKEN=<token>
237
+ publish-package --dry-run
238
+ publish-package
239
+ ```
240
+
241
+ ### Missing token scenario
242
+
243
+ ```bash
244
+ $ publish-package
245
+ FAIL: NPM_TOKEN not set. Set via: export NPM_TOKEN=<token> or add to .npmrc
246
+ ```
247
+
248
+ ## Integration with release-branch
249
+
250
+ When wired into `release-branch`, add a step after git push:
251
+
252
+ ```
253
+ 6a. Run publish-package to publish to package registries
254
+ → verify: publish-package --dry-run && publish-package
255
+ ```
256
+
257
+ ## Verify
258
+
259
+ → verify: `test -f publish-package/SKILL.md && echo "OK: skill file exists" || echo "FAIL: no skill file"`
260
+ → verify: `grep -q "name: publish-package" publish-package/SKILL.md && echo "OK: frontmatter" || echo "FAIL: frontmatter"`
261
+ → verify: `grep -ci "npm\|crates.io\|pypi\|publish\|registry" publish-package/SKILL.md | awk '{if($1>=4) print "OK: semantics"; else print "FAIL: missing"}'`
262
+ → verify: `grep -q "publish-package" SKILL-INDEX.md && echo "OK: in SKILL-INDEX" || echo "FAIL: not indexed"`
@@ -0,0 +1,309 @@
1
+ ---
2
+ name: wire-ci
3
+ description: "\"CI pipeline setup with pre-built templates and local validation. Generates GitHub Actions workflows, validates YAML syntax and permissions, supports dry-run via act/gh. The CI equivalent of wire-observability.\""
4
+ model: sonnet
5
+ ---
6
+
7
+
8
+ # Wire CI
9
+
10
+ > **HARD GATE** — Do not ship a project without CI. Run this skill before first merge to main or when adding CI to an existing project.
11
+ >
12
+ > **HARD GATE** — CI that is untestable locally will break every cycle. Always run `--validate` after generating workflows and `--dry-run` before pushing.
13
+
14
+ Generate, validate, and test CI workflows. Detects your project type, produces platform-appropriate GitHub Actions configurations, and provides local verification to catch auth, permissions, and syntax issues before they reach CI.
15
+
16
+ ## What this sets up
17
+
18
+ 1. **CI workflow** — `.github/workflows/ci.yaml` with test, lint, typecheck, build steps
19
+ 2. **Release workflow** — `.github/workflows/release.yaml` with semantic-release (if applicable)
20
+ 3. **`--validate` mode** — checks YAML syntax, workflow permissions, required secrets, and common pitfalls
21
+ 4. **`--dry-run` mode** — runs workflows locally via `act` or `gh workflow run` to prove correctness before push
22
+ 5. **Failure pattern documentation** — common CI failure categories and their fixes
23
+
24
+ ## Process
25
+
26
+ ### 1. Detect project type
27
+
28
+ Read the project root for manifest files to determine which template to use:
29
+
30
+ | Manifest | Type | Template |
31
+ |----------|------|----------|
32
+ | `Cargo.toml` | Rust | Rust CI: test, clippy, fmt, build |
33
+ | `package.json` | Node | Node CI: test, lint, typecheck, build |
34
+ | `setup.py` / `pyproject.toml` | Python | Python CI: pytest, ruff/mypy/flake8, build |
35
+ | `go.mod` | Go | Go CI: test, vet, staticcheck, build |
36
+ | `CMakeLists.txt` | C/C++ | C/C++ CI: cmake build, ctest |
37
+ | Multiple detected | Polyglot | Combined workflows or error if ambiguous |
38
+
39
+ If no manifest is found, prompt the user to specify the type or pass `--type <rust|node|python|go|cpp>`.
40
+
41
+ ### 2. Generate CI workflow
42
+
43
+ Create `.github/workflows/ci.yaml` with standard steps derived from the project type and its manifest:
44
+
45
+ **Rust template (`Cargo.toml`):**
46
+ ```yaml
47
+ name: CI
48
+ on: [push, pull_request]
49
+ jobs:
50
+ test:
51
+ runs-on: ubuntu-latest
52
+ steps:
53
+ - uses: actions/checkout@v4
54
+ - uses: actions-rust/toolchain@v1
55
+ with:
56
+ toolchain: stable
57
+ components: clippy, rustfmt
58
+ - run: cargo fmt --all -- --check
59
+ - run: cargo clippy -- -D warnings
60
+ - run: cargo test
61
+ - run: cargo build --release
62
+ ```
63
+
64
+ **Node template (`package.json`):**
65
+ ```yaml
66
+ name: CI
67
+ on: [push, pull_request]
68
+ jobs:
69
+ test:
70
+ runs-on: ubuntu-latest
71
+ steps:
72
+ - uses: actions/checkout@v4
73
+ - uses: actions/setup-node@v4
74
+ with:
75
+ node-version: 20
76
+ cache: npm
77
+ - run: npm ci
78
+ - run: npm test
79
+ - run: npm run lint 2>/dev/null || true
80
+ - run: npm run typecheck 2>/dev/null || true
81
+ - run: npm run build 2>/dev/null || true
82
+ ```
83
+
84
+ **Python template (`setup.py` / `pyproject.toml`):**
85
+ ```yaml
86
+ name: CI
87
+ on: [push, pull_request]
88
+ jobs:
89
+ test:
90
+ runs-on: ubuntu-latest
91
+ steps:
92
+ - uses: actions/checkout@v4
93
+ - uses: actions/setup-python@v5
94
+ with:
95
+ python-version: "3.12"
96
+ cache: pip
97
+ - run: pip install -e ".[dev]" || pip install -e .
98
+ - run: pip install pytest ruff mypy
99
+ - run: ruff check .
100
+ - run: mypy . 2>/dev/null || true
101
+ - run: pytest
102
+ ```
103
+
104
+ **Go template (`go.mod`):**
105
+ ```yaml
106
+ name: CI
107
+ on: [push, pull_request]
108
+ jobs:
109
+ test:
110
+ runs-on: ubuntu-latest
111
+ steps:
112
+ - uses: actions/checkout@v4
113
+ - uses: actions/setup-go@v5
114
+ with:
115
+ go-version: stable
116
+ cache: true
117
+ - run: go vet ./...
118
+ - run: go test ./...
119
+ - run: go build ./...
120
+ ```
121
+
122
+ **C/C++ template (`CMakeLists.txt`):**
123
+ ```yaml
124
+ name: CI
125
+ on: [push, pull_request]
126
+ jobs:
127
+ test:
128
+ runs-on: ubuntu-latest
129
+ steps:
130
+ - uses: actions/checkout@v4
131
+ - run: cmake -B build
132
+ - run: cmake --build build
133
+ - run: ctest --test-dir build
134
+ ```
135
+
136
+ ### 3. Generate release workflow (if semantic-release detected)
137
+
138
+ If the project has semantic-release configured (in `package.json`, `.releaserc`, or `release.config.js`), also generate `.github/workflows/release.yaml`:
139
+
140
+ ```yaml
141
+ name: Release
142
+ on:
143
+ push:
144
+ branches: [main]
145
+ jobs:
146
+ release:
147
+ runs-on: ubuntu-latest
148
+ permissions:
149
+ contents: write
150
+ issues: write
151
+ pull-requests: write
152
+ id-token: write
153
+ steps:
154
+ - uses: actions/checkout@v4
155
+ with:
156
+ fetch-depth: 0
157
+ - uses: actions/setup-node@v4
158
+ with:
159
+ node-version: 20
160
+ cache: npm
161
+ - run: npm ci
162
+ - run: npm run build 2>/dev/null || true
163
+ - run: npx semantic-release
164
+ env:
165
+ GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
166
+ NPM_TOKEN: \${{ secrets.NPM_TOKEN }}
167
+ ```
168
+
169
+ > **NPM_TOKEN is required** for publishing to npm. Without it, semantic-release will fail at the publish step. See `--validate` to check this.
170
+
171
+ ### 4. Validate workflows (`--validate`)
172
+
173
+ Run `wire-ci --validate` to check all generated workflow files:
174
+
175
+ ```bash
176
+ # Validate YAML syntax
177
+ for f in .github/workflows/*.yaml; do
178
+ python3 -c "import yaml; yaml.safe_load(open('$f'))" || echo "FAIL: $f has YAML syntax errors"
179
+ done
180
+
181
+ # Check permissions block presence
182
+ for f in .github/workflows/*.yaml; do
183
+ if grep -q "permissions:" "$f"; then
184
+ echo "OK: $f has permissions block"
185
+ else
186
+ echo "WARNING: $f missing permissions block — add one for security"
187
+ fi
188
+ done
189
+
190
+ # Check for npm publish without NPM_TOKEN
191
+ for f in .github/workflows/*.yaml; do
192
+ if grep -q "npm publish\|npx semantic-release" "$f"; then
193
+ if ! grep -q "NPM_TOKEN" "$f"; then
194
+ echo "WARNING: $f has npm publish/semantic-release but no NPM_TOKEN secret"
195
+ fi
196
+ fi
197
+ done
198
+
199
+ # Check for hardcoded Node versions
200
+ for f in .github/workflows/*.yaml; do
201
+ if grep -q "node-version: [0-9]" "$f" && grep -qv "node-version-file\|\.nvmrc" "$f"; then
202
+ echo "NOTE: $f has hardcoded Node version — consider using .nvmrc instead"
203
+ fi
204
+ done
205
+
206
+ # Check for common secrets reference errors
207
+ for f in .github/workflows/*.yaml; do
208
+ # Secrets referencing something that doesn't exist in the workflow
209
+ grep -oP 'secrets\.\w+' "$f" | sort -u | while read -r secret; do
210
+ echo "REF: $f references $secret"
211
+ done
212
+ done
213
+ ```
214
+
215
+ **Exit codes:**
216
+ - `0` — all checks pass (no errors)
217
+ - `1` — YAML syntax errors found
218
+ - `2` — validation warnings only (missing permissions, secrets, etc.)
219
+
220
+ ### 5. Dry-run workflows (`--dry-run`)
221
+
222
+ Attempt to run the generated workflows locally to catch errors before push:
223
+
224
+ ```bash
225
+ # Option A: Use act (recommended)
226
+ if command -v act &>/dev/null; then
227
+ act push --dry-run
228
+ echo "OK: act dry-run completed"
229
+ elif command -v gh &>/dev/null; then
230
+ # Option B: Use gh workflow run (remote test, no local docker)
231
+ gh workflow run ci.yaml --ref "$(git branch --show-current)"
232
+ echo "OK: CI workflow dispatched. Check status: gh run list"
233
+ else
234
+ echo "NOTE: Install act (https://github.com/nektos/act) for full local dry-run"
235
+ echo " Install gh CLI for remote dry-run"
236
+ fi
237
+ ```
238
+
239
+ > **act** runs workflows in a local Docker environment — the most accurate pre-push validation.
240
+ > **gh workflow run** sends the workflow to GitHub but doesn't execute locally — useful for checking YAML parsing but not for testing the actual steps.
241
+
242
+ ### 6. Document common CI failure patterns
243
+
244
+ Add the following to the project's documentation or CLAUDE.md after setup:
245
+
246
+ | Failure | Cause | Fix |
247
+ |---------|-------|-----|
248
+ | `npm publish` fails | `NPM_TOKEN` not set as repo secret | Add `NPM_TOKEN` to GitHub repo secrets |
249
+ | `semantic-release` fails on push | Missing `permissions: contents: write` | Add `permissions: contents: write` to release job |
250
+ | `cargo publish` auth fail | `CARGO_REGISTRY_TOKEN` not set | Add token to `~/.cargo/config.toml` or env |
251
+ | `go vet` fails | Go version mismatch | Match `go.mod` `go` directive with setup-go version |
252
+ | `cargo clippy` errors | New lints in Rust nightly | `cargo clippy --fix` or allow specific lints |
253
+ | `act` not found | Docker not running or act not installed | `brew install act` / `docker ps` to verify Docker |
254
+ | Hardcoded Node version stale | `.nvmrc` exists but workflow uses hardcoded version | Use `node-version-file: .nvmrc` instead |
255
+
256
+ ## Examples
257
+
258
+ ### Create CI for a Rust project
259
+
260
+ ```bash
261
+ # Detect from Cargo.toml, generate workflows
262
+ wire-ci
263
+
264
+ # Validate generated workflows
265
+ wire-ci --validate
266
+
267
+ # Run locally with act
268
+ wire-ci --dry-run
269
+ ```
270
+
271
+ ### Create CI for a Node project with semantic-release
272
+
273
+ ```bash
274
+ wire-ci
275
+ wire-ci --validate
276
+ # Expect warning: "npm publish step found but no NPM_TOKEN in secrets"
277
+ # Fix: add NPM_TOKEN to repo secrets
278
+ ```
279
+
280
+ ### Validate existing workflows (no generation)
281
+
282
+ ```bash
283
+ wire-ci --validate --check-only
284
+ ```
285
+
286
+ ## Options
287
+
288
+ | Flag | Description |
289
+ |------|-------------|
290
+ | `--validate` | Check YAML syntax, permissions, secrets, common pitfalls |
291
+ | `--dry-run` | Run workflows locally via `act` or dispatch via `gh` |
292
+ | `--check-only` | Only validate, do not generate new files |
293
+ | `--type <type>` | Force project type (skip auto-detection) |
294
+ | `--force` | Overwrite existing workflow files |
295
+ | `--no-release` | Skip release workflow generation even if semantic-release detected |
296
+
297
+ ## Integration with build-epic
298
+
299
+ When `wire-ci` is used as part of `build-epic`:
300
+
301
+ 1. **During develop-tdd**: If the task modifies `.github/workflows/`, run `wire-ci --validate` as a CI dry-run sub-step
302
+ 2. **During release-branch**: After push, run `gh run list --limit 1 --branch main --json status,conclusion` to verify CI passes
303
+
304
+ ## Verify
305
+
306
+ → verify: `test -f wire-ci/SKILL.md && echo "OK: skill file exists" || echo "FAIL: no skill file"`
307
+ → verify: `grep -q "name: wire-ci" wire-ci/SKILL.md && echo "OK: frontmatter" || echo "FAIL: frontmatter"`
308
+ → verify: `grep -ci "template\|workflow\|validate\|dry.run" wire-ci/SKILL.md | awk '{if($1>=3) print "OK: semantics"; else print "FAIL: missing"}'`
309
+ → verify: `grep -q "wire-ci" SKILL-INDEX.md && echo "OK: in SKILL-INDEX" || echo "FAIL: not indexed"`
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [2.9.0](https://github.com/danielvm-git/bigpowers/compare/v2.8.0...v2.9.0) (2026-06-20)
2
+
3
+
4
+ ### Features
5
+
6
+ * **skills:** add publish-package skill for multi-registry publishing ([945a481](https://github.com/danielvm-git/bigpowers/commit/945a481cef07335c59277c82137e4a6bec78655a))
7
+
8
+ # [2.8.0](https://github.com/danielvm-git/bigpowers/compare/v2.7.5...v2.8.0) (2026-06-20)
9
+
10
+
11
+ ### Features
12
+
13
+ * **skills:** add wire-ci CI pipeline skill ([7196579](https://github.com/danielvm-git/bigpowers/commit/71965799376ec894f48a957626455142beb5080b))
14
+
1
15
  ## [2.7.5](https://github.com/danielvm-git/bigpowers/compare/v2.7.4...v2.7.5) (2026-06-20)
2
16
 
3
17