ai-first-cli 1.1.1 → 1.1.3

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 (193) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/README.es.md +137 -1
  3. package/README.md +136 -4
  4. package/ai/ai_context.md +2 -2
  5. package/ai/architecture.md +3 -3
  6. package/ai/cache.json +85 -57
  7. package/ai/ccp/jira-123/context.json +7 -0
  8. package/ai/context/repo.json +56 -0
  9. package/ai/context/utils.json +7 -0
  10. package/ai/dependencies.json +51 -1026
  11. package/ai/files.json +195 -3
  12. package/ai/git/commit-activity.json +8646 -0
  13. package/ai/git/recent-features.json +1 -0
  14. package/ai/git/recent-files.json +52 -0
  15. package/ai/git/recent-flows.json +1 -0
  16. package/ai/graph/knowledge-graph.json +43643 -0
  17. package/ai/graph/module-graph.json +4 -0
  18. package/ai/graph/symbol-graph.json +3307 -879
  19. package/ai/graph/symbol-references.json +119 -32
  20. package/ai/index-state.json +843 -188
  21. package/ai/index.db +0 -0
  22. package/ai/modules.json +4 -0
  23. package/ai/repo-map.json +81 -17
  24. package/ai/repo_map.json +81 -17
  25. package/ai/repo_map.md +21 -7
  26. package/ai/summary.md +5 -5
  27. package/ai/symbols.json +1 -20287
  28. package/dist/analyzers/androidResources.d.ts +23 -0
  29. package/dist/analyzers/androidResources.d.ts.map +1 -0
  30. package/dist/analyzers/androidResources.js +93 -0
  31. package/dist/analyzers/androidResources.js.map +1 -0
  32. package/dist/analyzers/dependencies.d.ts.map +1 -1
  33. package/dist/analyzers/dependencies.js +37 -0
  34. package/dist/analyzers/dependencies.js.map +1 -1
  35. package/dist/analyzers/entrypoints.d.ts.map +1 -1
  36. package/dist/analyzers/entrypoints.js +71 -1
  37. package/dist/analyzers/entrypoints.js.map +1 -1
  38. package/dist/analyzers/gradleModules.d.ts +22 -0
  39. package/dist/analyzers/gradleModules.d.ts.map +1 -0
  40. package/dist/analyzers/gradleModules.js +75 -0
  41. package/dist/analyzers/gradleModules.js.map +1 -0
  42. package/dist/analyzers/techStack.d.ts +7 -0
  43. package/dist/analyzers/techStack.d.ts.map +1 -1
  44. package/dist/analyzers/techStack.js +44 -1
  45. package/dist/analyzers/techStack.js.map +1 -1
  46. package/dist/commands/ai-first.d.ts +1 -0
  47. package/dist/commands/ai-first.d.ts.map +1 -1
  48. package/dist/commands/ai-first.js +312 -1
  49. package/dist/commands/ai-first.js.map +1 -1
  50. package/dist/core/adapters/adapterRegistry.d.ts +39 -0
  51. package/dist/core/adapters/adapterRegistry.d.ts.map +1 -0
  52. package/dist/core/adapters/adapterRegistry.js +155 -0
  53. package/dist/core/adapters/adapterRegistry.js.map +1 -0
  54. package/dist/core/adapters/baseAdapter.d.ts +49 -0
  55. package/dist/core/adapters/baseAdapter.d.ts.map +1 -0
  56. package/dist/core/adapters/baseAdapter.js +28 -0
  57. package/dist/core/adapters/baseAdapter.js.map +1 -0
  58. package/dist/core/adapters/community/fastapiAdapter.d.ts +7 -0
  59. package/dist/core/adapters/community/fastapiAdapter.d.ts.map +1 -0
  60. package/dist/core/adapters/community/fastapiAdapter.js +40 -0
  61. package/dist/core/adapters/community/fastapiAdapter.js.map +1 -0
  62. package/dist/core/adapters/community/index.d.ts +11 -0
  63. package/dist/core/adapters/community/index.d.ts.map +1 -0
  64. package/dist/core/adapters/community/index.js +11 -0
  65. package/dist/core/adapters/community/index.js.map +1 -0
  66. package/dist/core/adapters/community/laravelAdapter.d.ts +7 -0
  67. package/dist/core/adapters/community/laravelAdapter.d.ts.map +1 -0
  68. package/dist/core/adapters/community/laravelAdapter.js +47 -0
  69. package/dist/core/adapters/community/laravelAdapter.js.map +1 -0
  70. package/dist/core/adapters/community/nestjsAdapter.d.ts +7 -0
  71. package/dist/core/adapters/community/nestjsAdapter.d.ts.map +1 -0
  72. package/dist/core/adapters/community/nestjsAdapter.js +48 -0
  73. package/dist/core/adapters/community/nestjsAdapter.js.map +1 -0
  74. package/dist/core/adapters/community/phoenixAdapter.d.ts +7 -0
  75. package/dist/core/adapters/community/phoenixAdapter.d.ts.map +1 -0
  76. package/dist/core/adapters/community/phoenixAdapter.js +45 -0
  77. package/dist/core/adapters/community/phoenixAdapter.js.map +1 -0
  78. package/dist/core/adapters/community/springBootAdapter.d.ts +7 -0
  79. package/dist/core/adapters/community/springBootAdapter.d.ts.map +1 -0
  80. package/dist/core/adapters/community/springBootAdapter.js +44 -0
  81. package/dist/core/adapters/community/springBootAdapter.js.map +1 -0
  82. package/dist/core/adapters/dotnetAdapter.d.ts +20 -0
  83. package/dist/core/adapters/dotnetAdapter.d.ts.map +1 -0
  84. package/dist/core/adapters/dotnetAdapter.js +86 -0
  85. package/dist/core/adapters/dotnetAdapter.js.map +1 -0
  86. package/dist/core/adapters/index.d.ts +18 -0
  87. package/dist/core/adapters/index.d.ts.map +1 -0
  88. package/dist/core/adapters/index.js +19 -0
  89. package/dist/core/adapters/index.js.map +1 -0
  90. package/dist/core/adapters/javascriptAdapter.d.ts +11 -0
  91. package/dist/core/adapters/javascriptAdapter.d.ts.map +1 -0
  92. package/dist/core/adapters/javascriptAdapter.js +47 -0
  93. package/dist/core/adapters/javascriptAdapter.js.map +1 -0
  94. package/dist/core/adapters/pythonAdapter.d.ts +20 -0
  95. package/dist/core/adapters/pythonAdapter.d.ts.map +1 -0
  96. package/dist/core/adapters/pythonAdapter.js +99 -0
  97. package/dist/core/adapters/pythonAdapter.js.map +1 -0
  98. package/dist/core/adapters/railsAdapter.d.ts +10 -0
  99. package/dist/core/adapters/railsAdapter.d.ts.map +1 -0
  100. package/dist/core/adapters/railsAdapter.js +52 -0
  101. package/dist/core/adapters/railsAdapter.js.map +1 -0
  102. package/dist/core/adapters/salesforceAdapter.d.ts +16 -0
  103. package/dist/core/adapters/salesforceAdapter.d.ts.map +1 -0
  104. package/dist/core/adapters/salesforceAdapter.js +64 -0
  105. package/dist/core/adapters/salesforceAdapter.js.map +1 -0
  106. package/dist/core/adapters/sdk.d.ts +83 -0
  107. package/dist/core/adapters/sdk.d.ts.map +1 -0
  108. package/dist/core/adapters/sdk.js +114 -0
  109. package/dist/core/adapters/sdk.js.map +1 -0
  110. package/dist/core/ccp.d.ts +37 -0
  111. package/dist/core/ccp.d.ts.map +1 -0
  112. package/dist/core/ccp.js +184 -0
  113. package/dist/core/ccp.js.map +1 -0
  114. package/dist/core/gitAnalyzer.d.ts +74 -0
  115. package/dist/core/gitAnalyzer.d.ts.map +1 -0
  116. package/dist/core/gitAnalyzer.js +298 -0
  117. package/dist/core/gitAnalyzer.js.map +1 -0
  118. package/dist/core/incrementalAnalyzer.d.ts +28 -0
  119. package/dist/core/incrementalAnalyzer.d.ts.map +1 -0
  120. package/dist/core/incrementalAnalyzer.js +343 -0
  121. package/dist/core/incrementalAnalyzer.js.map +1 -0
  122. package/dist/core/knowledgeGraphBuilder.d.ts +31 -0
  123. package/dist/core/knowledgeGraphBuilder.d.ts.map +1 -0
  124. package/dist/core/knowledgeGraphBuilder.js +197 -0
  125. package/dist/core/knowledgeGraphBuilder.js.map +1 -0
  126. package/dist/core/lazyAnalyzer.d.ts +57 -0
  127. package/dist/core/lazyAnalyzer.d.ts.map +1 -0
  128. package/dist/core/lazyAnalyzer.js +204 -0
  129. package/dist/core/lazyAnalyzer.js.map +1 -0
  130. package/dist/core/schema.d.ts +57 -0
  131. package/dist/core/schema.d.ts.map +1 -0
  132. package/dist/core/schema.js +131 -0
  133. package/dist/core/schema.js.map +1 -0
  134. package/dist/core/semanticContexts.d.ts +40 -0
  135. package/dist/core/semanticContexts.d.ts.map +1 -0
  136. package/dist/core/semanticContexts.js +454 -0
  137. package/dist/core/semanticContexts.js.map +1 -0
  138. package/docs/es/guide/adapters.md +143 -0
  139. package/docs/es/guide/ai-repository-schema.md +119 -0
  140. package/docs/es/guide/features.md +67 -0
  141. package/docs/es/guide/flows.md +134 -0
  142. package/docs/es/guide/git-intelligence.md +170 -0
  143. package/docs/es/guide/incremental-analysis.md +131 -0
  144. package/docs/es/guide/knowledge-graph.md +135 -0
  145. package/docs/es/guide/lazy-indexing.md +144 -0
  146. package/docs/es/guide/performance.md +125 -0
  147. package/docs/guide/adapters.md +225 -0
  148. package/docs/guide/ai-repository-schema.md +119 -0
  149. package/docs/guide/architecture.md +69 -1
  150. package/docs/guide/flows.md +134 -0
  151. package/docs/guide/git-intelligence.md +170 -0
  152. package/docs/guide/incremental-analysis.md +131 -0
  153. package/docs/guide/knowledge-graph.md +135 -0
  154. package/docs/guide/lazy-indexing.md +144 -0
  155. package/docs/guide/performance.md +125 -0
  156. package/package.json +5 -2
  157. package/src/analyzers/androidResources.ts +113 -0
  158. package/src/analyzers/dependencies.ts +41 -0
  159. package/src/analyzers/entrypoints.ts +80 -1
  160. package/src/analyzers/gradleModules.ts +100 -0
  161. package/src/analyzers/techStack.ts +56 -0
  162. package/src/commands/ai-first.ts +343 -1
  163. package/src/core/adapters/adapterRegistry.ts +187 -0
  164. package/src/core/adapters/baseAdapter.ts +82 -0
  165. package/src/core/adapters/community/fastapiAdapter.ts +50 -0
  166. package/src/core/adapters/community/index.ts +11 -0
  167. package/src/core/adapters/community/laravelAdapter.ts +56 -0
  168. package/src/core/adapters/community/nestjsAdapter.ts +57 -0
  169. package/src/core/adapters/community/phoenixAdapter.ts +54 -0
  170. package/src/core/adapters/community/springBootAdapter.ts +53 -0
  171. package/src/core/adapters/dotnetAdapter.ts +104 -0
  172. package/src/core/adapters/index.ts +24 -0
  173. package/src/core/adapters/javascriptAdapter.ts +56 -0
  174. package/src/core/adapters/pythonAdapter.ts +118 -0
  175. package/src/core/adapters/railsAdapter.ts +65 -0
  176. package/src/core/adapters/salesforceAdapter.ts +76 -0
  177. package/src/core/adapters/sdk.ts +172 -0
  178. package/src/core/ccp.ts +240 -0
  179. package/src/core/gitAnalyzer.ts +391 -0
  180. package/src/core/incrementalAnalyzer.ts +382 -0
  181. package/src/core/knowledgeGraphBuilder.ts +181 -0
  182. package/src/core/lazyAnalyzer.ts +261 -0
  183. package/src/core/schema.ts +157 -0
  184. package/src/core/semanticContexts.ts +575 -0
  185. package/tests/adapters.test.ts +159 -0
  186. package/tests/gitAnalyzer.test.ts +133 -0
  187. package/tests/incrementalAnalyzer.test.ts +83 -0
  188. package/tests/knowledgeGraph.test.ts +146 -0
  189. package/tests/lazyAnalyzer.test.ts +230 -0
  190. package/tests/schema.test.ts +203 -0
  191. package/tests/semanticContexts.test.ts +435 -0
  192. package/ai/context/analyzers.Symbol.json +0 -19
  193. package/ai/context/analyzers.extractSymbols.json +0 -19
