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 +1 -1
- package/.pi/prompts/build-epic.md +1 -1
- package/.pi/prompts/release-branch.md +1 -0
- package/.pi/prompts/research-first.md +23 -2
- package/.pi/skills/build-epic/SKILL.md +1 -1
- package/.pi/skills/release-branch/SKILL.md +1 -0
- package/.pi/skills/research-first/SKILL.md +23 -2
- package/CHANGELOG.md +14 -0
- package/CONVENTIONS.md +1 -0
- package/README.md +41 -0
- package/SKILL-INDEX.md +1 -1
- package/build-epic/SKILL.md +1 -1
- package/package.json +1 -1
- package/release-branch/SKILL.md +1 -0
- package/research-first/SKILL.md +23 -2
- package/scripts/bp-opensrc-check.sh +64 -0
- package/scripts/mcp-server.js +246 -0
- package/skills-lock.json +3 -3
package/.pi/package.json
CHANGED
|
@@ -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.
|
|
15
|
-
4.
|
|
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.
|
|
17
|
-
4.
|
|
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-
|
|
6
|
+
**Generated:** 2026-06-22T02:23:04Z
|
|
7
7
|
**Skills:** 68
|
|
8
8
|
|
|
9
9
|
---
|
package/build-epic/SKILL.md
CHANGED
|
@@ -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
package/release-branch/SKILL.md
CHANGED
|
@@ -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
|
|
package/research-first/SKILL.md
CHANGED
|
@@ -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.
|
|
16
|
-
4.
|
|
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": "
|
|
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": "
|
|
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": "
|
|
216
|
+
"sha256": "8c6928fce1c896b8",
|
|
217
217
|
"path": "research-first/SKILL.md"
|
|
218
218
|
},
|
|
219
219
|
"reset-baseline": {
|