devchain-cli 0.11.4 → 0.12.0

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 (337) hide show
  1. package/README.md +8 -4
  2. package/dist/drizzle/0050_teams.sql +26 -0
  3. package/dist/drizzle/0051_teams_optional_lead.sql +17 -0
  4. package/dist/drizzle/0054_provider_config_description.sql +1 -0
  5. package/dist/drizzle/0055_team_profiles.sql +10 -0
  6. package/dist/drizzle/0056_team_profile_configs.sql +11 -0
  7. package/dist/drizzle/0057_white_lester.sql +2 -0
  8. package/dist/drizzle/0058_fluffy_wolverine.sql +1 -0
  9. package/dist/drizzle/0059_loving_daimon_hellstrom.sql +1 -0
  10. package/dist/drizzle/meta/0050_snapshot.json +4929 -0
  11. package/dist/drizzle/meta/0051_snapshot.json +4929 -0
  12. package/dist/drizzle/meta/0053_snapshot.json +4944 -0
  13. package/dist/drizzle/meta/0054_snapshot.json +4951 -0
  14. package/dist/drizzle/meta/0055_snapshot.json +5025 -0
  15. package/dist/drizzle/meta/0056_snapshot.json +5109 -0
  16. package/dist/drizzle/meta/0057_snapshot.json +5125 -0
  17. package/dist/drizzle/meta/0058_snapshot.json +5133 -0
  18. package/dist/drizzle/meta/0059_snapshot.json +5140 -0
  19. package/dist/drizzle/meta/_journal.json +60 -4
  20. package/dist/node_modules/@devchain/codebase-overview/index.d.ts +2 -0
  21. package/dist/node_modules/@devchain/codebase-overview/index.d.ts.map +1 -0
  22. package/dist/node_modules/@devchain/codebase-overview/index.js +2 -0
  23. package/dist/node_modules/@devchain/codebase-overview/index.js.map +1 -0
  24. package/dist/node_modules/@devchain/codebase-overview/package.json +8 -0
  25. package/dist/node_modules/@devchain/codebase-overview/tsconfig.tsbuildinfo +1 -0
  26. package/dist/node_modules/@devchain/codebase-overview/types.d.ts +232 -0
  27. package/dist/node_modules/@devchain/codebase-overview/types.d.ts.map +1 -0
  28. package/dist/node_modules/@devchain/codebase-overview/types.js +2 -0
  29. package/dist/node_modules/@devchain/codebase-overview/types.js.map +1 -0
  30. package/dist/node_modules/@devchain/shared/index.d.ts +1 -1
  31. package/dist/node_modules/@devchain/shared/index.d.ts.map +1 -1
  32. package/dist/node_modules/@devchain/shared/index.js +1 -1
  33. package/dist/node_modules/@devchain/shared/index.js.map +1 -1
  34. package/dist/node_modules/@devchain/shared/schemas/env-vars.d.ts +3 -0
  35. package/dist/node_modules/@devchain/shared/schemas/env-vars.d.ts.map +1 -0
  36. package/dist/node_modules/@devchain/shared/schemas/env-vars.js +14 -0
  37. package/dist/node_modules/@devchain/shared/schemas/env-vars.js.map +1 -0
  38. package/dist/node_modules/@devchain/shared/schemas/export-schema.d.ts +99 -13
  39. package/dist/node_modules/@devchain/shared/schemas/export-schema.d.ts.map +1 -1
  40. package/dist/node_modules/@devchain/shared/schemas/export-schema.js +25 -1
  41. package/dist/node_modules/@devchain/shared/schemas/export-schema.js.map +1 -1
  42. package/dist/node_modules/@devchain/shared/schemas/index.d.ts +1 -0
  43. package/dist/node_modules/@devchain/shared/schemas/index.d.ts.map +1 -1
  44. package/dist/node_modules/@devchain/shared/schemas/index.js +1 -0
  45. package/dist/node_modules/@devchain/shared/schemas/index.js.map +1 -1
  46. package/dist/node_modules/@devchain/shared/tsconfig.tsbuildinfo +1 -1
  47. package/dist/server/app.main.module.js +4 -0
  48. package/dist/server/app.main.module.js.map +1 -1
  49. package/dist/server/app.normal.module.js +4 -0
  50. package/dist/server/app.normal.module.js.map +1 -1
  51. package/dist/server/common/config/feature-flags.d.ts +0 -2
  52. package/dist/server/common/config/feature-flags.js +1 -4
  53. package/dist/server/common/config/feature-flags.js.map +1 -1
  54. package/dist/server/common/errors/error-types.d.ts +3 -0
  55. package/dist/server/common/errors/error-types.js +10 -1
  56. package/dist/server/common/errors/error-types.js.map +1 -1
  57. package/dist/server/common/resolve-binary.d.ts +1 -0
  58. package/dist/server/common/resolve-binary.js +35 -0
  59. package/dist/server/common/resolve-binary.js.map +1 -0
  60. package/dist/server/common/template/agent-recipient-context.d.ts +10 -0
  61. package/dist/server/common/template/agent-recipient-context.js +13 -0
  62. package/dist/server/common/template/agent-recipient-context.js.map +1 -0
  63. package/dist/server/common/template/handlebars-renderer.d.ts +1 -0
  64. package/dist/server/common/template/handlebars-renderer.js +26 -0
  65. package/dist/server/common/template/handlebars-renderer.js.map +1 -0
  66. package/dist/server/modules/agents/agents.module.js +2 -1
  67. package/dist/server/modules/agents/agents.module.js.map +1 -1
  68. package/dist/server/modules/agents/controllers/agents.controller.d.ts +3 -1
  69. package/dist/server/modules/agents/controllers/agents.controller.js +36 -3
  70. package/dist/server/modules/agents/controllers/agents.controller.js.map +1 -1
  71. package/dist/server/modules/codebase-overview-analyzer/codebase-overview-analyzer.module.d.ts +2 -0
  72. package/dist/server/modules/codebase-overview-analyzer/codebase-overview-analyzer.module.js +51 -0
  73. package/dist/server/modules/codebase-overview-analyzer/codebase-overview-analyzer.module.js.map +1 -0
  74. package/dist/server/modules/codebase-overview-analyzer/controllers/codebase-overview.controller.d.ts +30 -0
  75. package/dist/server/modules/codebase-overview-analyzer/controllers/codebase-overview.controller.js +225 -0
  76. package/dist/server/modules/codebase-overview-analyzer/controllers/codebase-overview.controller.js.map +1 -0
  77. package/dist/server/modules/codebase-overview-analyzer/repositories/overview-scope.repository.d.ts +24 -0
  78. package/dist/server/modules/codebase-overview-analyzer/repositories/overview-scope.repository.js +188 -0
  79. package/dist/server/modules/codebase-overview-analyzer/repositories/overview-scope.repository.js.map +1 -0
  80. package/dist/server/modules/codebase-overview-analyzer/services/codebase-overview-analyzer.service.d.ts +71 -0
  81. package/dist/server/modules/codebase-overview-analyzer/services/codebase-overview-analyzer.service.js +1128 -0
  82. package/dist/server/modules/codebase-overview-analyzer/services/codebase-overview-analyzer.service.js.map +1 -0
  83. package/dist/server/modules/codebase-overview-analyzer/services/dependency-aggregation.service.d.ts +14 -0
  84. package/dist/server/modules/codebase-overview-analyzer/services/dependency-aggregation.service.js +114 -0
  85. package/dist/server/modules/codebase-overview-analyzer/services/dependency-aggregation.service.js.map +1 -0
  86. package/dist/server/modules/codebase-overview-analyzer/services/district-splitting.service.d.ts +8 -0
  87. package/dist/server/modules/codebase-overview-analyzer/services/district-splitting.service.js +200 -0
  88. package/dist/server/modules/codebase-overview-analyzer/services/district-splitting.service.js.map +1 -0
  89. package/dist/server/modules/codebase-overview-analyzer/services/evidence-query.service.d.ts +11 -0
  90. package/dist/server/modules/codebase-overview-analyzer/services/evidence-query.service.js +164 -0
  91. package/dist/server/modules/codebase-overview-analyzer/services/evidence-query.service.js.map +1 -0
  92. package/dist/server/modules/codebase-overview-analyzer/services/go-adapter.d.ts +2 -0
  93. package/dist/server/modules/codebase-overview-analyzer/services/go-adapter.js +166 -0
  94. package/dist/server/modules/codebase-overview-analyzer/services/go-adapter.js.map +1 -0
  95. package/dist/server/modules/codebase-overview-analyzer/services/hotspot-scoring.service.d.ts +21 -0
  96. package/dist/server/modules/codebase-overview-analyzer/services/hotspot-scoring.service.js +252 -0
  97. package/dist/server/modules/codebase-overview-analyzer/services/hotspot-scoring.service.js.map +1 -0
  98. package/dist/server/modules/codebase-overview-analyzer/services/identity-resolver.service.d.ts +24 -0
  99. package/dist/server/modules/codebase-overview-analyzer/services/identity-resolver.service.js +98 -0
  100. package/dist/server/modules/codebase-overview-analyzer/services/identity-resolver.service.js.map +1 -0
  101. package/dist/server/modules/codebase-overview-analyzer/services/java-adapter.d.ts +2 -0
  102. package/dist/server/modules/codebase-overview-analyzer/services/java-adapter.js +155 -0
  103. package/dist/server/modules/codebase-overview-analyzer/services/java-adapter.js.map +1 -0
  104. package/dist/server/modules/codebase-overview-analyzer/services/language-adapter-registry.service.d.ts +19 -0
  105. package/dist/server/modules/codebase-overview-analyzer/services/language-adapter-registry.service.js +87 -0
  106. package/dist/server/modules/codebase-overview-analyzer/services/language-adapter-registry.service.js.map +1 -0
  107. package/dist/server/modules/codebase-overview-analyzer/services/php-adapter.d.ts +2 -0
  108. package/dist/server/modules/codebase-overview-analyzer/services/php-adapter.js +173 -0
  109. package/dist/server/modules/codebase-overview-analyzer/services/php-adapter.js.map +1 -0
  110. package/dist/server/modules/codebase-overview-analyzer/services/python-adapter.d.ts +2 -0
  111. package/dist/server/modules/codebase-overview-analyzer/services/python-adapter.js +171 -0
  112. package/dist/server/modules/codebase-overview-analyzer/services/python-adapter.js.map +1 -0
  113. package/dist/server/modules/codebase-overview-analyzer/services/ruby-adapter.d.ts +2 -0
  114. package/dist/server/modules/codebase-overview-analyzer/services/ruby-adapter.js +158 -0
  115. package/dist/server/modules/codebase-overview-analyzer/services/ruby-adapter.js.map +1 -0
  116. package/dist/server/modules/codebase-overview-analyzer/services/rust-adapter.d.ts +2 -0
  117. package/dist/server/modules/codebase-overview-analyzer/services/rust-adapter.js +222 -0
  118. package/dist/server/modules/codebase-overview-analyzer/services/rust-adapter.js.map +1 -0
  119. package/dist/server/modules/codebase-overview-analyzer/services/scope-auto-detector.service.d.ts +4 -0
  120. package/dist/server/modules/codebase-overview-analyzer/services/scope-auto-detector.service.js +72 -0
  121. package/dist/server/modules/codebase-overview-analyzer/services/scope-auto-detector.service.js.map +1 -0
  122. package/dist/server/modules/codebase-overview-analyzer/services/scope-resolver.service.d.ts +6 -0
  123. package/dist/server/modules/codebase-overview-analyzer/services/scope-resolver.service.js +37 -0
  124. package/dist/server/modules/codebase-overview-analyzer/services/scope-resolver.service.js.map +1 -0
  125. package/dist/server/modules/codebase-overview-analyzer/services/typescript-adapter.d.ts +2 -0
  126. package/dist/server/modules/codebase-overview-analyzer/services/typescript-adapter.js +108 -0
  127. package/dist/server/modules/codebase-overview-analyzer/services/typescript-adapter.js.map +1 -0
  128. package/dist/server/modules/codebase-overview-analyzer/types/index.d.ts +2 -0
  129. package/dist/server/modules/codebase-overview-analyzer/types/index.js +6 -0
  130. package/dist/server/modules/codebase-overview-analyzer/types/index.js.map +1 -0
  131. package/dist/server/modules/codebase-overview-analyzer/types/scope-defaults.d.ts +2 -0
  132. package/dist/server/modules/codebase-overview-analyzer/types/scope-defaults.js +13 -0
  133. package/dist/server/modules/codebase-overview-analyzer/types/scope-defaults.js.map +1 -0
  134. package/dist/server/modules/codebase-overview-analyzer/types/scope.schema.d.ts +54 -0
  135. package/dist/server/modules/codebase-overview-analyzer/types/scope.schema.js +27 -0
  136. package/dist/server/modules/codebase-overview-analyzer/types/scope.schema.js.map +1 -0
  137. package/dist/server/modules/codebase-overview-analyzer/types/scope.types.d.ts +12 -0
  138. package/dist/server/modules/codebase-overview-analyzer/types/scope.types.js +3 -0
  139. package/dist/server/modules/codebase-overview-analyzer/types/scope.types.js.map +1 -0
  140. package/dist/server/modules/codebase-overview-analyzer/utils/constants.d.ts +1 -0
  141. package/dist/server/modules/codebase-overview-analyzer/utils/constants.js +5 -0
  142. package/dist/server/modules/codebase-overview-analyzer/utils/constants.js.map +1 -0
  143. package/dist/server/modules/codebase-overview-analyzer/utils/path-matcher.d.ts +2 -0
  144. package/dist/server/modules/codebase-overview-analyzer/utils/path-matcher.js +17 -0
  145. package/dist/server/modules/codebase-overview-analyzer/utils/path-matcher.js.map +1 -0
  146. package/dist/server/modules/core/controllers/preflight.controller.d.ts +1 -1
  147. package/dist/server/modules/core/controllers/preflight.controller.js +6 -4
  148. package/dist/server/modules/core/controllers/preflight.controller.js.map +1 -1
  149. package/dist/server/modules/core/services/preflight.service.d.ts +7 -1
  150. package/dist/server/modules/core/services/preflight.service.js +127 -10
  151. package/dist/server/modules/core/services/preflight.service.js.map +1 -1
  152. package/dist/server/modules/events/catalog/agent.created.d.ts +42 -0
  153. package/dist/server/modules/events/catalog/agent.created.js +23 -0
  154. package/dist/server/modules/events/catalog/agent.created.js.map +1 -0
  155. package/dist/server/modules/events/catalog/agent.deleted.d.ts +42 -0
  156. package/dist/server/modules/events/catalog/agent.deleted.js +22 -0
  157. package/dist/server/modules/events/catalog/agent.deleted.js.map +1 -0
  158. package/dist/server/modules/events/catalog/index.d.ts +180 -0
  159. package/dist/server/modules/events/catalog/index.js +10 -0
  160. package/dist/server/modules/events/catalog/index.js.map +1 -1
  161. package/dist/server/modules/events/catalog/team.config.updated.d.ts +67 -0
  162. package/dist/server/modules/events/catalog/team.config.updated.js +21 -0
  163. package/dist/server/modules/events/catalog/team.config.updated.js.map +1 -0
  164. package/dist/server/modules/events/catalog/team.member.added.d.ts +27 -0
  165. package/dist/server/modules/events/catalog/team.member.added.js +16 -0
  166. package/dist/server/modules/events/catalog/team.member.added.js.map +1 -0
  167. package/dist/server/modules/events/catalog/team.member.removed.d.ts +27 -0
  168. package/dist/server/modules/events/catalog/team.member.removed.js +16 -0
  169. package/dist/server/modules/events/catalog/team.member.removed.js.map +1 -0
  170. package/dist/server/modules/events/controllers/event-log.controller.d.ts +1 -1
  171. package/dist/server/modules/events/controllers/event-log.controller.js +11 -9
  172. package/dist/server/modules/events/controllers/event-log.controller.js.map +1 -1
  173. package/dist/server/modules/events/dtos/event-log.dto.d.ts +1 -0
  174. package/dist/server/modules/events/services/event-log.service.js +3 -0
  175. package/dist/server/modules/events/services/event-log.service.js.map +1 -1
  176. package/dist/server/modules/events/subscribers/epic-assignment-notifier.subscriber.d.ts +2 -1
  177. package/dist/server/modules/events/subscribers/epic-assignment-notifier.subscriber.js +30 -10
  178. package/dist/server/modules/events/subscribers/epic-assignment-notifier.subscriber.js.map +1 -1
  179. package/dist/server/modules/events/subscribers/index.js +8 -0
  180. package/dist/server/modules/events/subscribers/index.js.map +1 -1
  181. package/dist/server/modules/events/subscribers/project-state-broadcaster.subscriber.d.ts +16 -0
  182. package/dist/server/modules/events/subscribers/project-state-broadcaster.subscriber.js +101 -0
  183. package/dist/server/modules/events/subscribers/project-state-broadcaster.subscriber.js.map +1 -0
  184. package/dist/server/modules/events/subscribers/review-comment-notifier.subscriber.d.ts +2 -1
  185. package/dist/server/modules/events/subscribers/review-comment-notifier.subscriber.js +30 -8
  186. package/dist/server/modules/events/subscribers/review-comment-notifier.subscriber.js.map +1 -1
  187. package/dist/server/modules/events/subscribers/sub-epic-created-notifier.subscriber.d.ts +18 -0
  188. package/dist/server/modules/events/subscribers/sub-epic-created-notifier.subscriber.js +154 -0
  189. package/dist/server/modules/events/subscribers/sub-epic-created-notifier.subscriber.js.map +1 -0
  190. package/dist/server/modules/events/subscribers/team-config-updated-notifier.subscriber.d.ts +18 -0
  191. package/dist/server/modules/events/subscribers/team-config-updated-notifier.subscriber.js +138 -0
  192. package/dist/server/modules/events/subscribers/team-config-updated-notifier.subscriber.js.map +1 -0
  193. package/dist/server/modules/events/subscribers/team-membership-changed-notifier.subscriber.d.ts +18 -0
  194. package/dist/server/modules/events/subscribers/team-membership-changed-notifier.subscriber.js +129 -0
  195. package/dist/server/modules/events/subscribers/team-membership-changed-notifier.subscriber.js.map +1 -0
  196. package/dist/server/modules/mcp/dtos/mcp.dto.d.ts +173 -0
  197. package/dist/server/modules/mcp/dtos/mcp.dto.js +69 -6
  198. package/dist/server/modules/mcp/dtos/mcp.dto.js.map +1 -1
  199. package/dist/server/modules/mcp/dtos/schema-registry.js +6 -0
  200. package/dist/server/modules/mcp/dtos/schema-registry.js.map +1 -1
  201. package/dist/server/modules/mcp/mcp.module.js +2 -0
  202. package/dist/server/modules/mcp/mcp.module.js.map +1 -1
  203. package/dist/server/modules/mcp/services/handlers/chat-tools.js +117 -3
  204. package/dist/server/modules/mcp/services/handlers/chat-tools.js.map +1 -1
  205. package/dist/server/modules/mcp/services/handlers/epic-tools.js +26 -4
  206. package/dist/server/modules/mcp/services/handlers/epic-tools.js.map +1 -1
  207. package/dist/server/modules/mcp/services/handlers/prompt-tools.js +33 -1
  208. package/dist/server/modules/mcp/services/handlers/prompt-tools.js.map +1 -1
  209. package/dist/server/modules/mcp/services/handlers/teams-tools.d.ts +8 -0
  210. package/dist/server/modules/mcp/services/handlers/teams-tools.js +457 -0
  211. package/dist/server/modules/mcp/services/handlers/teams-tools.js.map +1 -0
  212. package/dist/server/modules/mcp/services/handlers/types.d.ts +2 -0
  213. package/dist/server/modules/mcp/services/instructions-resolver.d.ts +7 -3
  214. package/dist/server/modules/mcp/services/instructions-resolver.js +50 -26
  215. package/dist/server/modules/mcp/services/instructions-resolver.js.map +1 -1
  216. package/dist/server/modules/mcp/services/mcp-provider-registration.service.d.ts +0 -1
  217. package/dist/server/modules/mcp/services/mcp-provider-registration.service.js +11 -43
  218. package/dist/server/modules/mcp/services/mcp-provider-registration.service.js.map +1 -1
  219. package/dist/server/modules/mcp/services/mcp.service.d.ts +3 -1
  220. package/dist/server/modules/mcp/services/mcp.service.js +15 -3
  221. package/dist/server/modules/mcp/services/mcp.service.js.map +1 -1
  222. package/dist/server/modules/mcp/tool-definitions.d.ts +501 -0
  223. package/dist/server/modules/mcp/tool-definitions.js +137 -3
  224. package/dist/server/modules/mcp/tool-definitions.js.map +1 -1
  225. package/dist/server/modules/profiles/controllers/profiles.controller.js +1 -0
  226. package/dist/server/modules/profiles/controllers/profiles.controller.js.map +1 -1
  227. package/dist/server/modules/profiles/controllers/provider-configs.controller.js +3 -0
  228. package/dist/server/modules/profiles/controllers/provider-configs.controller.js.map +1 -1
  229. package/dist/server/modules/profiles/dto.d.ts +19 -6
  230. package/dist/server/modules/profiles/dto.js +13 -15
  231. package/dist/server/modules/profiles/dto.js.map +1 -1
  232. package/dist/server/modules/projects/controllers/projects.controller.d.ts +34 -0
  233. package/dist/server/modules/projects/controllers/projects.controller.js +52 -1
  234. package/dist/server/modules/projects/controllers/projects.controller.js.map +1 -1
  235. package/dist/server/modules/projects/helpers/project-export.d.ts +47 -0
  236. package/dist/server/modules/projects/helpers/project-export.js +116 -40
  237. package/dist/server/modules/projects/helpers/project-export.js.map +1 -1
  238. package/dist/server/modules/projects/helpers/project-import.d.ts +62 -0
  239. package/dist/server/modules/projects/helpers/project-import.js +191 -1
  240. package/dist/server/modules/projects/helpers/project-import.js.map +1 -1
  241. package/dist/server/modules/projects/helpers/template-loader.d.ts +13 -0
  242. package/dist/server/modules/projects/helpers/template-loader.js +60 -1
  243. package/dist/server/modules/projects/helpers/template-loader.js.map +1 -1
  244. package/dist/server/modules/projects/projects.module.js +2 -1
  245. package/dist/server/modules/projects/projects.module.js.map +1 -1
  246. package/dist/server/modules/projects/services/projects.service.d.ts +41 -1
  247. package/dist/server/modules/projects/services/projects.service.js +9 -2
  248. package/dist/server/modules/projects/services/projects.service.js.map +1 -1
  249. package/dist/server/modules/providers/adapters/gemini.adapter.js +2 -2
  250. package/dist/server/modules/providers/adapters/gemini.adapter.js.map +1 -1
  251. package/dist/server/modules/providers/controllers/providers.controller.d.ts +17 -2
  252. package/dist/server/modules/providers/controllers/providers.controller.js +76 -3
  253. package/dist/server/modules/providers/controllers/providers.controller.js.map +1 -1
  254. package/dist/server/modules/providers/providers.module.js +14 -2
  255. package/dist/server/modules/providers/providers.module.js.map +1 -1
  256. package/dist/server/modules/providers/services/provider-discovery.service.d.ts +17 -0
  257. package/dist/server/modules/providers/services/provider-discovery.service.js +64 -0
  258. package/dist/server/modules/providers/services/provider-discovery.service.js.map +1 -0
  259. package/dist/server/modules/providers/services/provider-project-sync.service.d.ts +27 -0
  260. package/dist/server/modules/providers/services/provider-project-sync.service.js +171 -0
  261. package/dist/server/modules/providers/services/provider-project-sync.service.js.map +1 -0
  262. package/dist/server/modules/registry/controllers/templates.controller.d.ts +153 -0
  263. package/dist/server/modules/registry/controllers/templates.controller.js +56 -0
  264. package/dist/server/modules/registry/controllers/templates.controller.js.map +1 -1
  265. package/dist/server/modules/seeders/seeders/0007_seed_claude_no_flicker_env.d.ts +3 -0
  266. package/dist/server/modules/seeders/seeders/0007_seed_claude_no_flicker_env.js +28 -0
  267. package/dist/server/modules/seeders/seeders/0007_seed_claude_no_flicker_env.js.map +1 -0
  268. package/dist/server/modules/seeders/services/data-seeder.service.js +2 -0
  269. package/dist/server/modules/seeders/services/data-seeder.service.js.map +1 -1
  270. package/dist/server/modules/session-reader/data/pricing.json +242 -21
  271. package/dist/server/modules/sessions/services/sessions-message-pool.service.js +15 -9
  272. package/dist/server/modules/sessions/services/sessions-message-pool.service.js.map +1 -1
  273. package/dist/server/modules/sessions/services/sessions.service.d.ts +1 -0
  274. package/dist/server/modules/sessions/services/sessions.service.js +26 -5
  275. package/dist/server/modules/sessions/services/sessions.service.js.map +1 -1
  276. package/dist/server/modules/sessions/utils/profile-options.js +3 -0
  277. package/dist/server/modules/sessions/utils/profile-options.js.map +1 -1
  278. package/dist/server/modules/sessions/utils/template-renderer.d.ts +6 -0
  279. package/dist/server/modules/sessions/utils/template-renderer.js +15 -10
  280. package/dist/server/modules/sessions/utils/template-renderer.js.map +1 -1
  281. package/dist/server/modules/storage/db/schema.d.ts +440 -0
  282. package/dist/server/modules/storage/db/schema.js +65 -1
  283. package/dist/server/modules/storage/db/schema.js.map +1 -1
  284. package/dist/server/modules/storage/interfaces/storage.interface.d.ts +14 -0
  285. package/dist/server/modules/storage/interfaces/storage.interface.js.map +1 -1
  286. package/dist/server/modules/storage/local/delegates/agent.delegate.js +40 -15
  287. package/dist/server/modules/storage/local/delegates/agent.delegate.js.map +1 -1
  288. package/dist/server/modules/storage/local/delegates/profile-provider-config.delegate.d.ts +13 -0
  289. package/dist/server/modules/storage/local/delegates/profile-provider-config.delegate.js +142 -11
  290. package/dist/server/modules/storage/local/delegates/profile-provider-config.delegate.js.map +1 -1
  291. package/dist/server/modules/storage/local/delegates/project.delegate.js +10 -0
  292. package/dist/server/modules/storage/local/delegates/project.delegate.js.map +1 -1
  293. package/dist/server/modules/storage/local/delegates/provider.delegate.js +38 -10
  294. package/dist/server/modules/storage/local/delegates/provider.delegate.js.map +1 -1
  295. package/dist/server/modules/storage/local/helpers/storage-helpers.d.ts +2 -0
  296. package/dist/server/modules/storage/local/helpers/storage-helpers.js +36 -0
  297. package/dist/server/modules/storage/local/helpers/storage-helpers.js.map +1 -1
  298. package/dist/server/modules/storage/local/local-storage.service.d.ts +2 -1
  299. package/dist/server/modules/storage/local/local-storage.service.js +3 -0
  300. package/dist/server/modules/storage/local/local-storage.service.js.map +1 -1
  301. package/dist/server/modules/storage/models/domain.models.d.ts +62 -0
  302. package/dist/server/modules/subscribers/services/subscriber-executor.service.d.ts +6 -2
  303. package/dist/server/modules/subscribers/services/subscriber-executor.service.js +52 -5
  304. package/dist/server/modules/subscribers/services/subscriber-executor.service.js.map +1 -1
  305. package/dist/server/modules/teams/controllers/teams.controller.d.ts +39 -0
  306. package/dist/server/modules/teams/controllers/teams.controller.js +214 -0
  307. package/dist/server/modules/teams/controllers/teams.controller.js.map +1 -0
  308. package/dist/server/modules/teams/services/teams.service.d.ts +106 -0
  309. package/dist/server/modules/teams/services/teams.service.js +748 -0
  310. package/dist/server/modules/teams/services/teams.service.js.map +1 -0
  311. package/dist/server/modules/teams/storage/teams.store.d.ts +58 -0
  312. package/dist/server/modules/teams/storage/teams.store.js +468 -0
  313. package/dist/server/modules/teams/storage/teams.store.js.map +1 -0
  314. package/dist/server/modules/teams/teams.module.d.ts +2 -0
  315. package/dist/server/modules/teams/teams.module.js +27 -0
  316. package/dist/server/modules/teams/teams.module.js.map +1 -0
  317. package/dist/server/modules/terminal/services/confirmed-delivery.helper.d.ts +2 -0
  318. package/dist/server/modules/terminal/services/confirmed-delivery.helper.js +8 -1
  319. package/dist/server/modules/terminal/services/confirmed-delivery.helper.js.map +1 -1
  320. package/dist/server/templates/3-agents-dev.json +169 -89
  321. package/dist/server/templates/5-agents-dev.json +243 -135
  322. package/dist/server/templates/teams-dev.json +1096 -0
  323. package/dist/server/tsconfig.tsbuildinfo +1 -1
  324. package/dist/server/ui/assets/{ReviewDetailPage-B5Wk-cyO.js → ReviewDetailPage-CEMxN6RQ.js} +1 -1
  325. package/dist/server/ui/assets/{ReviewsPage-SUvvu_uV.js → ReviewsPage-BzMksnGd.js} +1 -1
  326. package/dist/server/ui/assets/index-ChJ1IUMI.css +32 -0
  327. package/dist/server/ui/assets/index-Csagg3g2.js +1027 -0
  328. package/dist/server/ui/assets/{useReviewSubscription-C_dnAb0l.js → useReviewSubscription-B2ejeWE4.js} +1 -1
  329. package/dist/server/ui/index.html +2 -2
  330. package/dist/templates/3-agents-dev.json +169 -89
  331. package/dist/templates/5-agents-dev.json +243 -135
  332. package/dist/templates/teams-dev.json +1096 -0
  333. package/package.json +34 -2
  334. package/dist/server/ui/assets/index-Bl-zkrCF.js +0 -1011
  335. package/dist/server/ui/assets/index-C99ggRaD.css +0 -32
  336. /package/dist/drizzle/{0050_providers_one_million_context.sql → 0052_providers_one_million_context.sql} +0 -0
  337. /package/dist/drizzle/{0051_providers_auto_compact_threshold_1m.sql → 0053_providers_auto_compact_threshold_1m.sql} +0 -0
