@vpxa/kb 0.1.11 → 0.1.13

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 (58) hide show
  1. package/README.md +48 -37
  2. package/package.json +1 -1
  3. package/packages/analyzers/dist/entry-point-analyzer.d.ts +18 -0
  4. package/packages/analyzers/dist/entry-point-analyzer.js +6 -5
  5. package/packages/analyzers/dist/pattern-analyzer.js +1 -1
  6. package/packages/analyzers/dist/types.d.ts +1 -1
  7. package/packages/cli/dist/commands/init.d.ts +2 -1
  8. package/packages/cli/dist/commands/init.js +242 -183
  9. package/packages/cli/dist/commands/knowledge.js +1 -1
  10. package/packages/cli/dist/commands/system.js +6 -3
  11. package/packages/cli/dist/helpers.js +5 -3
  12. package/packages/core/dist/content-detector.d.ts +5 -1
  13. package/packages/core/dist/content-detector.js +1 -1
  14. package/packages/core/dist/index.d.ts +1 -1
  15. package/packages/core/dist/index.js +1 -1
  16. package/packages/core/dist/types.d.ts +2 -0
  17. package/packages/server/dist/index.js +1 -1
  18. package/packages/server/dist/server.d.ts +0 -13
  19. package/packages/server/dist/server.js +1 -1
  20. package/packages/server/dist/tools/analyze.tools.js +3 -1
  21. package/packages/server/dist/tools/audit.tool.d.ts +5 -0
  22. package/packages/server/dist/tools/audit.tool.js +4 -0
  23. package/packages/server/dist/tools/replay.tool.js +4 -4
  24. package/packages/server/dist/tools/search.tool.js +18 -14
  25. package/packages/server/dist/tools/status.tool.js +3 -3
  26. package/packages/server/dist/tools/toolkit.tools.d.ts +1 -1
  27. package/packages/server/dist/tools/toolkit.tools.js +23 -20
  28. package/packages/server/dist/version-check.d.ts +10 -0
  29. package/packages/server/dist/version-check.js +1 -0
  30. package/packages/store/dist/lance-store.js +1 -1
  31. package/packages/store/dist/store.interface.d.ts +2 -0
  32. package/packages/tools/dist/audit.d.ts +66 -0
  33. package/packages/tools/dist/audit.js +7 -0
  34. package/packages/tools/dist/check.d.ts +19 -0
  35. package/packages/tools/dist/check.js +2 -2
  36. package/packages/tools/dist/compact.d.ts +4 -2
  37. package/packages/tools/dist/compact.js +2 -2
  38. package/packages/tools/dist/dead-symbols.d.ts +9 -1
  39. package/packages/tools/dist/dead-symbols.js +2 -2
  40. package/packages/tools/dist/forge-classify.js +1 -1
  41. package/packages/tools/dist/guide.d.ts +23 -0
  42. package/packages/tools/dist/guide.js +1 -0
  43. package/packages/tools/dist/health.js +2 -1
  44. package/packages/tools/dist/index.d.ts +6 -2
  45. package/packages/tools/dist/index.js +1 -1
  46. package/packages/tools/dist/path-resolver.d.ts +12 -0
  47. package/packages/tools/dist/path-resolver.js +1 -0
  48. package/packages/tools/dist/replay.d.ts +1 -1
  49. package/packages/tools/dist/response-envelope.d.ts +41 -0
  50. package/packages/tools/dist/response-envelope.js +1 -0
  51. package/packages/tools/dist/scope-map.d.ts +2 -0
  52. package/packages/tools/dist/scope-map.js +1 -1
  53. package/packages/tools/dist/truncation.d.ts +9 -0
  54. package/packages/tools/dist/truncation.js +8 -8
  55. package/packages/tui/dist/App.js +109 -109
  56. package/packages/tui/dist/index.js +116 -116
  57. package/packages/tui/dist/panels/LogPanel.js +100 -100
  58. package/skills/knowledge-base/SKILL.md +19 -19
