@jakkrichm/create-nexus-devflow 2.0.27 → 2.2.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/README.md +29 -7
- package/dist/bin/create-nexus-devflow.d.ts +5 -1
- package/dist/bin/create-nexus-devflow.js +247 -4
- package/dist/bin/create-nexus-devflow.js.map +1 -1
- package/dist/lib/branch-context.d.ts +39 -0
- package/dist/lib/branch-context.js +196 -0
- package/dist/lib/branch-context.js.map +1 -0
- package/dist/lib/code-graph.d.ts +30 -0
- package/dist/lib/code-graph.js +209 -0
- package/dist/lib/code-graph.js.map +1 -0
- package/dist/lib/context-slicer.d.ts +31 -0
- package/dist/lib/context-slicer.js +234 -0
- package/dist/lib/context-slicer.js.map +1 -0
- package/dist/lib/current-work.js +4 -2
- package/dist/lib/current-work.js.map +1 -1
- package/dist/lib/dashboard-page.d.ts +1 -1
- package/dist/lib/dashboard-page.js +140 -56
- package/dist/lib/dashboard-page.js.map +1 -1
- package/dist/lib/dashboard-snapshot.d.ts +13 -0
- package/dist/lib/dashboard-snapshot.js +24 -6
- package/dist/lib/dashboard-snapshot.js.map +1 -1
- package/dist/lib/dashboard.js +38 -0
- package/dist/lib/dashboard.js.map +1 -1
- package/dist/lib/drift-reconciler.d.ts +38 -0
- package/dist/lib/drift-reconciler.js +155 -0
- package/dist/lib/drift-reconciler.js.map +1 -0
- package/dist/lib/gatekeeper.d.ts +1 -0
- package/dist/lib/gatekeeper.js +30 -1
- package/dist/lib/gatekeeper.js.map +1 -1
- package/dist/lib/git-hooks.js +41 -16
- package/dist/lib/git-hooks.js.map +1 -1
- package/dist/lib/ide-extension.d.ts +38 -0
- package/dist/lib/ide-extension.js +61 -0
- package/dist/lib/ide-extension.js.map +1 -0
- package/dist/lib/mcp.d.ts +36 -0
- package/dist/lib/mcp.js +653 -0
- package/dist/lib/mcp.js.map +1 -0
- package/dist/lib/project-metadata.d.ts +1 -1
- package/dist/lib/project-metadata.js +3 -2
- package/dist/lib/project-metadata.js.map +1 -1
- package/dist/lib/status.d.ts +1 -1
- package/dist/lib/status.js +4 -4
- package/dist/lib/status.js.map +1 -1
- package/dist/lib/swarm-orchestrator.d.ts +31 -0
- package/dist/lib/swarm-orchestrator.js +134 -0
- package/dist/lib/swarm-orchestrator.js.map +1 -0
- package/dist/lib/update.js +7 -3
- package/dist/lib/update.js.map +1 -1
- package/dist/lib/webview-studio.d.ts +8 -0
- package/dist/lib/webview-studio.js +463 -0
- package/dist/lib/webview-studio.js.map +1 -0
- package/dist/lib/workflow-state.js +24 -8
- package/dist/lib/workflow-state.js.map +1 -1
- package/package.json +1 -1
- package/template/.agents/skills/adopt/SKILL.md +58 -5
- package/template/.agents/skills/doctor/SKILL.md +23 -16
- package/template/.agents/skills/implement/SKILL.md +2 -2
- package/template/.agents/skills/onboard/SKILL.md +18 -17
- package/template/.agents/skills/rollback/SKILL.md +1 -1
- package/template/.claude/skills/00-explore/SKILL.md +2 -2
- package/template/.claude/skills/10-define/SKILL.md +2 -2
- package/template/.claude/skills/20-spec/SKILL.md +1 -2
- package/template/.claude/skills/30-plan/SKILL.md +1 -2
- package/template/.claude/skills/40-execute/SKILL.md +2 -2
- package/template/.claude/skills/50-verify/SKILL.md +2 -2
- package/template/.claude/skills/60-report/SKILL.md +2 -2
- package/template/.claude/skills/70-deliver/SKILL.md +2 -2
- package/template/.claude/skills/adopt/SKILL.md +191 -75
- package/template/.claude/skills/audit/SKILL.md +267 -133
- package/template/.claude/skills/autopilot/SKILL.md +226 -167
- package/template/.claude/skills/brainstorm/SKILL.md +62 -0
- package/template/.claude/skills/brief/SKILL.md +93 -92
- package/template/.claude/skills/check/SKILL.md +96 -76
- package/template/.claude/skills/ci/SKILL.md +140 -61
- package/template/.claude/skills/complete/SKILL.md +156 -101
- package/template/.claude/skills/convert-any-to-md/SKILL.md +2 -2
- package/template/.claude/skills/convert-any-to-md/references/setup.md +29 -0
- package/template/.claude/skills/convert-any-to-md/scripts/convert_any_to_md.py +487 -0
- package/template/.claude/skills/convert-any-to-md/scripts/requirements.txt +3 -0
- package/template/.claude/skills/debug/SKILL.md +124 -49
- package/template/.claude/skills/devflow/SKILL.md +9 -3
- package/template/.claude/skills/discovery/SKILL.md +150 -129
- package/template/.claude/skills/doctor/SKILL.md +195 -72
- package/template/.claude/skills/feature/SKILL.md +195 -151
- package/template/.claude/skills/fix/SKILL.md +41 -90
- package/template/.claude/skills/idea/SKILL.md +2 -2
- package/template/.claude/skills/implement/SKILL.md +189 -46
- package/template/.claude/skills/onboard/SKILL.md +216 -85
- package/template/.claude/skills/overview/SKILL.md +44 -29
- package/template/.claude/skills/prototype/SKILL.md +82 -27
- package/template/.claude/skills/release/SKILL.md +119 -130
- package/template/.claude/skills/report-html/SKILL.md +2 -2
- package/template/.claude/skills/rollback/SKILL.md +123 -77
- package/template/.claude/skills/status/SKILL.md +109 -0
- package/template/.claude/skills/test/SKILL.md +2 -2
- package/template/.claude/skills/tests/SKILL.md +126 -0
- package/template/.claude/skills/try/SKILL.md +77 -65
- package/template/AGENTS.md +2 -1
- package/template/devflow/build-plan.md +50 -20
- package/template/devflow/history/features/README.md +5 -0
- package/template/devflow/history/fixes/README.md +5 -0
- package/template/devflow/history/rollbacks/README.md +5 -0
- package/template/devflow/project-plan.md +70 -18
- package/template/devflow/reference/studio.html +504 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import fsSync from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { readGitStatus } from "./git-status.js";
|
|
5
|
+
/**
|
|
6
|
+
* Sanitizes a Git branch name into a cross-platform safe directory name.
|
|
7
|
+
* e.g. "feature/044-auth#login" -> "feature-044-auth-login"
|
|
8
|
+
*/
|
|
9
|
+
export function sanitizeBranchName(branch) {
|
|
10
|
+
return branch
|
|
11
|
+
.trim()
|
|
12
|
+
.replace(/[^a-zA-Z0-9._-]+/g, "-")
|
|
13
|
+
.replace(/-+/g, "-")
|
|
14
|
+
.replace(/^-+|-+$/g, "")
|
|
15
|
+
.toLowerCase();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Resolves active context paths for the current repository and git branch.
|
|
19
|
+
* Checks for branch-isolated context in:
|
|
20
|
+
* 1. devflow/context/<sanitized>/ (Primary user-visible multi-dev location)
|
|
21
|
+
* 2. .nexus/branches/<sanitized>/ (Internal branch cache)
|
|
22
|
+
* 3. devflow/context/ (Default fallback)
|
|
23
|
+
*/
|
|
24
|
+
export async function resolveActiveContextPaths(projectRoot, explicitBranch) {
|
|
25
|
+
const defaultFeaturePath = path.join(projectRoot, "devflow", "context", "current-feature.md");
|
|
26
|
+
const defaultStagePath = path.join(projectRoot, "devflow", "context", "current-stage.md");
|
|
27
|
+
const defaultFindingsPath = path.join(projectRoot, "devflow", "context", "findings.md");
|
|
28
|
+
let branchName = explicitBranch || null;
|
|
29
|
+
if (!branchName) {
|
|
30
|
+
const git = await readGitStatus(projectRoot);
|
|
31
|
+
if (git.available && git.branch) {
|
|
32
|
+
branchName = git.branch;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (!branchName || branchName === "main" || branchName === "master" || branchName === "HEAD") {
|
|
36
|
+
return {
|
|
37
|
+
isBranchScoped: false,
|
|
38
|
+
branchName,
|
|
39
|
+
sanitizedBranch: null,
|
|
40
|
+
branchDir: null,
|
|
41
|
+
featureSpecPath: defaultFeaturePath,
|
|
42
|
+
stagePath: defaultStagePath,
|
|
43
|
+
findingsPath: defaultFindingsPath
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const sanitized = sanitizeBranchName(branchName);
|
|
47
|
+
// Candidate 1: devflow/context/<sanitized>/
|
|
48
|
+
const devflowBranchDir = path.join(projectRoot, "devflow", "context", sanitized);
|
|
49
|
+
const devflowBranchFeature = path.join(devflowBranchDir, "current-feature.md");
|
|
50
|
+
const devflowBranchStage = path.join(devflowBranchDir, "current-stage.md");
|
|
51
|
+
if (fsSync.existsSync(devflowBranchFeature)) {
|
|
52
|
+
return {
|
|
53
|
+
isBranchScoped: true,
|
|
54
|
+
branchName,
|
|
55
|
+
sanitizedBranch: sanitized,
|
|
56
|
+
branchDir: devflowBranchDir,
|
|
57
|
+
featureSpecPath: devflowBranchFeature,
|
|
58
|
+
stagePath: fsSync.existsSync(devflowBranchStage) ? devflowBranchStage : defaultStagePath,
|
|
59
|
+
findingsPath: defaultFindingsPath
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// Candidate 2: .nexus/branches/<sanitized>/
|
|
63
|
+
const nexusBranchDir = path.join(projectRoot, ".nexus", "branches", sanitized);
|
|
64
|
+
const nexusBranchFeature = path.join(nexusBranchDir, "current-feature.md");
|
|
65
|
+
const nexusBranchStage = path.join(nexusBranchDir, "current-stage.md");
|
|
66
|
+
if (fsSync.existsSync(nexusBranchFeature)) {
|
|
67
|
+
return {
|
|
68
|
+
isBranchScoped: true,
|
|
69
|
+
branchName,
|
|
70
|
+
sanitizedBranch: sanitized,
|
|
71
|
+
branchDir: nexusBranchDir,
|
|
72
|
+
featureSpecPath: nexusBranchFeature,
|
|
73
|
+
stagePath: fsSync.existsSync(nexusBranchStage) ? nexusBranchStage : defaultStagePath,
|
|
74
|
+
findingsPath: defaultFindingsPath
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
isBranchScoped: false,
|
|
79
|
+
branchName,
|
|
80
|
+
sanitizedBranch: sanitized,
|
|
81
|
+
branchDir: null,
|
|
82
|
+
featureSpecPath: defaultFeaturePath,
|
|
83
|
+
stagePath: defaultStagePath,
|
|
84
|
+
findingsPath: defaultFindingsPath
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Initializes a branch-scoped context directory under devflow/context/<sanitized>/ (or .nexus/branches/)
|
|
89
|
+
*/
|
|
90
|
+
export async function initBranchContext(projectRoot, branchName, initialSpec, useDevflowContextDir = true) {
|
|
91
|
+
const sanitized = sanitizeBranchName(branchName);
|
|
92
|
+
const branchDir = useDevflowContextDir
|
|
93
|
+
? path.join(projectRoot, "devflow", "context", sanitized)
|
|
94
|
+
: path.join(projectRoot, ".nexus", "branches", sanitized);
|
|
95
|
+
await fs.mkdir(branchDir, { recursive: true });
|
|
96
|
+
const featurePath = path.join(branchDir, "current-feature.md");
|
|
97
|
+
const stagePath = path.join(branchDir, "current-stage.md");
|
|
98
|
+
if (initialSpec) {
|
|
99
|
+
await fs.writeFile(featurePath, initialSpec, "utf8");
|
|
100
|
+
}
|
|
101
|
+
else if (!fsSync.existsSync(featurePath)) {
|
|
102
|
+
const defaultFeature = path.join(projectRoot, "devflow", "context", "current-feature.md");
|
|
103
|
+
try {
|
|
104
|
+
const baseline = await fs.readFile(defaultFeature, "utf8");
|
|
105
|
+
await fs.writeFile(featurePath, baseline, "utf8");
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
await fs.writeFile(featurePath, "# Current Feature\n\n_Nothing in progress. Run /feature, /fix, or /rollback to start._\n", "utf8");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (!fsSync.existsSync(stagePath)) {
|
|
112
|
+
const defaultStage = path.join(projectRoot, "devflow", "context", "current-stage.md");
|
|
113
|
+
try {
|
|
114
|
+
const baseline = await fs.readFile(defaultStage, "utf8");
|
|
115
|
+
await fs.writeFile(stagePath, baseline, "utf8");
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
await fs.writeFile(stagePath, `# Current Stage\n\n- Track: \`fast\`\n- Branch: \`${branchName}\`\n`, "utf8");
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
isBranchScoped: true,
|
|
123
|
+
branchName,
|
|
124
|
+
sanitizedBranch: sanitized,
|
|
125
|
+
branchDir,
|
|
126
|
+
featureSpecPath: featurePath,
|
|
127
|
+
stagePath,
|
|
128
|
+
findingsPath: path.join(projectRoot, "devflow", "context", "findings.md")
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Cleans up branch-scoped context directories after completion.
|
|
133
|
+
*/
|
|
134
|
+
export async function cleanupBranchContext(projectRoot, branchName) {
|
|
135
|
+
const sanitized = sanitizeBranchName(branchName);
|
|
136
|
+
const devflowBranchDir = path.join(projectRoot, "devflow", "context", sanitized);
|
|
137
|
+
const nexusBranchDir = path.join(projectRoot, ".nexus", "branches", sanitized);
|
|
138
|
+
let cleaned = false;
|
|
139
|
+
try {
|
|
140
|
+
if (fsSync.existsSync(devflowBranchDir)) {
|
|
141
|
+
await fs.rm(devflowBranchDir, { recursive: true, force: true });
|
|
142
|
+
cleaned = true;
|
|
143
|
+
}
|
|
144
|
+
if (fsSync.existsSync(nexusBranchDir)) {
|
|
145
|
+
await fs.rm(nexusBranchDir, { recursive: true, force: true });
|
|
146
|
+
cleaned = true;
|
|
147
|
+
}
|
|
148
|
+
return cleaned;
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Lists all active branch isolated contexts.
|
|
156
|
+
*/
|
|
157
|
+
export async function listBranchContexts(projectRoot) {
|
|
158
|
+
const results = [];
|
|
159
|
+
const reservedDevflowDirs = new Set(["current-run", "findings.md", "current-feature.md", "current-stage.md", "coding-standards.md", "project-overview.md", "ai-interaction.md"]);
|
|
160
|
+
// Scan devflow/context/
|
|
161
|
+
const contextRoot = path.join(projectRoot, "devflow", "context");
|
|
162
|
+
if (fsSync.existsSync(contextRoot)) {
|
|
163
|
+
const entries = await fs.readdir(contextRoot, { withFileTypes: true });
|
|
164
|
+
for (const entry of entries) {
|
|
165
|
+
if (entry.isDirectory() && !reservedDevflowDirs.has(entry.name)) {
|
|
166
|
+
const dirPath = path.join(contextRoot, entry.name);
|
|
167
|
+
const specPath = path.join(dirPath, "current-feature.md");
|
|
168
|
+
results.push({
|
|
169
|
+
branch: entry.name,
|
|
170
|
+
path: dirPath,
|
|
171
|
+
hasSpec: fsSync.existsSync(specPath),
|
|
172
|
+
type: "devflow"
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// Scan .nexus/branches/
|
|
178
|
+
const nexusBranchesRoot = path.join(projectRoot, ".nexus", "branches");
|
|
179
|
+
if (fsSync.existsSync(nexusBranchesRoot)) {
|
|
180
|
+
const entries = await fs.readdir(nexusBranchesRoot, { withFileTypes: true });
|
|
181
|
+
for (const entry of entries) {
|
|
182
|
+
if (entry.isDirectory()) {
|
|
183
|
+
const dirPath = path.join(nexusBranchesRoot, entry.name);
|
|
184
|
+
const specPath = path.join(dirPath, "current-feature.md");
|
|
185
|
+
results.push({
|
|
186
|
+
branch: entry.name,
|
|
187
|
+
path: dirPath,
|
|
188
|
+
hasSpec: fsSync.existsSync(specPath),
|
|
189
|
+
type: "nexus"
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return results;
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=branch-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-context.js","sourceRoot":"","sources":["../../lib/branch-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface CodeGraphNode {
|
|
2
|
+
filePath: string;
|
|
3
|
+
imports: string[];
|
|
4
|
+
importedBy: string[];
|
|
5
|
+
exports: string[];
|
|
6
|
+
}
|
|
7
|
+
export interface CodeGraph {
|
|
8
|
+
nodes: Record<string, CodeGraphNode>;
|
|
9
|
+
totalFiles: number;
|
|
10
|
+
totalEdges: number;
|
|
11
|
+
}
|
|
12
|
+
export interface BlastRadiusReport {
|
|
13
|
+
targetFile: string;
|
|
14
|
+
exists: boolean;
|
|
15
|
+
directDependents: string[];
|
|
16
|
+
transitiveDependents: string[];
|
|
17
|
+
totalAffected: number;
|
|
18
|
+
impactScore: "LOW" | "MEDIUM" | "HIGH" | "CRITICAL";
|
|
19
|
+
affectedFiles: string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Builds an In-Memory Codebase Semantic Dependency Graph.
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildCodeGraph(projectRoot: string, options?: {
|
|
25
|
+
maxFiles?: number;
|
|
26
|
+
}): Promise<CodeGraph>;
|
|
27
|
+
/**
|
|
28
|
+
* Calculates the Blast Radius (direct and transitive dependents) of a modified target file.
|
|
29
|
+
*/
|
|
30
|
+
export declare function calculateBlastRadius(graph: CodeGraph, targetFile: string): BlastRadiusReport;
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import fsSync from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
const SUPPORTED_EXTENSIONS = new Set([".ts", ".js", ".mjs", ".cjs", ".jsx", ".tsx"]);
|
|
5
|
+
const IGNORED_DIRS = new Set([
|
|
6
|
+
"node_modules",
|
|
7
|
+
".git",
|
|
8
|
+
"dist",
|
|
9
|
+
"build",
|
|
10
|
+
".nexus",
|
|
11
|
+
".agents",
|
|
12
|
+
".claude",
|
|
13
|
+
"coverage"
|
|
14
|
+
]);
|
|
15
|
+
/**
|
|
16
|
+
* Normalizes file path to forward slashes relative to workspace root.
|
|
17
|
+
*/
|
|
18
|
+
function normalizeRelative(projectRoot, filePath) {
|
|
19
|
+
const rel = path.isAbsolute(filePath) ? path.relative(projectRoot, filePath) : filePath;
|
|
20
|
+
return rel.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Resolves an import specifier relative to the importing file.
|
|
24
|
+
*/
|
|
25
|
+
function resolveImportPath(projectRoot, importingFile, specifier) {
|
|
26
|
+
if (!specifier.startsWith(".")) {
|
|
27
|
+
return null; // External package
|
|
28
|
+
}
|
|
29
|
+
const baseDir = path.dirname(path.join(projectRoot, importingFile));
|
|
30
|
+
let resolved = path.join(baseDir, specifier);
|
|
31
|
+
// Try direct match or common extensions
|
|
32
|
+
if (fsSync.existsSync(resolved) && fsSync.statSync(resolved).isFile()) {
|
|
33
|
+
return normalizeRelative(projectRoot, resolved);
|
|
34
|
+
}
|
|
35
|
+
const candidates = [
|
|
36
|
+
resolved,
|
|
37
|
+
resolved + ".ts",
|
|
38
|
+
resolved + ".js",
|
|
39
|
+
resolved + ".tsx",
|
|
40
|
+
resolved + ".jsx",
|
|
41
|
+
resolved.replace(/\.js$/, ".ts"),
|
|
42
|
+
resolved.replace(/\.jsx$/, ".tsx"),
|
|
43
|
+
path.join(resolved, "index.ts"),
|
|
44
|
+
path.join(resolved, "index.js")
|
|
45
|
+
];
|
|
46
|
+
for (const c of candidates) {
|
|
47
|
+
if (fsSync.existsSync(c) && fsSync.statSync(c).isFile()) {
|
|
48
|
+
return normalizeRelative(projectRoot, c);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return normalizeRelative(projectRoot, resolved.replace(/\\/g, "/"));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Parses exports and imports from code contents using regex AST heuristic.
|
|
55
|
+
*/
|
|
56
|
+
function parseModuleSymbols(content) {
|
|
57
|
+
const imports = [];
|
|
58
|
+
const exports = [];
|
|
59
|
+
// Import matches: import ... from "..." or require("...")
|
|
60
|
+
const importRegex = /(?:import\s+(?:[\w*\s{},$]+from\s+)?['"]([^'"]+)['"])|(?:require\s*\(\s*['"]([^'"]+)['"]\s*\))/g;
|
|
61
|
+
let match;
|
|
62
|
+
while ((match = importRegex.exec(content)) !== null) {
|
|
63
|
+
const spec = match[1] || match[2];
|
|
64
|
+
if (spec)
|
|
65
|
+
imports.push(spec);
|
|
66
|
+
}
|
|
67
|
+
// Export matches: export { ... } or export const/function/class/interface/type/default
|
|
68
|
+
const exportRegex = /export\s+(?:default\s+|const\s+|let\s+|var\s+|function\s+|class\s+|interface\s+|type\s+)?([a-zA-Z0-9_$]+)/g;
|
|
69
|
+
while ((match = exportRegex.exec(content)) !== null) {
|
|
70
|
+
const sym = match[1];
|
|
71
|
+
if (sym && !["default", "const", "let", "var", "function", "class", "interface", "type"].includes(sym)) {
|
|
72
|
+
exports.push(sym);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
imports: Array.from(new Set(imports)),
|
|
77
|
+
exports: Array.from(new Set(exports))
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Recursively scans directory to collect supported code files.
|
|
82
|
+
*/
|
|
83
|
+
async function collectFiles(dir, projectRoot, fileList = []) {
|
|
84
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
85
|
+
for (const entry of entries) {
|
|
86
|
+
if (entry.name.startsWith(".") && entry.name !== ".gitignore")
|
|
87
|
+
continue;
|
|
88
|
+
if (IGNORED_DIRS.has(entry.name))
|
|
89
|
+
continue;
|
|
90
|
+
const fullPath = path.join(dir, entry.name);
|
|
91
|
+
if (entry.isDirectory()) {
|
|
92
|
+
await collectFiles(fullPath, projectRoot, fileList);
|
|
93
|
+
}
|
|
94
|
+
else if (entry.isFile()) {
|
|
95
|
+
const ext = path.extname(entry.name).toLowerCase();
|
|
96
|
+
if (SUPPORTED_EXTENSIONS.has(ext)) {
|
|
97
|
+
fileList.push(normalizeRelative(projectRoot, fullPath));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return fileList;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Builds an In-Memory Codebase Semantic Dependency Graph.
|
|
105
|
+
*/
|
|
106
|
+
export async function buildCodeGraph(projectRoot, options = {}) {
|
|
107
|
+
const files = await collectFiles(projectRoot, projectRoot);
|
|
108
|
+
const targetFiles = options.maxFiles ? files.slice(0, options.maxFiles) : files;
|
|
109
|
+
const nodes = {};
|
|
110
|
+
// 1. Initialize all nodes
|
|
111
|
+
for (const file of targetFiles) {
|
|
112
|
+
nodes[file] = {
|
|
113
|
+
filePath: file,
|
|
114
|
+
imports: [],
|
|
115
|
+
importedBy: [],
|
|
116
|
+
exports: []
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
// 2. Parse symbols and build edges
|
|
120
|
+
let totalEdges = 0;
|
|
121
|
+
for (const file of targetFiles) {
|
|
122
|
+
try {
|
|
123
|
+
const fullPath = path.join(projectRoot, file);
|
|
124
|
+
const content = await fs.readFile(fullPath, "utf8");
|
|
125
|
+
const { imports, exports } = parseModuleSymbols(content);
|
|
126
|
+
nodes[file].exports = exports;
|
|
127
|
+
for (const imp of imports) {
|
|
128
|
+
const resolved = resolveImportPath(projectRoot, file, imp);
|
|
129
|
+
if (resolved && nodes[resolved]) {
|
|
130
|
+
if (!nodes[file].imports.includes(resolved)) {
|
|
131
|
+
nodes[file].imports.push(resolved);
|
|
132
|
+
totalEdges++;
|
|
133
|
+
}
|
|
134
|
+
if (!nodes[resolved].importedBy.includes(file)) {
|
|
135
|
+
nodes[resolved].importedBy.push(file);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Graceful ignore on unreadable files
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
nodes,
|
|
146
|
+
totalFiles: Object.keys(nodes).length,
|
|
147
|
+
totalEdges
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Calculates the Blast Radius (direct and transitive dependents) of a modified target file.
|
|
152
|
+
*/
|
|
153
|
+
export function calculateBlastRadius(graph, targetFile) {
|
|
154
|
+
const normalizedTarget = targetFile.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
155
|
+
const directDependents = [];
|
|
156
|
+
const transitiveDependents = [];
|
|
157
|
+
const visited = new Set();
|
|
158
|
+
// Find exact node or match suffix
|
|
159
|
+
let targetNodeKey = Object.keys(graph.nodes).find((k) => k === normalizedTarget || k.endsWith(normalizedTarget) || normalizedTarget.endsWith(k));
|
|
160
|
+
if (!targetNodeKey || !graph.nodes[targetNodeKey]) {
|
|
161
|
+
return {
|
|
162
|
+
targetFile: normalizedTarget,
|
|
163
|
+
exists: false,
|
|
164
|
+
directDependents: [],
|
|
165
|
+
transitiveDependents: [],
|
|
166
|
+
totalAffected: 0,
|
|
167
|
+
impactScore: "LOW",
|
|
168
|
+
affectedFiles: []
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
const direct = graph.nodes[targetNodeKey].importedBy;
|
|
172
|
+
directDependents.push(...direct);
|
|
173
|
+
visited.add(targetNodeKey);
|
|
174
|
+
const queue = [...direct];
|
|
175
|
+
for (const d of direct)
|
|
176
|
+
visited.add(d);
|
|
177
|
+
while (queue.length > 0) {
|
|
178
|
+
const current = queue.shift();
|
|
179
|
+
const node = graph.nodes[current];
|
|
180
|
+
if (node && node.importedBy) {
|
|
181
|
+
for (const parent of node.importedBy) {
|
|
182
|
+
if (!visited.has(parent)) {
|
|
183
|
+
visited.add(parent);
|
|
184
|
+
transitiveDependents.push(parent);
|
|
185
|
+
queue.push(parent);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
const totalAffected = directDependents.length + transitiveDependents.length;
|
|
191
|
+
let impactScore = "LOW";
|
|
192
|
+
if (totalAffected >= 10)
|
|
193
|
+
impactScore = "CRITICAL";
|
|
194
|
+
else if (totalAffected >= 5)
|
|
195
|
+
impactScore = "HIGH";
|
|
196
|
+
else if (totalAffected >= 2)
|
|
197
|
+
impactScore = "MEDIUM";
|
|
198
|
+
const affectedFiles = Array.from(new Set([...directDependents, ...transitiveDependents]));
|
|
199
|
+
return {
|
|
200
|
+
targetFile: targetNodeKey,
|
|
201
|
+
exists: true,
|
|
202
|
+
directDependents,
|
|
203
|
+
transitiveDependents,
|
|
204
|
+
totalAffected,
|
|
205
|
+
impactScore,
|
|
206
|
+
affectedFiles
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=code-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-graph.js","sourceRoot":"","sources":["../../lib/code-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type SliceStage = "implement" | "check" | "explore" | "feature" | "status";
|
|
2
|
+
export interface SliceOptions {
|
|
3
|
+
maxTokens?: number;
|
|
4
|
+
taskIndex?: number;
|
|
5
|
+
customBranch?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ContextSliceSection {
|
|
8
|
+
name: string;
|
|
9
|
+
tokens: number;
|
|
10
|
+
content: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ContextSliceResult {
|
|
13
|
+
stage: SliceStage;
|
|
14
|
+
estimatedTokens: number;
|
|
15
|
+
rawTokens: number;
|
|
16
|
+
reductionPercentage: number;
|
|
17
|
+
content: string;
|
|
18
|
+
sections: ContextSliceSection[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Estimates token count for text using standard character/word heuristic for mixed markdown/code.
|
|
22
|
+
*/
|
|
23
|
+
export declare function estimateTokenCount(text: string): number;
|
|
24
|
+
/**
|
|
25
|
+
* Parses markdown into discrete sections by headings (## or ###) and filters by allowed patterns.
|
|
26
|
+
*/
|
|
27
|
+
export declare function pruneMarkdownSections(markdown: string, allowedHeadingPatterns: RegExp[], maxTokens?: number): string;
|
|
28
|
+
/**
|
|
29
|
+
* Creates a stage-aware context slice for AI agents, omitting irrelevant sections.
|
|
30
|
+
*/
|
|
31
|
+
export declare function sliceContextForStage(projectRoot: string, stage: SliceStage, options?: SliceOptions): Promise<ContextSliceResult>;
|