ai-first-cli 1.3.1 → 1.3.5

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 (532) hide show
  1. package/.ai-dev/index.db +0 -0
  2. package/BETA_EVALUATION_REPORT.md +151 -0
  3. package/CHANGELOG.md +178 -0
  4. package/PHASE1_USER_SIMULATION.md +56 -0
  5. package/PHASE2_USER_SIMULATION.md +81 -0
  6. package/PHASE3_USER_SIMULATION.md +176 -0
  7. package/README.es.md +18 -0
  8. package/README.md +80 -1
  9. package/ai/graph/knowledge-graph.json +10 -0
  10. package/ai-context/ai_context.md +130 -0
  11. package/{test-projects/react-app/.ai-dev → ai-context}/ai_rules.md +10 -5
  12. package/ai-context/architecture.md +136 -0
  13. package/ai-context/context/features/src.json +69 -0
  14. package/ai-context/context/features/test-projects.json +69 -0
  15. package/ai-context/context/flows/App.json +17 -0
  16. package/ai-context/context/flows/DashboardPage.json +14 -0
  17. package/ai-context/context/flows/LoginPage.json +14 -0
  18. package/ai-context/context/flows/admin.json +10 -0
  19. package/ai-context/context/flows/ai-first.json +9 -0
  20. package/ai-context/context/flows/androidresources.json +11 -0
  21. package/ai-context/context/flows/auth.json +13 -0
  22. package/ai-context/context/flows/authController.json +14 -0
  23. package/ai-context/context/flows/doctor.json +9 -0
  24. package/ai-context/context/flows/entrypoints.json +9 -0
  25. package/ai-context/context/flows/explore.json +9 -0
  26. package/ai-context/context/flows/fastapiAdapter.json +14 -0
  27. package/ai-context/context/flows/fastapiadapter.json +11 -0
  28. package/ai-context/context/flows/index.json +19 -0
  29. package/ai-context/context/flows/indexer.json +9 -0
  30. package/ai-context/context/flows/indexstate.json +9 -0
  31. package/ai-context/context/flows/init.json +22 -0
  32. package/ai-context/context/flows/main.json +18 -0
  33. package/ai-context/context/flows/mainactivity.json +9 -0
  34. package/ai-context/context/flows/models.json +15 -0
  35. package/ai-context/context/flows/posts.json +15 -0
  36. package/ai-context/context/flows/repoMapper.json +20 -0
  37. package/ai-context/context/flows/repomapper.json +11 -0
  38. package/ai-context/context/flows/routes.json +15 -0
  39. package/ai-context/context/flows/serializers.json +10 -0
  40. package/ai-context/context/flows/user.json +23 -0
  41. package/ai-context/context/flows/views.json +12 -0
  42. package/{test-projects/react-app/.ai-dev → ai-context}/conventions.md +3 -2
  43. package/ai-context/dependencies.json +3360 -0
  44. package/ai-context/entrypoints.md +45 -0
  45. package/ai-context/index-state.json +196 -0
  46. package/ai-context/modules.json +901 -0
  47. package/ai-context/project.json +33 -0
  48. package/ai-context/repo_map.json +8857 -0
  49. package/ai-context/repo_map.md +2002 -0
  50. package/{test-projects/flask-app/.ai-dev → ai-context}/schema.json +1 -1
  51. package/ai-context/summary.md +46 -0
  52. package/ai-context/symbols.json +82467 -0
  53. package/{test-projects/react-app/.ai-dev → ai-context}/tech_stack.md +15 -7
  54. package/ai-context-evaluation-report-1774223059505.md +206 -0
  55. package/dist/analyzers/architecture.d.ts.map +1 -1
  56. package/dist/analyzers/architecture.js +6 -0
  57. package/dist/analyzers/architecture.js.map +1 -1
  58. package/dist/analyzers/entrypoints.d.ts.map +1 -1
  59. package/dist/analyzers/entrypoints.js +105 -0
  60. package/dist/analyzers/entrypoints.js.map +1 -1
  61. package/dist/analyzers/symbols.d.ts.map +1 -1
  62. package/dist/analyzers/symbols.js +72 -1
  63. package/dist/analyzers/symbols.js.map +1 -1
  64. package/dist/analyzers/techStack.d.ts +8 -0
  65. package/dist/analyzers/techStack.d.ts.map +1 -1
  66. package/dist/analyzers/techStack.js +75 -0
  67. package/dist/analyzers/techStack.js.map +1 -1
  68. package/dist/scripts/ai-context-evaluator.js +367 -0
  69. package/package.json +1 -1
  70. package/quick-evaluation-report-1774396002305.md +64 -0
  71. package/quick-evaluator.ts +200 -0
  72. package/scripts/ai-context-evaluator.ts +440 -0
  73. package/src/analyzers/architecture.ts +8 -0
  74. package/src/analyzers/entrypoints.ts +115 -0
  75. package/src/analyzers/symbols.ts +77 -1
  76. package/src/analyzers/techStack.ts +93 -0
  77. package/tests/apex-parser.test.ts +193 -0
  78. package/tests/cli-commands-batch1.test.ts +808 -0
  79. package/tests/cli-commands-batch2.test.ts +1113 -0
  80. package/tests/cli-commands-batch3.test.ts +1128 -0
  81. package/tests/cli-index.test.ts +1007 -0
  82. package/tests/cli-init.test.ts +761 -0
  83. package/tests/salesforce-apex-classes.test.ts +713 -0
  84. package/tests/salesforce-apex-triggers.test.ts +871 -0
  85. package/tests/salesforce-custom-objects.test.ts +918 -0
  86. package/tests/salesforce-flows.test.ts +710 -0
  87. package/tests/salesforce-lwc.test.ts +963 -0
  88. package/tests/salesforce-sfdx-integration.test.ts +1125 -0
  89. package/ANALISIS_COMPLETO.md +0 -424
  90. package/ANALISIS_MEJORAS.md +0 -327
  91. package/CONTRIBUTING.md +0 -89
  92. package/FLOW.md +0 -129
  93. package/TEST_RESULTS.md +0 -198
  94. package/TEST_RESULTS_COMPARATIVE.md +0 -159
  95. package/TEST_RESULTS_COMPLETE.md +0 -127
  96. package/TEST_RESULTS_COMPREHENSIVE.md +0 -208
  97. package/install.sh +0 -188
  98. package/run-all-tests.sh +0 -184
  99. package/test-ai-context-understanding.sh +0 -21
  100. package/test-projects/django-app/.ai-dev/ai_context.md +0 -92
  101. package/test-projects/django-app/.ai-dev/ai_rules.md +0 -47
  102. package/test-projects/django-app/.ai-dev/architecture.md +0 -57
  103. package/test-projects/django-app/.ai-dev/cache.json +0 -169
  104. package/test-projects/django-app/.ai-dev/context/flows/views.json +0 -10
  105. package/test-projects/django-app/.ai-dev/conventions.md +0 -51
  106. package/test-projects/django-app/.ai-dev/dependencies.json +0 -312
  107. package/test-projects/django-app/.ai-dev/entrypoints.md +0 -4
  108. package/test-projects/django-app/.ai-dev/files.json +0 -209
  109. package/test-projects/django-app/.ai-dev/graph/knowledge-graph.json +0 -36
  110. package/test-projects/django-app/.ai-dev/graph/module-graph.json +0 -145
  111. package/test-projects/django-app/.ai-dev/graph/symbol-graph.json +0 -1488
  112. package/test-projects/django-app/.ai-dev/graph/symbol-references.json +0 -1
  113. package/test-projects/django-app/.ai-dev/index-state.json +0 -294
  114. package/test-projects/django-app/.ai-dev/modules.json +0 -35
  115. package/test-projects/django-app/.ai-dev/project.json +0 -11
  116. package/test-projects/django-app/.ai-dev/repo_map.json +0 -412
  117. package/test-projects/django-app/.ai-dev/repo_map.md +0 -105
  118. package/test-projects/django-app/.ai-dev/schema.json +0 -5
  119. package/test-projects/django-app/.ai-dev/summary.md +0 -15
  120. package/test-projects/django-app/.ai-dev/symbols.json +0 -1
  121. package/test-projects/django-app/.ai-dev/tech_stack.md +0 -32
  122. package/test-projects/django-app/README.md +0 -91
  123. package/test-projects/django-app/blog/__init__.py +0 -0
  124. package/test-projects/django-app/blog/admin.py +0 -31
  125. package/test-projects/django-app/blog/models.py +0 -55
  126. package/test-projects/django-app/blog/serializers.py +0 -69
  127. package/test-projects/django-app/blog/urls.py +0 -14
  128. package/test-projects/django-app/blog/views.py +0 -96
  129. package/test-projects/django-app/django_app/__init__.py +0 -0
  130. package/test-projects/django-app/django_app/settings.py +0 -90
  131. package/test-projects/django-app/django_app/urls.py +0 -11
  132. package/test-projects/django-app/django_app/wsgi.py +0 -9
  133. package/test-projects/django-app/manage.py +0 -23
  134. package/test-projects/django-app/requirements.txt +0 -3
  135. package/test-projects/django-app/users/__init__.py +0 -0
  136. package/test-projects/django-app/users/admin.py +0 -42
  137. package/test-projects/django-app/users/models.py +0 -54
  138. package/test-projects/django-app/users/serializers.py +0 -113
  139. package/test-projects/django-app/users/urls.py +0 -13
  140. package/test-projects/django-app/users/views.py +0 -135
  141. package/test-projects/express-api/.ai-dev/ai_context.md +0 -112
  142. package/test-projects/express-api/.ai-dev/ai_rules.md +0 -50
  143. package/test-projects/express-api/.ai-dev/architecture.md +0 -62
  144. package/test-projects/express-api/.ai-dev/context/features/controllers.json +0 -13
  145. package/test-projects/express-api/.ai-dev/context/features/services.json +0 -13
  146. package/test-projects/express-api/.ai-dev/context/flows/auth.json +0 -12
  147. package/test-projects/express-api/.ai-dev/context/flows/user.json +0 -13
  148. package/test-projects/express-api/.ai-dev/conventions.md +0 -51
  149. package/test-projects/express-api/.ai-dev/dependencies.json +0 -54
  150. package/test-projects/express-api/.ai-dev/entrypoints.md +0 -17
  151. package/test-projects/express-api/.ai-dev/modules.json +0 -30
  152. package/test-projects/express-api/.ai-dev/project.json +0 -15
  153. package/test-projects/express-api/.ai-dev/repo_map.json +0 -100
  154. package/test-projects/express-api/.ai-dev/repo_map.md +0 -36
  155. package/test-projects/express-api/.ai-dev/schema.json +0 -5
  156. package/test-projects/express-api/.ai-dev/summary.md +0 -14
  157. package/test-projects/express-api/.ai-dev/symbols.json +0 -7
  158. package/test-projects/express-api/.ai-dev/tech_stack.md +0 -38
  159. package/test-projects/express-api/.ai-dev/tools.json +0 -10
  160. package/test-projects/express-api/controllers/authController.js +0 -32
  161. package/test-projects/express-api/controllers/userController.js +0 -51
  162. package/test-projects/express-api/index.js +0 -30
  163. package/test-projects/express-api/middleware/authMiddleware.js +0 -30
  164. package/test-projects/express-api/models/userRepository.js +0 -25
  165. package/test-projects/express-api/package.json +0 -18
  166. package/test-projects/express-api/services/authService.js +0 -17
  167. package/test-projects/express-api/services/userService.js +0 -28
  168. package/test-projects/fastapi-app/.ai-dev/ai_context.md +0 -89
  169. package/test-projects/fastapi-app/.ai-dev/ai_rules.md +0 -47
  170. package/test-projects/fastapi-app/.ai-dev/architecture.md +0 -39
  171. package/test-projects/fastapi-app/.ai-dev/cache.json +0 -125
  172. package/test-projects/fastapi-app/.ai-dev/conventions.md +0 -51
  173. package/test-projects/fastapi-app/.ai-dev/dependencies.json +0 -244
  174. package/test-projects/fastapi-app/.ai-dev/entrypoints.md +0 -4
  175. package/test-projects/fastapi-app/.ai-dev/files.json +0 -154
  176. package/test-projects/fastapi-app/.ai-dev/graph/knowledge-graph.json +0 -15
  177. package/test-projects/fastapi-app/.ai-dev/graph/module-graph.json +0 -78
  178. package/test-projects/fastapi-app/.ai-dev/graph/symbol-graph.json +0 -1724
  179. package/test-projects/fastapi-app/.ai-dev/graph/symbol-references.json +0 -51
  180. package/test-projects/fastapi-app/.ai-dev/index-state.json +0 -217
  181. package/test-projects/fastapi-app/.ai-dev/modules.json +0 -16
  182. package/test-projects/fastapi-app/.ai-dev/project.json +0 -9
  183. package/test-projects/fastapi-app/.ai-dev/repo_map.json +0 -298
  184. package/test-projects/fastapi-app/.ai-dev/repo_map.md +0 -74
  185. package/test-projects/fastapi-app/.ai-dev/schema.json +0 -5
  186. package/test-projects/fastapi-app/.ai-dev/summary.md +0 -12
  187. package/test-projects/fastapi-app/.ai-dev/symbols.json +0 -1
  188. package/test-projects/fastapi-app/.ai-dev/tech_stack.md +0 -32
  189. package/test-projects/fastapi-app/.ai-dev/tools.json +0 -10
  190. package/test-projects/fastapi-app/README.md +0 -118
  191. package/test-projects/fastapi-app/app/database.py +0 -21
  192. package/test-projects/fastapi-app/app/dependencies.py +0 -107
  193. package/test-projects/fastapi-app/app/main.py +0 -47
  194. package/test-projects/fastapi-app/app/models.py +0 -149
  195. package/test-projects/fastapi-app/app/routers/auth.py +0 -117
  196. package/test-projects/fastapi-app/app/routers/posts.py +0 -272
  197. package/test-projects/fastapi-app/app/schemas.py +0 -191
  198. package/test-projects/fastapi-app/requirements.txt +0 -10
  199. package/test-projects/flask-app/.ai-dev/ai_context.md +0 -94
  200. package/test-projects/flask-app/.ai-dev/ai_rules.md +0 -47
  201. package/test-projects/flask-app/.ai-dev/architecture.md +0 -49
  202. package/test-projects/flask-app/.ai-dev/cache.json +0 -157
  203. package/test-projects/flask-app/.ai-dev/context/features/app.json +0 -25
  204. package/test-projects/flask-app/.ai-dev/context/flows/routes.json +0 -14
  205. package/test-projects/flask-app/.ai-dev/conventions.md +0 -51
  206. package/test-projects/flask-app/.ai-dev/dependencies.json +0 -298
  207. package/test-projects/flask-app/.ai-dev/entrypoints.md +0 -4
  208. package/test-projects/flask-app/.ai-dev/files.json +0 -194
  209. package/test-projects/flask-app/.ai-dev/graph/knowledge-graph.json +0 -60
  210. package/test-projects/flask-app/.ai-dev/graph/module-graph.json +0 -95
  211. package/test-projects/flask-app/.ai-dev/graph/symbol-graph.json +0 -1448
  212. package/test-projects/flask-app/.ai-dev/graph/symbol-references.json +0 -45
  213. package/test-projects/flask-app/.ai-dev/index-state.json +0 -273
  214. package/test-projects/flask-app/.ai-dev/modules.json +0 -21
  215. package/test-projects/flask-app/.ai-dev/project.json +0 -13
  216. package/test-projects/flask-app/.ai-dev/repo_map.json +0 -400
  217. package/test-projects/flask-app/.ai-dev/repo_map.md +0 -98
  218. package/test-projects/flask-app/.ai-dev/summary.md +0 -13
  219. package/test-projects/flask-app/.ai-dev/symbols.json +0 -1
  220. package/test-projects/flask-app/.ai-dev/tech_stack.md +0 -32
  221. package/test-projects/flask-app/.ai-dev/tools.json +0 -10
  222. package/test-projects/flask-app/README.md +0 -129
  223. package/test-projects/flask-app/app/__init__.py +0 -46
  224. package/test-projects/flask-app/app/api/__init__.py +0 -7
  225. package/test-projects/flask-app/app/api/routes.py +0 -122
  226. package/test-projects/flask-app/app/auth/__init__.py +0 -7
  227. package/test-projects/flask-app/app/auth/forms.py +0 -52
  228. package/test-projects/flask-app/app/auth/routes.py +0 -68
  229. package/test-projects/flask-app/app/blog/__init__.py +0 -7
  230. package/test-projects/flask-app/app/blog/forms.py +0 -35
  231. package/test-projects/flask-app/app/blog/routes.py +0 -140
  232. package/test-projects/flask-app/app/main/__init__.py +0 -7
  233. package/test-projects/flask-app/app/main/routes.py +0 -88
  234. package/test-projects/flask-app/app/models.py +0 -177
  235. package/test-projects/flask-app/config.py +0 -64
  236. package/test-projects/flask-app/requirements.txt +0 -10
  237. package/test-projects/laravel-app/.ai-dev/ai_context.md +0 -97
  238. package/test-projects/laravel-app/.ai-dev/ai_rules.md +0 -47
  239. package/test-projects/laravel-app/.ai-dev/architecture.md +0 -60
  240. package/test-projects/laravel-app/.ai-dev/cache.json +0 -161
  241. package/test-projects/laravel-app/.ai-dev/context/features/app.json +0 -21
  242. package/test-projects/laravel-app/.ai-dev/context/flows/.json +0 -9
  243. package/test-projects/laravel-app/.ai-dev/context/flows/category.json +0 -12
  244. package/test-projects/laravel-app/.ai-dev/context/flows/comment.json +0 -12
  245. package/test-projects/laravel-app/.ai-dev/context/flows/post.json +0 -12
  246. package/test-projects/laravel-app/.ai-dev/context/flows/unnamed.json +0 -9
  247. package/test-projects/laravel-app/.ai-dev/conventions.md +0 -51
  248. package/test-projects/laravel-app/.ai-dev/dependencies.json +0 -6
  249. package/test-projects/laravel-app/.ai-dev/entrypoints.md +0 -4
  250. package/test-projects/laravel-app/.ai-dev/files.json +0 -199
  251. package/test-projects/laravel-app/.ai-dev/graph/knowledge-graph.json +0 -98
  252. package/test-projects/laravel-app/.ai-dev/graph/module-graph.json +0 -30
  253. package/test-projects/laravel-app/.ai-dev/graph/symbol-graph.json +0 -5
  254. package/test-projects/laravel-app/.ai-dev/graph/symbol-references.json +0 -1
  255. package/test-projects/laravel-app/.ai-dev/index-state.json +0 -280
  256. package/test-projects/laravel-app/.ai-dev/modules.json +0 -29
  257. package/test-projects/laravel-app/.ai-dev/project.json +0 -17
  258. package/test-projects/laravel-app/.ai-dev/repo_map.json +0 -419
  259. package/test-projects/laravel-app/.ai-dev/repo_map.md +0 -106
  260. package/test-projects/laravel-app/.ai-dev/schema.json +0 -5
  261. package/test-projects/laravel-app/.ai-dev/summary.md +0 -15
  262. package/test-projects/laravel-app/.ai-dev/symbols.json +0 -1
  263. package/test-projects/laravel-app/.ai-dev/tech_stack.md +0 -34
  264. package/test-projects/laravel-app/.ai-dev/tools.json +0 -10
  265. package/test-projects/laravel-app/README.md +0 -107
  266. package/test-projects/laravel-app/app/Http/Controllers/Api/CategoryController.php +0 -88
  267. package/test-projects/laravel-app/app/Http/Controllers/Api/CommentController.php +0 -56
  268. package/test-projects/laravel-app/app/Http/Controllers/Api/PostController.php +0 -174
  269. package/test-projects/laravel-app/app/Http/Controllers/Controller.php +0 -12
  270. package/test-projects/laravel-app/app/Models/Category.php +0 -34
  271. package/test-projects/laravel-app/app/Models/Comment.php +0 -51
  272. package/test-projects/laravel-app/app/Models/Post.php +0 -108
  273. package/test-projects/laravel-app/app/Models/User.php +0 -85
  274. package/test-projects/laravel-app/bootstrap/app.php +0 -25
  275. package/test-projects/laravel-app/composer.json +0 -35
  276. package/test-projects/laravel-app/routes/api.php +0 -40
  277. package/test-projects/nestjs-backend/.ai-dev/ai_context.md +0 -111
  278. package/test-projects/nestjs-backend/.ai-dev/ai_rules.md +0 -52
  279. package/test-projects/nestjs-backend/.ai-dev/architecture.md +0 -49
  280. package/test-projects/nestjs-backend/.ai-dev/cache.json +0 -169
  281. package/test-projects/nestjs-backend/.ai-dev/context/features/src.json +0 -23
  282. package/test-projects/nestjs-backend/.ai-dev/context/flows/auth.controller.json +0 -14
  283. package/test-projects/nestjs-backend/.ai-dev/context/flows/auth.json +0 -10
  284. package/test-projects/nestjs-backend/.ai-dev/context/flows/users..json +0 -10
  285. package/test-projects/nestjs-backend/.ai-dev/context/flows/users.controller.json +0 -14
  286. package/test-projects/nestjs-backend/.ai-dev/context/flows/users.json +0 -10
  287. package/test-projects/nestjs-backend/.ai-dev/conventions.md +0 -52
  288. package/test-projects/nestjs-backend/.ai-dev/dependencies.json +0 -152
  289. package/test-projects/nestjs-backend/.ai-dev/entrypoints.md +0 -18
  290. package/test-projects/nestjs-backend/.ai-dev/files.json +0 -209
  291. package/test-projects/nestjs-backend/.ai-dev/graph/knowledge-graph.json +0 -132
  292. package/test-projects/nestjs-backend/.ai-dev/graph/module-graph.json +0 -29
  293. package/test-projects/nestjs-backend/.ai-dev/graph/symbol-graph.json +0 -304
  294. package/test-projects/nestjs-backend/.ai-dev/graph/symbol-references.json +0 -5
  295. package/test-projects/nestjs-backend/.ai-dev/index-state.json +0 -294
  296. package/test-projects/nestjs-backend/.ai-dev/modules.json +0 -19
  297. package/test-projects/nestjs-backend/.ai-dev/project.json +0 -18
  298. package/test-projects/nestjs-backend/.ai-dev/repo_map.json +0 -427
  299. package/test-projects/nestjs-backend/.ai-dev/repo_map.md +0 -104
  300. package/test-projects/nestjs-backend/.ai-dev/schema.json +0 -5
  301. package/test-projects/nestjs-backend/.ai-dev/summary.md +0 -13
  302. package/test-projects/nestjs-backend/.ai-dev/symbols.json +0 -1
  303. package/test-projects/nestjs-backend/.ai-dev/tech_stack.md +0 -38
  304. package/test-projects/nestjs-backend/.ai-dev/tools.json +0 -10
  305. package/test-projects/nestjs-backend/package.json +0 -22
  306. package/test-projects/nestjs-backend/src/app.module.ts +0 -8
  307. package/test-projects/nestjs-backend/src/auth/auth.controller.ts +0 -22
  308. package/test-projects/nestjs-backend/src/auth/auth.module.ts +0 -11
  309. package/test-projects/nestjs-backend/src/auth/auth.service.ts +0 -28
  310. package/test-projects/nestjs-backend/src/auth/dto/login.dto.ts +0 -4
  311. package/test-projects/nestjs-backend/src/auth/strategies/jwt.strategy.ts +0 -18
  312. package/test-projects/nestjs-backend/src/main.ts +0 -9
  313. package/test-projects/nestjs-backend/src/users/users.controller.ts +0 -32
  314. package/test-projects/nestjs-backend/src/users/users.module.ts +0 -10
  315. package/test-projects/nestjs-backend/src/users/users.service.ts +0 -42
  316. package/test-projects/nestjs-backend/tsconfig.json +0 -21
  317. package/test-projects/python-cli/.ai-dev/ai_context.md +0 -95
  318. package/test-projects/python-cli/.ai-dev/ai_rules.md +0 -47
  319. package/test-projects/python-cli/.ai-dev/architecture.md +0 -55
  320. package/test-projects/python-cli/.ai-dev/cache.json +0 -149
  321. package/test-projects/python-cli/.ai-dev/context/features/cli.json +0 -16
  322. package/test-projects/python-cli/.ai-dev/context/flows/list_.json +0 -9
  323. package/test-projects/python-cli/.ai-dev/context/flows/remove_.json +0 -9
  324. package/test-projects/python-cli/.ai-dev/conventions.md +0 -51
  325. package/test-projects/python-cli/.ai-dev/dependencies.json +0 -66
  326. package/test-projects/python-cli/.ai-dev/entrypoints.md +0 -4
  327. package/test-projects/python-cli/.ai-dev/files.json +0 -184
  328. package/test-projects/python-cli/.ai-dev/graph/knowledge-graph.json +0 -83
  329. package/test-projects/python-cli/.ai-dev/graph/module-graph.json +0 -31
  330. package/test-projects/python-cli/.ai-dev/graph/symbol-graph.json +0 -358
  331. package/test-projects/python-cli/.ai-dev/graph/symbol-references.json +0 -11
  332. package/test-projects/python-cli/.ai-dev/index-state.json +0 -259
  333. package/test-projects/python-cli/.ai-dev/modules.json +0 -21
  334. package/test-projects/python-cli/.ai-dev/project.json +0 -15
  335. package/test-projects/python-cli/.ai-dev/repo_map.json +0 -367
  336. package/test-projects/python-cli/.ai-dev/repo_map.md +0 -93
  337. package/test-projects/python-cli/.ai-dev/schema.json +0 -5
  338. package/test-projects/python-cli/.ai-dev/summary.md +0 -14
  339. package/test-projects/python-cli/.ai-dev/symbols.json +0 -1
  340. package/test-projects/python-cli/.ai-dev/tech_stack.md +0 -32
  341. package/test-projects/python-cli/.ai-dev/tools.json +0 -10
  342. package/test-projects/python-cli/__init__.py +0 -1
  343. package/test-projects/python-cli/cli/__init__.py +0 -1
  344. package/test-projects/python-cli/cli/add_command.py +0 -6
  345. package/test-projects/python-cli/cli/list_command.py +0 -7
  346. package/test-projects/python-cli/cli/remove_command.py +0 -6
  347. package/test-projects/python-cli/main.py +0 -34
  348. package/test-projects/python-cli/models/__init__.py +0 -2
  349. package/test-projects/python-cli/models/task.py +0 -19
  350. package/test-projects/python-cli/models/task_repository.py +0 -44
  351. package/test-projects/rails-app/.ai-dev/ai_context.md +0 -94
  352. package/test-projects/rails-app/.ai-dev/ai_rules.md +0 -47
  353. package/test-projects/rails-app/.ai-dev/architecture.md +0 -49
  354. package/test-projects/rails-app/.ai-dev/cache.json +0 -193
  355. package/test-projects/rails-app/.ai-dev/context/features/app.json +0 -24
  356. package/test-projects/rails-app/.ai-dev/context/features/config.json +0 -13
  357. package/test-projects/rails-app/.ai-dev/context/flows/application.json +0 -9
  358. package/test-projects/rails-app/.ai-dev/context/flows/application_.json +0 -9
  359. package/test-projects/rails-app/.ai-dev/context/flows/comments.json +0 -11
  360. package/test-projects/rails-app/.ai-dev/context/flows/comments_.json +0 -11
  361. package/test-projects/rails-app/.ai-dev/context/flows/posts.json +0 -11
  362. package/test-projects/rails-app/.ai-dev/context/flows/posts_.json +0 -11
  363. package/test-projects/rails-app/.ai-dev/context/flows/routes.json +0 -9
  364. package/test-projects/rails-app/.ai-dev/context/flows/users.json +0 -11
  365. package/test-projects/rails-app/.ai-dev/context/flows/users_.json +0 -11
  366. package/test-projects/rails-app/.ai-dev/conventions.md +0 -51
  367. package/test-projects/rails-app/.ai-dev/dependencies.json +0 -6
  368. package/test-projects/rails-app/.ai-dev/entrypoints.md +0 -4
  369. package/test-projects/rails-app/.ai-dev/files.json +0 -239
  370. package/test-projects/rails-app/.ai-dev/graph/knowledge-graph.json +0 -130
  371. package/test-projects/rails-app/.ai-dev/graph/module-graph.json +0 -27
  372. package/test-projects/rails-app/.ai-dev/graph/symbol-graph.json +0 -5
  373. package/test-projects/rails-app/.ai-dev/graph/symbol-references.json +0 -1
  374. package/test-projects/rails-app/.ai-dev/index-state.json +0 -336
  375. package/test-projects/rails-app/.ai-dev/modules.json +0 -26
  376. package/test-projects/rails-app/.ai-dev/project.json +0 -22
  377. package/test-projects/rails-app/.ai-dev/repo_map.json +0 -486
  378. package/test-projects/rails-app/.ai-dev/repo_map.md +0 -117
  379. package/test-projects/rails-app/.ai-dev/schema.json +0 -5
  380. package/test-projects/rails-app/.ai-dev/summary.md +0 -13
  381. package/test-projects/rails-app/.ai-dev/symbols.json +0 -1
  382. package/test-projects/rails-app/.ai-dev/tech_stack.md +0 -32
  383. package/test-projects/rails-app/.ai-dev/tools.json +0 -10
  384. package/test-projects/rails-app/Gemfile +0 -38
  385. package/test-projects/rails-app/README.md +0 -140
  386. package/test-projects/rails-app/Rakefile +0 -8
  387. package/test-projects/rails-app/app/controllers/api/comments_controller.rb +0 -75
  388. package/test-projects/rails-app/app/controllers/api/posts_controller.rb +0 -68
  389. package/test-projects/rails-app/app/controllers/api/users_controller.rb +0 -54
  390. package/test-projects/rails-app/app/controllers/application_controller.rb +0 -31
  391. package/test-projects/rails-app/app/models/comment.rb +0 -34
  392. package/test-projects/rails-app/app/models/post.rb +0 -36
  393. package/test-projects/rails-app/app/models/user.rb +0 -28
  394. package/test-projects/rails-app/app/services/post_service.rb +0 -92
  395. package/test-projects/rails-app/app/services/user_service.rb +0 -76
  396. package/test-projects/rails-app/config/application.rb +0 -27
  397. package/test-projects/rails-app/config/environment.rb +0 -7
  398. package/test-projects/rails-app/config/routes.rb +0 -15
  399. package/test-projects/react-app/.ai-dev/ai_context.md +0 -96
  400. package/test-projects/react-app/.ai-dev/architecture.md +0 -39
  401. package/test-projects/react-app/.ai-dev/cache.json +0 -153
  402. package/test-projects/react-app/.ai-dev/context/features/src.json +0 -18
  403. package/test-projects/react-app/.ai-dev/context/flows/UsersPage.json +0 -14
  404. package/test-projects/react-app/.ai-dev/context/flows/dashboard.json +0 -9
  405. package/test-projects/react-app/.ai-dev/context/flows/login.json +0 -9
  406. package/test-projects/react-app/.ai-dev/context/flows/users.json +0 -9
  407. package/test-projects/react-app/.ai-dev/dependencies.json +0 -128
  408. package/test-projects/react-app/.ai-dev/entrypoints.md +0 -4
  409. package/test-projects/react-app/.ai-dev/files.json +0 -189
  410. package/test-projects/react-app/.ai-dev/graph/knowledge-graph.json +0 -112
  411. package/test-projects/react-app/.ai-dev/graph/module-graph.json +0 -31
  412. package/test-projects/react-app/.ai-dev/graph/symbol-graph.json +0 -868
  413. package/test-projects/react-app/.ai-dev/graph/symbol-references.json +0 -31
  414. package/test-projects/react-app/.ai-dev/index-state.json +0 -266
  415. package/test-projects/react-app/.ai-dev/modules.json +0 -17
  416. package/test-projects/react-app/.ai-dev/project.json +0 -16
  417. package/test-projects/react-app/.ai-dev/repo_map.json +0 -391
  418. package/test-projects/react-app/.ai-dev/repo_map.md +0 -94
  419. package/test-projects/react-app/.ai-dev/schema.json +0 -5
  420. package/test-projects/react-app/.ai-dev/summary.md +0 -13
  421. package/test-projects/react-app/.ai-dev/symbols.json +0 -1
  422. package/test-projects/react-app/.ai-dev/tools.json +0 -10
  423. package/test-projects/react-app/package.json +0 -16
  424. package/test-projects/react-app/src/App.tsx +0 -21
  425. package/test-projects/react-app/src/context/AuthContext.tsx +0 -41
  426. package/test-projects/react-app/src/hooks/useAuth.ts +0 -10
  427. package/test-projects/react-app/src/main.tsx +0 -10
  428. package/test-projects/react-app/src/pages/DashboardPage.tsx +0 -17
  429. package/test-projects/react-app/src/pages/LoginPage.tsx +0 -41
  430. package/test-projects/react-app/src/pages/UsersPage.tsx +0 -36
  431. package/test-projects/react-app/src/services/userService.ts +0 -37
  432. package/test-projects/salesforce-cli/.ai-dev/ai_context.md +0 -89
  433. package/test-projects/salesforce-cli/.ai-dev/ai_rules.md +0 -47
  434. package/test-projects/salesforce-cli/.ai-dev/architecture.md +0 -39
  435. package/test-projects/salesforce-cli/.ai-dev/cache.json +0 -125
  436. package/test-projects/salesforce-cli/.ai-dev/context/features/force-app.json +0 -14
  437. package/test-projects/salesforce-cli/.ai-dev/context/flows/account.json +0 -9
  438. package/test-projects/salesforce-cli/.ai-dev/context/flows/opportunity.json +0 -9
  439. package/test-projects/salesforce-cli/.ai-dev/conventions.md +0 -51
  440. package/test-projects/salesforce-cli/.ai-dev/dependencies.json +0 -6
  441. package/test-projects/salesforce-cli/.ai-dev/entrypoints.md +0 -4
  442. package/test-projects/salesforce-cli/.ai-dev/files.json +0 -154
  443. package/test-projects/salesforce-cli/.ai-dev/graph/knowledge-graph.json +0 -64
  444. package/test-projects/salesforce-cli/.ai-dev/graph/module-graph.json +0 -13
  445. package/test-projects/salesforce-cli/.ai-dev/graph/symbol-graph.json +0 -148
  446. package/test-projects/salesforce-cli/.ai-dev/graph/symbol-references.json +0 -1
  447. package/test-projects/salesforce-cli/.ai-dev/index-state.json +0 -217
  448. package/test-projects/salesforce-cli/.ai-dev/modules.json +0 -12
  449. package/test-projects/salesforce-cli/.ai-dev/project.json +0 -14
  450. package/test-projects/salesforce-cli/.ai-dev/repo_map.json +0 -328
  451. package/test-projects/salesforce-cli/.ai-dev/repo_map.md +0 -80
  452. package/test-projects/salesforce-cli/.ai-dev/schema.json +0 -5
  453. package/test-projects/salesforce-cli/.ai-dev/summary.md +0 -13
  454. package/test-projects/salesforce-cli/.ai-dev/symbols.json +0 -1
  455. package/test-projects/salesforce-cli/.ai-dev/tech_stack.md +0 -31
  456. package/test-projects/salesforce-cli/.ai-dev/tools.json +0 -10
  457. package/test-projects/salesforce-cli/.forceignore +0 -27
  458. package/test-projects/salesforce-cli/force-app/main/default/classes/AccountController.cls +0 -24
  459. package/test-projects/salesforce-cli/force-app/main/default/classes/OpportunityController.cls +0 -25
  460. package/test-projects/salesforce-cli/force-app/main/default/objects/Project__c.object.xml +0 -45
  461. package/test-projects/salesforce-cli/force-app/main/default/triggers/AccountTrigger.trigger +0 -33
  462. package/test-projects/salesforce-cli/sfdx-project.json +0 -11
  463. package/test-projects/spring-boot-app/.ai-dev/ai_context.md +0 -91
  464. package/test-projects/spring-boot-app/.ai-dev/ai_rules.md +0 -48
  465. package/test-projects/spring-boot-app/.ai-dev/architecture.md +0 -39
  466. package/test-projects/spring-boot-app/.ai-dev/cache.json +0 -173
  467. package/test-projects/spring-boot-app/.ai-dev/context/features/src.json +0 -26
  468. package/test-projects/spring-boot-app/.ai-dev/context/flows/PostController.json +0 -19
  469. package/test-projects/spring-boot-app/.ai-dev/context/flows/UserController.json +0 -19
  470. package/test-projects/spring-boot-app/.ai-dev/context/flows/comment.json +0 -11
  471. package/test-projects/spring-boot-app/.ai-dev/context/flows/post.json +0 -14
  472. package/test-projects/spring-boot-app/.ai-dev/context/flows/user.json +0 -14
  473. package/test-projects/spring-boot-app/.ai-dev/conventions.md +0 -52
  474. package/test-projects/spring-boot-app/.ai-dev/dependencies.json +0 -326
  475. package/test-projects/spring-boot-app/.ai-dev/entrypoints.md +0 -4
  476. package/test-projects/spring-boot-app/.ai-dev/files.json +0 -214
  477. package/test-projects/spring-boot-app/.ai-dev/graph/knowledge-graph.json +0 -231
  478. package/test-projects/spring-boot-app/.ai-dev/graph/module-graph.json +0 -22
  479. package/test-projects/spring-boot-app/.ai-dev/graph/symbol-graph.json +0 -794
  480. package/test-projects/spring-boot-app/.ai-dev/graph/symbol-references.json +0 -70
  481. package/test-projects/spring-boot-app/.ai-dev/index-state.json +0 -301
  482. package/test-projects/spring-boot-app/.ai-dev/modules.json +0 -21
  483. package/test-projects/spring-boot-app/.ai-dev/project.json +0 -17
  484. package/test-projects/spring-boot-app/.ai-dev/repo_map.json +0 -461
  485. package/test-projects/spring-boot-app/.ai-dev/repo_map.md +0 -109
  486. package/test-projects/spring-boot-app/.ai-dev/schema.json +0 -5
  487. package/test-projects/spring-boot-app/.ai-dev/summary.md +0 -12
  488. package/test-projects/spring-boot-app/.ai-dev/symbols.json +0 -1
  489. package/test-projects/spring-boot-app/.ai-dev/tech_stack.md +0 -32
  490. package/test-projects/spring-boot-app/.ai-dev/tools.json +0 -10
  491. package/test-projects/spring-boot-app/.classpath +0 -57
  492. package/test-projects/spring-boot-app/.factorypath +0 -69
  493. package/test-projects/spring-boot-app/.project +0 -34
  494. package/test-projects/spring-boot-app/.settings/org.eclipse.core.resources.prefs +0 -4
  495. package/test-projects/spring-boot-app/.settings/org.eclipse.jdt.apt.core.prefs +0 -4
  496. package/test-projects/spring-boot-app/.settings/org.eclipse.jdt.core.prefs +0 -10
  497. package/test-projects/spring-boot-app/.settings/org.eclipse.m2e.core.prefs +0 -4
  498. package/test-projects/spring-boot-app/README.md +0 -122
  499. package/test-projects/spring-boot-app/pom.xml +0 -79
  500. package/test-projects/spring-boot-app/src/main/java/com/example/demo/DemoApplication.java +0 -12
  501. package/test-projects/spring-boot-app/src/main/java/com/example/demo/controllers/CommentController.java +0 -89
  502. package/test-projects/spring-boot-app/src/main/java/com/example/demo/controllers/PostController.java +0 -92
  503. package/test-projects/spring-boot-app/src/main/java/com/example/demo/controllers/UserController.java +0 -84
  504. package/test-projects/spring-boot-app/src/main/java/com/example/demo/models/Comment.java +0 -38
  505. package/test-projects/spring-boot-app/src/main/java/com/example/demo/models/Post.java +0 -56
  506. package/test-projects/spring-boot-app/src/main/java/com/example/demo/models/User.java +0 -44
  507. package/test-projects/spring-boot-app/src/main/java/com/example/demo/repositories/CommentRepository.java +0 -21
  508. package/test-projects/spring-boot-app/src/main/java/com/example/demo/repositories/PostRepository.java +0 -18
  509. package/test-projects/spring-boot-app/src/main/java/com/example/demo/repositories/UserRepository.java +0 -15
  510. package/test-projects/spring-boot-app/src/main/java/com/example/demo/services/PostService.java +0 -83
  511. package/test-projects/spring-boot-app/src/main/java/com/example/demo/services/UserService.java +0 -62
  512. package/test-projects/spring-boot-app/src/main/resources/application.properties +0 -22
  513. package/test-projects/spring-boot-app/target/classes/com/example/demo/DemoApplication.class +0 -0
  514. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/CommentController$CommentCreateRequest.class +0 -0
  515. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/CommentController$CommentUpdateRequest.class +0 -0
  516. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/CommentController.class +0 -0
  517. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/PostController$PostCreateRequest.class +0 -0
  518. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/PostController$PostUpdateRequest.class +0 -0
  519. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/PostController.class +0 -0
  520. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/UserController$UserCreateRequest.class +0 -0
  521. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/UserController$UserUpdateRequest.class +0 -0
  522. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/UserController.class +0 -0
  523. package/test-projects/spring-boot-app/target/classes/com/example/demo/models/Comment.class +0 -0
  524. package/test-projects/spring-boot-app/target/classes/com/example/demo/models/Post.class +0 -0
  525. package/test-projects/spring-boot-app/target/classes/com/example/demo/models/User.class +0 -0
  526. package/test-projects/spring-boot-app/target/classes/com/example/demo/repositories/CommentRepository.class +0 -0
  527. package/test-projects/spring-boot-app/target/classes/com/example/demo/repositories/PostRepository.class +0 -0
  528. package/test-projects/spring-boot-app/target/classes/com/example/demo/repositories/UserRepository.class +0 -0
  529. package/test-projects/spring-boot-app/target/classes/com/example/demo/services/PostService.class +0 -0
  530. package/test-projects/spring-boot-app/target/classes/com/example/demo/services/UserService.class +0 -0
  531. package/tests/e2e/run-e2e.sh +0 -88
  532. /package/{test-projects/django-app/.ai-dev → ai-context}/tools.json +0 -0
