septum 0.1.3 → 0.1.5

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 (74) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +105 -102
  3. package/bin/septum.ts +4 -4
  4. package/package.json +63 -63
  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 +48 -90
  13. package/src/cli/commands/sync.ts +31 -31
  14. package/src/cli/commands/topology.ts +119 -0
  15. package/src/cli/index.ts +210 -199
  16. package/src/cli/templates/hooks.ts +75 -75
  17. package/src/cli/templates/rules.ts +38 -38
  18. package/src/cli/templates/skill.ts +69 -69
  19. package/src/core/boundary/evaluator.ts +232 -210
  20. package/src/core/config/loader.ts +97 -97
  21. package/src/core/config/schema.ts +39 -39
  22. package/src/core/database/client.ts +44 -44
  23. package/src/core/database/repositories/dependency.repository.ts +366 -349
  24. package/src/core/database/repositories/domain.repository.ts +218 -198
  25. package/src/core/database/repositories/environment.repository.ts +207 -0
  26. package/src/core/database/repositories/file.repository.ts +116 -106
  27. package/src/core/database/repositories/meta.repository.ts +33 -33
  28. package/src/core/database/repositories/symbol.repository.ts +443 -424
  29. package/src/core/database/repository.ts +264 -255
  30. package/src/core/database/schema.ts +34 -1
  31. package/src/core/discovery/topology-detector.ts +486 -486
  32. package/src/core/ingestion/hasher.ts +5 -5
  33. package/src/core/ingestion/pipeline.ts +584 -535
  34. package/src/core/parser/behavioral-analyzer.ts +119 -0
  35. package/src/core/parser/boundary-tracker.ts +288 -128
  36. package/src/core/parser/extractors/base.ts +62 -61
  37. package/src/core/parser/extractors/frontend.ts +194 -194
  38. package/src/core/parser/extractors/go.ts +229 -176
  39. package/src/core/parser/extractors/laravel-semantic.ts +1039 -585
  40. package/src/core/parser/extractors/mcp-cli-semantic.ts +199 -199
  41. package/src/core/parser/extractors/nestjs-semantic.ts +119 -119
  42. package/src/core/parser/extractors/php.ts +153 -149
  43. package/src/core/parser/extractors/python.ts +228 -226
  44. package/src/core/parser/extractors/registry.ts +70 -70
  45. package/src/core/parser/extractors/semantic-extractor.interface.ts +21 -21
  46. package/src/core/parser/extractors/typescript.ts +181 -177
  47. package/src/core/parser/schema/providers/laravel-migration-provider.ts +215 -0
  48. package/src/core/parser/schema/providers/prisma-schema-provider.ts +89 -0
  49. package/src/core/parser/schema/schema-provider-registry.ts +43 -0
  50. package/src/core/parser/schema/schema-provider.interface.ts +33 -0
  51. package/src/core/parser/tree-sitter.ts +41 -41
  52. package/src/core/resolver/call-graph-tracer.ts +666 -668
  53. package/src/core/resolver/module-resolver.ts +408 -342
  54. package/src/core/resolver/symbol-locator.ts +543 -543
  55. package/src/core/resolver/vertical-slice-tracer.ts +301 -252
  56. package/src/core/session/session-manager.ts +56 -56
  57. package/src/core/telemetry/telemetry.ts +86 -86
  58. package/src/core/topology/environment-detector.ts +860 -0
  59. package/src/core/topology/types.ts +83 -0
  60. package/src/index.ts +21 -18
  61. package/src/mcp/schemas.ts +578 -238
  62. package/src/mcp/server.ts +875 -656
  63. package/src/mcp/tools/check-boundary.ts +171 -152
  64. package/src/mcp/tools/get-domain-catalog.ts +145 -121
  65. package/src/mcp/tools/get-environment-topology.ts +141 -0
  66. package/src/mcp/tools/get-feature-context.ts +212 -116
  67. package/src/mcp/tools/get-symbol-hotspots.ts +60 -49
  68. package/src/mcp/tools/get-symbol-impact.ts +28 -26
  69. package/src/mcp/tools/get-symbol.ts +65 -63
  70. package/src/mcp/tools/locate-symbol.ts +171 -190
  71. package/src/mcp/tools/register-domain.ts +68 -64
  72. package/src/mcp/tools/register-feature.ts +100 -0
  73. package/src/mcp/tools/trace-vertical-slice.ts +74 -103
  74. package/src/types/index.ts +335 -299
