@vpxa/kb 0.1.8 → 0.1.10

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.
package/README.md CHANGED
@@ -34,18 +34,20 @@ The KB auto-indexes configured source directories on startup, stores embeddings
34
34
  pnpm add -D @vpxa/kb
35
35
 
36
36
  # Initialize in your project
37
- npx kb init
37
+ npx @vpxa/kb init
38
38
 
39
39
  # Index your codebase
40
- npx kb reindex
40
+ npx @vpxa/kb reindex
41
41
 
42
42
  # Search
43
- npx kb search "authentication middleware"
43
+ npx @vpxa/kb search "authentication middleware"
44
44
 
45
45
  # Start MCP server for AI agents
46
- npx kb serve
46
+ npx @vpxa/kb serve
47
47
  ```
48
48
 
49
+ > **Note:** Once `@vpxa/kb` is installed locally, you can use the short `kb` command (e.g. `kb search`, `kb serve`) since the local binary takes precedence.
50
+
49
51
  ## Tools by Category
50
52
 
51
53
  ### Search & Discovery
@@ -181,8 +183,9 @@ After `kb init`, your `.vscode/mcp.json` is configured automatically:
181
183
  {
182
184
  "servers": {
183
185
  "knowledge-base": {
186
+ "type": "stdio",
184
187
  "command": "npx",
185
- "args": ["kb", "serve"]
188
+ "args": ["@vpxa/kb", "serve"]
186
189
  }
187
190
  }
188
191
  }
@@ -256,7 +259,7 @@ kb graph traverse <startId> [--direction forward|backward] [--depth N]
256
259
  # System
257
260
  kb status
258
261
  kb reindex [--full]
259
- kb onboard <path> [--mode analyze|generate]
262
+ kb onboard <path> [--generate] [--out-dir <dir>]
260
263
  kb serve [--transport stdio|http] [--port N]
261
264
  kb init [--force]
262
265
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vpxa/kb",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "type": "module",
5
5
  "description": "Local-first AI developer toolkit — knowledge base, code analysis, context management, and developer tools for LLM agents",
6
6
  "license": "MIT",
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * `kb init` — scaffold a knowledge base in the current directory.
3
- * Creates kb.config.json, .gitignore entry, and optional IDE config.
3
+ * Creates kb.config.json, .gitignore entry, optional IDE config,
4
+ * and agent instruction files (.github/copilot-instructions.md, AGENTS.md).
4
5
  */
5
6
  export declare function initProject(options: {
6
7
  force: boolean;
@@ -1,9 +1,249 @@
1
- import{appendFileSync as l,existsSync as e,mkdirSync as g,readFileSync as b,writeFileSync as c}from"node:fs";import{resolve as o}from"node:path";const u={sources:[{path:".",excludePatterns:["**/node_modules/**","**/dist/**","**/build/**","**/.git/**","**/.kb-data/**","**/coverage/**","**/*.min.js","**/package-lock.json","**/pnpm-lock.yaml"]}],indexing:{chunkSize:1500,chunkOverlap:200,minChunkSize:100},embedding:{model:"Xenova/mxbai-embed-large-v1",dimensions:1024},store:{backend:"lancedb",path:".kb-data/lance"},curated:{path:"curated"}},f={servers:{"knowledge-base":{type:"stdio",command:"npx",args:["kb","serve"]}}};async function v(d){const n=process.cwd(),s=o(n,"kb.config.json");if(e(s)&&!d.force){console.log("kb.config.json already exists. Use --force to overwrite.");return}c(s,`${JSON.stringify(u,null,2)}
2
- `,"utf-8"),console.log(" Created kb.config.json");const r=o(n,"curated");e(r)||(g(r,{recursive:!0}),console.log(" Created curated/"));const t=o(n,".gitignore");e(t)?b(t,"utf-8").includes(".kb-data")||(l(t,`
1
+ import{appendFileSync as p,existsSync as s,mkdirSync as u,readFileSync as m,writeFileSync as a}from"node:fs";import{basename as g,resolve as e}from"node:path";const h={sources:[{path:".",excludePatterns:["**/node_modules/**","**/dist/**","**/build/**","**/.git/**","**/.kb-data/**","**/coverage/**","**/*.min.js","**/package-lock.json","**/pnpm-lock.yaml"]}],indexing:{chunkSize:1500,chunkOverlap:200,minChunkSize:100},embedding:{model:"mixedbread-ai/mxbai-embed-large-v1",dimensions:1024},store:{backend:"lancedb",path:".kb-data/lance"},curated:{path:"curated"}},f={servers:{"knowledge-base":{type:"stdio",command:"npx",args:["@vpxa/kb","serve"]}}};function y(o){return`# ${o} \u2014 Copilot Instructions
2
+
3
+ This project uses **@vpxa/kb** as an MCP knowledge base server. Use the KB tools to search, analyze, and understand the codebase before making changes.
4
+
5
+ ## KB Tools
6
+
7
+ Before starting any task on **${o}**, use these MCP tools:
8
+
9
+ | Action | Tool | Example |
10
+ |--------|------|---------|
11
+ | Search code & decisions | \`kb_search\` | \`kb_search({ query: "..." })\` |
12
+ | Find symbol definition | \`kb_symbol\` | \`kb_symbol({ name: "ClassName" })\` |
13
+ | Plan what to read | \`kb_scope_map\` | \`kb_scope_map({ task: "..." })\` |
14
+ | Trace call chains | \`kb_trace\` | \`kb_trace({ symbol: "fn", file: "path" })\` |
15
+ | Impact of a change | \`kb_blast_radius\` | \`kb_blast_radius({ changed_files: ["..."] })\` |
16
+ | Persist what you learn | \`kb_remember\` | \`kb_remember({ title: "...", category: "decisions" })\` |
17
+ | Typecheck + lint | \`kb_check\` | \`kb_check({})\` |
18
+ | Run tests | \`kb_test_run\` | \`kb_test_run({})\` |
19
+
20
+ ## Workflow
21
+
22
+ \`\`\`
23
+ kb_search({ query: "your task keywords" }) # Recall prior decisions
24
+ kb_scope_map({ task: "what you are doing" }) # Get a reading plan
25
+ # ... do the work ...
26
+ kb_check({}) # Typecheck + lint
27
+ kb_test_run({}) # Run tests
28
+ kb_remember({ title: "What I learned", category: "decisions" }) # Persist
29
+ \`\`\`
30
+
31
+ ## KB MCP Tools \u2014 Complete Reference
32
+
33
+ ### Search & Discovery
34
+ | Tool | Purpose |
35
+ |------|---------|
36
+ | \`kb_search\` | Hybrid vector + keyword search. Modes: \`hybrid\` (default), \`semantic\`, \`keyword\`. Filters: \`origin\`, \`category\`, \`content_type\`, \`tags\`. |
37
+ | \`kb_find\` | Federated search: vector + FTS + glob + regex in one call. |
38
+ | \`kb_symbol\` | Resolve symbol definition, imports, and all references across files. |
39
+ | \`kb_lookup\` | Full-file retrieval by path or record ID. |
40
+ | \`kb_scope_map\` | Task-scoped reading plan with file list and token estimates. |
41
+ | \`kb_trace\` | Forward/backward flow tracing through call chains. |
42
+ | \`kb_find_examples\` | Find real usage examples of a symbol or pattern. |
43
+ | \`kb_dead_symbols\` | Find exported symbols that are never imported anywhere. |
44
+ | \`kb_file_summary\` | Structural overview of a file (exports, imports, functions). |
45
+
46
+ ### Code Analysis
47
+ | Tool | Purpose |
48
+ |------|---------|
49
+ | \`kb_analyze_structure\` | Project structure overview with file tree and stats. |
50
+ | \`kb_analyze_dependencies\` | Dependency graph with confidence scoring. |
51
+ | \`kb_analyze_symbols\` | Symbol extraction and cross-references. |
52
+ | \`kb_analyze_patterns\` | Design pattern detection (Singleton, Factory, etc.). |
53
+ | \`kb_analyze_entry_points\` | Discover entry points (Lambda handlers, CLI, HTTP routes). |
54
+ | \`kb_analyze_diagram\` | Generate Mermaid architecture diagrams. |
55
+ | \`kb_blast_radius\` | Change impact analysis \u2014 what breaks if you modify a file. |
56
+
57
+ ### Knowledge Management
58
+ | Tool | Purpose |
59
+ |------|---------|
60
+ | \`kb_remember\` | Store a curated knowledge entry (decisions, patterns, conventions). |
61
+ | \`kb_read\` | Read a curated entry by path. |
62
+ | \`kb_update\` | Update an existing curated entry. |
63
+ | \`kb_forget\` | Delete a curated entry (requires reason). |
64
+ | \`kb_list\` | List curated entries, filterable by category and tags. |
65
+ | \`kb_produce_knowledge\` | Auto-generate knowledge from codebase analysis. |
66
+
67
+ ### Execution & Validation
68
+ | Tool | Purpose |
69
+ |------|---------|
70
+ | \`kb_check\` | Incremental typecheck + lint in one call (tsc + biome). |
71
+ | \`kb_test_run\` | Run tests with structured pass/fail results. |
72
+ | \`kb_eval\` | Sandboxed JavaScript/TypeScript execution. |
73
+ | \`kb_batch\` | Execute multiple operations in parallel. |
74
+
75
+ ### Code Manipulation
76
+ | Tool | Purpose |
77
+ |------|---------|
78
+ | \`kb_rename\` | Smart whole-word symbol rename across files (dry-run supported). |
79
+ | \`kb_codemod\` | Regex-based code transformations with rule files (dry-run supported). |
80
+ | \`kb_diff_parse\` | Parse unified diff into structured file changes. |
81
+ | \`kb_data_transform\` | JQ-like JSON transformations. |
82
+
83
+ ### Context Management
84
+ | Tool | Purpose |
85
+ |------|---------|
86
+ | \`kb_compact\` | Compress text to relevant sections using embeddings (no LLM). |
87
+ | \`kb_workset\` | Named file set management (save/load/add/remove working sets). |
88
+ | \`kb_stash\` | Named key-value store for session data. |
89
+ | \`kb_checkpoint\` | Save/restore lightweight session checkpoints. |
90
+ | \`kb_parse_output\` | Parse build tool output (tsc, vitest, biome, git) into structured JSON. |
91
+
92
+ ### FORGE & Context Compression
93
+ | Tool | Purpose |
94
+ |------|---------|
95
+ | \`kb_forge_ground\` | Full FORGE Ground phase (classify + scope + constraints + evidence). |
96
+ | \`kb_forge_classify\` | Quick FORGE tier classification (Floor/Standard/Critical). |
97
+ | \`kb_evidence_map\` | Track critical-path claims as Verified/Assumed/Unknown with receipts. |
98
+ | \`kb_digest\` | Compress multiple text blocks into token-budgeted digest. |
99
+ | \`kb_stratum_card\` | Generate T1/T2 context cards (10-100x token reduction). |
100
+
101
+ ### Web & Network
102
+ | Tool | Purpose |
103
+ |------|---------|
104
+ | \`kb_web_fetch\` | Fetch web page \u2192 LLM-optimized markdown. CSS selectors, 4 modes, smart truncation. |
105
+ | \`kb_web_search\` | Search the web via DuckDuckGo (no API key needed). |
106
+ | \`kb_http\` | HTTP requests (GET/POST/PUT/PATCH/DELETE) for API testing with timing. |
107
+
108
+ ### Verified Lanes
109
+ | Tool | Purpose |
110
+ |------|---------|
111
+ | \`kb_lane\` | Manage isolated file copies for parallel exploration. Actions: \`create\`, \`list\`, \`status\`, \`diff\`, \`merge\`, \`discard\`. |
112
+
113
+ ### Git & Environment
114
+ | Tool | Purpose |
115
+ |------|---------|
116
+ | \`kb_git_context\` | Branch, status, recent commits, optional diff stats. |
117
+ | \`kb_process\` | Process supervisor (start/stop/logs). |
118
+ | \`kb_watch\` | Filesystem watcher for auto-triggered workflows. |
119
+ | \`kb_delegate\` | Delegate subtask to a local Ollama model. |
120
+
121
+ ### Developer Utilities
122
+ | Tool | Purpose |
123
+ |------|---------|
124
+ | \`kb_regex_test\` | Test regex patterns with match/replace/split modes. |
125
+ | \`kb_encode\` | Base64, URL, SHA-256, MD5, hex encode/decode, JWT decode. |
126
+ | \`kb_measure\` | Code complexity metrics (cyclomatic complexity, line counts). |
127
+ | \`kb_changelog\` | Generate changelog from git history (conventional commits). |
128
+ | \`kb_schema_validate\` | Validate JSON data against JSON Schema. |
129
+ | \`kb_snippet\` | Save/get/search/delete persistent code snippets. |
130
+ | \`kb_env\` | System and runtime environment info (sensitive values redacted). |
131
+ | \`kb_time\` | Date parsing, timezone conversion, duration math. |
132
+
133
+ ### System
134
+ | Tool | Purpose |
135
+ |------|---------|
136
+ | \`kb_status\` | Index statistics (record count, file count, content types). |
137
+ | \`kb_reindex\` | Rebuild the vector index from configured sources. |
138
+ | \`kb_health\` | Project health checks (package.json, tsconfig, lockfile, etc.). |
139
+ | \`kb_onboard\` | First-time codebase onboarding \u2014 runs all analyses, auto-persists results. |
140
+ | \`kb_graph\` | Knowledge graph queries (find_nodes, find_edges, neighbors, traverse, stats). |
141
+ | \`kb_queue\` | Task queue for sequential agent operations. |
142
+ | \`kb_replay_list\` | View audit trail of tool invocations. |
143
+ | \`kb_replay_clear\` | Clear the replay audit trail. |
144
+ `}function w(o){return`# ${o} \u2014 Agent Instructions
145
+
146
+ ## KB Knowledge Base
147
+
148
+ This project has a **@vpxa/kb** MCP server providing search, analysis, memory, and developer tools.
149
+
150
+ ### Skills Reference
151
+
152
+ | Context | Skill | Details |
153
+ |---------|-------|---------|
154
+ | KB search, analysis, memory | \`kb\` | See [skills/knowledge-base/SKILL.md](skills/knowledge-base/SKILL.md) or run \`kb_status({})\` |
155
+
156
+ ### Available Tool Categories
157
+
158
+ | Category | Tools | Purpose |
159
+ |----------|-------|---------|
160
+ | Search & Discovery | \`kb_search\`, \`kb_find\`, \`kb_symbol\`, \`kb_trace\`, \`kb_scope_map\`, \`kb_lookup\`, \`kb_find_examples\`, \`kb_dead_symbols\`, \`kb_file_summary\` | Find code, symbols, data flow, reading plans |
161
+ | Code Analysis | \`kb_analyze_structure\`, \`kb_analyze_dependencies\`, \`kb_analyze_symbols\`, \`kb_analyze_patterns\`, \`kb_analyze_entry_points\`, \`kb_analyze_diagram\`, \`kb_blast_radius\` | Structure, deps, patterns, impact, diagrams |
162
+ | Knowledge | \`kb_remember\`, \`kb_read\`, \`kb_update\`, \`kb_forget\`, \`kb_list\`, \`kb_produce_knowledge\` | Persistent cross-session memory |
163
+ | Execution | \`kb_check\`, \`kb_test_run\`, \`kb_eval\`, \`kb_batch\` | Typecheck, lint, test, run code |
164
+ | Code Manipulation | \`kb_rename\`, \`kb_codemod\`, \`kb_diff_parse\`, \`kb_data_transform\` | Safe renames, transforms, diff parsing |
165
+ | Context | \`kb_compact\`, \`kb_workset\`, \`kb_stash\`, \`kb_checkpoint\`, \`kb_parse_output\` | Manage working sets, save progress |
166
+ | FORGE | \`kb_forge_ground\`, \`kb_forge_classify\`, \`kb_evidence_map\`, \`kb_digest\`, \`kb_stratum_card\` | Quality gates, context compression |
167
+ | Web & API | \`kb_web_fetch\`, \`kb_web_search\`, \`kb_http\` | Fetch pages, search web, test APIs |
168
+ | Lanes | \`kb_lane\` | Isolated file copies for parallel exploration (create/list/status/diff/merge/discard) |
169
+ | Git & Environment | \`kb_git_context\`, \`kb_process\`, \`kb_watch\`, \`kb_delegate\` | Git info, process management |
170
+ | Utilities | \`kb_regex_test\`, \`kb_encode\`, \`kb_measure\`, \`kb_changelog\`, \`kb_schema_validate\`, \`kb_snippet\`, \`kb_env\`, \`kb_time\` | Regex, encoding, metrics, validation |
171
+ | System | \`kb_status\`, \`kb_reindex\`, \`kb_health\`, \`kb_onboard\`, \`kb_graph\`, \`kb_queue\`, \`kb_replay_list\`, \`kb_replay_clear\` | Index management, health checks, knowledge graph |
172
+
173
+ ### Search Modes
174
+
175
+ The \`kb_search\` tool supports three search strategies via the \`search_mode\` parameter:
176
+
177
+ - **\`hybrid\`** (default) \u2014 Vector similarity + full-text keyword search merged via Reciprocal Rank Fusion. Best for most queries.
178
+ - **\`semantic\`** \u2014 Pure vector cosine similarity. Best for conceptual/meaning-based queries.
179
+ - **\`keyword\`** \u2014 Full-text search only. Best for exact identifiers, function names, specific strings.
180
+
181
+ Additional filters: \`origin\` (\`indexed\`/\`curated\`/\`produced\`), \`category\`, \`content_type\`, \`tags\`, \`min_score\`.
182
+
183
+ ### Session Protocol
184
+
185
+ **Start of session:**
186
+ \`\`\`
187
+ kb_status({})
188
+ kb_search({ query: "SESSION CHECKPOINT", origin: "curated" })
189
+ \`\`\`
190
+
191
+ **During session:**
192
+ \`\`\`
193
+ kb_search \u2192 kb_scope_map \u2192 kb_symbol \u2192 kb_trace # Orient
194
+ kb_check \u2192 kb_test_run # Validate changes
195
+ kb_remember # Capture insights
196
+ \`\`\`
197
+
198
+ **End of session:**
199
+ \`\`\`
200
+ kb_remember({ title: "Session checkpoint: <topic>", content: "<summary>", category: "conventions" })
201
+ \`\`\`
202
+
203
+ ### Workflow Chains
204
+
205
+ **Codebase onboarding:**
206
+ \`\`\`
207
+ kb_onboard({ path: "." }) \u2192 kb_produce_knowledge({ path: "src/" }) \u2192 kb_remember(...)
208
+ \`\`\`
209
+
210
+ **Planning a task:**
211
+ \`\`\`
212
+ kb_search({ query: "task keywords" }) \u2192 kb_scope_map({ task: "description" }) \u2192 kb_workset({ action: "save", name: "task", files: [...] })
213
+ \`\`\`
214
+
215
+ **Bug investigation:**
216
+ \`\`\`
217
+ kb_parse_output({ output: "<error>" }) \u2192 kb_symbol({ name: "failingFn" }) \u2192 kb_trace({ symbol: "failingFn", direction: "backward" }) \u2192 kb_blast_radius({ changed_files: ["suspect.ts"] })
218
+ \`\`\`
219
+
220
+ **Safe refactor with lanes:**
221
+ \`\`\`
222
+ kb_lane({ action: "create", name: "refactor", files: [...] }) \u2192 [make changes] \u2192 kb_lane({ action: "diff", name: "refactor" }) \u2192 kb_check({}) \u2192 kb_lane({ action: "merge", name: "refactor" })
223
+ \`\`\`
224
+
225
+ **After making changes:**
226
+ \`\`\`
227
+ kb_blast_radius({ changed_files: ["src/file.ts"] }) \u2192 kb_check({}) \u2192 kb_test_run({}) \u2192 kb_reindex({}) \u2192 kb_remember(...)
228
+ \`\`\`
229
+
230
+ ### Knowledge Categories
231
+
232
+ \`decisions\` | \`patterns\` | \`conventions\` | \`troubleshooting\`
233
+
234
+ ### Core Rules
235
+
236
+ - Search KB for prior decisions before proposing new ones
237
+ - Follow \`_Next:\` hints in tool responses for guided workflows
238
+ - Use \`kb_check\` and \`kb_test_run\` to validate before committing
239
+ - Use \`kb_remember\` to persist architecture decisions and lessons learned
240
+ - Analysis results are auto-persisted as \`origin: "produced"\` entries
241
+ `}async function P(o){const t=process.cwd(),n=e(t,"kb.config.json");if(s(n)&&!o.force){console.log("kb.config.json already exists. Use --force to overwrite.");return}a(n,`${JSON.stringify(h,null,2)}
242
+ `,"utf-8"),console.log(" Created kb.config.json");const i=e(t,"curated");s(i)||(u(i,{recursive:!0}),console.log(" Created curated/"));const r=e(t,".gitignore");s(r)?m(r,"utf-8").includes(".kb-data")||(p(r,`
3
243
  # Knowledge base vector store
4
244
  .kb-data/
5
- `,"utf-8"),console.log(" Added .kb-data/ to .gitignore")):(c(t,`# Knowledge base vector store
245
+ `,"utf-8"),console.log(" Added .kb-data/ to .gitignore")):(a(r,`# Knowledge base vector store
6
246
  .kb-data/
7
- `,"utf-8"),console.log(" Created .gitignore with .kb-data/"));const i=o(n,".vscode"),a=o(i,"mcp.json");e(i)&&!e(a)&&(c(a,`${JSON.stringify(f,null,2)}
8
- `,"utf-8"),console.log(" Created .vscode/mcp.json")),console.log(`
9
- Knowledge base initialized! Next steps:`),console.log(" kb reindex Index your codebase"),console.log(" kb search Search indexed content"),console.log(" kb serve Start MCP server for IDE integration")}export{v as initProject};
247
+ `,"utf-8"),console.log(" Created .gitignore with .kb-data/"));const c=e(t,".vscode"),l=e(c,"mcp.json");s(c)&&!s(l)&&(a(l,`${JSON.stringify(f,null,2)}
248
+ `,"utf-8"),console.log(" Created .vscode/mcp.json"));const d=g(t),b=e(t,".github"),k=e(b,"copilot-instructions.md");s(k)||(u(b,{recursive:!0}),a(k,y(d),"utf-8"),console.log(" Created .github/copilot-instructions.md"));const _=e(t,"AGENTS.md");s(_)||(a(_,w(d),"utf-8"),console.log(" Created AGENTS.md")),console.log(`
249
+ Knowledge base initialized! Next steps:`),console.log(" kb reindex Index your codebase"),console.log(" kb search Search indexed content"),console.log(" kb serve Start MCP server for IDE integration")}export{P as initProject};
@@ -1,3 +1,3 @@
1
- import{analyzeCommands as a}from"./commands/analyze.js";import{contextCommands as i}from"./commands/context-cmds.js";import{environmentCommands as c}from"./commands/environment.js";import{executionCommands as l}from"./commands/execution.js";import{graphCommands as p}from"./commands/graph.js";import{knowledgeCommands as d}from"./commands/knowledge.js";import{searchCommands as f}from"./commands/search.js";import{systemCommands as g}from"./commands/system.js";import{workspaceCommands as h}from"./commands/workspace.js";import{getCtx as C}from"./context.js";const e=[...f,...d,...a,...p,...g,...l,...i,...h,...c];e.push({name:"help",description:"Show available commands",run:async()=>{r()}});async function U(s){const o=[...s],n=o.shift();if(!n||n==="--help"||n==="-h"){r();return}if(n==="--version"||n==="-v"){console.log("0.1.0");return}const t=e.find(m=>m.name===n);t||(console.error(`Unknown command: ${n}`),r(),process.exit(1));try{await t.run(o)}finally{const m=C();m&&await m.store.close()}}function r(){console.log(`@vpxa/kb \u2014 Local-first AI developer toolkit
1
+ import{readFileSync as i}from"node:fs";import{dirname as c,resolve as p}from"node:path";import{fileURLToPath as l}from"node:url";import{analyzeCommands as d}from"./commands/analyze.js";import{contextCommands as f}from"./commands/context-cmds.js";import{environmentCommands as g}from"./commands/environment.js";import{executionCommands as h}from"./commands/execution.js";import{graphCommands as C}from"./commands/graph.js";import{knowledgeCommands as v}from"./commands/knowledge.js";import{searchCommands as u}from"./commands/search.js";import{systemCommands as k}from"./commands/system.js";import{workspaceCommands as x}from"./commands/workspace.js";import{getCtx as y}from"./context.js";const e=[...u,...v,...d,...C,...k,...h,...f,...x,...g];e.push({name:"help",description:"Show available commands",run:async()=>{s()}});async function F(r){const o=[...r],n=o.shift();if(!n||n==="--help"||n==="-h"){s();return}if(n==="--version"||n==="-v"){const m=p(c(l(import.meta.url)),"..","..","..","package.json"),a=JSON.parse(i(m,"utf-8"));console.log(a.version);return}const t=e.find(m=>m.name===n);t||(console.error(`Unknown command: ${n}`),s(),process.exit(1));try{await t.run(o)}finally{const m=y();m&&await m.store.close()}}function s(){console.log(`@vpxa/kb \u2014 Local-first AI developer toolkit
2
2
  `),console.log(`Usage: kb <command> [options]
3
- `),console.log("Commands:");const s=Math.max(...e.map(o=>o.name.length));for(const o of e)console.log(` ${o.name.padEnd(s+2)}${o.description}`);console.log(""),console.log("Options:"),console.log(" --help, -h Show this help"),console.log(" --version, -v Show version")}export{U as run};
3
+ `),console.log("Commands:");const r=Math.max(...e.map(o=>o.name.length));for(const o of e)console.log(` ${o.name.padEnd(r+2)}${o.description}`);console.log(""),console.log("Options:"),console.log(" --help, -h Show this help"),console.log(" --version, -v Show version")}export{F as run};
@@ -1,45 +1,45 @@
1
- import{existsSync as W,mkdirSync as V,readdirSync as q,rmSync as U,writeFileSync as I}from"node:fs";import{readdir as J,readFile as Z}from"node:fs/promises";import{basename as L,join as K,relative as H,resolve as Q}from"node:path";import{DependencyAnalyzer as X,DiagramGenerator as Y,EntryPointAnalyzer as ee,extractRegexCallGraph as te,extractTsCallGraph as se,PatternAnalyzer as ne,StructureAnalyzer as oe,SymbolAnalyzer as re}from"../../analyzers/dist/index.js";const N={structure:"Project Structure",dependencies:"Dependencies","entry-points":"Entry Points",symbols:"Symbols",patterns:"Patterns",diagram:"C4 Container Diagram","code-map":"Code Map (Module Graph)","config-values":"Configuration Values","synthesis-guide":"Synthesis Guide"};function ie(g,u,t,p){const n=[`Analysis baselines for **${t}** have been generated.`];u==="generate"?n.push("Individual results are in the sibling `.md` and `.json` files in this directory.",""):n.push("Results are stored in the KB vector store.","");const a=p.get("symbols"),i=p.get("dependencies"),d=p.get("patterns"),y=p.get("entry-points"),b=a?.totalCount??0,k=a?.exportedCount??0,x=i?.totalImports??0,C=y?.total??0,r=(d?.patterns??[]).map(m=>m.pattern),w=r.some(m=>m.startsWith("Spring")),D=r.includes("AWS CDK")||r.includes("CDK IaC"),P=r.includes("Maven"),T=r.includes("Serverless")||C>3,$=i?.external?Object.keys(i.external):[],f=$.some(m=>["express","fastify","next","react","vitest","jest"].includes(m))||x>0,_=$.some(m=>["turbo","lerna","nx"].includes(m))||r.includes("Monorepo");if(n.push("### Project Profile",""),n.push(`- **${b} symbols** (${k} exported), **${x} imports**, **${C} entry ${C===1?"point":"points"}**`),r.length>0&&n.push(`- **Detected**: ${r.slice(0,8).join(", ")}`),n.push(""),b===0&&x===0&&C===0)return n.push("> **Note:** This project appears to be empty or contains no analyzable source code.","> Run onboard again after adding source files."),n.join(`
2
- `);const v=g.filter(m=>m.status==="success"),M=g.filter(m=>m.status==="failed");n.push("### Completed Analyses","");for(const m of v){const S=N[m.name]??m.name,e=m.output.length>1e3?`${Math.round(m.output.length/1024)}KB`:`${m.output.length}B`;u==="generate"?n.push(`- \u2713 [${S}](./${m.name}.md) (${e})`):n.push(`- \u2713 ${S} (${e})`)}if(M.length>0){n.push("","### Failed Analyses","");for(const m of M)n.push(`- \u2717 ${m.name}: ${m.error}`)}n.push("","### Recommended Reading Order","","1. **Start with** `synthesis-guide.md` (this file) \u2192 `entry-points.md` \u2192 `patterns.md`","2. **Module graph** via `code-map.md` \u2014 cross-package call edges with function names","3. **Architecture** via `diagram.md` (C4 Container) \u2192 `dependencies.md`","4. **Browse structure** via `structure.md` for file layout","5. **API surface** via `symbols.md` \u2014 file paths + exported symbols (capped at 80KB)","6. **Reference**: `config-values.md` (config reference)","","> **Size guidance:** Total output is ~");const j=v.reduce((m,S)=>m+S.output.length,0)/1024;return n[n.length-1]+=`${Math.round(j)}KB. Focus on code-map.md + entry-points.md + diagram.md (~${Math.round((v.find(m=>m.name==="code-map")?.output.length??0)/1024+(v.find(m=>m.name==="entry-points")?.output.length??0)/1024+(v.find(m=>m.name==="diagram")?.output.length??0)/1024)}KB) for maximum signal-to-token ratio.`,n.push("","### Synthesize Knowledge","","Produce the following `kb_remember` entries:",""),n.push("1. **Architecture Summary** (category: `architecture`)"),_?(n.push(" - Package boundaries, dependency graph between packages"),n.push(" - Shared vs service-specific code")):T?(n.push(" - Lambda functions, triggers, event flow"),n.push(" - Infrastructure patterns (queues, tables, APIs)")):w?(n.push(" - Controller \u2192 Service \u2192 Repository layers"),n.push(" - Spring configuration and profiles")):(n.push(" - Layer structure, dependency flow"),n.push(" - Key design decisions")),n.push(""),n.push("2. **Domain Model** (category: `architecture`)"),n.push(" - Key entities/types and their relationships"),n.push(" - Data flow from entry points through processing"),n.push(""),n.push("3. **Conventions** (category: `conventions`)"),n.push(" - Naming patterns, file organization, testing approach"),D&&n.push(" - CDK construct patterns and stack organization"),f&&n.push(" - Build tooling, package manager, module system"),P&&n.push(" - Maven module structure, dependency management"),n.push("","### Using KB Tools","","This project has a KB MCP server with tools for search, analysis, memory, and more.","Add the KB tools to your agent configuration so every session benefits from them.","","**Add to `.github/copilot-instructions.md`** or `AGENTS.md`:","","```markdown","## KB Tools","",`Before starting any task on **${t}**, use these MCP tools:`,"","| Action | Tool | Example |","|--------|------|---------|",'| Search code & decisions | `kb_search` | `kb_search({ query: "..." })` |','| Find symbol definition | `kb_symbol` | `kb_symbol({ name: "ClassName" })` |','| Trace call chains | `kb_trace` | `kb_trace({ symbol: "fn", file: "path" })` |','| Impact of a change | `kb_blast_radius` | `kb_blast_radius({ changed_files: ["..."] })` |','| Persist what you learn | `kb_remember` | `kb_remember({ title: "...", category: "decisions" })` |',"| Typecheck + lint | `kb_check` | `kb_check({})` |","| Run tests | `kb_test_run` | `kb_test_run({})` |","```","","**Add to each `.github/agents/*.agent.md`** (Skills Reference table):","","```markdown","| Context | Skill | Details |","|---------|-------|---------|","| KB search, analysis, memory | `kb` | `path/to/skills/kb/SKILL.md` |","```","","The KB skill teaches agents the full tool set:","","| Category | Tools | Purpose |","|----------|-------|---------|","| Search & Discovery | `kb_search`, `kb_find`, `kb_symbol`, `kb_trace` | Find code, symbols, data flow |","| Code Analysis | `kb_analyze_*`, `kb_blast_radius` | Structure, deps, patterns, impact |","| Knowledge | `kb_remember`, `kb_read`, `kb_update`, `kb_forget` | Persistent cross-session memory |","| Execution | `kb_check`, `kb_test_run`, `kb_eval` | Typecheck, lint, test, run code |","| Refactoring | `kb_rename`, `kb_codemod`, `kb_dead_symbols` | Safe renames, transforms, cleanup |","| Web & API | `kb_web_fetch`, `kb_web_search`, `kb_http` | Research, API testing |","| Context | `kb_workset`, `kb_stash`, `kb_checkpoint` | Manage working sets, save progress |","","**Workflow pattern \u2014 use on every task:**","","```",'kb_search({ query: "your task keywords" }) # Recall prior decisions','kb_scope_map({ task: "what you are doing" }) # Get a reading plan',"# ... do the work ...",'kb_remember({ title: "What I learned", category: "decisions" }) # Persist',"```"),n.join(`
1
+ import{existsSync as F,mkdirSync as V,readdirSync as q,rmSync as U,writeFileSync as B}from"node:fs";import{readdir as J,readFile as Z}from"node:fs/promises";import{basename as N,join as O,relative as H,resolve as Q}from"node:path";import{DependencyAnalyzer as X,DiagramGenerator as Y,EntryPointAnalyzer as ee,extractRegexCallGraph as te,extractTsCallGraph as se,PatternAnalyzer as ne,StructureAnalyzer as oe,SymbolAnalyzer as re}from"../../analyzers/dist/index.js";const L={structure:"Project Structure",dependencies:"Dependencies","entry-points":"Entry Points",symbols:"Symbols",patterns:"Patterns",diagram:"C4 Container Diagram","code-map":"Code Map (Module Graph)","config-values":"Configuration Values","synthesis-guide":"Synthesis Guide"};function ie(g,u,t,p){const n=[`Analysis baselines for **${t}** have been generated.`];u==="generate"?n.push("Individual results are in the sibling `.md` and `.json` files in this directory.",""):n.push("Results are stored in the KB vector store.","");const a=p.get("symbols"),i=p.get("dependencies"),d=p.get("patterns"),y=p.get("entry-points"),$=a?.totalCount??0,b=a?.exportedCount??0,M=i?.totalImports??0,C=y?.total??0,r=(d?.patterns??[]).map(m=>m.pattern),w=r.some(m=>m.startsWith("Spring")),_=r.includes("AWS CDK")||r.includes("CDK IaC"),P=r.includes("Maven"),T=r.includes("Serverless")||C>3,k=i?.external?Object.keys(i.external):[],f=k.some(m=>["express","fastify","next","react","vitest","jest"].includes(m))||M>0,x=k.some(m=>["turbo","lerna","nx"].includes(m))||r.includes("Monorepo");if(n.push("### Project Profile",""),n.push(`- **${$} symbols** (${b} exported), **${M} imports**, **${C} entry ${C===1?"point":"points"}**`),r.length>0&&n.push(`- **Detected**: ${r.slice(0,8).join(", ")}`),n.push(""),$===0&&M===0&&C===0)return n.push("> **Note:** This project appears to be empty or contains no analyzable source code.","> Run onboard again after adding source files."),n.join(`
2
+ `);const v=g.filter(m=>m.status==="success"),j=g.filter(m=>m.status==="failed");n.push("### Completed Analyses","");for(const m of v){const S=L[m.name]??m.name,e=m.output.length>1e3?`${Math.round(m.output.length/1024)}KB`:`${m.output.length}B`;u==="generate"?n.push(`- \u2713 [${S}](./${m.name}.md) (${e})`):n.push(`- \u2713 ${S} (${e})`)}if(j.length>0){n.push("","### Failed Analyses","");for(const m of j)n.push(`- \u2717 ${m.name}: ${m.error}`)}n.push("","### Recommended Reading Order","","1. **Start with** `synthesis-guide.md` (this file) \u2192 `entry-points.md` \u2192 `patterns.md`","2. **Module graph** via `code-map.md` \u2014 cross-package call edges with function names","3. **Architecture** via `diagram.md` (C4 Container) \u2192 `dependencies.md`","4. **Browse structure** via `structure.md` for file layout","5. **API surface** via `symbols.md` \u2014 file paths + exported symbols (capped at 80KB)","6. **Reference**: `config-values.md` (config reference)","","> **Size guidance:** Total output is ~");const D=v.reduce((m,S)=>m+S.output.length,0)/1024;return n[n.length-1]+=`${Math.round(D)}KB. Focus on code-map.md + entry-points.md + diagram.md (~${Math.round((v.find(m=>m.name==="code-map")?.output.length??0)/1024+(v.find(m=>m.name==="entry-points")?.output.length??0)/1024+(v.find(m=>m.name==="diagram")?.output.length??0)/1024)}KB) for maximum signal-to-token ratio.`,n.push("","### Synthesize Knowledge","","Produce the following `kb_remember` entries:",""),n.push("1. **Architecture Summary** (category: `architecture`)"),x?(n.push(" - Package boundaries, dependency graph between packages"),n.push(" - Shared vs service-specific code")):T?(n.push(" - Lambda functions, triggers, event flow"),n.push(" - Infrastructure patterns (queues, tables, APIs)")):w?(n.push(" - Controller \u2192 Service \u2192 Repository layers"),n.push(" - Spring configuration and profiles")):(n.push(" - Layer structure, dependency flow"),n.push(" - Key design decisions")),n.push(""),n.push("2. **Domain Model** (category: `architecture`)"),n.push(" - Key entities/types and their relationships"),n.push(" - Data flow from entry points through processing"),n.push(""),n.push("3. **Conventions** (category: `conventions`)"),n.push(" - Naming patterns, file organization, testing approach"),_&&n.push(" - CDK construct patterns and stack organization"),f&&n.push(" - Build tooling, package manager, module system"),P&&n.push(" - Maven module structure, dependency management"),n.push("","### Using KB Tools","","This project has a KB MCP server with tools for search, analysis, memory, and more.","`kb init` has already created `.github/copilot-instructions.md` and `AGENTS.md` with the complete tool reference.","If not, run `npx @vpxa/kb init` to generate them.","","**Workflow pattern \u2014 use on every task:**","","```",'kb_search({ query: "your task keywords" }) # Recall prior decisions','kb_scope_map({ task: "what you are doing" }) # Get a reading plan',"# ... do the work ...","kb_check({}) # Typecheck + lint","kb_test_run({}) # Run tests",'kb_remember({ title: "What I learned", category: "decisions" }) # Persist',"```"),n.join(`
3
3
  `)}const ae=new Set(["test","tests","__tests__","spec","specs","__mocks__","__fixtures__","fixtures","test-utils"]);function R(g){return g.replace(/\\/g,"/").split("/").some(t=>ae.has(t))||/\.(test|spec)\.[jt]sx?$/.test(g)||/Test\.java$/.test(g)}function ce(g,u,t){const p=g.get("dependencies"),n=g.get("symbols"),a=g.get("entry-points"),i=[`## Code Map: ${u}
4
4
  `];if(!p&&!n)return i.push("No dependency or symbol data available."),i.join(`
5
- `);const d=p?.reverseGraph??{},y=n?.symbols??[],b=a?.entryPoints??[],k=new Map;for(const f of y){if(!f.exported)continue;const _=f.filePath.replace(/\\/g,"/");if(R(_))continue;const v=k.get(_);v?v.push({name:f.name,kind:f.kind}):k.set(_,[{name:f.name,kind:f.kind}])}const x=new Map;for(const[f,_]of Object.entries(d)){const v=f.replace(/\\/g,"/"),M=ue(v,k),j=_.map(S=>S.replace(/\\/g,"/")).filter(S=>!R(S));if(j.length===0)continue;const m=x.get(M);if(m)for(const S of j)m.add(S);else x.set(M,new Set(j))}const C=new Map;for(const f of b)C.set(f.filePath.replace(/\\/g,"/"),{name:f.name,trigger:f.trigger});const l=new Map,r=new Map;if(t)for(const[f,_]of t){if(R(f))continue;const v=z(f);for(const[M,j]of _){if(R(M))continue;const m=z(M);if(v===m)continue;let S=l.get(f);S||(S=new Map,l.set(f,S)),S.set(M,j);const e=r.get(M),o={file:f,symbols:j};e?e.push(o):r.set(M,[o])}}const w=new Set;for(const f of C.keys())w.add(f);for(const f of l.keys())w.add(f);for(const f of r.keys())w.add(f);if(!t)for(const f of k.keys()){const _=x.get(f);_&&_.size>=3&&w.add(f)}const D=new Map;for(const f of w){const _=z(f),v=D.get(_);v?v.push(f):D.set(_,[f])}const P=[...D.entries()].sort((f,_)=>f[0].localeCompare(_[0])),T=t?"AST call graph":"import analysis",$=t?`, ${l.size} cross-package callers`:"";i.push(`**${w.size} key modules** (${T}${$})
5
+ `);const d=p?.reverseGraph??{},y=n?.symbols??[],$=a?.entryPoints??[],b=new Map;for(const f of y){if(!f.exported)continue;const x=f.filePath.replace(/\\/g,"/");if(R(x))continue;const v=b.get(x);v?v.push({name:f.name,kind:f.kind}):b.set(x,[{name:f.name,kind:f.kind}])}const M=new Map;for(const[f,x]of Object.entries(d)){const v=f.replace(/\\/g,"/"),j=ue(v,b),D=x.map(S=>S.replace(/\\/g,"/")).filter(S=>!R(S));if(D.length===0)continue;const m=M.get(j);if(m)for(const S of D)m.add(S);else M.set(j,new Set(D))}const C=new Map;for(const f of $)C.set(f.filePath.replace(/\\/g,"/"),{name:f.name,trigger:f.trigger});const l=new Map,r=new Map;if(t)for(const[f,x]of t){if(R(f))continue;const v=z(f);for(const[j,D]of x){if(R(j))continue;const m=z(j);if(v===m)continue;let S=l.get(f);S||(S=new Map,l.set(f,S)),S.set(j,D);const e=r.get(j),o={file:f,symbols:D};e?e.push(o):r.set(j,[o])}}const w=new Set;for(const f of C.keys())w.add(f);for(const f of l.keys())w.add(f);for(const f of r.keys())w.add(f);if(!t)for(const f of b.keys()){const x=M.get(f);x&&x.size>=3&&w.add(f)}const _=new Map;for(const f of w){const x=z(f),v=_.get(x);v?v.push(f):_.set(x,[f])}const P=[..._.entries()].sort((f,x)=>f[0].localeCompare(x[0])),T=t?"AST call graph":"import analysis",k=t?`, ${l.size} cross-package callers`:"";i.push(`**${w.size} key modules** (${T}${k})
6
6
  `),i.push(`**Legend:** \u26A1 Entry point | \u{1F4E4} Exports | \u2192 Calls (outgoing) | \u2190 Called by (incoming) | \u27A1 Used by (import)
7
- `);for(const[f,_]of P){_.sort(),i.push(`### ${f}/
8
- `);for(const v of _){const M=k.get(v),j=C.get(v),m=l.get(v),S=r.get(v),e=x.get(v),o=v.startsWith(`${f}/`)?v.slice(f.length+1):v;if(i.push(`**${o}**`),j&&i.push(` \u26A1 Entry: \`${j.name}\`${j.trigger?` (${j.trigger})`:""}`),M&&M.length>0){const s=M.slice(0,8).map(h=>`${h.name}`).join(", "),c=M.length>8?` (+${M.length-8})`:"";i.push(` \u{1F4E4} ${s}${c}`)}if(m&&m.size>0){const s=[...m.entries()].sort((c,h)=>h[1].length-c[1].length);for(const[c,h]of s.slice(0,4)){const A=c.startsWith(`${f}/`)?c.slice(f.length+1):c;i.push(` \u2192 ${A}: ${h.slice(0,5).join(", ")}${h.length>5?"\u2026":""}`)}s.length>4&&i.push(` \u2192 +${s.length-4} more targets`)}if(S&&S.length>0){for(const s of S.slice(0,4)){const c=s.file.startsWith(`${f}/`)?s.file.slice(f.length+1):s.file;i.push(` \u2190 ${c}: ${s.symbols.slice(0,4).join(", ")}${s.symbols.length>4?"\u2026":""}`)}S.length>4&&i.push(` \u2190 +${S.length-4} more callers`)}else if(!t&&e&&e.size>0){const s=[...e].filter(c=>!R(c));s.length<=3?i.push(` \u27A1 Used by: ${s.join(", ")}`):i.push(` \u27A1 Used by: ${s.slice(0,3).join(", ")} (+${s.length-3} more)`)}i.push("")}}return i.join(`
7
+ `);for(const[f,x]of P){x.sort(),i.push(`### ${f}/
8
+ `);for(const v of x){const j=b.get(v),D=C.get(v),m=l.get(v),S=r.get(v),e=M.get(v),o=v.startsWith(`${f}/`)?v.slice(f.length+1):v;if(i.push(`**${o}**`),D&&i.push(` \u26A1 Entry: \`${D.name}\`${D.trigger?` (${D.trigger})`:""}`),j&&j.length>0){const s=j.slice(0,8).map(h=>`${h.name}`).join(", "),c=j.length>8?` (+${j.length-8})`:"";i.push(` \u{1F4E4} ${s}${c}`)}if(m&&m.size>0){const s=[...m.entries()].sort((c,h)=>h[1].length-c[1].length);for(const[c,h]of s.slice(0,4)){const A=c.startsWith(`${f}/`)?c.slice(f.length+1):c;i.push(` \u2192 ${A}: ${h.slice(0,5).join(", ")}${h.length>5?"\u2026":""}`)}s.length>4&&i.push(` \u2192 +${s.length-4} more targets`)}if(S&&S.length>0){for(const s of S.slice(0,4)){const c=s.file.startsWith(`${f}/`)?s.file.slice(f.length+1):s.file;i.push(` \u2190 ${c}: ${s.symbols.slice(0,4).join(", ")}${s.symbols.length>4?"\u2026":""}`)}S.length>4&&i.push(` \u2190 +${S.length-4} more callers`)}else if(!t&&e&&e.size>0){const s=[...e].filter(c=>!R(c));s.length<=3?i.push(` \u27A1 Used by: ${s.join(", ")}`):i.push(` \u27A1 Used by: ${s.slice(0,3).join(", ")} (+${s.length-3} more)`)}i.push("")}}return i.join(`
9
9
  `)}function z(g){const u=g.split("/");if(u.length>=2&&["packages","services","providers","apps","libs"].includes(u[0]))return`${u[0]}/${u[1]}`;const t=u.indexOf("java"),p=u.indexOf("kotlin"),n=t>=0?t:p;if(n>=0&&n+2<u.length){const a=u.slice(n+1);return["com","org","net","io","dev"].includes(a[0])&&a.length>=3?a.slice(0,3).join("/"):a.slice(0,2).join("/")}return u[0]==="src"&&u.length>=3?`${u[0]}/${u[1]}`:u[0]}function le(g,u,t){const p=u.get("symbols"),n=u.get("entry-points"),a=u.get("dependencies"),i=new Map;for(const[e,o]of g)if(!R(e))for(const[s,c]of o){if(R(s))continue;const h=z(e),A=z(s);if(h===A)continue;const E=`${h}|${A}`;i.set(E,(i.get(E)??0)+c.length)}if(i.size===0)return`## Architecture Diagram
10
10
 
11
- No cross-package dependencies detected.`;const d=new Set;for(const e of i.keys()){const[o,s]=e.split("|");d.add(o),d.add(s)}const y=new Map;if(p?.symbols)for(const e of p.symbols){if(!e.exported)continue;const o=e.filePath.replace(/\\/g,"/");if(R(o))continue;const s=z(o);y.set(s,(y.get(s)??0)+1)}const b=new Map;if(n?.entryPoints)for(const e of n.entryPoints){const o=e.filePath.replace(/\\/g,"/"),s=z(o),c=b.get(s);c?(c.count++,e.trigger&&c.triggers.add(e.trigger)):b.set(s,{count:1,triggers:new Set(e.trigger?[e.trigger]:[])})}const k=[];if(a?.external){const e=a.external,o={"client-dynamodb":{id:"dynamodb",name:"DynamoDB"},"lib-dynamodb":{id:"dynamodb",name:"DynamoDB"},"client-sqs":{id:"sqs",name:"SQS"},"client-ses":{id:"ses",name:"SES"},"client-sesv2":{id:"ses",name:"SES"},"client-s3":{id:"s3",name:"S3"},"client-eventbridge":{id:"eventbridge",name:"EventBridge"},"client-sns":{id:"sns",name:"SNS"},"client-secrets-manager":{id:"secrets",name:"Secrets Manager"},"client-scheduler":{id:"scheduler",name:"EventBridge Scheduler"},"client-apigatewaymanagementapi":{id:"apigw",name:"API Gateway"},"client-cloudwatch":{id:"cloudwatch",name:"CloudWatch"}},s=new Set;for(const c of Object.keys(e))for(const[h,A]of Object.entries(o))c.includes(h)&&!s.has(A.id)&&(s.add(A.id),k.push(A));k.sort((c,h)=>c.name.localeCompare(h.name))}const x=new Map;for(const e of[...d].sort()){const o=e.split("/")[0],s=x.get(o);s?s.push(e):x.set(o,[e])}const C=new Map;if(p?.symbols){const e=new Map;for(const s of p.symbols){const c=s.filePath.replace(/\\/g,"/"),h=z(c),A=c.match(/\.[^./]+$/)?.[0]||"";e.has(h)||e.set(h,new Map);const E=e.get(h);E.set(A,(E.get(A)??0)+1)}const o={".ts":"TypeScript",".tsx":"TypeScript",".js":"JavaScript",".jsx":"JavaScript",".java":"Java",".kt":"Kotlin",".scala":"Scala",".py":"Python",".go":"Go",".rs":"Rust",".cs":"C#",".rb":"Ruby",".php":"PHP",".swift":"Swift"};for(const[s,c]of e){let h="",A=0;for(const[E,O]of c)O>A&&(A=O,h=E);C.set(s,o[h]||"TypeScript")}}const l=e=>e.replace(/[^a-zA-Z0-9]/g,"_"),r=[];r.push("```mermaid"),r.push("C4Container"),r.push(` title C4 Container: ${t}`),r.push("");const w=e=>{const o=[],s=b.get(e);s&&(o.push(`${s.count} handlers`),s.triggers.size>0&&o.push([...s.triggers].join(", ")));const c=y.get(e);return c&&o.push(`${c} exports`),o.join(" \xB7 ")||""},D=e=>{const o=C.get(e)||"TypeScript";if(e.startsWith("infra"))return`CDK/${o}`;if(b.has(e)){const s=b.get(e);if(s?.triggers.has("SQS")||s?.triggers.has("SNS")||s?.triggers.has("API Gateway"))return`Lambda/${o}`;if(s?.triggers.has("HTTP Server")||s?.triggers.has("HTTP Endpoint"))return`Spring Boot/${o}`}return o};for(const[e,o]of[...x.entries()].sort()){const c=new Set(["com","org","net","io","dev","src"]).has(e)?t.charAt(0).toUpperCase()+t.slice(1):e.charAt(0).toUpperCase()+e.slice(1);if(o.length===1&&o[0]===e){const h=o[0];r.push(` Container(${l(h)}, "${h}", "${D(h)}", "${w(h)}")`)}else{r.push(` System_Boundary(${l(e)}_boundary, "${c}") {`);for(const h of o){const A=h.split("/").slice(1).join("/")||h;r.push(` Container(${l(h)}, "${A}", "${D(h)}", "${w(h)}")`)}r.push(" }")}r.push("")}if(k.length>0){for(const e of k)r.push(` System_Ext(ext_${e.id}, "${e.name}", "AWS")`);r.push("")}const P=[...i.entries()].sort((e,o)=>o[1]-e[1]);for(const[e,o]of P.slice(0,30)){const[s,c]=e.split("|");r.push(` Rel(${l(s)}, ${l(c)}, "Uses", "${o} calls")`)}r.push("```");const T=`## C4 Container Diagram
11
+ No cross-package dependencies detected.`;const d=new Set;for(const e of i.keys()){const[o,s]=e.split("|");d.add(o),d.add(s)}const y=new Map;if(p?.symbols)for(const e of p.symbols){if(!e.exported)continue;const o=e.filePath.replace(/\\/g,"/");if(R(o))continue;const s=z(o);y.set(s,(y.get(s)??0)+1)}const $=new Map;if(n?.entryPoints)for(const e of n.entryPoints){const o=e.filePath.replace(/\\/g,"/"),s=z(o),c=$.get(s);c?(c.count++,e.trigger&&c.triggers.add(e.trigger)):$.set(s,{count:1,triggers:new Set(e.trigger?[e.trigger]:[])})}const b=[];if(a?.external){const e=a.external,o={"client-dynamodb":{id:"dynamodb",name:"DynamoDB"},"lib-dynamodb":{id:"dynamodb",name:"DynamoDB"},"client-sqs":{id:"sqs",name:"SQS"},"client-ses":{id:"ses",name:"SES"},"client-sesv2":{id:"ses",name:"SES"},"client-s3":{id:"s3",name:"S3"},"client-eventbridge":{id:"eventbridge",name:"EventBridge"},"client-sns":{id:"sns",name:"SNS"},"client-secrets-manager":{id:"secrets",name:"Secrets Manager"},"client-scheduler":{id:"scheduler",name:"EventBridge Scheduler"},"client-apigatewaymanagementapi":{id:"apigw",name:"API Gateway"},"client-cloudwatch":{id:"cloudwatch",name:"CloudWatch"}},s=new Set;for(const c of Object.keys(e))for(const[h,A]of Object.entries(o))c.includes(h)&&!s.has(A.id)&&(s.add(A.id),b.push(A));b.sort((c,h)=>c.name.localeCompare(h.name))}const M=new Map;for(const e of[...d].sort()){const o=e.split("/")[0],s=M.get(o);s?s.push(e):M.set(o,[e])}const C=new Map;if(p?.symbols){const e=new Map;for(const s of p.symbols){const c=s.filePath.replace(/\\/g,"/"),h=z(c),A=c.match(/\.[^./]+$/)?.[0]||"";e.has(h)||e.set(h,new Map);const E=e.get(h);E.set(A,(E.get(A)??0)+1)}const o={".ts":"TypeScript",".tsx":"TypeScript",".js":"JavaScript",".jsx":"JavaScript",".java":"Java",".kt":"Kotlin",".scala":"Scala",".py":"Python",".go":"Go",".rs":"Rust",".cs":"C#",".rb":"Ruby",".php":"PHP",".swift":"Swift"};for(const[s,c]of e){let h="",A=0;for(const[E,I]of c)I>A&&(A=I,h=E);C.set(s,o[h]||"TypeScript")}}const l=e=>e.replace(/[^a-zA-Z0-9]/g,"_"),r=[];r.push("```mermaid"),r.push("C4Container"),r.push(` title C4 Container: ${t}`),r.push("");const w=e=>{const o=[],s=$.get(e);s&&(o.push(`${s.count} handlers`),s.triggers.size>0&&o.push([...s.triggers].join(", ")));const c=y.get(e);return c&&o.push(`${c} exports`),o.join(" \xB7 ")||""},_=e=>{const o=C.get(e)||"TypeScript";if(e.startsWith("infra"))return`CDK/${o}`;if($.has(e)){const s=$.get(e);if(s?.triggers.has("SQS")||s?.triggers.has("SNS")||s?.triggers.has("API Gateway"))return`Lambda/${o}`;if(s?.triggers.has("HTTP Server")||s?.triggers.has("HTTP Endpoint"))return`Spring Boot/${o}`}return o};for(const[e,o]of[...M.entries()].sort()){const c=new Set(["com","org","net","io","dev","src"]).has(e)?t.charAt(0).toUpperCase()+t.slice(1):e.charAt(0).toUpperCase()+e.slice(1);if(o.length===1&&o[0]===e){const h=o[0];r.push(` Container(${l(h)}, "${h}", "${_(h)}", "${w(h)}")`)}else{r.push(` System_Boundary(${l(e)}_boundary, "${c}") {`);for(const h of o){const A=h.split("/").slice(1).join("/")||h;r.push(` Container(${l(h)}, "${A}", "${_(h)}", "${w(h)}")`)}r.push(" }")}r.push("")}if(b.length>0){for(const e of b)r.push(` System_Ext(ext_${e.id}, "${e.name}", "AWS")`);r.push("")}const P=[...i.entries()].sort((e,o)=>o[1]-e[1]);for(const[e,o]of P.slice(0,30)){const[s,c]=e.split("|");r.push(` Rel(${l(s)}, ${l(c)}, "Uses", "${o} calls")`)}r.push("```");const T=`## C4 Container Diagram
12
12
 
13
13
  ${r.join(`
14
- `)}`,$=[];$.push("```mermaid"),$.push("graph TB");const f=new Set;for(const[,e]of b)for(const o of e.triggers)f.add(o);if(f.size>0){$.push(' subgraph Triggers["External Triggers"]');for(const e of[...f].sort()){const o=`trigger_${e.replace(/[^a-zA-Z0-9]/g,"_")}`;$.push(` ${o}(("${e}"))`)}$.push(" end"),$.push("")}const _=[...d].filter(e=>b.has(e)).sort(),v=[...d].filter(e=>!b.has(e)).sort();if(_.length>0){$.push(' subgraph Services["Service Layer"]');for(const e of _){const o=`flow_${l(e)}`,s=e.includes("/")?e.split("/").pop()??e:e,c=b.get(e);$.push(` ${o}["${s} (${c?.count??0} handlers)"]`)}$.push(" end"),$.push("")}if(v.length>0){$.push(' subgraph Libraries["Shared Libraries"]');for(const e of v){const o=`flow_${l(e)}`,s=e.includes("/")?e.split("/").pop()??e:e;$.push(` ${o}["${s}"]`)}$.push(" end"),$.push("")}if(k.length>0){$.push(' subgraph External["AWS Services"]');for(const e of k)$.push(` flow_ext_${e.id}[("${e.name}")]`);$.push(" end"),$.push("")}for(const e of _){const o=b.get(e);if(!o)continue;const s=`flow_${l(e)}`;for(const c of o.triggers){const h=`trigger_${c.replace(/[^a-zA-Z0-9]/g,"_")}`;$.push(` ${h} --> ${s}`)}}const M=P.filter(([e])=>{const[o,s]=e.split("|");return b.has(o)&&!b.has(s)});for(const[e,o]of M.slice(0,15)){const[s,c]=e.split("|");$.push(` flow_${l(s)} -->|${o}| flow_${l(c)}`)}const j=P.filter(([e])=>{const[o,s]=e.split("|");return!b.has(o)&&!b.has(s)});for(const[e,o]of j.slice(0,10)){const[s,c]=e.split("|");$.push(` flow_${l(s)} -->|${o}| flow_${l(c)}`)}$.push("```");const m=`## Architectural Flow
14
+ `)}`,k=[];k.push("```mermaid"),k.push("graph TB");const f=new Set;for(const[,e]of $)for(const o of e.triggers)f.add(o);if(f.size>0){k.push(' subgraph Triggers["External Triggers"]');for(const e of[...f].sort()){const o=`trigger_${e.replace(/[^a-zA-Z0-9]/g,"_")}`;k.push(` ${o}(("${e}"))`)}k.push(" end"),k.push("")}const x=[...d].filter(e=>$.has(e)).sort(),v=[...d].filter(e=>!$.has(e)).sort();if(x.length>0){k.push(' subgraph Services["Service Layer"]');for(const e of x){const o=`flow_${l(e)}`,s=e.includes("/")?e.split("/").pop()??e:e,c=$.get(e);k.push(` ${o}["${s} (${c?.count??0} handlers)"]`)}k.push(" end"),k.push("")}if(v.length>0){k.push(' subgraph Libraries["Shared Libraries"]');for(const e of v){const o=`flow_${l(e)}`,s=e.includes("/")?e.split("/").pop()??e:e;k.push(` ${o}["${s}"]`)}k.push(" end"),k.push("")}if(b.length>0){k.push(' subgraph External["AWS Services"]');for(const e of b)k.push(` flow_ext_${e.id}[("${e.name}")]`);k.push(" end"),k.push("")}for(const e of x){const o=$.get(e);if(!o)continue;const s=`flow_${l(e)}`;for(const c of o.triggers){const h=`trigger_${c.replace(/[^a-zA-Z0-9]/g,"_")}`;k.push(` ${h} --> ${s}`)}}const j=P.filter(([e])=>{const[o,s]=e.split("|");return $.has(o)&&!$.has(s)});for(const[e,o]of j.slice(0,15)){const[s,c]=e.split("|");k.push(` flow_${l(s)} -->|${o}| flow_${l(c)}`)}const D=P.filter(([e])=>{const[o,s]=e.split("|");return!$.has(o)&&!$.has(s)});for(const[e,o]of D.slice(0,10)){const[s,c]=e.split("|");k.push(` flow_${l(s)} -->|${o}| flow_${l(c)}`)}k.push("```");const m=`## Architectural Flow
15
15
 
