bigpowers 2.87.6 → 2.87.8

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bigpowers",
3
- "version": "2.87.6",
3
+ "version": "2.87.8",
4
4
  "description": "81 skills — 73 agent skills synthesizing 17 years of software engineering discipline into a prescriptive methodology for solo developers",
5
5
  "keywords": [
6
6
  "gemini-extension"
package/.pi/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bigpowers",
3
- "version": "2.87.6",
3
+ "version": "2.87.8",
4
4
  "description": "81 skills — 73 agent skills synthesizing 17 years of software engineering discipline into a prescriptive methodology for solo developers",
5
5
  "keywords": [
6
6
  "pi-package"
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [2.87.8](https://github.com/danielvm-git/bigpowers/compare/v2.87.7...v2.87.8) (2026-09-01)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **cli:** bigpowers init provisions scripts/ + specs/ into consumer projects ([#117](https://github.com/danielvm-git/bigpowers/issues/117)) ([37bc0bf](https://github.com/danielvm-git/bigpowers/commit/37bc0bf72875cd66898d35138870982c8af2d310)), closes [#116](https://github.com/danielvm-git/bigpowers/issues/116) [#116](https://github.com/danielvm-git/bigpowers/issues/116) [#114](https://github.com/danielvm-git/bigpowers/issues/114) [#116](https://github.com/danielvm-git/bigpowers/issues/116) [#114](https://github.com/danielvm-git/bigpowers/issues/114)
7
+
8
+ ## [2.87.7](https://github.com/danielvm-git/bigpowers/compare/v2.87.6...v2.87.7) (2026-09-01)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **packaging:** ship wire-ci CI templates in the npm tarball ([#115](https://github.com/danielvm-git/bigpowers/issues/115)) ([26df32b](https://github.com/danielvm-git/bigpowers/commit/26df32bc88310950863715dc26ca9c97dcaa4601)), closes [#113](https://github.com/danielvm-git/bigpowers/issues/113)
14
+
1
15
  ## [2.87.6](https://github.com/danielvm-git/bigpowers/compare/v2.87.5...v2.87.6) (2026-09-01)
2
16
 
3
17
 
package/README.md CHANGED
@@ -216,6 +216,25 @@ pi install .
216
216
  pi install npm:bigpowers
217
217
  ```
218
218
 
219
+ ### Provision a consumer project (`bigpowers init`)
220
+
221
+ pi's package contract registers **skills and prompts only** — it has no resource
222
+ type for arbitrary project files, and no lifecycle script runs on install. Skills
223
+ reference the package's `scripts/*.sh` tooling project-relative (e.g.
224
+ `bash scripts/run-skill-verify.sh`, verify gates like `test -f scripts/... &&
225
+ test -d specs/bugs`), so after installing the package, run **one command per
226
+ consumer project** to provision what the skills expect:
227
+
228
+ ```bash
229
+ cd <your-project>
230
+ npx bigpowers init # or: bigpowers init
231
+ ```
232
+
233
+ This symlinks `<project>/scripts` → the installed package's `scripts/` tree and
234
+ scaffolds `specs/bugs/` + `specs/verifications/`. It refuses (never clobbers) a
235
+ `scripts/` you already own; `bigpowers init --remove` undoes it. The same step
236
+ applies to `npm i -g bigpowers` / `npx bigpowers setup` consumers.
237
+
219
238
  **What you get:**
220
239
  - **pi skills** in `.pi/skills/` (one per SKILL.md) — loaded automatically into pi's system prompt as `<available_skills>`
221
240
  - **pi prompt templates** in `.pi/prompts/` — slash commands like `/survey-context`, `/plan-work`
package/bin/bigpowers.js CHANGED
@@ -75,6 +75,13 @@ if (cmd === 'setup' || cmd === 'install') {
75
75
  return;
76
76
  }
77
77
 
78
+ if (cmd === 'init') {
79
+ // Provision the CURRENT project (cwd): scripts/ link + specs/ scaffolding (#116)
80
+ const initScript = path.join(ROOT, 'bin', 'init.js');
81
+ require(initScript);
82
+ return;
83
+ }
84
+
78
85
  if (cmd === 'update') {
79
86
  // Pull the newest release first (global installs), then re-sync + refresh symlinks.
80
87
  selfUpdateGlobalPackage();
@@ -106,6 +113,7 @@ bigpowers — agent skills for spec-driven, test-first development
106
113
 
107
114
  Commands:
108
115
  bigpowers setup Install skills into ~/.claude/skills/
116
+ bigpowers init Provision the CURRENT project: scripts/ link + specs/ scaffolding (run per project)
109
117
  bigpowers update Fetch the latest release (global installs) + re-sync and refresh symlinks
110
118
  bigpowers status Show installed version and skill count (warns if a newer release exists)
111
119
  bigpowers help This message
package/bin/init.js ADDED
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ // bigpowers init — provision the CURRENT project (cwd) for skill tooling.
3
+ // story: BUG-2026-08-31-pi-scripts-provisioning (#116)
4
+ //
5
+ // Package installs (pi install npm:bigpowers, npm i -g, npx) register skills
6
+ // but never provision a project-local scripts/ tree — pi's package contract
7
+ // has no resource type for project files and no lifecycle script runs — so
8
+ // SKILL.md commands (`bash scripts/*.sh`) and `→ verify:` gates fail in every
9
+ // consumer project. `bigpowers init` (or `npx bigpowers init`) links the
10
+ // package's scripts/ into the project and scaffolds specs/{bugs,verifications}.
11
+
12
+ 'use strict';
13
+
14
+ const path = require('path');
15
+
16
+ const ROOT = path.dirname(path.dirname(__filename));
17
+ const { initProject, initProjectRemove } = require('../scripts/lib/install-helpers.js');
18
+
19
+ if (process.argv.includes('--remove')) {
20
+ initProjectRemove(ROOT);
21
+ console.log('bigpowers init --remove: removed the managed scripts/ link');
22
+ console.log(' (and specs/ scaffolding dirs only where untouched).');
23
+ process.exit(0);
24
+ }
25
+
26
+ try {
27
+ const result = initProject(ROOT);
28
+ if (result.skipped === 'cwd-is-package') {
29
+ console.log('bigpowers init: already inside the bigpowers package — nothing to provision.');
30
+ } else {
31
+ console.log('bigpowers init: linked scripts/ → package scripts tree.');
32
+ console.log('bigpowers init: ensured specs/bugs/ + specs/verifications/ scaffolding.');
33
+ console.log('Skill commands and verify gates (fix-bug, verify-work, wire-ci, …) now resolve here.');
34
+ }
35
+ } catch (e) {
36
+ // e.g. Refusing to replace a user-owned scripts/ — surface it, don't stack-trace.
37
+ console.error(`bigpowers init: ${e.message}`);
38
+ process.exit(1);
39
+ }
@@ -0,0 +1,89 @@
1
+ # story: e37s01
2
+ # story: e45s21
3
+ # story: e81s01
4
+ # scenario: SC-e37s01-P1-01
5
+ # [Project Name] — AI Agents
6
+
7
+ > **Multi-agent context** — This file is the canonical project context for **Cline**, **Aider**, **OpenCode**, and other AGENTS.md-native tools. Claude Code and Cursor read it via the `CLAUDE.md` symlink.
8
+
9
+ Read CONVENTIONS.md before any GitHub or git operation.
10
+
11
+ <!-- BEGIN bigpowers:context-routing -->
12
+ ## Context Routing
13
+
14
+ Load subdirectory context by file glob — see project-specific routing table (seeded by `seed-conventions`).
15
+ <!-- END bigpowers:context-routing -->
16
+
17
+ <!-- BEGIN bigpowers:learned-preferences -->
18
+ ## Learned User Preferences
19
+
20
+ - (none yet — updated via `session-state`)
21
+
22
+ ## Workspace Facts
23
+
24
+ - (none yet — durable facts discovered across sessions)
25
+ <!-- END bigpowers:learned-preferences -->
26
+
27
+ <!-- BEGIN bigpowers:project -->
28
+ ## Project
29
+
30
+ [One sentence. What this codebase does.]
31
+ Stack: [language, framework, runtime]
32
+
33
+ ## Commands
34
+
35
+ | Action | Command |
36
+ |--------|---------|
37
+ | Run | `[cmd]` |
38
+ | Test | `[cmd]` or N/A |
39
+ | Build | `[cmd]` |
40
+ | Lint | `[cmd]` |
41
+ | Preflight | `[test && lint && build chain — or user-named full-green cmd]` |
42
+ | CI | `gh pr checks` (when a PR is open) |
43
+
44
+ ## Test
45
+
46
+ `[cmd]` or N/A
47
+
48
+ ## Lint
49
+
50
+ `[cmd]` or N/A
51
+
52
+ ## Build
53
+
54
+ `[cmd]` or N/A
55
+
56
+ ## Architecture
57
+
58
+ [1–2 sentences. Key modules and their relationships.]
59
+
60
+ ## Conventions
61
+
62
+ - [e.g. Named exports only]
63
+ - [e.g. All queries go through the repository layer]
64
+
65
+ ## Never
66
+
67
+ - Never dismiss reproducible gate failures as pre-existing or out of scope
68
+ - Never proceed on red Preflight or red CI — invoke quick-fix or fix-bug first
69
+ - [Hard stop — e.g. Never touch legacy/]
70
+
71
+ ## Agent Rules
72
+
73
+ - **Workflow Mandate:** Use bigpowers skills (e.g. `plan-work`, `develop-tdd`) for structured work.
74
+ - **Always Green:** Preflight and CI must be green before forward work.
75
+ - Read specs/ and CONVENTIONS.md before writing code.
76
+ - Write the minimum code that solves the stated problem.
77
+ - Run tests after every change. Show evidence before declaring done.
78
+ - All planning output goes in specs/.
79
+
80
+ ## Token Economy — Minimal Footprint
81
+
82
+ > Production-safe subset of the 8-rule AGENTS.md pattern (Vercel engineer, ~60B tokens).
83
+ > Rule 1 ("no backward compatibility") is excluded deliberately: it risks data loss in production.
84
+
85
+ 1. **Check existing dependencies first.** DO inspect what your current dependencies already do before adding a package or writing your own code.
86
+ 2. **Prefer mature, maintained libraries.** DO NOT rewrite a capability a maintained library provides without a documented reason.
87
+ 3. **Copy validated patterns.** DO study how established products solve the same problem before inventing a new approach.
88
+ 4. **Keep the simplest working implementation.** DO write the least code that satisfies the stated requirement. NEVER add preventive abstraction or unused config layers.
89
+ <!-- END bigpowers:project -->
@@ -0,0 +1,68 @@
1
+ # Bundled bigpowers CI template — Go. See test-build-release-node.yml for
2
+ # the override mechanism (BIGPOWERS_CI_TEMPLATES). GH #104.
3
+ name: Test Build Release
4
+
5
+ on:
6
+ push:
7
+ branches: [main]
8
+ pull_request:
9
+ branches: [main]
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ lint:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v6
19
+ # Read the version from go.mod so `go vet` cannot drift from the module.
20
+ - uses: actions/setup-go@v5
21
+ with:
22
+ go-version-file: go.mod
23
+ cache: true
24
+ - run: go vet ./...
25
+
26
+ test:
27
+ runs-on: ubuntu-latest
28
+ needs: lint
29
+ steps:
30
+ - uses: actions/checkout@v6
31
+ - uses: actions/setup-go@v5
32
+ with:
33
+ go-version-file: go.mod
34
+ cache: true
35
+ - run: go test ./... -race
36
+
37
+ build:
38
+ runs-on: ubuntu-latest
39
+ needs: test
40
+ steps:
41
+ - uses: actions/checkout@v6
42
+ - uses: actions/setup-go@v5
43
+ with:
44
+ go-version-file: go.mod
45
+ cache: true
46
+ - run: go build ./...
47
+ - uses: actions/upload-artifact@v4
48
+ with:
49
+ name: dist
50
+ path: bin/
51
+ if-no-files-found: ignore
52
+
53
+ release:
54
+ runs-on: ubuntu-latest
55
+ needs: build
56
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
57
+ permissions:
58
+ contents: write
59
+ steps:
60
+ - uses: actions/checkout@v6
61
+ with:
62
+ fetch-depth: 0
63
+ - uses: actions/download-artifact@v4
64
+ with:
65
+ name: dist
66
+ path: bin/
67
+ continue-on-error: true
68
+ - run: echo "Add your release step (goreleaser, gh release create, ...) here"
@@ -0,0 +1,87 @@
1
+ # Bundled bigpowers CI template — Node.
2
+ # Ships inside the npm package so `wire-ci` has no network dependency on any
3
+ # third party's repository (GH #104). Override the source with
4
+ # BIGPOWERS_CI_TEMPLATES=/path/to/your/templates to use your own org templates.
5
+ #
6
+ # Keep `name:` as "Test Build Release" — deploy.yml listens for it via workflow_run.
7
+ name: Test Build Release
8
+
9
+ on:
10
+ push:
11
+ branches: [main]
12
+ pull_request:
13
+ branches: [main]
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ jobs:
19
+ lint:
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - uses: actions/checkout@v6
23
+ - uses: actions/setup-node@v4
24
+ with:
25
+ node-version-file: .nvmrc
26
+ cache: npm
27
+ - run: npm ci
28
+ - run: npm run lint --if-present
29
+
30
+ test:
31
+ runs-on: ubuntu-latest
32
+ needs: lint
33
+ steps:
34
+ - uses: actions/checkout@v6
35
+ - uses: actions/setup-node@v4
36
+ with:
37
+ node-version-file: .nvmrc
38
+ cache: npm
39
+ - run: npm ci
40
+ - run: npm test
41
+
42
+ build:
43
+ runs-on: ubuntu-latest
44
+ needs: test
45
+ steps:
46
+ - uses: actions/checkout@v6
47
+ - uses: actions/setup-node@v4
48
+ with:
49
+ node-version-file: .nvmrc
50
+ cache: npm
51
+ - run: npm ci
52
+ - run: npm run build --if-present
53
+ - uses: actions/upload-artifact@v4
54
+ with:
55
+ name: dist
56
+ path: dist/
57
+ if-no-files-found: ignore
58
+
59
+ release:
60
+ runs-on: ubuntu-latest
61
+ needs: build
62
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
63
+ permissions:
64
+ contents: write
65
+ issues: write
66
+ pull-requests: write
67
+ id-token: write
68
+ steps:
69
+ - uses: actions/checkout@v6
70
+ with:
71
+ fetch-depth: 0
72
+ - uses: actions/setup-node@v4
73
+ with:
74
+ node-version-file: .nvmrc
75
+ cache: npm
76
+ - run: npm ci
77
+ # Reuse the build output rather than rebuilding — a rebuilt binary is not
78
+ # the artifact that was tested.
79
+ - uses: actions/download-artifact@v4
80
+ with:
81
+ name: dist
82
+ path: dist/
83
+ continue-on-error: true
84
+ - run: npx semantic-release
85
+ env:
86
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
87
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -0,0 +1,74 @@
1
+ # Bundled bigpowers CI template — Python. See test-build-release-node.yml for
2
+ # the override mechanism (BIGPOWERS_CI_TEMPLATES). GH #104.
3
+ name: Test Build Release
4
+
5
+ on:
6
+ push:
7
+ branches: [main]
8
+ pull_request:
9
+ branches: [main]
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ env:
15
+ PYTHON_VERSION: '3.12'
16
+
17
+ jobs:
18
+ lint:
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v6
22
+ - uses: actions/setup-python@v5
23
+ with:
24
+ python-version: ${{ env.PYTHON_VERSION }}
25
+ cache: pip
26
+ - run: pip install -r requirements.txt
27
+ - run: ruff check .
28
+
29
+ test:
30
+ runs-on: ubuntu-latest
31
+ needs: lint
32
+ steps:
33
+ - uses: actions/checkout@v6
34
+ - uses: actions/setup-python@v5
35
+ with:
36
+ python-version: ${{ env.PYTHON_VERSION }}
37
+ cache: pip
38
+ - run: pip install -r requirements.txt
39
+ - run: pytest
40
+
41
+ build:
42
+ runs-on: ubuntu-latest
43
+ needs: test
44
+ steps:
45
+ - uses: actions/checkout@v6
46
+ - uses: actions/setup-python@v5
47
+ with:
48
+ python-version: ${{ env.PYTHON_VERSION }}
49
+ - run: pip install build
50
+ - run: python -m build
51
+ - uses: actions/upload-artifact@v4
52
+ with:
53
+ name: dist
54
+ path: dist/
55
+ if-no-files-found: ignore
56
+
57
+ release:
58
+ runs-on: ubuntu-latest
59
+ needs: build
60
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
61
+ permissions:
62
+ contents: write
63
+ id-token: write
64
+ steps:
65
+ - uses: actions/checkout@v6
66
+ with:
67
+ fetch-depth: 0
68
+ - uses: actions/download-artifact@v4
69
+ with:
70
+ name: dist
71
+ path: dist/
72
+ - uses: pypa/gh-action-pypi-publish@release/v1
73
+ with:
74
+ skip-existing: true
@@ -0,0 +1,67 @@
1
+ # Bundled bigpowers CI template — Rust. See test-build-release-node.yml for
2
+ # the override mechanism (BIGPOWERS_CI_TEMPLATES). GH #104.
3
+ name: Test Build Release
4
+
5
+ on:
6
+ push:
7
+ branches: [main]
8
+ pull_request:
9
+ branches: [main]
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ env:
15
+ CARGO_TERM_COLOR: always
16
+
17
+ jobs:
18
+ lint:
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v6
22
+ - uses: dtolnay/rust-toolchain@stable
23
+ with:
24
+ components: clippy, rustfmt
25
+ - uses: Swatinem/rust-cache@v2
26
+ - run: cargo fmt --check
27
+ # Pin clippy to the stable toolchain above: new nightly lints otherwise
28
+ # break CI on days nobody changed the code.
29
+ - run: cargo clippy --all-targets -- -D warnings
30
+
31
+ test:
32
+ runs-on: ubuntu-latest
33
+ needs: lint
34
+ steps:
35
+ - uses: actions/checkout@v6
36
+ - uses: dtolnay/rust-toolchain@stable
37
+ - uses: Swatinem/rust-cache@v2
38
+ - run: cargo test --all
39
+
40
+ build:
41
+ runs-on: ubuntu-latest
42
+ needs: test
43
+ steps:
44
+ - uses: actions/checkout@v6
45
+ - uses: dtolnay/rust-toolchain@stable
46
+ - uses: Swatinem/rust-cache@v2
47
+ - run: cargo build --release
48
+ - uses: actions/upload-artifact@v4
49
+ with:
50
+ name: dist
51
+ path: target/release/
52
+ if-no-files-found: ignore
53
+
54
+ release:
55
+ runs-on: ubuntu-latest
56
+ needs: build
57
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
58
+ permissions:
59
+ contents: write
60
+ steps:
61
+ - uses: actions/checkout@v6
62
+ with:
63
+ fetch-depth: 0
64
+ - uses: dtolnay/rust-toolchain@stable
65
+ - run: cargo publish --no-verify
66
+ env:
67
+ CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bigpowers",
3
- "version": "2.87.6",
3
+ "version": "2.87.8",
4
4
  "description": "73 agent skills synthesizing 17 years of software engineering discipline into a prescriptive methodology for solo developers",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -36,7 +36,11 @@ function assertReplaceable(dst) {
36
36
  }
37
37
  if (st.isSymbolicLink()) {
38
38
  const target = fs.readlinkSync(dst);
39
- if (target.startsWith(REPO_ROOT)) return; // managed by bigpowers — safe to re-link
39
+ // Path-separator boundary: a string-prefix sibling of the package root
40
+ // (e.g. <ROOT>-evil) is NOT managed by this package.
41
+ if (target === REPO_ROOT || target.startsWith(REPO_ROOT + path.sep)) {
42
+ return; // managed by bigpowers — safe to re-link
43
+ }
40
44
  }
41
45
  throw new Error(
42
46
  `Refusing to replace ${dst}: it exists and is not a bigpowers-managed symlink. ` +
@@ -416,6 +420,52 @@ function installLocal(tool, repoRoot) {
416
420
  }
417
421
  }
418
422
 
423
+ // ── Project provisioning (bigpowers init) ────────────────────────────────────
424
+
425
+ // Provision the CURRENT project (cwd) with the package's scripts/ tree and the
426
+ // specs/ scaffolding skill bodies assume. Package installs (pi, npm -g, npx)
427
+ // register skills but pi's package contract has no resource type for project
428
+ // files and no lifecycle script runs — so `bash scripts/*.sh` invocations and
429
+ // `→ verify:` gates in SKILL.md files fail outside a bigpowers checkout. (#116)
430
+ function initProject(repoRoot) {
431
+ const cwd = process.cwd();
432
+ if (path.resolve(cwd) === path.resolve(repoRoot)) {
433
+ return { skipped: 'cwd-is-package' };
434
+ }
435
+ linkDir(path.join(repoRoot, 'scripts'), path.join(cwd, 'scripts'));
436
+ const created = [];
437
+ for (const rel of [path.join('specs', 'bugs'), path.join('specs', 'verifications')]) {
438
+ const dir = path.join(cwd, rel);
439
+ if (!fs.existsSync(dir)) {
440
+ fs.mkdirSync(dir, { recursive: true });
441
+ created.push(rel);
442
+ }
443
+ }
444
+ return { skipped: null, scriptsLinked: true, created };
445
+ }
446
+
447
+ // Inverse of initProject: remove ONLY the managed scripts symlink and specs/
448
+ // scaffolding dirs we created (and only while untouched — user content survives).
449
+ function initProjectRemove(repoRoot) {
450
+ const cwd = process.cwd();
451
+ const scriptsLink = path.join(cwd, 'scripts');
452
+ try {
453
+ if (fs.lstatSync(scriptsLink).isSymbolicLink()
454
+ && fs.readlinkSync(scriptsLink) === path.join(repoRoot, 'scripts')) {
455
+ fs.unlinkSync(scriptsLink);
456
+ }
457
+ } catch {}
458
+ for (const rel of [path.join('specs', 'bugs'), path.join('specs', 'verifications'), 'specs']) {
459
+ const dir = path.join(cwd, rel);
460
+ try {
461
+ if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()
462
+ && fs.readdirSync(dir).length === 0) {
463
+ fs.rmdirSync(dir);
464
+ }
465
+ } catch {}
466
+ }
467
+ }
468
+
419
469
  // ── Uninstall per tool ───────────────────────────────────────────────────────
420
470
 
421
471
  function uninstallTool(toolId, repoRoot) {
@@ -694,6 +744,8 @@ module.exports = {
694
744
  linkHook,
695
745
  installGlobal,
696
746
  installLocal,
747
+ initProject,
748
+ initProjectRemove,
697
749
  uninstallTool,
698
750
  removeSymlink,
699
751
  detectExistingInstall,
@@ -230,6 +230,7 @@ try {
230
230
  '.cursor/rules',
231
231
  '.pi/skills',
232
232
  'skills/audit-code/SKILL.md',
233
+ 'docs/templates/ci/github/test-build-release-node.yml',
233
234
  ];
234
235
  const isIgnored = (p) =>
235
236
  npmignore.some((pat) => {
@@ -244,6 +245,118 @@ try {
244
245
  }
245
246
  }
246
247
 
248
+ // story: #113 — wire-ci templates must actually ship in the npm tarball.
249
+ // The .npmignore pattern check above is necessary but not sufficient (it
250
+ // cannot model gitignore negation); prove it with a real pack listing.
251
+ {
252
+ const { execSync } = require('child_process');
253
+ const packOut = execSync('npm pack --dry-run 2>&1', {
254
+ cwd: ROOT,
255
+ encoding: 'utf8',
256
+ maxBuffer: 16 * 1024 * 1024,
257
+ });
258
+ for (const tpl of [
259
+ 'docs/templates/ci/github/test-build-release-node.yml',
260
+ 'docs/templates/ci/github/test-build-release-rust.yml',
261
+ 'docs/templates/ci/github/test-build-release-python.yml',
262
+ 'docs/templates/ci/github/test-build-release-go.yml',
263
+ 'docs/templates/AGENTS.md',
264
+ ]) {
265
+ assert.ok(
266
+ packOut.includes(tpl),
267
+ `npm tarball must include ${tpl} (wire-ci templates, #113)`
268
+ );
269
+ }
270
+ }
271
+
272
+ // story: BUG-2026-08-31-pi-scripts-provisioning (#116)
273
+ // A package consumer project needs bigpowers' scripts/ + specs/ scaffolding
274
+ // so SKILL.md bodies ("bash scripts/run-skill-verify.sh") and verify gates
275
+ // ("test -f scripts/... && test -d specs/bugs") resolve outside a checkout.
276
+ {
277
+ const { initProject, initProjectRemove } = require('../scripts/lib/install-helpers.js');
278
+ const savedInitCwd = process.cwd();
279
+ const consumerDir = mkdtempSync(path.join(os.tmpdir(), 'bp-init-project-'));
280
+ try {
281
+ process.chdir(consumerDir);
282
+
283
+ // (a) init provisions scripts/ + specs/ scaffolding
284
+ initProject(ROOT);
285
+ assert.ok(
286
+ fs.lstatSync(path.join(consumerDir, 'scripts')).isSymbolicLink(),
287
+ 'init must symlink scripts/ into the consumer project'
288
+ );
289
+ assert.strictEqual(
290
+ fs.readlinkSync(path.join(consumerDir, 'scripts')),
291
+ path.join(ROOT, 'scripts'),
292
+ 'scripts symlink must point at the package scripts tree'
293
+ );
294
+ assert.ok(
295
+ fs.existsSync(path.join(consumerDir, 'scripts', 'run-skill-verify.sh')),
296
+ 'scripts/run-skill-verify.sh must resolve through the link (skill verify gate)'
297
+ );
298
+ assert.ok(
299
+ fs.existsSync(path.join(consumerDir, 'specs', 'bugs')),
300
+ 'init must scaffold specs/bugs (fix-bug verify gate probes it)'
301
+ );
302
+ assert.ok(
303
+ fs.existsSync(path.join(consumerDir, 'specs', 'verifications')),
304
+ 'init must scaffold specs/verifications'
305
+ );
306
+
307
+ // (b) init --remove cleans managed artifacts only
308
+ initProjectRemove(ROOT);
309
+ assert.ok(
310
+ !fs.existsSync(path.join(consumerDir, 'scripts')),
311
+ 'init --remove must remove the managed scripts symlink'
312
+ );
313
+ assert.ok(
314
+ !fs.existsSync(path.join(consumerDir, 'specs')),
315
+ 'init --remove must remove the untouched scaffolded specs tree'
316
+ );
317
+
318
+ // (c) refuses a pre-existing non-managed scripts/ (never clobbers)
319
+ fs.mkdirSync(path.join(consumerDir, 'scripts'));
320
+ fs.writeFileSync(path.join(consumerDir, 'scripts', 'mine.sh'), 'echo mine\n');
321
+ assert.throws(
322
+ () => initProject(ROOT),
323
+ /Refusing to replace/,
324
+ 'init must refuse a user-owned scripts/ dir'
325
+ );
326
+ assert.ok(
327
+ fs.existsSync(path.join(consumerDir, 'scripts', 'mine.sh')),
328
+ 'user-owned scripts/ content must survive the refusal'
329
+ );
330
+ } finally {
331
+ process.chdir(savedInitCwd);
332
+ rmSync(consumerDir, { recursive: true, force: true });
333
+ }
334
+
335
+ // (d) CLI dispatch drift guard: `bigpowers init` must stay wired
336
+ const bigpowersSrc = fs.readFileSync(path.join(ROOT, 'bin', 'bigpowers.js'), 'utf8');
337
+ assert.ok(
338
+ /'init'/.test(bigpowersSrc),
339
+ "bin/bigpowers.js must dispatch the 'init' command"
340
+ );
341
+ assert.ok(
342
+ fs.existsSync(path.join(ROOT, 'bin', 'init.js')),
343
+ 'bin/init.js must exist'
344
+ );
345
+ }
346
+
347
+ // story: BUG-2026-08-31-pi-scripts-provisioning (follow-up from PR #114 review)
348
+ // The managed-symlink check must not treat a string-prefix sibling of the
349
+ // package root (e.g. <ROOT>-evil) as managed — needs a path-separator boundary.
350
+ {
351
+ const dst = path.join(tmpHome, 'prefix-boundary-hook.sh');
352
+ fs.symlinkSync(path.join(`${ROOT}-evil`, 'x.sh'), dst); // dangling foreign link
353
+ assert.throws(
354
+ () => linkHook(rtkSrc, dst),
355
+ /Refusing to replace/,
356
+ 'managed-symlink check must require a path-separator boundary (prefix sibling is NOT managed)'
357
+ );
358
+ }
359
+
247
360
  console.log('test-install-helpers: ALL PASS');
248
361
  } finally {
249
362
  rmSync(tmpHome, { recursive: true, force: true });