bigpowers 2.21.0 → 2.23.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.
package/.pi/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bigpowers",
3
- "version": "2.21.0",
3
+ "version": "2.23.0",
4
4
  "description": "68 skills — 61 agent skills for spec-driven, test-first software development by solo developers",
5
5
  "keywords": [
6
6
  "pi-package"
@@ -24,7 +24,7 @@ Orchestrates the **build** flow for a single epic: survey → plan tasks → kic
24
24
  | 5 | `verify-work` — UAT + mechanical gates |
25
25
  | 6 | `audit-code` — **non-optional gate** (pass/fail; fail → loop back to step 4) |
26
26
  | 7 | `commit-message` — Conventional Commits draft |
27
- | 8 | `release-branch` — PR or solo land |
27
+ | 8 | `release-branch` — PR or solo land (supports `--squash-state`) |
28
28
 
29
29
  ## Process
30
30
 
@@ -12,6 +12,7 @@ Finalize a completed feature branch: verify coverage gates, integrate onto `main
12
12
  ## Additional modes
13
13
 
14
14
  - `--hotfix`: Emergency fix. Cherry-pick to main plus immediate tag. Skip PR in solo profile.
15
+ - `--squash-state`: Squashes all intermediate `chore(state):` commits on the feature branch into a single clean commit before merging. Use this to reduce noise in the main git repository history.
15
16
 
16
17
  ## Integrate mode
17
18
 
@@ -11,8 +11,29 @@ description: Look-before-build — search registries, repo, existing skills, and
11
11
 
12
12
  1. Read `specs/product/SCOPE_LATEST.yaml`, `specs/release-plan.yaml + epic shards`, and the current task statement.
13
13
  2. Search in order: this repo → bigpowers skills (`search-skills`) → package registries → web docs.
14
- 3. For each candidate: note name, URL/path, fit (adopt | extend | compose | build).
15
- 4. Append `## Prior Art` to `requirements/SCOPE_LATEST.yaml` notes or the active epic story.
14
+ 3. **Check opensrc cache** if the task integrates an external library, run `bash scripts/bp-opensrc-check.sh` (or `npx opensrc search <pkg>`) to find locally-cached source. Read the `src/` directory for API shapes before writing any integration code.
15
+ 4. For each candidate: note name, URL/path, fit (adopt | extend | compose | build).
16
+ 5. Append `## Prior Art` to `requirements/SCOPE_LATEST.yaml` notes or the active epic story.
17
+
18
+ ## opensrc Integration
19
+
20
+ `opensrc` is a local cache of 200+ open-source repos and npm/PyPI packages. Query it before building any external integration to avoid re-inventing documented API shapes.
21
+
22
+ ```bash
23
+ # Check if a package is cached
24
+ npx opensrc search <package-name>
25
+
26
+ # Or use the bundled helper (checks all deps from package.json or requirements.txt)
27
+ bash scripts/bp-opensrc-check.sh [package.json|requirements.txt]
28
+ ```
29
+
30
+ If opensrc finds a match, read its `src/` or source directory and append findings to the **Prior Art** section:
31
+
32
+ ```
33
+ opensrc: found <pkg> v<version> — exports <key classes/functions>
34
+ ```
35
+
36
+ If opensrc is not installed or the package is not cached, fall through to web docs normally.
16
37
 
17
38
  ## Outcome matrix
18
39
 
@@ -26,7 +26,7 @@ Orchestrates the **build** flow for a single epic: survey → plan tasks → kic
26
26
  | 5 | `verify-work` — UAT + mechanical gates |
27
27
  | 6 | `audit-code` — **non-optional gate** (pass/fail; fail → loop back to step 4) |
28
28
  | 7 | `commit-message` — Conventional Commits draft |
29
- | 8 | `release-branch` — PR or solo land |
29
+ | 8 | `release-branch` — PR or solo land (supports `--squash-state`) |
30
30
 
31
31
  ## Process
32
32
 
@@ -14,6 +14,7 @@ Finalize a completed feature branch: verify coverage gates, integrate onto `main
14
14
  ## Additional modes
15
15
 
16
16
  - `--hotfix`: Emergency fix. Cherry-pick to main plus immediate tag. Skip PR in solo profile.
17
+ - `--squash-state`: Squashes all intermediate `chore(state):` commits on the feature branch into a single clean commit before merging. Use this to reduce noise in the main git repository history.
17
18
 
18
19
  ## Integrate mode
19
20
 
@@ -13,8 +13,29 @@ model: sonnet
13
13
 
14
14
  1. Read `specs/product/SCOPE_LATEST.yaml`, `specs/release-plan.yaml + epic shards`, and the current task statement.
15
15
  2. Search in order: this repo → bigpowers skills (`search-skills`) → package registries → web docs.
16
- 3. For each candidate: note name, URL/path, fit (adopt | extend | compose | build).
17
- 4. Append `## Prior Art` to `requirements/SCOPE_LATEST.yaml` notes or the active epic story.
16
+ 3. **Check opensrc cache** if the task integrates an external library, run `bash scripts/bp-opensrc-check.sh` (or `npx opensrc search <pkg>`) to find locally-cached source. Read the `src/` directory for API shapes before writing any integration code.
17
+ 4. For each candidate: note name, URL/path, fit (adopt | extend | compose | build).
18
+ 5. Append `## Prior Art` to `requirements/SCOPE_LATEST.yaml` notes or the active epic story.
19
+
20
+ ## opensrc Integration
21
+
22
+ `opensrc` is a local cache of 200+ open-source repos and npm/PyPI packages. Query it before building any external integration to avoid re-inventing documented API shapes.
23
+
24
+ ```bash
25
+ # Check if a package is cached
26
+ npx opensrc search <package-name>
27
+
28
+ # Or use the bundled helper (checks all deps from package.json or requirements.txt)
29
+ bash scripts/bp-opensrc-check.sh [package.json|requirements.txt]
30
+ ```
31
+
32
+ If opensrc finds a match, read its `src/` or source directory and append findings to the **Prior Art** section:
33
+
34
+ ```
35
+ opensrc: found <pkg> v<version> — exports <key classes/functions>
36
+ ```
37
+
38
+ If opensrc is not installed or the package is not cached, fall through to web docs normally.
18
39
 
19
40
  ## Outcome matrix
20
41
 
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [2.23.0](https://github.com/danielvm-git/bigpowers/compare/v2.22.0...v2.23.0) (2026-06-22)
2
+
3
+
4
+ ### Features
5
+
6
+ * **research-first:** add opensrc cache check before building ([9921db6](https://github.com/danielvm-git/bigpowers/commit/9921db68c05b914da8e924a3fbba0d03e6e9dd35))
7
+
8
+ # [2.22.0](https://github.com/danielvm-git/bigpowers/compare/v2.21.0...v2.22.0) (2026-06-22)
9
+
10
+
11
+ ### Features
12
+
13
+ * **mcp-server:** add MCP server exposing 68 skills as MCP tools ([58c4592](https://github.com/danielvm-git/bigpowers/commit/58c45925d63c505c8eadf1443b6268f4d8791715))
14
+
1
15
  # [2.21.0](https://github.com/danielvm-git/bigpowers/compare/v2.20.0...v2.21.0) (2026-06-22)
2
16
 
3
17
 
package/CONVENTIONS.md CHANGED
@@ -24,6 +24,7 @@ All changes to this repository MUST follow the [Conventional Commits 1.0.0](http
24
24
  - Use `gh run view` / `gh run watch` for CI status
25
25
  - Verify auth with `gh auth status` before operations
26
26
  - **Git Attribution:** NEVER include `Co-authored-by`, `Co-Authored-By`, or any other footer that attributes code to an AI agent (e.g., Claude, Gemini). All commits must appear as if they were authored solely by the human user.
27
+ - **State Commit Policy:** To minimize git history noise, intermediate `chore(state):` commits (e.g., tracking build-epic step transitions) should either be squashed locally using the `--squash-state` flag on `release-branch` before merging, or kept out-of-band using local cycle-state files.
27
28
  - Never call GitHub REST API directly (curl, fetch, etc.)
28
29
  - Never create GitHub issues from automated workflows — produce local .md files in specs/ instead
29
30
 
package/README.md CHANGED
@@ -122,6 +122,47 @@ pi install npm:bigpowers
122
122
 
123
123
  Skills are loaded on-demand via progressive disclosure: only descriptions are always in context; the full SKILL.md loads when the agent reads it. Prompt templates expand in pi's editor with autocomplete.
124
124
 
125
+ ## 🔧 MCP Server (Model Context Protocol)
126
+
127
+ bigpowers ships an MCP server that exposes all skills as callable MCP tools. Agents can discover and invoke skills dynamically instead of relying on a static system prompt.
128
+
129
+ ### Start the server
130
+
131
+ ```bash
132
+ node scripts/mcp-server.js
133
+ ```
134
+
135
+ ### Add to Claude Code
136
+
137
+ ```bash
138
+ claude mcp add bigpowers node /path/to/bigpowers/scripts/mcp-server.js
139
+ ```
140
+
141
+ Or add manually to `.claude/settings.json`:
142
+
143
+ ```json
144
+ {
145
+ "mcpServers": {
146
+ "bigpowers": {
147
+ "command": "node",
148
+ "args": ["/path/to/bigpowers/scripts/mcp-server.js"]
149
+ }
150
+ }
151
+ }
152
+ ```
153
+
154
+ ### Available MCP tools
155
+
156
+ | Tool | Description |
157
+ |------|-------------|
158
+ | `bigpowers_list_skills` | List all 68 skills with name, description, phase. Optional `phase` filter. |
159
+ | `bigpowers_get_skill` | Get full SKILL.md content for any skill by name. |
160
+ | `bigpowers_search_skills` | Keyword/semantic search — returns ranked matches for a query. |
161
+ | `bigpowers_get_state` | Get current `specs/state.yaml` (active flow, epic, step). |
162
+ | `bigpowers_invoke_skill` | Get skill instructions with optional context for agent invocation. |
163
+
164
+ ---
165
+
125
166
  ## 🏗 The v2.0.0 Lifecycle
126
167
 
127
168
  Every project follows the **orchestrate-project 6-phase model** (full SOP: [`docs/WORKFLOW-SOP-v2.md`](docs/WORKFLOW-SOP-v2.md)):
package/SKILL-INDEX.md CHANGED
@@ -3,7 +3,7 @@
3
3
  > **DO NOT EDIT** — This file is auto-generated by `scripts/generate-skill-index.sh`.
4
4
  > Edit `SKILL.md` source files or `skills-lock.json` instead. Run `bash scripts/sync-skills.sh` to regenerate.
5
5
 
6
- **Generated:** 2026-06-22T01:58:28Z
6
+ **Generated:** 2026-06-22T02:23:04Z
7
7
  **Skills:** 68
8
8
 
9
9
  ---
@@ -25,7 +25,7 @@ Orchestrates the **build** flow for a single epic: survey → plan tasks → kic
25
25
  | 5 | `verify-work` — UAT + mechanical gates |
26
26
  | 6 | `audit-code` — **non-optional gate** (pass/fail; fail → loop back to step 4) |
27
27
  | 7 | `commit-message` — Conventional Commits draft |
28
- | 8 | `release-branch` — PR or solo land |
28
+ | 8 | `release-branch` — PR or solo land (supports `--squash-state`) |
29
29
 
30
30
  ## Process
31
31
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bigpowers",
3
- "version": "2.21.0",
3
+ "version": "2.23.0",
4
4
  "description": "61 agent skills for spec-driven, test-first software development by solo developers",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -13,6 +13,7 @@ Finalize a completed feature branch: verify coverage gates, integrate onto `main
13
13
  ## Additional modes
14
14
 
15
15
  - `--hotfix`: Emergency fix. Cherry-pick to main plus immediate tag. Skip PR in solo profile.
16
+ - `--squash-state`: Squashes all intermediate `chore(state):` commits on the feature branch into a single clean commit before merging. Use this to reduce noise in the main git repository history.
16
17
 
17
18
  ## Integrate mode
18
19
 
@@ -12,8 +12,29 @@ model: sonnet
12
12
 
13
13
  1. Read `specs/product/SCOPE_LATEST.yaml`, `specs/release-plan.yaml + epic shards`, and the current task statement.
14
14
  2. Search in order: this repo → bigpowers skills (`search-skills`) → package registries → web docs.
15
- 3. For each candidate: note name, URL/path, fit (adopt | extend | compose | build).
16
- 4. Append `## Prior Art` to `requirements/SCOPE_LATEST.yaml` notes or the active epic story.
15
+ 3. **Check opensrc cache** if the task integrates an external library, run `bash scripts/bp-opensrc-check.sh` (or `npx opensrc search <pkg>`) to find locally-cached source. Read the `src/` directory for API shapes before writing any integration code.
16
+ 4. For each candidate: note name, URL/path, fit (adopt | extend | compose | build).
17
+ 5. Append `## Prior Art` to `requirements/SCOPE_LATEST.yaml` notes or the active epic story.
18
+
19
+ ## opensrc Integration
20
+
21
+ `opensrc` is a local cache of 200+ open-source repos and npm/PyPI packages. Query it before building any external integration to avoid re-inventing documented API shapes.
22
+
23
+ ```bash
24
+ # Check if a package is cached
25
+ npx opensrc search <package-name>
26
+
27
+ # Or use the bundled helper (checks all deps from package.json or requirements.txt)
28
+ bash scripts/bp-opensrc-check.sh [package.json|requirements.txt]
29
+ ```
30
+
31
+ If opensrc finds a match, read its `src/` or source directory and append findings to the **Prior Art** section:
32
+
33
+ ```
34
+ opensrc: found <pkg> v<version> — exports <key classes/functions>
35
+ ```
36
+
37
+ If opensrc is not installed or the package is not cached, fall through to web docs normally.
17
38
 
18
39
  ## Outcome matrix
19
40
 
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env bash
2
+ # bp-opensrc-check.sh — Check project dependencies against the local opensrc cache.
3
+ # Usage: bash scripts/bp-opensrc-check.sh [package.json|requirements.txt]
4
+ # Output: one line per dependency — FOUND or NOT CACHED, with local path when found.
5
+ set -euo pipefail
6
+
7
+ INPUT="${1:-package.json}"
8
+
9
+ if ! command -v npx >/dev/null 2>&1; then
10
+ echo "SKIP: npx not found — opensrc requires Node.js" >&2
11
+ exit 0
12
+ fi
13
+
14
+ if ! npx opensrc --version >/dev/null 2>&1; then
15
+ echo "SKIP: opensrc not installed — run: npm install -g opensrc" >&2
16
+ exit 0
17
+ fi
18
+
19
+ extract_deps() {
20
+ local file="$1"
21
+ case "$file" in
22
+ *.json)
23
+ python3 -c "
24
+ import json, sys
25
+ data = json.load(open('$file'))
26
+ deps = list(data.get('dependencies', {}).keys()) + list(data.get('devDependencies', {}).keys())
27
+ print('\n'.join(deps))
28
+ " 2>/dev/null || true
29
+ ;;
30
+ requirements*.txt)
31
+ grep -v '^#' "$file" | grep -v '^$' | sed 's/[>=<!].*//' | tr -d ' ' || true
32
+ ;;
33
+ *)
34
+ echo "WARN: unsupported file type: $file — pass package.json or requirements.txt" >&2
35
+ exit 1
36
+ ;;
37
+ esac
38
+ }
39
+
40
+ if [ ! -f "$INPUT" ]; then
41
+ echo "WARN: $INPUT not found" >&2
42
+ exit 0
43
+ fi
44
+
45
+ echo "opensrc cache check: $INPUT"
46
+ echo "---"
47
+
48
+ FOUND=0
49
+ MISSING=0
50
+
51
+ while IFS= read -r dep; do
52
+ [ -z "$dep" ] && continue
53
+ result=$(npx opensrc search "$dep" 2>/dev/null | head -1 || true)
54
+ if [ -n "$result" ]; then
55
+ echo "FOUND $dep — $result"
56
+ FOUND=$((FOUND + 1))
57
+ else
58
+ echo "NOT CACHED $dep"
59
+ MISSING=$((MISSING + 1))
60
+ fi
61
+ done < <(extract_deps "$INPUT")
62
+
63
+ echo "---"
64
+ echo "Summary: $FOUND cached, $MISSING not cached"
@@ -0,0 +1,246 @@
1
+ #!/usr/bin/env node
2
+ // bigpowers MCP server — exposes 68 skills as MCP tools via stdio transport
3
+ // Zero dependencies — raw JSON-RPC over stdio with Content-Length framing
4
+
5
+ 'use strict';
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+
10
+ const ROOT = path.resolve(__dirname, '..');
11
+ const SKILLS_LOCK = path.join(ROOT, 'skills-lock.json');
12
+ const STATE_YAML = path.join(ROOT, 'specs', 'state.yaml');
13
+
14
+ // Phase map — mirrors generate-skill-index.sh PHASE_MAP
15
+ const PHASE_MAP = {
16
+ 'survey-context': 'Discover', 'research-first': 'Discover', 'search-skills': 'Discover',
17
+ 'using-bigpowers': 'Discover', 'map-codebase': 'Discover', 'elaborate-spec': 'Discover',
18
+ 'model-domain': 'Design', 'define-language': 'Design', 'grill-me': 'Design',
19
+ 'grill-with-docs': 'Design', 'deepen-architecture': 'Design', 'design-interface': 'Design',
20
+ 'define-success': 'Design',
21
+ 'scope-work': 'Plan', 'slice-tasks': 'Plan', 'plan-work': 'Plan', 'plan-release': 'Plan',
22
+ 'plan-refactor': 'Plan', 'assess-impact': 'Plan', 'change-request': 'Plan',
23
+ 'run-planning': 'Plan', 'seed-conventions': 'Plan',
24
+ 'develop-tdd': 'Build', 'kickoff-branch': 'Build', 'execute-plan': 'Build',
25
+ 'build-epic': 'Build', 'spike-prototype': 'Build', 'craft-skill': 'Build',
26
+ 'quick-fix': 'Build', 'setup-environment': 'Build', 'wire-observability': 'Build',
27
+ 'wire-ci': 'Build', 'publish-package': 'Build', 'align-grid': 'Build',
28
+ 'orchestrate-project': 'Build', 'guard-git': 'Build', 'hook-commits': 'Build',
29
+ 'deploy': 'Build', 'smoke-test': 'Build', 'validate-contracts': 'Build',
30
+ 'verify-work': 'Verify', 'validate-fix': 'Verify', 'audit-code': 'Verify',
31
+ 'enforce-first': 'Verify', 'run-evals': 'Verify', 'investigate-bug': 'Verify',
32
+ 'diagnose-root': 'Verify', 'fix-bug': 'Verify', 'inspect-quality': 'Verify',
33
+ 'request-review': 'Verify', 'respond-review': 'Verify', 'trace-requirement': 'Verify',
34
+ 'release-branch': 'Release', 'commit-message': 'Release',
35
+ 'session-state': 'Sustain', 'terse-mode': 'Sustain', 'compose-workflow': 'Sustain',
36
+ 'delegate-task': 'Sustain', 'dispatch-agents': 'Sustain', 'edit-document': 'Sustain',
37
+ 'evolve-skill': 'Sustain', 'migrate-spec': 'Sustain', 'organize-workspace': 'Sustain',
38
+ 'reset-baseline': 'Sustain', 'simulate-agents': 'Sustain', 'stocktake-skills': 'Sustain',
39
+ 'write-document': 'Sustain',
40
+ };
41
+
42
+ function loadSkillsCatalog() {
43
+ const lock = JSON.parse(fs.readFileSync(SKILLS_LOCK, 'utf8'));
44
+ return Object.entries(lock.skills).map(([name, meta]) => ({
45
+ name,
46
+ description: meta.description,
47
+ path: meta.path,
48
+ phase: PHASE_MAP[name] || 'Other',
49
+ }));
50
+ }
51
+
52
+ function getSkillContent(skillName) {
53
+ const catalog = loadSkillsCatalog();
54
+ const skill = catalog.find(s => s.name === skillName);
55
+ if (!skill) return null;
56
+ const skillPath = path.join(ROOT, skill.path);
57
+ if (!fs.existsSync(skillPath)) return null;
58
+ return fs.readFileSync(skillPath, 'utf8');
59
+ }
60
+
61
+ function searchSkills(query) {
62
+ const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
63
+ const catalog = loadSkillsCatalog();
64
+ return catalog
65
+ .map(skill => {
66
+ const haystack = `${skill.name} ${skill.description} ${skill.phase}`.toLowerCase();
67
+ const score = terms.reduce((s, t) => s + (haystack.includes(t) ? 1 : 0), 0);
68
+ return { skill, score };
69
+ })
70
+ .filter(({ score }) => score > 0)
71
+ .sort((a, b) => b.score - a.score)
72
+ .map(({ skill }) => skill);
73
+ }
74
+
75
+ // Tool handlers
76
+ const TOOLS = {
77
+ bigpowers_list_skills: {
78
+ description: 'List all bigpowers skills with name, description, and lifecycle phase. Optionally filter by phase.',
79
+ inputSchema: {
80
+ type: 'object',
81
+ properties: {
82
+ phase: {
83
+ type: 'string',
84
+ description: 'Filter by lifecycle phase: Discover, Design, Plan, Build, Verify, Release, Sustain',
85
+ },
86
+ },
87
+ },
88
+ handler({ phase } = {}) {
89
+ let skills = loadSkillsCatalog();
90
+ if (phase) skills = skills.filter(s => s.phase.toLowerCase() === phase.toLowerCase());
91
+ return skills.map(({ name, description, phase: p }) => ({ name, description, phase: p }));
92
+ },
93
+ },
94
+
95
+ bigpowers_get_skill: {
96
+ description: 'Get the full SKILL.md content for a specific bigpowers skill by name.',
97
+ inputSchema: {
98
+ type: 'object',
99
+ properties: {
100
+ name: { type: 'string', description: 'Skill name (kebab-case, e.g. "survey-context")' },
101
+ },
102
+ required: ['name'],
103
+ },
104
+ handler({ name }) {
105
+ const content = getSkillContent(name);
106
+ if (!content) return { error: `Skill "${name}" not found` };
107
+ return { name, content };
108
+ },
109
+ },
110
+
111
+ bigpowers_search_skills: {
112
+ description: 'Search bigpowers skills by keyword or intent. Returns matching skills ranked by relevance.',
113
+ inputSchema: {
114
+ type: 'object',
115
+ properties: {
116
+ query: { type: 'string', description: 'Natural language query or keywords, e.g. "deploy to production"' },
117
+ },
118
+ required: ['query'],
119
+ },
120
+ handler({ query }) {
121
+ return searchSkills(query).map(({ name, description, phase }) => ({ name, description, phase }));
122
+ },
123
+ },
124
+
125
+ bigpowers_get_state: {
126
+ description: 'Get the current bigpowers project state (active flow, epic, story, step) from specs/state.yaml.',
127
+ inputSchema: { type: 'object', properties: {} },
128
+ handler() {
129
+ if (!fs.existsSync(STATE_YAML)) return { error: 'specs/state.yaml not found' };
130
+ return { content: fs.readFileSync(STATE_YAML, 'utf8') };
131
+ },
132
+ },
133
+
134
+ bigpowers_invoke_skill: {
135
+ description: 'Get the full instructions for a skill in context. Returns SKILL.md content suitable for agent invocation.',
136
+ inputSchema: {
137
+ type: 'object',
138
+ properties: {
139
+ name: { type: 'string', description: 'Skill name to invoke (kebab-case)' },
140
+ context: { type: 'string', description: 'Optional context or arguments to pass with the skill invocation' },
141
+ },
142
+ required: ['name'],
143
+ },
144
+ handler({ name, context }) {
145
+ const content = getSkillContent(name);
146
+ if (!content) return { error: `Skill "${name}" not found` };
147
+ const result = { name, instructions: content };
148
+ if (context) result.context = context;
149
+ return result;
150
+ },
151
+ },
152
+ };
153
+
154
+ // ─── MCP stdio transport ──────────────────────────────────────────────────────
155
+
156
+ let inputBuffer = Buffer.alloc(0);
157
+
158
+ process.stdin.on('data', chunk => {
159
+ inputBuffer = Buffer.concat([inputBuffer, chunk]);
160
+ processBuffer();
161
+ });
162
+
163
+ process.stdin.on('end', () => process.exit(0));
164
+
165
+ function processBuffer() {
166
+ while (true) {
167
+ const headerEnd = inputBuffer.indexOf('\r\n\r\n');
168
+ if (headerEnd === -1) break;
169
+
170
+ const header = inputBuffer.slice(0, headerEnd).toString();
171
+ const match = header.match(/Content-Length:\s*(\d+)/i);
172
+ if (!match) { inputBuffer = inputBuffer.slice(headerEnd + 4); continue; }
173
+
174
+ const contentLength = parseInt(match[1], 10);
175
+ const bodyStart = headerEnd + 4;
176
+ if (inputBuffer.length < bodyStart + contentLength) break;
177
+
178
+ const body = inputBuffer.slice(bodyStart, bodyStart + contentLength).toString();
179
+ inputBuffer = inputBuffer.slice(bodyStart + contentLength);
180
+
181
+ try { handleMessage(JSON.parse(body)); } catch (_) {}
182
+ }
183
+ }
184
+
185
+ function send(msg) {
186
+ const body = JSON.stringify(msg);
187
+ process.stdout.write(`Content-Length: ${Buffer.byteLength(body, 'utf8')}\r\n\r\n${body}`);
188
+ }
189
+
190
+ function handleInitialize(id) {
191
+ send({
192
+ jsonrpc: '2.0', id,
193
+ result: {
194
+ protocolVersion: '2024-11-05',
195
+ capabilities: { tools: {} },
196
+ serverInfo: { name: 'bigpowers', version: '1.0.0' },
197
+ },
198
+ });
199
+ }
200
+
201
+ function handleToolsList(id) {
202
+ send({
203
+ jsonrpc: '2.0', id,
204
+ result: {
205
+ tools: Object.entries(TOOLS).map(([name, tool]) => ({
206
+ name,
207
+ description: tool.description,
208
+ inputSchema: tool.inputSchema,
209
+ })),
210
+ },
211
+ });
212
+ }
213
+
214
+ function handleToolCall(id, params) {
215
+ const { name, arguments: args } = params;
216
+ const tool = TOOLS[name];
217
+ if (!tool) {
218
+ send({ jsonrpc: '2.0', id, error: { code: -32601, message: `Unknown tool: ${name}` } });
219
+ return;
220
+ }
221
+ try {
222
+ const result = tool.handler(args || {});
223
+ send({
224
+ jsonrpc: '2.0', id,
225
+ result: { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] },
226
+ });
227
+ } catch (err) {
228
+ send({ jsonrpc: '2.0', id, error: { code: -32603, message: err.message } });
229
+ }
230
+ }
231
+
232
+ function handleMessage(msg) {
233
+ const { id, method, params } = msg;
234
+ if (method === 'initialize') { handleInitialize(id); return; }
235
+ if (method === 'notifications/initialized') return;
236
+ if (method === 'tools/list') { handleToolsList(id); return; }
237
+ if (method === 'tools/call') { handleToolCall(id, params); return; }
238
+ if (id !== undefined) {
239
+ send({ jsonrpc: '2.0', id, error: { code: -32601, message: `Method not found: ${method}` } });
240
+ }
241
+ }
242
+
243
+ // Allow require() without starting the server (for testing)
244
+ if (require.main === module) {
245
+ process.stderr.write('bigpowers MCP server started (stdio)\n');
246
+ }
package/skills-lock.json CHANGED
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "build-epic": {
20
20
  "description": "Eight-step epic build cycle — reads state.yaml, execution-status.yaml, and one epic capsule; updates status via bp-yaml-set or direct edit. Resume mode runs one step per invocation. Use instead of ad-hoc execute-plan for release work.",
21
- "sha256": "3c1707cca32b24de",
21
+ "sha256": "b7049084cd180053",
22
22
  "path": "build-epic/SKILL.md"
23
23
  },
24
24
  "change-request": {
@@ -203,7 +203,7 @@
203
203
  },
204
204
  "release-branch": {
205
205
  "description": "Make the merge/PR/keep/discard decision for a feature branch, verify coverage gates, create the PR with gh, and clean up the worktree. Use when a feature is done and ready to ship, or when user says \"release\", \"merge\", or \"open a PR\".",
206
- "sha256": "140f4bec3690bd51",
206
+ "sha256": "5d1e07e58d1aff44",
207
207
  "path": "release-branch/SKILL.md"
208
208
  },
209
209
  "request-review": {
@@ -213,7 +213,7 @@
213
213
  },
214
214
  "research-first": {
215
215
  "description": "Look-before-build — search registries, repo, existing skills, and web for prior art before implementing. Appends Prior Art to the spec. Use after survey-context and before elaborate-spec, when adding dependencies, or when the task may already be solved.",
216
- "sha256": "2d11dadf63b9dbd3",
216
+ "sha256": "8c6928fce1c896b8",
217
217
  "path": "research-first/SKILL.md"
218
218
  },
219
219
  "reset-baseline": {