bigpowers 2.60.0 → 2.61.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/.mcp.json +9 -0
  2. package/.pi/package.json +1 -1
  3. package/CHANGELOG.md +14 -0
  4. package/bigpowers-mcp/build/config.d.ts +7 -0
  5. package/bigpowers-mcp/build/config.js +35 -0
  6. package/bigpowers-mcp/build/config.js.map +1 -0
  7. package/bigpowers-mcp/build/index.d.ts +2 -0
  8. package/bigpowers-mcp/build/index.js +20 -0
  9. package/bigpowers-mcp/build/index.js.map +1 -0
  10. package/bigpowers-mcp/build/lib/git-context.d.ts +12 -0
  11. package/bigpowers-mcp/build/lib/git-context.js +92 -0
  12. package/bigpowers-mcp/build/lib/git-context.js.map +1 -0
  13. package/bigpowers-mcp/build/lib/graph/builder.d.ts +4 -0
  14. package/bigpowers-mcp/build/lib/graph/builder.js +85 -0
  15. package/bigpowers-mcp/build/lib/graph/builder.js.map +1 -0
  16. package/bigpowers-mcp/build/lib/graph/store.d.ts +11 -0
  17. package/bigpowers-mcp/build/lib/graph/store.js +77 -0
  18. package/bigpowers-mcp/build/lib/graph/store.js.map +1 -0
  19. package/bigpowers-mcp/build/lib/graph/types.d.ts +24 -0
  20. package/bigpowers-mcp/build/lib/graph/types.js +2 -0
  21. package/bigpowers-mcp/build/lib/graph/types.js.map +1 -0
  22. package/bigpowers-mcp/build/lib/paths.d.ts +8 -0
  23. package/bigpowers-mcp/build/lib/paths.js +40 -0
  24. package/bigpowers-mcp/build/lib/paths.js.map +1 -0
  25. package/bigpowers-mcp/build/lib/phase-map.d.ts +3 -0
  26. package/bigpowers-mcp/build/lib/phase-map.js +77 -0
  27. package/bigpowers-mcp/build/lib/phase-map.js.map +1 -0
  28. package/bigpowers-mcp/build/lib/skill-parser.d.ts +31 -0
  29. package/bigpowers-mcp/build/lib/skill-parser.js +159 -0
  30. package/bigpowers-mcp/build/lib/skill-parser.js.map +1 -0
  31. package/bigpowers-mcp/build/lib/validate-skill.d.ts +13 -0
  32. package/bigpowers-mcp/build/lib/validate-skill.js +63 -0
  33. package/bigpowers-mcp/build/lib/validate-skill.js.map +1 -0
  34. package/bigpowers-mcp/build/tools/index.d.ts +9 -0
  35. package/bigpowers-mcp/build/tools/index.js +172 -0
  36. package/bigpowers-mcp/build/tools/index.js.map +1 -0
  37. package/bigpowers-mcp/package-lock.json +3685 -0
  38. package/bigpowers-mcp/package.json +30 -0
  39. package/bigpowers-mcp/src/config.ts +44 -0
  40. package/bigpowers-mcp/src/index.ts +23 -0
  41. package/bigpowers-mcp/src/lib/git-context.ts +99 -0
  42. package/bigpowers-mcp/src/lib/graph/builder.ts +95 -0
  43. package/bigpowers-mcp/src/lib/graph/store.ts +87 -0
  44. package/bigpowers-mcp/src/lib/graph/types.ts +28 -0
  45. package/bigpowers-mcp/src/lib/paths.ts +47 -0
  46. package/bigpowers-mcp/src/lib/phase-map.ts +77 -0
  47. package/bigpowers-mcp/src/lib/skill-parser.ts +191 -0
  48. package/bigpowers-mcp/src/lib/validate-skill.ts +91 -0
  49. package/bigpowers-mcp/src/tools/index.ts +227 -0
  50. package/bigpowers-mcp/test/catalog.test.ts +148 -0
  51. package/bigpowers-mcp/test/fixtures/graph/test-graph.jsonl +5 -0
  52. package/bigpowers-mcp/test/fixtures/skills/broken-link/SKILL.md +11 -0
  53. package/bigpowers-mcp/test/fixtures/skills/missing-verify/SKILL.md +9 -0
  54. package/bigpowers-mcp/test/fixtures/skills/valid-skill/SKILL.md +14 -0
  55. package/bigpowers-mcp/tsconfig.json +16 -0
  56. package/bigpowers-mcp/vitest.config.ts +8 -0
  57. package/package.json +1 -1
