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.
Files changed (46) hide show
  1. package/README.md +7 -2
  2. package/package.json +1 -1
  3. package/src/cli/commands/slice.ts +4 -46
  4. package/src/cli/commands/topology.ts +119 -0
  5. package/src/cli/index.ts +11 -0
  6. package/src/cli/templates/skill.ts +7 -4
  7. package/src/core/config/loader.ts +21 -8
  8. package/src/core/database/repositories/dependency.repository.ts +70 -0
  9. package/src/core/database/repositories/environment.repository.ts +207 -0
  10. package/src/core/database/repositories/file.repository.ts +7 -0
  11. package/src/core/database/repositories/symbol.repository.ts +28 -9
  12. package/src/core/database/repository.ts +19 -1
  13. package/src/core/database/schema.ts +153 -120
  14. package/src/core/discovery/topology-detector.ts +71 -3
  15. package/src/core/ingestion/pipeline.ts +98 -1
  16. package/src/core/parser/behavioral-analyzer.ts +119 -0
  17. package/src/core/parser/boundary-tracker.ts +160 -0
  18. package/src/core/parser/extractors/base.ts +2 -0
  19. package/src/core/parser/extractors/blade.ts +158 -0
  20. package/src/core/parser/extractors/go.ts +5 -1
  21. package/src/core/parser/extractors/laravel-semantic.ts +506 -31
  22. package/src/core/parser/extractors/php.ts +5 -1
  23. package/src/core/parser/extractors/python.ts +3 -1
  24. package/src/core/parser/extractors/registry.ts +21 -0
  25. package/src/core/parser/extractors/typescript.ts +5 -1
  26. package/src/core/parser/schema/providers/laravel-migration-provider.ts +215 -0
  27. package/src/core/parser/schema/providers/prisma-schema-provider.ts +89 -0
  28. package/src/core/parser/schema/schema-provider-registry.ts +43 -0
  29. package/src/core/parser/schema/schema-provider.interface.ts +33 -0
  30. package/src/core/parser/tree-sitter.ts +2 -0
  31. package/src/core/resolver/path-resolver.ts +147 -0
  32. package/src/core/resolver/vertical-slice-tracer.ts +56 -8
  33. package/src/core/topology/environment-detector.ts +860 -0
  34. package/src/core/topology/types.ts +83 -0
  35. package/src/index.ts +3 -0
  36. package/src/mcp/schemas.ts +264 -46
  37. package/src/mcp/server.ts +130 -26
  38. package/src/mcp/tools/check-boundary.ts +58 -8
  39. package/src/mcp/tools/get-domain-catalog.ts +31 -1
  40. package/src/mcp/tools/get-environment-topology.ts +141 -0
  41. package/src/mcp/tools/get-symbol-hotspots.ts +13 -3
  42. package/src/mcp/tools/locate-symbol.ts +119 -3
  43. package/src/mcp/tools/register-domain.ts +1 -1
  44. package/src/mcp/tools/trace-vertical-slice.ts +11 -65
  45. package/src/types/index.ts +20 -1
  46. 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, attempt heuristic call-graph tracing
29
- if (allSlices.length === 0) {
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 tracer = new CallGraphTracer(this.repo);
32
- const traced = tracer.traceAllSlices();
33
- if (traced.length > 0) {
34
- for (const s of traced) {
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
- return `${stageLabel} ${node.symbol}${loc}`;
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
  }