septum 0.1.5 → 0.1.6

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 (44) hide show
  1. package/package.json +1 -1
  2. package/src/cli/commands/hook.ts +36 -8
  3. package/src/cli/commands/init.ts +6 -4
  4. package/src/cli/commands/query.ts +45 -5
  5. package/src/cli/commands/slice.ts +4 -2
  6. package/src/cli/index.ts +15 -5
  7. package/src/cli/templates/hooks.ts +6 -6
  8. package/src/cli/templates/rules.ts +35 -23
  9. package/src/cli/templates/skill.ts +47 -51
  10. package/src/core/boundary/evaluator.ts +198 -1
  11. package/src/core/config/loader.ts +20 -0
  12. package/src/core/database/repositories/dependency.repository.ts +249 -63
  13. package/src/core/database/repositories/domain.repository.ts +96 -39
  14. package/src/core/database/repositories/file.repository.ts +20 -19
  15. package/src/core/database/repositories/symbol.repository.ts +44 -5
  16. package/src/core/database/repository.ts +19 -2
  17. package/src/core/database/schema.ts +3 -2
  18. package/src/core/ingestion/pipeline.ts +47 -25
  19. package/src/core/parser/boundary-tracker.ts +145 -0
  20. package/src/core/parser/extractors/frontend.ts +43 -90
  21. package/src/core/parser/extractors/go.ts +200 -21
  22. package/src/core/parser/extractors/laravel-semantic.ts +18 -12
  23. package/src/core/parser/extractors/mcp-cli-semantic.ts +173 -44
  24. package/src/core/parser/extractors/nestjs-semantic.ts +20 -5
  25. package/src/core/parser/extractors/php.ts +293 -31
  26. package/src/core/parser/extractors/python.ts +242 -10
  27. package/src/core/parser/extractors/typescript.ts +604 -117
  28. package/src/core/parser/wasm-loader.ts +271 -0
  29. package/src/core/resolver/call-graph-tracer.ts +49 -17
  30. package/src/core/resolver/module-resolver.ts +87 -16
  31. package/src/core/resolver/vertical-slice-tracer.ts +33 -11
  32. package/src/core/topology/environment-detector.ts +109 -6
  33. package/src/mcp/schemas.ts +146 -29
  34. package/src/mcp/server.ts +93 -41
  35. package/src/mcp/tools/check-boundary.ts +176 -40
  36. package/src/mcp/tools/get-domain-catalog.ts +24 -14
  37. package/src/mcp/tools/get-environment-topology.ts +3 -6
  38. package/src/mcp/tools/get-feature-context.ts +35 -20
  39. package/src/mcp/tools/get-symbol-hotspots.ts +4 -10
  40. package/src/mcp/tools/locate-symbol.ts +12 -14
  41. package/src/mcp/tools/register-domain.ts +3 -12
  42. package/src/mcp/tools/register-feature.ts +22 -31
  43. package/src/mcp/tools/trace-vertical-slice.ts +8 -8
  44. package/src/types/index.ts +36 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "septum",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
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",
@@ -8,14 +8,26 @@ import { ASTParserEngine } from "../../core/parser/tree-sitter.ts";
8
8
  import { SessionManager } from "../../core/session/session-manager.ts";
9
9
 