package/.mcp.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "mcpServers": {
3
+ "bigpowers-mcp": {
4
+ "command": "node",
5
+ "args": ["bigpowers-mcp/build/index.js"],
6
+ "cwd": "${workspaceFolder}"
7
+ }
8
+ }
9
+ }
package/.pi/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bigpowers",
3
- "version": "2.60.0",
3
+ "version": "2.61.1",
4
4
  "description": "74 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.61.1](https://github.com/danielvm-git/bigpowers/compare/v2.61.0...v2.61.1) (2026-07-04)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **e32:** add traceability tags for strict CI gate ([aca9a26](https://github.com/danielvm-git/bigpowers/commit/aca9a263dd1d2167e32c339c14d29a422a989177))
7
+
8
+ # [2.61.0](https://github.com/danielvm-git/bigpowers/compare/v2.60.0...v2.61.0) (2026-07-04)
9
+
10
+
11
+ ### Features
12
+
13
+ * **e32:** add bigpowers-mcp semantic context server ([f0f95b7](https://github.com/danielvm-git/bigpowers/commit/f0f95b7a790d7b4a5e056fb88fa6a771717ce29f))
14
+
1
15
  # [2.60.0](https://github.com/danielvm-git/bigpowers/compare/v2.59.9...v2.60.0) (2026-07-04)
2
16
 
3
17
 
@@ -0,0 +1,7 @@
1
+ /** Repo root: cwd when launched from workspace, else parent of bigpowers-mcp. */
2
+ export declare function getRepoRoot(): string;
3
+ export declare function getSkillsDir(repoRoot: string): string;
4
+ export declare function getGraphPath(repoRoot: string): string;
5
+ export declare const MAX_READ_SKILL_BYTES: number;
6
+ export declare const SECRET_DENYLIST: RegExp[];
7
+ export declare const GIT_SCOPE_DIRS: string[];
@@ -0,0 +1,35 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ const packageDir = path.dirname(fileURLToPath(import.meta.url));
5
+ /** Repo root: cwd when launched from workspace, else parent of bigpowers-mcp. */
6
+ export function getRepoRoot() {
7
+ const fromEnv = process.env.BIGPOWERS_ROOT;
8
+ if (fromEnv)
9
+ return path.resolve(fromEnv);
10
+ const cwd = process.cwd();
11
+ if (isRepoRoot(cwd))
12
+ return cwd;
13
+ const parentOfPackage = path.resolve(packageDir, "../..");
14
+ if (isRepoRoot(parentOfPackage))
15
+ return parentOfPackage;
16
+ return cwd;
17
+ }
18
+ function isRepoRoot(dir) {
19
+ return (fs.existsSync(path.join(dir, "skills")) && fs.existsSync(path.join(dir, "specs")));
20
+ }
21
+ export function getSkillsDir(repoRoot) {
22
+ return path.join(repoRoot, "skills");
23
+ }
24
+ export function getGraphPath(repoRoot) {
25
+ return path.join(repoRoot, "bigpowers-mcp", "graph.jsonl");
26
+ }
27
+ export const MAX_READ_SKILL_BYTES = 512 * 1024;
28
+ export const SECRET_DENYLIST = [
29
+ /\.env/i,
30
+ /\.pem$/i,
31
+ /secret/i,
32
+ /credentials/i,
33
+ ];
34
+ export const GIT_SCOPE_DIRS = ["skills", "specs"];
35
+ //# sourceMappingURL=config.js.map
@@ -0,0 +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,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAClF,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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { createContext, registerTools } from "./tools/index.js";
5
+ async function main() {
6
+ const ctx = createContext();
7
+ const server = new McpServer({
8
+ name: "bigpowers-mcp",
9
+ version: "0.1.0",
10
+ });
11
+ registerTools(server, ctx);
12
+ const transport = new StdioServerTransport();
13
+ await server.connect(transport);
14
+ console.error("bigpowers-mcp started");
15
+ }
16
+ main().catch((err) => {
17
+ console.error("Fatal error:", err);
18
+ process.exit(1);
19
+ });
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEhE,KAAK,UAAU,IAAI;IACjB,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE3B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;AACzC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ export interface GitContextResult {
2
+ action: string;
3
+ changed_files: Record<string, string[]>;
4
+ commits?: Array<{
5
+ hash: string;
6
+ subject: string;
7
+ files: string[];
8
+ }>;
9
+ diffs?: Record<string, string>;
10
+ }
11
+ export declare function getGitContext(repoRoot: string, action: "status" | "log" | "diff"): GitContextResult;
12
+ export declare function isGitRepo(repoRoot: string): boolean;
@@ -0,0 +1,92 @@
1
+ // story: e32s04
2
+ import { execFileSync } from "node:child_process";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import { GIT_SCOPE_DIRS } from "../config.js";
6
+ import { isSecretPath } from "./paths.js";
7
+ function inScope(filePath) {
8
+ const norm = filePath.replace(/\\/g, "/");
9
+ if (isSecretPath(norm))
10
+ return false;
11
+ return GIT_SCOPE_DIRS.some((d) => norm === d || norm.startsWith(`${d}/`));
12
+ }
13
+ function groupByDir(files) {
14
+ const grouped = {};
15
+ for (const f of files) {
16
+ const parts = f.split("/");
17
+ const dir = parts.length > 1 ? parts[0] : ".";
18
+ if (!grouped[dir])
19
+ grouped[dir] = [];
20
+ grouped[dir].push(f);
21
+ }
22
+ return grouped;
23
+ }
24
+ function git(repoRoot, args) {
25
+ return execFileSync("git", args, {
26
+ cwd: repoRoot,
27
+ encoding: "utf8",
28
+ maxBuffer: 10 * 1024 * 1024,
29
+ }).trim();
30
+ }
31
+ export function getGitContext(repoRoot, action) {
32
+ if (action === "status") {
33
+ const out = git(repoRoot, ["status", "--porcelain"]);
34
+ const files = out
35
+ .split("\n")
36
+ .filter(Boolean)
37
+ .map((line) => line.slice(3).trim())
38
+ .filter(inScope);
39
+ return { action, changed_files: groupByDir(files) };
40
+ }
41
+ if (action === "log") {
42
+ const out = git(repoRoot, [
43
+ "log",
44
+ "-10",
45
+ "--pretty=format:%H|%s",
46
+ "--name-only",
47
+ "--",
48
+ ...GIT_SCOPE_DIRS,
49
+ ]);
50
+ const commits = [];
51
+ let current = null;
52
+ for (const line of out.split("\n")) {
53
+ if (line.includes("|")) {
54
+ if (current)
55
+ commits.push(current);
56
+ const [hash, subject] = line.split("|");
57
+ current = { hash, subject, files: [] };
58
+ }
59
+ else if (line.trim() && current && inScope(line.trim())) {
60
+ current.files.push(line.trim());
61
+ }
62
+ }
63
+ if (current)
64
+ commits.push(current);
65
+ return { action, changed_files: {}, commits };
66
+ }
67
+ const diffOut = git(repoRoot, ["diff", "--", ...GIT_SCOPE_DIRS]);
68
+ const diffs = {};
69
+ let currentFile = "";
70
+ let buf = [];
71
+ for (const line of diffOut.split("\n")) {
72
+ if (line.startsWith("diff --git")) {
73
+ if (currentFile && buf.length)
74
+ diffs[currentFile] = buf.join("\n");
75
+ const match = / b\/(.+)$/.exec(line);
76
+ currentFile = match?.[1] ?? "";
77
+ buf = [line];
78
+ }
79
+ else {
80
+ buf.push(line);
81
+ }
82
+ }
83
+ if (currentFile && buf.length && inScope(currentFile) && !isSecretPath(currentFile)) {
84
+ diffs[currentFile] = buf.join("\n");
85
+ }
86
+ const changed = Object.keys(diffs);
87
+ return { action, changed_files: groupByDir(changed), diffs };
88
+ }
89
+ export function isGitRepo(repoRoot) {
90
+ return fs.existsSync(path.join(repoRoot, ".git"));
91
+ }
92
+ //# sourceMappingURL=git-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-context.js","sourceRoot":"","sources":["../../src/lib/git-context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ParsedSkill } from "../skill-parser.js";
2
+ import type { SkillGraph } from "./types.js";
3
+ export declare function buildGraphFromSkills(parsedSkills: ParsedSkill[]): SkillGraph;
4
+ export declare function mergeGraphs(base: SkillGraph, incoming: SkillGraph): SkillGraph;
@@ -0,0 +1,85 @@
1
+ const HANDOFF_AFTER = /run\s+(\S+)\s+after\s+(\S+)/gi;
2
+ const HARD_GATE = /HARD GATE:\s*(.+)/i;
3
+ const SKILL_REF = /see\s+skills\/(\S+)\/SKILL\.md/gi;
4
+ const CONVENTIONS_REF = /CONVENTIONS\.md(?:\s*[§#]\s*(\S+))?/gi;
5
+ export function buildGraphFromSkills(parsedSkills) {
6
+ const graph = { entities: new Map(), relations: [] };
7
+ for (const skill of parsedSkills) {
8
+ const fm = skill.frontmatter;
9
+ const observations = [];
10
+ if (fm.model)
11
+ observations.push(`model: ${String(fm.model)}`);
12
+ if (fm.effort)
13
+ observations.push(`effort: ${String(fm.effort)}`);
14
+ if (fm.description)
15
+ observations.push(`description: ${String(fm.description)}`);
16
+ const entity = {
17
+ type: "entity",
18
+ name: skill.name,
19
+ entityType: "Skill",
20
+ observations,
21
+ };
22
+ graph.entities.set(skill.name, entity);
23
+ const prose = skill.rawProse + "\n" + skill.sections.map((s) => s.prose).join("\n");
24
+ let m;
25
+ HANDOFF_AFTER.lastIndex = 0;
26
+ while ((m = HANDOFF_AFTER.exec(prose)) !== null) {
27
+ graph.relations.push({
28
+ type: "relation",
29
+ from: m[1],
30
+ to: m[2],
31
+ relationType: "depends_on",
32
+ });
33
+ }
34
+ const gateMatch = HARD_GATE.exec(prose);
35
+ if (gateMatch) {
36
+ const gateText = gateMatch[1].trim();
37
+ const targetMatch = /(\S+-?\S+)/.exec(gateText);
38
+ if (targetMatch) {
39
+ graph.relations.push({
40
+ type: "relation",
41
+ from: skill.name,
42
+ to: targetMatch[1].replace(/[`'"]/g, ""),
43
+ relationType: "gates",
44
+ });
45
+ }
46
+ }
47
+ SKILL_REF.lastIndex = 0;
48
+ while ((m = SKILL_REF.exec(prose)) !== null) {
49
+ graph.relations.push({
50
+ type: "relation",
51
+ from: skill.name,
52
+ to: m[1],
53
+ relationType: "references",
54
+ });
55
+ }
56
+ CONVENTIONS_REF.lastIndex = 0;
57
+ while ((m = CONVENTIONS_REF.exec(prose)) !== null) {
58
+ graph.relations.push({
59
+ type: "relation",
60
+ from: skill.name,
61
+ to: m[1] ? `CONVENTIONS.md §${m[1]}` : "CONVENTIONS.md",
62
+ relationType: "enforces",
63
+ });
64
+ }
65
+ const desc = String(fm.description ?? "");
66
+ const handoffMatch = /handoff.*?(\S+-?\S+)/i.exec(desc);
67
+ if (handoffMatch) {
68
+ graph.relations.push({
69
+ type: "relation",
70
+ from: skill.name,
71
+ to: handoffMatch[1],
72
+ relationType: "handoff_to",
73
+ });
74
+ }
75
+ }
76
+ return graph;
77
+ }
78
+ export function mergeGraphs(base, incoming) {
79
+ for (const [name, entity] of incoming.entities) {
80
+ base.entities.set(name, entity);
81
+ }
82
+ base.relations.push(...incoming.relations);
83
+ return base;
84
+ }
85
+ //# sourceMappingURL=builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builder.js","sourceRoot":"","sources":["../../../src/lib/graph/builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { GraphEntity, GraphRelation, SkillGraph } from "./types.js";
2
+ export declare function emptyGraph(): SkillGraph;
3
+ export declare function loadGraph(graphPath: string): SkillGraph;
4
+ export declare function saveGraph(graphPath: string, graph: SkillGraph): void;
5
+ export declare function searchNodes(graph: SkillGraph, query: string): GraphEntity[];
6
+ export declare function openNodes(graph: SkillGraph, names: string[]): GraphEntity[];
7
+ export declare function getRelationsFor(graph: SkillGraph, skillName: string): GraphRelation[];
8
+ export declare function getForwardDeps(graph: SkillGraph, skillName: string): string[];
9
+ export declare function getReverseDeps(graph: SkillGraph, skillName: string): string[];
10
+ export declare function getHandoffChain(graph: SkillGraph, skillName: string): string[];
11
+ export declare function getConventions(graph: SkillGraph, skillName: string): string[];
@@ -0,0 +1,77 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ export function emptyGraph() {
4
+ return { entities: new Map(), relations: [] };
5
+ }
6
+ export function loadGraph(graphPath) {
7
+ const graph = emptyGraph();
8
+ if (!fs.existsSync(graphPath))
9
+ return graph;
10
+ const lines = fs.readFileSync(graphPath, "utf8").split("\n").filter(Boolean);
11
+ for (const line of lines) {
12
+ const parsed = JSON.parse(line);
13
+ if (parsed.type === "entity") {
14
+ graph.entities.set(parsed.name, parsed);
15
+ }
16
+ else if (parsed.type === "relation") {
17
+ graph.relations.push(parsed);
18
+ }
19
+ }
20
+ return graph;
21
+ }
22
+ export function saveGraph(graphPath, graph) {
23
+ fs.mkdirSync(path.dirname(graphPath), { recursive: true });
24
+ const lines = [];
25
+ for (const entity of graph.entities.values()) {
26
+ lines.push(JSON.stringify(entity));
27
+ }
28
+ for (const rel of graph.relations) {
29
+ lines.push(JSON.stringify(rel));
30
+ }
31
+ fs.writeFileSync(graphPath, lines.join("\n") + (lines.length ? "\n" : ""));
32
+ }
33
+ export function searchNodes(graph, query) {
34
+ const q = query.toLowerCase();
35
+ return [...graph.entities.values()].filter((e) => {
36
+ const hay = [e.name, e.entityType, ...e.observations].join(" ").toLowerCase();
37
+ return hay.includes(q);
38
+ });
39
+ }
40
+ export function openNodes(graph, names) {
41
+ return names
42
+ .map((n) => graph.entities.get(n))
43
+ .filter((e) => e !== undefined);
44
+ }
45
+ export function getRelationsFor(graph, skillName) {
46
+ return graph.relations.filter((r) => r.from === skillName || r.to === skillName);
47
+ }
48
+ export function getForwardDeps(graph, skillName) {
49
+ return graph.relations
50
+ .filter((r) => r.from === skillName && r.relationType === "depends_on")
51
+ .map((r) => r.to);
52
+ }
53
+ export function getReverseDeps(graph, skillName) {
54
+ return graph.relations
55
+ .filter((r) => r.to === skillName && r.relationType === "depends_on")
56
+ .map((r) => r.from);
57
+ }
58
+ export function getHandoffChain(graph, skillName) {
59
+ const chain = [skillName];
60
+ let current = skillName;
61
+ const seen = new Set([skillName]);
62
+ for (let i = 0; i < 20; i++) {
63
+ const next = graph.relations.find((r) => r.from === current && r.relationType === "handoff_to");
64
+ if (!next || seen.has(next.to))
65
+ break;
66
+ chain.push(next.to);
67
+ seen.add(next.to);
68
+ current = next.to;
69
+ }
70
+ return chain;
71
+ }
72
+ export function getConventions(graph, skillName) {
73
+ return graph.relations
74
+ .filter((r) => r.from === skillName && r.relationType === "enforces")
75
+ .map((r) => r.to);
76
+ }
77
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/lib/graph/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export interface GraphEntity {
2
+ type: "entity";
3
+ name: string;
4
+ entityType: string;
5
+ observations: string[];
6
+ }
7
+ export interface GraphRelation {
8
+ type: "relation";
9
+ from: string;
10
+ to: string;
11
+ relationType: string;
12
+ }
13
+ export type GraphLine = GraphEntity | GraphRelation;
14
+ export interface SkillGraph {
15
+ entities: Map<string, GraphEntity>;
16
+ relations: GraphRelation[];
17
+ }
18
+ export interface DependencyReport {
19
+ skill: string;
20
+ depends_on: string[];
21
+ depended_by: string[];
22
+ handoff_chain: string[];
23
+ conventions: string[];
24
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/graph/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ export declare class PathGuardError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ /** Resolve userPath strictly within allowedRoot; reject traversal. */
5
+ export declare function resolveWithin(allowedRoot: string, userPath: string): string;
6
+ /** Resolve a skill name to skills/<name>/SKILL.md under repo root. */
7
+ export declare function resolveSkillPath(repoRoot: string, skillName: string): string;
8
+ export declare function isSecretPath(filePath: string): boolean;
@@ -0,0 +1,40 @@
1
+ import path from "node:path";
2
+ export class PathGuardError extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = "PathGuardError";
6
+ }
7
+ }
8
+ /** Resolve userPath strictly within allowedRoot; reject traversal. */
9
+ export function resolveWithin(allowedRoot, userPath) {
10
+ const normalized = userPath.replace(/\\/g, "/").trim();
11
+ if (!normalized || normalized.startsWith("/") || normalized.includes("..")) {
12
+ throw new PathGuardError(`Invalid path: ${userPath}`);
13
+ }
14
+ const resolved = path.resolve(allowedRoot, normalized);
15
+ const rootWithSep = allowedRoot.endsWith(path.sep)
16
+ ? allowedRoot
17
+ : allowedRoot + path.sep;
18
+ if (!resolved.startsWith(rootWithSep) && resolved !== allowedRoot) {
19
+ throw new PathGuardError(`Path escapes allowed root: ${userPath}`);
20
+ }
21
+ return resolved;
22
+ }
23
+ /** Resolve a skill name to skills/<name>/SKILL.md under repo root. */
24
+ export function resolveSkillPath(repoRoot, skillName) {
25
+ const name = skillName.trim();
26
+ if (!name || name.includes("/") || name.includes("\\") || name.includes("..")) {
27
+ throw new PathGuardError(`Invalid skill name: ${skillName}`);
28
+ }
29
+ const skillsDir = path.join(repoRoot, "skills");
30
+ const skillDir = resolveWithin(skillsDir, name);
31
+ return path.join(skillDir, "SKILL.md");
32
+ }
33
+ export function isSecretPath(filePath) {
34
+ const base = path.basename(filePath);
35
+ return (base.startsWith(".env") ||
36
+ /\.pem$/i.test(base) ||
37
+ /secret/i.test(base) ||
38
+ /credentials/i.test(base));
39
+ }
40
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED,sEAAsE;AACtE,MAAM,UAAU,aAAa,CAAC,WAAmB,EAAE,QAAgB;IACjE,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACvD,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,cAAc,CAAC,iBAAiB,QAAQ,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACvD,MAAM,WAAW,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;QAChD,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC;IAE3B,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;QAClE,MAAM,IAAI,cAAc,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,SAAiB;IAClE,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9E,MAAM,IAAI,cAAc,CAAC,uBAAuB,SAAS,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAChD,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,OAAO,CACL,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QACvB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;QACpB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;QACpB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAC1B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Lifecycle phase map — mirrors scripts/mcp-server.js PHASE_MAP. */
2
+ export declare const PHASE_MAP: Record<string, string>;
3
+ export declare function phaseForSkill(name: string): string;
@@ -0,0 +1,77 @@
1
+ /** Lifecycle phase map — mirrors scripts/mcp-server.js PHASE_MAP. */
2
+ export const PHASE_MAP = {
3
+ "survey-context": "Discover",
4
+ "research-first": "Discover",
5
+ "search-skills": "Discover",
6
+ "using-bigpowers": "Discover",
7
+ "map-codebase": "Discover",
8
+ "elaborate-spec": "Discover",
9
+ "model-domain": "Design",
10
+ "define-language": "Design",
11
+ "grill-me": "Design",
12
+ "grill-with-docs": "Design",
13
+ "deepen-architecture": "Design",
14
+ "design-interface": "Design",
15
+ "define-success": "Design",
16
+ "scope-work": "Plan",
17
+ "slice-tasks": "Plan",
18
+ "plan-work": "Plan",
19
+ "plan-release": "Plan",
20
+ "plan-refactor": "Plan",
21
+ "assess-impact": "Plan",
22
+ "change-request": "Plan",
23
+ "run-planning": "Plan",
24
+ "seed-conventions": "Plan",
25
+ "develop-tdd": "Build",
26
+ "kickoff-branch": "Build",
27
+ "execute-plan": "Build",
28
+ "build-epic": "Build",
29
+ "spike-prototype": "Build",
30
+ "craft-skill": "Build",
31
+ "quick-fix": "Build",
32
+ "setup-environment": "Build",
33
+ "wire-observability": "Build",
34
+ "wire-ci": "Build",
35
+ "publish-package": "Build",
36
+ "align-grid": "Build",
37
+ "orchestrate-project": "Build",
38
+ "guard-git": "Build",
39
+ "hook-commits": "Build",
40
+ "deploy": "Build",
41
+ "smoke-test": "Build",
42
+ "validate-contracts": "Build",
43
+ "verify-work": "Verify",
44
+ "validate-fix": "Verify",
45
+ "audit-code": "Verify",
46
+ "enforce-first": "Verify",
47
+ "run-evals": "Verify",
48
+ "investigate-bug": "Verify",
49
+ "diagnose-root": "Verify",
50
+ "fix-bug": "Verify",
51
+ "inspect-quality": "Verify",
52
+ "request-review": "Verify",
53
+ "respond-review": "Verify",
54
+ "trace-requirement": "Verify",
55
+ "release-branch": "Release",
56
+ "commit-message": "Release",
57
+ "session-state": "Sustain",
58
+ "terse-mode": "Sustain",
59
+ "compose-workflow": "Sustain",
60
+ "delegate-task": "Sustain",
61
+ "dispatch-agents": "Sustain",
62
+ "edit-document": "Sustain",
63
+ "evolve-skill": "Sustain",
64
+ "migrate-spec": "Sustain",
65
+ "organize-workspace": "Sustain",
66
+ "reset-baseline": "Sustain",
67
+ "simulate-agents": "Sustain",
68
+ "stocktake-skills": "Sustain",
69
+ "write-document": "Sustain",
70
+ "plan-tests": "Plan",
71
+ "gate-trace": "Verify",
72
+ "security-review": "Verify",
73
+ };
74
+ export function phaseForSkill(name) {
75
+ return PHASE_MAP[name] ?? "Other";
76
+ }
77
+ //# sourceMappingURL=phase-map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phase-map.js","sourceRoot":"","sources":["../../src/lib/phase-map.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,MAAM,CAAC,MAAM,SAAS,GAA2B;IAC/C,gBAAgB,EAAE,UAAU;IAC5B,gBAAgB,EAAE,UAAU;IAC5B,eAAe,EAAE,UAAU;IAC3B,iBAAiB,EAAE,UAAU;IAC7B,cAAc,EAAE,UAAU;IAC1B,gBAAgB,EAAE,UAAU;IAC5B,cAAc,EAAE,QAAQ;IACxB,iBAAiB,EAAE,QAAQ;IAC3B,UAAU,EAAE,QAAQ;IACpB,iBAAiB,EAAE,QAAQ;IAC3B,qBAAqB,EAAE,QAAQ;IAC/B,kBAAkB,EAAE,QAAQ;IAC5B,gBAAgB,EAAE,QAAQ;IAC1B,YAAY,EAAE,MAAM;IACpB,aAAa,EAAE,MAAM;IACrB,WAAW,EAAE,MAAM;IACnB,cAAc,EAAE,MAAM;IACtB,eAAe,EAAE,MAAM;IACvB,eAAe,EAAE,MAAM;IACvB,gBAAgB,EAAE,MAAM;IACxB,cAAc,EAAE,MAAM;IACtB,kBAAkB,EAAE,MAAM;IAC1B,aAAa,EAAE,OAAO;IACtB,gBAAgB,EAAE,OAAO;IACzB,cAAc,EAAE,OAAO;IACvB,YAAY,EAAE,OAAO;IACrB,iBAAiB,EAAE,OAAO;IAC1B,aAAa,EAAE,OAAO;IACtB,WAAW,EAAE,OAAO;IACpB,mBAAmB,EAAE,OAAO;IAC5B,oBAAoB,EAAE,OAAO;IAC7B,SAAS,EAAE,OAAO;IAClB,iBAAiB,EAAE,OAAO;IAC1B,YAAY,EAAE,OAAO;IACrB,qBAAqB,EAAE,OAAO;IAC9B,WAAW,EAAE,OAAO;IACpB,cAAc,EAAE,OAAO;IACvB,QAAQ,EAAE,OAAO;IACjB,YAAY,EAAE,OAAO;IACrB,oBAAoB,EAAE,OAAO;IAC7B,aAAa,EAAE,QAAQ;IACvB,cAAc,EAAE,QAAQ;IACxB,YAAY,EAAE,QAAQ;IACtB,eAAe,EAAE,QAAQ;IACzB,WAAW,EAAE,QAAQ;IACrB,iBAAiB,EAAE,QAAQ;IAC3B,eAAe,EAAE,QAAQ;IACzB,SAAS,EAAE,QAAQ;IACnB,iBAAiB,EAAE,QAAQ;IAC3B,gBAAgB,EAAE,QAAQ;IAC1B,gBAAgB,EAAE,QAAQ;IAC1B,mBAAmB,EAAE,QAAQ;IAC7B,gBAAgB,EAAE,SAAS;IAC3B,gBAAgB,EAAE,SAAS;IAC3B,eAAe,EAAE,SAAS;IAC1B,YAAY,EAAE,SAAS;IACvB,kBAAkB,EAAE,SAAS;IAC7B,eAAe,EAAE,SAAS;IAC1B,iBAAiB,EAAE,SAAS;IAC5B,eAAe,EAAE,SAAS;IAC1B,cAAc,EAAE,SAAS;IACzB,cAAc,EAAE,SAAS;IACzB,oBAAoB,EAAE,SAAS;IAC/B,gBAAgB,EAAE,SAAS;IAC3B,iBAAiB,EAAE,SAAS;IAC5B,kBAAkB,EAAE,SAAS;IAC7B,gBAAgB,EAAE,SAAS;IAC3B,YAAY,EAAE,MAAM;IACpB,YAAY,EAAE,QAAQ;IACtB,iBAAiB,EAAE,QAAQ;CAC5B,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC;AACpC,CAAC"}
@@ -0,0 +1,31 @@
1
+ export interface SkillIndexEntry {
2
+ name: string;
3
+ path: string;
4
+ phase: string;
5
+ }
6
+ export interface ParsedSkill {
7
+ name: string;
8
+ path: string;
9
+ frontmatter: Record<string, unknown>;
10
+ headings: Array<{
11
+ depth: number;
12
+ text: string;
13
+ }>;
14
+ codeBlocks: Array<{
15
+ lang: string | null;
16
+ value: string;
17
+ }>;
18
+ sections: Array<{
19
+ heading: string | null;
20
+ prose: string;
21
+ }>;
22
+ links: Array<{
23
+ text: string;
24
+ url: string;
25
+ }>;
26
+ rawProse: string;
27
+ truncated?: boolean;
28
+ }
29
+ export declare function discoverSkills(repoRoot: string, phaseFn: (n: string) => string): SkillIndexEntry[];
30
+ export declare function readSkillFile(repoRoot: string, skillName: string, maxBytes?: number): ParsedSkill;
31
+ export declare function parseSkillMarkdown(raw: string, skillName: string, skillPath: string, repoRoot: string): ParsedSkill;