16
- ${$.join(`
16
+ ${k.join(`
17
17
  `)}`,S=[`# Architecture Diagrams: ${t}
18
18
  `];return S.push(T),S.push(m),S.join(`
19
19
 
20
20
  ---
21
21
 
22
- `)}function ue(g,u){if(u.has(g))return g;for(const t of[".ts",".tsx",".js",".jsx"])if(u.has(`${g}${t}`))return`${g}${t}`;return u.has(`${g}/index.ts`)?`${g}/index.ts`:g}const ge=new Set(["node_modules",".git","dist","build","coverage",".turbo",".cache","cdk.out","__pycache__",".venv","target","obj",".gradle"]),G=[{glob:/\.env(?:\.\w+)?$/,type:"env"},{glob:/\.env\.example$/,type:"env"},{glob:/package\.json$/,type:"package-json"},{glob:/^(?:app|config|settings|default)\.(?:json|ya?ml|toml)$/i,type:"config"},{glob:/docker-compose\.ya?ml$/,type:"docker"},{glob:/cdk\.json$/,type:"cdk"},{glob:/turbo\.json$/,type:"tooling"},{glob:/application\.(?:properties|ya?ml)$/i,type:"spring"},{glob:/settings\.py$/,type:"django"},{glob:/\.flaskenv$/,type:"env"},{glob:/appsettings\.(?:\w+\.)?json$/i,type:"dotnet"}];async function pe(g,u){const t=[],p=await fe(g),n=/kb\.config\.json$/;for(const a of p)try{const i=H(g,a).replace(/\\/g,"/");if(n.test(i))continue;const d=await Z(a,"utf-8"),y=de(a);if(i.split("/").length-1>1&&y==="tooling")continue;const k=he(d,y);k.length>0&&t.push({file:i,type:y,values:k})}catch{}return me(t,u)}async function fe(g){const u=[],t=async(p,n)=>{if(!(n>3))try{const a=await J(p,{withFileTypes:!0});for(const i of a){if(ge.has(i.name))continue;const d=K(p,i.name);i.isDirectory()&&!i.name.startsWith(".")?await t(d,n+1):i.isFile()&&G.some(y=>y.glob.test(i.name))&&u.push(d)}}catch{}};return await t(g,0),u}function de(g){const u=L(g);for(const t of G)if(t.glob.test(u))return t.type;return"unknown"}const B=/(?:secret|password|token|key|api.?key|auth|credential|private)/i;function he(g,u){const t=[];if(u==="env")for(const p of g.split(`
23
- `)){const n=p.trim();if(!n||n.startsWith("#"))continue;const a=n.indexOf("=");if(a===-1)continue;const i=n.slice(0,a).trim(),d=n.slice(a+1).trim(),y=B.test(i);t.push({key:i,value:y?"***":d,sensitive:y})}else if(u==="package-json")try{const p=JSON.parse(g);if(p.scripts)for(const[n,a]of Object.entries(p.scripts))t.push({key:`scripts.${n}`,value:String(a),sensitive:!1});if(p.engines)for(const[n,a]of Object.entries(p.engines))t.push({key:`engines.${n}`,value:String(a),sensitive:!1})}catch{}else if(u==="spring")for(const p of g.split(`
24
- `)){const n=p.trim();if(!n||n.startsWith("#")||n.startsWith("---"))continue;const a=n.match(/^([\w.[\]-]+)\s*[=:]\s*(.*)$/);if(a){const i=a[1],d=a[2].trim(),y=B.test(i);t.push({key:i,value:y?"***":d,sensitive:y})}}else if(u==="json"||u==="config"||u==="cdk"||u==="tooling"||u==="dotnet")try{const p=JSON.parse(g);F(p,"",t,0)}catch{}else if(u==="django")for(const p of g.split(`
25
- `)){const n=p.match(/^([A-Z_][A-Z0-9_]*)\s*=\s*(.+)$/);if(n){const a=n[1],i=n[2].trim(),d=B.test(a);t.push({key:a,value:d?"***":i.slice(0,100),sensitive:d})}}return t}function F(g,u,t,p){if(!(p>3)&&g!=null&&typeof g=="object"&&!Array.isArray(g))for(const[n,a]of Object.entries(g)){const i=u?`${u}.${n}`:n;if(typeof a=="object"&&a!==null&&!Array.isArray(a))F(a,i,t,p+1);else{const d=B.test(n),y=Array.isArray(a)?`[${a.length} items]`:String(a);t.push({key:i,value:d?"***":y.slice(0,120),sensitive:d})}}}function me(g,u){const t=[];if(t.push(`## Configuration Values: ${u}
22
+ `)}function ue(g,u){if(u.has(g))return g;for(const t of[".ts",".tsx",".js",".jsx"])if(u.has(`${g}${t}`))return`${g}${t}`;return u.has(`${g}/index.ts`)?`${g}/index.ts`:g}const ge=new Set(["node_modules",".git","dist","build","coverage",".turbo",".cache","cdk.out","__pycache__",".venv","target","obj",".gradle"]),G=[{glob:/\.env(?:\.\w+)?$/,type:"env"},{glob:/\.env\.example$/,type:"env"},{glob:/package\.json$/,type:"package-json"},{glob:/^(?:app|config|settings|default)\.(?:json|ya?ml|toml)$/i,type:"config"},{glob:/docker-compose\.ya?ml$/,type:"docker"},{glob:/cdk\.json$/,type:"cdk"},{glob:/turbo\.json$/,type:"tooling"},{glob:/application\.(?:properties|ya?ml)$/i,type:"spring"},{glob:/settings\.py$/,type:"django"},{glob:/\.flaskenv$/,type:"env"},{glob:/appsettings\.(?:\w+\.)?json$/i,type:"dotnet"}];async function pe(g,u){const t=[],p=await fe(g),n=/kb\.config\.json$/;for(const a of p)try{const i=H(g,a).replace(/\\/g,"/");if(n.test(i))continue;const d=await Z(a,"utf-8"),y=de(a);if(i.split("/").length-1>1&&y==="tooling")continue;const b=he(d,y);b.length>0&&t.push({file:i,type:y,values:b})}catch{}return me(t,u)}async function fe(g){const u=[],t=async(p,n)=>{if(!(n>3))try{const a=await J(p,{withFileTypes:!0});for(const i of a){if(ge.has(i.name))continue;const d=O(p,i.name);i.isDirectory()&&!i.name.startsWith(".")?await t(d,n+1):i.isFile()&&G.some(y=>y.glob.test(i.name))&&u.push(d)}}catch{}};return await t(g,0),u}function de(g){const u=N(g);for(const t of G)if(t.glob.test(u))return t.type;return"unknown"}const K=/(?:secret|password|token|key|api.?key|auth|credential|private)/i;function he(g,u){const t=[];if(u==="env")for(const p of g.split(`
23
+ `)){const n=p.trim();if(!n||n.startsWith("#"))continue;const a=n.indexOf("=");if(a===-1)continue;const i=n.slice(0,a).trim(),d=n.slice(a+1).trim(),y=K.test(i);t.push({key:i,value:y?"***":d,sensitive:y})}else if(u==="package-json")try{const p=JSON.parse(g);if(p.scripts)for(const[n,a]of Object.entries(p.scripts))t.push({key:`scripts.${n}`,value:String(a),sensitive:!1});if(p.engines)for(const[n,a]of Object.entries(p.engines))t.push({key:`engines.${n}`,value:String(a),sensitive:!1})}catch{}else if(u==="spring")for(const p of g.split(`
24
+ `)){const n=p.trim();if(!n||n.startsWith("#")||n.startsWith("---"))continue;const a=n.match(/^([\w.[\]-]+)\s*[=:]\s*(.*)$/);if(a){const i=a[1],d=a[2].trim(),y=K.test(i);t.push({key:i,value:y?"***":d,sensitive:y})}}else if(u==="json"||u==="config"||u==="cdk"||u==="tooling"||u==="dotnet")try{const p=JSON.parse(g);W(p,"",t,0)}catch{}else if(u==="django")for(const p of g.split(`
25
+ `)){const n=p.match(/^([A-Z_][A-Z0-9_]*)\s*=\s*(.+)$/);if(n){const a=n[1],i=n[2].trim(),d=K.test(a);t.push({key:a,value:d?"***":i.slice(0,100),sensitive:d})}}return t}function W(g,u,t,p){if(!(p>3)&&g!=null&&typeof g=="object"&&!Array.isArray(g))for(const[n,a]of Object.entries(g)){const i=u?`${u}.${n}`:n;if(typeof a=="object"&&a!==null&&!Array.isArray(a))W(a,i,t,p+1);else{const d=K.test(n),y=Array.isArray(a)?`[${a.length} items]`:String(a);t.push({key:i,value:d?"***":y.slice(0,120),sensitive:d})}}}function me(g,u){const t=[];if(t.push(`## Configuration Values: ${u}
26
26
  `),g.length===0)return t.push("No configuration files detected."),t.join(`
27
27
  `);t.push(`**${g.length} config files** found
28
28
  `);const p=new Map;for(const a of g)p.has(a.type)||p.set(a.type,[]),p.get(a.type)?.push(a);for(const[a,i]of p){if(a==="package-json"&&i.length>2){t.push(`### ${a}
29
- `);const d=i.find(b=>b.file==="package.json");if(d){t.push(`#### ${d.file}
30
- `),t.push("| Key | Value | Sensitive |"),t.push("|-----|-------|-----------|");for(const b of d.values.slice(0,50)){const k=b.value.replace(/\|/g,"\\|");t.push(`| ${b.key} | ${k} | ${b.sensitive?"\u26A0\uFE0F yes":"no"} |`)}t.push("")}const y=i.filter(b=>b.file!=="package.json");if(y.length>0){const b=new Map;for(const l of y)for(const r of l.values){const w=`${r.key}=${r.value}`;b.set(w,(b.get(w)??0)+1)}const k=Math.max(2,Math.floor(y.length*.5));t.push(`#### Sub-packages (${y.length} packages)
31
- `);const x=[...b.entries()].filter(([,l])=>l>=k).map(([l])=>{const[r,...w]=l.split("=");return{key:r,value:w.join("=")}});if(x.length>0){t.push(`**Common scripts** (shared by most sub-packages):
32
- `),t.push("| Key | Value |"),t.push("|-----|-------|");for(const l of x)t.push(`| ${l.key} | ${l.value.replace(/\|/g,"\\|")} |`);t.push("")}const C=new Map;for(const l of y){const r=l.values.filter(P=>{const T=`${P.key}=${P.value}`;return(b.get(T)??0)<k});if(r.length===0)continue;const w=r.map(P=>`${P.key}=${P.value}`).sort().join("||"),D=C.get(w);D?D.files.push(l.file):C.set(w,{files:[l.file],entries:r.map(P=>({key:P.key,value:P.value}))})}for(const[,l]of C){l.files.length>1?t.push(`**${l.files.length} packages** (${l.files.map(r=>r.split("/").slice(-2,-1)[0]||r).join(", ")}):`):t.push(`**${l.files[0]}**:`),t.push("| Key | Value |"),t.push("|-----|-------|");for(const r of l.entries)t.push(`| ${r.key} | ${r.value.replace(/\|/g,"\\|")} |`);t.push("")}}continue}if(i.length>3){const d=i.map(k=>k.values.map(x=>`${x.key}=${x.value}`).sort().join("||")),y=d.sort((k,x)=>d.filter(C=>C===x).length-d.filter(C=>C===k).length)[0];if(d.filter(k=>k===y).length>2){t.push(`### ${a}
33
- `);const k=i[d.indexOf(y)],x=i.filter((l,r)=>d[r]===y).map(l=>l.file),C=i.filter((l,r)=>d[r]!==y);t.push(`**${x.length} identical files**: ${x.join(", ")}
34
- `),t.push("| Key | Value | Sensitive |"),t.push("|-----|-------|-----------|");for(const l of k.values.slice(0,30)){const r=l.value.replace(/\|/g,"\\|");t.push(`| ${l.key} | ${r} | ${l.sensitive?"\u26A0\uFE0F yes":"no"} |`)}t.push("");for(const l of C){t.push(`#### ${l.file}
29
+ `);const d=i.find($=>$.file==="package.json");if(d){t.push(`#### ${d.file}
30
+ `),t.push("| Key | Value | Sensitive |"),t.push("|-----|-------|-----------|");for(const $ of d.values.slice(0,50)){const b=$.value.replace(/\|/g,"\\|");t.push(`| ${$.key} | ${b} | ${$.sensitive?"\u26A0\uFE0F yes":"no"} |`)}t.push("")}const y=i.filter($=>$.file!=="package.json");if(y.length>0){const $=new Map;for(const l of y)for(const r of l.values){const w=`${r.key}=${r.value}`;$.set(w,($.get(w)??0)+1)}const b=Math.max(2,Math.floor(y.length*.5));t.push(`#### Sub-packages (${y.length} packages)
31
+ `);const M=[...$.entries()].filter(([,l])=>l>=b).map(([l])=>{const[r,...w]=l.split("=");return{key:r,value:w.join("=")}});if(M.length>0){t.push(`**Common scripts** (shared by most sub-packages):
32
+ `),t.push("| Key | Value |"),t.push("|-----|-------|");for(const l of M)t.push(`| ${l.key} | ${l.value.replace(/\|/g,"\\|")} |`);t.push("")}const C=new Map;for(const l of y){const r=l.values.filter(P=>{const T=`${P.key}=${P.value}`;return($.get(T)??0)<b});if(r.length===0)continue;const w=r.map(P=>`${P.key}=${P.value}`).sort().join("||"),_=C.get(w);_?_.files.push(l.file):C.set(w,{files:[l.file],entries:r.map(P=>({key:P.key,value:P.value}))})}for(const[,l]of C){l.files.length>1?t.push(`**${l.files.length} packages** (${l.files.map(r=>r.split("/").slice(-2,-1)[0]||r).join(", ")}):`):t.push(`**${l.files[0]}**:`),t.push("| Key | Value |"),t.push("|-----|-------|");for(const r of l.entries)t.push(`| ${r.key} | ${r.value.replace(/\|/g,"\\|")} |`);t.push("")}}continue}if(i.length>3){const d=i.map(b=>b.values.map(M=>`${M.key}=${M.value}`).sort().join("||")),y=d.sort((b,M)=>d.filter(C=>C===M).length-d.filter(C=>C===b).length)[0];if(d.filter(b=>b===y).length>2){t.push(`### ${a}
33
+ `);const b=i[d.indexOf(y)],M=i.filter((l,r)=>d[r]===y).map(l=>l.file),C=i.filter((l,r)=>d[r]!==y);t.push(`**${M.length} identical files**: ${M.join(", ")}
34
+ `),t.push("| Key | Value | Sensitive |"),t.push("|-----|-------|-----------|");for(const l of b.values.slice(0,30)){const r=l.value.replace(/\|/g,"\\|");t.push(`| ${l.key} | ${r} | ${l.sensitive?"\u26A0\uFE0F yes":"no"} |`)}t.push("");for(const l of C){t.push(`#### ${l.file}
35
35
  `),t.push("| Key | Value | Sensitive |"),t.push("|-----|-------|-----------|");for(const r of l.values.slice(0,30)){const w=r.value.replace(/\|/g,"\\|");t.push(`| ${r.key} | ${w} | ${r.sensitive?"\u26A0\uFE0F yes":"no"} |`)}t.push("")}continue}}t.push(`### ${a}
36
36
  `);for(const d of i){t.push(`#### ${d.file}
37
- `),t.push("| Key | Value | Sensitive |"),t.push("|-----|-------|-----------|");for(const y of d.values.slice(0,50)){const b=y.value.replace(/\|/g,"\\|");t.push(`| ${y.key} | ${b} | ${y.sensitive?"\u26A0\uFE0F yes":"no"} |`)}d.values.length>50&&t.push(`
37
+ `),t.push("| Key | Value | Sensitive |"),t.push("|-----|-------|-----------|");for(const y of d.values.slice(0,50)){const $=y.value.replace(/\|/g,"\\|");t.push(`| ${y.key} | ${$} | ${y.sensitive?"\u26A0\uFE0F yes":"no"} |`)}d.values.length>50&&t.push(`
38
38
  _...and ${d.values.length-50} more values._`),t.push("")}}const n=g.reduce((a,i)=>a+i.values.filter(d=>d.sensitive).length,0);return n>0&&t.push(`
39
39
  **\u26A0\uFE0F ${n} sensitive values detected** (values masked).`),t.join(`
40
- `)}async function ve(g){const u=Date.now(),t=Q(g.path),p=L(t),n=g.mode??"memory",a=g.outDir??K(t,".ai","kb"),i=new oe,d=new X,y=new re,b=new ne,k=new ee,x=new Y,C=[{name:"structure",fn:()=>i.analyze(t,{format:"markdown",maxDepth:3,sourceOnly:!0})},{name:"dependencies",fn:()=>d.analyze(t,{format:"markdown"})},{name:"entry-points",fn:()=>k.analyze(t)},{name:"symbols",fn:()=>y.analyze(t,{format:"markdown"})},{name:"patterns",fn:()=>b.analyze(t)},{name:"diagram",fn:()=>x.analyze(t,{diagramType:"architecture"})}],l=await Promise.allSettled(C.map(async e=>{const o=Date.now(),s=await e.fn();return{name:e.name,result:s,durationMs:Date.now()-o}})),r=[],w=new Map,D=new Map;for(const e of l)if(e.status==="fulfilled"){const{name:o,result:s,durationMs:c}=e.value,h=s;r.push({name:o,status:"success",output:h.output,durationMs:c}),w.set(o,h.output),D.set(o,h.data)}else{const o=e.reason,s=l.indexOf(e),c=C[s].name;r.push({name:c,status:"failed",output:"",durationMs:0,error:o.message})}const P=Date.now();let T=null;try{let e=await se(t);if((!e||e.edges.length===0)&&(e=await te(t)),e&&e.edges.length>0){T=new Map;for(const o of e.edges){let s=T.get(o.from);s||(s=new Map,T.set(o.from,s));const c=s.get(o.to);if(c)for(const h of o.symbols)c.includes(h)||c.push(h);else s.set(o.to,[...o.symbols])}}}catch{}const $=Date.now()-P,f=Date.now(),_=ce(D,p,T),v=Date.now()-f+$;if(r.push({name:"code-map",status:"success",output:_,durationMs:v}),w.set("code-map",_),T&&T.size>0){const e=le(T,D,p),o=r.find(s=>s.name==="diagram");o&&(o.output=e,w.set("diagram",e))}const M=Date.now(),j=await pe(t,p),m=Date.now()-M;r.push({name:"config-values",status:"success",output:j,durationMs:m}),w.set("config-values",j);const S=ie(r,n,p,D);if(r.push({name:"synthesis-guide",status:"success",output:S,durationMs:0}),w.set("synthesis-guide",S),n==="generate"){if(W(a))for(const s of q(a))(s.endsWith(".md")||s.endsWith(".json"))&&U(K(a,s),{force:!0});V(a,{recursive:!0});const e=new Date().toISOString();for(const[s,c]of w){const h=`${s}.md`,A=K(a,h),E=c.replaceAll(t,p),O=`<!-- Generated: ${e} -->
40
+ `)}async function ve(g){const u=Date.now(),t=Q(g.path),p=N(t),n=g.mode??"memory",a=g.outDir??O(t,".ai","kb"),i=new oe,d=new X,y=new re,$=new ne,b=new ee,M=new Y,C=[{name:"structure",fn:()=>i.analyze(t,{format:"markdown",maxDepth:3,sourceOnly:!0})},{name:"dependencies",fn:()=>d.analyze(t,{format:"markdown"})},{name:"entry-points",fn:()=>b.analyze(t)},{name:"symbols",fn:()=>y.analyze(t,{format:"markdown"})},{name:"patterns",fn:()=>$.analyze(t)},{name:"diagram",fn:()=>M.analyze(t,{diagramType:"architecture"})}],l=await Promise.allSettled(C.map(async e=>{const o=Date.now(),s=await e.fn();return{name:e.name,result:s,durationMs:Date.now()-o}})),r=[],w=new Map,_=new Map;for(const e of l)if(e.status==="fulfilled"){const{name:o,result:s,durationMs:c}=e.value,h=s;r.push({name:o,status:"success",output:h.output,durationMs:c}),w.set(o,h.output),_.set(o,h.data)}else{const o=e.reason,s=l.indexOf(e),c=C[s].name;r.push({name:c,status:"failed",output:"",durationMs:0,error:o.message})}const P=Date.now();let T=null;try{let e=await se(t);if((!e||e.edges.length===0)&&(e=await te(t)),e&&e.edges.length>0){T=new Map;for(const o of e.edges){let s=T.get(o.from);s||(s=new Map,T.set(o.from,s));const c=s.get(o.to);if(c)for(const h of o.symbols)c.includes(h)||c.push(h);else s.set(o.to,[...o.symbols])}}}catch{}const k=Date.now()-P,f=Date.now(),x=ce(_,p,T),v=Date.now()-f+k;if(r.push({name:"code-map",status:"success",output:x,durationMs:v}),w.set("code-map",x),T&&T.size>0){const e=le(T,_,p),o=r.find(s=>s.name==="diagram");o&&(o.output=e,w.set("diagram",e))}const j=Date.now(),D=await pe(t,p),m=Date.now()-j;r.push({name:"config-values",status:"success",output:D,durationMs:m}),w.set("config-values",D);const S=ie(r,n,p,_);if(r.push({name:"synthesis-guide",status:"success",output:S,durationMs:0}),w.set("synthesis-guide",S),n==="generate"){if(F(a))for(const s of q(a))(s.endsWith(".md")||s.endsWith(".json"))&&U(O(a,s),{force:!0});V(a,{recursive:!0});const e=new Date().toISOString();for(const[s,c]of w){const h=`${s}.md`,A=O(a,h),E=c.replaceAll(t,p),I=`<!-- Generated: ${e} -->
41
41
  <!-- Project: ${p} -->
42
42
  <!-- Source: ${t} -->
43
43
 
44
- `;I(A,O+E,"utf-8")}const o=[`<!-- Generated: ${e} -->`,`<!-- Project: ${p} -->`,`<!-- Source: ${t} -->`,"",`# ${p} \u2014 Codebase Knowledge`,"","## Contents",""];for(const s of r){const c=`${s.name}.md`,h=N[s.name]??s.name,A=s.status==="success"?"\u2713":"\u2717",E=s.durationMs>0?` (${s.durationMs}ms)`:"";o.push(`- ${A} [${h}](./${c})${E}`)}o.push(""),I(K(a,"README.md"),o.join(`
44
+ `;B(A,I+E,"utf-8")}const o=[`<!-- Generated: ${e} -->`,`<!-- Project: ${p} -->`,`<!-- Source: ${t} -->`,"",`# ${p} \u2014 Codebase Knowledge`,"","## Contents",""];for(const s of r){const c=`${s.name}.md`,h=L[s.name]??s.name,A=s.status==="success"?"\u2713":"\u2717",E=s.durationMs>0?` (${s.durationMs}ms)`:"";o.push(`- ${A} [${h}](./${c})${E}`)}o.push(""),B(O(a,"README.md"),o.join(`
45
45
  `),"utf-8")}return{path:t,mode:n,steps:r,outDir:n==="generate"?a:void 0,totalDurationMs:Date.now()-u}}export{ve as onboard};