septum 0.1.0 → 0.1.2

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 (65) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +100 -100
  3. package/bin/septum.ts +4 -4
  4. package/package.json +63 -62
  5. package/src/cli/commands/check.ts +161 -161
  6. package/src/cli/commands/hook.ts +188 -188
  7. package/src/cli/commands/ingest.ts +29 -29
  8. package/src/cli/commands/init.ts +211 -211
  9. package/src/cli/commands/locate.ts +61 -61
  10. package/src/cli/commands/query.ts +64 -64
  11. package/src/cli/commands/serve.ts +5 -5
  12. package/src/cli/commands/slice.ts +90 -90
  13. package/src/cli/commands/sync.ts +31 -31
  14. package/src/cli/index.ts +199 -178
  15. package/src/cli/templates/hooks.ts +75 -75
  16. package/src/cli/templates/rules.ts +38 -38
  17. package/src/cli/templates/skill.ts +66 -66
  18. package/src/core/boundary/evaluator.ts +210 -210
  19. package/src/core/config/loader.ts +84 -84
  20. package/src/core/config/schema.ts +39 -39
  21. package/src/core/database/client.ts +44 -132
  22. package/src/core/database/repositories/dependency.repository.ts +279 -279
  23. package/src/core/database/repositories/domain.repository.ts +198 -198
  24. package/src/core/database/repositories/file.repository.ts +99 -99
  25. package/src/core/database/repositories/meta.repository.ts +33 -33
  26. package/src/core/database/repositories/symbol.repository.ts +424 -424
  27. package/src/core/database/repository.ts +242 -242
  28. package/src/core/database/schema.ts +120 -0
  29. package/src/core/discovery/topology-detector.ts +418 -418
  30. package/src/core/ingestion/hasher.ts +5 -5
  31. package/src/core/ingestion/pipeline.ts +438 -438
  32. package/src/core/parser/boundary-tracker.ts +128 -128
  33. package/src/core/parser/extractors/base.ts +60 -60
  34. package/src/core/parser/extractors/frontend.ts +194 -194
  35. package/src/core/parser/extractors/go.ts +176 -176
  36. package/src/core/parser/extractors/laravel-semantic.ts +426 -426
  37. package/src/core/parser/extractors/mcp-cli-semantic.ts +199 -199
  38. package/src/core/parser/extractors/nestjs-semantic.ts +119 -119
  39. package/src/core/parser/extractors/php.ts +149 -149
  40. package/src/core/parser/extractors/python.ts +226 -226
  41. package/src/core/parser/extractors/registry.ts +49 -49
  42. package/src/core/parser/extractors/semantic-extractor.interface.ts +21 -21
  43. package/src/core/parser/extractors/typescript.ts +177 -177
  44. package/src/core/parser/tree-sitter.ts +39 -39
  45. package/src/core/resolver/call-graph-tracer.ts +668 -668
  46. package/src/core/resolver/module-resolver.ts +342 -323
  47. package/src/core/resolver/symbol-locator.ts +543 -405
  48. package/src/core/resolver/vertical-slice-tracer.ts +237 -236
  49. package/src/core/session/session-manager.ts +56 -56
  50. package/src/core/telemetry/telemetry.ts +86 -86
  51. package/src/index.ts +18 -18
  52. package/src/mcp/schemas.ts +68 -68
  53. package/src/mcp/server.ts +612 -602
  54. package/src/mcp/tools/check-boundary.ts +102 -102
  55. package/src/mcp/tools/get-domain-catalog.ts +91 -91
  56. package/src/mcp/tools/get-feature-context.ts +116 -116
  57. package/src/mcp/tools/get-symbol-hotspots.ts +49 -49
  58. package/src/mcp/tools/get-symbol-impact.ts +26 -26
  59. package/src/mcp/tools/get-symbol.ts +63 -63
  60. package/src/mcp/tools/locate-symbol.ts +74 -74
  61. package/src/mcp/tools/register-domain.ts +64 -64
  62. package/src/mcp/tools/trace-vertical-slice.ts +102 -102
  63. package/src/types/index.ts +296 -296
  64. package/src/version.ts +3 -0
  65. package/src/core/database/schema.sql +0 -92
