septum 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -2
- package/package.json +1 -1
- package/src/cli/commands/slice.ts +4 -46
- package/src/cli/commands/topology.ts +119 -0
- package/src/cli/index.ts +11 -0
- package/src/cli/templates/skill.ts +7 -4
- package/src/core/config/loader.ts +21 -8
- package/src/core/database/repositories/dependency.repository.ts +70 -0
- package/src/core/database/repositories/environment.repository.ts +207 -0
- package/src/core/database/repositories/file.repository.ts +7 -0
- package/src/core/database/repositories/symbol.repository.ts +28 -9
- package/src/core/database/repository.ts +19 -1
- package/src/core/database/schema.ts +153 -120
- package/src/core/discovery/topology-detector.ts +71 -3
- package/src/core/ingestion/pipeline.ts +98 -1
- package/src/core/parser/behavioral-analyzer.ts +119 -0
- package/src/core/parser/boundary-tracker.ts +160 -0
- package/src/core/parser/extractors/base.ts +2 -0
- package/src/core/parser/extractors/blade.ts +158 -0
- package/src/core/parser/extractors/go.ts +5 -1
- package/src/core/parser/extractors/laravel-semantic.ts +506 -31
- package/src/core/parser/extractors/php.ts +5 -1
- package/src/core/parser/extractors/python.ts +3 -1
- package/src/core/parser/extractors/registry.ts +21 -0
- package/src/core/parser/extractors/typescript.ts +5 -1
- package/src/core/parser/schema/providers/laravel-migration-provider.ts +215 -0
- package/src/core/parser/schema/providers/prisma-schema-provider.ts +89 -0
- package/src/core/parser/schema/schema-provider-registry.ts +43 -0
- package/src/core/parser/schema/schema-provider.interface.ts +33 -0
- package/src/core/parser/tree-sitter.ts +2 -0
- package/src/core/resolver/path-resolver.ts +147 -0
- package/src/core/resolver/vertical-slice-tracer.ts +56 -8
- package/src/core/topology/environment-detector.ts +860 -0
- package/src/core/topology/types.ts +83 -0
- package/src/index.ts +3 -0
- package/src/mcp/schemas.ts +264 -46
- package/src/mcp/server.ts +130 -26
- package/src/mcp/tools/check-boundary.ts +58 -8
- package/src/mcp/tools/get-domain-catalog.ts +31 -1
- package/src/mcp/tools/get-environment-topology.ts +141 -0
- package/src/mcp/tools/get-symbol-hotspots.ts +13 -3
- package/src/mcp/tools/locate-symbol.ts +119 -3
- package/src/mcp/tools/register-domain.ts +1 -1
- package/src/mcp/tools/trace-vertical-slice.ts +11 -65
- package/src/types/index.ts +20 -1
- package/src/version.ts +3 -3
|
@@ -5,9 +5,11 @@ import type {
|
|
|
5
5
|
} from "../../types/index.ts";
|
|
6
6
|
import type { SeptumRepository } from "../database/repository.ts";
|
|
7
7
|
import { CallGraphTracer } from "./call-graph-tracer.ts";
|
|
8
|
+
import { SemanticSliceExtractorRegistry } from "../parser/extractors/registry.ts";
|
|
9
|
+
import { TopologyDetector } from "../discovery/topology-detector.ts";
|
|
8
10
|
|
|
9
11
|
export class VerticalSliceTracer {
|
|
10
|
-
constructor(private repo: SeptumRepository) {}
|
|
12
|
+
constructor(private repo: SeptumRepository, private projectRoot: string = process.cwd()) {}
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
15
|
* Trace an end-to-end vertical slice from route/action/intent query.
|
|
@@ -25,16 +27,29 @@ export class VerticalSliceTracer {
|
|
|
25
27
|
const lowerTrimmed = trimmed.toLowerCase();
|
|
26
28
|
let allSlices = this.repo.getAllVerticalSlices();
|
|
27
29
|
|
|
28
|
-
// Lazy fallback: If no slices cataloged,
|
|
29
|
-
|
|
30
|
+
// Lazy on-demand fallback: If no slices cataloged, extract framework routes or trace call-graph
|
|
31
|
+
const hasCatalogData = typeof (this.repo as any).getAllDomains === "function" && this.repo.getAllDomains().length > 0;
|
|
32
|
+
if (allSlices.length === 0 && hasCatalogData) {
|
|
30
33
|
try {
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
const topology = TopologyDetector.detect(this.projectRoot);
|
|
35
|
+
const semanticSlices = SemanticSliceExtractorRegistry.extractAllSlicesSync(
|
|
36
|
+
this.projectRoot,
|
|
37
|
+
topology.framework
|
|
38
|
+
);
|
|
39
|
+
if (semanticSlices.length > 0) {
|
|
40
|
+
for (const s of semanticSlices) {
|
|
35
41
|
this.repo.upsertVerticalSlice(s);
|
|
36
42
|
}
|
|
37
43
|
allSlices = this.repo.getAllVerticalSlices();
|
|
44
|
+
} else {
|
|
45
|
+
const tracer = new CallGraphTracer(this.repo, this.projectRoot);
|
|
46
|
+
const traced = tracer.traceAllSlices();
|
|
47
|
+
if (traced.length > 0) {
|
|
48
|
+
for (const s of traced) {
|
|
49
|
+
this.repo.upsertVerticalSlice(s);
|
|
50
|
+
}
|
|
51
|
+
allSlices = this.repo.getAllVerticalSlices();
|
|
52
|
+
}
|
|
38
53
|
}
|
|
39
54
|
} catch (err: unknown) {
|
|
40
55
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -83,6 +98,23 @@ export class VerticalSliceTracer {
|
|
|
83
98
|
return this.formatSuccessResponse(trimmed, nameMatch, "exact");
|
|
84
99
|
}
|
|
85
100
|
|
|
101
|
+
// 3b. Omni-Trigger Match: "JOB ProcessOrderJob", "job:ProcessOrderJob", "CLI order:cleanup", "EVENT OrderPlacedListener"
|
|
102
|
+
const omniTriggerMatch = trimmed.match(/^(JOB|CLI|EVENT)\s+([A-Za-z0-9_:\-]+)$/i);
|
|
103
|
+
if (omniTriggerMatch) {
|
|
104
|
+
const triggerKind = omniTriggerMatch[1].toUpperCase();
|
|
105
|
+
const targetName = omniTriggerMatch[2].toLowerCase();
|
|
106
|
+
const exact = allSlices.find(
|
|
107
|
+
(s) =>
|
|
108
|
+
s.http_method.toUpperCase() === triggerKind &&
|
|
109
|
+
(s.controller_class.toLowerCase() === targetName ||
|
|
110
|
+
s.route_uri.toLowerCase() === targetName ||
|
|
111
|
+
s.route_uri.toLowerCase() === `${triggerKind.toLowerCase()}:${targetName}`)
|
|
112
|
+
);
|
|
113
|
+
if (exact) {
|
|
114
|
+
return this.formatSuccessResponse(trimmed, exact, "exact");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
86
118
|
// 4. Controller@Action match: "OrderController@updateStatus" or "OrderController"
|
|
87
119
|
const controllerActionMatch = trimmed.match(/^([A-Za-z0-9_]+)(?:@([A-Za-z0-9_]+))?$/);
|
|
88
120
|
if (controllerActionMatch) {
|
|
@@ -204,7 +236,23 @@ export class VerticalSliceTracer {
|
|
|
204
236
|
const stageLines = chain.map((node) => {
|
|
205
237
|
const stageLabel = `[${node.stage.toUpperCase()}]`.padEnd(14, " ");
|
|
206
238
|
const loc = node.file ? ` (${node.file}${node.line ? `:${node.line}` : ""})` : "";
|
|
207
|
-
|
|
239
|
+
let extra = "";
|
|
240
|
+
if (node.table) {
|
|
241
|
+
extra += ` [table: ${node.table}]`;
|
|
242
|
+
}
|
|
243
|
+
if (node.columns_summary) {
|
|
244
|
+
extra += ` {${node.columns_summary}}`;
|
|
245
|
+
}
|
|
246
|
+
if (node.guards && node.guards.length > 0 && node.stage !== "guard") {
|
|
247
|
+
extra += ` [guards: ${node.guards.join(", ")}]`;
|
|
248
|
+
}
|
|
249
|
+
if (node.mutations && node.mutations.length > 0 && node.stage !== "side_effect") {
|
|
250
|
+
extra += ` [mutates: ${node.mutations.join(", ")}]`;
|
|
251
|
+
}
|
|
252
|
+
if (node.transactions && node.stage !== "transaction") {
|
|
253
|
+
extra += ` [tx: active]`;
|
|
254
|
+
}
|
|
255
|
+
return `${stageLabel} ${node.symbol}${loc}${extra}`;
|
|
208
256
|
});
|
|
209
257
|
message = `=== VERTICAL SLICE TRACE (${confidence.toUpperCase()}) ===\n` + stageLines.join("\n");
|
|
210
258
|
}
|