septum 0.1.7 → 0.1.8

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 (59) hide show
  1. package/README.md +36 -55
  2. package/package.json +3 -2
  3. package/src/cli/commands/check.ts +2 -0
  4. package/src/cli/commands/hook.ts +59 -12
  5. package/src/cli/commands/init.ts +440 -121
  6. package/src/cli/commands/sync.ts +27 -17
  7. package/src/cli/commands/topology.ts +89 -47
  8. package/src/cli/index.ts +5 -67
  9. package/src/cli/scaffold/harness-config.ts +697 -0
  10. package/src/cli/templates/hooks.ts +6 -6
  11. package/src/cli/templates/rules.ts +8 -8
  12. package/src/cli/templates/skill.ts +11 -18
  13. package/src/cli/ui/prompts.ts +122 -0
  14. package/src/core/boundary/staged-auditor.ts +5 -2
  15. package/src/core/database/client.ts +8 -0
  16. package/src/core/database/repositories/dependency.repository.ts +77 -13
  17. package/src/core/database/repositories/domain.repository.ts +86 -33
  18. package/src/core/database/repositories/symbol.repository.ts +128 -117
  19. package/src/core/database/repository.ts +17 -5
  20. package/src/core/database/schema.ts +1 -1
  21. package/src/core/discovery/topology-detector.ts +71 -19
  22. package/src/core/ingestion/pipeline.ts +228 -94
  23. package/src/core/parser/extractors/laravel-semantic.ts +9 -8
  24. package/src/core/parser/extractors/mcp-cli-semantic.ts +56 -16
  25. package/src/core/parser/extractors/nestjs-semantic.ts +3 -2
  26. package/src/core/parser/schema/providers/laravel-migration-provider.ts +4 -3
  27. package/src/core/parser/schema/providers/prisma-schema-provider.ts +2 -1
  28. package/src/core/resolver/call-graph-tracer.ts +4 -3
  29. package/src/core/resolver/path-resolver.ts +57 -4
  30. package/src/core/resources/ignore.ts +35 -0
  31. package/src/core/resources/limits.ts +14 -0
  32. package/src/core/resources/source-files.ts +62 -0
  33. package/src/core/resources/work-queue.ts +74 -0
  34. package/src/core/session/session-manager.ts +19 -6
  35. package/src/core/telemetry/telemetry.ts +12 -1
  36. package/src/core/topology/environment-detector.ts +21 -11
  37. package/src/mcp/schemas.ts +381 -8
  38. package/src/mcp/server.ts +321 -535
  39. package/src/mcp/tools/boundary.ts +17 -0
  40. package/src/mcp/tools/check-boundary.ts +83 -11
  41. package/src/mcp/tools/domain.ts +40 -0
  42. package/src/mcp/tools/feature.ts +67 -0
  43. package/src/mcp/tools/get-domain-catalog.ts +9 -6
  44. package/src/mcp/tools/get-environment-topology.ts +2 -2
  45. package/src/mcp/tools/get-feature-context.ts +9 -12
  46. package/src/mcp/tools/get-symbol-impact.ts +5 -2
  47. package/src/mcp/tools/get-symbol.ts +2 -1
  48. package/src/mcp/tools/locate-symbol.ts +3 -3
  49. package/src/mcp/tools/register-domain.ts +25 -9
  50. package/src/mcp/tools/register-feature.ts +34 -17
  51. package/src/mcp/tools/slice.ts +15 -0
  52. package/src/mcp/tools/symbol.ts +82 -0
  53. package/src/mcp/workspace-manager.ts +159 -0
  54. package/src/mcp/workspace-watcher.ts +202 -0
  55. package/src/types/index.ts +1 -0
  56. package/src/cli/commands/ingest.ts +0 -29
  57. package/src/cli/commands/locate.ts +0 -61
  58. package/src/cli/commands/query.ts +0 -104
  59. package/src/cli/commands/slice.ts +0 -50
@@ -1,31 +1,41 @@
1
+ import * as path from "node:path";
1
2
  import { ConfigLoader } from "../../core/config/loader.ts";
2
3
  import { SeptumDatabase } from "../../core/database/client.ts";
3
4
  import { SeptumRepository } from "../../core/database/repository.ts";
