ai-first-cli 1.3.1 → 1.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (514) hide show
  1. package/.ai-dev/index.db +0 -0
  2. package/CHANGELOG.md +241 -0
  3. package/PHASE1_USER_SIMULATION.md +56 -0
  4. package/PHASE2_USER_SIMULATION.md +81 -0
  5. package/PHASE3_USER_SIMULATION.md +176 -0
  6. package/README.es.md +73 -0
  7. package/README.md +119 -15
  8. package/ai/graph/knowledge-graph.json +10 -0
  9. package/ai-context/ai_context.md +130 -0
  10. package/{test-projects/react-app/.ai-dev → ai-context}/ai_rules.md +10 -5
  11. package/ai-context/architecture.md +136 -0
  12. package/ai-context/context/features/src.json +69 -0
  13. package/ai-context/context/features/test-projects.json +69 -0
  14. package/ai-context/context/flows/ai-first.json +9 -0
  15. package/ai-context/context/flows/auth.json +13 -0
  16. package/ai-context/context/flows/doctor.json +9 -0
  17. package/ai-context/context/flows/explore.json +9 -0
  18. package/ai-context/context/flows/routes.json +15 -0
  19. package/ai-context/context/flows/user.json +23 -0
  20. package/ai-context/context/flows/views.json +12 -0
  21. package/{test-projects/react-app/.ai-dev → ai-context}/conventions.md +3 -2
  22. package/ai-context/dependencies.json +3360 -0
  23. package/ai-context/entrypoints.md +45 -0
  24. package/ai-context/index-state.json +196 -0
  25. package/ai-context/modules.json +901 -0
  26. package/ai-context/project.json +33 -0
  27. package/ai-context/repo_map.json +8857 -0
  28. package/ai-context/repo_map.md +2002 -0
  29. package/{test-projects/flask-app/.ai-dev → ai-context}/schema.json +1 -1
  30. package/ai-context/summary.md +46 -0
  31. package/ai-context/symbols.json +82467 -0
  32. package/{test-projects/react-app/.ai-dev → ai-context}/tech_stack.md +15 -7
  33. package/ai-context-evaluation-report-1774223059505.md +206 -0
  34. package/dist/analyzers/architecture.d.ts.map +1 -1
  35. package/dist/analyzers/architecture.js +78 -5
  36. package/dist/analyzers/architecture.js.map +1 -1
  37. package/dist/analyzers/entrypoints.d.ts.map +1 -1
  38. package/dist/analyzers/entrypoints.js +358 -0
  39. package/dist/analyzers/entrypoints.js.map +1 -1
  40. package/dist/analyzers/symbols.d.ts.map +1 -1
  41. package/dist/analyzers/symbols.js +119 -3
  42. package/dist/analyzers/symbols.js.map +1 -1
  43. package/dist/analyzers/techStack.d.ts +8 -0
  44. package/dist/analyzers/techStack.d.ts.map +1 -1
  45. package/dist/analyzers/techStack.js +118 -0
  46. package/dist/analyzers/techStack.js.map +1 -1
  47. package/dist/utils/fileUtils.d.ts.map +1 -1
  48. package/dist/utils/fileUtils.js +5 -0
  49. package/dist/utils/fileUtils.js.map +1 -1
  50. package/package.json +1 -1
  51. package/scripts/ai-context-evaluator.ts +440 -0
  52. package/src/analyzers/architecture.ts +83 -6
  53. package/src/analyzers/entrypoints.ts +400 -0
  54. package/src/analyzers/symbols.ts +129 -3
  55. package/src/analyzers/techStack.ts +137 -0
  56. package/src/utils/fileUtils.ts +5 -0
  57. package/tests/apex-parser.test.ts +193 -0
  58. package/tests/cli-commands-batch1.test.ts +808 -0
  59. package/tests/cli-commands-batch2.test.ts +1113 -0
  60. package/tests/cli-commands-batch3.test.ts +1128 -0
  61. package/tests/cli-index.test.ts +1007 -0
  62. package/tests/cli-init.test.ts +761 -0
  63. package/tests/entrypoints-languages.test.ts +373 -0
  64. package/tests/framework-detection.test.ts +296 -0
  65. package/tests/salesforce-apex-classes.test.ts +713 -0
  66. package/tests/salesforce-apex-triggers.test.ts +871 -0
  67. package/tests/salesforce-custom-objects.test.ts +918 -0
  68. package/tests/salesforce-flows.test.ts +710 -0
  69. package/tests/salesforce-lwc.test.ts +963 -0
  70. package/tests/salesforce-sfdx-integration.test.ts +1125 -0
  71. package/ANALISIS_COMPLETO.md +0 -424
  72. package/ANALISIS_MEJORAS.md +0 -327
  73. package/CONTRIBUTING.md +0 -89
  74. package/FLOW.md +0 -129
  75. package/TEST_RESULTS.md +0 -198
  76. package/TEST_RESULTS_COMPARATIVE.md +0 -159
  77. package/TEST_RESULTS_COMPLETE.md +0 -127
  78. package/TEST_RESULTS_COMPREHENSIVE.md +0 -208
  79. package/install.sh +0 -188
  80. package/run-all-tests.sh +0 -184
  81. package/test-ai-context-understanding.sh +0 -21
  82. package/test-projects/django-app/.ai-dev/ai_context.md +0 -92
  83. package/test-projects/django-app/.ai-dev/ai_rules.md +0 -47
  84. package/test-projects/django-app/.ai-dev/architecture.md +0 -57
  85. package/test-projects/django-app/.ai-dev/cache.json +0 -169
  86. package/test-projects/django-app/.ai-dev/context/flows/views.json +0 -10
  87. package/test-projects/django-app/.ai-dev/conventions.md +0 -51
  88. package/test-projects/django-app/.ai-dev/dependencies.json +0 -312
  89. package/test-projects/django-app/.ai-dev/entrypoints.md +0 -4
  90. package/test-projects/django-app/.ai-dev/files.json +0 -209
  91. package/test-projects/django-app/.ai-dev/graph/knowledge-graph.json +0 -36
  92. package/test-projects/django-app/.ai-dev/graph/module-graph.json +0 -145
  93. package/test-projects/django-app/.ai-dev/graph/symbol-graph.json +0 -1488
  94. package/test-projects/django-app/.ai-dev/graph/symbol-references.json +0 -1
  95. package/test-projects/django-app/.ai-dev/index-state.json +0 -294
  96. package/test-projects/django-app/.ai-dev/modules.json +0 -35
  97. package/test-projects/django-app/.ai-dev/project.json +0 -11
  98. package/test-projects/django-app/.ai-dev/repo_map.json +0 -412
  99. package/test-projects/django-app/.ai-dev/repo_map.md +0 -105
  100. package/test-projects/django-app/.ai-dev/schema.json +0 -5
  101. package/test-projects/django-app/.ai-dev/summary.md +0 -15
  102. package/test-projects/django-app/.ai-dev/symbols.json +0 -1
  103. package/test-projects/django-app/.ai-dev/tech_stack.md +0 -32
  104. package/test-projects/django-app/README.md +0 -91
  105. package/test-projects/django-app/blog/__init__.py +0 -0
  106. package/test-projects/django-app/blog/admin.py +0 -31
  107. package/test-projects/django-app/blog/models.py +0 -55
  108. package/test-projects/django-app/blog/serializers.py +0 -69
  109. package/test-projects/django-app/blog/urls.py +0 -14
  110. package/test-projects/django-app/blog/views.py +0 -96
  111. package/test-projects/django-app/django_app/__init__.py +0 -0
  112. package/test-projects/django-app/django_app/settings.py +0 -90
  113. package/test-projects/django-app/django_app/urls.py +0 -11
  114. package/test-projects/django-app/django_app/wsgi.py +0 -9
  115. package/test-projects/django-app/manage.py +0 -23
  116. package/test-projects/django-app/requirements.txt +0 -3
  117. package/test-projects/django-app/users/__init__.py +0 -0
  118. package/test-projects/django-app/users/admin.py +0 -42
  119. package/test-projects/django-app/users/models.py +0 -54
  120. package/test-projects/django-app/users/serializers.py +0 -113
  121. package/test-projects/django-app/users/urls.py +0 -13
  122. package/test-projects/django-app/users/views.py +0 -135
  123. package/test-projects/express-api/.ai-dev/ai_context.md +0 -112
  124. package/test-projects/express-api/.ai-dev/ai_rules.md +0 -50
  125. package/test-projects/express-api/.ai-dev/architecture.md +0 -62
  126. package/test-projects/express-api/.ai-dev/context/features/controllers.json +0 -13
  127. package/test-projects/express-api/.ai-dev/context/features/services.json +0 -13
  128. package/test-projects/express-api/.ai-dev/context/flows/auth.json +0 -12
  129. package/test-projects/express-api/.ai-dev/context/flows/user.json +0 -13
  130. package/test-projects/express-api/.ai-dev/conventions.md +0 -51
  131. package/test-projects/express-api/.ai-dev/dependencies.json +0 -54
  132. package/test-projects/express-api/.ai-dev/entrypoints.md +0 -17
  133. package/test-projects/express-api/.ai-dev/modules.json +0 -30
  134. package/test-projects/express-api/.ai-dev/project.json +0 -15
  135. package/test-projects/express-api/.ai-dev/repo_map.json +0 -100
  136. package/test-projects/express-api/.ai-dev/repo_map.md +0 -36
  137. package/test-projects/express-api/.ai-dev/schema.json +0 -5
  138. package/test-projects/express-api/.ai-dev/summary.md +0 -14
  139. package/test-projects/express-api/.ai-dev/symbols.json +0 -7
  140. package/test-projects/express-api/.ai-dev/tech_stack.md +0 -38
  141. package/test-projects/express-api/.ai-dev/tools.json +0 -10
  142. package/test-projects/express-api/controllers/authController.js +0 -32
  143. package/test-projects/express-api/controllers/userController.js +0 -51
  144. package/test-projects/express-api/index.js +0 -30
  145. package/test-projects/express-api/middleware/authMiddleware.js +0 -30
  146. package/test-projects/express-api/models/userRepository.js +0 -25
  147. package/test-projects/express-api/package.json +0 -18
  148. package/test-projects/express-api/services/authService.js +0 -17
  149. package/test-projects/express-api/services/userService.js +0 -28
  150. package/test-projects/fastapi-app/.ai-dev/ai_context.md +0 -89
  151. package/test-projects/fastapi-app/.ai-dev/ai_rules.md +0 -47
  152. package/test-projects/fastapi-app/.ai-dev/architecture.md +0 -39
  153. package/test-projects/fastapi-app/.ai-dev/cache.json +0 -125
  154. package/test-projects/fastapi-app/.ai-dev/conventions.md +0 -51
  155. package/test-projects/fastapi-app/.ai-dev/dependencies.json +0 -244
  156. package/test-projects/fastapi-app/.ai-dev/entrypoints.md +0 -4
  157. package/test-projects/fastapi-app/.ai-dev/files.json +0 -154
  158. package/test-projects/fastapi-app/.ai-dev/graph/knowledge-graph.json +0 -15
  159. package/test-projects/fastapi-app/.ai-dev/graph/module-graph.json +0 -78
  160. package/test-projects/fastapi-app/.ai-dev/graph/symbol-graph.json +0 -1724
  161. package/test-projects/fastapi-app/.ai-dev/graph/symbol-references.json +0 -51
  162. package/test-projects/fastapi-app/.ai-dev/index-state.json +0 -217
  163. package/test-projects/fastapi-app/.ai-dev/modules.json +0 -16
  164. package/test-projects/fastapi-app/.ai-dev/project.json +0 -9
  165. package/test-projects/fastapi-app/.ai-dev/repo_map.json +0 -298
  166. package/test-projects/fastapi-app/.ai-dev/repo_map.md +0 -74
  167. package/test-projects/fastapi-app/.ai-dev/schema.json +0 -5
  168. package/test-projects/fastapi-app/.ai-dev/summary.md +0 -12
  169. package/test-projects/fastapi-app/.ai-dev/symbols.json +0 -1
  170. package/test-projects/fastapi-app/.ai-dev/tech_stack.md +0 -32
  171. package/test-projects/fastapi-app/.ai-dev/tools.json +0 -10
  172. package/test-projects/fastapi-app/README.md +0 -118
  173. package/test-projects/fastapi-app/app/database.py +0 -21
  174. package/test-projects/fastapi-app/app/dependencies.py +0 -107
  175. package/test-projects/fastapi-app/app/main.py +0 -47
  176. package/test-projects/fastapi-app/app/models.py +0 -149
  177. package/test-projects/fastapi-app/app/routers/auth.py +0 -117
  178. package/test-projects/fastapi-app/app/routers/posts.py +0 -272
  179. package/test-projects/fastapi-app/app/schemas.py +0 -191
  180. package/test-projects/fastapi-app/requirements.txt +0 -10
  181. package/test-projects/flask-app/.ai-dev/ai_context.md +0 -94
  182. package/test-projects/flask-app/.ai-dev/ai_rules.md +0 -47
  183. package/test-projects/flask-app/.ai-dev/architecture.md +0 -49
  184. package/test-projects/flask-app/.ai-dev/cache.json +0 -157
  185. package/test-projects/flask-app/.ai-dev/context/features/app.json +0 -25
  186. package/test-projects/flask-app/.ai-dev/context/flows/routes.json +0 -14
  187. package/test-projects/flask-app/.ai-dev/conventions.md +0 -51
  188. package/test-projects/flask-app/.ai-dev/dependencies.json +0 -298
  189. package/test-projects/flask-app/.ai-dev/entrypoints.md +0 -4
  190. package/test-projects/flask-app/.ai-dev/files.json +0 -194
  191. package/test-projects/flask-app/.ai-dev/graph/knowledge-graph.json +0 -60
  192. package/test-projects/flask-app/.ai-dev/graph/module-graph.json +0 -95
  193. package/test-projects/flask-app/.ai-dev/graph/symbol-graph.json +0 -1448
  194. package/test-projects/flask-app/.ai-dev/graph/symbol-references.json +0 -45
  195. package/test-projects/flask-app/.ai-dev/index-state.json +0 -273
  196. package/test-projects/flask-app/.ai-dev/modules.json +0 -21
  197. package/test-projects/flask-app/.ai-dev/project.json +0 -13
  198. package/test-projects/flask-app/.ai-dev/repo_map.json +0 -400
  199. package/test-projects/flask-app/.ai-dev/repo_map.md +0 -98
  200. package/test-projects/flask-app/.ai-dev/summary.md +0 -13
  201. package/test-projects/flask-app/.ai-dev/symbols.json +0 -1
  202. package/test-projects/flask-app/.ai-dev/tech_stack.md +0 -32
  203. package/test-projects/flask-app/.ai-dev/tools.json +0 -10
  204. package/test-projects/flask-app/README.md +0 -129
  205. package/test-projects/flask-app/app/__init__.py +0 -46
  206. package/test-projects/flask-app/app/api/__init__.py +0 -7
  207. package/test-projects/flask-app/app/api/routes.py +0 -122
  208. package/test-projects/flask-app/app/auth/__init__.py +0 -7
  209. package/test-projects/flask-app/app/auth/forms.py +0 -52
  210. package/test-projects/flask-app/app/auth/routes.py +0 -68
  211. package/test-projects/flask-app/app/blog/__init__.py +0 -7
  212. package/test-projects/flask-app/app/blog/forms.py +0 -35
  213. package/test-projects/flask-app/app/blog/routes.py +0 -140
  214. package/test-projects/flask-app/app/main/__init__.py +0 -7
  215. package/test-projects/flask-app/app/main/routes.py +0 -88
  216. package/test-projects/flask-app/app/models.py +0 -177
  217. package/test-projects/flask-app/config.py +0 -64
  218. package/test-projects/flask-app/requirements.txt +0 -10
  219. package/test-projects/laravel-app/.ai-dev/ai_context.md +0 -97
  220. package/test-projects/laravel-app/.ai-dev/ai_rules.md +0 -47
  221. package/test-projects/laravel-app/.ai-dev/architecture.md +0 -60
  222. package/test-projects/laravel-app/.ai-dev/cache.json +0 -161
  223. package/test-projects/laravel-app/.ai-dev/context/features/app.json +0 -21
  224. package/test-projects/laravel-app/.ai-dev/context/flows/.json +0 -9
  225. package/test-projects/laravel-app/.ai-dev/context/flows/category.json +0 -12
  226. package/test-projects/laravel-app/.ai-dev/context/flows/comment.json +0 -12
  227. package/test-projects/laravel-app/.ai-dev/context/flows/post.json +0 -12
  228. package/test-projects/laravel-app/.ai-dev/context/flows/unnamed.json +0 -9
  229. package/test-projects/laravel-app/.ai-dev/conventions.md +0 -51
  230. package/test-projects/laravel-app/.ai-dev/dependencies.json +0 -6
  231. package/test-projects/laravel-app/.ai-dev/entrypoints.md +0 -4
  232. package/test-projects/laravel-app/.ai-dev/files.json +0 -199
  233. package/test-projects/laravel-app/.ai-dev/graph/knowledge-graph.json +0 -98
  234. package/test-projects/laravel-app/.ai-dev/graph/module-graph.json +0 -30
  235. package/test-projects/laravel-app/.ai-dev/graph/symbol-graph.json +0 -5
  236. package/test-projects/laravel-app/.ai-dev/graph/symbol-references.json +0 -1
  237. package/test-projects/laravel-app/.ai-dev/index-state.json +0 -280
  238. package/test-projects/laravel-app/.ai-dev/modules.json +0 -29
  239. package/test-projects/laravel-app/.ai-dev/project.json +0 -17
  240. package/test-projects/laravel-app/.ai-dev/repo_map.json +0 -419
  241. package/test-projects/laravel-app/.ai-dev/repo_map.md +0 -106
  242. package/test-projects/laravel-app/.ai-dev/schema.json +0 -5
  243. package/test-projects/laravel-app/.ai-dev/summary.md +0 -15
  244. package/test-projects/laravel-app/.ai-dev/symbols.json +0 -1
  245. package/test-projects/laravel-app/.ai-dev/tech_stack.md +0 -34
  246. package/test-projects/laravel-app/.ai-dev/tools.json +0 -10
  247. package/test-projects/laravel-app/README.md +0 -107
  248. package/test-projects/laravel-app/app/Http/Controllers/Api/CategoryController.php +0 -88
  249. package/test-projects/laravel-app/app/Http/Controllers/Api/CommentController.php +0 -56
  250. package/test-projects/laravel-app/app/Http/Controllers/Api/PostController.php +0 -174
  251. package/test-projects/laravel-app/app/Http/Controllers/Controller.php +0 -12
  252. package/test-projects/laravel-app/app/Models/Category.php +0 -34
  253. package/test-projects/laravel-app/app/Models/Comment.php +0 -51
  254. package/test-projects/laravel-app/app/Models/Post.php +0 -108
  255. package/test-projects/laravel-app/app/Models/User.php +0 -85
  256. package/test-projects/laravel-app/bootstrap/app.php +0 -25
  257. package/test-projects/laravel-app/composer.json +0 -35
  258. package/test-projects/laravel-app/routes/api.php +0 -40
  259. package/test-projects/nestjs-backend/.ai-dev/ai_context.md +0 -111
  260. package/test-projects/nestjs-backend/.ai-dev/ai_rules.md +0 -52
  261. package/test-projects/nestjs-backend/.ai-dev/architecture.md +0 -49
  262. package/test-projects/nestjs-backend/.ai-dev/cache.json +0 -169
  263. package/test-projects/nestjs-backend/.ai-dev/context/features/src.json +0 -23
  264. package/test-projects/nestjs-backend/.ai-dev/context/flows/auth.controller.json +0 -14
  265. package/test-projects/nestjs-backend/.ai-dev/context/flows/auth.json +0 -10
  266. package/test-projects/nestjs-backend/.ai-dev/context/flows/users..json +0 -10
  267. package/test-projects/nestjs-backend/.ai-dev/context/flows/users.controller.json +0 -14
  268. package/test-projects/nestjs-backend/.ai-dev/context/flows/users.json +0 -10
  269. package/test-projects/nestjs-backend/.ai-dev/conventions.md +0 -52
  270. package/test-projects/nestjs-backend/.ai-dev/dependencies.json +0 -152
  271. package/test-projects/nestjs-backend/.ai-dev/entrypoints.md +0 -18
  272. package/test-projects/nestjs-backend/.ai-dev/files.json +0 -209
  273. package/test-projects/nestjs-backend/.ai-dev/graph/knowledge-graph.json +0 -132
  274. package/test-projects/nestjs-backend/.ai-dev/graph/module-graph.json +0 -29
  275. package/test-projects/nestjs-backend/.ai-dev/graph/symbol-graph.json +0 -304
  276. package/test-projects/nestjs-backend/.ai-dev/graph/symbol-references.json +0 -5
  277. package/test-projects/nestjs-backend/.ai-dev/index-state.json +0 -294
  278. package/test-projects/nestjs-backend/.ai-dev/modules.json +0 -19
  279. package/test-projects/nestjs-backend/.ai-dev/project.json +0 -18
  280. package/test-projects/nestjs-backend/.ai-dev/repo_map.json +0 -427
  281. package/test-projects/nestjs-backend/.ai-dev/repo_map.md +0 -104
  282. package/test-projects/nestjs-backend/.ai-dev/schema.json +0 -5
  283. package/test-projects/nestjs-backend/.ai-dev/summary.md +0 -13
  284. package/test-projects/nestjs-backend/.ai-dev/symbols.json +0 -1
  285. package/test-projects/nestjs-backend/.ai-dev/tech_stack.md +0 -38
  286. package/test-projects/nestjs-backend/.ai-dev/tools.json +0 -10
  287. package/test-projects/nestjs-backend/package.json +0 -22
  288. package/test-projects/nestjs-backend/src/app.module.ts +0 -8
  289. package/test-projects/nestjs-backend/src/auth/auth.controller.ts +0 -22
  290. package/test-projects/nestjs-backend/src/auth/auth.module.ts +0 -11
  291. package/test-projects/nestjs-backend/src/auth/auth.service.ts +0 -28
  292. package/test-projects/nestjs-backend/src/auth/dto/login.dto.ts +0 -4
  293. package/test-projects/nestjs-backend/src/auth/strategies/jwt.strategy.ts +0 -18
  294. package/test-projects/nestjs-backend/src/main.ts +0 -9
  295. package/test-projects/nestjs-backend/src/users/users.controller.ts +0 -32
  296. package/test-projects/nestjs-backend/src/users/users.module.ts +0 -10
  297. package/test-projects/nestjs-backend/src/users/users.service.ts +0 -42
  298. package/test-projects/nestjs-backend/tsconfig.json +0 -21
  299. package/test-projects/python-cli/.ai-dev/ai_context.md +0 -95
  300. package/test-projects/python-cli/.ai-dev/ai_rules.md +0 -47
  301. package/test-projects/python-cli/.ai-dev/architecture.md +0 -55
  302. package/test-projects/python-cli/.ai-dev/cache.json +0 -149
  303. package/test-projects/python-cli/.ai-dev/context/features/cli.json +0 -16
  304. package/test-projects/python-cli/.ai-dev/context/flows/list_.json +0 -9
  305. package/test-projects/python-cli/.ai-dev/context/flows/remove_.json +0 -9
  306. package/test-projects/python-cli/.ai-dev/conventions.md +0 -51
  307. package/test-projects/python-cli/.ai-dev/dependencies.json +0 -66
  308. package/test-projects/python-cli/.ai-dev/entrypoints.md +0 -4
  309. package/test-projects/python-cli/.ai-dev/files.json +0 -184
  310. package/test-projects/python-cli/.ai-dev/graph/knowledge-graph.json +0 -83
  311. package/test-projects/python-cli/.ai-dev/graph/module-graph.json +0 -31
  312. package/test-projects/python-cli/.ai-dev/graph/symbol-graph.json +0 -358
  313. package/test-projects/python-cli/.ai-dev/graph/symbol-references.json +0 -11
  314. package/test-projects/python-cli/.ai-dev/index-state.json +0 -259
  315. package/test-projects/python-cli/.ai-dev/modules.json +0 -21
  316. package/test-projects/python-cli/.ai-dev/project.json +0 -15
  317. package/test-projects/python-cli/.ai-dev/repo_map.json +0 -367
  318. package/test-projects/python-cli/.ai-dev/repo_map.md +0 -93
  319. package/test-projects/python-cli/.ai-dev/schema.json +0 -5
  320. package/test-projects/python-cli/.ai-dev/summary.md +0 -14
  321. package/test-projects/python-cli/.ai-dev/symbols.json +0 -1
  322. package/test-projects/python-cli/.ai-dev/tech_stack.md +0 -32
  323. package/test-projects/python-cli/.ai-dev/tools.json +0 -10
  324. package/test-projects/python-cli/__init__.py +0 -1
  325. package/test-projects/python-cli/cli/__init__.py +0 -1
  326. package/test-projects/python-cli/cli/add_command.py +0 -6
  327. package/test-projects/python-cli/cli/list_command.py +0 -7
  328. package/test-projects/python-cli/cli/remove_command.py +0 -6
  329. package/test-projects/python-cli/main.py +0 -34
  330. package/test-projects/python-cli/models/__init__.py +0 -2
  331. package/test-projects/python-cli/models/task.py +0 -19
  332. package/test-projects/python-cli/models/task_repository.py +0 -44
  333. package/test-projects/rails-app/.ai-dev/ai_context.md +0 -94
  334. package/test-projects/rails-app/.ai-dev/ai_rules.md +0 -47
  335. package/test-projects/rails-app/.ai-dev/architecture.md +0 -49
  336. package/test-projects/rails-app/.ai-dev/cache.json +0 -193
  337. package/test-projects/rails-app/.ai-dev/context/features/app.json +0 -24
  338. package/test-projects/rails-app/.ai-dev/context/features/config.json +0 -13
  339. package/test-projects/rails-app/.ai-dev/context/flows/application.json +0 -9
  340. package/test-projects/rails-app/.ai-dev/context/flows/application_.json +0 -9
  341. package/test-projects/rails-app/.ai-dev/context/flows/comments.json +0 -11
  342. package/test-projects/rails-app/.ai-dev/context/flows/comments_.json +0 -11
  343. package/test-projects/rails-app/.ai-dev/context/flows/posts.json +0 -11
  344. package/test-projects/rails-app/.ai-dev/context/flows/posts_.json +0 -11
  345. package/test-projects/rails-app/.ai-dev/context/flows/routes.json +0 -9
  346. package/test-projects/rails-app/.ai-dev/context/flows/users.json +0 -11
  347. package/test-projects/rails-app/.ai-dev/context/flows/users_.json +0 -11
  348. package/test-projects/rails-app/.ai-dev/conventions.md +0 -51
  349. package/test-projects/rails-app/.ai-dev/dependencies.json +0 -6
  350. package/test-projects/rails-app/.ai-dev/entrypoints.md +0 -4
  351. package/test-projects/rails-app/.ai-dev/files.json +0 -239
  352. package/test-projects/rails-app/.ai-dev/graph/knowledge-graph.json +0 -130
  353. package/test-projects/rails-app/.ai-dev/graph/module-graph.json +0 -27
  354. package/test-projects/rails-app/.ai-dev/graph/symbol-graph.json +0 -5
  355. package/test-projects/rails-app/.ai-dev/graph/symbol-references.json +0 -1
  356. package/test-projects/rails-app/.ai-dev/index-state.json +0 -336
  357. package/test-projects/rails-app/.ai-dev/modules.json +0 -26
  358. package/test-projects/rails-app/.ai-dev/project.json +0 -22
  359. package/test-projects/rails-app/.ai-dev/repo_map.json +0 -486
  360. package/test-projects/rails-app/.ai-dev/repo_map.md +0 -117
  361. package/test-projects/rails-app/.ai-dev/schema.json +0 -5
  362. package/test-projects/rails-app/.ai-dev/summary.md +0 -13
  363. package/test-projects/rails-app/.ai-dev/symbols.json +0 -1
  364. package/test-projects/rails-app/.ai-dev/tech_stack.md +0 -32
  365. package/test-projects/rails-app/.ai-dev/tools.json +0 -10
  366. package/test-projects/rails-app/Gemfile +0 -38
  367. package/test-projects/rails-app/README.md +0 -140
  368. package/test-projects/rails-app/Rakefile +0 -8
  369. package/test-projects/rails-app/app/controllers/api/comments_controller.rb +0 -75
  370. package/test-projects/rails-app/app/controllers/api/posts_controller.rb +0 -68
  371. package/test-projects/rails-app/app/controllers/api/users_controller.rb +0 -54
  372. package/test-projects/rails-app/app/controllers/application_controller.rb +0 -31
  373. package/test-projects/rails-app/app/models/comment.rb +0 -34
  374. package/test-projects/rails-app/app/models/post.rb +0 -36
  375. package/test-projects/rails-app/app/models/user.rb +0 -28
  376. package/test-projects/rails-app/app/services/post_service.rb +0 -92
  377. package/test-projects/rails-app/app/services/user_service.rb +0 -76
  378. package/test-projects/rails-app/config/application.rb +0 -27
  379. package/test-projects/rails-app/config/environment.rb +0 -7
  380. package/test-projects/rails-app/config/routes.rb +0 -15
  381. package/test-projects/react-app/.ai-dev/ai_context.md +0 -96
  382. package/test-projects/react-app/.ai-dev/architecture.md +0 -39
  383. package/test-projects/react-app/.ai-dev/cache.json +0 -153
  384. package/test-projects/react-app/.ai-dev/context/features/src.json +0 -18
  385. package/test-projects/react-app/.ai-dev/context/flows/UsersPage.json +0 -14
  386. package/test-projects/react-app/.ai-dev/context/flows/dashboard.json +0 -9
  387. package/test-projects/react-app/.ai-dev/context/flows/login.json +0 -9
  388. package/test-projects/react-app/.ai-dev/context/flows/users.json +0 -9
  389. package/test-projects/react-app/.ai-dev/dependencies.json +0 -128
  390. package/test-projects/react-app/.ai-dev/entrypoints.md +0 -4
  391. package/test-projects/react-app/.ai-dev/files.json +0 -189
  392. package/test-projects/react-app/.ai-dev/graph/knowledge-graph.json +0 -112
  393. package/test-projects/react-app/.ai-dev/graph/module-graph.json +0 -31
  394. package/test-projects/react-app/.ai-dev/graph/symbol-graph.json +0 -868
  395. package/test-projects/react-app/.ai-dev/graph/symbol-references.json +0 -31
  396. package/test-projects/react-app/.ai-dev/index-state.json +0 -266
  397. package/test-projects/react-app/.ai-dev/modules.json +0 -17
  398. package/test-projects/react-app/.ai-dev/project.json +0 -16
  399. package/test-projects/react-app/.ai-dev/repo_map.json +0 -391
  400. package/test-projects/react-app/.ai-dev/repo_map.md +0 -94
  401. package/test-projects/react-app/.ai-dev/schema.json +0 -5
  402. package/test-projects/react-app/.ai-dev/summary.md +0 -13
  403. package/test-projects/react-app/.ai-dev/symbols.json +0 -1
  404. package/test-projects/react-app/.ai-dev/tools.json +0 -10
  405. package/test-projects/react-app/package.json +0 -16
  406. package/test-projects/react-app/src/App.tsx +0 -21
  407. package/test-projects/react-app/src/context/AuthContext.tsx +0 -41
  408. package/test-projects/react-app/src/hooks/useAuth.ts +0 -10
  409. package/test-projects/react-app/src/main.tsx +0 -10
  410. package/test-projects/react-app/src/pages/DashboardPage.tsx +0 -17
  411. package/test-projects/react-app/src/pages/LoginPage.tsx +0 -41
  412. package/test-projects/react-app/src/pages/UsersPage.tsx +0 -36
  413. package/test-projects/react-app/src/services/userService.ts +0 -37
  414. package/test-projects/salesforce-cli/.ai-dev/ai_context.md +0 -89
  415. package/test-projects/salesforce-cli/.ai-dev/ai_rules.md +0 -47
  416. package/test-projects/salesforce-cli/.ai-dev/architecture.md +0 -39
  417. package/test-projects/salesforce-cli/.ai-dev/cache.json +0 -125
  418. package/test-projects/salesforce-cli/.ai-dev/context/features/force-app.json +0 -14
  419. package/test-projects/salesforce-cli/.ai-dev/context/flows/account.json +0 -9
  420. package/test-projects/salesforce-cli/.ai-dev/context/flows/opportunity.json +0 -9
  421. package/test-projects/salesforce-cli/.ai-dev/conventions.md +0 -51
  422. package/test-projects/salesforce-cli/.ai-dev/dependencies.json +0 -6
  423. package/test-projects/salesforce-cli/.ai-dev/entrypoints.md +0 -4
  424. package/test-projects/salesforce-cli/.ai-dev/files.json +0 -154
  425. package/test-projects/salesforce-cli/.ai-dev/graph/knowledge-graph.json +0 -64
  426. package/test-projects/salesforce-cli/.ai-dev/graph/module-graph.json +0 -13
  427. package/test-projects/salesforce-cli/.ai-dev/graph/symbol-graph.json +0 -148
  428. package/test-projects/salesforce-cli/.ai-dev/graph/symbol-references.json +0 -1
  429. package/test-projects/salesforce-cli/.ai-dev/index-state.json +0 -217
  430. package/test-projects/salesforce-cli/.ai-dev/modules.json +0 -12
  431. package/test-projects/salesforce-cli/.ai-dev/project.json +0 -14
  432. package/test-projects/salesforce-cli/.ai-dev/repo_map.json +0 -328
  433. package/test-projects/salesforce-cli/.ai-dev/repo_map.md +0 -80
  434. package/test-projects/salesforce-cli/.ai-dev/schema.json +0 -5
  435. package/test-projects/salesforce-cli/.ai-dev/summary.md +0 -13
  436. package/test-projects/salesforce-cli/.ai-dev/symbols.json +0 -1
  437. package/test-projects/salesforce-cli/.ai-dev/tech_stack.md +0 -31
  438. package/test-projects/salesforce-cli/.ai-dev/tools.json +0 -10
  439. package/test-projects/salesforce-cli/.forceignore +0 -27
  440. package/test-projects/salesforce-cli/force-app/main/default/classes/AccountController.cls +0 -24
  441. package/test-projects/salesforce-cli/force-app/main/default/classes/OpportunityController.cls +0 -25
  442. package/test-projects/salesforce-cli/force-app/main/default/objects/Project__c.object.xml +0 -45
  443. package/test-projects/salesforce-cli/force-app/main/default/triggers/AccountTrigger.trigger +0 -33
  444. package/test-projects/salesforce-cli/sfdx-project.json +0 -11
  445. package/test-projects/spring-boot-app/.ai-dev/ai_context.md +0 -91
  446. package/test-projects/spring-boot-app/.ai-dev/ai_rules.md +0 -48
  447. package/test-projects/spring-boot-app/.ai-dev/architecture.md +0 -39
  448. package/test-projects/spring-boot-app/.ai-dev/cache.json +0 -173
  449. package/test-projects/spring-boot-app/.ai-dev/context/features/src.json +0 -26
  450. package/test-projects/spring-boot-app/.ai-dev/context/flows/PostController.json +0 -19
  451. package/test-projects/spring-boot-app/.ai-dev/context/flows/UserController.json +0 -19
  452. package/test-projects/spring-boot-app/.ai-dev/context/flows/comment.json +0 -11
  453. package/test-projects/spring-boot-app/.ai-dev/context/flows/post.json +0 -14
  454. package/test-projects/spring-boot-app/.ai-dev/context/flows/user.json +0 -14
  455. package/test-projects/spring-boot-app/.ai-dev/conventions.md +0 -52
  456. package/test-projects/spring-boot-app/.ai-dev/dependencies.json +0 -326
  457. package/test-projects/spring-boot-app/.ai-dev/entrypoints.md +0 -4
  458. package/test-projects/spring-boot-app/.ai-dev/files.json +0 -214
  459. package/test-projects/spring-boot-app/.ai-dev/graph/knowledge-graph.json +0 -231
  460. package/test-projects/spring-boot-app/.ai-dev/graph/module-graph.json +0 -22
  461. package/test-projects/spring-boot-app/.ai-dev/graph/symbol-graph.json +0 -794
  462. package/test-projects/spring-boot-app/.ai-dev/graph/symbol-references.json +0 -70
  463. package/test-projects/spring-boot-app/.ai-dev/index-state.json +0 -301
  464. package/test-projects/spring-boot-app/.ai-dev/modules.json +0 -21
  465. package/test-projects/spring-boot-app/.ai-dev/project.json +0 -17
  466. package/test-projects/spring-boot-app/.ai-dev/repo_map.json +0 -461
  467. package/test-projects/spring-boot-app/.ai-dev/repo_map.md +0 -109
  468. package/test-projects/spring-boot-app/.ai-dev/schema.json +0 -5
  469. package/test-projects/spring-boot-app/.ai-dev/summary.md +0 -12
  470. package/test-projects/spring-boot-app/.ai-dev/symbols.json +0 -1
  471. package/test-projects/spring-boot-app/.ai-dev/tech_stack.md +0 -32
  472. package/test-projects/spring-boot-app/.ai-dev/tools.json +0 -10
  473. package/test-projects/spring-boot-app/.classpath +0 -57
  474. package/test-projects/spring-boot-app/.factorypath +0 -69
  475. package/test-projects/spring-boot-app/.project +0 -34
  476. package/test-projects/spring-boot-app/.settings/org.eclipse.core.resources.prefs +0 -4
  477. package/test-projects/spring-boot-app/.settings/org.eclipse.jdt.apt.core.prefs +0 -4
  478. package/test-projects/spring-boot-app/.settings/org.eclipse.jdt.core.prefs +0 -10
  479. package/test-projects/spring-boot-app/.settings/org.eclipse.m2e.core.prefs +0 -4
  480. package/test-projects/spring-boot-app/README.md +0 -122
  481. package/test-projects/spring-boot-app/pom.xml +0 -79
  482. package/test-projects/spring-boot-app/src/main/java/com/example/demo/DemoApplication.java +0 -12
  483. package/test-projects/spring-boot-app/src/main/java/com/example/demo/controllers/CommentController.java +0 -89
  484. package/test-projects/spring-boot-app/src/main/java/com/example/demo/controllers/PostController.java +0 -92
  485. package/test-projects/spring-boot-app/src/main/java/com/example/demo/controllers/UserController.java +0 -84
  486. package/test-projects/spring-boot-app/src/main/java/com/example/demo/models/Comment.java +0 -38
  487. package/test-projects/spring-boot-app/src/main/java/com/example/demo/models/Post.java +0 -56
  488. package/test-projects/spring-boot-app/src/main/java/com/example/demo/models/User.java +0 -44
  489. package/test-projects/spring-boot-app/src/main/java/com/example/demo/repositories/CommentRepository.java +0 -21
  490. package/test-projects/spring-boot-app/src/main/java/com/example/demo/repositories/PostRepository.java +0 -18
  491. package/test-projects/spring-boot-app/src/main/java/com/example/demo/repositories/UserRepository.java +0 -15
  492. package/test-projects/spring-boot-app/src/main/java/com/example/demo/services/PostService.java +0 -83
  493. package/test-projects/spring-boot-app/src/main/java/com/example/demo/services/UserService.java +0 -62
  494. package/test-projects/spring-boot-app/src/main/resources/application.properties +0 -22
  495. package/test-projects/spring-boot-app/target/classes/com/example/demo/DemoApplication.class +0 -0
  496. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/CommentController$CommentCreateRequest.class +0 -0
  497. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/CommentController$CommentUpdateRequest.class +0 -0
  498. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/CommentController.class +0 -0
  499. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/PostController$PostCreateRequest.class +0 -0
  500. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/PostController$PostUpdateRequest.class +0 -0
  501. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/PostController.class +0 -0
  502. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/UserController$UserCreateRequest.class +0 -0
  503. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/UserController$UserUpdateRequest.class +0 -0
  504. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/UserController.class +0 -0
  505. package/test-projects/spring-boot-app/target/classes/com/example/demo/models/Comment.class +0 -0
  506. package/test-projects/spring-boot-app/target/classes/com/example/demo/models/Post.class +0 -0
  507. package/test-projects/spring-boot-app/target/classes/com/example/demo/models/User.class +0 -0
  508. package/test-projects/spring-boot-app/target/classes/com/example/demo/repositories/CommentRepository.class +0 -0
  509. package/test-projects/spring-boot-app/target/classes/com/example/demo/repositories/PostRepository.class +0 -0
  510. package/test-projects/spring-boot-app/target/classes/com/example/demo/repositories/UserRepository.class +0 -0
  511. package/test-projects/spring-boot-app/target/classes/com/example/demo/services/PostService.class +0 -0
  512. package/test-projects/spring-boot-app/target/classes/com/example/demo/services/UserService.class +0 -0
  513. package/tests/e2e/run-e2e.sh +0 -88
  514. /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
+ });