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
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **Deterministic Bounded-Context & Anti-Poisoning Architecture Guard for AI Coding Agents.**
4
4
 
5
- [![Version: 0.1.7](https://img.shields.io/badge/Version-0.1.7-blue)](package.json)
5
+ [![Version: 0.1.8](https://img.shields.io/badge/Version-0.1.8-blue)](package.json)
6
6
  [![Runtime: Bun](https://img.shields.io/badge/Runtime-Bun-black?logo=bun)](https://bun.sh)
7
7
  [![Protocol: Model Context Protocol](https://img.shields.io/badge/Protocol-MCP-green)](https://modelcontextprotocol.io/)
8
8
  [![Database: SQLite WAL](https://img.shields.io/badge/Database-SQLite%20(bun:sqlite)-003B57?logo=sqlite)](https://sqlite.org/)
@@ -28,16 +28,26 @@ bun add -g septum
28
28
 
29
29
  ### 1. Initialize in Any Project
30
30
 
31
+ Run `septum init` in your project root:
32
+
31
33
  ```bash
32
34
  septum init
33
35
  # or zero-install via bunx:
34
36
  bunx septum init
35
37
  ```
36
- *Auto-detects project topology (Monorepos, Laravel, Next.js, Go, NestJS), registers domains, and ingests AST symbols into `.septum/septum.db`.*
37
38
 
38
- ### 2. Connect to AI Agent (MCP Server)
39
+ Septum automatically:
40
+ 1. **Detects Architecture & Topology:** Discovers bounded domains across Monorepos, Laravel, Next.js, Go, NestJS, and more.
41
+ 2. **Builds AST Symbol SSOT:** Ingests symbols, interfaces, and dependencies into `.septum/septum.db`.
42
+ 3. **Scaffolds AI Agent Harnesses:** Interactively configures MCP servers, guardrail rules, and pre-write boundary hooks for your favorite agent environments:
43
+ - **Claude Code** (`.mcp.json`, `.claude/settings.json`)
44
+ - **Antigravity** (`.gemini/`)
45
+ - **Cursor** (`.cursor/mcp.json`, `.cursor/hooks.json`)
46
+ - **Opencode** (`opencode.json`)
47
+
48
+ ### 2. Manual MCP Client Configuration (Optional)
39
49
 
40
- Add Septum to your MCP client (`mcp.json` or `claude_desktop_config.json`):
50
+ If your MCP client is not configured via `septum init`, add Septum manually (`mcp.json` or `claude_desktop_config.json`):
41
51
 
42
52
  ```json
43
53
  {
@@ -57,15 +67,12 @@ Add Septum to your MCP client (`mcp.json` or `claude_desktop_config.json`):
57
67
 
58
68
  | Command | Description |
59
69
  |---|---|
60
- | `septum init` | Detect topology, scaffold boundary guards, and build initial catalog |
61
- | `septum ingest` | Full AST re-indexing into `.septum/septum.db` |
62
- | `septum sync` | Incremental synchronization of modified files for modified files |
63
- | `septum check --strict` | CI/CD gate: verify boundary integrity & fail on violations |
64
- | `septum query [domain]` | Inspect domain catalog, archetypes, and public signatures |
65
- | `septum locate <query>` | Locate symbol, class, interface, method, or error source |
66
- | `septum slice <route\|intent>` | Trace end-to-end vertical execution slice for route/intent |
67
- | `septum topology [action]` | Inspect 6-layer environment topology plane & distributed nodes |
68
- | `septum feature status\|clear` | Manage active feature lease and editing scope |
70
+ | `septum init [--force]` | Detect topology, scaffold boundary guards, and build initial catalog. `--force` regenerates Septum-owned hooks and harness artifacts while strictly preserving SQLite DB, manual domain policies, and user Git hooks |
71
+ | `septum sync [--json]` | AST synchronization and catalog update into `.septum/septum.db` (full or incremental) |
72
+ | `septum check [--strict] [--staged] [--feature <name>] [--json]` | CI/CD gate & pre-commit hook: verify boundary integrity & fail on cross-domain violations |
73
+ | `septum feature [status|clear] [--force]` | View or release active feature lease and editing scope (`--force` for other owner's session) |
74
+ | `septum hook [subhook]` | Internal pre-tool guardrail hook (e.g. pre-write, post-write) for AI agent tools |
75
+ | `septum topology [subcommand]` | Inspect 6-layer environment topology plane & distributed nodes (`env` alias available). Subcommands: `resolve <layer> <platform>`, `add-node`, `remove-node`, `clear` |
69
76
  | `septum serve` | Launch stdio MCP server for AI coding agents |
70
77
 
71
78
  ---
@@ -74,29 +81,22 @@ Add Septum to your MCP client (`mcp.json` or `claude_desktop_config.json`):
74
81
 
75
82
  All tools expose typed schemas automatically via the Model Context Protocol:
76
83
 
77
- - **Self-Aware Environment Topology (`septum_get_environment_topology`):** Maps and verifies the 6-layer production architecture (Edge/WAF, Gateway/Web Server, Host, Runtime, Storage/Cache, Telemetry) and distributed entities with cross-layer invariants.
78
- - **Whole-Project Telescope (`septum_get_domain_catalog`):** Returns macro architecture maps in < 400 tokens.
79
- - **Omni-Trigger Vertical Slice Tracer (`septum_trace_vertical_slice`):** Traces execution chains across HTTP routes, queue jobs, console commands, and event listeners (*Ingress ➔ Validation ➔ Orchestration ➔ Domain ➔ Egress*).
80
- - **Pre-Flight Boundary Guard (`septum_check_boundary`):** Validates proposed edits and imports against bounded-context rules.
81
- - **Scope Locking (`septum_get_feature_context` / `septum_clear_feature_context`):** Locks active feature scope to eliminate context drift.
82
- - **Symbol & Blast Radius (`septum_locate_symbol`, `septum_get_symbol`, `septum_get_symbol_impact`):** Resolves call chains, signatures, and refactoring impact.
83
- - **God Function & Nesting Detector (`septum_get_symbol_hotspots`):** Surfaces oversized functions/methods ranked by physical lines, cyclomatic nesting depth, and composite risk score.
84
- - **Dynamic Topology (`septum_register_domain`):** Registers or updates domains and boundary rules on-the-fly.
85
-
86
- ---
87
-
88
- ## Development & Contributing
89
-
90
- ```bash
91
- # Clone and install dependencies
92
- git clone https://github.com/shironim/septum.git
93
- cd septum
94
- bun install
95
-
96
- # Run test suite & build
97
- bun test
98
- bun run build
99
- ```
84
+ - **Domain Catalog, Registration & Environment Topology (`septum_domain`):**
85
+ - `action: "catalog"`: Whole-project macro architecture map and file connections in < 400 tokens (`detail_level: "compact" | "full"`).
86
+ - `action: "register"`: Dynamically registers or updates bounded-context domains with allowed/forbidden dependencies and layer archetypes.
87
+ - `action: "topology"`: Maps and verifies the 6-layer production architecture (Edge/WAF, Gateway/Web Server, Host, Runtime, Storage/Cache, Telemetry) and distributed nodes with cross-layer invariants.
88
+ - **Unified Symbol Engine (`septum_symbol`):**
89
+ - `action: "locate"`: Fast fuzzy search and error log resolution to pinpoint symbols across workspaces.
90
+ - `action: "inspect"`: Deep inspection of physical coordinates, declarations, and full typed signatures.
91
+ - `action: "impact"`: Refactoring blast radius, call graphs, and inbound/outbound dependency analysis.
92
+ - `action: "hotspots"`: God function and Single Responsibility Principle (SRP) detector ranked by physical lines, cyclomatic nesting depth, and composite risk score.
93
+ - **Omni-Trigger Vertical Slice Tracer (`septum_slice`):**
94
+ - Traces end-to-end execution flow (*Ingress ➔ Validation ➔ Controller ➔ Service ➔ Repository ➔ Entity*) from route URIs, controller actions, or high-level intent across HTTP routes, queue jobs, console commands, and events up to 8 levels deep.
95
+ - **Architecture Guard & Circular Dependency Gate (`septum_boundary`):**
96
+ - Validates proposed edits, additions, and imports against domain rules and feature touchpoints before files are modified on disk (`scope: "file"`).
97
+ - Audits staged files (`scope: "staged"`), domain boundaries (`scope: "domain"`), or the entire repository (`scope: "all"`) for cross-domain leaks and dependency cycles.
98
+ - **Active Touchpoint & Scope Lock Engine (`septum_feature`):**
99
+ - Locks active feature task context, touchpoints, and contracts (`action: "lock"` / `action: "get"` / `action: "release"`) via `.septum/session.json` to eliminate AI context drift and unintended edits.
100
100
 
101
101
  ---
102
102
 
@@ -104,22 +104,3 @@ bun run build
104
104
 
105
105
  [MIT](LICENSE) © shironim
106
106
 
107
- ## Reliability and Scope
108
-
109
- `septum check --strict` enables strict dependency rules before evaluating the codebase. A full check synchronizes the index first. CLI and MCP staged checks read Git index blobs, so unstaged edits cannot hide a violation in the proposed commit. Staged checks also evaluate dependency cycles using indexed dependencies with staged imports overlaid.
110
-
111
- Domain ownership uses the most specific normalized root in both full and single-file ingestion. Feature touchpoints are normalized against the workspace; `/*` permits immediate children and `/**` permits descendants.
112
-
113
- Each active MCP workspace has a watcher. Changes to multiple files are batched without dropping earlier paths; deletion and directory moves reconcile the catalog. If a native watcher is unavailable, Septum falls back to polling and synchronizes before answering queries. Catalog responses expose `index_status.watcher_mode` and `index_status.unsupported_files`. Single-file updates invalidate cached execution slices; the next trace rebuilds them.
114
-
115
- Tree-sitter grammars are runtime dependencies and are embedded in compiled executables. The active extractors cover TypeScript/JavaScript, PHP/Blade, Python, Go, and script extraction from Vue/Svelte/Astro. Rust, Java, C#, and Ruby do not yet have active extractors. Unsupported files are reported explicitly; an incomplete audit does not receive a clean approval. Unindexed symbols return `risk_level: "unknown"`.
116
-
117
- Feature sessions have a single owner per workspace. The default owner is the MCP process; set `SEPTUM_SESSION_ID` when several commands intentionally share the same owner. Another owner cannot replace or release the active session. Use `septum feature clear --force` for explicit recovery after a process exits or for a legacy session without ownership metadata.
118
-
119
- Run the real-server integration checks with Python 3:
120
-
121
- ```bash
122
- bun run test:integration
123
- ```
124
-
125
- These checks exercise live rule changes, Git staged blobs, multiple workspaces, rapid edits, directory moves, and unsupported-file diagnostics. The normal `bun test` suite includes a standalone-binary regression for forbidden multiline imports.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "septum",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Deterministic Bounded-Context, Structural File Catalog & Anti-Poisoning Partition for AI Agents",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -19,7 +19,8 @@
19
19
  "test": "bun test",
20
20
  "build": "bun build ./bin/septum.ts --compile --outfile dist/septum",
21
21
  "typecheck": "tsc --noEmit",
22
- "test:integration": "python3 tests/integration/mcp-reliability.py"
22
+ "test:integration": "python3 tests/integration/mcp-reliability.py",
23
+ "postinstall": "bun run scripts/postinstall.ts || true"
23
24
  },
24
25
  "dependencies": {
25
26
  "@modelcontextprotocol/sdk": "^1.5.0",
@@ -41,6 +41,8 @@ export async function handleCheckCommand(
41
41
  if (unsupported.length > 0) {
42
42
  throw new Error(`Cannot complete boundary audit: unsupported source files: ${unsupported.join(", ")}`);
43
43
  }
44
+ const skipped = JSON.parse(repo.getMeta("skipped_files") || "[]") as {path: string}[];
45
+ if (skipped.length) throw new Error(`Cannot complete boundary audit: files exceed resource limits: ${skipped.map(file => file.path).join(", ")}`);
44
46
  violations = evaluator.auditCodebase(config);
45
47
  }
46
48
 
@@ -7,8 +7,14 @@ import { SeptumRepository } from "../../core/database/repository.ts";
7
7
  import { ASTParserEngine } from "../../core/parser/tree-sitter.ts";
8
8
  import { SessionManager } from "../../core/session/session-manager.ts";
9
9
 
10
+ interface ToolCallInfo {
11
+ name?: string;
12
+ args?: Record<string, unknown>;
13
+ }
14
+
10
15
  export interface ToolPayload {
11
16
  tool_name?: string;
17
+ toolCall?: ToolCallInfo;
12
18
  tool_input?: {
13
19
  TargetFile?: string;
14
20
  file_path?: string;
@@ -30,8 +36,13 @@ export interface ToolPayload {
30
36
  CodeContent?: string;
31
37
  }
32
38
 
39
+ let configuredExitCode = 1;
40
+
33
41
  export async function handleHookCommand(args: string[]): Promise<void> {
34
42
  const subHook = args[1] || "pre-write";
43
+ if (args.includes("--exit-code-2") || args.includes("--claude") || args.includes("--cursor")) {
44
+ configuredExitCode = 2;
45
+ }
35
46
 
36
47
  if (subHook === "pre-write") {
37
48
  await runPreWriteHook();
@@ -40,6 +51,34 @@ export async function handleHookCommand(args: string[]): Promise<void> {
40
51
  }
41
52
  }
42
53
 
54
+ function blockHook(db: SeptumDatabase | null, reason: string): never {
55
+ if (db) {
56
+ try {
57
+ db.close();
58
+ } catch {
59
+ // ignore
60
+ }
61
+ }
62
+
63
+ // Print readable error to stderr for humans and Claude/Cursor/Codex
64
+ console.error(reason);
65
+
66
+ // Print JSON contract to stdout for Antigravity hook engine
67
+ try {
68
+ process.stdout.write(
69
+ JSON.stringify({
70
+ decision: "deny",
71
+ reason: reason.trim(),
72
+ }) + "\n"
73
+ );
74
+ } catch {
75
+ // ignore
76
+ }
77
+
78
+ // Exit code: 1 by default (Unix standard), or 2 if specified for Claude Code / Cursor hooks
79
+ process.exit(configuredExitCode);
80
+ }
81
+
43
82
  async function runPreWriteHook(): Promise<void> {
44
83
  // If .septum/septum.db does not exist, pass through
45
84
  const dbPath = path.resolve(process.cwd(), ".septum", "septum.db");
@@ -62,7 +101,11 @@ async function runPreWriteHook(): Promise<void> {
62
101
  }
63
102
 
64
103
  const toolInput: Record<string, any> =
65
- payload.tool_input || payload.arguments || (payload as Record<string, any>) || {};
104
+ payload.tool_input ||
105
+ payload.arguments ||
106
+ payload.toolCall?.args ||
107
+ (payload as Record<string, any>) ||
108
+ {};
66
109
  const targetFile: string | undefined =
67
110
  toolInput.TargetFile || toolInput.file_path || toolInput.filePath || toolInput.path;
68
111
  const chunkContent = Array.isArray(toolInput.ReplacementChunks)
@@ -115,15 +158,14 @@ async function runPreWriteHook(): Promise<void> {
115
158
  }
116
159
 
117
160
  if (!hasConsulted) {
118
- console.error(
161
+ blockHook(
162
+ db,
119
163
  `\n[SEPTUM GATE 3 VIOLATION - Mandatory Consultation Required]\n` +
120
164
  `✕ Operation blocked: You are attempting to write to domain '${sourceDomain}' (${targetFile}) ` +
121
165
  `without inspecting its authoritative symbol & file-connection catalog first.\n` +
122
- `▶ REQUIRED ACTION: Call tool 'septum_get_domain_catalog({ domain: "${sourceDomain}", detail_level: "compact" })' ` +
123
- `or 'septum_get_feature_context' before writing code.\n`
166
+ `▶ REQUIRED ACTION: Call tool 'septum_domain({ action: "catalog", domain: "${sourceDomain}", detail_level: "compact" })' ` +
167
+ `or 'septum_feature({ action: "get" })' before writing code.\n`
124
168
  );
125
- db.close();
126
- process.exit(1);
127
169
  }
128
170
  }
129
171
 
@@ -145,14 +187,13 @@ async function runPreWriteHook(): Promise<void> {
145
187
  );
146
188
 
147
189
  if (touchpointViolations.length > 0) {
148
- console.error(
190
+ blockHook(
191
+ db,
149
192
  `\n[SEPTUM GATE 1 VIOLATION - Scope Touchpoint Lock]\n` +
150
193
  `✕ Operation blocked: File '${targetFile}' is outside the declared allowed_touchpoints for feature '${activeFeatureKey}'.\n` +
151
194
  `▶ REASON: ${touchpointViolations[0].message}\n` +
152
195
  `▶ REQUIRED ACTION: Only modify files declared in allowed_touchpoints for this feature.\n`
153
196
  );
154
- db.close();
155
- process.exit(1);
156
197
  }
157
198
  }
158
199
 
@@ -176,7 +217,8 @@ async function runPreWriteHook(): Promise<void> {
176
217
 
177
218
  if (boundaryViolations.length > 0) {
178
219
  const v = boundaryViolations[0];
179
- console.error(
220
+ blockHook(
221
+ db,
180
222
  `\n[SEPTUM GATE 2 VIOLATION - Forbidden Cross-Domain Import]\n` +
181
223
  `✕ Operation blocked: Proposed code imports forbidden domain '${v.target_domain}' from '${v.source_domain}'.\n` +
182
224
  `▶ OFFENDING IMPORT: ${v.imported_target}\n` +
@@ -184,12 +226,17 @@ async function runPreWriteHook(): Promise<void> {
184
226
  `▶ MESSAGE: ${v.message}\n` +
185
227
  `▶ REQUIRED ACTION: Decouple this dependency. Use an authorized Interface, Event, or Shared Kernel.\n`
186
228
  );
187
- db.close();
188
- process.exit(1);
189
229
  }
190
230
  }
191
231
 
192
232
  db.close();
233
+
234
+ // If running in Antigravity or standard JSON IPC mode, emit allow decision
235
+ try {
236
+ process.stdout.write(JSON.stringify({ decision: "allow" }) + "\n");
237
+ } catch {
238
+ // ignore
239
+ }
193
240
  process.exit(0);
194
241
  } catch (err) {
195
242
  db.close();