bigpowers 2.34.1 → 2.35.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.
Files changed (48) hide show
  1. package/.pi/package.json +2 -2
  2. package/.pi/prompts/deploy.md +53 -28
  3. package/.pi/prompts/develop-tdd.md +5 -80
  4. package/.pi/prompts/migrate-spec.md +273 -197
  5. package/.pi/prompts/publish-package.md +125 -67
  6. package/.pi/prompts/release-branch.md +85 -69
  7. package/.pi/prompts/security-review.md +323 -0
  8. package/.pi/prompts/smoke-test.md +98 -58
  9. package/.pi/prompts/using-bigpowers.md +2 -2
  10. package/.pi/prompts/validate-contracts.md +169 -54
  11. package/.pi/prompts/wire-ci.md +147 -89
  12. package/.pi/skills/deploy/SKILL.md +53 -28
  13. package/.pi/skills/develop-tdd/SKILL.md +5 -80
  14. package/.pi/skills/migrate-spec/SKILL.md +273 -197
  15. package/.pi/skills/publish-package/SKILL.md +125 -67
  16. package/.pi/skills/release-branch/SKILL.md +85 -69
  17. package/.pi/skills/security-review/SKILL.md +324 -0
  18. package/.pi/skills/smoke-test/SKILL.md +98 -58
  19. package/.pi/skills/using-bigpowers/SKILL.md +2 -2
  20. package/.pi/skills/validate-contracts/SKILL.md +169 -54
  21. package/.pi/skills/wire-ci/SKILL.md +147 -89
  22. package/CHANGELOG.md +14 -0
  23. package/README.md +4 -4
  24. package/SKILL-INDEX.md +2 -2
  25. package/deploy/REFERENCE.md +82 -0
  26. package/deploy/SKILL.md +3 -63
  27. package/develop-tdd/SKILL.md +5 -80
  28. package/migrate-spec/REFERENCE.md +268 -0
  29. package/migrate-spec/SKILL.md +5 -199
  30. package/package.json +2 -2
  31. package/publish-package/REFERENCE.md +239 -0
  32. package/publish-package/SKILL.md +8 -192
  33. package/release-branch/REFERENCE.md +83 -0
  34. package/release-branch/SKILL.md +2 -69
  35. package/scripts/generate-reference-tables.sh +1 -0
  36. package/scripts/sync-skills.sh +4 -1
  37. package/security-review/REFERENCE-confidence-rubric.md +85 -0
  38. package/security-review/REFERENCE-false-positives.md +68 -0
  39. package/security-review/REFERENCE-vuln-categories.md +103 -0
  40. package/security-review/SKILL.md +63 -0
  41. package/skills-lock.json +14 -9
  42. package/smoke-test/REFERENCE.md +162 -0
  43. package/smoke-test/SKILL.md +5 -130
  44. package/using-bigpowers/SKILL.md +2 -2
  45. package/validate-contracts/REFERENCE.md +183 -0
  46. package/validate-contracts/SKILL.md +6 -77
  47. package/wire-ci/REFERENCE.md +257 -0
  48. package/wire-ci/SKILL.md +8 -210
@@ -49,20 +49,7 @@ If none found: ask the user which framework before proceeding.
49
49
 
50
50
  List every artifact found matching the detected framework. Present the list to the user:
51
51
 
52
- ```
53
- Detected: GSD
54
- Found:
55
- ✓ .planning/ROADMAP.md
56
- ✓ .planning/REQUIREMENTS.md (12 REQ-XX items)
57
- ✓ .planning/state.yaml
58
- ✓ .planning/phases/01-auth/01-CONTEXT.md
59
- ✗ .planning/METHODOLOGY.md (not present)
60
-
61
- Skipping:
62
- .planning/phases/01-auth/01-01-SUMMARY.md (execution record; archived only)
63
-
64
- Proceed with migration? [yes / skip <artifact> / abort]
65
- ```
52
+ See [REFERENCE.md](REFERENCE.md) — `Detected: GSD...`
66
53
 