@@ -0,0 +1,1128 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __metadata = (this && this.__metadata) || function (k, v) {
42
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
+ };
44
+ var CodebaseOverviewAnalyzerService_1;
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.CodebaseOverviewAnalyzerService = void 0;
47
+ const common_1 = require("@nestjs/common");
48
+ const child_process_1 = require("child_process");
49
+ const crypto_1 = require("crypto");
50
+ const util_1 = require("util");
51
+ const fs_1 = require("fs");
52
+ const fs = __importStar(require("fs/promises"));
53
+ const path_1 = require("path");
54
+ const path_matcher_1 = require("../utils/path-matcher");
55
+ const constants_1 = require("../utils/constants");
56
+ const logger_1 = require("../../../common/logging/logger");
57
+ const identity_resolver_service_1 = require("./identity-resolver.service");
58
+ const hotspot_scoring_service_1 = require("./hotspot-scoring.service");
59
+ const district_splitting_service_1 = require("./district-splitting.service");
60
+ const dependency_aggregation_service_1 = require("./dependency-aggregation.service");
61
+ const evidence_query_service_1 = require("./evidence-query.service");
62
+ const language_adapter_registry_service_1 = require("./language-adapter-registry.service");
63
+ const scope_resolver_service_1 = require("./scope-resolver.service");
64
+ const scope_auto_detector_service_1 = require("./scope-auto-detector.service");
65
+ const overview_scope_repository_1 = require("../repositories/overview-scope.repository");
66
+ const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
67
+ const MAX_BUFFER = 10 * 1024 * 1024;
68
+ const MAX_ADAPTER_FILE_SIZE = 256 * 1024;
69
+ const EMPTY_TREE_SHA = '4b825dc642cb6eb9a060e54bf899d15f0a75b9a7';
70
+ const ROOT_REGION_NAME = '(root)';
71
+ const RESOLVE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.mts', '.cts'];
72
+ const logger = (0, logger_1.createLogger)('CodebaseOverviewAnalyzer');
73
+ let CodebaseOverviewAnalyzerService = CodebaseOverviewAnalyzerService_1 = class CodebaseOverviewAnalyzerService {
74
+ constructor(identityResolver, hotspotScoring, districtSplitting, dependencyAggregation, evidenceQuery, adapterRegistry, scopeResolver, scopeAutoDetector, scopeRepository) {
75
+ this.identityResolver = identityResolver;
76
+ this.hotspotScoring = hotspotScoring;
77
+ this.districtSplitting = districtSplitting;
78
+ this.dependencyAggregation = dependencyAggregation;
79
+ this.evidenceQuery = evidenceQuery;
80
+ this.adapterRegistry = adapterRegistry;
81
+ this.scopeResolver = scopeResolver;
82
+ this.scopeAutoDetector = scopeAutoDetector;
83
+ this.scopeRepository = scopeRepository;
84
+ this.identityStore = new Map();
85
+ this.queryStore = new Map();
86
+ }
87
+ async getSnapshot(projectPath, projectId) {
88
+ const capabilities = await this.detectCapabilities(projectPath);
89
+ const userEntries = this.scopeRepository.readUserEntries(projectPath, projectId);
90
+ const preResolvedScope = this.scopeResolver.resolve(userEntries);
91
+ const preExcludedFolders = this.scopeResolver.getExcludedFolders(preResolvedScope);
92
+ const { files, locFallbackStats } = await this.scanFiles(projectPath, capabilities, preExcludedFolders);
93
+ const observedFolders = this.extractObservedFolders(files);
94
+ const autoDetected = this.scopeAutoDetector.detect(observedFolders);
95
+ const resolvedScope = this.scopeResolver.resolve(userEntries, autoDetected);
96
+ const excludedFolders = this.scopeResolver.getExcludedFolders(resolvedScope);
97
+ const generatedFolders = this.scopeResolver.getGeneratedFolders(resolvedScope);
98
+ const scopeConfigHash = (0, crypto_1.createHash)('sha256')
99
+ .update(JSON.stringify(resolvedScope))
100
+ .digest('hex')
101
+ .slice(0, 8);
102
+ const extraExcluded = excludedFolders.filter((f) => !preExcludedFolders.includes(f));
103
+ let filteredFiles = files;
104
+ if (extraExcluded.length > 0) {
105
+ filteredFiles = files.filter((f) => !(0, path_matcher_1.isUnderAnyFolder)(f.path, extraExcluded));
106
+ }
107
+ const segmented = this.segmentFiles(filteredFiles);
108
+ const regions = segmented.regions;
109
+ const locMap = new Map(filteredFiles.map((f) => [f.path, f.loc]));
110
+ const { districts, districtFileMap } = this.districtSplitting.splitOversizedDistricts(segmented.districts, segmented.districtFileMap, locMap, filteredFiles.length);
111
+ const previousState = this.identityStore.get(projectPath) ?? null;
112
+ const commitSha = capabilities.isGitRepo ? await this.getCurrentCommitSha(projectPath) : null;
113
+ const gitRenames = capabilities.isGitRepo
114
+ ? await this.detectGitRenames(projectPath, previousState?.commitSha ?? null)
115
+ : [];
116
+ const fileIds = this.identityResolver.resolveFileIds(filteredFiles.map((f) => f.path), previousState, gitRenames);
117
+ const regionIds = this.identityResolver.resolveRegionIds(regions.map((r) => r.name), previousState);
118
+ const districtCandidates = [...districtFileMap.entries()].map(([key, paths]) => ({
119
+ key,
120
+ memberFileIds: paths.map((p) => fileIds.get(p)),
121
+ }));
122
+ const districtIds = this.identityResolver.resolveDistrictIds(districtCandidates, previousState);
123
+ for (const region of regions) {
124
+ region.id = regionIds.get(region.name);
125
+ }
126
+ for (const district of districts) {
127
+ const districtKey = district.id.slice('district:'.length);
128
+ const resolvedId = districtIds.get(districtKey);
129
+ if (resolvedId)
130
+ district.id = resolvedId;
131
+ const regionName = districtKey.split('/')[0];
132
+ district.regionId = regionIds.get(regionName);
133
+ }
134
+ this.storeIdentityState(projectPath, commitSha, fileIds, regionIds, districtIds, districtFileMap);
135
+ const [churn1d, churn7d, churn30d, dailyChurnFileMap] = capabilities.isGitRepo
136
+ ? await Promise.all([
137
+ this.getChurnMap(projectPath, 1),
138
+ this.getChurnMap(projectPath, 7),
139
+ this.getChurnMap(projectPath, 30),
140
+ this.getDailyChurnMap(projectPath, 14),
141
+ ])
142
+ : [
143
+ new Map(),
144
+ new Map(),
145
+ new Map(),
146
+ null,
147
+ ];
148
+ const fileByPath = new Map(filteredFiles.map((f) => [f.path, f]));
149
+ const districtFilesById = new Map();
150
+ for (const [districtKey, filePaths] of districtFileMap) {
151
+ const districtId = districtIds.get(districtKey);
152
+ if (!districtId)
153
+ continue;
154
+ const enriched = filePaths.map((p) => {
155
+ const file = fileByPath.get(p);
156
+ return {
157
+ path: p,
158
+ loc: file?.loc ?? 0,
159
+ lastModified: file?.lastModified ?? Date.now(),
160
+ churn1d: churn1d.get(p) ?? 0,
161
+ churn7d: churn7d.get(p) ?? 0,
162
+ churn30d: churn30d.get(p) ?? 0,
163
+ isTest: (0, hotspot_scoring_service_1.isTestFile)(p),
164
+ };
165
+ });
166
+ districtFilesById.set(districtId, enriched);
167
+ }
168
+ const analysisDistrictFilesById = new Map();
169
+ for (const [districtId, dFiles] of districtFilesById) {
170
+ const filtered = dFiles.filter((f) => !(0, path_matcher_1.isUnderAnyFolder)(f.path, generatedFolders));
171
+ analysisDistrictFilesById.set(districtId, filtered);
172
+ }
173
+ const analysisDistricts = districts.filter((d) => {
174
+ const files = analysisDistrictFilesById.get(d.id);
175
+ return Array.isArray(files) && files.length > 0;
176
+ });
177
+ this.hotspotScoring.enrichDistrictMetrics(districts, analysisDistrictFilesById);
178
+ const [windowedAuthor7d, windowedAuthor30d] = capabilities.isGitRepo
179
+ ? await Promise.all([
180
+ this.getWindowedAuthorMap(projectPath, 7),
181
+ this.getWindowedAuthorMap(projectPath, 30),
182
+ ])
183
+ : [null, null];
184
+ const activity = this.hotspotScoring.computeActivitySummaries(districts, districtFilesById, dailyChurnFileMap, windowedAuthor7d, windowedAuthor30d);
185
+ const globalContributors = this.buildGlobalContributors(districts, districtFilesById, windowedAuthor7d, windowedAuthor30d);
186
+ const allFilePaths = new Set();
187
+ for (const dFiles of districtFilesById.values()) {
188
+ for (const f of dFiles)
189
+ allFilePaths.add(f.path);
190
+ }
191
+ const adapterResult = await this.analyzeWithAdapters(projectPath, allFilePaths);
192
+ this.hotspotScoring.enrichDistrictAdapterMetrics(districts, analysisDistrictFilesById, adapterResult.enrichments);
193
+ const fileAuthors = capabilities.isGitRepo
194
+ ? await this.getFileAuthorMap(projectPath)
195
+ : new Map();
196
+ this.hotspotScoring.enrichDistrictOwnership(districts, districtFilesById, fileAuthors);
197
+ const fileToDistrictId = new Map();
198
+ for (const [districtId, dFiles] of districtFilesById) {
199
+ for (const f of dFiles) {
200
+ fileToDistrictId.set(f.path, districtId);
201
+ }
202
+ }
203
+ const dependencies = this.dependencyAggregation.aggregateDistrictDependencies(adapterResult.fileEdges, fileToDistrictId);
204
+ this.dependencyAggregation.enrichDistrictWeights(districts, dependencies);
205
+ const blastRadiusMap = this.dependencyAggregation.computeBlastRadius(districts, dependencies);
206
+ const hotspots = this.hotspotScoring.rankHotspots(analysisDistricts, analysisDistrictFilesById);
207
+ const hasImportData = adapterResult.fileEdges.length > 0;
208
+ const warnings = this.buildWarnings(capabilities, hasImportData, adapterResult.adapterFileCount, locFallbackStats);
209
+ const hasUnmeasuredCoverage = districts.some((d) => {
210
+ const dFiles = analysisDistrictFilesById.get(d.id) ?? [];
211
+ return dFiles.some((f) => !f.isTest) && d.testCoverageRate === null;
212
+ });
213
+ if (hasUnmeasuredCoverage) {
214
+ warnings.push({
215
+ code: 'coverage_unmeasured',
216
+ message: 'Some districts contain source files but no supported language adapter could measure test coverage.',
217
+ });
218
+ }
219
+ if (capabilities.isGitRepo && dailyChurnFileMap === null) {
220
+ warnings.push({
221
+ code: 'daily_churn_unavailable',
222
+ message: 'Daily churn data could not be retrieved. The per-day change heatmap will be unavailable.',
223
+ });
224
+ }
225
+ if (capabilities.isGitRepo && (windowedAuthor7d === null || windowedAuthor30d === null)) {
226
+ warnings.push({
227
+ code: 'windowed_authors_unavailable',
228
+ message: 'Windowed author data could not be retrieved. Contributor rankings will be incomplete.',
229
+ });
230
+ }
231
+ const excludedAuthorCount = this.computeExcludedAuthorCount(fileAuthors, excludedFolders, globalContributors);
232
+ const metrics = this.computeMetrics(filteredFiles, regions, districts, capabilities, warnings, excludedAuthorCount, scopeConfigHash);
233
+ const activityByDistrictId = new Map(activity.map((a) => [a.targetId, a]));
234
+ for (const district of districts) {
235
+ if (district.primaryAuthorName == null) {
236
+ district.primaryAuthorRecentlyActive = false;
237
+ continue;
238
+ }
239
+ const act = activityByDistrictId.get(district.id);
240
+ const recentNames = new Set(act?.recentContributors30d.map((c) => c.authorName) ?? []);
241
+ district.primaryAuthorRecentlyActive = recentNames.has(district.primaryAuthorName);
242
+ }
243
+ const regionById = new Map(regions.map((r) => [r.id, r]));
244
+ const signals = districts.map((district) => {
245
+ const dFiles = districtFilesById.get(district.id) ?? [];
246
+ const extCounts = {};
247
+ let sourceFileCount = 0;
248
+ let supportFileCount = 0;
249
+ for (const f of dFiles) {
250
+ const ext = (0, path_1.extname)(f.path) || '(no ext)';
251
+ extCounts[ext] = (extCounts[ext] ?? 0) + 1;
252
+ if (f.isTest) {
253
+ supportFileCount++;
254
+ }
255
+ else {
256
+ sourceFileCount++;
257
+ }
258
+ }
259
+ return {
260
+ districtId: district.id,
261
+ name: district.name,
262
+ path: district.path,
263
+ regionId: district.regionId,
264
+ regionName: regionById.get(district.regionId)?.name ?? '',
265
+ files: district.totalFiles,
266
+ sourceFileCount,
267
+ supportFileCount,
268
+ hasSourceFiles: sourceFileCount > 0,
269
+ loc: district.totalLOC,
270
+ churn7d: district.churn7d,
271
+ churn30d: district.churn30d,
272
+ testCoverageRate: district.testCoverageRate,
273
+ sourceCoverageMeasured: district.testCoverageRate !== null,
274
+ complexityAvg: district.complexityAvg,
275
+ inboundWeight: district.inboundWeight,
276
+ outboundWeight: district.outboundWeight,
277
+ blastRadius: district.blastRadius,
278
+ couplingScore: district.couplingScore,
279
+ ownershipHHI: district.ownershipConcentration,
280
+ ownershipMeasured: district.ownershipConcentration !== null,
281
+ primaryAuthorName: district.primaryAuthorName,
282
+ primaryAuthorShare: district.primaryAuthorShare,
283
+ primaryAuthorRecentlyActive: district.primaryAuthorRecentlyActive,
284
+ fileTypeBreakdown: { kind: 'extension', counts: extCounts },
285
+ };
286
+ });
287
+ const snapshot = {
288
+ snapshotId: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
289
+ projectKey: projectPath,
290
+ name: projectPath.split(path_1.sep).pop() || projectPath,
291
+ regions,
292
+ districts,
293
+ dependencies,
294
+ hotspots,
295
+ activity,
296
+ metrics,
297
+ signals,
298
+ globalContributors,
299
+ };
300
+ this.queryStore.set(projectPath, {
301
+ snapshot,
302
+ districtFilesById,
303
+ fileIds,
304
+ allFilePaths,
305
+ fileEnrichments: adapterResult.enrichments,
306
+ blastRadiusMap,
307
+ fileEdges: adapterResult.fileEdges,
308
+ isGitRepo: capabilities.isGitRepo,
309
+ });
310
+ return snapshot;
311
+ }
312
+ async getTargetDetails(projectPath, targetId) {
313
+ const state = this.queryStore.get(projectPath);
314
+ if (!state)
315
+ return null;
316
+ const district = state.snapshot.districts.find((d) => d.id === targetId);
317
+ if (!district)
318
+ return null;
319
+ const filePaths = state.districtFilesById.get(targetId)?.map((f) => f.path) ?? [];
320
+ const recentCommits = state.isGitRepo
321
+ ? await this.getRecentCommits(projectPath, filePaths)
322
+ : [];
323
+ const topAuthors = state.isGitRepo ? await this.getTopAuthors(projectPath, filePaths) : [];
324
+ const blastRadius = state.blastRadiusMap.get(targetId);
325
+ return this.evidenceQuery.buildTargetDetail(district, state.snapshot.hotspots, state.snapshot.activity, state.snapshot.dependencies, recentCommits, topAuthors, blastRadius);
326
+ }
327
+ getDependencyPairDetails(projectPath, fromDistrictId, toDistrictId) {
328
+ const state = this.queryStore.get(projectPath);
329
+ if (!state)
330
+ return null;
331
+ const fromDistrict = state.snapshot.districts.find((d) => d.id === fromDistrictId);
332
+ const toDistrict = state.snapshot.districts.find((d) => d.id === toDistrictId);
333
+ if (!fromDistrict || !toDistrict)
334
+ return null;
335
+ const exemplars = this.buildExemplarEdges(fromDistrictId, toDistrictId, state.fileEdges, state.districtFilesById, state.fileIds);
336
+ return this.evidenceQuery.buildDependencyPairDetail(fromDistrictId, toDistrictId, state.snapshot.dependencies, fromDistrict.name, toDistrict.name, exemplars);
337
+ }
338
+ listDistrictFiles(projectPath, districtId, cursor) {
339
+ const state = this.queryStore.get(projectPath);
340
+ if (!state)
341
+ return null;
342
+ const files = state.districtFilesById.get(districtId);
343
+ if (!files)
344
+ return null;
345
+ return this.evidenceQuery.buildDistrictFilePage(districtId, files, state.fileIds, state.allFilePaths, cursor, state.fileEnrichments);
346
+ }
347
+ async execGit(projectPath, args, options) {
348
+ try {
349
+ const { stdout } = await execFileAsync('git', args, {
350
+ cwd: projectPath,
351
+ maxBuffer: MAX_BUFFER,
352
+ });
353
+ return stdout;
354
+ }
355
+ catch (err) {
356
+ if (options?.allowNonZero && isExecError(err) && err.stdout != null) {
357
+ return err.stdout;
358
+ }
359
+ throw err;
360
+ }
361
+ }
362
+ async getRecentCommits(projectPath, filePaths, limit = 10) {
363
+ if (filePaths.length === 0)
364
+ return [];
365
+ try {
366
+ const out = await this.execGit(projectPath, [
367
+ 'log',
368
+ `--format=%H%n%s%n%at`,
369
+ `-n`,
370
+ String(limit),
371
+ '--',
372
+ ...filePaths,
373
+ ]);
374
+ const lines = out.split('\n').filter((l) => l.length > 0);
375
+ const commits = [];
376
+ for (let i = 0; i + 2 < lines.length; i += 3) {
377
+ const ts = parseInt(lines[i + 2], 10);
378
+ commits.push({
379
+ sha: lines[i],
380
+ message: lines[i + 1],
381
+ timestamp: isNaN(ts) ? 0 : ts,
382
+ });
383
+ }
384
+ return commits;
385
+ }
386
+ catch {
387
+ return [];
388
+ }
389
+ }
390
+ async getTopAuthors(projectPath, filePaths, limit = 5) {
391
+ if (filePaths.length === 0)
392
+ return [];
393
+ try {
394
+ const out = await this.execGit(projectPath, ['shortlog', '-sn', 'HEAD', '--', ...filePaths]);
395
+ const entries = [];
396
+ for (const line of out.split('\n')) {
397
+ const match = line.match(/^\s*(\d+)\s+(.+)$/);
398
+ if (match) {
399
+ entries.push({ author: match[2].trim(), count: parseInt(match[1], 10) });
400
+ }
401
+ }
402
+ const total = entries.reduce((sum, e) => sum + e.count, 0);
403
+ if (total === 0)
404
+ return [];
405
+ return entries.slice(0, limit).map((e) => ({
406
+ author: e.author,
407
+ share: Math.round((e.count / total) * 100) / 100,
408
+ }));
409
+ }
410
+ catch {
411
+ return [];
412
+ }
413
+ }
414
+ buildExemplarEdges(fromDistrictId, toDistrictId, fileEdges, districtFilesById, fileIds, limit = 10) {
415
+ const fromFiles = new Set((districtFilesById.get(fromDistrictId) ?? []).map((f) => f.path));
416
+ const toFiles = new Set((districtFilesById.get(toDistrictId) ?? []).map((f) => f.path));
417
+ const edgeMap = new Map();
418
+ for (const edge of fileEdges) {
419
+ if (!fromFiles.has(edge.fromPath) || !toFiles.has(edge.toPath))
420
+ continue;
421
+ const key = `${edge.fromPath}\0${edge.toPath}`;
422
+ const existing = edgeMap.get(key);
423
+ if (existing) {
424
+ existing.weight += edge.weight ?? 1;
425
+ }
426
+ else {
427
+ edgeMap.set(key, {
428
+ fromPath: edge.fromPath,
429
+ toPath: edge.toPath,
430
+ weight: edge.weight ?? 1,
431
+ });
432
+ }
433
+ }
434
+ return [...edgeMap.values()]
435
+ .sort((a, b) => b.weight - a.weight)
436
+ .slice(0, limit)
437
+ .map((e) => ({
438
+ fromFileId: fileIds.get(e.fromPath) ?? e.fromPath,
439
+ toFileId: fileIds.get(e.toPath) ?? e.toPath,
440
+ fromPath: e.fromPath,
441
+ toPath: e.toPath,
442
+ weight: e.weight,
443
+ }));
444
+ }
445
+ async getFileAuthorMap(projectPath) {
446
+ const result = new Map();
447
+ try {
448
+ const out = await this.execGit(projectPath, ['log', '--format=%aN', '--name-only', 'HEAD']);
449
+ let currentAuthor = null;
450
+ let seenFiles = false;
451
+ for (const line of out.split('\n')) {
452
+ const trimmed = line.trim();
453
+ if (!trimmed) {
454
+ if (seenFiles) {
455
+ currentAuthor = null;
456
+ seenFiles = false;
457
+ }
458
+ continue;
459
+ }
460
+ if (currentAuthor === null) {
461
+ currentAuthor = trimmed;
462
+ continue;
463
+ }
464
+ seenFiles = true;
465
+ let authorMap = result.get(trimmed);
466
+ if (!authorMap) {
467
+ authorMap = new Map();
468
+ result.set(trimmed, authorMap);
469
+ }
470
+ authorMap.set(currentAuthor, (authorMap.get(currentAuthor) ?? 0) + 1);
471
+ }
472
+ }
473
+ catch {
474
+ }
475
+ return result;
476
+ }
477
+ async detectCapabilities(projectPath) {
478
+ const gitDir = (0, path_1.join)(projectPath, '.git');
479
+ const isGitRepo = (0, fs_1.existsSync)(gitDir);
480
+ if (!isGitRepo) {
481
+ return {
482
+ isGitRepo: false,
483
+ isShallow: false,
484
+ totalCommits: 0,
485
+ oldestCommitTimestamp: null,
486
+ gitHistoryDays: null,
487
+ };
488
+ }
489
+ let isShallow = false;
490
+ try {
491
+ const out = await this.execGit(projectPath, ['rev-parse', '--is-shallow-repository']);
492
+ isShallow = out.trim() === 'true';
493
+ }
494
+ catch {
495
+ }
496
+ let totalCommits = 0;
497
+ let oldestCommitTimestamp = null;
498
+ try {
499
+ const countOut = await this.execGit(projectPath, ['rev-list', '--count', 'HEAD']);
500
+ totalCommits = parseInt(countOut.trim(), 10) || 0;
501
+ if (totalCommits > 0) {
502
+ const oldestOut = await this.execGit(projectPath, [
503
+ 'log',
504
+ '--format=%at',
505
+ '--reverse',
506
+ '-1',
507
+ ]);
508
+ const ts = parseInt(oldestOut.trim(), 10);
509
+ if (!isNaN(ts)) {
510
+ oldestCommitTimestamp = ts;
511
+ }
512
+ }
513
+ }
514
+ catch {
515
+ }
516
+ const gitHistoryDays = oldestCommitTimestamp != null
517
+ ? Math.floor((Date.now() / 1000 - oldestCommitTimestamp) / 86400)
518
+ : null;
519
+ return {
520
+ isGitRepo,
521
+ isShallow,
522
+ totalCommits,
523
+ oldestCommitTimestamp,
524
+ gitHistoryDays,
525
+ };
526
+ }
527
+ extractObservedFolders(files) {
528
+ const seen = new Set();
529
+ for (const file of files) {
530
+ const segments = file.path.split(/[/\\]/);
531
+ const limit = Math.min(segments.length - 1, constants_1.MAX_FOLDER_DEPTH);
532
+ for (let d = 1; d <= limit; d++) {
533
+ seen.add(segments.slice(0, d).join('/'));
534
+ }
535
+ }
536
+ return [...seen];
537
+ }
538
+ async scanFiles(projectPath, capabilities, excludedFolders = []) {
539
+ let filePaths;
540
+ if (capabilities.isGitRepo) {
541
+ filePaths = await this.listGitFiles(projectPath);
542
+ }
543
+ else {
544
+ filePaths = await this.listFsFiles(projectPath, projectPath, 10, new Set(excludedFolders));
545
+ }
546
+ if (excludedFolders.length > 0) {
547
+ filePaths = filePaths.filter((p) => !(0, path_matcher_1.isUnderAnyFolder)(p, excludedFolders));
548
+ }
549
+ let locMap;
550
+ let locFallbackStats;
551
+ if (capabilities.isGitRepo) {
552
+ locMap = await this.getLocMap(projectPath);
553
+ if (locMap.size === 0 && filePaths.length > 0) {
554
+ const fallback = await this.computeFallbackLineCounts(projectPath, filePaths);
555
+ locMap = fallback.map;
556
+ locFallbackStats = {
557
+ counted: fallback.counted,
558
+ skipped: fallback.skipped,
559
+ eligible: fallback.eligible,
560
+ };
561
+ }
562
+ }
563
+ else {
564
+ locMap = new Map();
565
+ }
566
+ const files = [];
567
+ for (const filePath of filePaths) {
568
+ const absPath = (0, path_1.join)(projectPath, filePath);
569
+ let lastModified = Date.now();
570
+ try {
571
+ const stat = await fs.stat(absPath);
572
+ lastModified = stat.mtimeMs;
573
+ }
574
+ catch {
575
+ continue;
576
+ }
577
+ const loc = locMap.get(filePath) ?? 0;
578
+ files.push({ path: filePath, loc, lastModified });
579
+ }
580
+ return { files, locFallbackStats };
581
+ }
582
+ async listGitFiles(projectPath) {
583
+ try {
584
+ const out = await this.execGit(projectPath, ['ls-files', '-z']);
585
+ return out.split('\0').filter((p) => p.length > 0);
586
+ }
587
+ catch (err) {
588
+ logger.warn({ err }, 'Failed to list git files, falling back to fs scan');
589
+ return this.listFsFiles(projectPath, projectPath);
590
+ }
591
+ }
592
+ async listFsFiles(rootPath, currentPath, maxDepth = 10, excludedFolders = new Set()) {
593
+ if (maxDepth <= 0)
594
+ return [];
595
+ const result = [];
596
+ let entries;
597
+ try {
598
+ entries = await fs.readdir(currentPath, { withFileTypes: true, encoding: 'utf-8' });
599
+ }
600
+ catch {
601
+ return result;
602
+ }
603
+ for (const entry of entries) {
604
+ if (entry.isDirectory()) {
605
+ const relDir = (0, path_1.join)((0, path_1.relative)(rootPath, currentPath), entry.name);
606
+ if ((0, path_matcher_1.isUnderAnyFolder)(relDir, excludedFolders))
607
+ continue;
608
+ }
609
+ const fullPath = (0, path_1.join)(currentPath, entry.name);
610
+ if (entry.isFile()) {
611
+ result.push((0, path_1.relative)(rootPath, fullPath));
612
+ }
613
+ else if (entry.isDirectory()) {
614
+ const sub = await this.listFsFiles(rootPath, fullPath, maxDepth - 1, excludedFolders);
615
+ result.push(...sub);
616
+ }
617
+ }
618
+ return result;
619
+ }
620
+ async getLocMap(projectPath) {
621
+ const map = new Map();
622
+ try {
623
+ const out = await this.execGit(projectPath, ['diff', '--numstat', EMPTY_TREE_SHA, 'HEAD'], {
624
+ allowNonZero: true,
625
+ });
626
+ for (const line of out.split('\n')) {
627
+ if (!line)
628
+ continue;
629
+ const parts = line.split('\t');
630
+ if (parts.length < 3)
631
+ continue;
632
+ const added = parseInt(parts[0], 10);
633
+ const filePath = parts[2];
634
+ if (!isNaN(added) && filePath) {
635
+ map.set(filePath, added);
636
+ }
637
+ }
638
+ }
639
+ catch {
640
+ }
641
+ return map;
642
+ }
643
+ async computeFallbackLineCounts(projectPath, filePaths) {
644
+ const map = new Map();
645
+ const eligible = filePaths.length;
646
+ let skipped = 0;
647
+ const CONCURRENCY = 16;
648
+ for (let i = 0; i < filePaths.length; i += CONCURRENCY) {
649
+ const batch = filePaths.slice(i, i + CONCURRENCY);
650
+ const results = await Promise.all(batch.map(async (filePath) => {
651
+ try {
652
+ const absPath = (0, path_1.join)(projectPath, filePath);
653
+ const stat = await fs.stat(absPath);
654
+ if (stat.size > MAX_ADAPTER_FILE_SIZE)
655
+ return null;
656
+ const buf = await fs.readFile(absPath);
657
+ const checkLen = Math.min(buf.length, 8192);
658
+ for (let j = 0; j < checkLen; j++) {
659
+ if (buf[j] <= 0x08)
660
+ return null;
661
+ }
662
+ let lines = 0;
663
+ for (let j = 0; j < buf.length; j++) {
664
+ if (buf[j] === 0x0a)
665
+ lines++;
666
+ }
667
+ if (buf.length > 0 && buf[buf.length - 1] !== 0x0a)
668
+ lines++;
669
+ return { path: filePath, loc: lines };
670
+ }
671
+ catch {
672
+ return null;
673
+ }
674
+ }));
675
+ for (const r of results) {
676
+ if (r === null) {
677
+ skipped++;
678
+ }
679
+ else {
680
+ map.set(r.path, r.loc);
681
+ }
682
+ }
683
+ }
684
+ return { map, counted: eligible - skipped, skipped, eligible };
685
+ }
686
+ async getChurnMap(projectPath, sinceDays) {
687
+ const map = new Map();
688
+ try {
689
+ const out = await this.execGit(projectPath, [
690
+ 'log',
691
+ `--since=${sinceDays} days ago`,
692
+ '--name-only',
693
+ '--format=',
694
+ 'HEAD',
695
+ ]);
696
+ for (const line of out.split('\n')) {
697
+ const trimmed = line.trim();
698
+ if (!trimmed)
699
+ continue;
700
+ map.set(trimmed, (map.get(trimmed) ?? 0) + 1);
701
+ }
702
+ }
703
+ catch {
704
+ }
705
+ return map;
706
+ }
707
+ async getDailyChurnMap(projectPath, days) {
708
+ try {
709
+ const out = await this.execGit(projectPath, [
710
+ 'log',
711
+ `--since=${days} days ago`,
712
+ '--format=COMMIT %H%n%aI%n%aN',
713
+ '--name-only',
714
+ 'HEAD',
715
+ ]);
716
+ if (!out.trim())
717
+ return null;
718
+ const map = new Map();
719
+ const lines = out.split('\n');
720
+ let i = 0;
721
+ while (i < lines.length) {
722
+ const line = lines[i];
723
+ if (line.startsWith('COMMIT ')) {
724
+ const aI = (lines[i + 1] ?? '').trim();
725
+ const dateStr = aI.slice(0, 10);
726
+ i += 3;
727
+ while (i < lines.length && lines[i]?.trim() === '')
728
+ i++;
729
+ while (i < lines.length && lines[i]?.trim() !== '' && !lines[i].startsWith('COMMIT ')) {
730
+ const filePath = lines[i].trim();
731
+ if (filePath) {
732
+ let dateMap = map.get(filePath);
733
+ if (!dateMap) {
734
+ dateMap = new Map();
735
+ map.set(filePath, dateMap);
736
+ }
737
+ dateMap.set(dateStr, (dateMap.get(dateStr) ?? 0) + 1);
738
+ }
739
+ i++;
740
+ }
741
+ }
742
+ else {
743
+ i++;
744
+ }
745
+ }
746
+ return map;
747
+ }
748
+ catch {
749
+ return null;
750
+ }
751
+ }
752
+ async getWindowedAuthorMap(projectPath, days) {
753
+ try {
754
+ const out = await this.execGit(projectPath, [
755
+ 'log',
756
+ `--since=${days} days ago`,
757
+ '--format=COMMIT %H%n%aI%n%aN',
758
+ '--name-only',
759
+ 'HEAD',
760
+ ]);
761
+ if (!out.trim())
762
+ return null;
763
+ const map = new Map();
764
+ const lines = out.split('\n');
765
+ let i = 0;
766
+ while (i < lines.length) {
767
+ const line = lines[i];
768
+ if (line.startsWith('COMMIT ')) {
769
+ i += 2;
770
+ const authorName = (lines[i] ?? '').trim();
771
+ i++;
772
+ while (i < lines.length && lines[i]?.trim() === '')
773
+ i++;
774
+ while (i < lines.length && lines[i]?.trim() !== '' && !lines[i].startsWith('COMMIT ')) {
775
+ const filePath = lines[i].trim();
776
+ if (filePath) {
777
+ let authorMap = map.get(filePath);
778
+ if (!authorMap) {
779
+ authorMap = new Map();
780
+ map.set(filePath, authorMap);
781
+ }
782
+ authorMap.set(authorName, (authorMap.get(authorName) ?? 0) + 1);
783
+ }
784
+ i++;
785
+ }
786
+ }
787
+ else {
788
+ i++;
789
+ }
790
+ }
791
+ return map;
792
+ }
793
+ catch {
794
+ return null;
795
+ }
796
+ }
797
+ buildGlobalContributors(districts, districtFiles, windowedAuthor7d, windowedAuthor30d) {
798
+ if (!windowedAuthor7d && !windowedAuthor30d)
799
+ return [];
800
+ const author7dTotals = new Map();
801
+ const author30dTotals = new Map();
802
+ for (const district of districts) {
803
+ const files = districtFiles.get(district.id) ?? [];
804
+ for (const f of files) {
805
+ if (windowedAuthor7d) {
806
+ const fileAuthors = windowedAuthor7d.get(f.path);
807
+ if (fileAuthors) {
808
+ for (const [author, count] of fileAuthors) {
809
+ author7dTotals.set(author, (author7dTotals.get(author) ?? 0) + count);
810
+ }
811
+ }
812
+ }
813
+ if (windowedAuthor30d) {
814
+ const fileAuthors = windowedAuthor30d.get(f.path);
815
+ if (fileAuthors) {
816
+ for (const [author, count] of fileAuthors) {
817
+ author30dTotals.set(author, (author30dTotals.get(author) ?? 0) + count);
818
+ }
819
+ }
820
+ }
821
+ }
822
+ }
823
+ const allAuthors = new Set([...author7dTotals.keys(), ...author30dTotals.keys()]);
824
+ const result = [];
825
+ for (const author of allAuthors) {
826
+ result.push({
827
+ authorName: author,
828
+ commitCount7d: author7dTotals.get(author) ?? 0,
829
+ commitCount30d: author30dTotals.get(author) ?? 0,
830
+ });
831
+ }
832
+ return result
833
+ .sort((a, b) => b.commitCount30d - a.commitCount30d)
834
+ .slice(0, CodebaseOverviewAnalyzerService_1.GLOBAL_CONTRIBUTORS_CAP);
835
+ }
836
+ computeExcludedAuthorCount(fileAuthors, excludedFolders, globalContributors) {
837
+ if (excludedFolders.length === 0)
838
+ return 0;
839
+ const authorsInExcluded = new Set();
840
+ const authorsInNonExcluded = new Set();
841
+ for (const [filePath, authorMap] of fileAuthors) {
842
+ const isExcluded = (0, path_matcher_1.isUnderAnyFolder)(filePath, excludedFolders);
843
+ for (const author of authorMap.keys()) {
844
+ if (isExcluded) {
845
+ authorsInExcluded.add(author);
846
+ }
847
+ else {
848
+ authorsInNonExcluded.add(author);
849
+ }
850
+ }
851
+ }
852
+ const globalNames = new Set(globalContributors.map((c) => c.authorName));
853
+ let count = 0;
854
+ for (const author of authorsInExcluded) {
855
+ if (!authorsInNonExcluded.has(author) && !globalNames.has(author)) {
856
+ count++;
857
+ }
858
+ }
859
+ return count;
860
+ }
861
+ segmentFiles(files) {
862
+ const regionMap = new Map();
863
+ for (const file of files) {
864
+ const segments = file.path.split(/[/\\]/);
865
+ const regionName = segments.length > 1 ? segments[0] : ROOT_REGION_NAME;
866
+ const districtName = segments.length > 2 ? segments[1] : ROOT_REGION_NAME;
867
+ if (!regionMap.has(regionName)) {
868
+ regionMap.set(regionName, { files: [], districtMap: new Map() });
869
+ }
870
+ const region = regionMap.get(regionName);
871
+ region.files.push(file);
872
+ const districtKey = `${regionName}/${districtName}`;
873
+ if (!region.districtMap.has(districtKey)) {
874
+ region.districtMap.set(districtKey, []);
875
+ }
876
+ region.districtMap.get(districtKey).push(file);
877
+ }
878
+ const regions = [];
879
+ const districts = [];
880
+ const districtFileMap = new Map();
881
+ for (const [regionName, regionData] of regionMap) {
882
+ const regionId = `region:${regionName}`;
883
+ const totalFiles = regionData.files.length;
884
+ const totalLOC = regionData.files.reduce((sum, f) => sum + f.loc, 0);
885
+ const regionPath = regionName === ROOT_REGION_NAME ? '.' : regionName;
886
+ regions.push({
887
+ id: regionId,
888
+ path: regionPath,
889
+ name: regionName,
890
+ totalFiles,
891
+ totalLOC,
892
+ });
893
+ for (const [districtKey, districtFiles] of regionData.districtMap) {
894
+ const districtName = districtKey.split('/')[1] || districtKey;
895
+ const districtId = `district:${districtKey}`;
896
+ const dTotalFiles = districtFiles.length;
897
+ const dTotalLOC = districtFiles.reduce((sum, f) => sum + f.loc, 0);
898
+ const districtPath = regionName === ROOT_REGION_NAME
899
+ ? '.'
900
+ : districtName === ROOT_REGION_NAME
901
+ ? regionName
902
+ : `${regionName}/${districtName}`;
903
+ districts.push({
904
+ id: districtId,
905
+ regionId,
906
+ path: districtPath,
907
+ name: districtName,
908
+ totalFiles: dTotalFiles,
909
+ totalLOC: dTotalLOC,
910
+ churn7d: 0,
911
+ churn30d: 0,
912
+ inboundWeight: 0,
913
+ outboundWeight: 0,
914
+ couplingScore: 0,
915
+ testFileCount: 0,
916
+ testFileRatio: null,
917
+ role: 'mixed',
918
+ complexityAvg: null,
919
+ ownershipConcentration: null,
920
+ testCoverageRate: null,
921
+ blastRadius: 0,
922
+ primaryAuthorName: null,
923
+ primaryAuthorShare: null,
924
+ primaryAuthorRecentlyActive: false,
925
+ });
926
+ districtFileMap.set(districtKey, districtFiles.map((f) => f.path));
927
+ }
928
+ }
929
+ regions.sort((a, b) => b.totalLOC - a.totalLOC);
930
+ districts.sort((a, b) => b.totalLOC - a.totalLOC);
931
+ return { regions, districts, districtFileMap };
932
+ }
933
+ async getCurrentCommitSha(projectPath) {
934
+ try {
935
+ const out = await this.execGit(projectPath, ['rev-parse', 'HEAD']);
936
+ return out.trim() || null;
937
+ }
938
+ catch {
939
+ return null;
940
+ }
941
+ }
942
+ async detectGitRenames(projectPath, previousCommitSha) {
943
+ if (!previousCommitSha)
944
+ return [];
945
+ try {
946
+ const out = await this.execGit(projectPath, ['diff', '--name-status', '-M', previousCommitSha, 'HEAD'], { allowNonZero: true });
947
+ const renames = [];
948
+ for (const line of out.split('\n')) {
949
+ if (!line.startsWith('R'))
950
+ continue;
951
+ const parts = line.split('\t');
952
+ if (parts.length < 3)
953
+ continue;
954
+ const similarity = parseInt(parts[0].slice(1), 10);
955
+ renames.push({
956
+ oldPath: parts[1],
957
+ newPath: parts[2],
958
+ similarity: isNaN(similarity) ? 100 : similarity,
959
+ });
960
+ }
961
+ return renames;
962
+ }
963
+ catch {
964
+ return [];
965
+ }
966
+ }
967
+ storeIdentityState(projectPath, commitSha, fileIds, regionIds, districtIds, districtFileMap) {
968
+ const districts = new Map();
969
+ for (const [key, id] of districtIds) {
970
+ const filePaths = districtFileMap.get(key) ?? [];
971
+ const memberFileIds = new Set(filePaths.map((p) => fileIds.get(p)).filter(Boolean));
972
+ districts.set(key, { id, memberFileIds });
973
+ }
974
+ this.identityStore.set(projectPath, {
975
+ commitSha,
976
+ files: new Map(fileIds),
977
+ districts,
978
+ regions: new Map(regionIds),
979
+ });
980
+ }
981
+ buildWarnings(capabilities, hasImportData, adapterFileCount, locFallbackStats) {
982
+ const warnings = [];
983
+ if (!capabilities.isGitRepo) {
984
+ warnings.push({
985
+ code: 'shallow_git_history',
986
+ message: 'No git repository detected. Churn and staleness signals are unavailable.',
987
+ });
988
+ }
989
+ else if (capabilities.isShallow) {
990
+ warnings.push({
991
+ code: 'shallow_git_history',
992
+ message: 'Shallow git history detected. Churn and staleness signals may be incomplete.',
993
+ });
994
+ }
995
+ if (locFallbackStats) {
996
+ warnings.push({
997
+ code: 'loc_unavailable',
998
+ message: `LOC computed via file-read fallback (${locFallbackStats.counted} files counted, ${locFallbackStats.skipped} skipped).`,
999
+ data: locFallbackStats,
1000
+ });
1001
+ }
1002
+ if (!hasImportData) {
1003
+ if (adapterFileCount === 0) {
1004
+ warnings.push({
1005
+ code: 'missing_dependency_data',
1006
+ message: 'No supported source files found for import analysis. Coupling scores are empty.',
1007
+ });
1008
+ }
1009
+ else {
1010
+ warnings.push({
1011
+ code: 'missing_dependency_data',
1012
+ message: 'Import analysis found no cross-district dependencies. Coupling scores are empty.',
1013
+ });
1014
+ }
1015
+ }
1016
+ return warnings;
1017
+ }
1018
+ async analyzeWithAdapters(projectPath, allFilePaths) {
1019
+ const enrichments = new Map();
1020
+ const fileEdges = [];
1021
+ let adapterFileCount = 0;
1022
+ const adapterFiles = [];
1023
+ for (const filePath of allFilePaths) {
1024
+ if (this.adapterRegistry.getAdapter(filePath)) {
1025
+ adapterFiles.push(filePath);
1026
+ }
1027
+ }
1028
+ adapterFileCount = adapterFiles.length;
1029
+ if (adapterFiles.length === 0) {
1030
+ return { fileEdges, enrichments, adapterFileCount };
1031
+ }
1032
+ const BATCH_SIZE = 100;
1033
+ for (let i = 0; i < adapterFiles.length; i += BATCH_SIZE) {
1034
+ const batch = adapterFiles.slice(i, i + BATCH_SIZE);
1035
+ const results = await Promise.allSettled(batch.map(async (filePath) => {
1036
+ const absPath = (0, path_1.join)(projectPath, filePath);
1037
+ const stat = await fs.stat(absPath);
1038
+ if (stat.size > MAX_ADAPTER_FILE_SIZE)
1039
+ return null;
1040
+ const content = await fs.readFile(absPath, 'utf-8');
1041
+ return { filePath, content };
1042
+ }));
1043
+ for (const result of results) {
1044
+ if (result.status !== 'fulfilled' || !result.value)
1045
+ continue;
1046
+ const { filePath, content } = result.value;
1047
+ const role = this.adapterRegistry.classifyRole(filePath, content);
1048
+ const symbolCount = this.adapterRegistry.countSymbols(filePath, content);
1049
+ const complexity = this.adapterRegistry.computeComplexity(filePath, content);
1050
+ const testPair = this.adapterRegistry.detectTestPair(filePath, allFilePaths);
1051
+ enrichments.set(filePath, { role, symbolCount, complexity, testPair });
1052
+ const specifiers = this.adapterRegistry.extractImports(filePath, content);
1053
+ if (specifiers) {
1054
+ const resolvedTargets = new Set();
1055
+ for (const specifier of specifiers) {
1056
+ const resolved = this.adapterRegistry.resolveImport(filePath, specifier, allFilePaths) ??
1057
+ resolveImportSpecifier(specifier, filePath, allFilePaths);
1058
+ if (resolved) {
1059
+ resolvedTargets.add(resolved);
1060
+ }
1061
+ }
1062
+ for (const toPath of resolvedTargets) {
1063
+ fileEdges.push({ fromPath: filePath, toPath });
1064
+ }
1065
+ }
1066
+ }
1067
+ }
1068
+ logger.info({ adapterFiles: adapterFileCount, enriched: enrichments.size, edges: fileEdges.length }, 'Language adapter analysis complete');
1069
+ return { fileEdges, enrichments, adapterFileCount };
1070
+ }
1071
+ computeMetrics(files, regions, districts, capabilities, warnings, excludedAuthorCount, scopeConfigHash) {
1072
+ return {
1073
+ totalRegions: regions.length,
1074
+ totalDistricts: districts.length,
1075
+ totalFiles: files.length,
1076
+ gitHistoryDaysAvailable: capabilities.gitHistoryDays,
1077
+ shallowHistoryDetected: capabilities.isShallow || !capabilities.isGitRepo,
1078
+ dependencyCoverage: null,
1079
+ warnings,
1080
+ excludedAuthorCount,
1081
+ scopeConfigHash,
1082
+ };
1083
+ }
1084
+ };
1085
+ exports.CodebaseOverviewAnalyzerService = CodebaseOverviewAnalyzerService;
1086
+ CodebaseOverviewAnalyzerService.GLOBAL_CONTRIBUTORS_CAP = 20;
1087
+ exports.CodebaseOverviewAnalyzerService = CodebaseOverviewAnalyzerService = CodebaseOverviewAnalyzerService_1 = __decorate([
1088
+ (0, common_1.Injectable)(),
1089
+ __metadata("design:paramtypes", [identity_resolver_service_1.IdentityResolverService,
1090
+ hotspot_scoring_service_1.HotspotScoringService,
1091
+ district_splitting_service_1.DistrictSplittingService,
1092
+ dependency_aggregation_service_1.DependencyAggregationService,
1093
+ evidence_query_service_1.EvidenceQueryService,
1094
+ language_adapter_registry_service_1.LanguageAdapterRegistryService,
1095
+ scope_resolver_service_1.ScopeResolverService,
1096
+ scope_auto_detector_service_1.ScopeAutoDetectorService,
1097
+ overview_scope_repository_1.OverviewScopeRepository])
1098
+ ], CodebaseOverviewAnalyzerService);
1099
+ function isExecError(err) {
1100
+ return err instanceof Error && 'stdout' in err;
1101
+ }
1102
+ function resolveImportSpecifier(specifier, importerPath, allPaths) {
1103
+ if (!specifier.startsWith('.'))
1104
+ return null;
1105
+ const importerDir = (0, path_1.dirname)(importerPath);
1106
+ const resolved = (0, path_1.normalize)((0, path_1.join)(importerDir, specifier));
1107
+ if (allPaths.has(resolved))
1108
+ return resolved;
1109
+ const existingExt = (0, path_1.extname)(resolved);
1110
+ if (existingExt) {
1111
+ const withoutExt = resolved.slice(0, -existingExt.length);
1112
+ for (const ext of RESOLVE_EXTENSIONS) {
1113
+ if (allPaths.has(withoutExt + ext))
1114
+ return withoutExt + ext;
1115
+ }
1116
+ }
1117
+ for (const ext of RESOLVE_EXTENSIONS) {
1118
+ if (allPaths.has(resolved + ext))
1119
+ return resolved + ext;
1120
+ }
1121
+ for (const ext of RESOLVE_EXTENSIONS) {
1122
+ const indexPath = (0, path_1.join)(resolved, 'index' + ext);
1123
+ if (allPaths.has(indexPath))
1124
+ return indexPath;
1125
+ }
1126
+ return null;
1127
+ }
1128
+ //# sourceMappingURL=codebase-overview-analyzer.service.js.map