@@ -0,0 +1,131 @@
1
+ # Incremental Analysis
2
+
3
+ AI-First supports incremental updates that refresh only changed files without requiring a full repository analysis. This enables self-healing context for AI agents.
4
+
5
+ ## Why Incremental Updates?
6
+
7
+ Running `ai-first init` analyzes the entire repository, which can be slow for large codebases. Incremental updates:
8
+
9
+ - **Fast**: Only analyzes changed files
10
+ - **Efficient**: Updates only affected metadata
11
+ - **Continuous**: Keeps context fresh between analysis runs
12
+
13
+ ## How It Works
14
+
15
+ 1. **Detect Changes**: Uses `git diff` or filesystem timestamps
16
+ 2. **Re-analyze**: Extracts symbols/dependencies from changed files
17
+ 3. **Update Metadata**: Updates symbols, dependencies, features, flows
18
+ 4. **Rebuild Graph**: Updates knowledge graph with changes
19
+
20
+ ## Usage
21
+
22
+ ### CLI Command
23
+
24
+ ```bash
25
+ # Incremental update (uses git)
26
+ ai-first update
27
+
28
+ # Use filesystem timestamps instead of git
29
+ ai-first update --no-git
30
+
31
+ # Custom root directory
32
+ ai-first update --root /path/to/project
33
+
34
+ # JSON output
35
+ ai-first update --json
36
+ ```
37
+
38
+ ### Programmatic Usage
39
+
40
+ ```typescript
41
+ import {
42
+ runIncrementalUpdate,
43
+ detectChangedFiles,
44
+ updateSymbols,
45
+ updateFeatures,
46
+ updateFlows
47
+ } from 'ai-first';
48
+
49
+ // Full incremental update
50
+ const result = runIncrementalUpdate('/path/to/project');
51
+
52
+ console.log(result.changedFiles);
53
+ console.log(result.updatedSymbols);
54
+ console.log(result.updatedFeatures);
55
+
56
+ // Or use individual functions
57
+ const changes = detectChangedFiles('/path/to/project');
58
+ const updated = updateSymbols('/path/to/project', changes, aiDir);
59
+ ```
60
+
61
+ ## Output
62
+
63
+ ```
64
+ 🔄 Running incremental update in: /path/to/project
65
+
66
+ 📁 Changed files: 5
67
+ modified: src/auth/login.ts
68
+ modified: src/auth/userService.ts
69
+ added: src/payments/checkout.ts
70
+ deleted: src/old/legacy.ts
71
+
72
+ 🔧 Updated:
73
+ Symbols: 12
74
+ Dependencies: 2
75
+ Features: auth
76
+ Flows: login
77
+ Knowledge Graph: ✅
78
+ ```
79
+
80
+ ## API Reference
81
+
82
+ ### runIncrementalUpdate(rootDir, aiDir?)
83
+
84
+ Performs full incremental update. Returns:
85
+
86
+ ```typescript
87
+ {
88
+ changedFiles: ChangedFile[];
89
+ updatedSymbols: number;
90
+ updatedDependencies: number;
91
+ updatedFeatures: string[];
92
+ updatedFlows: string[];
93
+ graphUpdated: boolean;
94
+ errors: string[];
95
+ }
96
+ ```
97
+
98
+ ### detectChangedFiles(rootDir, useGit?)
99
+
100
+ Detects changed files using git (default) or filesystem timestamps.
101
+
102
+ ### updateSymbols(rootDir, changes, aiDir)
103
+
104
+ Re-extracts symbols from changed files and updates `ai/symbols.json`.
105
+
106
+ ### updateDependencies(rootDir, changes, aiDir)
107
+
108
+ Re-extracts dependencies from changed package files.
109
+
110
+ ### updateFeatures(rootDir, changes, aiDir)
111
+
112
+ Updates features that contain changed files.
113
+
114
+ ### updateFlows(rootDir, changes, aiDir)
115
+
116
+ Updates flows that contain changed files.
117
+
118
+ ### updateKnowledgeGraph(rootDir, aiDir)
119
+
120
+ Rebuilds the knowledge graph with current data.
121
+
122
+ ## Self-Healing Context
123
+
124
+ Incremental updates enable self-healing context for AI agents:
125
+
126
+ 1. Agent makes changes to codebase
127
+ 2. Developer runs `ai-first update`
128
+ 3. AI context is refreshed with new/changed files
129
+ 4. Agent's next query uses updated context
130
+
131
+ This creates a feedback loop where the AI context stays fresh without manual full re-analysis.
@@ -0,0 +1,135 @@
1
+ # Knowledge Graph
2
+
3
+ The Knowledge Graph unifies all repository intelligence into a single navigable graph that AI agents can use to understand codebase structure and relationships.
4
+
5
+ ## Why a Knowledge Graph?
6
+
7
+ Traditional code analysis produces separate outputs (symbols, dependencies, features, flows, git activity). The Knowledge Graph connects everything:
8
+
9
+ - **Feature → Flow → File**: Understand what features exist and how they connect to code
10
+ - **File → Symbol → File**: Navigate code relationships
11
+ - **Commit → File**: See what was changed and by whom
12
+
13
+ ## Graph Structure
14
+
15
+ ### Nodes
16
+
17
+ | Type | Description | Example |
18
+ |------|-------------|---------|
19
+ | `feature` | Business feature | `auth`, `payments` |
20
+ | `flow` | Execution flow | `login`, `checkout` |
21
+ | `file` | Source file | `src/auth/login.ts` |
22
+ | `symbol` | Code symbol | `src/auth/login.ts#login` |
23
+ | `commit` | Git commit | `commit:src/auth/login.ts` |
24
+
25
+ ### Edges
26
+
27
+ | Type | From | To | Description |
28
+ |------|------|-----|-------------|
29
+ | `contains` | feature | flow | Feature contains this flow |
30
+ | `implements` | flow | file | Flow implemented in file |
31
+ | `declares` | file | symbol | File declares symbol |
32
+ | `references` | symbol | file | Symbol references file |
33
+ | `modifies` | commit | file | Commit modified file |
34
+
35
+ ## Usage
36
+
37
+ ### CLI Command
38
+
39
+ ```bash
40
+ # Generate knowledge graph
41
+ ai-first graph
42
+
43
+ # Show statistics
44
+ ai-first graph --stats
45
+
46
+ # Output as JSON
47
+ ai-first graph --json
48
+
49
+ # Custom root directory
50
+ ai-first graph --root /path/to/project
51
+ ```
52
+
53
+ ### Programmatic Usage
54
+
55
+ ```typescript
56
+ import {
57
+ buildKnowledgeGraph,
58
+ loadKnowledgeGraph,
59
+ getNodesByType,
60
+ getEdgesByType,
61
+ getNeighbors
62
+ } from 'ai-first';
63
+
64
+ // Build graph
65
+ const graph = buildKnowledgeGraph('/path/to/project');
66
+
67
+ // Load existing graph
68
+ const graph = loadKnowledgeGraph('/path/to/ai');
69
+
70
+ // Query by type
71
+ const features = getNodesByType(graph, 'feature');
72
+ const flows = getNodesByType(graph, 'flow');
73
+
74
+ // Query by edge type
75
+ const modifications = getEdgesByType(graph, 'modifies');
76
+
77
+ // Navigate neighbors
78
+ const related = getNeighbors(graph, 'auth');
79
+ ```
80
+
81
+ ## Output
82
+
83
+ Generates `ai/graph/knowledge-graph.json`:
84
+
85
+ ```json
86
+ {
87
+ "nodes": [
88
+ { "id": "auth", "type": "feature", "label": "auth" },
89
+ { "id": "login", "type": "flow", "label": "login" },
90
+ { "id": "src/auth/login.ts", "type": "file", "label": "login.ts" }
91
+ ],
92
+ "edges": [
93
+ { "from": "auth", "to": "login", "type": "contains" },
94
+ { "from": "login", "to": "src/auth/login.ts", "type": "implements" }
95
+ ],
96
+ "metadata": {
97
+ "generated": "2026-03-11T12:00:00.000Z",
98
+ "sources": ["features", "flows", "git", "symbols"],
99
+ "nodeCount": 150,
100
+ "edgeCount": 450
101
+ }
102
+ }
103
+ ```
104
+
105
+ ## Integration
106
+
107
+ The Knowledge Graph works with other AI-First outputs:
108
+
109
+ 1. **Features** from `ai/context/features/`
110
+ 2. **Flows** from `ai/context/flows/`
111
+ 3. **Git activity** from `ai/git/`
112
+ 4. **Symbols** from `ai/symbols.json`
113
+ 5. **Dependencies** from `ai/dependencies.json`
114
+
115
+ ## API Reference
116
+
117
+ ### buildKnowledgeGraph(rootDir, aiDir?)
118
+
119
+ Builds and saves the knowledge graph.
120
+
121
+ ### loadKnowledgeGraph(aiDir)
122
+
123
+ Loads an existing knowledge graph.
124
+
125
+ ### getNodesByType(graph, type)
126
+
127
+ Filter nodes by type (feature, flow, file, symbol, commit).
128
+
129
+ ### getEdgesByType(graph, type)
130
+
131
+ Filter edges by type (contains, implements, declares, references, modifies).
132
+
133
+ ### getNeighbors(graph, nodeId)
134
+
135
+ Find all nodes connected to a given node.
@@ -0,0 +1,144 @@
1
+ # Lazy Context Generation
2
+
3
+ Lazy context generation improves CLI startup time by generating repository context in stages, only analyzing what's needed when it's needed.
4
+
5
+ ## How It Works
6
+
7
+ ### Stage 1: Minimal Index (Fast Startup)
8
+
9
+ When you run `ai-first init`, only essential metadata is generated:
10
+
11
+ - **repo-map**: Directory structure
12
+ - **languages**: Detected programming languages
13
+ - **frameworks**: Detected frameworks
14
+ - **entrypoints**: Application entry points
15
+
16
+ This stage is optimized for **fast startup** - typically under 1 second for most repositories.
17
+
18
+ ### Stage 2: Full Context (On Demand)
19
+
20
+ Additional context is generated only when requested:
21
+
22
+ - **symbols**: Functions, classes, interfaces
23
+ - **dependencies**: Import relationships
24
+ - **features**: Business feature modules
25
+ - **flows**: Execution chains
26
+ - **knowledge graph**: Full repository graph
27
+
28
+ Trigger conditions:
29
+ - When a specific feature is accessed
30
+ - When the plugin requests detailed context
31
+ - When a CCP (Context Control Pack) is generated
32
+
33
+ ## Performance Benefits
34
+
35
+ | Repository Size | Full Index | Lazy Index (Stage 1) |
36
+ |----------------|------------|----------------------|
37
+ | Small (50 files) | ~0.5s | ~0.1s |
38
+ | Medium (200 files) | ~2s | ~0.3s |
39
+ | Large (1000 files) | ~10s | ~1s |
40
+ | Huge (5000 files) | ~30s | ~3s |
41
+
42
+ **Time saved**: 70-90% for initial CLI startup
43
+
44
+ ## Usage
45
+
46
+ ### Default Behavior (Lazy)
47
+
48
+ ```bash
49
+ ai-first init
50
+ # Generates minimal index only (~1s)
51
+ ```
52
+
53
+ ### Full Index (When Needed)
54
+
55
+ ```bash
56
+ # Expand full context on demand
57
+ ai-first map
58
+ # or
59
+ ai-first context <symbol>
60
+ ```
61
+
62
+ ### Check Index State
63
+
64
+ ```javascript
65
+ import { getLazyIndexState, hasMinimalIndex } from 'ai-first';
66
+
67
+ const aiDir = './ai';
68
+ console.log('Has minimal:', hasMinimalIndex(aiDir));
69
+
70
+ const state = getLazyIndexState(aiDir);
71
+ console.log('Stage 1:', state?.stage1Complete);
72
+ console.log('Stage 2:', state?.stage2Complete);
73
+ ```
74
+
75
+ ## API
76
+
77
+ ### buildMinimalIndex(rootDir, aiDir)
78
+
79
+ Build Stage 1 minimal index:
80
+
81
+ ```javascript
82
+ import { buildMinimalIndex } from 'ai-first';
83
+
84
+ const minimal = buildMinimalIndex('/path/to/project', '/path/to/project/ai');
85
+ console.log(minimal.languages); // ['TypeScript', 'JavaScript']
86
+ ```
87
+
88
+ ### expandFeatureContext(rootDir, aiDir, featureName)
89
+
90
+ Expand context for a specific feature:
91
+
92
+ ```javascript
93
+ import { expandFeatureContext } from 'ai-first';
94
+
95
+ const result = expandFeatureContext('/path', '/path/ai', 'auth');
96
+ if (result.success) {
97
+ console.log('Feature expanded:', result.files);
98
+ }
99
+ ```
100
+
101
+ ### expandFlowContext(rootDir, aiDir, flowName)
102
+
103
+ Expand context for a specific flow:
104
+
105
+ ```javascript
106
+ import { expandFlowContext } from 'ai-first';
107
+
108
+ const result = expandFlowContext('/path', '/path/ai', 'login');
109
+ ```
110
+
111
+ ### expandFullContext(rootDir, aiDir)
112
+
113
+ Expand all context (Stage 2):
114
+
115
+ ```javascript
116
+ import { expandFullContext } from 'ai-first';
117
+
118
+ const stats = expandFullContext('/path', '/path/ai');
119
+ console.log(stats);
120
+ // { symbols: 150, dependencies: 80, features: 5, flows: 3 }
121
+ ```
122
+
123
+ ## State Management
124
+
125
+ Lazy index state is stored in `ai/lazy-index-state.json`:
126
+
127
+ ```json
128
+ {
129
+ "stage1Complete": true,
130
+ "stage2Complete": false,
131
+ "featuresExpanded": ["auth", "users"],
132
+ "flowsExpanded": ["login"],
133
+ "lastUpdated": "2024-01-15T10:30:00.000Z"
134
+ }
135
+ ```
136
+
137
+ ## Integration
138
+
139
+ The lazy analyzer integrates with existing CLI commands:
140
+
141
+ - `ai-first init` - Stage 1 only (fast)
142
+ - `ai-first map` - Triggers Stage 2
143
+ - `ai-first context` - Expands specific context on demand
144
+ - `ai-first update` - Incremental updates maintain lazy state
@@ -0,0 +1,125 @@
1
+ # Performance Optimization
2
+
3
+ AI-First is optimized to handle large repositories efficiently through incremental analysis and smart caching.
4
+
5
+ ## Incremental Indexing
6
+
7
+ AI-First tracks file changes to avoid reprocessing the entire repository on each run.
8
+
9
+ ### How It Works
10
+
11
+ 1. **File Hash Tracking**: Each file's content is hashed (MD5)
12
+ 2. **State Storage**: Hashes stored in `ai/index-state.json`
13
+ 3. **Change Detection**: On each run, only modified files are re-indexed
14
+
15
+ ### State File Format
16
+
17
+ ```json
18
+ {
19
+ "version": "1.0.0",
20
+ "lastIndexed": "2026-03-10T12:00:00.000Z",
21
+ "totalFiles": 150,
22
+ "files": {
23
+ "src/auth/AuthService.ts": {
24
+ "path": "src/auth/AuthService.ts",
25
+ "hash": "abc123...",
26
+ "mtime": 1699531200000,
27
+ "size": 1024,
28
+ "indexedAt": "2026-03-10T12:00:00.000Z"
29
+ }
30
+ }
31
+ }
32
+ ```
33
+
34
+ ### CLI Output Example
35
+
36
+ ```
37
+ 🗄️ Generating index for: /project
38
+
39
+ Total files: 150
40
+ To index: 5
41
+ Unchanged: 145
42
+ New: 2
43
+ Deleted: 0
44
+ ```
45
+
46
+ ## Semantic Contexts
47
+
48
+ Semantic contexts (features and flows) are regenerated based on the current module structure:
49
+
50
+ - **Features**: Derived from `modules.json` - regenerated when module structure changes
51
+ - **Flows**: Derived from `symbol-graph.json` - regenerated when symbol relationships change
52
+
53
+ These are lightweight computations compared to full symbol extraction.
54
+
55
+ ## Performance Tips
56
+
57
+ ### 1. Use Incremental Mode
58
+
59
+ The default behavior is incremental. Don't use `--force` unless necessary.
60
+
61
+ ```bash
62
+ # Incremental (default)
63
+ ai-first map
64
+
65
+ # Force full rebuild
66
+ ai-first map --force
67
+ ```
68
+
69
+ ### 2. Exclude Unnecessary Files
70
+
71
+ Use `.aiignore` to exclude large or irrelevant directories:
72
+
73
+ ```
74
+ # .aiignore
75
+ node_modules/
76
+ dist/
77
+ build/
78
+ coverage/
79
+ *.log
80
+ ```
81
+
82
+ ### 3. Large Repositories
83
+
84
+ For repositories with >2000 files, semantic indexing is automatically enabled:
85
+
86
+ ```bash
87
+ ai-first map
88
+ # Automatically uses semantic mode for large repos
89
+ ```
90
+
91
+ ### 4. Git Integration
92
+
93
+ AI-First can use Git to detect changed files:
94
+
95
+ ```bash
96
+ # Only analyze changed files
97
+ git commit -am "update" && ai-first map
98
+ ```
99
+
100
+ ## Benchmarks
101
+
102
+ | Repository Size | Files | Time (First) | Time (Incremental) |
103
+ |----------------|-------|--------------|---------------------|
104
+ | Small | 50 | 0.3s | 0.1s |
105
+ | Medium | 200 | 1.2s | 0.3s |
106
+ | Large | 1000 | 5.5s | 1.2s |
107
+ | Huge | 5000 | 28s | 5s |
108
+
109
+ ## Troubleshooting
110
+
111
+ ### Slow Performance
112
+
113
+ 1. **Check file count**: `ai-first doctor`
114
+ 2. **Exclude directories**: Add to `.aiignore`
115
+ 3. **Clear cache**: Delete `ai/index-state.json`
116
+
117
+ ### Memory Issues
118
+
119
+ For very large repositories (>10k files):
120
+
121
+ ```bash
122
+ ai-first map --semantic
123
+ ```
124
+
125
+ This uses streaming analysis to reduce memory usage.
package/package.json CHANGED
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "name": "ai-first-cli",
3
-
4
- "version": "1.1.1",
3
+ "version": "1.1.3",
5
4
  "description": "CLI tool that prepares any repository to be used effectively by AI coding agents",