67
54
  → verify: `find . -maxdepth 4 \( -name "ROADMAP.md" -o -name "spec.md" -o -name "prd.md" -o -name "REQUIREMENTS.md" \) 2>/dev/null | grep -v ".git" | head -15`
68
55
 
@@ -78,17 +65,7 @@ Apply the mapping from [REFERENCE.md](./REFERENCE.md) and [REFERENCE-GSD.md](./R
78
65
 
79
66
  When source artifacts contain IDs (REQ-XX, FR-XX, UJ-XX), emit them as **first-class YAML fields** in `in_scope` entries, not YAML comments:
80
67
 
81
- ```yaml
82
- # CORRECT — first-class id: field
83
- in_scope:
84
- - id: REQ-001
85
- description: "User can register with email/password"
86
- source: "REQUIREMENTS.md"
87
-
88
- # DEPRECATED — comment-only
89
- in_scope:
90
- - "User can register with email/password" # REQ-001
91
- ```
68
+ See [REFERENCE.md](REFERENCE.md) — `# CORRECT — first-class id: field...`
92
69
 
93
70
  **When source has no IDs:** Prompt the user: "No IDs found. Assign auto-generated IDs? [yes / no]". If yes, emit `REQ-{NNN}` with `# auto-generated` annotation.
94
71
 
@@ -100,20 +77,7 @@ See [REFERENCE.md — in_scope format with ID tracking](./REFERENCE.md#in_scope-
100
77
 
101
78
  When source has FR-XX or UJ-XX IDs, emit `specs/product/REQUIREMENTS_TRACE.yaml` for end-to-end requirement traceability:
102
79
 
103
- ```yaml
104
- trace:
105
- - id: FR-001
106
- type: functional_requirement
107
- description: "User can register with email/password"
108
- epic: e02-auth-ui
109
- story: e02s01
110
- verify: "grep -q 'FR-001' specs/product/SCOPE_LATEST.yaml && echo OK"
111
- - id: UJ-001
112
- type: user_journey
113
- description: "New user completes registration flow"
114
- epic: e02-auth-ui
115
- story: e02s01
116
- ```
80
+ See [REFERENCE.md](REFERENCE.md) — `trace:...`
117
81
 
118
82
  **Existing trace file:** If `REQUIREMENTS_TRACE.yaml` already exists, prompt: "REQUIREMENTS_TRACE.yaml exists. [overwrite / merge / skip]"
119
83
 
@@ -131,168 +95,10 @@ See [REFERENCE.md — REQUIREMENTS_TRACE.yaml format](./REFERENCE.md#requirement
131
95
 
132
96
  Always regenerate `specs/state.yaml` from scratch in bigpowers YAML format (see REFERENCE.md for template). The **handoff block is mandatory** and must include all four fields:
133
97
 
134
- ```yaml
135
- active_flow: null
136
- active_epic_id: null
137
- active_story_id: null
138
-
139
- # ... other state fields ...
140
-
141
- handoff:
142
- last_step_completed: "Migrated from <framework> on <date>"
143
- open_decisions:
144
- - "decision text here"
145
- required_reading:
146
- - specs/product/VISION_LATEST.yaml
147
- - specs/product/SCOPE_LATEST.yaml
148
- - specs/tech-architecture/TECH_STACK_LATEST.md
149
- - specs/release-plan.yaml
150
- next_skill: survey-context
151
- ```
98
+ See [REFERENCE.md](REFERENCE.md) — `active_flow: null...`
152
99
 
153
100
  If no open decisions were found during migration, the `open_decisions` list may be empty with an explanatory comment:
154
101
 
155
- ```yaml
156
- handoff:
157
- last_step_completed: "..."
158
- open_decisions: [] # None — all decisions resolved during migration
159
- required_reading: [...]
160
- next_skill: survey-context
161
- ```
102
+ See [REFERENCE.md](REFERENCE.md) — `handoff:...`
162
103
 
163
104
  → verify: `grep -q 'handoff:' specs/state.yaml && grep -q 'last_step_completed' specs/state.yaml && echo "ok" || echo "MISSING or INCOMPLETE: handoff block"`
164
-
165
- ### Step 5 — Surface learnings (optional)
166
-
167
- After migration, offer the user a brief analysis of what the source framework did that bigpowers doesn't have yet.
168
-
169
- Use the learnings table from [REFERENCE.md](./REFERENCE.md#learnings-to-adopt). Present as checkboxes so the user can decide which to adopt.
170
-
171
- → verify: `grep -c "\- \[ \]" specs/state.yaml 2>/dev/null && echo "pending items recorded" || echo "no pending items in state.yaml"`
172
-
173
- ### Step 6 — Adversarial review (optional)
174
-
175
- Before the user runs `plan-work`, offer an optional lightweight audit of the migrated artifacts. This catches common migration errors early — incomplete specs, missing verification commands, unresolved decisions.
176
-
177
- Prompt: "Run adversarial review of migrated artifacts? [yes / skip]"
178
-
179
- If yes, perform these checks:
180
-
181
- 1. **Scan for incomplete markers** — Find TODO, FIXME, MISSING in specs/
182
- 2. **Verify every epic has `verify:` commands** — Parse all `eNN-*/epic.yaml` files
183
- 3. **Check state.yaml handoff** — Ensure `open_decisions` is documented (even if empty)
184
-
185
- Collect findings and write to `specs/archive/MIGRATION-AUDIT.md`:
186
-
187
- ```markdown
188
- # Migration Audit — <project-name> from <framework>
189
-
190
- **Date:** <ISO 8601 timestamp>
191
- **Status:** Pass / Fail with findings
192
-
193
- ## Findings
194
-
195
- ### High Priority
196
- - Artifact: specs/epics/e02-auth-ui/epic.yaml
197
- Finding: No verify: commands in story tasks
198
- Recommendation: Add `verify:` to each task before develop-tdd
199
-
200
- ### Information
201
- - Count of TODO markers: 3 (normal for fresh migration)
202
- ```
203
-
204
- If findings exist, the handoff block should note: "Adversarial review: N findings — see `specs/archive/MIGRATION-AUDIT.md`"
205
-
206
- If skip is chosen, add to handoff: "Adversarial review: skipped — review manually before plan-work"
207
-
208
- → verify: `test -f specs/archive/MIGRATION-AUDIT.md && echo "audit completed" || echo "audit skipped or not performed"`
209
-
210
- ### Step 7 — Post-migration: Optional two-pass spec writing gate
211
-
212
- After Steps 1–6, offer the user an optional two-pass spec writing workflow (spec-kit learning):
213
-
214
- Prompt: "Use two-pass spec writing (user journeys first, then technical)? [yes / no]"
215
-
216
- If **yes**, initialize the gate in `specs/state.yaml`:
217
-
218
- ```yaml
219
- two_pass_spec:
220
- journey_pass: pending
221
- technical_pass: pending
222
- approved_at: null
223
- ```
224
-
225
- The journey pass must be marked "complete" by the user (after stakeholder approval of user-journey specs) before the technical pass begins:
226
-
227
- ```yaml
228
- two_pass_spec:
229
- journey_pass: complete
230
- approved_at: "2026-06-26T12:00:00Z"
231
- technical_pass: pending
232
- ```
233
-
234
- Inform the user: "Journey pass is pending. Run `elaborate-spec` for user journeys, get stakeholder approval, then update `two_pass_spec.journey_pass: complete` in state.yaml before proceeding to technical specs."
235
-
236
- If **no**, skip the two-pass gate. Proceed directly to plan-work.
237
-
238
- → verify: `grep -q 'two_pass_spec:' specs/state.yaml && echo "two-pass gate initialized" || echo "two-pass gate not activated"`
239
-
240
- ### Step 8 — Post-migration: Optional methodology doc template
241
-
242
- After Steps 1–7, offer the user an optional analytical framework scaffold (GSD learning):
243
-
244
- Prompt: "Create a methodology doc? [yes / no]"
245
-
246
- If **yes**, present a checklist of analytical lenses:
247
-
248
- ```
249
- Which lenses to include in specs/tech-architecture/METHODOLOGY_LATEST.md?
250
-
251
- [x] Cost of Delay (CD3) — Priority & trade-off assessment
252
- [ ] STRIDE — Security threat modeling
253
- [ ] F.I.R.S.T — Test quality principles
254
- [ ] Bayesian Updating — Probabilistic decision-making
255
- [ ] OWASP Top 10 — Web security framework
256
- ```
257
-
258
- Copy the template from `migrate-spec/templates/METHODOLOGY_LATEST.md` to `specs/tech-architecture/METHODOLOGY_LATEST.md`.
259
- - Active lenses remain uncommented
260
- - Unselected lenses are left commented out
261
- - Populate `{{project_name}}` with the migrated project's name
262
-
263
- If **no**, skip. Add note to handoff: "Methodology doc: skipped — can be added later via `cp migrate-spec/templates/METHODOLOGY_LATEST.md specs/tech-architecture/`"
264
-
265
- → verify: `test -f specs/tech-architecture/METHODOLOGY_LATEST.md && echo "methodology doc created" || echo "methodology doc skipped"`
266
-
267
- ---
268
-
269
- ## Artifact Mapping Summary
270
-
271
- Full mapping tables: [REFERENCE-GSD.md](./REFERENCE-GSD.md) (GSD) · [REFERENCE.md](./REFERENCE.md) (spec-kit, BMAD, learnings).
272
-
273
- | Source | Target |
274
- |--------|--------|
275
- | GSD `ROADMAP.md` | `specs/release-plan.yaml + epic shards` |
276
- | GSD `REQUIREMENTS.md` | `specs/product/SCOPE_LATEST.yaml` |
277
- | GSD `CONTEXT.md` (phases) | `specs/tech-architecture/tech-stack.md` + `specs/adr/` |
278
- | GSD `PLAN.md` | `specs/epics/eNN-slug/epic.yaml` (tasks with verify in `-tasks.yaml`) |
279
- | GSD `METHODOLOGY.md` | `specs/tech-architecture/tech-stack.md` |
280
- | spec-kit `spec.md` | `specs/product/SCOPE_LATEST.yaml` + `specs/tech-architecture/tech-stack.md` |
281
- | spec-kit `plan.md` | `specs/tech-architecture/tech-stack.md` + `specs/release-plan.yaml` + `specs/epics/` |
282
- | spec-kit `tasks.md` | `specs/epics/ (see slice-tasks)` |
283
- | BMAD `prd.md` | `specs/product/SCOPE_LATEST.yaml` |
284
- | BMAD `architecture.md` | `specs/tech-architecture/tech-stack.md` + `specs/adr/` |
285
- | BMAD `epic-*.md` | `specs/release-plan.yaml + epic shards` |
286
- | BMAD `story-*.md` | `specs/epics/ (see slice-tasks)` |
287
- | BMAD `project-context.md` | `CLAUDE.md` (append project-specific section) |
288
- | BMAD `decision-log.md` | `specs/adr/` (one ADR per logged decision) |
289
-
290
- ---
291
-
292
- ## Rules
293
-
294
- - **Preserve source IDs** — REQ-XX, FR-XX, UJ-XX are emitted as first-class `id:` fields in bigpowers YAML targets (e.g., `in_scope` entries). Never silently renumber. See Step 3 ID Tracking subsection for details.
295
- - **Never merge contradictory docs** — if source has both `CONTEXT.md` and `architecture.md`, create sections in bigpowers `CONTEXT.md`; don't collapse them.
296
- - **ADRs are opt-in** — only create an ADR when: hard to reverse, surprising without context, result of a real trade-off. Lightweight decisions go to `specs/DECISION-LOG.md`.
297
- - **state.yaml is always regenerated** — never migrate source STATE verbatim; bigpowers state.yaml needs its own format.
298
- - **specs/ is the only output location** — no files are created outside `specs/` and `CLAUDE.md`.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bigpowers",
3
- "version": "2.34.1",
4
- "description": "61 agent skills for spec-driven, test-first software development by solo developers",
3
+ "version": "2.35.0",
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
+ ```