@@ -1,147 +1,92 @@
1
- import{appendFileSync as p,existsSync as o,mkdirSync as u,readFileSync as m,writeFileSync as a}from"node:fs";import{basename as g,resolve as t}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"}};function f(e){return{servers:{[`${e}-kb`]:{type:"stdio",command:"npx",args:["@vpxa/kb","serve"]}}}}function y(e){return`# ${e} \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 **${e}**, 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(e){return`# ${e} \u2014 Agent Instructions
1
+ import{appendFileSync as h,copyFileSync as y,existsSync as t,mkdirSync as n,readFileSync as v,writeFileSync as r}from"node:fs";import{basename as w,dirname as S,resolve as e}from"node:path";import{fileURLToPath as x}from"node:url";const C={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"}};function A(o){return{servers:{[`${o}-kb`]:{type:"stdio",command:"npx",args:["@vpxa/kb","serve"]}}}}function T(o){return`# ${o} \u2014 Copilot Instructions
2
+
3
+ This project uses **@vpxa/kb** as an MCP knowledge base server. The KB provides search, context compression, persistent memory, and validation tools that **MUST** be used to maintain quality and performance.
4
+
5
+ ## Mandatory Rules
6
+
7
+ ### 1. ALWAYS search before acting
8
+ Before writing or modifying code, you MUST recall prior decisions and understand the affected area:
9
+ \`\`\`
10
+ kb_search({ query: "<task keywords>" })
11
+ kb_scope_map({ task: "<what you are doing>" })
12
+ \`\`\`
13
+
14
+ ### 2. ALWAYS compress context before reading large files
15
+ Do NOT read entire files into context. Use these tools to reduce tokens and focus on what matters:
16
+
17
+ | Situation | Tool | Why |
18
+ |-----------|------|-----|
19
+ | Need relevant sections of a large file | \`kb_compact\` | Extracts only semantically relevant chunks \u2014 5-20x reduction |
20
+ | Need to summarize multiple sources | \`kb_digest\` | Compresses multiple text blocks into a token-budgeted summary |
21
+ | Need a quick structural overview of a file | \`kb_file_summary\` | Returns exports, imports, functions without reading the full file |
22
+ | Need a reusable context card | \`kb_stratum_card\` | Generates T1/T2 cards \u2014 10-100x token reduction |
23
+
24
+ **Example \u2014 reading a 400-line file:**
25
+ \`\`\`
26
+ # BAD: read_file entire file (wastes ~3000 tokens)
27
+ # GOOD: get structure first, then compact only what you need
28
+ kb_file_summary({ path: "src/http-client.ts" })
29
+ kb_compact({ path: "src/http-client.ts", query: "retry logic" })
30
+ \`\`\`
31
+
32
+ ### 3. ALWAYS use persistent memory
33
+ - **Start of session**: Read prior knowledge with \`kb_list()\` and \`kb_search({ query: "SESSION CHECKPOINT", origin: "curated" })\`
34
+ - **During session**: Use \`kb_stash\` for temporary working data, \`kb_checkpoint\` to save progress
35
+ - **End of session**: MUST call \`kb_remember\` to persist decisions, patterns, and lessons learned
36
+ - **Before proposing a new approach**: MUST \`kb_search\` to check if a decision already exists
37
+
38
+ | Tool | When | Persistence |
39
+ |------|------|-------------|
40
+ | \`kb_stash\` | Temporary data within a session (intermediate results, scratch notes) | Session only |
41
+ | \`kb_checkpoint\` | Save/restore session progress (resumable work) | Session only |
42
+ | \`kb_remember\` | Architecture decisions, conventions, patterns, troubleshooting | Permanent (survives reindex) |
43
+
44
+ ### 4. ALWAYS validate before committing
45
+ \`\`\`
46
+ kb_check({}) # Typecheck + lint (returns summary by default)
47
+ kb_test_run({}) # Run tests
48
+ kb_blast_radius({ changed_files: ["..."] }) # Impact analysis
49
+ kb_audit({}) # Unified project audit with score and recommendations
50
+ \`\`\`
51
+
52
+ ### 5. Use FORGE for complex tasks
53
+ For tasks involving multiple files or architectural decisions:
54
+ \`\`\`
55
+ kb_forge_classify({ task: "<description>" }) # Classify complexity tier
56
+ kb_forge_ground({ task: "<description>" }) # Full analysis: scope + constraints + evidence
57
+ kb_evidence_map({ claims: [...] }) # Track verified vs assumed claims
58
+ \`\`\`
59
+
60
+ ## Quick Workflow
61
+
62
+ \`\`\`
63
+ # 1. Orient
64
+ kb_search({ query: "task keywords" })
65
+ kb_scope_map({ task: "what you are doing" })
66
+
67
+ # 2. Read efficiently (NEVER raw-read large files)
68
+ kb_file_summary({ path: "relevant-file.ts" })
69
+ kb_compact({ path: "relevant-file.ts", query: "specific concern" })
70
+
71
+ # 3. Do the work
72
+
73
+ # 4. Validate
74
+ kb_check({})
75
+ kb_test_run({})
76
+
77
+ # 5. Persist
78
+ kb_remember({ title: "What I learned", content: "...", category: "decisions" })
79
+ \`\`\`
80
+
81
+ ## Context Budget Rules
82
+
83
+ - **Prefer \`kb_file_summary\` over \`read_file\`** for understanding file structure
84
+ - **Prefer \`kb_compact\` over full file reads** when you need specific sections (use \`path\` param to avoid read_file round-trip)
85
+ - **Prefer \`kb_search\` over \`grep_search\`** for semantic/conceptual queries
86
+ - **Prefer \`kb_symbol\` over manual grep** for finding definitions and references
87
+ - **Use \`kb_digest\`** when combining information from 3+ sources
88
+ - **Use \`kb_stratum_card\`** to create reusable compressed context for repeated reference
89
+ `}function P(o){return`# ${o} \u2014 Agent Instructions
145
90
 
146
91
  ## KB Knowledge Base
147
92
 
@@ -157,50 +102,140 @@ This project has a **@vpxa/kb** MCP server providing search, analysis, memory, a
157
102
 
158
103
  | Category | Tools | Purpose |
159
104
  |----------|-------|---------|
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 |
105
+ | Search & Discovery | \`kb_search\`, \`kb_find\`, \`kb_symbol\`, \`kb_trace\`, \`kb_scope_map\`, \`kb_lookup\`, \`kb_dead_symbols\`, \`kb_file_summary\` | Find code, symbols, data flow, reading plans |
161
106
  | 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
107
  | 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 |
108
+ | Execution | \`kb_check\`, \`kb_test_run\`, \`kb_eval\`, \`kb_batch\`, \`kb_audit\` | Typecheck, lint, test, run code, unified audit. \`check\` defaults to summary output (~300 tokens) |
164
109
  | 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 |
110
+ | Context | \`kb_compact\`, \`kb_workset\`, \`kb_stash\`, \`kb_checkpoint\`, \`kb_parse_output\` | Manage working sets, save progress. \`compact\` accepts \`path\` for server-side file read |
166
111
  | FORGE | \`kb_forge_ground\`, \`kb_forge_classify\`, \`kb_evidence_map\`, \`kb_digest\`, \`kb_stratum_card\` | Quality gates, context compression |
167
112
  | Web & API | \`kb_web_fetch\`, \`kb_web_search\`, \`kb_http\` | Fetch pages, search web, test APIs |
168
113
  | Lanes | \`kb_lane\` | Isolated file copies for parallel exploration (create/list/status/diff/merge/discard) |
169
114
  | Git & Environment | \`kb_git_context\`, \`kb_process\`, \`kb_watch\`, \`kb_delegate\` | Git info, process management |
170
115
  | 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 |
116
+ | System | \`kb_status\`, \`kb_reindex\`, \`kb_health\`, \`kb_guide\`, \`kb_onboard\`, \`kb_graph\`, \`kb_queue\`, \`kb_replay\` | Index management, health checks, tool discovery, knowledge graph |
117
+
118
+ ---
119
+
120
+ ## MANDATORY: Context Reduction Protocol
172
121
 
173
- ### Search Modes
122
+ **Every agent interaction MUST minimize context window usage.** Raw file reads waste tokens and degrade LLM output quality. Use these tools instead:
174
123
 
175
- The \`kb_search\` tool supports three search strategies via the \`search_mode\` parameter:
124
+ ### Decision Tree \u2014 How to Read Code
176
125
 
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.
126
+ \`\`\`
127
+ Need to understand a file?
128
+ \u251C\u2500 Just structure? \u2192 kb_file_summary (exports, imports, functions \u2014 ~50 tokens)
129
+ \u251C\u2500 Specific section? \u2192 kb_compact({ path: "file.ts", query: "topic" }) \u2014 5-20x reduction
130
+ \u251C\u2500 Multiple files? \u2192 kb_digest (multi-source compression \u2014 token-budgeted)
131
+ \u251C\u2500 Repeated reference? \u2192 kb_stratum_card (T1/T2 card \u2014 10-100x reduction)
132
+ \u2514\u2500 Full file needed? \u2192 ONLY as last resort, and compact it after reading
133
+ \`\`\`
134
+
135
+ ### Rules
136
+ 1. **NEVER read a file >100 lines without compressing it first**
137
+ 2. **ALWAYS use \`kb_file_summary\` before \`read_file\`** \u2014 often the summary is sufficient
138
+ 3. **ALWAYS use \`kb_compact\` when you only need specific sections** of a file (use \`path\` param to read server-side)
139
+ 4. **Use \`kb_digest\` when synthesizing from 3+ sources** \u2014 don't accumulate raw text
140
+ 5. **Use \`kb_stratum_card\` for files you'll reference repeatedly** in a session
141
+
142
+ ---
143
+
144
+ ## MANDATORY: Memory Protocol
145
+
146
+ **Every session MUST read and write persistent memory.** Without this, every conversation starts from zero.
147
+
148
+ ### Session Start (MUST do ALL of these)
149
+ \`\`\`
150
+ kb_status({}) # Verify KB is ready
151
+ kb_list() # See what knowledge exists
152
+ kb_search({ query: "SESSION CHECKPOINT", origin: "curated" }) # Resume prior work
153
+ \`\`\`
154
+
155
+ ### During Session
156
+ | Situation | Action |
157
+ |-----------|--------|
158
+ | Found a useful intermediate result | \`kb_stash({ key: "name", value: "data" })\` |
159
+ | Completed a milestone | \`kb_checkpoint({ action: "save", name: "milestone" })\` |
160
+ | Made an architecture decision | \`kb_remember({ title: "...", category: "decisions" })\` |
161
+ | Discovered a pattern or convention | \`kb_remember({ title: "...", category: "patterns" })\` |
162
+ | Found a non-obvious solution | \`kb_remember({ title: "...", category: "troubleshooting" })\` |
163
+ | About to propose a new approach | \`kb_search({ query: "..." })\` \u2014 check if decided before |
164
+
165
+ ### Session End (MUST do this)
166
+ \`\`\`
167
+ kb_remember({
168
+ title: "Session checkpoint: <topic>",
169
+ content: "<what was done, decisions made, blockers, next steps>",
170
+ category: "conventions"
171
+ })
172
+ \`\`\`
173
+
174
+ ### Memory Decision Tree
175
+ \`\`\`
176
+ Is this data temporary (scratch, intermediate)?
177
+ \u251C\u2500 Yes \u2192 kb_stash (session-scoped key-value)
178
+ \u2514\u2500 No \u2192 Is it resumable progress?
179
+ \u251C\u2500 Yes \u2192 kb_checkpoint (session-scoped snapshot)
180
+ \u2514\u2500 No \u2192 kb_remember (permanent, survives reindex)
181
+ Categories: decisions | patterns | conventions | troubleshooting
182
+ \`\`\`
180
183
 
181
- Additional filters: \`origin\` (\`indexed\`/\`curated\`/\`produced\`), \`category\`, \`content_type\`, \`tags\`, \`min_score\`.
184
+ ---
182
185
 
183
- ### Session Protocol
186
+ ## MANDATORY: Search-Before-Act Protocol
187
+
188
+ **NEVER write or modify code without first searching for context.**
184
189
 
185
- **Start of session:**
186
190
  \`\`\`
187
- kb_status({})
188
- kb_search({ query: "SESSION CHECKPOINT", origin: "curated" })
191
+ # Before ANY code change:
192
+ kb_search({ query: "<what you're about to change>" }) # Prior decisions?
193
+ kb_scope_map({ task: "<description>" }) # What files to read?
194
+ kb_symbol({ name: "<key symbol>" }) # Where is it defined/used?
189
195
  \`\`\`
190
196
 
191
- **During session:**
197
+ If \`kb_search\` returns a prior decision about the topic, you MUST follow it or explicitly explain why you're deviating.
198
+
199
+ ---
200
+
201
+ ## MANDATORY: Validation Protocol
202
+
203
+ **NEVER commit or present code without validation.**
204
+
192
205
  \`\`\`
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
206
+ kb_check({}) # Typecheck + lint (tsc + biome)
207
+ kb_test_run({}) # Run tests
208
+ kb_blast_radius({ changed_files: ["..."] }) # Impact analysis
209
+ kb_audit({}) # Unified project audit (structure, deps, patterns, health, dead symbols, entry points)
196
210
  \`\`\`
197
211
 
198
- **End of session:**
212
+ ---
213
+
214
+ ## FORGE Protocol (for complex tasks)
215
+
216
+ For tasks touching 3+ files or involving architectural decisions:
217
+
199
218
  \`\`\`
200
- kb_remember({ title: "Session checkpoint: <topic>", content: "<summary>", category: "conventions" })
219
+ kb_forge_classify({ task: "<description>" }) # Quick: Floor/Standard/Critical tier
220
+ kb_forge_ground({ task: "<description>" }) # Full: scope + constraints + evidence
221
+ kb_evidence_map({ claims: ["claim1", "claim2"] }) # Track verified vs assumed
201
222
  \`\`\`
202
223
 
203
- ### Workflow Chains
224
+ ---
225
+
226
+ ## Search Modes
227
+
228
+ | Mode | When | Example |
229
+ |------|------|---------|
230
+ | \`hybrid\` (default) | General queries | \`kb_search({ query: "error handling" })\` |
231
+ | \`semantic\` | Conceptual/meaning-based | \`kb_search({ query: "retry with backoff", search_mode: "semantic" })\` |
232
+ | \`keyword\` | Exact identifiers | \`kb_search({ query: "CircuitBreaker", search_mode: "keyword" })\` |
233
+
234
+ Filters: \`origin\` (\`indexed\`/\`curated\`/\`produced\`), \`category\`, \`content_type\`, \`tags\`, \`min_score\`.
235
+
236
+ ---
237
+
238
+ ## Workflow Chains
204
239
 
205
240
  **Codebase onboarding:**
206
241
  \`\`\`
@@ -209,41 +244,65 @@ kb_onboard({ path: "." }) \u2192 kb_produce_knowledge({ path: "src/" }) \u2192 k
209
244
 
210
245
  **Planning a task:**
211
246
  \`\`\`
212
- kb_search({ query: "task keywords" }) \u2192 kb_scope_map({ task: "description" }) \u2192 kb_workset({ action: "save", name: "task", files: [...] })
247
+ kb_search({ query: "task keywords" })
248
+ \u2192 kb_scope_map({ task: "description" })
249
+ \u2192 kb_file_summary for each file in scope
250
+ \u2192 kb_compact({ path: "relevant-file.ts", query: "detail needed" }) for files needing detail
251
+ \u2192 kb_workset({ action: "save", name: "task", files: [...] })
213
252
  \`\`\`
214
253
 
215
254
  **Bug investigation:**
216
255
  \`\`\`
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"] })
256
+ kb_parse_output({ output: "<error>" })
257
+ \u2192 kb_symbol({ name: "failingFn" })
258
+ \u2192 kb_trace({ symbol: "failingFn", direction: "backward" })
259
+ \u2192 kb_blast_radius({ changed_files: ["suspect.ts"] })
218
260
  \`\`\`
219
261
 
220
262
  **Safe refactor with lanes:**
221
263
  \`\`\`
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" })
264
+ kb_lane({ action: "create", name: "refactor", files: [...] })
265
+ \u2192 [make changes]
266
+ \u2192 kb_lane({ action: "diff", name: "refactor" })
267
+ \u2192 kb_check({}) \u2192 kb_test_run({})
268
+ \u2192 kb_lane({ action: "merge", name: "refactor" })
223
269
  \`\`\`
224
270
 
225
271
  **After making changes:**
226
272
  \`\`\`
227
- kb_blast_radius({ changed_files: ["src/file.ts"] }) \u2192 kb_check({}) \u2192 kb_test_run({}) \u2192 kb_reindex({}) \u2192 kb_remember(...)
273
+ kb_blast_radius({ changed_files: ["src/file.ts"] })
274
+ \u2192 kb_check({}) \u2192 kb_test_run({})
275
+ \u2192 kb_reindex({})
276
+ \u2192 kb_remember(...)
228
277
  \`\`\`
229
278
 
230
- ### Knowledge Categories
279
+ ---
280
+
281
+ ## Knowledge Categories
282
+
283
+ | Category | What to store |
284
+ |----------|---------------|
285
+ | \`decisions\` | Architecture choices, trade-offs, rejected alternatives |
286
+ | \`patterns\` | Code patterns, naming conventions, structural patterns |
287
+ | \`conventions\` | Session checkpoints, workflow conventions, team agreements |
288
+ | \`troubleshooting\` | Non-obvious fixes, debugging strategies, workarounds |
231
289
 
232
- \`decisions\` | \`patterns\` | \`conventions\` | \`troubleshooting\`
290
+ ---
233
291
 
234
- ### Core Rules
292
+ ## Core Rules Summary
235
293
 
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(e){const s=process.cwd(),i=t(s,"kb.config.json");if(o(i)&&!e.force){console.log("kb.config.json already exists. Use --force to overwrite.");return}a(i,`${JSON.stringify(h,null,2)}
242
- `,"utf-8"),console.log(" Created kb.config.json");const c=t(s,"curated");o(c)||(u(c,{recursive:!0}),console.log(" Created curated/"));const r=t(s,".gitignore");o(r)?m(r,"utf-8").includes(".kb-data")||(p(r,`
294
+ 1. **Search KB before proposing anything new** \u2014 prior decisions exist
295
+ 2. **Compress context aggressively** \u2014 \`file_summary\` \u2192 \`compact\` \u2192 \`digest\`
296
+ 3. **Use persistent memory** \u2014 \`remember\` decisions, \`stash\` temporary data
297
+ 4. **Validate before committing** \u2014 \`check\` + \`test_run\` + \`blast_radius\`
298
+ 5. **Follow \`_Next:\` hints** in tool responses for guided workflow
299
+ 6. **Use FORGE for complex tasks** \u2014 \`forge_classify\` \u2192 \`forge_ground\` \u2192 \`evidence_map\`
300
+ `}async function R(o){const s=process.cwd(),c=e(s,"kb.config.json");if(t(c)&&!o.force){console.log("kb.config.json already exists. Use --force to overwrite.");return}r(c,`${JSON.stringify(C,null,2)}
301
+ `,"utf-8"),console.log(" Created kb.config.json");const d=e(s,"curated");t(d)||(n(d,{recursive:!0}),console.log(" Created curated/"));const a=e(s,".gitignore");t(a)?v(a,"utf-8").includes(".kb-data")||(h(a,`
243
302
  # Knowledge base vector store
244
303
  .kb-data/
245
- `,"utf-8"),console.log(" Added .kb-data/ to .gitignore")):(a(r,`# Knowledge base vector store
304
+ `,"utf-8"),console.log(" Added .kb-data/ to .gitignore")):(r(a,`# Knowledge base vector store
246
305
  .kb-data/
247
- `,"utf-8"),console.log(" Created .gitignore with .kb-data/"));const n=g(s),l=t(s,".vscode"),d=t(l,"mcp.json");o(l)&&!o(d)&&(a(d,`${JSON.stringify(f(n),null,2)}
248
- `,"utf-8"),console.log(" Created .vscode/mcp.json"));const b=t(s,".github"),k=t(b,"copilot-instructions.md");o(k)||(u(b,{recursive:!0}),a(k,y(n),"utf-8"),console.log(" Created .github/copilot-instructions.md"));const _=t(s,"AGENTS.md");o(_)||(a(_,w(n),"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};
306
+ `,"utf-8"),console.log(" Created .gitignore with .kb-data/"));const i=w(s),l=e(s,".vscode"),k=e(l,"mcp.json");t(l)&&!t(k)&&(r(k,`${JSON.stringify(A(i),null,2)}
307
+ `,"utf-8"),console.log(" Created .vscode/mcp.json"));const u=e(s,".github"),b=e(u,"copilot-instructions.md");t(b)||(n(u,{recursive:!0}),r(b,T(i),"utf-8"),console.log(" Created .github/copilot-instructions.md"));const m=e(s,"AGENTS.md");t(m)||(r(m,P(i),"utf-8"),console.log(" Created AGENTS.md"));const _=e(s,"skills","knowledge-base"),p=e(_,"SKILL.md");if(!t(p)){const f=S(x(import.meta.url)),g=e(f,"..","..","..","skills","knowledge-base","SKILL.md");t(g)&&(n(_,{recursive:!0}),y(g,p),console.log(" Created skills/knowledge-base/SKILL.md"))}console.log(`
308
+ 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{R as initProject};
@@ -1 +1 @@
1
- import{compact as m}from"../../../tools/dist/index.js";import{ctx as i}from"../context.js";import{extractNumFlag as p,extractStrFlag as c,readStdin as l,splitCsv as d}from"../helpers.js";const f=[{name:"remember",description:"Store curated knowledge",usage:"kb remember <title> --category <cat> [--tags tag1,tag2]",run:async t=>{const o=c(t,"--category","").trim(),a=d(c(t,"--tags","")),e=t.shift()?.trim()??"",r=await l(),n=r.trim().length>0?r:t.join(" ").trim();(!e||!o||!n.trim())&&(console.error("Usage: kb remember <title> --category <cat> [--tags tag1,tag2]"),process.exit(1));const{curated:s}=await i(),g=await s.remember(e,n,o,a);console.log("Stored curated entry"),console.log(` Path: ${g.path}`),console.log(` Category: ${o}`),a.length>0&&console.log(` Tags: ${a.join(", ")}`)}},{name:"forget",description:"Remove a curated entry",usage:"kb forget <path> --reason <reason>",run:async t=>{const o=c(t,"--reason","").trim(),a=t.shift()?.trim()??"";(!a||!o)&&(console.error("Usage: kb forget <path> --reason <reason>"),process.exit(1));const{curated:e}=await i(),r=await e.forget(a,o);console.log(`Removed curated entry: ${r.path}`)}},{name:"read",description:"Read a curated entry",usage:"kb read <path>",run:async t=>{const o=t.shift()?.trim()??"";o||(console.error("Usage: kb read <path>"),process.exit(1));const{curated:a}=await i(),e=await a.read(o);console.log(e.title),console.log("\u2500".repeat(60)),console.log(`Path: ${e.path}`),console.log(`Category: ${e.category}`),console.log(`Version: ${e.version}`),console.log(`Tags: ${e.tags.length>0?e.tags.join(", "):"None"}`),console.log(""),console.log(e.content)}},{name:"list",description:"List curated entries",usage:"kb list [--category <cat>] [--tag <tag>]",run:async t=>{const o=c(t,"--category","").trim()||void 0,a=c(t,"--tag","").trim()||void 0,{curated:e}=await i(),r=await e.list({category:o,tag:a});if(r.length===0){console.log("No curated entries found.");return}console.log(`Curated entries (${r.length})`),console.log("\u2500".repeat(60));for(const n of r){console.log(n.path),console.log(` ${n.title}`),console.log(` Category: ${n.category} | Version: ${n.version}`),console.log(` Tags: ${n.tags.length>0?n.tags.join(", "):"None"}`);const s=n.contentPreview.replace(/\s+/g," ").trim();s&&console.log(` Preview: ${s}`),console.log("")}}},{name:"update",description:"Update a curated entry",usage:"kb update <path> --reason <reason>",run:async t=>{const o=c(t,"--reason","").trim(),a=t.shift()?.trim()??"",e=await l();(!a||!o||!e.trim())&&(console.error("Usage: kb update <path> --reason <reason>"),process.exit(1));const{curated:r}=await i(),n=await r.update(a,e,o);console.log("Updated curated entry"),console.log(` Path: ${n.path}`),console.log(` Version: ${n.version}`)}},{name:"compact",description:"Compress text for context",usage:"kb compact <query> [--max-chars N] [--segmentation paragraph|sentence|line]",run:async t=>{const o=p(t,"--max-chars",3e3),a=c(t,"--segmentation","paragraph"),e=t.join(" ").trim(),r=await l();(!e||!r.trim())&&(console.error("Usage: kb compact <query> [--max-chars N] [--segmentation paragraph|sentence|line]"),process.exit(1));const{embedder:n}=await i(),s=await m(n,{text:r,query:e,maxChars:o,segmentation:a});console.log(`Compressed ${s.originalChars} chars to ${s.compressedChars} chars`),console.log(`Ratio: ${(s.ratio*100).toFixed(1)}% | Segments: ${s.segmentsKept}/${s.segmentsTotal}`),console.log(""),console.log(s.text)}}];export{f as knowledgeCommands};
1
+ import{compact as m}from"../../../tools/dist/index.js";import{ctx as l}from"../context.js";import{extractNumFlag as p,extractStrFlag as c,readStdin as g,splitCsv as d}from"../helpers.js";const y=[{name:"remember",description:"Store curated knowledge",usage:"kb remember <title> --category <cat> [--tags tag1,tag2]",run:async e=>{const a=c(e,"--category","").trim(),o=d(c(e,"--tags","")),t=e.shift()?.trim()??"",r=await g(),n=r.trim().length>0?r:e.join(" ").trim();(!t||!a||!n.trim())&&(console.error("Usage: kb remember <title> --category <cat> [--tags tag1,tag2]"),process.exit(1));const{curated:i}=await l(),s=await i.remember(t,n,a,o);console.log("Stored curated entry"),console.log(` Path: ${s.path}`),console.log(` Category: ${a}`),o.length>0&&console.log(` Tags: ${o.join(", ")}`)}},{name:"forget",description:"Remove a curated entry",usage:"kb forget <path> --reason <reason>",run:async e=>{const a=c(e,"--reason","").trim(),o=e.shift()?.trim()??"";(!o||!a)&&(console.error("Usage: kb forget <path> --reason <reason>"),process.exit(1));const{curated:t}=await l(),r=await t.forget(o,a);console.log(`Removed curated entry: ${r.path}`)}},{name:"read",description:"Read a curated entry",usage:"kb read <path>",run:async e=>{const a=e.shift()?.trim()??"";a||(console.error("Usage: kb read <path>"),process.exit(1));const{curated:o}=await l(),t=await o.read(a);console.log(t.title),console.log("\u2500".repeat(60)),console.log(`Path: ${t.path}`),console.log(`Category: ${t.category}`),console.log(`Version: ${t.version}`),console.log(`Tags: ${t.tags.length>0?t.tags.join(", "):"None"}`),console.log(""),console.log(t.content)}},{name:"list",description:"List curated entries",usage:"kb list [--category <cat>] [--tag <tag>]",run:async e=>{const a=c(e,"--category","").trim()||void 0,o=c(e,"--tag","").trim()||void 0,{curated:t}=await l(),r=await t.list({category:a,tag:o});if(r.length===0){console.log("No curated entries found.");return}console.log(`Curated entries (${r.length})`),console.log("\u2500".repeat(60));for(const n of r){console.log(n.path),console.log(` ${n.title}`),console.log(` Category: ${n.category} | Version: ${n.version}`),console.log(` Tags: ${n.tags.length>0?n.tags.join(", "):"None"}`);const i=n.contentPreview.replace(/\s+/g," ").trim();i&&console.log(` Preview: ${i}`),console.log("")}}},{name:"update",description:"Update a curated entry",usage:"kb update <path> --reason <reason>",run:async e=>{const a=c(e,"--reason","").trim(),o=e.shift()?.trim()??"",t=await g();(!o||!a||!t.trim())&&(console.error("Usage: kb update <path> --reason <reason>"),process.exit(1));const{curated:r}=await l(),n=await r.update(o,t,a);console.log("Updated curated entry"),console.log(` Path: ${n.path}`),console.log(` Version: ${n.version}`)}},{name:"compact",description:"Compress text for context",usage:"kb compact <query> [--path <file>] [--max-chars N] [--segmentation paragraph|sentence|line]",run:async e=>{const a=p(e,"--max-chars",3e3),o=c(e,"--path","").trim()||void 0,t=c(e,"--segmentation","paragraph"),r=e.join(" ").trim(),n=o?void 0:await g();(!r||!o&&!n?.trim())&&(console.error("Usage: kb compact <query> --path <file> OR cat file | kb compact <query>"),process.exit(1));const{embedder:i}=await l(),s=await m(i,{text:n,path:o,query:r,maxChars:a,segmentation:t});console.log(`Compressed ${s.originalChars} chars to ${s.compressedChars} chars`),console.log(`Ratio: ${(s.ratio*100).toFixed(1)}% | Segments: ${s.segmentsKept}/${s.segmentsTotal}`),console.log(""),console.log(s.text)}}];export{y as knowledgeCommands};
@@ -1,4 +1,7 @@
1
- import{fork as f}from"node:child_process";import{dirname as m,resolve as h}from"node:path";import{fileURLToPath as g}from"node:url";import{batch as y,check as x,health as k,replayClear as w,replayList as $,replayTrim as b}from"../../../tools/dist/index.js";import{ctx as p}from"../context.js";import{executeCliBatchOperation as I,extractStrFlag as a,parseBatchPayload as R,printCheckResult as N,readInput as T}from"../helpers.js";const C=m(g(import.meta.url)),E=[{name:"status",description:"Show knowledge base index status and statistics",run:async()=>{const{store:e}=await p(),s=await e.getStats(),t=await e.listSourcePaths();console.log("Knowledge Base Status"),console.log("\u2500".repeat(40)),console.log(` Records: ${s.totalRecords}`),console.log(` Files: ${s.totalFiles}`),console.log(` Indexed: ${s.lastIndexedAt??"Never"}`),console.log(` Backend: ${s.storeBackend}`),console.log(` Model: ${s.embeddingModel}`),console.log(""),console.log("Content Types:");for(const[n,o]of Object.entries(s.contentTypeBreakdown))console.log(` ${n}: ${o}`);if(t.length>0){console.log(""),console.log(`Files (${t.length} total):`);for(const n of t.slice(0,20))console.log(` ${n}`);t.length>20&&console.log(` ... and ${t.length-20} more`)}}},{name:"reindex",description:"Re-index the knowledge base from configured sources",usage:"kb reindex [--full]",run:async e=>{const s=e.includes("--full"),{store:t,indexer:n,curated:o,config:i}=await p();console.log("Indexing sources...");const l=r=>{r.phase==="chunking"&&r.currentFile&&process.stdout.write(`\r [${r.filesProcessed+1}/${r.filesTotal}] ${r.currentFile}`),r.phase==="done"&&process.stdout.write(`
2
- `)};let c;s?(console.log("Dropping existing index for full reindex..."),c=await n.reindexAll(i,l)):c=await n.index(i,l),console.log(`Done: ${c.filesProcessed} files, ${c.chunksCreated} chunks in ${(c.durationMs/1e3).toFixed(1)}s`),console.log("Building FTS index..."),await t.createFtsIndex(),console.log("Re-indexing curated entries...");const d=await o.reindexAll();console.log(`Curated: ${d.indexed} entries restored`)}},{name:"serve",description:"Start the MCP server (stdio or HTTP)",usage:"kb serve [--transport stdio|http] [--port N]",run:async e=>{const s=h(C,"..","..","..","server","dist","index.js"),t=a(e,"--transport","stdio"),n=a(e,"--port","3210"),o=f(s,[],{stdio:t==="stdio"?["pipe","pipe","inherit","ipc"]:"inherit",env:{...process.env,KB_TRANSPORT:t,KB_PORT:n}});t==="stdio"&&o.stdin&&o.stdout&&(process.stdin.pipe(o.stdin),o.stdout.pipe(process.stdout)),o.on("exit",i=>process.exit(i??0)),process.on("SIGINT",()=>o.kill("SIGINT")),process.on("SIGTERM",()=>o.kill("SIGTERM")),await new Promise(()=>{})}},{name:"init",description:"Initialize a knowledge base in the current directory",usage:"kb init [--force]",run:async e=>{const s=e.includes("--force"),{initProject:t}=await import("./init.js");await t({force:s})}},{name:"check",description:"Run incremental typecheck and lint",usage:"kb check [--cwd <dir>] [--files f1,f2] [--skip-types] [--skip-lint]",run:async e=>{const s=a(e,"--cwd","").trim()||void 0,n=a(e,"--files","").split(",").map(c=>c.trim()).filter(Boolean);let o=!1;e.includes("--skip-types")&&(e.splice(e.indexOf("--skip-types"),1),o=!0);let i=!1;e.includes("--skip-lint")&&(e.splice(e.indexOf("--skip-lint"),1),i=!0);const l=await x({cwd:s,files:n.length>0?n:void 0,skipTypes:o,skipLint:i});N(l),l.passed||(process.exitCode=1)}},{name:"batch",description:"Execute built-in operations from JSON input",usage:"kb batch [--file path] [--concurrency N]",run:async e=>{const s=a(e,"--file","").trim()||void 0,t=(()=>{const r=e.indexOf("--concurrency");if(r===-1||r+1>=e.length)return 0;const u=Number.parseInt(e.splice(r,2)[1],10);return Number.isNaN(u)?0:u})(),n=await T(s);n.trim()||(console.error("Usage: kb batch [--file path] [--concurrency N]"),process.exit(1));const o=R(n),i=t>0?t:o.concurrency,c=o.operations.some(r=>r.type!=="check")?await p():null,d=await y(o.operations,async r=>I(r,c),{concurrency:i});console.log(JSON.stringify(d,null,2)),d.some(r=>r.status==="error")&&(process.exitCode=1)}},{name:"health",description:"Run project health checks on the current directory",usage:"kb health [path]",run:async e=>{const s=e.shift(),t=k(s);console.log(`Project Health: ${t.path}`),console.log("\u2500".repeat(50));for(const n of t.checks){const o=n.status==="pass"?"+":n.status==="warn"?"~":"X";console.log(` [${o}] ${n.name}: ${n.message}`)}console.log("\u2500".repeat(50)),console.log(`Score: ${t.score}% \u2014 ${t.summary}`)}},{name:"replay",description:"Show recent tool invocation audit trail",usage:"kb replay [--last N] [--tool <name>] [--source mcp|cli]",run:async e=>{const s=Number.parseInt(e[e.indexOf("--last")+1],10)||20,t=e.includes("--tool")?e[e.indexOf("--tool")+1]:void 0,n=e.includes("--source")?e[e.indexOf("--source")+1]:void 0,o=$({last:s,tool:t,source:n});if(o.length===0){console.log("No replay entries. Activity is logged when tools are invoked.");return}console.log(`Replay Log (${o.length} entries)
3
- `);for(const i of o){const l=i.ts.split("T")[1]?.split(".")[0]??i.ts,c=i.status==="ok"?"\u2713":"\u2717";console.log(`${l} ${c} ${i.tool} (${i.durationMs}ms) [${i.source}]`),console.log(` in: ${i.input}`),console.log(` out: ${i.output}`)}b()}},{name:"replay-clear",description:"Clear the replay audit trail",run:async()=>{w(),console.log("Replay log cleared.")}},{name:"tui",description:"Launch interactive terminal dashboard (human monitoring)",run:async()=>{try{const{launch:e}=await import("../../../tui/dist/index.js"),{store:s,embedder:t,config:n}=await p();e({store:s,embedder:t,config:n})}catch(e){throw e.code==="ERR_MODULE_NOT_FOUND"&&(console.error(`TUI requires ink and react. Install them with:
1
+ import{fork as m}from"node:child_process";import{dirname as f,resolve as g}from"node:path";import{fileURLToPath as h}from"node:url";import{audit as y,batch as x,check as k,guide as w,health as $,replayClear as b,replayList as N,replayTrim as R}from"../../../tools/dist/index.js";import{ctx as u}from"../context.js";import{executeCliBatchOperation as I,extractStrFlag as d,parseBatchPayload as v,printCheckResult as C,readInput as T}from"../helpers.js";const S=f(h(import.meta.url)),E=[{name:"status",description:"Show knowledge base index status and statistics",run:async()=>{const{store:e}=await u(),s=await e.getStats(),t=await e.listSourcePaths();console.log("Knowledge Base Status"),console.log("\u2500".repeat(40)),console.log(` Records: ${s.totalRecords}`),console.log(` Files: ${s.totalFiles}`),console.log(` Indexed: ${s.lastIndexedAt??"Never"}`),console.log(` Backend: ${s.storeBackend}`),console.log(` Model: ${s.embeddingModel}`),console.log(""),console.log("Content Types:");for(const[n,o]of Object.entries(s.contentTypeBreakdown))console.log(` ${n}: ${o}`);if(t.length>0){console.log(""),console.log(`Files (${t.length} total):`);for(const n of t.slice(0,20))console.log(` ${n}`);t.length>20&&console.log(` ... and ${t.length-20} more`)}}},{name:"reindex",description:"Re-index the knowledge base from configured sources",usage:"kb reindex [--full]",run:async e=>{const s=e.includes("--full"),{store:t,indexer:n,curated:o,config:i}=await u();console.log("Indexing sources...");const l=c=>{c.phase==="chunking"&&c.currentFile&&process.stdout.write(`\r [${c.filesProcessed+1}/${c.filesTotal}] ${c.currentFile}`),c.phase==="done"&&process.stdout.write(`
2
+ `)};let r;s?(console.log("Dropping existing index for full reindex..."),r=await n.reindexAll(i,l)):r=await n.index(i,l),console.log(`Done: ${r.filesProcessed} files, ${r.chunksCreated} chunks in ${(r.durationMs/1e3).toFixed(1)}s`),console.log("Building FTS index..."),await t.createFtsIndex(),console.log("Re-indexing curated entries...");const a=await o.reindexAll();console.log(`Curated: ${a.indexed} entries restored`)}},{name:"serve",description:"Start the MCP server (stdio or HTTP)",usage:"kb serve [--transport stdio|http] [--port N]",run:async e=>{const s=g(S,"..","..","..","server","dist","index.js"),t=d(e,"--transport","stdio"),n=d(e,"--port","3210"),o=m(s,[],{stdio:t==="stdio"?["pipe","pipe","inherit","ipc"]:"inherit",env:{...process.env,KB_TRANSPORT:t,KB_PORT:n}});t==="stdio"&&o.stdin&&o.stdout&&(process.stdin.pipe(o.stdin),o.stdout.pipe(process.stdout)),o.on("exit",i=>process.exit(i??0)),process.on("SIGINT",()=>o.kill("SIGINT")),process.on("SIGTERM",()=>o.kill("SIGTERM")),await new Promise(()=>{})}},{name:"init",description:"Initialize a knowledge base in the current directory",usage:"kb init [--force]",run:async e=>{const s=e.includes("--force"),{initProject:t}=await import("./init.js");await t({force:s})}},{name:"check",description:"Run incremental typecheck and lint",usage:"kb check [--cwd <dir>] [--files f1,f2] [--skip-types] [--skip-lint] [--detail summary|errors|full]",run:async e=>{const s=d(e,"--cwd","").trim()||void 0,t=d(e,"--files",""),n=d(e,"--detail","full")||"full",o=t.split(",").map(a=>a.trim()).filter(Boolean);let i=!1;e.includes("--skip-types")&&(e.splice(e.indexOf("--skip-types"),1),i=!0);let l=!1;e.includes("--skip-lint")&&(e.splice(e.indexOf("--skip-lint"),1),l=!0);const r=await k({cwd:s,files:o.length>0?o:void 0,skipTypes:i,skipLint:l,detail:n});C(r),r.passed||(process.exitCode=1)}},{name:"batch",description:"Execute built-in operations from JSON input",usage:"kb batch [--file path] [--concurrency N]",run:async e=>{const s=d(e,"--file","").trim()||void 0,t=(()=>{const c=e.indexOf("--concurrency");if(c===-1||c+1>=e.length)return 0;const p=Number.parseInt(e.splice(c,2)[1],10);return Number.isNaN(p)?0:p})(),n=await T(s);n.trim()||(console.error("Usage: kb batch [--file path] [--concurrency N]"),process.exit(1));const o=v(n),i=t>0?t:o.concurrency,r=o.operations.some(c=>c.type!=="check")?await u():null,a=await x(o.operations,async c=>I(c,r),{concurrency:i});console.log(JSON.stringify(a,null,2)),a.some(c=>c.status==="error")&&(process.exitCode=1)}},{name:"health",description:"Run project health checks on the current directory",usage:"kb health [path]",run:async e=>{const s=e.shift(),t=$(s);console.log(`Project Health: ${t.path}`),console.log("\u2500".repeat(50));for(const n of t.checks){const o=n.status==="pass"?"+":n.status==="warn"?"~":"X";console.log(` [${o}] ${n.name}: ${n.message}`)}console.log("\u2500".repeat(50)),console.log(`Score: ${t.score}% \u2014 ${t.summary}`)}},{name:"audit",description:"Run a unified project audit (structure, deps, patterns, health, dead symbols, check)",usage:"kb audit [path] [--checks structure,dependencies,patterns,health,dead_symbols,check,entry_points] [--detail summary|full]",run:async e=>{const{store:s,embedder:t}=await u(),n=d(e,"--detail","summary")||"summary",o=d(e,"--checks",""),i=o?o.split(",").map(a=>a.trim()):void 0,l=e.shift()||".",r=await y(s,t,{path:l,checks:i,detail:n});if(r.ok){if(console.log(r.summary),r.next&&r.next.length>0){console.log(`
3
+ Suggested next steps:`);for(const a of r.next)console.log(` \u2192 ${a.tool}: ${a.reason}`)}}else console.error(r.error?.message??"Audit failed"),process.exitCode=1}},{name:"guide",description:"Tool discovery \u2014 recommend KB tools for a given goal",usage:"kb guide <goal> [--max N]",run:async e=>{const s=e.indexOf("--max");let t=5;s!==-1&&s+1<e.length&&(t=Number.parseInt(e.splice(s,2)[1],10)||5);const n=e.join(" ").trim();n||(console.error("Usage: kb guide <goal> [--max N]"),console.error('Example: kb guide "audit this project"'),process.exit(1));const o=w(n,t);console.log(`Workflow: ${o.workflow}`),console.log(` ${o.description}
4
+ `),console.log("Recommended tools:");for(const i of o.tools){const l=i.suggestedArgs?` ${JSON.stringify(i.suggestedArgs)}`:"";console.log(` ${i.order}. ${i.tool} \u2014 ${i.reason}${l}`)}o.alternativeWorkflows.length>0&&console.log(`
5
+ Alternatives: ${o.alternativeWorkflows.join(", ")}`)}},{name:"replay",description:"Show recent tool invocation audit trail",usage:"kb replay [--last N] [--tool <name>] [--source mcp|cli]",run:async e=>{const s=Number.parseInt(e[e.indexOf("--last")+1],10)||20,t=e.includes("--tool")?e[e.indexOf("--tool")+1]:void 0,n=e.includes("--source")?e[e.indexOf("--source")+1]:void 0,o=N({last:s,tool:t,source:n});if(o.length===0){console.log("No replay entries. Activity is logged when tools are invoked.");return}console.log(`Replay Log (${o.length} entries)
6
+ `);for(const i of o){const l=i.ts.split("T")[1]?.split(".")[0]??i.ts,r=i.status==="ok"?"\u2713":"\u2717";console.log(`${l} ${r} ${i.tool} (${i.durationMs}ms) [${i.source}]`),console.log(` in: ${i.input}`),console.log(` out: ${i.output}`)}R()}},{name:"replay-clear",description:"Clear the replay audit trail",run:async()=>{b(),console.log("Replay log cleared.")}},{name:"tui",description:"Launch interactive terminal dashboard (human monitoring)",run:async()=>{try{const{launch:e}=await import("../../../tui/dist/index.js"),{store:s,embedder:t,config:n}=await u();e({store:s,embedder:t,config:n})}catch(e){throw e.code==="ERR_MODULE_NOT_FOUND"&&(console.error(`TUI requires ink and react. Install them with:
4
7
  pnpm add -D ink react @types/react`),process.exit(1)),e}}}];export{E as systemCommands};