4
5
  import { IngestionPipeline } from "../../core/ingestion/pipeline.ts";
6
+ import { resolveWorkspaceRoot } from "../../core/resolver/path-resolver.ts";
5
7
 
6
8
  export interface SyncCommandOptions {
7
9
  json?: boolean;
10
+ workspaceRoot?: string;
11
+ dbPath?: string;
8
12
  }
9
13
 
10
14
  export async function handleSyncCommand(options: SyncCommandOptions = {}): Promise<void> {
11
- const config = ConfigLoader.load();
12
- const db = new SeptumDatabase(config.settings.db_path);
13
- const repo = new SeptumRepository(db.raw);
14
- const pipeline = new IngestionPipeline(repo);
15
+ const root = options.workspaceRoot || resolveWorkspaceRoot();
16
+ const config = ConfigLoader.load(options.dbPath, root);
17
+ const resolvedDbPath = options.dbPath
18
+ ? (path.isAbsolute(options.dbPath) ? options.dbPath : path.join(root, options.dbPath))
19
+ : (path.isAbsolute(config.settings.db_path) ? config.settings.db_path : path.join(root, config.settings.db_path));
20
+ const db = new SeptumDatabase(resolvedDbPath);
21
+ try {
22
+ const repo = new SeptumRepository(db.raw);
23
+ const pipeline = new IngestionPipeline(repo, root);
15
24
 
16
- const metrics = await pipeline.run(config);
25
+ const metrics = await pipeline.run(config);
17
26
 
18
- if (options.json) {
19
- console.log(JSON.stringify(metrics, null, 2));
20
- } else {
21
- console.log(
22
- `[Septum Sync] Ingested in ${metrics.duration_ms.toFixed(0)}ms: ` +
23
- `${metrics.files_updated} updated/added, ` +
24
- `${metrics.files_skipped} unchanged, ` +
25
- `${metrics.symbols_indexed} symbols, ` +
26
- `${metrics.dependencies_indexed} deps.`
27
- );
27
+ if (options.json) {
28
+ console.log(JSON.stringify(metrics, null, 2));
29
+ } else {
30
+ console.log(
31
+ `[Septum Sync] Ingested in ${metrics.duration_ms.toFixed(0)}ms: ` +
32
+ `${metrics.files_updated} updated/added, ` +
33
+ `${metrics.files_skipped} unchanged, ` +
34
+ `${metrics.symbols_indexed} symbols, ` +
35
+ `${metrics.dependencies_indexed} deps.`
36
+ );
37
+ }
38
+ } finally {
39
+ db.close();
28
40
  }
29
-
30
- db.close();
31
41
  }
@@ -1,62 +1,103 @@
1
+ import { join } from "node:path";
1
2
  import { SeptumDatabase } from "../../core/database/client.ts";
2
3
  import { SeptumRepository } from "../../core/database/repository.ts";
3
4
  import { EnvironmentDetector } from "../../core/topology/environment-detector.ts";
4
5
  import type { EnvironmentLayer, TopologyNode } from "../../core/topology/types.ts";
5
6
 
7
+ const VALID_LAYERS = new Set<EnvironmentLayer>([
8
+ "edge",
9
+ "gateway",
10
+ "host",
11
+ "runtime",
12
+ "storage",
13
+ "telemetry",
14
+ ]);
15
+
6
16
  export async function handleTopologyCommand(
7
17
  subcommand?: string,
8
18
  arg1?: string,
9
19
  arg2?: string,
10
20
  arg3?: string,
11
- arg4?: string
21
+ arg4?: string,
22
+ workspaceRoot?: string
12
23
  ): Promise<void> {
13
- const cwd = process.cwd();
14
- const db = new SeptumDatabase();
15
- const repo = new SeptumRepository(db.raw);
24
+ const normalizedSub = subcommand?.trim().toLowerCase();
16
25
 
17
- if (subcommand === "resolve" && arg1 && arg2) {
18
- const layer = arg1.toLowerCase() as EnvironmentLayer;
19
- const platform = arg2;
20
- // Fix: Preserve existing constraints instead of overwriting with empty array
21
- const existing = repo.environment.getLayer(layer);
22
- repo.environment.saveLayer({
23
- layer,
24
- platform,
25
- canonical_tag: EnvironmentDetector.matchCanonicalTag(platform),
26
- status: "VERIFIED",
27
- detected_from: ["CLI Manual Resolution"],
28
- constraints: existing?.constraints && existing.constraints.length > 0 ? existing.constraints : [
29
- `Configured manually as '${platform}'.`
30
- ],
31
- });
32
- console.log(`[Septum Topology] Layer '${layer}' successfully verified as '${platform}' in SQLite SSOT.\n`);
33
- } else if (subcommand === "add-node" && arg1 && arg2 && arg3) {
34
- const nodeId = arg1;
35
- const layer = arg2.toLowerCase() as EnvironmentLayer;
36
- const platform = arg3;
37
- const domainOrIp = arg4;
26
+ if (normalizedSub && normalizedSub !== "resolve" && normalizedSub !== "add-node" && normalizedSub !== "remove-node" && normalizedSub !== "clear") {
27
+ throw new Error(`Unknown topology subcommand: '${subcommand}'. Valid subcommands: resolve, add-node, remove-node, clear.`);
28
+ }
38
29
 
39
- const node: TopologyNode = {
40
- id: nodeId,
41
- layer,
42
- name: nodeId,
43
- platform,
44
- canonical_tag: EnvironmentDetector.matchCanonicalTag(platform),
45
- domain_or_ip: domainOrIp,
46
- status: "VERIFIED",
47
- detected_from: ["CLI Manual Node Resolution"],
48
- constraints: [`Node added manually with platform '${platform}'.`],
49
- };
50
- repo.environment.saveNode(node);
51
- console.log(`[Septum Topology] Node '${nodeId}' (${layer.toUpperCase()}) added to distributed topology graph.\n`);
52
- } else if (subcommand === "remove-node" && arg1) {
53
- repo.environment.deleteNode(arg1);
54
- console.log(`[Septum Topology] Node '${arg1}' removed from distributed topology graph.\n`);
55
- } else if (subcommand === "clear") {
56
- repo.environment.clearAll();
57
- console.log("[Septum Topology] Cleared environment topology and nodes in SQLite SSOT.\n");
30
+ if (normalizedSub === "resolve") {
31
+ if (!arg1 || !arg2) {
32
+ throw new Error("Missing required arguments for 'topology resolve'. Usage: septum topology resolve <layer> <platform>");
33
+ }
34
+ const layerCandidate = arg1.trim().toLowerCase() as EnvironmentLayer;
35
+ if (!VALID_LAYERS.has(layerCandidate)) {
36
+ throw new Error(`Invalid environment layer '${arg1}'. Valid layers: ${Array.from(VALID_LAYERS).join(", ")}`);
37
+ }
38
+ } else if (normalizedSub === "add-node") {
39
+ if (!arg1 || !arg2 || !arg3) {
40
+ throw new Error("Missing required arguments for 'topology add-node'. Usage: septum topology add-node <id> <layer> <platform> [domain_or_ip]");
41
+ }
42
+ const layerCandidate = arg2.trim().toLowerCase() as EnvironmentLayer;
43
+ if (!VALID_LAYERS.has(layerCandidate)) {
44
+ throw new Error(`Invalid environment layer '${arg2}'. Valid layers: ${Array.from(VALID_LAYERS).join(", ")}`);
45
+ }
46
+ } else if (normalizedSub === "remove-node") {
47
+ if (!arg1) {
48
+ throw new Error("Missing required argument for 'topology remove-node'. Usage: septum topology remove-node <id>");
49
+ }
58
50
  }
59
51
 
52
+ const cwd = workspaceRoot || process.cwd();
53
+ const dbPath = workspaceRoot ? join(workspaceRoot, ".septum/septum.db") : undefined;
54
+ const db = new SeptumDatabase(dbPath);
55
+ const repo = new SeptumRepository(db.raw);
56
+
57
+ try {
58
+ if (normalizedSub === "resolve" && arg1 && arg2) {
59
+ const layer = arg1.trim().toLowerCase() as EnvironmentLayer;
60
+ const platform = arg2;
61
+ // Fix: Preserve existing constraints instead of overwriting with empty array
62
+ const existing = repo.environment.getLayer(layer);
63
+ repo.environment.saveLayer({
64
+ layer,
65
+ platform,
66
+ canonical_tag: EnvironmentDetector.matchCanonicalTag(platform),
67
+ status: "VERIFIED",
68
+ detected_from: ["CLI Manual Resolution"],
69
+ constraints: existing?.constraints && existing.constraints.length > 0 ? existing.constraints : [
70
+ `Configured manually as '${platform}'.`
71
+ ],
72
+ });
73
+ console.log(`[Septum Topology] Layer '${layer}' successfully verified as '${platform}' in SQLite SSOT.\n`);
74
+ } else if (normalizedSub === "add-node" && arg1 && arg2 && arg3) {
75
+ const nodeId = arg1;
76
+ const layer = arg2.trim().toLowerCase() as EnvironmentLayer;
77
+ const platform = arg3;
78
+ const domainOrIp = arg4;
79
+
80
+ const node: TopologyNode = {
81
+ id: nodeId,
82
+ layer,
83
+ name: nodeId,
84
+ platform,
85
+ canonical_tag: EnvironmentDetector.matchCanonicalTag(platform),
86
+ domain_or_ip: domainOrIp,
87
+ status: "VERIFIED",
88
+ detected_from: ["CLI Manual Node Resolution"],
89
+ constraints: [`Node added manually with platform '${platform}'.`],
90
+ };
91
+ repo.environment.saveNode(node);
92
+ console.log(`[Septum Topology] Node '${nodeId}' (${layer.toUpperCase()}) added to distributed topology graph.\n`);
93
+ } else if (normalizedSub === "remove-node" && arg1) {
94
+ repo.environment.deleteNode(arg1);
95
+ console.log(`[Septum Topology] Node '${arg1}' removed from distributed topology graph.\n`);
96
+ } else if (normalizedSub === "clear") {
97
+ repo.environment.clearAll();
98
+ console.log("[Septum Topology] Cleared environment topology and nodes in SQLite SSOT.\n");
99
+ }
100
+
60
101
  const topology = EnvironmentDetector.detect(cwd, repo);
61
102
 
62
103
  console.log("================================================================================");
@@ -113,7 +154,8 @@ export async function handleTopologyCommand(
113
154
  console.log(" septum topology add-node host:vps-worker host \"Ubuntu 24.04 (Dedicated Worker)\" 10.0.0.6");
114
155
  }
115
156
 
116
- console.log("================================================================================\n");
117
-
118
- db.close();
157
+ console.log("================================================================================\n");
158
+ } finally {
159
+ db.close();
160
+ }
119
161
  }
package/src/cli/index.ts CHANGED
@@ -3,13 +3,9 @@ import { SessionManager } from "../core/session/session-manager.ts";
3
3
  import { SEPTUM_VERSION } from "../version.ts";
4
4
  import { handleCheckCommand } from "./commands/check.ts";
5
5
  import { handleHookCommand } from "./commands/hook.ts";
6
- import { handleIngestCommand } from "./commands/ingest.ts";
7
6
  import { handleInitCommand } from "./commands/init.ts";
8
7
  import { handleTopologyCommand } from "./commands/topology.ts";
9
- import { handleLocateCommand } from "./commands/locate.ts";
10
- import { handleQueryCommand } from "./commands/query.ts";
11
8
  import { handleServeCommand } from "./commands/serve.ts";
12
- import { handleSliceCommand } from "./commands/slice.ts";
13
9
  import { handleSyncCommand } from "./commands/sync.ts";
14
10
 
15
11
  export async function runCLI(argv: string[]): Promise<void> {
@@ -22,13 +18,8 @@ export async function runCLI(argv: string[]): Promise<void> {
22
18
  version: { type: "boolean", short: "v" },
23
19
  force: { type: "boolean", short: "f" },
24
20
  json: { type: "boolean" },
25
- full: { type: "boolean" },
26
- file: { type: "string" },
27
21
  strict: { type: "boolean" },
28
22
  staged: { type: "boolean" },
29
- domain: { type: "string", short: "d" },
30
- "max-depth": { type: "string" },
31
- archetype: { type: "string", short: "a" },
32
23
  feature: { type: "string" },
33
24
  },
34
25
  allowPositionals: true,
@@ -61,55 +52,12 @@ export async function runCLI(argv: string[]): Promise<void> {
61
52
  break;
62
53
  }
63
54
 
64
- case "ingest": {
65
- await handleIngestCommand();
66
- break;
67
- }
68
-
69
55
  case "sync": {
70
56
  const json = Boolean(flags.json);
71
57
  await handleSyncCommand({ json });
72
58
  break;
73
59
  }
74
60
 
75
- case "query": {
76
- const domainName = positionals[1];
77
- const archetype = typeof flags.archetype === "string" ? flags.archetype : undefined;
78
- const jsonOutput = Boolean(flags.json);
79
- const full = Boolean(flags.full);
80
- const file = typeof flags.file === "string" ? flags.file : undefined;
81
- await handleQueryCommand(domainName, archetype, { json: jsonOutput, full, file });
82
- break;
83
- }
84
-
85
- case "locate": {
86
- const query = positionals[1];
87
- if (!query) {
88
- console.error("Usage: septum locate <symbol-or-error> [--domain <domain>] [--json]");
89
- process.exit(1);
90
- }
91
- const domain = typeof flags.domain === "string" ? flags.domain : undefined;
92
- const json = Boolean(flags.json);
93
- await handleLocateCommand(query, { domain, json });
94
- break;
95
- }
96
-
97
- case "slice": {
98
- const query = positionals[1];
99
- if (!query) {
100
- console.error("Usage: septum slice <route-or-intent> [-d|--max-depth <number>] [--json]");
101
- process.exit(1);
102
- }
103
- const json = Boolean(flags.json);
104
- const rawDepth = flags["max-depth"] ?? flags.domain;
105
- const parsedDepth = rawDepth !== undefined ? Number(rawDepth) : 5;
106
- const maxDepth = !Number.isNaN(parsedDepth)
107
- ? Math.min(Math.max(Math.trunc(parsedDepth), 1), 8)
108
- : 5;
109
- await handleSliceCommand(query, { json, maxDepth });
110
- break;
111
- }
112
-
113
61
  case "check": {
114
62
  const strict = Boolean(flags.strict);
115
63
  const staged = Boolean(flags.staged);
@@ -184,30 +132,21 @@ USAGE:
184
132
  septum [flags]
185
133
 
186
134
  COMMANDS:
187
- Catalog & Ingestion:
135
+ Core Lifecycle & Indexing:
188
136
  init Initialize configuration, gitignore, pre-commit hook, and catalog
189
- Flags: -f, --force
190
- ingest Full AST scan and synchronization to SQLite database
191
- sync Incremental fast synchronization of modified files
137
+ Flags: -f, --force (regenerate Septum-owned hooks & harness artifacts; preserves DB, domain policies, and user hooks)
138
+ sync Codebase AST synchronization and catalog update (full or incremental)
192
139
  Flags: --json
193
140
 
194
- Structural Discovery:
195
- query [domain] Query structural catalog for a domain or whole project
196
- Flags: -a, --archetype <name>, --full, --file <filter>, --json
197
- locate <query> Locate symbol, class, interface, method, or error source
198
- Flags: -d, --domain <name>, --json
199
- slice <route|intent> Trace end-to-end vertical execution slice for route/intent
200
- Flags: -d, --max-depth <number>, --json
201
-
202
141
  Boundary & Enforcement:
203
142
  check Audit codebase for cross-domain boundary violations
204
- Flags: --strict, --staged, --feature <name>
143
+ Flags: --strict, --staged, --feature <name>, --json
205
144
  feature [status|clear] View or release active feature context session lock
206
145
  Flags: --force (explicit recovery of another owner's session)
207
146
  hook [subhook] Internal pre-tool guardrail hook (e.g. pre-write)
208
147
 
209
148
  Environment & Topology:
210
- topology [action] Inspect 6-layer environment topology & distributed nodes
149
+ topology, env [action] Inspect 6-layer environment topology & distributed nodes
211
150
  Subcommands: resolve <layer> <platform>, add-node, remove-node, clear
212
151
 
213
152
  Daemon & Protocol:
@@ -216,6 +155,5 @@ COMMANDS:
216
155
  GLOBAL FLAGS:
217
156
  -h, --help Show this help message
218
157
  -v, --version Show current version
219
- --json Output formatted JSON metrics / results
220
158
  `);
221
159
  }