bigpowers 2.88.2 → 2.88.4
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/.gemini/extensions/bigpowers/gemini-extension.json +1 -1
- package/.mcp.json +2 -2
- package/.pi/package.json +1 -1
- package/CHANGELOG.md +14 -0
- package/CONTRIBUTORS.md +1 -1
- package/README.md +1 -1
- package/bigpowers-mcp/build/config.js +7 -1
- package/bigpowers-mcp/build/config.js.map +1 -1
- package/bigpowers-mcp/src/config.ts +9 -1
- package/extensions/omp-hooks.ts +3 -14
- package/package.json +8 -2
- package/scripts/lib/__pycache__/link_utils.cpython-312.pyc +0 -0
- package/scripts/lib/__pycache__/srp_engine_links.cpython-312.pyc +0 -0
- package/scripts/lib/golden-suite-gates.sh +1 -0
- package/scripts/mcp-smoke.ts +67 -0
- package/scripts/omp-smoke.ts +16 -12
- package/scripts/test-install-helpers.js +4 -0
- package/scripts/validate-mcp-package.sh +75 -0
- package/scripts/validate-omp-extension.sh +17 -5
package/.mcp.json
CHANGED
package/.pi/package.json
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [2.88.4](https://github.com/danielvm-git/bigpowers/compare/v2.88.3...v2.88.4) (2026-09-13)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **mcp:** start bigpowers-mcp from OMP plugin installs ([#123](https://github.com/danielvm-git/bigpowers/issues/123)) ([#125](https://github.com/danielvm-git/bigpowers/issues/125)) ([1194dc1](https://github.com/danielvm-git/bigpowers/commit/1194dc158ab191ec3be32b55b8b4400a7ddcf277))
|
|
7
|
+
|
|
8
|
+
## [2.88.3](https://github.com/danielvm-git/bigpowers/compare/v2.88.2...v2.88.3) (2026-09-13)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **pi:** prevent duplicate Bigpowers slash commands ([#121](https://github.com/danielvm-git/bigpowers/issues/121)) ([#124](https://github.com/danielvm-git/bigpowers/issues/124)) ([45870e2](https://github.com/danielvm-git/bigpowers/commit/45870e2e8e041ba3e21996fb98c96ec2a2484552))
|
|
14
|
+
|
|
1
15
|
## [2.88.2](https://github.com/danielvm-git/bigpowers/compare/v2.88.1...v2.88.2) (2026-09-06)
|
|
2
16
|
|
|
3
17
|
|
package/CONTRIBUTORS.md
CHANGED
|
@@ -36,7 +36,7 @@ Discovered via fork audit on 2026-09-01.
|
|
|
36
36
|
|
|
37
37
|
XcluEzy7 built a native [oh-my-pi](https://github.com/oh-my-pi) OMP plugin that:
|
|
38
38
|
|
|
39
|
-
- Discovers every skill in `skills/` at runtime
|
|
39
|
+
- Discovers every skill in `skills/` at runtime for dynamic tool invocation.
|
|
40
40
|
- Exposes a unified `bigpowers_skill` LLM tool with `list`/`get`/`run` operations.
|
|
41
41
|
- Ports bigpowers' git-safety pre-tool-use hook into OMP's `tool_call` event API,
|
|
42
42
|
blocking dangerous patterns and enforcing Conventional Commits.
|
package/README.md
CHANGED
|
@@ -391,7 +391,7 @@ bigpowers has been shaped by contributors who extended it in their own forks.
|
|
|
391
391
|
See [CONTRIBUTORS.md](CONTRIBUTORS.md) for the full list.
|
|
392
392
|
|
|
393
393
|
- **[Kevin Oberlies (favilo)](https://github.com/favilo/bigpowers)** — Jujutsu VCS support across lifecycle skills + `project-runtime.sh` configurable settings library.
|
|
394
|
-
- **[XcluEzy7](https://github.com/XcluEzy7/bigpowers)** — OMP plugin extension (`extensions/omp-hooks.ts`): native skill discovery,
|
|
394
|
+
- **[XcluEzy7](https://github.com/XcluEzy7/bigpowers)** — OMP plugin extension (`extensions/omp-hooks.ts`): native skill discovery, unified skill tooling, and git-safety hooks for the oh-my-pi runtime.
|
|
395
395
|
|
|
396
396
|
---
|
|
397
397
|
|
|
@@ -16,7 +16,13 @@ export function getRepoRoot() {
|
|
|
16
16
|
return cwd;
|
|
17
17
|
}
|
|
18
18
|
function isRepoRoot(dir) {
|
|
19
|
-
|
|
19
|
+
if (fs.existsSync(path.join(dir, "skills")) &&
|
|
20
|
+
fs.existsSync(path.join(dir, "specs"))) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
// Published npm package ships skills/ but excludes specs/ (.npmignore).
|
|
24
|
+
return (fs.existsSync(path.join(dir, "skills")) &&
|
|
25
|
+
fs.existsSync(path.join(dir, "bigpowers-mcp", "build", "index.js")));
|
|
20
26
|
}
|
|
21
27
|
export function getSkillsDir(repoRoot) {
|
|
22
28
|
return path.join(repoRoot, "skills");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAEhE,iFAAiF;AACjF,MAAM,UAAU,WAAW;IACzB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC3C,IAAI,OAAO;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAE1C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,IAAI,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IAEhC,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC1D,IAAI,UAAU,CAAC,eAAe,CAAC;QAAE,OAAO,eAAe,CAAC;IAExD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,CACL,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAEhE,iFAAiF;AACjF,MAAM,UAAU,WAAW;IACzB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC3C,IAAI,OAAO;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAE1C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,IAAI,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IAEhC,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC1D,IAAI,UAAU,CAAC,eAAe,CAAC;QAAE,OAAO,eAAe,CAAC;IAExD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,IACE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACvC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,EACtC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,wEAAwE;IACxE,OAAO,CACL,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACvC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CACpE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,eAAe,EAAE,aAAa,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,GAAG,IAAI,CAAC;AAE/C,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,QAAQ;IACR,SAAS;IACT,SAAS;IACT,cAAc;CACf,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC"}
|
|
@@ -19,8 +19,16 @@ export function getRepoRoot(): string {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
function isRepoRoot(dir: string): boolean {
|
|
22
|
+
if (
|
|
23
|
+
fs.existsSync(path.join(dir, "skills")) &&
|
|
24
|
+
fs.existsSync(path.join(dir, "specs"))
|
|
25
|
+
) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
// Published npm package ships skills/ but excludes specs/ (.npmignore).
|
|
22
29
|
return (
|
|
23
|
-
fs.existsSync(path.join(dir, "skills")) &&
|
|
30
|
+
fs.existsSync(path.join(dir, "skills")) &&
|
|
31
|
+
fs.existsSync(path.join(dir, "bigpowers-mcp", "build", "index.js"))
|
|
24
32
|
);
|
|
25
33
|
}
|
|
26
34
|
|
package/extensions/omp-hooks.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// story: e82s03
|
|
2
2
|
// extensions/omp-hooks.ts
|
|
3
|
-
// bigpowers — Single OMP extension entry exposing
|
|
4
|
-
//
|
|
3
|
+
// bigpowers — Single OMP extension entry exposing source skills through the
|
|
4
|
+
// bigpowers_skill LLM tool and enforcing safety policy guards. Pi prompt
|
|
5
|
+
// templates own slash-command registration so each workflow appears once.
|
|
5
6
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
6
7
|
import { Type } from "typebox";
|
|
7
8
|
import { execSync } from "node:child_process";
|
|
@@ -247,18 +248,6 @@ export default function bigpowers(pi: ExtensionAPI) {
|
|
|
247
248
|
// Discover skills from skills/ in the installed plugin package root.
|
|
248
249
|
const skills = discoverSkills(join(pluginRoot(), "skills"));
|
|
249
250
|
|
|
250
|
-
// ----- Slash commands --------------------------------------------------
|
|
251
|
-
|
|
252
|
-
for (const skill of skills) {
|
|
253
|
-
pi.registerCommand(skill.name, {
|
|
254
|
-
description: skill.description,
|
|
255
|
-
handler: async (args, _ctx) => {
|
|
256
|
-
const prompt = buildSkillPrompt(skill, args);
|
|
257
|
-
await injectSkillPrompt(pi, prompt);
|
|
258
|
-
},
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
|
|
262
251
|
// ----- bigpowers_skill tool --------------------------------------------
|
|
263
252
|
|
|
264
253
|
pi.registerTool({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bigpowers",
|
|
3
|
-
"version": "2.88.
|
|
3
|
+
"version": "2.88.4",
|
|
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": {
|
|
@@ -59,7 +59,13 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@clack/prompts": "^0.10.0",
|
|
62
|
-
"
|
|
62
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
63
|
+
"js-yaml": "^4.1.0",
|
|
64
|
+
"picocolors": "^1.1.1",
|
|
65
|
+
"remark-frontmatter": "^5.0.0",
|
|
66
|
+
"remark-parse": "^11.0.0",
|
|
67
|
+
"unified": "^11.0.5",
|
|
68
|
+
"zod": "^3.24.2"
|
|
63
69
|
},
|
|
64
70
|
"devDependencies": {
|
|
65
71
|
"@semantic-release/changelog": "^6.0.3",
|
|
Binary file
|
|
Binary file
|
|
@@ -66,6 +66,7 @@ GOLDEN_GATES=(
|
|
|
66
66
|
"install-helpers:bash scripts/test-install-helpers.sh:false"
|
|
67
67
|
"project-runtime:bash scripts/test-project-runtime.sh:false"
|
|
68
68
|
"omp-extension:bash scripts/validate-omp-extension.sh:false"
|
|
69
|
+
"mcp-package:bash scripts/validate-mcp-package.sh:false"
|
|
69
70
|
"import-boundaries:bash scripts/check-import-boundaries.sh:false"
|
|
70
71
|
"skill-catalog:bash scripts/validate-skill-catalog.sh:false"
|
|
71
72
|
"specs-parse:bash scripts/validate-specs-yaml.sh:false"
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// story: e32s06
|
|
2
|
+
// Simulates OMP spawning bigpowers-mcp from the installed plugin root (#123).
|
|
3
|
+
// Verifies Node resolves @modelcontextprotocol/sdk from the root package graph
|
|
4
|
+
// and the server reaches its startup log line without module-not-found.
|
|
5
|
+
|
|
6
|
+
import { readFileSync } from "node:fs";
|
|
7
|
+
import { spawn } from "node:child_process";
|
|
8
|
+
import { dirname, join } from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
|
|
11
|
+
const repoRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
12
|
+
const manifest = JSON.parse(readFileSync(join(repoRoot, ".mcp.json"), "utf8")) as {
|
|
13
|
+
mcpServers?: Record<string, { args?: string[]; cwd?: string }>;
|
|
14
|
+
};
|
|
15
|
+
const server = manifest.mcpServers?.["bigpowers-mcp"];
|
|
16
|
+
if (!server) throw new Error("bigpowers-mcp entry missing from .mcp.json");
|
|
17
|
+
|
|
18
|
+
const entry = join(repoRoot, "bigpowers-mcp/build/index.js");
|
|
19
|
+
const started = await new Promise<{ ok: boolean; detail: string }>((resolve) => {
|
|
20
|
+
const child = spawn("node", [entry], {
|
|
21
|
+
cwd: repoRoot,
|
|
22
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
23
|
+
env: { ...process.env, OMP_PLUGIN_ROOT: repoRoot },
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
let stderr = "";
|
|
27
|
+
const timer = setTimeout(() => {
|
|
28
|
+
child.kill("SIGTERM");
|
|
29
|
+
resolve({ ok: false, detail: `timeout waiting for startup (stderr: ${stderr.trim()})` });
|
|
30
|
+
}, 5000);
|
|
31
|
+
|
|
32
|
+
child.stderr.on("data", (chunk: Buffer) => {
|
|
33
|
+
stderr += chunk.toString();
|
|
34
|
+
if (stderr.includes("bigpowers-mcp started")) {
|
|
35
|
+
clearTimeout(timer);
|
|
36
|
+
child.kill("SIGTERM");
|
|
37
|
+
resolve({ ok: true, detail: "bigpowers-mcp started" });
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
child.on("exit", (code, signal) => {
|
|
42
|
+
if (stderr.includes("ERR_MODULE_NOT_FOUND")) {
|
|
43
|
+
clearTimeout(timer);
|
|
44
|
+
resolve({ ok: false, detail: stderr.trim() });
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (signal === "SIGTERM" && stderr.includes("bigpowers-mcp started")) return;
|
|
48
|
+
clearTimeout(timer);
|
|
49
|
+
resolve({
|
|
50
|
+
ok: false,
|
|
51
|
+
detail: `exit code=${code ?? "null"} signal=${signal ?? "null"} stderr=${stderr.trim()}`,
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
if (!started.ok) {
|
|
57
|
+
throw new Error(started.detail);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
console.log(
|
|
61
|
+
JSON.stringify({
|
|
62
|
+
pluginRoot: repoRoot,
|
|
63
|
+
entry,
|
|
64
|
+
ompPluginRootInManifest: server.cwd?.includes("OMP_PLUGIN_ROOT") ?? false,
|
|
65
|
+
startup: started.detail,
|
|
66
|
+
}),
|
|
67
|
+
);
|
package/scripts/omp-smoke.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// story: e82s03
|
|
2
2
|
// Runtime smoke for extensions/omp-hooks.ts.
|
|
3
|
-
// Imports the extension, registers a fake ExtensionAPI,
|
|
4
|
-
//
|
|
3
|
+
// Imports the extension, registers a fake ExtensionAPI, and verifies the
|
|
4
|
+
// extension leaves commands to prompt templates while skill-tool injection works.
|
|
5
5
|
//
|
|
6
6
|
// Load-phase contract (BUG-2026-09-05, #119): pi installs throwing stubs for
|
|
7
7
|
// ACTION methods during extension loading and only binds real implementations
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
// fails here exactly as it does in real pi, instead of silently passing.
|
|
11
11
|
// See pi 0.85.1 src/core/extensions/loader.ts (createExtensionRuntime).
|
|
12
12
|
|
|
13
|
+
import { readFileSync } from "node:fs";
|
|
13
14
|
import bigpowers from "../extensions/omp-hooks.ts";
|
|
14
15
|
|
|
15
16
|
type AnyObj = Record<string, unknown>;
|
|
@@ -82,23 +83,26 @@ await bigpowers(pi as unknown as never);
|
|
|
82
83
|
// are callable from here on (handlers, tool executions).
|
|
83
84
|
loading = false;
|
|
84
85
|
|
|
86
|
+
const packageManifest = JSON.parse(
|
|
87
|
+
readFileSync(new URL("../package.json", import.meta.url), "utf8"),
|
|
88
|
+
) as { pi?: { prompts?: string[] } };
|
|
89
|
+
const promptTemplates = packageManifest.pi?.prompts ?? [];
|
|
90
|
+
|
|
91
|
+
if (commands.size !== 0) {
|
|
92
|
+
throw new Error(`extension registered ${commands.size} duplicate workflow commands`);
|
|
93
|
+
}
|
|
94
|
+
if (!promptTemplates.includes("./.pi/prompts")) {
|
|
95
|
+
throw new Error("package does not declare the canonical Pi prompt templates");
|
|
96
|
+
}
|
|
97
|
+
|
|
85
98
|
console.log(JSON.stringify({
|
|
86
99
|
commands: commands.size,
|
|
100
|
+
promptTemplates,
|
|
87
101
|
tool: tools[0]?.name,
|
|
88
102
|
events: [...events.keys()],
|
|
89
|
-
firstCommand: [...commands.keys()].slice(0, 5),
|
|
90
103
|
sendUserMessageAwaitable: typeof pi.sendUserMessage === "function",
|
|
91
104
|
}));
|
|
92
105
|
|
|
93
|
-
// Exercise the /survey-context handler end-to-end.
|
|
94
|
-
const handler = commands.get("survey-context")?.handler;
|
|
95
|
-
if (!handler) throw new Error("survey-context command not registered");
|
|
96
|
-
await handler("", {});
|
|
97
|
-
|
|
98
|
-
// Verify a nonexistent command is not present.
|
|
99
|
-
const fallback = commands.get("nonexistent-skill-for-test")?.handler;
|
|
100
|
-
if (fallback) throw new Error("unexpected command registered");
|
|
101
|
-
|
|
102
106
|
// Test bigpowers_skill run path.
|
|
103
107
|
const skillTool = tools[0];
|
|
104
108
|
if (!skillTool?.execute) throw new Error("bigpowers_skill tool missing execute");
|
|
@@ -229,6 +229,8 @@ try {
|
|
|
229
229
|
'.gemini/extensions/bigpowers/hooks/before-tool-git-guard.sh',
|
|
230
230
|
'.cursor/rules',
|
|
231
231
|
'.pi/skills',
|
|
232
|
+
'.mcp.json',
|
|
233
|
+
'bigpowers-mcp/build/index.js',
|
|
232
234
|
'skills/audit-code/SKILL.md',
|
|
233
235
|
'docs/templates/ci/github/test-build-release-node.yml',
|
|
234
236
|
];
|
|
@@ -256,6 +258,8 @@ try {
|
|
|
256
258
|
maxBuffer: 16 * 1024 * 1024,
|
|
257
259
|
});
|
|
258
260
|
for (const tpl of [
|
|
261
|
+
'.mcp.json',
|
|
262
|
+
'bigpowers-mcp/build/index.js',
|
|
259
263
|
'docs/templates/ci/github/test-build-release-node.yml',
|
|
260
264
|
'docs/templates/ci/github/test-build-release-rust.yml',
|
|
261
265
|
'docs/templates/ci/github/test-build-release-python.yml',
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# story: e32s06
|
|
3
|
+
# MCP package integrity guard — shipped .mcp.json must start from OMP plugin installs
|
|
4
|
+
# and root package.json must declare bigpowers-mcp runtime dependencies.
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
8
|
+
cd "$REPO_ROOT"
|
|
9
|
+
|
|
10
|
+
ERRORS=0
|
|
11
|
+
|
|
12
|
+
fail() {
|
|
13
|
+
echo "FAIL: $*"
|
|
14
|
+
ERRORS=$((ERRORS + 1))
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
pass() {
|
|
18
|
+
echo "ok : $*"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
MCP_JSON="$REPO_ROOT/.mcp.json"
|
|
22
|
+
echo "--- [MCP] shipped .mcp.json OMP compatibility ---"
|
|
23
|
+
if [[ ! -f "$MCP_JSON" ]]; then
|
|
24
|
+
fail ".mcp.json missing at repo root"
|
|
25
|
+
else
|
|
26
|
+
if grep -q 'workspaceFolder' "$MCP_JSON" 2>/dev/null; then
|
|
27
|
+
fail ".mcp.json uses workspaceFolder — not valid in OMP env expansion (#123)"
|
|
28
|
+
else
|
|
29
|
+
pass ".mcp.json does not reference workspaceFolder"
|
|
30
|
+
fi
|
|
31
|
+
if grep -q 'OMP_PLUGIN_ROOT' "$MCP_JSON" 2>/dev/null; then
|
|
32
|
+
pass ".mcp.json references OMP_PLUGIN_ROOT for plugin installs"
|
|
33
|
+
else
|
|
34
|
+
fail ".mcp.json must reference OMP_PLUGIN_ROOT for OMP plugin cwd/args"
|
|
35
|
+
fi
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
echo "--- [MCP] root runtime dependencies ---"
|
|
39
|
+
for dep in "@modelcontextprotocol/sdk" "unified" "remark-parse" "zod"; do
|
|
40
|
+
if node -e "const p=require('./package.json'); process.exit(p.dependencies?.['$dep'] ? 0 : 1)"; then
|
|
41
|
+
pass "root dependencies include $dep"
|
|
42
|
+
else
|
|
43
|
+
fail "root dependencies missing $dep (bigpowers-mcp runtime)"
|
|
44
|
+
fi
|
|
45
|
+
done
|
|
46
|
+
|
|
47
|
+
echo "--- [MCP] built server entry ---"
|
|
48
|
+
if [[ -f "$REPO_ROOT/bigpowers-mcp/build/index.js" ]]; then
|
|
49
|
+
pass "bigpowers-mcp/build/index.js exists"
|
|
50
|
+
else
|
|
51
|
+
fail "bigpowers-mcp/build/index.js missing — run cd bigpowers-mcp && npm run build"
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
echo "--- [MCP] runtime load smoke (scripts/mcp-smoke.ts) ---"
|
|
55
|
+
if ! command -v node >/dev/null 2>&1; then
|
|
56
|
+
echo "warn: node unavailable — skipping runtime load smoke"
|
|
57
|
+
elif [[ ! -f "$REPO_ROOT/scripts/mcp-smoke.ts" ]]; then
|
|
58
|
+
fail "scripts/mcp-smoke.ts not found"
|
|
59
|
+
else
|
|
60
|
+
SMOKE_ERR=$(mktemp)
|
|
61
|
+
if node "$REPO_ROOT/scripts/mcp-smoke.ts" >/dev/null 2>"$SMOKE_ERR"; then
|
|
62
|
+
pass "MCP server loads from simulated OMP plugin root"
|
|
63
|
+
else
|
|
64
|
+
fail "MCP smoke failed — $(head -3 "$SMOKE_ERR" 2>/dev/null | tr '\n' ' ')"
|
|
65
|
+
fi
|
|
66
|
+
rm -f "$SMOKE_ERR"
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
echo "---"
|
|
70
|
+
if [[ "$ERRORS" -eq 0 ]]; then
|
|
71
|
+
echo "MCP package validation passed"
|
|
72
|
+
else
|
|
73
|
+
echo "MCP package validation FAILED ($ERRORS error(s))"
|
|
74
|
+
exit 1
|
|
75
|
+
fi
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# story: e82s03
|
|
3
|
-
# OMP extension integrity guard — validates the extension entry is wired
|
|
4
|
-
#
|
|
3
|
+
# OMP extension integrity guard — validates the extension entry is wired,
|
|
4
|
+
# leaves slash commands to Pi prompt templates, and discovers all source skills.
|
|
5
5
|
# Run before merging any branch that touches extensions/.
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
|
|
@@ -43,20 +43,32 @@ else
|
|
|
43
43
|
fi
|
|
44
44
|
fi
|
|
45
45
|
|
|
46
|
-
# ── 3. Extension
|
|
47
|
-
echo "--- [OMP]
|
|
46
|
+
# ── 3. Extension owns tools/hooks; prompt templates own slash commands ─────
|
|
47
|
+
echo "--- [OMP] separated runtime responsibilities ---"
|
|
48
48
|
if [[ -n "$EXT_PATH" && -f "$EXT_PATH" ]]; then
|
|
49
|
-
for sym in "
|
|
49
|
+
for sym in "registerTool" "tool_call"; do
|
|
50
50
|
if grep -q "$sym" "$EXT_PATH" 2>/dev/null; then
|
|
51
51
|
pass "symbol '$sym' found in extension source"
|
|
52
52
|
else
|
|
53
53
|
fail "symbol '$sym' NOT found in extension source"
|
|
54
54
|
fi
|
|
55
55
|
done
|
|
56
|
+
if grep -q 'pi\.registerCommand' "$EXT_PATH" 2>/dev/null; then
|
|
57
|
+
fail "extension registers commands already supplied by Pi prompt templates"
|
|
58
|
+
else
|
|
59
|
+
pass "extension leaves slash-command registration to Pi prompt templates"
|
|
60
|
+
fi
|
|
56
61
|
else
|
|
57
62
|
fail "Cannot scan extension symbols — file not resolved"
|
|
58
63
|
fi
|
|
59
64
|
|
|
65
|
+
PROMPT_COUNT=$(node -e "const p = require('./package.json'); console.log(p.pi?.prompts?.length || 0)")
|
|
66
|
+
if [[ "$PROMPT_COUNT" -eq 1 ]]; then
|
|
67
|
+
pass "pi.prompts has exactly 1 canonical prompt-template entry"
|
|
68
|
+
else
|
|
69
|
+
fail "pi.prompts has $PROMPT_COUNT entries (expected 1)"
|
|
70
|
+
fi
|
|
71
|
+
|
|
60
72
|
# ── 4. Skill discovery root is skills/ ────────────────────────────────────
|
|
61
73
|
echo "--- [OMP] source skill discoverability (skills/<name>/SKILL.md) ---"
|
|
62
74
|
SKILLS_ROOT="$REPO_ROOT/skills"
|