@@ -1,149 +1,149 @@
1
- import type { ExtractedDependency, ExtractedSymbol, ParsedFileAST, Visibility } from "../../../types/index.ts";
2
- import { findBraceBlockEnd } from "../boundary-tracker.ts";
3
- import type { CodeExtractor } from "./base.ts";
4
-
5
- export class PHPExtractor implements CodeExtractor {
6
- public canHandle(filePath: string): boolean {
7
- return /\.php$/i.test(filePath);
8
- }
9
-
10
- public async extract(filePath: string, content: string): Promise<ParsedFileAST> {
11
- const symbols: ExtractedSymbol[] = [];
12
- const dependencies: ExtractedDependency[] = [];
13
-
14
- const lines = content.split("\n");
15
-
16
- // 1. Extract PHP use / import statements
17
- const useRegex = /^\s*use\s+([^;]+);/;
18
- for (let i = 0; i < lines.length; i++) {
19
- const line = lines[i];
20
- const match = useRegex.exec(line);
21
- if (match) {
22
- const fullTarget = match[1].trim();
23
- // Remove 'function ' or 'const ' prefix if any
24
- const cleaned = fullTarget.replace(/^(function|const)\s+/, "");
25
- const isExternal =
26
- cleaned.startsWith("Illuminate\\") ||
27
- cleaned.startsWith("Symfony\\") ||
28
- cleaned.startsWith("Psr\\") ||
29
- cleaned.startsWith("Composer\\");
30
-
31
- dependencies.push({
32
- target: cleaned,
33
- statement: line.trim(),
34
- line_number: i + 1,
35
- is_external: isExternal,
36
- });
37
- }
38
- }
39
-
40
- // 2. Extract PHP Class / Interface / Trait / Enum
41
- let currentContainer: string | null = null;
42
- let currentContainerEndLine = 0;
43
-
44
- for (let i = 0; i < lines.length; i++) {
45
- const line = lines[i];
46
- const trimmed = line.trim();
47
- const lineNum = i + 1;
48
-
49
- if (currentContainer && lineNum > currentContainerEndLine) {
50
- currentContainer = null;
51
- currentContainerEndLine = 0;
52
- }
53
-
54
- // Class / Interface / Trait / Enum header
55
- const classMatch = /^(?:abstract\s+|final\s+|readonly\s+)*(class|interface|trait|enum)\s+([A-Za-z0-9_]+)/.exec(trimmed);
56
- if (classMatch) {
57
- currentContainer = classMatch[2];
58
- const endLine = findBraceBlockEnd(lines, i);
59
- currentContainerEndLine = endLine;
60
- symbols.push({
61
- name: classMatch[2],
62
- kind: classMatch[1] as any,
63
- signature: trimmed.replace(/\{$/, "").trim(),
64
- visibility: "public",
65
- line_start: lineNum,
66
- line_end: endLine,
67
- line_count: Math.max(1, endLine - lineNum + 1),
68
- });
69
- continue;
70
- }
71
-
72
- // Methods or Properties in class/interface/trait/enum
73
- if (currentContainer) {
74
- // PHP Constant: const STATUS_ACTIVE = 'active';
75
- const constMatch = /^(?:(public|protected|private)\s+)?const\s+([A-Za-z0-9_]+)\s*=/.exec(trimmed);
76
- if (constMatch) {
77
- const vis = (constMatch[1] as Visibility) || "public";
78
- const constName = constMatch[2];
79
- symbols.push({
80
- name: `${currentContainer}::${constName}`,
81
- kind: "property",
82
- signature: `${vis} const ${constName}`,
83
- visibility: vis,
84
- line_start: lineNum,
85
- line_end: lineNum,
86
- line_count: 1,
87
- });
88
- continue;
89
- }
90
-
91
- // PHP Property: public ?string $foo = null; or private readonly Bar $bar;
92
- const propMatch = /^(?:(public|protected|private)\s+)?(?:readonly\s+)?(?:static\s+)?(?:\??[A-Za-z0-9_\\\\]+\s+)?\$([A-Za-z0-9_]+)(?:\s*=[^;]+)?;\s*$/.exec(trimmed);
93
- if (propMatch && !trimmed.includes("function ")) {
94
- const vis = (propMatch[1] as Visibility) || "public";
95
- const propName = `$${propMatch[2]}`;
96
- symbols.push({
97
- name: `${currentContainer}::${propName}`,
98
- kind: "property",
99
- signature: `${vis} ${trimmed.replace(/;\s*$/, "")}`,
100
- visibility: vis,
101
- line_start: lineNum,
102
- line_end: lineNum,
103
- line_count: 1,
104
- });
105
- continue;
106
- }
107
-
108
- const methodMatch = /^(?:(public|protected|private)\s+)?(?:static\s+)?(?:final\s+)?function\s+([A-Za-z0-9_]+)\s*\(([^)]*)\)(?:\s*:\s*([^;{]+))?/.exec(trimmed);
109
- if (methodMatch) {
110
- const vis = (methodMatch[1] as Visibility) || "public";
111
- const name = methodMatch[2];
112
- const params = methodMatch[3].trim();
113
- const retType = methodMatch[4] ? `: ${methodMatch[4].trim()}` : "";
114
- const endLine = findBraceBlockEnd(lines, i);
115
- symbols.push({
116
- name: `${currentContainer}::${name}`,
117
- kind: "method",
118
- signature: `${vis} function ${name}(${params})${retType}`,
119
- visibility: vis,
120
- line_start: lineNum,
121
- line_end: endLine,
122
- line_count: Math.max(1, endLine - lineNum + 1),
123
- });
124
- continue;
125
- }
126
- }
127
-
128
- // Standalone Global Function in PHP
129
- const funcMatch = /^(?:final\s+)?function\s+([A-Za-z0-9_]+)\s*\(([^)]*)\)(?:\s*:\s*([^;{]+))?/.exec(trimmed);
130
- if (funcMatch && !currentContainer) {
131
- const name = funcMatch[1];
132
- const params = funcMatch[2].trim();
133
- const retType = funcMatch[3] ? `: ${funcMatch[3].trim()}` : "";
134
- const endLine = findBraceBlockEnd(lines, i);
135
- symbols.push({
136
- name,
137
- kind: "function",
138
- signature: `function ${name}(${params})${retType}`,
139
- visibility: "public",
140
- line_start: lineNum,
141
- line_end: endLine,
142
- line_count: Math.max(1, endLine - lineNum + 1),
143
- });
144
- }
145
- }
146
-
147
- return { symbols, dependencies };
148
- }
149
- }
1
+ import type { ExtractedDependency, ExtractedSymbol, ParsedFileAST, Visibility } from "../../../types/index.ts";
2
+ import { findBraceBlockEnd } from "../boundary-tracker.ts";
3
+ import type { CodeExtractor } from "./base.ts";
4
+
5
+ export class PHPExtractor implements CodeExtractor {
6
+ public canHandle(filePath: string): boolean {
7
+ return /\.php$/i.test(filePath);
8
+ }
9
+
10
+ public async extract(filePath: string, content: string): Promise<ParsedFileAST> {
11
+ const symbols: ExtractedSymbol[] = [];
12
+ const dependencies: ExtractedDependency[] = [];
13
+
14
+ const lines = content.split("\n");
15
+
16
+ // 1. Extract PHP use / import statements
17
+ const useRegex = /^\s*use\s+([^;]+);/;
18
+ for (let i = 0; i < lines.length; i++) {
19
+ const line = lines[i];
20
+ const match = useRegex.exec(line);
21
+ if (match) {
22
+ const fullTarget = match[1].trim();
23
+ // Remove 'function ' or 'const ' prefix if any
24
+ const cleaned = fullTarget.replace(/^(function|const)\s+/, "");
25
+ const isExternal =
26
+ cleaned.startsWith("Illuminate\\") ||
27
+ cleaned.startsWith("Symfony\\") ||
28
+ cleaned.startsWith("Psr\\") ||
29
+ cleaned.startsWith("Composer\\");
30
+
31
+ dependencies.push({
32
+ target: cleaned,
33
+ statement: line.trim(),
34
+ line_number: i + 1,
35
+ is_external: isExternal,
36
+ });
37
+ }
38
+ }
39
+
40
+ // 2. Extract PHP Class / Interface / Trait / Enum
41
+ let currentContainer: string | null = null;
42
+ let currentContainerEndLine = 0;
43
+
44
+ for (let i = 0; i < lines.length; i++) {
45
+ const line = lines[i];
46
+ const trimmed = line.trim();
47
+ const lineNum = i + 1;
48
+
49
+ if (currentContainer && lineNum > currentContainerEndLine) {
50
+ currentContainer = null;
51
+ currentContainerEndLine = 0;
52
+ }
53
+
54
+ // Class / Interface / Trait / Enum header
55
+ const classMatch = /^(?:abstract\s+|final\s+|readonly\s+)*(class|interface|trait|enum)\s+([A-Za-z0-9_]+)/.exec(trimmed);
56
+ if (classMatch) {
57
+ currentContainer = classMatch[2];
58
+ const endLine = findBraceBlockEnd(lines, i);
59
+ currentContainerEndLine = endLine;
60
+ symbols.push({
61
+ name: classMatch[2],
62
+ kind: classMatch[1] as any,
63
+ signature: trimmed.replace(/\{$/, "").trim(),
64
+ visibility: "public",
65
+ line_start: lineNum,
66
+ line_end: endLine,
67
+ line_count: Math.max(1, endLine - lineNum + 1),
68
+ });
69
+ continue;
70
+ }
71
+
72
+ // Methods or Properties in class/interface/trait/enum
73
+ if (currentContainer) {
74
+ // PHP Constant: const STATUS_ACTIVE = 'active';
75
+ const constMatch = /^(?:(public|protected|private)\s+)?const\s+([A-Za-z0-9_]+)\s*=/.exec(trimmed);
76
+ if (constMatch) {
77
+ const vis = (constMatch[1] as Visibility) || "public";
78
+ const constName = constMatch[2];
79
+ symbols.push({
80
+ name: `${currentContainer}::${constName}`,
81
+ kind: "property",
82
+ signature: `${vis} const ${constName}`,
83
+ visibility: vis,
84
+ line_start: lineNum,
85
+ line_end: lineNum,
86
+ line_count: 1,
87
+ });
88
+ continue;
89
+ }
90
+
91
+ // PHP Property: public ?string $foo = null; or private readonly Bar $bar;
92
+ const propMatch = /^(?:(public|protected|private)\s+)?(?:readonly\s+)?(?:static\s+)?(?:\??[A-Za-z0-9_\\\\]+\s+)?\$([A-Za-z0-9_]+)(?:\s*=[^;]+)?;\s*$/.exec(trimmed);
93
+ if (propMatch && !trimmed.includes("function ")) {
94
+ const vis = (propMatch[1] as Visibility) || "public";
95
+ const propName = `$${propMatch[2]}`;
96
+ symbols.push({
97
+ name: `${currentContainer}::${propName}`,
98
+ kind: "property",
99
+ signature: `${vis} ${trimmed.replace(/;\s*$/, "")}`,
100
+ visibility: vis,
101
+ line_start: lineNum,
102
+ line_end: lineNum,
103
+ line_count: 1,
104
+ });
105
+ continue;
106
+ }
107
+
108
+ const methodMatch = /^(?:(public|protected|private)\s+)?(?:static\s+)?(?:final\s+)?function\s+([A-Za-z0-9_]+)\s*\(([^)]*)\)(?:\s*:\s*([^;{]+))?/.exec(trimmed);
109
+ if (methodMatch) {
110
+ const vis = (methodMatch[1] as Visibility) || "public";
111
+ const name = methodMatch[2];
112
+ const params = methodMatch[3].trim();
113
+ const retType = methodMatch[4] ? `: ${methodMatch[4].trim()}` : "";
114
+ const endLine = findBraceBlockEnd(lines, i);
115
+ symbols.push({
116
+ name: `${currentContainer}::${name}`,
117
+ kind: "method",
118
+ signature: `${vis} function ${name}(${params})${retType}`,
119
+ visibility: vis,
120
+ line_start: lineNum,
121
+ line_end: endLine,
122
+ line_count: Math.max(1, endLine - lineNum + 1),
123
+ });
124
+ continue;
125
+ }
126
+ }
127
+
128
+ // Standalone Global Function in PHP
129
+ const funcMatch = /^(?:final\s+)?function\s+([A-Za-z0-9_]+)\s*\(([^)]*)\)(?:\s*:\s*([^;{]+))?/.exec(trimmed);
130
+ if (funcMatch && !currentContainer) {
131
+ const name = funcMatch[1];
132
+ const params = funcMatch[2].trim();
133
+ const retType = funcMatch[3] ? `: ${funcMatch[3].trim()}` : "";
134
+ const endLine = findBraceBlockEnd(lines, i);
135
+ symbols.push({
136
+ name,
137
+ kind: "function",
138
+ signature: `function ${name}(${params})${retType}`,
139
+ visibility: "public",
140
+ line_start: lineNum,
141
+ line_end: endLine,
142
+ line_count: Math.max(1, endLine - lineNum + 1),
143
+ });
144
+ }
145
+ }
146
+
147
+ return { symbols, dependencies };
148
+ }
149
+ }