@@ -1,255 +1,264 @@
1
- import type { Database } from "bun:sqlite";
2
- import type {
3
- ArchetypeKind,
4
- DomainCatalogResponse,
5
- DomainConfig,
6
- DomainRecord,
7
- ExtractedDependency,
8
- ExtractedSymbol,
9
- FileRecord,
10
- GetSymbolDetailsResponse,
11
- GetSymbolImpactResponse,
12
- InboundCaller,
13
- SymbolKind,
14
- SymbolRecord,
15
- VerticalSliceRecord,
16
- } from "../../types/index.ts";
17
-
18
- export type {
19
- ArchetypeKind,
20
- DomainCatalogResponse,
21
- DomainConfig,
22
- DomainRecord,
23
- ExtractedDependency,
24
- ExtractedSymbol,
25
- FileRecord,
26
- GetSymbolDetailsResponse,
27
- GetSymbolImpactResponse,
28
- InboundCaller,
29
- SymbolKind,
30
- SymbolRecord,
31
- VerticalSliceRecord,
32
- } from "../../types/index.ts";
33
- import { DependencyRepository } from "./repositories/dependency.repository.ts";
34
- import { DomainRepository } from "./repositories/domain.repository.ts";
35
- import { FileRepository } from "./repositories/file.repository.ts";
36
- import { MetaRepository } from "./repositories/meta.repository.ts";
37
- import { SymbolRepository } from "./repositories/symbol.repository.ts";
38
-
39
- export type DatabaseRepository = SeptumRepository;
40
-
41
- export class SeptumRepository {
42
- public readonly domains: DomainRepository;
43
- public readonly files: FileRepository;
44
- public readonly symbols: SymbolRepository;
45
- public readonly dependencies: DependencyRepository;
46
- public readonly meta: MetaRepository;
47
-
48
- constructor(private db: Database) {
49
- this.domains = new DomainRepository(db);
50
- this.files = new FileRepository(db);
51
- this.symbols = new SymbolRepository(db);
52
- this.dependencies = new DependencyRepository(db);
53
- this.meta = new MetaRepository(db);
54
- }
55
-
56
- public runInTransaction<T>(fn: () => T): T {
57
- return this.db.transaction(fn)();
58
- }
59
-
60
- // --- Domain Methods ---
61
- public upsertDomain(name: string, config: DomainConfig): number {
62
- return this.domains.upsertDomain(name, config);
63
- }
64
-
65
- public getDomainByName(name: string): DomainRecord | null {
66
- return this.domains.getDomainByName(name);
67
- }
68
-
69
- public getAllDomains(): DomainRecord[] {
70
- return this.domains.getAllDomains();
71
- }
72
-
73
- // --- File Methods ---
74
- public getFileByPath(path: string): FileRecord | null {
75
- return this.files.getFileByPath(path);
76
- }
77
-
78
- public countFiles(): number {
79
- return this.files.countFiles();
80
- }
81
-
82
- public getFilesByDomain(domainId: number): FileRecord[] {
83
- return this.files.getFilesByDomain(domainId);
84
- }
85
-
86
- public upsertFile(
87
- domainId: number,
88
- path: string,
89
- archetype: ArchetypeKind,
90
- contentHash: string,
91
- lineCount: number,
92
- mtimeMs: number = 0,
93
- sizeBytes: number = 0
94
- ): number {
95
- return this.files.upsertFile(
96
- domainId,
97
- path,
98
- archetype,
99
- contentHash,
100
- lineCount,
101
- mtimeMs,
102
- sizeBytes
103
- );
104
- }
105
-
106
- public updateFileMetadataOnly(id: number, mtimeMs: number, sizeBytes: number): void {
107
- this.files.updateFileMetadataOnly(id, mtimeMs, sizeBytes);
108
- }
109
-
110
- public deleteFilesNotInPaths(domainId: number, validPaths: string[]): number {
111
- return this.files.deleteFilesNotInPaths(domainId, validPaths);
112
- }
113
-
114
- public deleteFile(path: string): void {
115
- this.files.deleteFile(path);
116
- }
117
-
118
- public getDomainCatalog(
119
- domainName: string,
120
- archetypeFilter?: string
121
- ): DomainCatalogResponse | null {
122
- return this.domains.getDomainCatalog(domainName, archetypeFilter);
123
- }
124
-
125
- // --- Symbol Methods ---
126
- public replaceFileSymbols(fileId: number, symbols: ExtractedSymbol[]): void {
127
- this.symbols.replaceFileSymbols(fileId, symbols);
128
- }
129
-
130
- public getSymbolsByFileId(fileId: number): SymbolRecord[] {
131
- return this.symbols.getSymbolsByFileId(fileId);
132
- }
133
-
134
- public findSymbolsByName(name: string): Array<SymbolRecord & { file_path: string }> {
135
- return this.symbols.findSymbolsByName(name);
136
- }
137
-
138
- public findContainers(
139
- containerName: string
140
- ): Array<{ file: FileRecord; symbol?: SymbolRecord }> {
141
- return this.symbols.findContainers(containerName);
142
- }
143
-
144
- public getAllSymbolsWithFiles(): Array<SymbolRecord & { file_path: string }> {
145
- return this.symbols.getAllSymbolsWithFiles();
146
- }
147
-
148
- // --- Dependency & Slice Methods ---
149
- public replaceFileDependencies(fileId: number, deps: ExtractedDependency[]): void {
150
- this.dependencies.replaceFileDependencies(fileId, deps);
151
- }
152
-
153
- public upsertVerticalSlice(
154
- slice: Omit<VerticalSliceRecord, "id" | "created_at">
155
- ): void {
156
- this.dependencies.upsertVerticalSlice(slice);
157
- }
158
-
159
- public findVerticalSlices(searchTerm: string): VerticalSliceRecord[] {
160
- return this.dependencies.findVerticalSlices(searchTerm);
161
- }
162
-
163
- public getAllVerticalSlices(): VerticalSliceRecord[] {
164
- return this.dependencies.getAllVerticalSlices();
165
- }
166
-
167
- public clearVerticalSlices(domainId?: number): void {
168
- this.dependencies.clearVerticalSlices(domainId);
169
- }
170
-
171
- public getAllDependenciesWithDomains(): Array<{
172
- source_file: string;
173
- source_domain: string;
174
- line_number: number;
175
- target: string;
176
- statement: string;
177
- is_external: boolean;
178
- }> {
179
- return this.dependencies.getAllDependenciesWithDomains();
180
- }
181
-
182
- public findSymbolWithDomain(
183
- symbolName: string
184
- ): {
185
- symbol_name: string;
186
- kind: string;
187
- file_path: string;
188
- domain_name: string;
189
- } | null {
190
- return this.symbols.findSymbolWithDomain(symbolName);
191
- }
192
-
193
- public findSymbolWithMembers(symbolName: string): {
194
- symbol_name: string;
195
- kind: string;
196
- signature: string;
197
- file_path: string;
198
- domain_name: string;
199
- methods: string[];
200
- properties: string[];
201
- } | null {
202
- return this.symbols.findSymbolWithMembers(symbolName);
203
- }
204
-
205
- public getFileWithDomain(filePath: string): {
206
- file_id: number;
207
- file_path: string;
208
- domain_name: string;
209
- } | null {
210
- return this.symbols.getFileWithDomain(filePath);
211
- }
212
-
213
- public getHotspotSymbols(options: {
214
- minLines?: number;
215
- kind?: SymbolKind;
216
- domain?: string;
217
- limit?: number;
218
- } = {}): Array<SymbolRecord & { file_path: string; domain_name: string }> {
219
- return this.symbols.getHotspotSymbols(options);
220
- }
221
-
222
- public getSymbolDetails(
223
- symbolQuery: string,
224
- options: { domain?: string; includeDependencies?: boolean } = {}
225
- ): GetSymbolDetailsResponse | null {
226
- return this.symbols.getSymbolDetails(symbolQuery, options);
227
- }
228
-
229
- public getSymbolImpact(symbolName: string): GetSymbolImpactResponse {
230
- return this.dependencies.getSymbolImpact(symbolName);
231
- }
232
-
233
- public getFileInboundImpact(filePath: string): {
234
- direct_dependents_count: number;
235
- top_consumers: string[];
236
- symbols_count: number;
237
- risk_level: "low" | "medium" | "high";
238
- } {
239
- return this.dependencies.getFileInboundImpact(filePath);
240
- }
241
-
242
- // --- Metadata Methods ---
243
- public getMeta(key: string): string | null {
244
- return this.meta.getMeta(key);
245
- }
246
-
247
- public setMeta(key: string, value: string): void {
248
- this.meta.setMeta(key, value);
249
- }
250
-
251
- public getAllMeta(): Record<string, string> {
252
- return this.meta.getAllMeta();
253
- }
254
- }
255
-
1
+ import type { Database } from "bun:sqlite";
2
+ import type {
3
+ ArchetypeKind,
4
+ DomainCatalogResponse,
5
+ DomainConfig,
6
+ DomainRecord,
7
+ ExtractedDependency,
8
+ ExtractedSymbol,
9
+ FileRecord,
10
+ GetSymbolDetailsResponse,
11
+ GetSymbolImpactResponse,
12
+ InboundCaller,
13
+ SymbolKind,
14
+ SymbolRecord,
15
+ VerticalSliceRecord,
16
+ } from "../../types/index.ts";
17
+
18
+ export type {
19
+ ArchetypeKind,
20
+ DomainCatalogResponse,
21
+ DomainConfig,
22
+ DomainRecord,
23
+ ExtractedDependency,
24
+ ExtractedSymbol,
25
+ FileRecord,
26
+ GetSymbolDetailsResponse,
27
+ GetSymbolImpactResponse,
28
+ InboundCaller,
29
+ SymbolKind,
30
+ SymbolRecord,
31
+ VerticalSliceRecord,
32
+ } from "../../types/index.ts";
33
+ import { DependencyRepository } from "./repositories/dependency.repository.ts";
34
+ import { DomainRepository } from "./repositories/domain.repository.ts";
35
+ import { EnvironmentRepository } from "./repositories/environment.repository.ts";
36
+ import { FileRepository } from "./repositories/file.repository.ts";
37
+ import { MetaRepository } from "./repositories/meta.repository.ts";
38
+ import { SymbolRepository } from "./repositories/symbol.repository.ts";
39
+
40
+ export type DatabaseRepository = SeptumRepository;
41
+
42
+ export class SeptumRepository {
43
+ public readonly domains: DomainRepository;
44
+ public readonly files: FileRepository;
45
+ public readonly symbols: SymbolRepository;
46
+ public readonly dependencies: DependencyRepository;
47
+ public readonly meta: MetaRepository;
48
+ public readonly environment: EnvironmentRepository;
49
+
50
+ constructor(private db: Database) {
51
+ this.domains = new DomainRepository(db);
52
+ this.files = new FileRepository(db);
53
+ this.symbols = new SymbolRepository(db);
54
+ this.dependencies = new DependencyRepository(db);
55
+ this.meta = new MetaRepository(db);
56
+ this.environment = new EnvironmentRepository(db);
57
+ }
58
+
59
+ public runInTransaction<T>(fn: () => T): T {
60
+ return this.db.transaction(fn)();
61
+ }
62
+
63
+ // --- Domain Methods ---
64
+ public upsertDomain(name: string, config: DomainConfig): number {
65
+ return this.domains.upsertDomain(name, config);
66
+ }
67
+
68
+ public getDomainByName(name: string): DomainRecord | null {
69
+ return this.domains.getDomainByName(name);
70
+ }
71
+
72
+ public getAllDomains(): DomainRecord[] {
73
+ return this.domains.getAllDomains();
74
+ }
75
+
76
+ // --- File Methods ---
77
+ public getFileByPath(path: string): FileRecord | null {
78
+ return this.files.getFileByPath(path);
79
+ }
80
+
81
+ public countFiles(): number {
82
+ return this.files.countFiles();
83
+ }
84
+
85
+ public getFilesByDomain(domainId: number): FileRecord[] {
86
+ return this.files.getFilesByDomain(domainId);
87
+ }
88
+
89
+ public getAllFiles(): FileRecord[] {
90
+ return this.files.getAllFiles();
91
+ }
92
+
93
+ public upsertFile(
94
+ domainId: number,
95
+ path: string,
96
+ archetype: ArchetypeKind,
97
+ contentHash: string,
98
+ lineCount: number,
99
+ mtimeMs: number = 0,
100
+ sizeBytes: number = 0
101
+ ): number {
102
+ return this.files.upsertFile(
103
+ domainId,
104
+ path,
105
+ archetype,
106
+ contentHash,
107
+ lineCount,
108
+ mtimeMs,
109
+ sizeBytes
110
+ );
111
+ }
112
+
113
+ public updateFileMetadataOnly(id: number, mtimeMs: number, sizeBytes: number): void {
114
+ this.files.updateFileMetadataOnly(id, mtimeMs, sizeBytes);
115
+ }
116
+
117
+ public deleteFilesNotInPaths(domainId: number, validPaths: string[]): number {
118
+ return this.files.deleteFilesNotInPaths(domainId, validPaths);
119
+ }
120
+
121
+ public deleteFile(path: string): void {
122
+ this.files.deleteFile(path);
123
+ }
124
+
125
+ public getDomainCatalog(
126
+ domainName: string,
127
+ archetypeFilter?: string
128
+ ): DomainCatalogResponse | null {
129
+ return this.domains.getDomainCatalog(domainName, archetypeFilter);
130
+ }
131
+
132
+ // --- Symbol Methods ---
133
+ public replaceFileSymbols(fileId: number, symbols: ExtractedSymbol[]): void {
134
+ this.symbols.replaceFileSymbols(fileId, symbols);
135
+ }
136
+
137
+ public getSymbolsByFileId(fileId: number): SymbolRecord[] {
138
+ return this.symbols.getSymbolsByFileId(fileId);
139
+ }
140
+
141
+ public findSymbolsByName(name: string): Array<SymbolRecord & { file_path: string }> {
142
+ return this.symbols.findSymbolsByName(name);
143
+ }
144
+
145
+ public findContainers(
146
+ containerName: string
147
+ ): Array<{ file: FileRecord; symbol?: SymbolRecord }> {
148
+ return this.symbols.findContainers(containerName);
149
+ }
150
+
151
+ public getAllSymbolsWithFiles(): Array<SymbolRecord & { file_path: string }> {
152
+ return this.symbols.getAllSymbolsWithFiles();
153
+ }
154
+
155
+ // --- Dependency & Slice Methods ---
156
+ public replaceFileDependencies(fileId: number, deps: ExtractedDependency[]): void {
157
+ this.dependencies.replaceFileDependencies(fileId, deps);
158
+ }
159
+
160
+ public upsertVerticalSlice(
161
+ slice: Omit<VerticalSliceRecord, "id" | "created_at">
162
+ ): void {
163
+ this.dependencies.upsertVerticalSlice(slice);
164
+ }
165
+
166
+ public findVerticalSlices(searchTerm: string): VerticalSliceRecord[] {
167
+ return this.dependencies.findVerticalSlices(searchTerm);
168
+ }
169
+
170
+ public getAllVerticalSlices(): VerticalSliceRecord[] {
171
+ return this.dependencies.getAllVerticalSlices();
172
+ }
173
+
174
+ public clearVerticalSlices(domainId?: number): void {
175
+ this.dependencies.clearVerticalSlices(domainId);
176
+ }
177
+
178
+ public getAllDependenciesWithDomains(): Array<{
179
+ source_file: string;
180
+ source_domain: string;
181
+ line_number: number;
182
+ target: string;
183
+ statement: string;
184
+ is_external: boolean;
185
+ }> {
186
+ return this.dependencies.getAllDependenciesWithDomains();
187
+ }
188
+
189
+ public findSymbolWithDomain(
190
+ symbolName: string
191
+ ): {
192
+ symbol_name: string;
193
+ kind: string;
194
+ file_path: string;
195
+ domain_name: string;
196
+ } | null {
197
+ return this.symbols.findSymbolWithDomain(symbolName);
198
+ }
199
+
200
+ public findSymbolWithMembers(symbolName: string): {
201
+ symbol_name: string;
202
+ kind: string;
203
+ signature: string;
204
+ file_path: string;
205
+ domain_name: string;
206
+ methods: string[];
207
+ properties: string[];
208
+ } | null {
209
+ return this.symbols.findSymbolWithMembers(symbolName);
210
+ }
211
+
212
+ public getFileWithDomain(filePath: string): {
213
+ file_id: number;
214
+ file_path: string;
215
+ domain_name: string;
216
+ } | null {
217
+ return this.symbols.getFileWithDomain(filePath);
218
+ }
219
+
220
+ public getHotspotSymbols(options: {
221
+ minLines?: number;
222
+ minNesting?: number;
223
+ kind?: SymbolKind;
224
+ domain?: string;
225
+ limit?: number;
226
+ sortBy?: "lines" | "nesting" | "risk_score";
227
+ } = {}): Array<SymbolRecord & { file_path: string; domain_name: string; risk_score: number }> {
228
+ return this.symbols.getHotspotSymbols(options);
229
+ }
230
+
231
+ public getSymbolDetails(
232
+ symbolQuery: string,
233
+ options: { domain?: string; includeDependencies?: boolean } = {}
234
+ ): GetSymbolDetailsResponse | null {
235
+ return this.symbols.getSymbolDetails(symbolQuery, options);
236
+ }
237
+
238
+ public getSymbolImpact(symbolName: string): GetSymbolImpactResponse {
239
+ return this.dependencies.getSymbolImpact(symbolName);
240
+ }
241
+
242
+ public getFileInboundImpact(filePath: string): {
243
+ direct_dependents_count: number;
244
+ top_consumers: string[];
245
+ symbols_count: number;
246
+ risk_level: "low" | "medium" | "high";
247
+ } {
248
+ return this.dependencies.getFileInboundImpact(filePath);
249
+ }
250
+
251
+ // --- Metadata Methods ---
252
+ public getMeta(key: string): string | null {
253
+ return this.meta.getMeta(key);
254
+ }
255
+
256
+ public setMeta(key: string, value: string): void {
257
+ this.meta.setMeta(key, value);
258
+ }
259
+
260
+ public getAllMeta(): Record<string, string> {
261
+ return this.meta.getAllMeta();
262
+ }
263
+ }
264
+
@@ -1,6 +1,6 @@
1
1
  import type { Database } from "bun:sqlite";
