septum 0.1.4 → 0.1.6
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/LICENSE +21 -21
- package/README.md +105 -105
- package/bin/septum.ts +4 -4
- package/package.json +63 -63
- package/src/cli/commands/check.ts +161 -161
- package/src/cli/commands/hook.ts +216 -188
- package/src/cli/commands/ingest.ts +29 -29
- package/src/cli/commands/init.ts +213 -211
- package/src/cli/commands/locate.ts +61 -61
- package/src/cli/commands/query.ts +104 -64
- package/src/cli/commands/serve.ts +5 -5
- package/src/cli/commands/slice.ts +50 -48
- package/src/cli/commands/sync.ts +31 -31
- package/src/cli/index.ts +220 -210
- package/src/cli/templates/hooks.ts +75 -75
- package/src/cli/templates/rules.ts +50 -38
- package/src/cli/templates/skill.ts +65 -69
- package/src/core/boundary/evaluator.ts +429 -210
- package/src/core/config/loader.ts +117 -97
- package/src/core/config/schema.ts +39 -39
- package/src/core/database/client.ts +44 -44
- package/src/core/database/repositories/dependency.repository.ts +552 -349
- package/src/core/database/repositories/domain.repository.ts +275 -198
- package/src/core/database/repositories/file.repository.ts +117 -106
- package/src/core/database/repositories/meta.repository.ts +33 -33
- package/src/core/database/repositories/symbol.repository.ts +482 -443
- package/src/core/database/repository.ts +281 -260
- package/src/core/database/schema.ts +154 -153
- package/src/core/discovery/topology-detector.ts +486 -486
- package/src/core/ingestion/hasher.ts +5 -5
- package/src/core/ingestion/pipeline.ts +606 -535
- package/src/core/parser/boundary-tracker.ts +433 -288
- package/src/core/parser/extractors/base.ts +62 -62
- package/src/core/parser/extractors/blade.ts +158 -158
- package/src/core/parser/extractors/frontend.ts +147 -194
- package/src/core/parser/extractors/go.ts +408 -180
- package/src/core/parser/extractors/laravel-semantic.ts +1045 -901
- package/src/core/parser/extractors/mcp-cli-semantic.ts +328 -199
- package/src/core/parser/extractors/nestjs-semantic.ts +134 -119
- package/src/core/parser/extractors/php.ts +415 -153
- package/src/core/parser/extractors/python.ts +460 -228
- package/src/core/parser/extractors/registry.ts +70 -70
- package/src/core/parser/extractors/semantic-extractor.interface.ts +21 -21
- package/src/core/parser/extractors/typescript.ts +668 -181
- package/src/core/parser/tree-sitter.ts +41 -41
- package/src/core/parser/wasm-loader.ts +271 -0
- package/src/core/resolver/call-graph-tracer.ts +698 -668
- package/src/core/resolver/module-resolver.ts +479 -342
- package/src/core/resolver/path-resolver.ts +147 -147
- package/src/core/resolver/symbol-locator.ts +543 -543
- package/src/core/resolver/vertical-slice-tracer.ts +323 -285
- package/src/core/session/session-manager.ts +56 -56
- package/src/core/telemetry/telemetry.ts +86 -86
- package/src/core/topology/environment-detector.ts +109 -6
- package/src/index.ts +21 -21
- package/src/mcp/schemas.ts +695 -286
- package/src/mcp/server.ts +927 -716
- package/src/mcp/tools/check-boundary.ts +307 -152
- package/src/mcp/tools/get-domain-catalog.ts +155 -121
- package/src/mcp/tools/get-environment-topology.ts +3 -6
- package/src/mcp/tools/get-feature-context.ts +227 -116
- package/src/mcp/tools/get-symbol-hotspots.ts +54 -59
- package/src/mcp/tools/get-symbol-impact.ts +28 -26
- package/src/mcp/tools/get-symbol.ts +65 -63
- package/src/mcp/tools/locate-symbol.ts +169 -190
- package/src/mcp/tools/register-domain.ts +59 -64
- package/src/mcp/tools/register-feature.ts +91 -0
- package/src/mcp/tools/trace-vertical-slice.ts +74 -48
- package/src/types/index.ts +366 -315
- package/src/version.ts +3 -3
|
@@ -1,147 +1,147 @@
|
|
|
1
|
-
import { existsSync, statSync } from "node:fs";
|
|
2
|
-
import { dirname, isAbsolute, join, normalize, resolve } from "node:path";
|
|
3
|
-
|
|
4
|
-
export const PROJECT_ROOT_MARKERS = [
|
|
5
|
-
"package.json",
|
|
6
|
-
"composer.json",
|
|
7
|
-
"go.mod",
|
|
8
|
-
"pyproject.toml",
|
|
9
|
-
"Cargo.toml",
|
|
10
|
-
".git",
|
|
11
|
-
".septum",
|
|
12
|
-
"pnpm-workspace.yaml",
|
|
13
|
-
"lerna.json",
|
|
14
|
-
"tsconfig.json",
|
|
15
|
-
"jsconfig.json",
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
let lastKnownProjectRoot: string | undefined;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Normalizes and canonicalizes a path for cross-platform consistency.
|
|
22
|
-
* On Windows, uppercases drive letters (e.g. "c:\" -> "C:\") to eliminate map lookup misses.
|
|
23
|
-
*/
|
|
24
|
-
export function canonicalizePath(targetPath: string): string {
|
|
25
|
-
if (!targetPath || typeof targetPath !== "string") {
|
|
26
|
-
return targetPath;
|
|
27
|
-
}
|
|
28
|
-
let abs = normalize(resolve(targetPath));
|
|
29
|
-
if (process.platform === "win32") {
|
|
30
|
-
abs = abs.replace(/^[a-zA-Z]:/, (m) => m.toUpperCase());
|
|
31
|
-
}
|
|
32
|
-
return abs;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function setLastKnownProjectRoot(root: string): void {
|
|
36
|
-
if (root && typeof root === "string") {
|
|
37
|
-
lastKnownProjectRoot = canonicalizePath(root);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function getLastKnownProjectRoot(): string | undefined {
|
|
42
|
-
return lastKnownProjectRoot;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function clearLastKnownProjectRoot(): void {
|
|
46
|
-
lastKnownProjectRoot = undefined;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Checks whether a given directory is an MCP host / IDE installation directory
|
|
51
|
-
* (e.g. Antigravity Electron install directory) rather than a user project codebase.
|
|
52
|
-
*/
|
|
53
|
-
export function isAppHostDirectory(dirPath: string): boolean {
|
|
54
|
-
try {
|
|
55
|
-
const norm = dirPath.toLowerCase().replace(/\\/g, "/");
|
|
56
|
-
if (norm.includes("/antigravity") || norm.includes("/appdata/local/programs/antigravity")) {
|
|
57
|
-
// Check if it has Electron app runtime signatures
|
|
58
|
-
if (
|
|
59
|
-
existsSync(join(dirPath, "resources", "app.asar")) ||
|
|
60
|
-
existsSync(join(dirPath, "resources", "app.asar.unpacked")) ||
|
|
61
|
-
existsSync(join(dirPath, "locales"))
|
|
62
|
-
) {
|
|
63
|
-
return true;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
} catch {
|
|
67
|
-
// Ignore error
|
|
68
|
-
}
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Discovers the project root directory by walking up looking for marker files.
|
|
74
|
-
*/
|
|
75
|
-
export function findProjectRoot(fromPath: string): string {
|
|
76
|
-
try {
|
|
77
|
-
let dir = resolve(fromPath);
|
|
78
|
-
|
|
79
|
-
if (existsSync(dir)) {
|
|
80
|
-
const stat = statSync(dir);
|
|
81
|
-
if (!stat.isDirectory()) {
|
|
82
|
-
dir = dirname(dir);
|
|
83
|
-
}
|
|
84
|
-
} else {
|
|
85
|
-
dir = dirname(dir);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
let current = dir;
|
|
89
|
-
while (true) {
|
|
90
|
-
// Don't treat an app host directory as a project root
|
|
91
|
-
if (!isAppHostDirectory(current)) {
|
|
92
|
-
for (const marker of PROJECT_ROOT_MARKERS) {
|
|
93
|
-
if (existsSync(join(current, marker))) {
|
|
94
|
-
return canonicalizePath(current);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const parent = dirname(current);
|
|
100
|
-
if (parent === current) break;
|
|
101
|
-
current = parent;
|
|
102
|
-
}
|
|
103
|
-
} catch {
|
|
104
|
-
// Filesystem traversal error fallback
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return canonicalizePath(dirname(resolve(fromPath)));
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Ergonomically resolves the active workspace root:
|
|
112
|
-
* 1. Explicit pathHint (if provided and valid).
|
|
113
|
-
* 2. SEPTUM_WORKSPACE_ROOT environment variable.
|
|
114
|
-
* 3. lastKnownProjectRoot (if cached from earlier tool calls).
|
|
115
|
-
* 4. findProjectRoot from process.cwd() (if not an app host directory).
|
|
116
|
-
*/
|
|
117
|
-
export function resolveWorkspaceRoot(pathHint?: string): string {
|
|
118
|
-
if (pathHint && typeof pathHint === "string" && pathHint.trim()) {
|
|
119
|
-
const trimmed = pathHint.trim().replace(/^['"]|['"]$/g, "");
|
|
120
|
-
const candidate = findProjectRoot(trimmed);
|
|
121
|
-
if (candidate && existsSync(candidate) && !isAppHostDirectory(candidate)) {
|
|
122
|
-
setLastKnownProjectRoot(candidate);
|
|
123
|
-
return candidate;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const envRoot = process.env.SEPTUM_WORKSPACE_ROOT || process.env.WORKSPACE_ROOT;
|
|
128
|
-
if (envRoot && existsSync(envRoot) && !isAppHostDirectory(envRoot)) {
|
|
129
|
-
const candidate = canonicalizePath(envRoot);
|
|
130
|
-
setLastKnownProjectRoot(candidate);
|
|
131
|
-
return candidate;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (lastKnownProjectRoot && existsSync(lastKnownProjectRoot)) {
|
|
135
|
-
return lastKnownProjectRoot;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const cwd = process.cwd();
|
|
139
|
-
if (!isAppHostDirectory(cwd)) {
|
|
140
|
-
const candidate = findProjectRoot(cwd);
|
|
141
|
-
setLastKnownProjectRoot(candidate);
|
|
142
|
-
return candidate;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Fallback if inside app host directory: keep looking in lastKnown or return cwd
|
|
146
|
-
return canonicalizePath(cwd);
|
|
147
|
-
}
|
|
1
|
+
import { existsSync, statSync } from "node:fs";
|
|
2
|
+
import { dirname, isAbsolute, join, normalize, resolve } from "node:path";
|
|
3
|
+
|
|
4
|
+
export const PROJECT_ROOT_MARKERS = [
|
|
5
|
+
"package.json",
|
|
6
|
+
"composer.json",
|
|
7
|
+
"go.mod",
|
|
8
|
+
"pyproject.toml",
|
|
9
|
+
"Cargo.toml",
|
|
10
|
+
".git",
|
|
11
|
+
".septum",
|
|
12
|
+
"pnpm-workspace.yaml",
|
|
13
|
+
"lerna.json",
|
|
14
|
+
"tsconfig.json",
|
|
15
|
+
"jsconfig.json",
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
let lastKnownProjectRoot: string | undefined;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Normalizes and canonicalizes a path for cross-platform consistency.
|
|
22
|
+
* On Windows, uppercases drive letters (e.g. "c:\" -> "C:\") to eliminate map lookup misses.
|
|
23
|
+
*/
|
|
24
|
+
export function canonicalizePath(targetPath: string): string {
|
|
25
|
+
if (!targetPath || typeof targetPath !== "string") {
|
|
26
|
+
return targetPath;
|
|
27
|
+
}
|
|
28
|
+
let abs = normalize(resolve(targetPath));
|
|
29
|
+
if (process.platform === "win32") {
|
|
30
|
+
abs = abs.replace(/^[a-zA-Z]:/, (m) => m.toUpperCase());
|
|
31
|
+
}
|
|
32
|
+
return abs;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function setLastKnownProjectRoot(root: string): void {
|
|
36
|
+
if (root && typeof root === "string") {
|
|
37
|
+
lastKnownProjectRoot = canonicalizePath(root);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function getLastKnownProjectRoot(): string | undefined {
|
|
42
|
+
return lastKnownProjectRoot;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function clearLastKnownProjectRoot(): void {
|
|
46
|
+
lastKnownProjectRoot = undefined;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Checks whether a given directory is an MCP host / IDE installation directory
|
|
51
|
+
* (e.g. Antigravity Electron install directory) rather than a user project codebase.
|
|
52
|
+
*/
|
|
53
|
+
export function isAppHostDirectory(dirPath: string): boolean {
|
|
54
|
+
try {
|
|
55
|
+
const norm = dirPath.toLowerCase().replace(/\\/g, "/");
|
|
56
|
+
if (norm.includes("/antigravity") || norm.includes("/appdata/local/programs/antigravity")) {
|
|
57
|
+
// Check if it has Electron app runtime signatures
|
|
58
|
+
if (
|
|
59
|
+
existsSync(join(dirPath, "resources", "app.asar")) ||
|
|
60
|
+
existsSync(join(dirPath, "resources", "app.asar.unpacked")) ||
|
|
61
|
+
existsSync(join(dirPath, "locales"))
|
|
62
|
+
) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
} catch {
|
|
67
|
+
// Ignore error
|
|
68
|
+
}
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Discovers the project root directory by walking up looking for marker files.
|
|
74
|
+
*/
|
|
75
|
+
export function findProjectRoot(fromPath: string): string {
|
|
76
|
+
try {
|
|
77
|
+
let dir = resolve(fromPath);
|
|
78
|
+
|
|
79
|
+
if (existsSync(dir)) {
|
|
80
|
+
const stat = statSync(dir);
|
|
81
|
+
if (!stat.isDirectory()) {
|
|
82
|
+
dir = dirname(dir);
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
dir = dirname(dir);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let current = dir;
|
|
89
|
+
while (true) {
|
|
90
|
+
// Don't treat an app host directory as a project root
|
|
91
|
+
if (!isAppHostDirectory(current)) {
|
|
92
|
+
for (const marker of PROJECT_ROOT_MARKERS) {
|
|
93
|
+
if (existsSync(join(current, marker))) {
|
|
94
|
+
return canonicalizePath(current);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const parent = dirname(current);
|
|
100
|
+
if (parent === current) break;
|
|
101
|
+
current = parent;
|
|
102
|
+
}
|
|
103
|
+
} catch {
|
|
104
|
+
// Filesystem traversal error fallback
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return canonicalizePath(dirname(resolve(fromPath)));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Ergonomically resolves the active workspace root:
|
|
112
|
+
* 1. Explicit pathHint (if provided and valid).
|
|
113
|
+
* 2. SEPTUM_WORKSPACE_ROOT environment variable.
|
|
114
|
+
* 3. lastKnownProjectRoot (if cached from earlier tool calls).
|
|
115
|
+
* 4. findProjectRoot from process.cwd() (if not an app host directory).
|
|
116
|
+
*/
|
|
117
|
+
export function resolveWorkspaceRoot(pathHint?: string): string {
|
|
118
|
+
if (pathHint && typeof pathHint === "string" && pathHint.trim()) {
|
|
119
|
+
const trimmed = pathHint.trim().replace(/^['"]|['"]$/g, "");
|
|
120
|
+
const candidate = findProjectRoot(trimmed);
|
|
121
|
+
if (candidate && existsSync(candidate) && !isAppHostDirectory(candidate)) {
|
|
122
|
+
setLastKnownProjectRoot(candidate);
|
|
123
|
+
return candidate;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const envRoot = process.env.SEPTUM_WORKSPACE_ROOT || process.env.WORKSPACE_ROOT;
|
|
128
|
+
if (envRoot && existsSync(envRoot) && !isAppHostDirectory(envRoot)) {
|
|
129
|
+
const candidate = canonicalizePath(envRoot);
|
|
130
|
+
setLastKnownProjectRoot(candidate);
|
|
131
|
+
return candidate;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (lastKnownProjectRoot && existsSync(lastKnownProjectRoot)) {
|
|
135
|
+
return lastKnownProjectRoot;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const cwd = process.cwd();
|
|
139
|
+
if (!isAppHostDirectory(cwd)) {
|
|
140
|
+
const candidate = findProjectRoot(cwd);
|
|
141
|
+
setLastKnownProjectRoot(candidate);
|
|
142
|
+
return candidate;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Fallback if inside app host directory: keep looking in lastKnown or return cwd
|
|
146
|
+
return canonicalizePath(cwd);
|
|
147
|
+
}
|