bigpowers 2.59.9 → 2.61.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/.mcp.json +9 -0
- package/.pi/package.json +2 -2
- package/.pi/prompts/develop-tdd.md +1 -0
- package/.pi/prompts/gate-trace.md +1 -0
- package/.pi/prompts/orchestrate-project.md +1 -1
- package/.pi/prompts/plan-tests.md +74 -0
- package/.pi/prompts/plan-work.md +14 -1
- package/.pi/prompts/verify-work.md +14 -5
- package/.pi/skills/develop-tdd/SKILL.md +1 -0
- package/.pi/skills/gate-trace/SKILL.md +1 -0
- package/.pi/skills/orchestrate-project/SKILL.md +1 -1
- package/.pi/skills/plan-tests/SKILL.md +76 -0
- package/.pi/skills/plan-work/SKILL.md +14 -1
- package/.pi/skills/verify-work/SKILL.md +14 -5
- package/CHANGELOG.md +14 -0
- package/CONVENTIONS.md +5 -1
- package/README.md +1 -1
- package/SKILL-INDEX.md +1 -1
- package/bigpowers-mcp/build/config.d.ts +7 -0
- package/bigpowers-mcp/build/config.js +35 -0
- package/bigpowers-mcp/build/config.js.map +1 -0
- package/bigpowers-mcp/build/index.d.ts +2 -0
- package/bigpowers-mcp/build/index.js +20 -0
- package/bigpowers-mcp/build/index.js.map +1 -0
- package/bigpowers-mcp/build/lib/git-context.d.ts +12 -0
- package/bigpowers-mcp/build/lib/git-context.js +91 -0
- package/bigpowers-mcp/build/lib/git-context.js.map +1 -0
- package/bigpowers-mcp/build/lib/graph/builder.d.ts +4 -0
- package/bigpowers-mcp/build/lib/graph/builder.js +85 -0
- package/bigpowers-mcp/build/lib/graph/builder.js.map +1 -0
- package/bigpowers-mcp/build/lib/graph/store.d.ts +11 -0
- package/bigpowers-mcp/build/lib/graph/store.js +77 -0
- package/bigpowers-mcp/build/lib/graph/store.js.map +1 -0
- package/bigpowers-mcp/build/lib/graph/types.d.ts +24 -0
- package/bigpowers-mcp/build/lib/graph/types.js +2 -0
- package/bigpowers-mcp/build/lib/graph/types.js.map +1 -0
- package/bigpowers-mcp/build/lib/paths.d.ts +8 -0
- package/bigpowers-mcp/build/lib/paths.js +40 -0
- package/bigpowers-mcp/build/lib/paths.js.map +1 -0
- package/bigpowers-mcp/build/lib/phase-map.d.ts +3 -0
- package/bigpowers-mcp/build/lib/phase-map.js +77 -0
- package/bigpowers-mcp/build/lib/phase-map.js.map +1 -0
- package/bigpowers-mcp/build/lib/skill-parser.d.ts +31 -0
- package/bigpowers-mcp/build/lib/skill-parser.js +159 -0
- package/bigpowers-mcp/build/lib/skill-parser.js.map +1 -0
- package/bigpowers-mcp/build/lib/validate-skill.d.ts +13 -0
- package/bigpowers-mcp/build/lib/validate-skill.js +62 -0
- package/bigpowers-mcp/build/lib/validate-skill.js.map +1 -0
- package/bigpowers-mcp/build/tools/index.d.ts +9 -0
- package/bigpowers-mcp/build/tools/index.js +172 -0
- package/bigpowers-mcp/build/tools/index.js.map +1 -0
- package/bigpowers-mcp/package-lock.json +3685 -0
- package/bigpowers-mcp/package.json +30 -0
- package/bigpowers-mcp/src/config.ts +44 -0
- package/bigpowers-mcp/src/index.ts +23 -0
- package/bigpowers-mcp/src/lib/git-context.ts +98 -0
- package/bigpowers-mcp/src/lib/graph/builder.ts +95 -0
- package/bigpowers-mcp/src/lib/graph/store.ts +87 -0
- package/bigpowers-mcp/src/lib/graph/types.ts +28 -0
- package/bigpowers-mcp/src/lib/paths.ts +47 -0
- package/bigpowers-mcp/src/lib/phase-map.ts +77 -0
- package/bigpowers-mcp/src/lib/skill-parser.ts +191 -0
- package/bigpowers-mcp/src/lib/validate-skill.ts +90 -0
- package/bigpowers-mcp/src/tools/index.ts +225 -0
- package/bigpowers-mcp/test/catalog.test.ts +121 -0
- package/bigpowers-mcp/test/fixtures/graph/test-graph.jsonl +5 -0
- package/bigpowers-mcp/test/fixtures/skills/broken-link/SKILL.md +11 -0
- package/bigpowers-mcp/test/fixtures/skills/missing-verify/SKILL.md +9 -0
- package/bigpowers-mcp/test/fixtures/skills/valid-skill/SKILL.md +14 -0
- package/bigpowers-mcp/tsconfig.json +16 -0
- package/bigpowers-mcp/vitest.config.ts +8 -0
- package/package.json +1 -1
- package/scripts/check-blind-spots.sh +5 -4
- package/scripts/lib/blind-spots.py +37 -1
- package/skills/develop-tdd/SKILL.md +1 -0
- package/skills/gate-trace/SKILL.md +1 -0
- package/skills/orchestrate-project/SKILL.md +1 -1
- package/skills/plan-tests/REFERENCE.md +31 -0
- package/skills/plan-tests/SKILL.md +42 -0
- package/skills/plan-work/REFERENCE.md +13 -0
- package/skills/plan-work/SKILL.md +1 -1
- package/skills/verify-work/SKILL.md +14 -5
- package/skills-lock.json +10 -5
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { GIT_SCOPE_DIRS } from "../config.js";
|
|
5
|
+
import { isSecretPath } from "./paths.js";
|
|
6
|
+
function inScope(filePath) {
|
|
7
|
+
const norm = filePath.replace(/\\/g, "/");
|
|
8
|
+
if (isSecretPath(norm))
|
|
9
|
+
return false;
|
|
10
|
+
return GIT_SCOPE_DIRS.some((d) => norm === d || norm.startsWith(`${d}/`));
|
|
11
|
+
}
|
|
12
|
+
function groupByDir(files) {
|
|
13
|
+
const grouped = {};
|
|
14
|
+
for (const f of files) {
|
|
15
|
+
const parts = f.split("/");
|
|
16
|
+
const dir = parts.length > 1 ? parts[0] : ".";
|
|
17
|
+
if (!grouped[dir])
|
|
18
|
+
grouped[dir] = [];
|
|
19
|
+
grouped[dir].push(f);
|
|
20
|
+
}
|
|
21
|
+
return grouped;
|
|
22
|
+
}
|
|
23
|
+
function git(repoRoot, args) {
|
|
24
|
+
return execFileSync("git", args, {
|
|
25
|
+
cwd: repoRoot,
|
|
26
|
+
encoding: "utf8",
|
|
27
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
28
|
+
}).trim();
|
|
29
|
+
}
|
|
30
|
+
export function getGitContext(repoRoot, action) {
|
|
31
|
+
if (action === "status") {
|
|
32
|
+
const out = git(repoRoot, ["status", "--porcelain"]);
|
|
33
|
+
const files = out
|
|
34
|
+
.split("\n")
|
|
35
|
+
.filter(Boolean)
|
|
36
|
+
.map((line) => line.slice(3).trim())
|
|
37
|
+
.filter(inScope);
|
|
38
|
+
return { action, changed_files: groupByDir(files) };
|
|
39
|
+
}
|
|
40
|
+
if (action === "log") {
|
|
41
|
+
const out = git(repoRoot, [
|
|
42
|
+
"log",
|
|
43
|
+
"-10",
|
|
44
|
+
"--pretty=format:%H|%s",
|
|
45
|
+
"--name-only",
|
|
46
|
+
"--",
|
|
47
|
+
...GIT_SCOPE_DIRS,
|
|
48
|
+
]);
|
|
49
|
+
const commits = [];
|
|
50
|
+
let current = null;
|
|
51
|
+
for (const line of out.split("\n")) {
|
|
52
|
+
if (line.includes("|")) {
|
|
53
|
+
if (current)
|
|
54
|
+
commits.push(current);
|
|
55
|
+
const [hash, subject] = line.split("|");
|
|
56
|
+
current = { hash, subject, files: [] };
|
|
57
|
+
}
|
|
58
|
+
else if (line.trim() && current && inScope(line.trim())) {
|
|
59
|
+
current.files.push(line.trim());
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (current)
|
|
63
|
+
commits.push(current);
|
|
64
|
+
return { action, changed_files: {}, commits };
|
|
65
|
+
}
|
|
66
|
+
const diffOut = git(repoRoot, ["diff", "--", ...GIT_SCOPE_DIRS]);
|
|
67
|
+
const diffs = {};
|
|
68
|
+
let currentFile = "";
|
|
69
|
+
let buf = [];
|
|
70
|
+
for (const line of diffOut.split("\n")) {
|
|
71
|
+
if (line.startsWith("diff --git")) {
|
|
72
|
+
if (currentFile && buf.length)
|
|
73
|
+
diffs[currentFile] = buf.join("\n");
|
|
74
|
+
const match = / b\/(.+)$/.exec(line);
|
|
75
|
+
currentFile = match?.[1] ?? "";
|
|
76
|
+
buf = [line];
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
buf.push(line);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (currentFile && buf.length && inScope(currentFile) && !isSecretPath(currentFile)) {
|
|
83
|
+
diffs[currentFile] = buf.join("\n");
|
|
84
|
+
}
|
|
85
|
+
const changed = Object.keys(diffs);
|
|
86
|
+
return { action, changed_files: groupByDir(changed), diffs };
|
|
87
|
+
}
|
|
88
|
+
export function isGitRepo(repoRoot) {
|
|
89
|
+
return fs.existsSync(path.join(repoRoot, ".git"));
|
|
90
|
+
}
|
|
91
|
+
//# 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 @@
|
|
|
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,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;
|