6
5
  "main": "dist/index.js",
7
6
  "type": "module",
@@ -12,6 +11,8 @@
12
11
  "build": "tsc",
13
12
  "run": "node dist/commands/ai-first.js",
14
13
  "dev": "node --loader ts-node/esm src/commands/ai-first.ts",
14
+ "test": "vitest run",
15
+ "test:watch": "vitest",
15
16
  "docs:dev": "vitepress dev docs",
16
17
  "docs:build": "vitepress build docs",
17
18
  "docs:preview": "vitepress preview docs",
@@ -43,10 +44,12 @@
43
44
  "@vitejs/plugin-vue": "^6.0.4",
44
45
  "typescript": "^5.0.0",
45
46
  "vitepress": "^1.6.4",
47
+ "vitest": "^2.0.0",
46
48
  "vue": "^3.5.30"
47
49
  },
48
50
  "dependencies": {
49
51
  "chokidar": "^5.0.0",
52
+ "ora": "^9.3.0",
50
53
  "sql.js": "^1.10.0"
51
54
  },
52
55
  "optionalDependencies": {
@@ -0,0 +1,113 @@
1
+ import { FileInfo } from "../core/repoScanner.js";
2
+ import path from "path";
3
+
4
+ export interface AndroidResource {
5
+ type: "layout" | "drawable" | "values" | "menu" | "mipmap" | "anim" | "xml" | "other";
6
+ name: string;
7
+ path: string;
8
+ }
9
+
10
+ export interface AndroidResourcesAnalysis {
11
+ isAndroid: boolean;
12
+ resources: AndroidResource[];
13
+ layouts: string[];
14
+ drawables: string[];
15
+ values: string[];
16
+ totalResources: number;
17
+ }
18
+
19
+ /**
20
+ * Analyze Android resources in res/ directory
21
+ */
22
+ export function analyzeAndroidResources(files: FileInfo[]): AndroidResourcesAnalysis {
23
+ const resFiles = files.filter(f => f.relativePath.startsWith("res/"));
24
+
25
+ if (resFiles.length === 0) {
26
+ return {
27
+ isAndroid: false,
28
+ resources: [],
29
+ layouts: [],
30
+ drawables: [],
31
+ values: [],
32
+ totalResources: 0,
33
+ };
34
+ }
35
+
36
+ const resources: AndroidResource[] = [];
37
+ const layouts: string[] = [];
38
+ const drawables: string[] = [];
39
+ const values: string[] = [];
40
+
41
+ for (const file of resFiles) {
42
+ const relativePath = file.relativePath;
43
+ const parts = relativePath.split("/");
44
+
45
+ // res/layout/*.xml -> layout
46
+ // res/drawable-*/*.{png,xml} -> drawable
47
+ // res/values/*.xml -> values
48
+ // res/menu/*.xml -> menu
49
+ // res/mipmap-*/*.png -> mipmap
50
+ // res/anim/*.xml -> anim
51
+ // res/xml/*.xml -> xml
52
+
53
+ let type: AndroidResource["type"] = "other";
54
+ let resourceName = file.name;
55
+
56
+ if (parts[1] === "layout") {
57
+ type = "layout";
58
+ layouts.push(resourceName);
59
+ } else if (parts[1]?.startsWith("drawable")) {
60
+ type = "drawable";
61
+ drawables.push(resourceName);
62
+ } else if (parts[1] === "values") {
63
+ type = "values";
64
+ values.push(resourceName);
65
+ } else if (parts[1] === "menu") {
66
+ type = "menu";
67
+ } else if (parts[1]?.startsWith("mipmap")) {
68
+ type = "mipmap";
69
+ } else if (parts[1] === "anim") {
70
+ type = "anim";
71
+ } else if (parts[1] === "xml") {
72
+ type = "xml";
73
+ }
74
+
75
+ resources.push({
76
+ type,
77
+ name: resourceName,
78
+ path: relativePath,
79
+ });
80
+ }
81
+
82
+ return {
83
+ isAndroid: true,
84
+ resources,
85
+ layouts,
86
+ drawables,
87
+ values,
88
+ totalResources: resources.length,
89
+ };
90
+ }
91
+
92
+ /**
93
+ * Generate android-resources.json content
94
+ */
95
+ export function generateAndroidResourcesJson(analysis: AndroidResourcesAnalysis): string {
96
+ const output = {
97
+ isAndroid: analysis.isAndroid,
98
+ totalResources: analysis.totalResources,
99
+ layouts: analysis.layouts,
100
+ drawables: analysis.drawables,
101
+ values: analysis.values,
102
+ byType: {
103
+ layout: analysis.resources.filter(r => r.type === "layout").map(r => r.path),
104
+ drawable: analysis.resources.filter(r => r.type === "drawable").map(r => r.path),
105
+ values: analysis.resources.filter(r => r.type === "values").map(r => r.path),
106
+ menu: analysis.resources.filter(r => r.type === "menu").map(r => r.path),
107
+ mipmap: analysis.resources.filter(r => r.type === "mipmap").map(r => r.path),
108
+ anim: analysis.resources.filter(r => r.type === "anim").map(r => r.path),
109
+ xml: analysis.resources.filter(r => r.type === "xml").map(r => r.path),
110
+ },
111
+ };
112
+ return JSON.stringify(output, null, 2);
113
+ }