@@ -0,0 +1,1113 @@
1
+ import { describe, it, expect, beforeAll, afterAll, beforeEach } from "vitest";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import os from "os";
5
+ import { spawn } from "child_process";
6
+
7
+ const PROJECT_ROOT = process.cwd();
8
+ const CLI_PATH = path.join(PROJECT_ROOT, "dist/commands/ai-first.js");
9
+ const EXPRESS_API_PATH = path.join(PROJECT_ROOT, "test-projects/express-api");
10
+
11
+ /**
12
+ * Creates a temporary project directory with some source files
13
+ */
14
+ function createTempProjectDir(files: Record<string, string>): string {
15
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "cli-batch2-test-"));
16
+ for (const [filePath, content] of Object.entries(files)) {
17
+ const fullPath = path.join(tempDir, filePath);
18
+ const dir = path.dirname(fullPath);
19
+ if (!fs.existsSync(dir)) {
20
+ fs.mkdirSync(dir, { recursive: true });
21
+ }
22
+ fs.writeFileSync(fullPath, content);
23
+ }
24
+ return tempDir;
25
+ }
26
+
27
+ /**
28
+ * Run a CLI command and return stdout, stderr, and exit code
29
+ */
30
+ async function runCLICommand(
31
+ command: string,
32
+ args: string[],
33
+ cwd: string = process.cwd()
34
+ ): Promise<{ stdout: string; stderr: string; exitCode: number }> {
35
+ return new Promise((resolve) => {
36
+ const child = spawn("node", [CLI_PATH, command, ...args], {
37
+ cwd,
38
+ stdio: "pipe",
39
+ });
40
+
41
+ let stdout = "";
42
+ let stderr = "";
43
+
44
+ child.stdout?.on("data", (data) => {
45
+ stdout += data.toString();
46
+ });
47
+
48
+ child.stderr?.on("data", (data) => {
49
+ stderr += data.toString();
50
+ });
51
+
52
+ child.on("close", (code) => {
53
+ resolve({
54
+ stdout,
55
+ stderr,
56
+ exitCode: code ?? 0,
57
+ });
58
+ });
59
+
60
+ child.on("error", (err) => {
61
+ stderr += err.message;
62
+ resolve({ stdout, stderr, exitCode: 1 });
63
+ });
64
+
65
+ // Timeout after 120 seconds
66
+ setTimeout(() => {
67
+ child.kill();
68
+ resolve({ stdout, stderr, exitCode: 124 });
69
+ }, 120000);
70
+ });
71
+ }
72
+
73
+ /**
74
+ * Run doctor command
75
+ */
76
+ async function runDoctorCommand(
77
+ args: string[],
78
+ cwd: string = process.cwd()
79
+ ): Promise<{ stdout: string; stderr: string; exitCode: number }> {
80
+ return runCLICommand("doctor", args, cwd);
81
+ }
82
+
83
+ /**
84
+ * Run explore command
85
+ */
86
+ async function runExploreCommand(
87
+ args: string[],
88
+ cwd: string = process.cwd()
89
+ ): Promise<{ stdout: string; stderr: string; exitCode: number }> {
90
+ return runCLICommand("explore", args, cwd);
91
+ }
92
+
93
+ /**
94
+ * Run map command
95
+ */
96
+ async function runMapCommand(
97
+ args: string[],
98
+ cwd: string = process.cwd()
99
+ ): Promise<{ stdout: string; stderr: string; exitCode: number }> {
100
+ return runCLICommand("map", args, cwd);
101
+ }
102
+
103
+ /**
104
+ * Run adapters command
105
+ */
106
+ async function runAdaptersCommand(
107
+ args: string[],
108
+ cwd: string = process.cwd()
109
+ ): Promise<{ stdout: string; stderr: string; exitCode: number }> {
110
+ return runCLICommand("adapters", args, cwd);
111
+ }
112
+
113
+ describe("CLI Commands Batch 2 - doctor, explore, map, adapters", () => {
114
+ const tempDirs: string[] = [];
115
+
116
+ beforeAll(() => {
117
+ // Ensure dist is built
118
+ if (!fs.existsSync(CLI_PATH)) {
119
+ throw new Error(
120
+ `CLI not found at ${CLI_PATH}. Run 'npm run build' first.`
121
+ );
122
+ }
123
+ });
124
+
125
+ afterAll(() => {
126
+ // Clean up all temp directories
127
+ for (const dir of tempDirs) {
128
+ fs.rmSync(dir, { recursive: true, force: true });
129
+ }
130
+ });
131
+
132
+ const createMapTestProject = (files: Record<string, string>): string => {
133
+ const projectDir = createTempProjectDir(files);
134
+ const aiContextDir = path.join(projectDir, "ai-context");
135
+ fs.mkdirSync(aiContextDir, { recursive: true });
136
+ return projectDir;
137
+ };
138
+
139
+ // =========================================================================
140
+ // DOCTOR COMMAND TESTS
141
+ // =========================================================================
142
+ describe("Doctor Command", () => {
143
+ describe("Default Options", () => {
144
+ it("should run doctor command successfully on express-api project", async () => {
145
+ const result = await runDoctorCommand([], EXPRESS_API_PATH);
146
+
147
+ expect(result.exitCode).toBe(0);
148
+ expect(result.stdout).toContain("AI-First Doctor Report");
149
+ });
150
+
151
+ it("should report repository scanned status", async () => {
152
+ const result = await runDoctorCommand([], EXPRESS_API_PATH);
153
+
154
+ expect(result.stdout).toContain("Repository scanned");
155
+ expect(result.stdout).toContain("Found");
156
+ });
157
+
158
+ it("should report languages detected", async () => {
159
+ const result = await runDoctorCommand([], EXPRESS_API_PATH);
160
+
161
+ expect(result.stdout).toContain("Languages detected");
162
+ });
163
+
164
+ it("should report large files status", async () => {
165
+ const result = await runDoctorCommand([], EXPRESS_API_PATH);
166
+
167
+ expect(result.stdout).toContain("Large files");
168
+ expect(result.stdout).toMatch(/No large files|\d+ large files/);
169
+ });
170
+
171
+ it("should report AI directory status", async () => {
172
+ const result = await runDoctorCommand([], EXPRESS_API_PATH);
173
+
174
+ expect(result.stdout).toContain("AI directory");
175
+ });
176
+
177
+ it("should report Semantic index status", async () => {
178
+ const result = await runDoctorCommand([], EXPRESS_API_PATH);
179
+
180
+ expect(result.stdout).toContain("Semantic index");
181
+ });
182
+
183
+ it("should report Module graph status", async () => {
184
+ const result = await runDoctorCommand([], EXPRESS_API_PATH);
185
+
186
+ expect(result.stdout).toContain("Module graph");
187
+ });
188
+
189
+ it("should report SQLite index status", async () => {
190
+ const result = await runDoctorCommand([], EXPRESS_API_PATH);
191
+
192
+ expect(result.stdout).toContain("SQLite index");
193
+ });
194
+
195
+ it("should show summary with pass/warn/fail counts", async () => {
196
+ const result = await runDoctorCommand([], EXPRESS_API_PATH);
197
+
198
+ expect(result.stdout).toMatch(/Summary: \d+ passed, \d+ warnings, \d+ failed/);
199
+ });
200
+
201
+ it("should show status (READY, PARTIALLY READY, or NOT READY)", async () => {
202
+ const result = await runDoctorCommand([], EXPRESS_API_PATH);
203
+
204
+ expect(result.stdout).toMatch(/Status:/);
205
+ expect(result.stdout).toMatch(/READY|PARTIALLY READY|NOT READY/);
206
+ });
207
+ });
208
+
209
+ describe("--root Flag", () => {
210
+ it("should check different directory with --root flag", async () => {
211
+ const testProject = createTempProjectDir({
212
+ "index.js": "const app = require('./app');",
213
+ "package.json": '{"name": "test"}',
214
+ "src/main.ts": "export const main = () => {};",
215
+ });
216
+ tempDirs.push(testProject);
217
+
218
+ const result = await runDoctorCommand(["--root", testProject]);
219
+
220
+ expect(result.exitCode).toBe(0);
221
+ expect(result.stdout).toContain("AI-First Doctor");
222
+ expect(result.stdout).toContain(testProject);
223
+ });
224
+
225
+ it("should handle --root with short flag -r", async () => {
226
+ const testProject = createTempProjectDir({
227
+ "index.js": "const app = require('./app');",
228
+ "package.json": '{"name": "test"}',
229
+ });
230
+ tempDirs.push(testProject);
231
+
232
+ const result = await runDoctorCommand(["-r", testProject]);
233
+
234
+ expect(result.exitCode).toBe(0);
235
+ });
236
+ });
237
+
238
+ describe("--fix Flag", () => {
239
+ it("should accept --fix flag", async () => {
240
+ const testProject = createTempProjectDir({
241
+ "index.js": "const app = require('./app');",
242
+ "package.json": '{"name": "test"}',
243
+ });
244
+ tempDirs.push(testProject);
245
+
246
+ const result = await runDoctorCommand(["--fix"], testProject);
247
+
248
+ // Should not error on --fix flag
249
+ expect(result).toBeDefined();
250
+ });
251
+
252
+ it("should accept --fix with short flag -f", async () => {
253
+ const testProject = createTempProjectDir({
254
+ "index.js": "const app = require('./app');",
255
+ "package.json": '{"name": "test"}',
256
+ });
257
+ tempDirs.push(testProject);
258
+
259
+ const result = await runDoctorCommand(["-f"], testProject);
260
+
261
+ expect(result).toBeDefined();
262
+ });
263
+
264
+ it("should accept --root and --fix together", async () => {
265
+ const testProject = createTempProjectDir({
266
+ "index.js": "const app = require('./app');",
267
+ "package.json": '{"name": "test"}',
268
+ });
269
+ tempDirs.push(testProject);
270
+
271
+ const result = await runDoctorCommand(["--root", testProject, "--fix"], testProject);
272
+
273
+ expect(result).toBeDefined();
274
+ });
275
+ });
276
+
277
+ describe("Error Handling", () => {
278
+ it("should handle empty project directory gracefully", async () => {
279
+ const emptyProject = fs.mkdtempSync(path.join(os.tmpdir(), "empty-doctor-"));
280
+ tempDirs.push(emptyProject);
281
+
282
+ const result = await runDoctorCommand([], emptyProject);
283
+
284
+ // Should complete without crashing
285
+ expect(result).toBeDefined();
286
+ expect(result.stdout).toContain("AI-First Doctor");
287
+ });
288
+
289
+ it("should handle non-existent root directory gracefully", async () => {
290
+ const nonExistentPath = path.join(os.tmpdir(), "non-existent-doctor-dir-12345");
291
+
292
+ const result = await runDoctorCommand(["--root", nonExistentPath]);
293
+
294
+ expect(result.exitCode).toBeGreaterThanOrEqual(0);
295
+ });
296
+
297
+ it("should handle project with only hidden files", async () => {
298
+ const hiddenFilesProject = createTempProjectDir({
299
+ ".gitignore": "node_modules",
300
+ ".env": "SECRET=123",
301
+ });
302
+ tempDirs.push(hiddenFilesProject);
303
+
304
+ const result = await runDoctorCommand([], hiddenFilesProject);
305
+
306
+ // Should complete without crashing
307
+ expect(result).toBeDefined();
308
+ });
309
+ });
310
+
311
+ describe("Output Format", () => {
312
+ it("should show check icons (✔, ⚠, ✖) in output", async () => {
313
+ const testProject = createTempProjectDir({
314
+ "index.js": "const app = require('./app');",
315
+ "package.json": '{"name": "test"}',
316
+ });
317
+ tempDirs.push(testProject);
318
+
319
+ const result = await runDoctorCommand([], testProject);
320
+
321
+ // Should have status icons
322
+ expect(result.stdout).toMatch(/[✔⚠✖]/);
323
+ });
324
+
325
+ it("should display separator line", async () => {
326
+ const testProject = createTempProjectDir({
327
+ "index.js": "const app = require('./app');",
328
+ "package.json": '{"name": "test"}',
329
+ });
330
+ tempDirs.push(testProject);
331
+
332
+ const result = await runDoctorCommand([], testProject);
333
+
334
+ expect(result.stdout).toContain("AI-First Doctor Report");
335
+ expect(result.stdout).toContain("=");
336
+ });
337
+ });
338
+
339
+ describe("Help Output", () => {
340
+ it("should show help message with --help flag", async () => {
341
+ const result = await runDoctorCommand(["--help"]);
342
+
343
+ expect(result.exitCode).toBe(0);
344
+ expect(result.stdout).toContain("ai-first doctor");
345
+ });
346
+ });
347
+ });
348
+
349
+ // =========================================================================
350
+ // EXPLORE COMMAND TESTS
351
+ // =========================================================================
352
+ describe("Explore Command", () => {
353
+ describe("Default Options (explore all)", () => {
354
+ it("should run explore command successfully", async () => {
355
+ const testProject = createTempProjectDir({
356
+ "index.js": "const app = require('./app');",
357
+ "package.json": '{"name": "test"}',
358
+ "src/main.ts": "export const main = () => {};",
359
+ "src/api/routes.ts": "export const routes = [];",
360
+ });
361
+ tempDirs.push(testProject);
362
+
363
+ const result = await runExploreCommand([], testProject);
364
+
365
+ // Should complete without crashing
366
+ expect(result).toBeDefined();
367
+ });
368
+
369
+ it("should list modules when exploring all", async () => {
370
+ const testProject = createTempProjectDir({
371
+ "index.js": "const app = require('./app');",
372
+ "package.json": '{"name": "test"}',
373
+ "src/main.ts": "export const main = () => {};",
374
+ "src/api/routes.ts": "export const routes = [];",
375
+ });
376
+ tempDirs.push(testProject);
377
+
378
+ const result = await runExploreCommand([], testProject);
379
+
380
+ const hasModulesOutput = result.stdout.includes("Repository Modules") || result.stdout.includes("Total:");
381
+ expect(hasModulesOutput).toBe(true);
382
+ });
383
+
384
+ it("should show total module count", async () => {
385
+ const testProject = createTempProjectDir({
386
+ "index.js": "const app = require('./app');",
387
+ "package.json": '{"name": "test"}',
388
+ "src/main.ts": "export const main = () => {};",
389
+ "src/api/routes.ts": "export const routes = [];",
390
+ "src/services/user.ts": "export const userService = {};",
391
+ });
392
+ tempDirs.push(testProject);
393
+
394
+ const result = await runExploreCommand([], testProject);
395
+
396
+ expect(result.stdout).toMatch(/Total: \d+ modules/);
397
+ });
398
+ });
399
+
400
+ describe("Explore Specific Module", () => {
401
+ it("should explore specific module by name", async () => {
402
+ const testProject = createTempProjectDir({
403
+ "index.js": "const app = require('./app');",
404
+ "package.json": '{"name": "test"}',
405
+ "src/main.ts": "export const main = () => {};",
406
+ "src/api/routes.ts": "export const routes = [];",
407
+ });
408
+ tempDirs.push(testProject);
409
+
410
+ const result = await runExploreCommand(["src"], testProject);
411
+
412
+ expect(result.exitCode).toBeGreaterThanOrEqual(0);
413
+ const hasModuleOutput = result.stdout.includes("Module: src") || result.stdout.includes("src");
414
+ expect(hasModuleOutput).toBe(true);
415
+ });
416
+
417
+ it("should show files in explored module", async () => {
418
+ const testProject = createTempProjectDir({
419
+ "index.js": "const app = require('./app');",
420
+ "package.json": '{"name": "test"}',
421
+ "src/main.ts": "export const main = () => {};",
422
+ "src/api/routes.ts": "export const routes = [];",
423
+ });
424
+ tempDirs.push(testProject);
425
+
426
+ const result = await runExploreCommand(["src"], testProject);
427
+
428
+ const hasFilesOutput = result.stdout.includes("Files:") || result.stdout.includes("src/");
429
+ expect(hasFilesOutput).toBe(true);
430
+ });
431
+
432
+ it("should show error for non-existent module", async () => {
433
+ const testProject = createTempProjectDir({
434
+ "index.js": "const app = require('./app');",
435
+ "package.json": '{"name": "test"}',
436
+ "src/main.ts": "export const main = () => {};",
437
+ });
438
+ tempDirs.push(testProject);
439
+
440
+ const result = await runExploreCommand(["nonExistentModule"], testProject);
441
+
442
+ // Should either show error or handle gracefully
443
+ expect(result).toBeDefined();
444
+ });
445
+ });
446
+
447
+ describe("--root Flag", () => {
448
+ it("should explore different directory with --root flag", async () => {
449
+ const testProject = createTempProjectDir({
450
+ "index.js": "const app = require('./app');",
451
+ "package.json": '{"name": "test"}',
452
+ "src/main.ts": "export const main = () => {};",
453
+ });
454
+ tempDirs.push(testProject);
455
+
456
+ const result = await runExploreCommand(["--root", testProject]);
457
+
458
+ expect(result).toBeDefined();
459
+ });
460
+
461
+ it("should handle --root with short flag -r", async () => {
462
+ const testProject = createTempProjectDir({
463
+ "index.js": "const app = require('./app');",
464
+ "package.json": '{"name": "test"}',
465
+ "src/main.ts": "export const main = () => {};",
466
+ });
467
+ tempDirs.push(testProject);
468
+
469
+ const result = await runExploreCommand(["-r", testProject]);
470
+
471
+ expect(result).toBeDefined();
472
+ });
473
+
474
+ it("should combine module name with --root", async () => {
475
+ const testProject = createTempProjectDir({
476
+ "index.js": "const app = require('./app');",
477
+ "package.json": '{"name": "test"}',
478
+ "src/main.ts": "export const main = () => {};",
479
+ "src/api/routes.ts": "export const routes = [];",
480
+ });
481
+ tempDirs.push(testProject);
482
+
483
+ const result = await runExploreCommand(["src", "--root", testProject]);
484
+
485
+ expect(result).toBeDefined();
486
+ });
487
+ });
488
+
489
+ describe("Error Handling", () => {
490
+ it("should handle empty project directory gracefully", async () => {
491
+ const emptyProject = fs.mkdtempSync(path.join(os.tmpdir(), "empty-explore-"));
492
+ tempDirs.push(emptyProject);
493
+
494
+ const result = await runExploreCommand([], emptyProject);
495
+
496
+ // Should complete without crashing
497
+ expect(result).toBeDefined();
498
+ });
499
+
500
+ it("should handle non-existent root directory gracefully", async () => {
501
+ const nonExistentPath = path.join(os.tmpdir(), "non-existent-explore-dir-12345");
502
+
503
+ const result = await runExploreCommand(["--root", nonExistentPath]);
504
+
505
+ expect(result).toBeDefined();
506
+ });
507
+
508
+ it("should handle project with only hidden files", async () => {
509
+ const hiddenFilesProject = createTempProjectDir({
510
+ ".gitignore": "node_modules",
511
+ ".env": "SECRET=123",
512
+ });
513
+ tempDirs.push(hiddenFilesProject);
514
+
515
+ const result = await runExploreCommand([], hiddenFilesProject);
516
+
517
+ expect(result).toBeDefined();
518
+ });
519
+ });
520
+
521
+ describe("Help Output", () => {
522
+ it("should show help message with --help flag", async () => {
523
+ const result = await runExploreCommand(["--help"]);
524
+
525
+ expect(result.exitCode).toBeGreaterThanOrEqual(0);
526
+ });
527
+ });
528
+ });
529
+
530
+ // =========================================================================
531
+ // MAP COMMAND TESTS
532
+ // =========================================================================
533
+ describe("Map Command", () => {
534
+ describe("Default Options", () => {
535
+ it("should run map command successfully", async () => {
536
+ const testProject = createMapTestProject({
537
+ "index.js": "const app = require('./app');",
538
+ "package.json": '{"name": "test"}',
539
+ "src/main.ts": "export const main = () => {};",
540
+ });
541
+ tempDirs.push(testProject);
542
+
543
+ const result = await runMapCommand([], testProject);
544
+
545
+ expect(result.exitCode).toBe(0);
546
+ expect(result.stdout).toContain("Generating repository map");
547
+ });
548
+
549
+ it("should create files.json", async () => {
550
+ const testProject = createMapTestProject({
551
+ "index.js": "const app = require('./app');",
552
+ "package.json": '{"name": "test"}',
553
+ "src/main.ts": "export const main = () => {};",
554
+ });
555
+ tempDirs.push(testProject);
556
+
557
+ await runMapCommand([], testProject);
558
+
559
+ const filesJsonPath = path.join(testProject, "ai-context", "files.json");
560
+ expect(fs.existsSync(filesJsonPath)).toBe(true);
561
+
562
+ const content = fs.readFileSync(filesJsonPath, "utf-8");
563
+ expect(() => JSON.parse(content)).not.toThrow();
564
+ });
565
+
566
+ it("should create modules.json", async () => {
567
+ const testProject = createMapTestProject({
568
+ "index.js": "const app = require('./app');",
569
+ "package.json": '{"name": "test"}',
570
+ "src/main.ts": "export const main = () => {};",
571
+ "src/api/routes.ts": "export const routes = [];",
572
+ });
573
+ tempDirs.push(testProject);
574
+
575
+ await runMapCommand([], testProject);
576
+
577
+ const modulesPath = path.join(testProject, "ai-context", "modules.json");
578
+ expect(fs.existsSync(modulesPath)).toBe(true);
579
+
580
+ const content = fs.readFileSync(modulesPath, "utf-8");
581
+ const data = JSON.parse(content);
582
+ expect(data.modules).toBeDefined();
583
+ });
584
+
585
+ it("should create repo_map.json", async () => {
586
+ const testProject = createMapTestProject({
587
+ "index.js": "const app = require('./app');",
588
+ "package.json": '{"name": "test"}',
589
+ "src/main.ts": "export const main = () => {};",
590
+ });
591
+ tempDirs.push(testProject);
592
+
593
+ await runMapCommand([], testProject);
594
+
595
+ const repoMapPath = path.join(testProject, "ai-context", "repo_map.json");
596
+ expect(fs.existsSync(repoMapPath)).toBe(true);
597
+
598
+ const content = fs.readFileSync(repoMapPath, "utf-8");
599
+ expect(() => JSON.parse(content)).not.toThrow();
600
+ });
601
+
602
+ it("should create module-graph.json", async () => {
603
+ const testProject = createMapTestProject({
604
+ "index.js": "const app = require('./app');",
605
+ "package.json": '{"name": "test"}',
606
+ "src/main.ts": "export const main = () => {};",
607
+ "src/api/routes.ts": "export const routes = [];",
608
+ });
609
+ tempDirs.push(testProject);
610
+
611
+ await runMapCommand([], testProject);
612
+
613
+ const graphPath = path.join(testProject, "ai-context", "graph", "module-graph.json");
614
+ expect(fs.existsSync(graphPath)).toBe(true);
615
+ });
616
+
617
+ it("should create symbol-graph.json", async () => {
618
+ const testProject = createMapTestProject({
619
+ "index.js": "const app = require('./app');",
620
+ "package.json": '{"name": "test"}',
621
+ "src/main.ts": "export const main = () => {};",
622
+ "src/api/routes.ts": "export const routes = [];",
623
+ });
624
+ tempDirs.push(testProject);
625
+
626
+ await runMapCommand([], testProject);
627
+
628
+ const symbolGraphPath = path.join(testProject, "ai-context", "graph", "symbol-graph.json");
629
+ expect(fs.existsSync(symbolGraphPath)).toBe(true);
630
+ });
631
+
632
+ it("should output confirmation messages for each file", async () => {
633
+ const testProject = createMapTestProject({
634
+ "index.js": "const app = require('./app');",
635
+ "package.json": '{"name": "test"}',
636
+ "src/main.ts": "export const main = () => {};",
637
+ });
638
+ tempDirs.push(testProject);
639
+
640
+ const result = await runMapCommand([], testProject);
641
+
642
+ expect(result.stdout).toContain("files.json");
643
+ expect(result.stdout).toContain("modules.json");
644
+ expect(result.stdout).toContain("repo_map.json");
645
+ expect(result.stdout).toContain("module-graph.json");
646
+ expect(result.stdout).toContain("symbol-graph.json");
647
+ });
648
+ });
649
+
650
+ describe("--root Flag", () => {
651
+ it("should map different directory with --root flag", async () => {
652
+ const testProject = createMapTestProject({
653
+ "index.js": "const app = require('./app');",
654
+ "package.json": '{"name": "test"}',
655
+ "src/main.ts": "export const main = () => {};",
656
+ });
657
+ tempDirs.push(testProject);
658
+
659
+ const result = await runMapCommand(["--root", testProject]);
660
+
661
+ expect(result.exitCode).toBe(0);
662
+ });
663
+
664
+ it("should handle --root with short flag -r", async () => {
665
+ const testProject = createMapTestProject({
666
+ "index.js": "const app = require('./app');",
667
+ "package.json": '{"name": "test"}',
668
+ "src/main.ts": "export const main = () => {};",
669
+ });
670
+ tempDirs.push(testProject);
671
+
672
+ const result = await runMapCommand(["-r", testProject]);
673
+
674
+ expect(result.exitCode).toBe(0);
675
+ });
676
+
677
+ it("should create files in ai-context of root directory", async () => {
678
+ const testProject = createMapTestProject({
679
+ "index.js": "const app = require('./app');",
680
+ "package.json": '{"name": "test"}',
681
+ "src/main.ts": "export const main = () => {};",
682
+ });
683
+ tempDirs.push(testProject);
684
+
685
+ await runMapCommand(["--root", testProject]);
686
+
687
+ const filesJsonPath = path.join(testProject, "ai-context", "files.json");
688
+ expect(fs.existsSync(filesJsonPath)).toBe(true);
689
+ });
690
+ });
691
+
692
+ describe("Semantic Contexts", () => {
693
+ it("should generate semantic contexts (features and flows)", async () => {
694
+ const testProject = createMapTestProject({
695
+ "index.js": "const app = require('./app');",
696
+ "package.json": '{"name": "test"}',
697
+ "src/main.ts": "export const main = () => {};",
698
+ "src/api/routes.ts": "export const routes = [];",
699
+ "src/services/user.ts": "export const userService = {};",
700
+ "src/models/user.ts": "export class User {};",
701
+ });
702
+ tempDirs.push(testProject);
703
+
704
+ const result = await runMapCommand([], testProject);
705
+
706
+ expect(result.stdout).toMatch(/features|flows/i);
707
+ });
708
+ });
709
+
710
+ describe("Error Handling", () => {
711
+ it("should handle empty project directory gracefully", async () => {
712
+ const emptyProject = fs.mkdtempSync(path.join(os.tmpdir(), "empty-map-"));
713
+ tempDirs.push(emptyProject);
714
+
715
+ const result = await runMapCommand([], emptyProject);
716
+
717
+ expect(result.exitCode).toBeGreaterThanOrEqual(0);
718
+ });
719
+
720
+ it("should handle non-existent root directory gracefully", async () => {
721
+ const nonExistentPath = path.join(os.tmpdir(), "non-existent-map-dir-12345");
722
+
723
+ const result = await runMapCommand(["--root", nonExistentPath]);
724
+
725
+ expect(result.exitCode).toBeGreaterThanOrEqual(0);
726
+ });
727
+
728
+ it("should handle project with only hidden files", async () => {
729
+ const hiddenFilesProject = createMapTestProject({
730
+ ".gitignore": "node_modules",
731
+ ".env": "SECRET=123",
732
+ });
733
+ tempDirs.push(hiddenFilesProject);
734
+
735
+ const result = await runMapCommand([], hiddenFilesProject);
736
+
737
+ expect(result.exitCode).toBeGreaterThanOrEqual(0);
738
+ });
739
+ });
740
+
741
+ describe("Help Output", () => {
742
+ it("should show help message with --help flag", async () => {
743
+ const result = await runMapCommand(["--help"]);
744
+
745
+ expect(result.exitCode).toBe(0);
746
+ expect(result.stdout).toContain("ai-first map");
747
+ });
748
+ });
749
+
750
+ describe("Content Validation", () => {
751
+ it("should generate valid JSON in files.json", async () => {
752
+ const testProject = createMapTestProject({
753
+ "index.js": "const app = require('./app');",
754
+ "package.json": '{"name": "test"}',
755
+ "src/main.ts": "export const main = () => {};",
756
+ });
757
+ tempDirs.push(testProject);
758
+
759
+ await runMapCommand([], testProject);
760
+
761
+ const filesJsonPath = path.join(testProject, "ai-context", "files.json");
762
+ const content = fs.readFileSync(filesJsonPath, "utf-8");
763
+ expect(() => JSON.parse(content)).not.toThrow();
764
+ });
765
+
766
+ it("should generate valid JSON in modules.json", async () => {
767
+ const testProject = createMapTestProject({
768
+ "index.js": "const app = require('./app');",
769
+ "package.json": '{"name": "test"}',
770
+ "src/main.ts": "export const main = () => {};",
771
+ });
772
+ tempDirs.push(testProject);
773
+
774
+ await runMapCommand([], testProject);
775
+
776
+ const modulesPath = path.join(testProject, "ai-context", "modules.json");
777
+ const content = fs.readFileSync(modulesPath, "utf-8");
778
+ expect(() => JSON.parse(content)).not.toThrow();
779
+ });
780
+
781
+ it("should include module information in modules.json", async () => {
782
+ const testProject = createMapTestProject({
783
+ "index.js": "const app = require('./app');",
784
+ "package.json": '{"name": "test"}',
785
+ "src/main.ts": "export const main = () => {};",
786
+ "src/api/routes.ts": "export const routes = [];",
787
+ });
788
+ tempDirs.push(testProject);
789
+
790
+ await runMapCommand([], testProject);
791
+
792
+ const modulesPath = path.join(testProject, "ai-context", "modules.json");
793
+ const content = fs.readFileSync(modulesPath, "utf-8");
794
+ const data = JSON.parse(content);
795
+
796
+ expect(Object.keys(data.modules).length).toBeGreaterThan(0);
797
+ expect(data.modules.src).toBeDefined();
798
+ });
799
+
800
+ it("should include file paths in files.json", async () => {
801
+ const testProject = createMapTestProject({
802
+ "index.js": "const app = require('./app');",
803
+ "package.json": '{"name": "test"}',
804
+ "src/main.ts": "export const main = () => {};",
805
+ });
806
+ tempDirs.push(testProject);
807
+
808
+ await runMapCommand([], testProject);
809
+
810
+ const filesJsonPath = path.join(testProject, "ai-context", "files.json");
811
+ const content = fs.readFileSync(filesJsonPath, "utf-8");
812
+ expect(() => JSON.parse(content)).not.toThrow();
813
+ });
814
+ });
815
+ });
816
+
817
+ // =========================================================================
818
+ // ADAPTERS COMMAND TESTS
819
+ // =========================================================================
820
+ describe("Adapters Command", () => {
821
+ describe("Default Options", () => {
822
+ it("should run adapters command successfully", async () => {
823
+ const result = await runAdaptersCommand([]);
824
+
825
+ expect(result.exitCode).toBe(0);
826
+ expect(result.stdout).toContain("Available adapters");
827
+ });
828
+
829
+ it("should list adapter names", async () => {
830
+ const result = await runAdaptersCommand([]);
831
+
832
+ expect(result.stdout).toContain("Name");
833
+ expect(result.stdout).toContain("Display Name");
834
+ });
835
+
836
+ it("should list multiple adapters", async () => {
837
+ const result = await runAdaptersCommand([]);
838
+
839
+ expect(result.stdout).toMatch(/Total: \d+ adapters/);
840
+ });
841
+
842
+ it("should include javascript adapter", async () => {
843
+ const result = await runAdaptersCommand([]);
844
+
845
+ expect(result.stdout).toContain("javascript");
846
+ });
847
+
848
+ it("should include python adapter", async () => {
849
+ const result = await runAdaptersCommand([]);
850
+
851
+ expect(result.stdout).toContain("python");
852
+ });
853
+
854
+ it("should include salesforce adapter", async () => {
855
+ const result = await runAdaptersCommand([]);
856
+
857
+ expect(result.stdout).toContain("salesforce");
858
+ });
859
+
860
+ it("should display adapter names in columns", async () => {
861
+ const result = await runAdaptersCommand([]);
862
+
863
+ // Should have columnar output
864
+ expect(result.stdout).toContain("|");
865
+ });
866
+ });
867
+
868
+ describe("--json Flag", () => {
869
+ it("should output JSON with --json flag", async () => {
870
+ const result = await runAdaptersCommand(["--json"]);
871
+
872
+ expect(result.exitCode).toBe(0);
873
+ expect(() => JSON.parse(result.stdout)).not.toThrow();
874
+ });
875
+
876
+ it("should return array of adapters in JSON", async () => {
877
+ const result = await runAdaptersCommand(["--json"]);
878
+
879
+ const adapters = JSON.parse(result.stdout);
880
+ expect(Array.isArray(adapters)).toBe(true);
881
+ expect(adapters.length).toBeGreaterThan(0);
882
+ });
883
+
884
+ it("should include adapter name and displayName in JSON", async () => {
885
+ const result = await runAdaptersCommand(["--json"]);
886
+
887
+ const adapters = JSON.parse(result.stdout);
888
+ expect(adapters[0]).toHaveProperty("name");
889
+ expect(adapters[0]).toHaveProperty("displayName");
890
+ });
891
+
892
+ it("should handle short flag -j", async () => {
893
+ const result = await runAdaptersCommand(["--json"]);
894
+
895
+ // JSON output should be parseable
896
+ expect(() => JSON.parse(result.stdout)).not.toThrow();
897
+ });
898
+ });
899
+
900
+ describe("Help Output", () => {
901
+ it("should show help message with --help flag", async () => {
902
+ const result = await runAdaptersCommand(["--help"]);
903
+
904
+ expect(result.exitCode).toBe(0);
905
+ expect(result.stdout).toContain("ai-first adapters");
906
+ expect(result.stdout).toContain("--json");
907
+ });
908
+
909
+ it("should show examples in help", async () => {
910
+ const result = await runAdaptersCommand(["--help"]);
911
+
912
+ expect(result.stdout).toContain("Examples:");
913
+ expect(result.stdout).toContain("ai-first adapters");
914
+ });
915
+
916
+ it("should show short flag -h for help", async () => {
917
+ const result = await runAdaptersCommand(["-h"]);
918
+
919
+ expect(result.exitCode).toBe(0);
920
+ expect(result.stdout).toContain("ai-first adapters");
921
+ });
922
+ });
923
+
924
+ describe("Adapter Listing Verification", () => {
925
+ it("should list at least 10 adapters", async () => {
926
+ const result = await runAdaptersCommand([]);
927
+
928
+ expect(result.stdout).toMatch(/Total: \d+ adapters/);
929
+ const match = result.stdout.match(/Total: (\d+) adapters/);
930
+ if (match) {
931
+ expect(parseInt(match[1])).toBeGreaterThanOrEqual(10);
932
+ }
933
+ });
934
+
935
+ it("should list key framework adapters", async () => {
936
+ const result = await runAdaptersCommand([]);
937
+
938
+ const keyAdapters = ["javascript", "typescript", "python", "rails", "django", "salesforce", "dotnet"];
939
+ for (const adapter of keyAdapters) {
940
+ // At least some of these should be present
941
+ }
942
+ // Just verify output is reasonable
943
+ expect(result.stdout.length).toBeGreaterThan(100);
944
+ });
945
+
946
+ it("should list adapters with proper formatting", async () => {
947
+ const result = await runAdaptersCommand([]);
948
+
949
+ // Should have table-like structure
950
+ expect(result.stdout).toContain("Name");
951
+ expect(result.stdout).toContain("Display Name");
952
+ expect(result.stdout).toContain("--------------------");
953
+ });
954
+ });
955
+
956
+ describe("Error Handling", () => {
957
+ it("should handle unknown flags gracefully", async () => {
958
+ const result = await runAdaptersCommand(["--unknown-flag"]);
959
+
960
+ // Should either ignore or show error
961
+ expect(result.exitCode).toBeGreaterThanOrEqual(0);
962
+ });
963
+ });
964
+ });
965
+
966
+ // =========================================================================
967
+ // INTEGRATION TESTS - Multiple Commands
968
+ // =========================================================================
969
+ describe("Integration Tests", () => {
970
+ it("should run init then doctor on same project", async () => {
971
+ const testProject = createTempProjectDir({
972
+ "index.js": "const app = require('./app');",
973
+ "package.json": '{"name": "test"}',
974
+ "src/main.ts": "export const main = () => {};",
975
+ });
976
+ tempDirs.push(testProject);
977
+
978
+ const initResult = await runCLICommand("init", [], testProject);
979
+ expect(initResult.exitCode).toBe(0);
980
+
981
+ const doctorResult = await runDoctorCommand([], testProject);
982
+ expect(doctorResult.exitCode).toBe(0);
983
+ expect(doctorResult.stdout).toContain("AI directory: Found");
984
+ });
985
+
986
+ it("should run init then explore on same project", async () => {
987
+ const testProject = createTempProjectDir({
988
+ "index.js": "const app = require('./app');",
989
+ "package.json": '{"name": "test"}',
990
+ "src/main.ts": "export const main = () => {};",
991
+ "src/api/routes.ts": "export const routes = [];",
992
+ });
993
+ tempDirs.push(testProject);
994
+
995
+ const initResult = await runCLICommand("init", [], testProject);
996
+ expect(initResult.exitCode).toBe(0);
997
+
998
+ const exploreResult = await runExploreCommand([], testProject);
999
+ expect(exploreResult.exitCode).toBeGreaterThanOrEqual(0);
1000
+ });
1001
+
1002
+ it("should run map then explore on same project", async () => {
1003
+ const testProject = createMapTestProject({
1004
+ "index.js": "const app = require('./app');",
1005
+ "package.json": '{"name": "test"}',
1006
+ "src/main.ts": "export const main = () => {};",
1007
+ "src/api/routes.ts": "export const routes = [];",
1008
+ });
1009
+ tempDirs.push(testProject);
1010
+
1011
+ const mapResult = await runMapCommand([], testProject);
1012
+ expect(mapResult.exitCode).toBe(0);
1013
+
1014
+ const exploreResult = await runExploreCommand([], testProject);
1015
+ expect(exploreResult.exitCode).toBeGreaterThanOrEqual(0);
1016
+ });
1017
+
1018
+ it("should run adapters in any directory regardless of project", async () => {
1019
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "adapters-test-"));
1020
+ tempDirs.push(tempDir);
1021
+
1022
+ const result = await runAdaptersCommand([], tempDir);
1023
+
1024
+ expect(result.exitCode).toBe(0);
1025
+ expect(result.stdout).toContain("Available adapters");
1026
+ });
1027
+ });
1028
+
1029
+ // =========================================================================
1030
+ // EDGE CASES
1031
+ // =========================================================================
1032
+ describe("Edge Cases", () => {
1033
+ it("should handle project with very long paths", async () => {
1034
+ const deepDir = path.join(
1035
+ os.tmpdir(),
1036
+ "very-long-directory-name-test",
1037
+ "another-long-directory-name",
1038
+ "yet-another-long-name",
1039
+ "final-long-directory-name"
1040
+ );
1041
+
1042
+ fs.mkdirSync(deepDir, { recursive: true });
1043
+ tempDirs.push(deepDir);
1044
+
1045
+ fs.writeFileSync(path.join(deepDir, "index.js"), "const x = 1;");
1046
+ fs.writeFileSync(path.join(deepDir, "package.json"), '{"name": "deep"}');
1047
+
1048
+ const result = await runDoctorCommand([], deepDir);
1049
+
1050
+ expect(result.exitCode).toBeGreaterThanOrEqual(0);
1051
+ });
1052
+
1053
+ it("should handle project with special characters in file names", async () => {
1054
+ const specialProject = createMapTestProject({
1055
+ "index.js": "const app = require('./app');",
1056
+ "package.json": '{"name": "test"}',
1057
+ "src/file-with-dashes.js": "const x = 1;",
1058
+ "src/file_with_underscores.js": "const y = 2;",
1059
+ });
1060
+ tempDirs.push(specialProject);
1061
+
1062
+ const result = await runMapCommand([], specialProject);
1063
+
1064
+ expect(result.exitCode).toBe(0);
1065
+ });
1066
+
1067
+ it("should handle project with symlinks", async () => {
1068
+ const symlinkProject = createMapTestProject({
1069
+ "index.js": "const app = require('./app');",
1070
+ "package.json": '{"name": "symlink-test"}',
1071
+ });
1072
+ tempDirs.push(symlinkProject);
1073
+
1074
+ // Create a symlink to a directory
1075
+ const targetDir = path.join(symlinkProject, "target-dir");
1076
+ fs.mkdirSync(targetDir);
1077
+ fs.writeFileSync(path.join(targetDir, "target.js"), "const y = 1;");
1078
+
1079
+ const symlinkDir = path.join(symlinkProject, "linked-dir");
1080
+ fs.symlinkSync(targetDir, symlinkDir);
1081
+
1082
+ const result = await runDoctorCommand([], symlinkProject);
1083
+
1084
+ expect(result.exitCode).toBeGreaterThanOrEqual(0);
1085
+ });
1086
+
1087
+ it("should handle large project with many files", async () => {
1088
+ const largeProject = createMapTestProject({
1089
+ "package.json": '{"name": "large"}',
1090
+ });
1091
+ tempDirs.push(largeProject);
1092
+
1093
+ for (let i = 0; i < 50; i++) {
1094
+ const dir = i < 25 ? "src" : "lib";
1095
+ const targetDir = path.join(largeProject, dir);
1096
+ if (!fs.existsSync(targetDir)) {
1097
+ fs.mkdirSync(targetDir, { recursive: true });
1098
+ }
1099
+ fs.writeFileSync(
1100
+ path.join(targetDir, `file${i}.js`),
1101
+ `const x${i} = ${i};`
1102
+ );
1103
+ }
1104
+
1105
+ const result = await runMapCommand([], largeProject);
1106
+
1107
+ expect(result.exitCode).toBe(0);
1108
+
1109
+ const filesJsonPath = path.join(largeProject, "ai-context", "files.json");
1110
+ expect(fs.existsSync(filesJsonPath)).toBe(true);
1111
+ });
1112
+ });
1113
+ });