10
10
  export interface ToolPayload {
11
- tool_name: string;
12
- tool_input: {
11
+ tool_name?: string;
12
+ tool_input?: {
13
13
  TargetFile?: string;
14
14
  file_path?: string;
15
+ filePath?: string;
16
+ path?: string;
15
17
  ReplacementContent?: string;
16
18
  CodeContent?: string;
19
+ new_string?: string;
20
+ content?: string;
21
+ ReplacementChunks?: Array<{ ReplacementContent?: string }>;
17
22
  feature_key?: string;
18
23
  };
24
+ arguments?: Record<string, unknown>;
25
+ TargetFile?: string;
26
+ file_path?: string;
27
+ filePath?: string;
28
+ path?: string;
29
+ ReplacementContent?: string;
30
+ CodeContent?: string;
19
31
  }
20
32
 
21
33
  export async function handleHookCommand(args: string[]): Promise<void> {
@@ -49,9 +61,20 @@ async function runPreWriteHook(): Promise<void> {
49
61
  process.exit(0);
50
62
  }
51
63
 
52
- const toolInput = payload.tool_input || {};
53
- const targetFile = toolInput.TargetFile || toolInput.file_path;
54
- const content = toolInput.ReplacementContent || toolInput.CodeContent || "";
64
+ const toolInput: Record<string, any> =
65
+ payload.tool_input || payload.arguments || (payload as Record<string, any>) || {};
66
+ const targetFile: string | undefined =
67
+ toolInput.TargetFile || toolInput.file_path || toolInput.filePath || toolInput.path;
68
+ const chunkContent = Array.isArray(toolInput.ReplacementChunks)
69
+ ? toolInput.ReplacementChunks.map((c: any) => c?.ReplacementContent || "").join("\n")
70
+ : "";
71
+ const content: string =
72
+ toolInput.ReplacementContent ||
73
+ toolInput.CodeContent ||
74
+ toolInput.new_string ||
75
+ toolInput.content ||
76
+ chunkContent ||
77
+ "";
55
78
 
56
79
  if (!targetFile) {
57
80
  process.exit(0);
@@ -77,7 +100,12 @@ async function runPreWriteHook(): Promise<void> {
77
100
  if (fs.existsSync(accessLogPath)) {
78
101
  try {
79
102
  const rawAccess = JSON.parse(fs.readFileSync(accessLogPath, "utf-8"));
80
- const domainAccessedAt = rawAccess.domains?.[sourceDomain];
103
+ const domainsMap: Record<string, string> = rawAccess.domains || {};
104
+ const lowerSource = sourceDomain.toLowerCase();
105
+ const domainAccessedAt =
106
+ domainsMap[sourceDomain] ||
107
+ domainsMap[lowerSource] ||
108
+ Object.entries(domainsMap).find(([k]) => k.toLowerCase() === lowerSource)?.[1];
81
109
  if (domainAccessedAt) {
82
110
  hasConsulted = true;
83
111
  }
@@ -90,8 +118,8 @@ async function runPreWriteHook(): Promise<void> {
90
118
  console.error(
91
119
  `\n[SEPTUM GATE 3 VIOLATION - Mandatory Consultation Required]\n` +
92
120
  `✕ Operation blocked: You are attempting to write to domain '${sourceDomain}' (${targetFile}) ` +
93
- `without inspecting its authoritative catalog first.\n` +
94
- `▶ REQUIRED ACTION: Call tool 'septum_get_domain_catalog(domain: "${sourceDomain}")' ` +
121
+ `without inspecting its authoritative symbol & file-connection catalog first.\n` +
122
+ `▶ REQUIRED ACTION: Call tool 'septum_get_domain_catalog({ domain: "${sourceDomain}", detail_level: "compact" })' ` +
95
123
  `or 'septum_get_feature_context' before writing code.\n`
96
124
  );
97
125
  db.close();
@@ -9,20 +9,22 @@ import {
9
9
  import { SEPTUM_RULES_TEMPLATE } from "../templates/rules.ts";
10
10
  import { SEPTUM_MAP_SKILL_TEMPLATE } from "../templates/skill.ts";
11
11
  import { TopologyDetector } from "../../core/discovery/topology-detector.ts";
12
+ import { EnvironmentDetector } from "../../core/topology/environment-detector.ts";
12
13
  import { SeptumDatabase } from "../../core/database/client.ts";
13
14
  import { SeptumRepository } from "../../core/database/repository.ts";
14
15
 
15
16
  export async function handleInitCommand(force: boolean = false): Promise<void> {
16
- console.log("[Septum] Initializing Septum bounded-context environment (Zero-Config)...\n");
17
+ console.log("[Septum] Initializing Septum bounded-context & AST environment (Zero-Config SQLite SSOT)...\n");
17
18
 
18
19
  const cwd = process.cwd();
19
20
  const dbPath = ".septum/septum.db";
20
21
 
21
22
  // 1. Auto-discover project topology and persist to SQLite SSOT
22
- console.log(" • Analyzing codebase topology and modular boundaries...");
23
+ console.log(" • Analyzing codebase topology, modular boundaries, and 6-layer environment plane...");
23
24
  const db = new SeptumDatabase(dbPath);
24
25
  const repo = new SeptumRepository(db.raw);
25
26
  const domains = TopologyDetector.discoverAndPersist(repo, cwd);
27
+ EnvironmentDetector.detect(cwd, repo);
26
28
  const domainNames = Object.keys(domains);
27
29
  console.log(` ✓ Discovered and registered ${domainNames.length} domains directly in SQLite (${dbPath}):`);
28
30
  for (const name of domainNames) {
@@ -40,12 +42,12 @@ export async function handleInitCommand(force: boolean = false): Promise<void> {
40
42
  scaffoldAgentCustomizations(cwd);
41
43
 
42
44
  // 5. Run initial codebase ingestion
43
- console.log("\n[Septum] Running initial ingestion to build deterministic structural catalog...");
45
+ console.log("\n[Septum] Running initial Tree-Sitter WASM ingestion to build symbol & file-connection catalog...");
44
46
  try {
45
47
  await handleIngestCommand();
46
48
  console.log("\n✓ Septum successfully initialized and ready for production use!");
47
49
  console.log(" • Pre-commit hook is active (runs 'septum check --staged' before each commit).");
48
- console.log(" • AI Agent skill '/septum-map' and boundary hooks installed in '.agents/'.");
50
+ console.log(" • AI Agent skill '/septum-map', anti-duplication rules, and boundary hooks installed in '.agents/'.");
49
51
  console.log(" • MCP server is ready for AI coding agents via 'septum serve'.\n");
50
52
  } catch (err: unknown) {
51
53
  const message = err instanceof Error ? err.message : String(err);
@@ -1,8 +1,29 @@
1
1
  import { ConfigLoader } from "../../core/config/loader.ts";
2
2
  import { SeptumDatabase } from "../../core/database/client.ts";
3
3
  import { SeptumRepository } from "../../core/database/repository.ts";
4
+ import type { DomainCatalogResponse } from "../../types/index.ts";
5
+
6
+ export interface QueryCommandOptions {
7
+ json?: boolean;
8
+ full?: boolean;
9
+ file?: string;
10
+ }
11
+
12
+ export async function handleQueryCommand(
13
+ domainName?: string,
14
+ archetype?: string,
15
+ jsonOutputOrOptions?: boolean | QueryCommandOptions,
16
+ extraOptions?: QueryCommandOptions
17
+ ): Promise<void> {
18
+ const options: QueryCommandOptions =
19
+ typeof jsonOutputOrOptions === "boolean"
20
+ ? { json: jsonOutputOrOptions, ...extraOptions }
21
+ : { ...jsonOutputOrOptions, ...extraOptions };
22
+
23
+ const jsonOutput = Boolean(options.json);
24
+ const detailLevel: "compact" | "full" = options.full ? "full" : "compact";
25
+ const fileFilter = options.file;
4
26
 
5
- export async function handleQueryCommand(domainName?: string, archetype?: string, jsonOutput?: boolean): Promise<void> {
6
27
  const config = ConfigLoader.load();
7
28
  const db = new SeptumDatabase(config.settings.db_path);
8
29
  const repo = new SeptumRepository(db.raw);
@@ -23,7 +44,11 @@ export async function handleQueryCommand(domainName?: string, archetype?: string
23
44
  return;
24
45
  }
25
46
 
26
- const catalog = repo.getDomainCatalog(domainName, archetype);
47
+ const catalog: DomainCatalogResponse | null = (repo.getDomainCatalog as any)(
48
+ domainName,
49
+ archetype,
50
+ { detailLevel, fileFilter }
51
+ );
27
52
  if (!catalog) {
28
53
  console.error(`[Septum Error] Domain '${domainName}' not found in database. Run 'septum ingest' first.`);
29
54
  db.close();
@@ -36,15 +61,26 @@ export async function handleQueryCommand(domainName?: string, archetype?: string
36
61
  console.log(`=================================================`);
37
62
  console.log(` Domain: ${catalog.domain.toUpperCase()} (Root: ${catalog.root})`);
38
63
  console.log(`=================================================`);
64
+ console.log(` Detail Level: ${catalog.detail_level ?? detailLevel}`);
39
65
  console.log(` Allowed Dependencies: [${catalog.allowed_dependencies.join(", ")}]`);
40
66
  console.log(` Forbidden Dependencies: [${catalog.forbidden_dependencies.join(", ")}]`);
41
- console.log(` Total Files Cataloged: ${catalog.files.length}`);
67
+ console.log(` Total Files Cataloged: ${catalog.total_files ?? catalog.files.length} (Showing: ${catalog.showing_files ?? catalog.files.length})`);
42
68
  console.log(`-------------------------------------------------`);
43
69
 
44
70
  for (const file of catalog.files) {
45
- console.log(`\n File: ${file.path} [archetype: ${file.archetype}]`);
71
+ const lineInfo = file.line_count ? `, ${file.line_count} lines` : "";
72
+ console.log(`\n File: ${file.path} [archetype: ${file.archetype}${lineInfo}]`);
73
+ if (file.connections) {
74
+ const importsStr = file.connections.imports_from.length > 0 ? file.connections.imports_from.join(", ") : "none";
75
+ console.log(` ↔ Connections: imports [${importsStr}] | imported by ${file.connections.imported_by_count} file(s)`);
76
+ }
46
77
  for (const sym of file.symbols) {
47
- console.log(` • ${sym.kind.toUpperCase()} ${sym.name}`);
78
+ const spanStr = sym.line_span ? ` (L${sym.line_span})` : "";
79
+ const countsStr =
80
+ sym.methods_count !== undefined
81
+ ? ` [${sym.methods_count} methods${sym.properties_count ? `, ${sym.properties_count} props` : ""}]`
82
+ : "";
83
+ console.log(` • ${sym.kind.toUpperCase()} ${sym.name}${spanStr}${countsStr}`);
48
84
  if (sym.methods && sym.methods.length > 0) {
49
85
  for (const m of sym.methods) {
50
86
  console.log(` - ${m}`);
@@ -57,8 +93,12 @@ export async function handleQueryCommand(domainName?: string, archetype?: string
57
93
  }
58
94
  }
59
95
  }
96
+ if (catalog.agent_hint) {
97
+ console.log(`\n 💡 ${catalog.agent_hint}`);
98
+ }
60
99
  console.log(`\n=================================================`);
61
100
  }
62
101
 
63
102
  db.close();
64
103
  }
104
+
@@ -5,15 +5,16 @@ import { VerticalSliceTracer } from "../../core/resolver/vertical-slice-tracer.t
5
5
 
6
6
  export async function handleSliceCommand(
7
7
  query: string,
8
- options?: { json?: boolean }
8
+ options?: { json?: boolean; maxDepth?: number }
9
9
  ): Promise<void> {
10
10
  const config = ConfigLoader.load();
11
11
  const db = new SeptumDatabase(config.settings.db_path);
12
12
  const repo = new SeptumRepository(db.raw);
13
13
 
14
14
  try {
15
+ const maxDepth = Math.min(Math.max(Math.trunc(Number(options?.maxDepth ?? 5)), 1), 8);
15
16
  const tracer = new VerticalSliceTracer(repo);
16
- const result = tracer.trace(query);
17
+ const result = (tracer.trace as any)(query, maxDepth);
17
18
 
18
19
  if (options?.json) {
19
20
  console.log(JSON.stringify(result, null, 2));
@@ -46,3 +47,4 @@ export async function handleSliceCommand(
46
47
  db.close();
47
48
  }
48
49
  }
50
+
package/src/cli/index.ts CHANGED
@@ -22,9 +22,12 @@ export async function runCLI(argv: string[]): Promise<void> {
22
22
  version: { type: "boolean", short: "v" },
23
23
  force: { type: "boolean", short: "f" },
24
24
  json: { type: "boolean" },
25
+ full: { type: "boolean" },
26
+ file: { type: "string" },
25
27
  strict: { type: "boolean" },
26
28
  staged: { type: "boolean" },
27
29
  domain: { type: "string", short: "d" },
30
+ "max-depth": { type: "string" },
28
31
  archetype: { type: "string", short: "a" },
29
32
  feature: { type: "string" },
30
33
  },
@@ -73,7 +76,9 @@ export async function runCLI(argv: string[]): Promise<void> {
73
76
  const domainName = positionals[1];
74
77
  const archetype = typeof flags.archetype === "string" ? flags.archetype : undefined;
75
78
  const jsonOutput = Boolean(flags.json);
76
- await handleQueryCommand(domainName, archetype, jsonOutput);
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 });
77
82
  break;
78
83
  }
79
84
 
@@ -92,11 +97,16 @@ export async function runCLI(argv: string[]): Promise<void> {
92
97
  case "slice": {
93
98
  const query = positionals[1];
94
99
  if (!query) {
95
- console.error("Usage: septum slice <route-or-intent> [--json]");
100
+ console.error("Usage: septum slice <route-or-intent> [-d|--max-depth <number>] [--json]");
96
101
  process.exit(1);
97
102
  }
98
103
  const json = Boolean(flags.json);
99
- await handleSliceCommand(query, { 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 });
100
110
  break;
101
111
  }
102
112
 
@@ -183,11 +193,11 @@ COMMANDS:
183
193
 
184
194
  Structural Discovery:
185
195
  query [domain] Query structural catalog for a domain or whole project
186
- Flags: -a, --archetype <name>, --json
196
+ Flags: -a, --archetype <name>, --full, --file <filter>, --json
187
197
  locate <query> Locate symbol, class, interface, method, or error source
188
198
  Flags: -d, --domain <name>, --json
189
199
  slice <route|intent> Trace end-to-end vertical execution slice for route/intent
190
- Flags: --json
200
+ Flags: -d, --max-depth <number>, --json
191
201
 
192
202
  Boundary & Enforcement:
193
203
  check Audit codebase for cross-domain boundary violations
@@ -2,7 +2,7 @@ export const SEPTUM_HOOKS_CONFIG = {
2
2
  "septum-boundary-guard": {
3
3
  "PreToolUse": [
4
4
  {
5
- "matcher": "write_to_file|replace_file_content",
5
+ "matcher": "write_to_file|replace_file_content|multi_replace_file_content|Write|Edit|MultiEdit",
6
6
  "hooks": [
7
7
  {
8
8
  "type": "command",
@@ -14,7 +14,7 @@ export const SEPTUM_HOOKS_CONFIG = {
14
14
  ],
15
15
  "PostToolUse": [
16
16
  {
17
- "matcher": "write_to_file|replace_file_content",
17
+ "matcher": "write_to_file|replace_file_content|multi_replace_file_content|Write|Edit|MultiEdit",
18
18
  "hooks": [
19
19
  {
20
20
  "type": "command",
@@ -61,13 +61,13 @@ fi
61
61
 
62
62
  # Trigger background incremental sync
63
63
  if command -v bun >/dev/null 2>&1 && [ -f "$ROOT_DIR/bin/septum.ts" ]; then
64
- bun run "$ROOT_DIR/bin/septum.ts" sync --json >/dev/null 2>&1 &
64
+ bun run "$ROOT_DIR/bin/septum.ts" sync >/dev/null 2>&1 &
65
65
  elif command -v septum >/dev/null 2>&1; then
66
- septum sync --json >/dev/null 2>&1 &
66
+ septum sync >/dev/null 2>&1 &
67
67
  elif [ -f "$ROOT_DIR/node_modules/.bin/septum" ]; then
68
- "$ROOT_DIR/node_modules/.bin/septum" sync --json >/dev/null 2>&1 &
68
+ "$ROOT_DIR/node_modules/.bin/septum" sync >/dev/null 2>&1 &
69
69
  elif command -v bunx >/dev/null 2>&1; then
70
- bunx septum sync --json >/dev/null 2>&1 &
70
+ bunx septum sync >/dev/null 2>&1 &
71
71
  fi
72
72
 
73
73
  exit 0
@@ -1,38 +1,50 @@
1
- export const SEPTUM_RULES_TEMPLATE = `# Septum Bounded-Context & Anti-Poisoning Partition Rules
1
+ export const SEPTUM_RULES_TEMPLATE = `# Septum Bounded-Context, Anti-Duplication & File Connectivity Rules
2
2
 
3
- > **Prinsip Utama:** Proyek ini menggunakan **Septum** untuk menegakkan batasan arsitektur (bounded-context) secara deterministik. Setiap AI Coding Agent wajib mematuhi aturan batas domain dan touchpoint berikut.
3
+ > **Prinsip Utama:** Proyek ini menggunakan **Septum** (\`.septum/septum.db\`) sebagai Single Source of Truth (SSOT) untuk memetakan seluruh class, fungsi, method, struct/interface, dan variabel/konstanta beserta keterhubungan antar-file. Setiap AI Coding Agent **dilarang membuat simbol duplikat** dan wajib mematuhi batas domain.
4
4
 
5
5
  ---
6
6
 
7
- ## 1. Single Source of Truth (SSOT) via Septum MCP
8
-
9
- Sebelum menulis atau mengedit file backend/domain:
10
- 1. **Dilarang Menebak Kontrak Domain:**
11
- Gunakan tool MCP \`septum_get_domain_catalog(domain: "...")\` untuk memeriksa file, arketipe, dan signature publik yang sah di dalam domain tersebut.
12
- 2. **Kunci Scope pada Fitur Aktif:**
13
- Jika sedang mengerjakan fitur spesifik yang terdaftar di katalog Septum, panggil \`septum_get_feature_context(feature: "...")\`.
14
- * **Wajib patuhi \`allowed_touchpoints\`:** Jangan menyentuh atau memodifikasi file di luar daftar yang diizinkan untuk fitur tersebut.
15
- * **Wajib gunakan ulang \`reuse_symbols\`:** Jangan membuat fungsi atau helper duplikat jika simbol tersebut sudah terdaftar di \`reuse_symbols\`.
7
+ ## 1. Anti-Duplikasi Simbol & Peta Keterhubungan File (Wajib Sebelum Coding)
8
+
9
+ Sebelum membuat class, fungsi, method, tipe, atau variabel/konstanta baru di file backend:
10
+ 1. **Periksa Peta Domain & Koneksi File (Compact Mode < 400 Token):**
11
+ Panggil \`septum_get_domain_catalog({ domain: "<nama_domain>", detail_level: "compact" })\` (atau tanpa \`domain\` untuk *Macro Semantic Map*).
12
+ * Perhatikan daftar simbol eksisting (\`class\`, \`interface\`, \`struct\`, \`function\`, \`type\`, \`constant\`, \`variable\`) beserta \`line_span\`-nya.
13
+ * Perhatikan \`connections.imports_from\` (file mana saja yang diimpor oleh file tersebut) dan \`connections.imported_by_count\` (berapa file lain yang bergantung padanya).
14
+ * Jika membutuhkan daftar signature method lengkap pada satu file, panggil \`septum_get_symbol({ symbol: "<NamaSimbol>" })\` atau \`septum_get_domain_catalog({ domain: "<nama_domain>", detail_level: "full", file_filter: "<nama_file>" })\`.
15
+ 2. **Cari Simbol Lintas-Domain Sebelum Membuat Baru:**
16
+ Panggil \`septum_locate_symbol({ query: "<kata_kunci>" })\` untuk memastikan fungsi/helper/class yang ingin dibuat belum ada di codebase.
17
+ 3. **Kunci Scope pada Fitur Aktif:**
18
+ Jika mengerjakan fitur terdaftar, panggil \`septum_get_feature_context({ feature_key: "<nama_fitur>" })\`:
19
+ * **Patuhi \`allowed_touchpoints\`:** Jangan memodifikasi file di luar daftar touchpoint fitur aktif.
20
+ * **Gunakan ulang \`reuse_symbols\`:** Wajib mengimpor dan memakai kembali simbol yang terdaftar di \`reuse_symbols\`.
16
21
 
17
22
  ---
18
23
 
19
- ## 2. Pre-Flight Boundary Check Sebelum Menulis Kode
24
+ ## 2. Audit Blast Radius & Alur Eksekusi Sebelum Refactoring
20
25
 
21
- Sebelum mengeksekusi penulisan file (\`write_to_file\` atau \`replace_file_content\`):
22
- 1. Panggil tool MCP:
26
+ 1. **Cek Dampak Simbol (\`inbound_callers\`):**
27
+ Sebelum mengubah parameter/return signature atau menghapus class/fungsi/method publik, wajib panggil:
23
28
  \`\`\`json
24
- septum_check_boundary({
25
- "file_path": "path/ke/file.ts",
26
- "proposed_imports": ["target_import_statement"],
27
- "feature_key": "nama_fitur_opsional"
28
- })
29
+ septum_get_symbol_impact({ "symbol": "NamaClassAtauFungsi" })
29
30
  \`\`\`
30
- 2. **Rejection Handling:** Jika Septum mengembalikan status \`rejected\` (\`forbidden_dependency\`, \`disallowed_dependency\`, atau \`touchpoint_violation\`), **BATALKAN** rencana penulisan tersebut dan cari rute arsitektur yang sah (misal melalui Interface/Shared-Kernel yang diizinkan).
31
+ Periksa seluruh \`inbound_callers\` (termasuk *named imports* lintas file) agar tidak memutus kontrak file pemanggil.
32
+ 2. **Telusuri Vertical Slice (Default Depth 5, Max Depth 8):**
33
+ Gunakan \`septum_trace_vertical_slice({ query: "<route|command|handler>", max_depth: 5 })\` (naikkan hingga \`max_depth: 8\` untuk alur Event/Job/Queue berlapis) guna memahami rantai eksekusi dari Ingress hingga Repository/Entity.
31
34
 
32
35
  ---
33
36
 
34
- ## 3. Anti Local Scope Myopia
37
+ ## 3. Pre-Flight Boundary & Circular Dependency Check
35
38
 
36
- * Dilarang menghapus fungsi publik atau mengubah signature class hanya karena fungsi tersebut tidak terlihat dipanggil di file lokal yang sedang diedit.
37
- * Pastikan seluruh dependensi inbound/outbound mematuhi batasan domain yang terdaftar di database Septum (\`.septum/septum.db\`).
39
+ 1. **Sebelum Menulis Import Lintas-Domain (\`write_to_file\` / \`replace_file_content\`):**
40
+ \`\`\`json
41
+ septum_check_boundary({
42
+ "file_path": "path/ke/file.ts",
43
+ "proposed_imports": ["../other-domain/service"],
44
+ "feature_key": "opsional_feature_key"
45
+ })
46
+ \`\`\`
47
+ 2. **Audit Menyeluruh & Deteksi Siklus (\`circular_dependency\`):**
48
+ Jalankan \`septum_check_boundary({ scope: "staged" })\` atau \`septum_check_boundary({ scope: "all" })\` setelah menyelesaikan perubahan multi-file. Jika status \`rejected\` (\`forbidden_dependency\`, \`disallowed_dependency\`, \`touchpoint_violation\`, atau \`circular_dependency\`), batalkan/perbaiki arsitektur import sebelum melakukan commit.
38
49
  `;
50
+
@@ -1,69 +1,65 @@
1
1
  export const SEPTUM_MAP_SKILL_TEMPLATE = `---
2
2
  name: septum-map
3
- description: Framework-agnostic codebase discovery, architectural domain mapping, and bounded-context initialization for Septum. Uses AI reasoning to map unknown project topologies (JS/TS, PHP, Python, Go), auto-registers bounded contexts into Septum's SQLite catalog, and enforces deterministic architectural boundaries.
3
+ description: Framework-agnostic codebase discovery, multi-language AST symbol & file-connection mapping, and bounded-context governance for Septum. Uses Tree-Sitter WASM (TS/JS/TSX, PHP, Python, Go, Rust, Java, C#, Ruby + Vue/Svelte/Astro/Blade) and SQLite SSOT (.septum/septum.db) to prevent symbol duplication, map file integrations, and enforce architectural boundaries.
4
4
  ---
5
5
 
6
- # \`septum-map\` — Framework-Agnostic Semantic Discovery & Bounded-Context Initialization
6
+ # \`septum-map\` — Multi-Language AST Discovery, File Connectivity & Bounded-Context Governance
7
7
 
8
- > **Prinsip Utama:** AI Agent berperan sebagai *The Architect* untuk membedah topologi arsitektur proyek apa pun tanpa terikat pada framework tertentu, merumuskan batas bounded-context, dan mendaftarkannya langsung ke database deterministik (.septum/septum.db via septum_register_domain) agar AI coding berikutnya tidak mengalami context poisoning atau over-editing.
8
+ > **Prinsip Utama:** Septum memetakan setiap fungsi, class, method, struct/interface, dan variabel/konstanta di file backend beserta keterhubungan dua arah antar-file (\`imports_from\` & \`imported_by\`) ke dalam SQLite SSOT (\`.septum/septum.db\`). Dengan peta deterministik ini, AI Agent **tidak boleh menduplikasi simbol yang sudah ada** dan wajib menjaga integritas batas domain (*bounded-context*) serta mencegah *circular dependency*.
9
9
 
10
10
  ---
11
11
 
12
- ## 1. Landasan Riset & Filosofi Desain
12
+ ## 1. Landasan Arsitektur & Pencegahan Duplikasi
13
13
 
14
- Skill ini berakar langsung pada riset rekayasa perangkat lunak terkemuka:
15
- 1. **Software Reflexion Models (Murphy, Notkin, & Sullivan, IEEE TSE):**
16
- Membedakan model arsitektur tingkat tinggi yang dirancang (*high-level intention*) dengan implementasi fisik di kode sumber. Septum mendeteksi *Divergences* (pelanggaran baru) dan *Absences* sebelum kode di-merge.
17
- 2. **Eliminasi Over-Editing (SWE-bench, RepoCoder - NeurIPS / ICLR):**
18
- Akar kegagalan agen AI terbesar adalah mengedit file di luar lokus tugas (*local scope myopia*). \`septum-map\` menetapkan *bounded context* dan *allowed touchpoints* sejak awal.
19
- 3. **Principle of Least Privilege & Object-Capabilities (Miller):**
20
- Agen hanya diberikan kapabilitas membaca dan mengubah file dalam domain/fitur aktif, memangkas *blast radius* kesalahan hingga mendekati nol.
21
- 4. **Hybrid Defense (SynCode / NeMo Guardrails):**
22
- Probabilistic AI digunakan untuk penalaran awal (*discovery & blueprinting*), sementara eksekusi dan penegakannya 100% deterministik (*Tree-sitter WASM, SQLite WAL, Pre-Commit Hooks*).
14
+ 1. **Anti-Symbol Duplication (Peta Simbol & Keterhubungan File):**
15
+ Setiap file yang diindeks oleh mesin \`web-tree-sitter\` Septum memiliki daftar simbol terstruktur (\`class\`, \`interface\`, \`struct\`, \`trait\`, \`enum\`, \`function\`, \`method\`, \`type\`, \`constant\`, \`variable\`) serta graf koneksi dua arah (\`connections.imports_from\` dan \`connections.imported_by_count\`). Agen wajib memeriksa peta ini sebelum membuat fungsi, class, atau variabel baru.
16
+ 2. **Software Reflexion Models & Boundary Enforcement:**
17
+ Septum memvalidasi rencana perubahan kode terhadap aturan \`allowed_dependencies\`, \`forbidden_dependencies\`, \`allowed_touchpoints\`, dan mendeteksi siklus dependensi (\`circular_dependency\`) baik per-file maupun lintas-domain.
18
+ 3. **Token-Budgeted Context (< 400 Tokens Default):**
19
+ Katalog domain secara default disajikan dalam mode ringkas (\`detail_level: "compact"\`) agar agen memperoleh topologi file, rentang baris (\`line_span\`), jumlah method/property, dan koneksi antar-file tanpa membanjiri jendela konteks.
23
20
 
24
21
  ---
25
22
 
26
- ## 2. Kapan Wajib Menggunakan (Trigger Moments)
23
+ ## 2. Referensi Cepat 12 Tool MCP Septum (Standardized \`snake_case\` Contracts)
24
+
25
+ | Tool MCP | Parameter Utama (\`snake_case\`) | Fungsi & Kapan Digunakan |
26
+ |---|---|---|
27
+ | **\`septum_get_domain_catalog\`** | \`{ domain?, detail_level?: "compact"\\|"full", archetype_filter?, file_filter? }\` | Tanpa \`domain\`: menampilkan *Macro Semantic Map* seluruh proyek. Dengan \`domain\`: menampilkan daftar file, \`connections\` (\`imports_from\`, \`imported_by_count\`), dan simbol di domain tersebut (\`compact\` default < 400 token). |
28
+ | **\`septum_locate_symbol\`** | \`{ query, domain?, limit?: 10 }\` | Mencari lokasi file dan baris (\`line_start\`-\`line_end\`) dari class, fungsi, method (\`Class::method\`), struct, atau konstanta. |
29
+ | **\`septum_get_symbol\`** | \`{ symbol, domain?, include_dependencies?: true }\` | Mengekstrak detail kontrak simbol: signature, \`exact_range\`, \`dependencies_injected\`, \`outbound_calls\`, \`sibling_methods\`, dan \`connected_files\`. |
30
+ | **\`septum_get_symbol_impact\`** | \`{ symbol }\` | Menghitung *blast radius* (\`inbound_callers\`, \`total_dependents\`, \`risk_level\`) termasuk pelacakan *named imports* lintas file sebelum mengubah signature. |
31
+ | **\`septum_trace_vertical_slice\`** | \`{ query, max_depth?: 5 }\` | Menelusuri alur eksekusi end-to-end (\`Ingress ➔ Validation ➔ Controller ➔ Service ➔ Repository ➔ Entity\`). \`max_depth\` default \`5\`, rentang \`1..8\` (gunakan \`6..8\` untuk deep trace Event/Job/Queue). |
32
+ | **\`septum_check_boundary\`** | \`{ file_path?, file_paths?, proposed_imports?, feature_key?, scope?: "file"\\|"all"\\|"staged"\\|"domain", domain? }\` | **Pre-Write:** memvalidasi \`proposed_imports\` pada \`file_path\`. **Macro Audit:** panggil dengan \`{ scope: "all" }\` atau \`{ scope: "staged" }\` untuk mengaudit seluruh batas domain & *circular dependencies*. |
33
+ | **\`septum_get_symbol_hotspots\`** | \`{ domain?, min_lines?: 30, min_nesting?, kind?, limit?: 30, sort_by?: "risk_score" }\` | Mengidentifikasi fungsi/class paling kompleks berdasarkan \`risk_score\` (\`line_count\` $\\times$ \`nesting_depth\`). |
34
+ | **\`septum_get_feature_context\`** | \`{ feature_key? }\` | Mengambil konteks fitur aktif (\`allowed_touchpoints\`, \`reuse_symbols\`, input/output contract). |
35
+ | **\`septum_clear_feature_context\`** | \`{}\` | Melepaskan kunci sesi fitur aktif di \`.septum/session.json\`. |
36
+ | **\`septum_register_domain\`** | \`{ domain, root, description?, allowed_dependencies?, forbidden_dependencies?, archetypes?, ingest_now?: true }\` | Mendaftarkan atau memperbarui bounded-context domain langsung ke SQLite SSOT (\`.septum/septum.db\`). |
37
+ | **\`septum_register_feature\`** | \`{ feature_key, domain, description?, allowed_touchpoints?, reuse_symbols?, input_contract?, output_contract? }\` | Mendaftarkan kontrak fitur baru ke SQLite SSOT dan mengaktifkan sesi *touchpoint lock*. |
38
+ | **\`septum_get_environment_topology\`** | \`{ resolve?, resolveNode?, refresh? }\` | Memetakan 6-layer topologi infrastruktur (\`EDGE\`, \`GATEWAY\`, \`HOST\`, \`RUNTIME\`, \`STORAGE\`, \`TELEMETRY\`) beserta invarian lintas-layer. |
39
+
40
+ ---
41
+
42
+ ## 3. Alur Kerja Pemetaan & Inisialisasi Domain (The 4-Step Lifecycle)
27
43
 
28
44
  > [!NOTE] Zero-Config Default (\`septum init\`)
29
- > Untuk mayoritas proyek (library kecil/menengah, layered monolith standar, MVC, CLI, MCP tools), pengguna atau agen **cukup menjalankan \`septum init\`** di terminal. Perintah \`septum init\` secara default berjalan 100% otomatis tanpa wawancara manual (zero-config heuristic auto-detect & auto-ingest).
45
+ > Menjalankan \`septum init\` di terminal secara otomatis mendeteksi bahasa & framework (TS/JS, PHP/Laravel, Python, Go, Rust, Java, C#, Ruby), mendaftarkan domain ke \`.septum/septum.db\`, mengindeks AST via Tree-Sitter WASM, dan memasang hook di \`.agents/\`.
30
46
 
31
- Gunakan alur 4 langkah skill ini HANYA saat:
32
- 1. Memetakan domain bisnis kustom / modular DDD enterprise yang kompleks di mana batasan dependency non-standar perlu disepakati bersama Tech Lead.
33
- 2. Memetakan ulang domain bisnis setelah terjadi refactoring arsitektur besar (*re-mapping*).
34
- 3. Mengonfigurasi sesi fitur baru (\`features\` session) untuk mengunci daftar file yang boleh dimodifikasi (*allowed_touchpoints*) dan simbol yang wajib dipakai ulang (*reuse_symbols*).
35
- 4. Pengguna secara eksplisit meminta konsultasi desain domain boundary interaktif.
47
+ Gunakan alur 4 langkah ini saat merancang domain baru, melakukan *re-mapping* arsitektur, atau mengunci kontrak fitur:
36
48
 
37
- ---
49
+ ### Langkah 1: Topological & Connectivity Scan (Maksimal 2 Tool Call)
50
+ 1. Panggil \`septum_get_domain_catalog({})\` untuk memeriksa *Telescope View* dan daftar domain yang terdaftar.
51
+ 2. Panggil \`septum_get_domain_catalog({ domain: "<target>", detail_level: "compact" })\` untuk memetakan file, simbol yang sudah ada, dan koneksi \`imports_from\` / \`imported_by_count\`.
52
+
53
+ ### Langkah 2: Perumusan Kontrak Domain & Anti-Duplikasi Simbol
54
+ * **\`domain\` & \`root\`:** Nama domain dan direktori kanonikalnya.
55
+ * **\`allowed_dependencies\` & \`forbidden_dependencies\`:** Whitelist dan blacklist dependensi lintas-domain.
56
+ * **\`reuse_symbols\`:** Daftar class, service, repository, atau konstanta eksisting yang **wajib digunakan kembali** agar agen tidak membuat kode duplikat.
38
57
 
39
- ## 3. Alur Kerja 4 Langkah (The 4-Step Discovery Lifecycle)
40
-
41
- ### Langkah 1: Topological Scan (Maksimal 2 Tool Call)
42
- Analisis karakteristik proyek secara framework-agnostic:
43
- 1. **Periksa Manifest & Config Root:**
44
- * JS/TS: \`package.json\`, \`tsconfig.json\` (baca dependencies, path aliases).
45
- * PHP: \`composer.json\` (baca \`autoload.psr-4\`, framework dependencies).
46
- * Python: \`pyproject.toml\`, \`requirements.txt\`, \`setup.py\` (baca modules & framework).
47
- * Go: \`go.mod\` (baca module path).
48
- 2. **Petakan Direktori Tingkat Atas:**
49
- Identifikasi apakah proyek menggunakan pola:
50
- * *Domain-Driven / Vertical Slice:* \`src/domains/\`, \`app/Domain/\`, \`features/\`.
51
- * *Layered / Clean Architecture:* \`core/\`, \`infrastructure/\`, \`application/\`, \`interfaces/\`.
52
- * *Framework Conventional:* NestJS modules, Laravel app folders, FastAPI routers, Next.js route groups.
53
-
54
- ### Langkah 2: Semantic Blueprint Drafting & Domain Boundary Formulation
55
- Rumuskan spesifikasi domain dengan prinsip **Contract & Invariants (Bukan Prosedural)**:
56
- * **\`root\`:** Direktori fisik domain (gunakan path kanonikal).
57
- * **\`allowed_dependencies\`:** Domain mana saja yang sah diimpor (inbound whitelist).
58
- * **\`forbidden_dependencies\`:** Domain yang dilarang keras diimpor (outbound blacklist).
59
- * **\`archetypes\`:** Pola glob penamaan layer (\`service: "*Service.*"\`, \`model: "*Model.*"\`).
60
-
61
- ### Langkah 3: Human-in-the-Loop Approval Gate
62
- Tampilkan ringkasan domain boundary yang dirumuskan kepada pengguna / Tech Lead untuk disetujui atau disesuaikan sebelum didaftarkan.
63
-
64
- ### Langkah 4: Deterministic Registration & Ingestion
65
- Setelah disetujui:
66
- 1. Daftarkan domain secara langsung via tool MCP \`septum_register_domain(domain_name, root, ...)\` dengan opsi \`ingest_now: true\`.
67
- 2. Atau jalankan CLI \`septum ingest\` untuk mengekstrak seluruh simbol AST dan menyimpannya ke database SQLite \`.septum/septum.db\`.
68
- 3. Pastikan hook pre-commit terpasang aktif di \`.git/hooks/pre-commit\`.
58
+ ### Langkah 3: Registrasi Deterministik ke SQLite SSOT
59
+ 1. Gunakan \`septum_register_domain({ domain, root, allowed_dependencies, forbidden_dependencies, ingest_now: true })\` untuk menyimpan batas domain.
60
+ 2. Gunakan \`septum_register_feature({ feature_key, domain, allowed_touchpoints, reuse_symbols })\` untuk mengunci fokus pengerjaan fitur.
61
+
62
+ ### Langkah 4: Verifikasi Boundary & Siklus Dependensi
63
+ Jalankan \`septum_check_boundary({ scope: "all" })\` (atau CLI \`septum check --staged\`) untuk memastikan 0 pelanggaran batas domain dan 0 *circular dependency*.
69
64
  `;
65
+