2
2
 
3
- export const CURRENT_SCHEMA_VERSION = 2;
3
+ export const CURRENT_SCHEMA_VERSION = 4;
4
4
 
5
5
  export const TABLE_STATEMENTS = [
6
6
  `CREATE TABLE IF NOT EXISTS domains (
@@ -37,6 +37,7 @@ export const TABLE_STATEMENTS = [
37
37
  line_start INTEGER NOT NULL DEFAULT 0,
38
38
  line_end INTEGER NOT NULL DEFAULT 0,
39
39
  line_count INTEGER NOT NULL DEFAULT 1,
40
+ nesting_depth INTEGER NOT NULL DEFAULT 1,
40
41
  FOREIGN KEY (file_id) REFERENCES files(id) ON DELETE CASCADE
41
42
  );`,
42
43
 
@@ -73,6 +74,32 @@ export const TABLE_STATEMENTS = [
73
74
  value TEXT NOT NULL,
74
75
  updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
75
76
  );`,
77
+
78
+ `CREATE TABLE IF NOT EXISTS environment_topology (
79
+ layer TEXT PRIMARY KEY,
80
+ platform TEXT,
81
+ status TEXT NOT NULL,
82
+ detected_from_json TEXT NOT NULL DEFAULT '[]',
83
+ constraints_json TEXT NOT NULL DEFAULT '[]',
84
+ unresolved_inquiry TEXT,
85
+ updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
86
+ );`,
87
+
88
+ `CREATE TABLE IF NOT EXISTS environment_nodes (
89
+ id TEXT PRIMARY KEY,
90
+ layer TEXT NOT NULL,
91
+ name TEXT NOT NULL,
92
+ platform TEXT NOT NULL,
93
+ canonical_tag TEXT NOT NULL DEFAULT 'unspecified',
94
+ domain_or_ip TEXT,
95
+ role TEXT,
96
+ status TEXT NOT NULL,
97
+ detected_from_json TEXT NOT NULL DEFAULT '[]',
98
+ constraints_json TEXT NOT NULL DEFAULT '[]',
99
+ connected_to_json TEXT NOT NULL DEFAULT '[]',
100
+ unresolved_inquiry TEXT,
101
+ updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
102
+ );`,
76
103
  ];
77
104
 
78
105
  export const INDEX_STATEMENTS = [
@@ -83,14 +110,20 @@ export const INDEX_STATEMENTS = [
83
110
  "CREATE INDEX IF NOT EXISTS idx_symbols_name ON symbols(name);",
84
111
  "CREATE INDEX IF NOT EXISTS idx_symbols_kind ON symbols(kind);",
85
112
  "CREATE INDEX IF NOT EXISTS idx_symbols_line_count ON symbols(kind, line_count DESC);",
113
+ "CREATE INDEX IF NOT EXISTS idx_symbols_nesting_depth ON symbols(nesting_depth DESC);",
86
114
  "CREATE INDEX IF NOT EXISTS idx_dependencies_source ON dependencies(source_file_id);",
87
115
  "CREATE INDEX IF NOT EXISTS idx_dependencies_target ON dependencies(target_symbol_or_path);",
88
116
  "CREATE INDEX IF NOT EXISTS idx_slices_route_uri ON vertical_slices(route_uri);",
89
117
  "CREATE INDEX IF NOT EXISTS idx_slices_route_name ON vertical_slices(route_name);",
90
118
  "CREATE INDEX IF NOT EXISTS idx_slices_controller ON vertical_slices(controller_class, action_name);",
119
+ "CREATE INDEX IF NOT EXISTS idx_env_topology_status ON environment_topology(status);",
120
+ "CREATE INDEX IF NOT EXISTS idx_env_nodes_layer ON environment_nodes(layer);",
121
+ "CREATE INDEX IF NOT EXISTS idx_env_nodes_status ON environment_nodes(status);",
91
122
  ];
92
123
 
93
124
  const DROP_ALL_TABLES = `
125
+ DROP TABLE IF EXISTS environment_nodes;
126
+ DROP TABLE IF EXISTS environment_topology;
94
127
  DROP TABLE IF EXISTS repo_meta;
95
128
  DROP TABLE IF EXISTS vertical_slices;
96
129
  DROP TABLE IF EXISTS dependencies;