sdl-mcp 0.11.2 → 0.11.4

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 (372) hide show
  1. package/README.md +22 -14
  2. package/config/sdlmcp.config.example.json +32 -5
  3. package/config/sdlmcp.config.json +3 -2
  4. package/config/sdlmcp.config.schema.json +61 -8
  5. package/dist/.tsbuildinfo +1 -1
  6. package/dist/agent/context-engine.d.ts.map +1 -1
  7. package/dist/agent/context-engine.js +71 -13
  8. package/dist/agent/context-engine.js.map +1 -1
  9. package/dist/agent/context-ranking.d.ts.map +1 -1
  10. package/dist/agent/context-ranking.js +17 -4
  11. package/dist/agent/context-ranking.js.map +1 -1
  12. package/dist/agent/context-seeding.d.ts +6 -4
  13. package/dist/agent/context-seeding.d.ts.map +1 -1
  14. package/dist/agent/context-seeding.js +306 -60
  15. package/dist/agent/context-seeding.js.map +1 -1
  16. package/dist/agent/executor.d.ts +18 -5
  17. package/dist/agent/executor.d.ts.map +1 -1
  18. package/dist/agent/executor.js +347 -42
  19. package/dist/agent/executor.js.map +1 -1
  20. package/dist/agent/identifier-extraction.d.ts.map +1 -1
  21. package/dist/agent/identifier-extraction.js +6 -1
  22. package/dist/agent/identifier-extraction.js.map +1 -1
  23. package/dist/agent/types.d.ts +11 -2
  24. package/dist/agent/types.d.ts.map +1 -1
  25. package/dist/cli/argParsing.d.ts.map +1 -1
  26. package/dist/cli/argParsing.js +12 -0
  27. package/dist/cli/argParsing.js.map +1 -1
  28. package/dist/cli/commands/doctor.js +47 -6
  29. package/dist/cli/commands/doctor.js.map +1 -1
  30. package/dist/cli/commands/index.d.ts.map +1 -1
  31. package/dist/cli/commands/index.js +33 -15
  32. package/dist/cli/commands/index.js.map +1 -1
  33. package/dist/cli/commands/init.d.ts.map +1 -1
  34. package/dist/cli/commands/init.js +484 -132
  35. package/dist/cli/commands/init.js.map +1 -1
  36. package/dist/cli/commands/serve.d.ts.map +1 -1
  37. package/dist/cli/commands/serve.js +40 -21
  38. package/dist/cli/commands/serve.js.map +1 -1
  39. package/dist/cli/commands/tool-actions.d.ts +1 -1
  40. package/dist/cli/commands/tool-actions.d.ts.map +1 -1
  41. package/dist/cli/commands/tool-actions.js +199 -1
  42. package/dist/cli/commands/tool-actions.js.map +1 -1
  43. package/dist/cli/commands/tool-dispatch.d.ts +3 -0
  44. package/dist/cli/commands/tool-dispatch.d.ts.map +1 -1
  45. package/dist/cli/commands/tool-dispatch.js +163 -24
  46. package/dist/cli/commands/tool-dispatch.js.map +1 -1
  47. package/dist/cli/commands/tool-output.js +3 -3
  48. package/dist/cli/commands/tool-output.js.map +1 -1
  49. package/dist/cli/index.js +5 -2
  50. package/dist/cli/index.js.map +1 -1
  51. package/dist/cli/transport/http.d.ts +18 -6
  52. package/dist/cli/transport/http.d.ts.map +1 -1
  53. package/dist/cli/transport/http.js +428 -193
  54. package/dist/cli/transport/http.js.map +1 -1
  55. package/dist/cli/types.d.ts +1 -0
  56. package/dist/cli/types.d.ts.map +1 -1
  57. package/dist/code-mode/action-catalog.d.ts +2 -2
  58. package/dist/code-mode/action-catalog.d.ts.map +1 -1
  59. package/dist/code-mode/action-catalog.js +215 -118
  60. package/dist/code-mode/action-catalog.js.map +1 -1
  61. package/dist/code-mode/descriptions.d.ts.map +1 -1
  62. package/dist/code-mode/descriptions.js +4 -1
  63. package/dist/code-mode/descriptions.js.map +1 -1
  64. package/dist/code-mode/index.d.ts +13 -0
  65. package/dist/code-mode/index.d.ts.map +1 -1
  66. package/dist/code-mode/index.js +214 -152
  67. package/dist/code-mode/index.js.map +1 -1
  68. package/dist/code-mode/manual-generator.d.ts.map +1 -1
  69. package/dist/code-mode/manual-generator.js +25 -31
  70. package/dist/code-mode/manual-generator.js.map +1 -1
  71. package/dist/code-mode/ref-resolver.d.ts +1 -0
  72. package/dist/code-mode/ref-resolver.d.ts.map +1 -1
  73. package/dist/code-mode/ref-resolver.js +31 -4
  74. package/dist/code-mode/ref-resolver.js.map +1 -1
  75. package/dist/code-mode/transforms.d.ts.map +1 -1
  76. package/dist/code-mode/transforms.js +7 -1
  77. package/dist/code-mode/transforms.js.map +1 -1
  78. package/dist/code-mode/types.d.ts +3 -0
  79. package/dist/code-mode/types.d.ts.map +1 -1
  80. package/dist/code-mode/types.js +2 -0
  81. package/dist/code-mode/types.js.map +1 -1
  82. package/dist/code-mode/workflow-executor.d.ts.map +1 -1
  83. package/dist/code-mode/workflow-executor.js +82 -9
  84. package/dist/code-mode/workflow-executor.js.map +1 -1
  85. package/dist/code-mode/workflow-parser.d.ts +1 -0
  86. package/dist/code-mode/workflow-parser.d.ts.map +1 -1
  87. package/dist/code-mode/workflow-parser.js +17 -5
  88. package/dist/code-mode/workflow-parser.js.map +1 -1
  89. package/dist/code-mode/workflow-truncation.d.ts.map +1 -1
  90. package/dist/code-mode/workflow-truncation.js +44 -4
  91. package/dist/code-mode/workflow-truncation.js.map +1 -1
  92. package/dist/config/admin-api.d.ts +67 -0
  93. package/dist/config/admin-api.d.ts.map +1 -0
  94. package/dist/config/admin-api.js +762 -0
  95. package/dist/config/admin-api.js.map +1 -0
  96. package/dist/config/admin-metadata.d.ts +46 -0
  97. package/dist/config/admin-metadata.d.ts.map +1 -0
  98. package/dist/config/admin-metadata.js +140 -0
  99. package/dist/config/admin-metadata.js.map +1 -0
  100. package/dist/config/configPath.d.ts.map +1 -1
  101. package/dist/config/configPath.js +4 -13
  102. package/dist/config/configPath.js.map +1 -1
  103. package/dist/config/constants.d.ts +11 -4
  104. package/dist/config/constants.d.ts.map +1 -1
  105. package/dist/config/constants.js +11 -4
  106. package/dist/config/constants.js.map +1 -1
  107. package/dist/config/semantic-embedding-model-plan.d.ts +13 -0
  108. package/dist/config/semantic-embedding-model-plan.d.ts.map +1 -0
  109. package/dist/config/semantic-embedding-model-plan.js +82 -0
  110. package/dist/config/semantic-embedding-model-plan.js.map +1 -0
  111. package/dist/config/types.d.ts +55 -5
  112. package/dist/config/types.d.ts.map +1 -1
  113. package/dist/config/types.js +35 -15
  114. package/dist/config/types.js.map +1 -1
  115. package/dist/db/ladybug-core.d.ts +16 -5
  116. package/dist/db/ladybug-core.d.ts.map +1 -1
  117. package/dist/db/ladybug-core.js +201 -30
  118. package/dist/db/ladybug-core.js.map +1 -1
  119. package/dist/db/ladybug-derived-state.d.ts +2 -1
  120. package/dist/db/ladybug-derived-state.d.ts.map +1 -1
  121. package/dist/db/ladybug-derived-state.js +6 -1
  122. package/dist/db/ladybug-derived-state.js.map +1 -1
  123. package/dist/db/ladybug-prefetch-outcomes.d.ts +48 -0
  124. package/dist/db/ladybug-prefetch-outcomes.d.ts.map +1 -0
  125. package/dist/db/ladybug-prefetch-outcomes.js +109 -0
  126. package/dist/db/ladybug-prefetch-outcomes.js.map +1 -0
  127. package/dist/db/ladybug-processes.d.ts +1 -0
  128. package/dist/db/ladybug-processes.d.ts.map +1 -1
  129. package/dist/db/ladybug-processes.js +17 -0
  130. package/dist/db/ladybug-processes.js.map +1 -1
  131. package/dist/db/ladybug-queries.d.ts +1 -0
  132. package/dist/db/ladybug-queries.d.ts.map +1 -1
  133. package/dist/db/ladybug-queries.js +2 -0
  134. package/dist/db/ladybug-queries.js.map +1 -1
  135. package/dist/db/ladybug-repos.d.ts.map +1 -1
  136. package/dist/db/ladybug-repos.js +5 -0
  137. package/dist/db/ladybug-repos.js.map +1 -1
  138. package/dist/db/ladybug-schema.d.ts.map +1 -1
  139. package/dist/db/ladybug-schema.js +47 -17
  140. package/dist/db/ladybug-schema.js.map +1 -1
  141. package/dist/db/ladybug.d.ts.map +1 -1
  142. package/dist/db/ladybug.js +24 -19
  143. package/dist/db/ladybug.js.map +1 -1
  144. package/dist/db/migrations/index.d.ts.map +1 -1
  145. package/dist/db/migrations/index.js +2 -0
  146. package/dist/db/migrations/index.js.map +1 -1
  147. package/dist/db/migrations/m014-add-packed-stats.js +3 -15
  148. package/dist/db/migrations/m014-add-packed-stats.js.map +1 -1
  149. package/dist/db/migrations/m015-backfill-packed-stats.js +3 -15
  150. package/dist/db/migrations/m015-backfill-packed-stats.js.map +1 -1
  151. package/dist/db/migrations/m019-add-prefetch-outcomes.d.ts +5 -0
  152. package/dist/db/migrations/m019-add-prefetch-outcomes.d.ts.map +1 -0
  153. package/dist/db/migrations/m019-add-prefetch-outcomes.js +74 -0
  154. package/dist/db/migrations/m019-add-prefetch-outcomes.js.map +1 -0
  155. package/dist/gateway/descriptions.js +2 -2
  156. package/dist/gateway/descriptions.js.map +1 -1
  157. package/dist/gateway/router.d.ts.map +1 -1
  158. package/dist/gateway/router.js +6 -1
  159. package/dist/gateway/router.js.map +1 -1
  160. package/dist/gateway/schemas.d.ts +104 -3
  161. package/dist/gateway/schemas.d.ts.map +1 -1
  162. package/dist/gateway/schemas.js +179 -44
  163. package/dist/gateway/schemas.js.map +1 -1
  164. package/dist/graph/index.d.ts +3 -1
  165. package/dist/graph/index.d.ts.map +1 -1
  166. package/dist/graph/index.js +2 -1
  167. package/dist/graph/index.js.map +1 -1
  168. package/dist/graph/overview.js +6 -6
  169. package/dist/graph/overview.js.map +1 -1
  170. package/dist/graph/prefetch-model.d.ts +1 -0
  171. package/dist/graph/prefetch-model.d.ts.map +1 -1
  172. package/dist/graph/prefetch-model.js.map +1 -1
  173. package/dist/graph/prefetch-outcomes.d.ts +93 -0
  174. package/dist/graph/prefetch-outcomes.d.ts.map +1 -0
  175. package/dist/graph/prefetch-outcomes.js +429 -0
  176. package/dist/graph/prefetch-outcomes.js.map +1 -0
  177. package/dist/graph/prefetch.d.ts +33 -6
  178. package/dist/graph/prefetch.d.ts.map +1 -1
  179. package/dist/graph/prefetch.js +440 -61
  180. package/dist/graph/prefetch.js.map +1 -1
  181. package/dist/graph/slice/edge-projector.d.ts.map +1 -1
  182. package/dist/graph/slice/edge-projector.js +17 -4
  183. package/dist/graph/slice/edge-projector.js.map +1 -1
  184. package/dist/indexer/derived-refresh-queue.d.ts +9 -1
  185. package/dist/indexer/derived-refresh-queue.d.ts.map +1 -1
  186. package/dist/indexer/derived-refresh-queue.js +253 -19
  187. package/dist/indexer/derived-refresh-queue.js.map +1 -1
  188. package/dist/indexer/finalize-derived-state.d.ts.map +1 -1
  189. package/dist/indexer/finalize-derived-state.js +43 -72
  190. package/dist/indexer/finalize-derived-state.js.map +1 -1
  191. package/dist/indexer/metrics-updater.d.ts.map +1 -1
  192. package/dist/indexer/metrics-updater.js +14 -35
  193. package/dist/indexer/metrics-updater.js.map +1 -1
  194. package/dist/live-index/checkpoint-service.d.ts.map +1 -1
  195. package/dist/live-index/checkpoint-service.js +21 -1
  196. package/dist/live-index/checkpoint-service.js.map +1 -1
  197. package/dist/live-index/types.d.ts +1 -0
  198. package/dist/live-index/types.d.ts.map +1 -1
  199. package/dist/main.js +25 -5
  200. package/dist/main.js.map +1 -1
  201. package/dist/mcp/context-response-projection.d.ts +13 -7
  202. package/dist/mcp/context-response-projection.d.ts.map +1 -1
  203. package/dist/mcp/context-response-projection.js +147 -11
  204. package/dist/mcp/context-response-projection.js.map +1 -1
  205. package/dist/mcp/dispatch-limiter.d.ts +17 -2
  206. package/dist/mcp/dispatch-limiter.d.ts.map +1 -1
  207. package/dist/mcp/dispatch-limiter.js +81 -3
  208. package/dist/mcp/dispatch-limiter.js.map +1 -1
  209. package/dist/mcp/server-instructions.d.ts +2 -0
  210. package/dist/mcp/server-instructions.d.ts.map +1 -0
  211. package/dist/mcp/server-instructions.js +14 -0
  212. package/dist/mcp/server-instructions.js.map +1 -0
  213. package/dist/mcp/telemetry.d.ts +19 -0
  214. package/dist/mcp/telemetry.d.ts.map +1 -1
  215. package/dist/mcp/telemetry.js +9 -0
  216. package/dist/mcp/telemetry.js.map +1 -1
  217. package/dist/mcp/timing-diagnostics.d.ts +20 -0
  218. package/dist/mcp/timing-diagnostics.d.ts.map +1 -0
  219. package/dist/mcp/timing-diagnostics.js +82 -0
  220. package/dist/mcp/timing-diagnostics.js.map +1 -0
  221. package/dist/mcp/tool-call-formatter.d.ts +2 -2
  222. package/dist/mcp/tool-call-formatter.d.ts.map +1 -1
  223. package/dist/mcp/tool-call-formatter.js +387 -16
  224. package/dist/mcp/tool-call-formatter.js.map +1 -1
  225. package/dist/mcp/tools/buffer.d.ts.map +1 -1
  226. package/dist/mcp/tools/buffer.js +2 -1
  227. package/dist/mcp/tools/buffer.js.map +1 -1
  228. package/dist/mcp/tools/code.d.ts +2 -2
  229. package/dist/mcp/tools/code.d.ts.map +1 -1
  230. package/dist/mcp/tools/code.js +18 -6
  231. package/dist/mcp/tools/code.js.map +1 -1
  232. package/dist/mcp/tools/context.d.ts +19 -0
  233. package/dist/mcp/tools/context.d.ts.map +1 -1
  234. package/dist/mcp/tools/context.js +224 -6
  235. package/dist/mcp/tools/context.js.map +1 -1
  236. package/dist/mcp/tools/delta.d.ts +2 -1
  237. package/dist/mcp/tools/delta.d.ts.map +1 -1
  238. package/dist/mcp/tools/delta.js +4 -3
  239. package/dist/mcp/tools/delta.js.map +1 -1
  240. package/dist/mcp/tools/file-gateway.d.ts +134 -10
  241. package/dist/mcp/tools/file-gateway.d.ts.map +1 -1
  242. package/dist/mcp/tools/file-gateway.js +241 -25
  243. package/dist/mcp/tools/file-gateway.js.map +1 -1
  244. package/dist/mcp/tools/file-read.d.ts.map +1 -1
  245. package/dist/mcp/tools/file-read.js +64 -17
  246. package/dist/mcp/tools/file-read.js.map +1 -1
  247. package/dist/mcp/tools/file-write.d.ts.map +1 -1
  248. package/dist/mcp/tools/file-write.js +52 -2
  249. package/dist/mcp/tools/file-write.js.map +1 -1
  250. package/dist/mcp/tools/prRisk.d.ts +28 -9
  251. package/dist/mcp/tools/prRisk.d.ts.map +1 -1
  252. package/dist/mcp/tools/prRisk.js +90 -21
  253. package/dist/mcp/tools/prRisk.js.map +1 -1
  254. package/dist/mcp/tools/repo.d.ts.map +1 -1
  255. package/dist/mcp/tools/repo.js +153 -32
  256. package/dist/mcp/tools/repo.js.map +1 -1
  257. package/dist/mcp/tools/runtime.d.ts.map +1 -1
  258. package/dist/mcp/tools/runtime.js +116 -20
  259. package/dist/mcp/tools/runtime.js.map +1 -1
  260. package/dist/mcp/tools/scip.d.ts.map +1 -1
  261. package/dist/mcp/tools/scip.js +11 -1
  262. package/dist/mcp/tools/scip.js.map +1 -1
  263. package/dist/mcp/tools/search-edit/index.d.ts.map +1 -1
  264. package/dist/mcp/tools/search-edit/index.js +9 -0
  265. package/dist/mcp/tools/search-edit/index.js.map +1 -1
  266. package/dist/mcp/tools/search-edit/plan-store.d.ts +37 -1
  267. package/dist/mcp/tools/search-edit/plan-store.d.ts.map +1 -1
  268. package/dist/mcp/tools/search-edit/plan-store.js +2 -1
  269. package/dist/mcp/tools/search-edit/plan-store.js.map +1 -1
  270. package/dist/mcp/tools/search-edit/planner.d.ts +20 -5
  271. package/dist/mcp/tools/search-edit/planner.d.ts.map +1 -1
  272. package/dist/mcp/tools/search-edit/planner.js +326 -1
  273. package/dist/mcp/tools/search-edit/planner.js.map +1 -1
  274. package/dist/mcp/tools/slice.d.ts.map +1 -1
  275. package/dist/mcp/tools/slice.js +3 -2
  276. package/dist/mcp/tools/slice.js.map +1 -1
  277. package/dist/mcp/tools/symbol-edit/ast.d.ts +28 -0
  278. package/dist/mcp/tools/symbol-edit/ast.d.ts.map +1 -0
  279. package/dist/mcp/tools/symbol-edit/ast.js +513 -0
  280. package/dist/mcp/tools/symbol-edit/ast.js.map +1 -0
  281. package/dist/mcp/tools/symbol-edit/index.d.ts +12 -0
  282. package/dist/mcp/tools/symbol-edit/index.d.ts.map +1 -0
  283. package/dist/mcp/tools/symbol-edit/index.js +633 -0
  284. package/dist/mcp/tools/symbol-edit/index.js.map +1 -0
  285. package/dist/mcp/tools/symbol.d.ts +3 -2
  286. package/dist/mcp/tools/symbol.d.ts.map +1 -1
  287. package/dist/mcp/tools/symbol.js +13 -11
  288. package/dist/mcp/tools/symbol.js.map +1 -1
  289. package/dist/mcp/tools/tool-descriptors.d.ts.map +1 -1
  290. package/dist/mcp/tools/tool-descriptors.js +8 -1
  291. package/dist/mcp/tools/tool-descriptors.js.map +1 -1
  292. package/dist/mcp/tools/usage.d.ts.map +1 -1
  293. package/dist/mcp/tools/usage.js +19 -6
  294. package/dist/mcp/tools/usage.js.map +1 -1
  295. package/dist/mcp/tools.d.ts +332 -18
  296. package/dist/mcp/tools.d.ts.map +1 -1
  297. package/dist/mcp/tools.js +210 -11
  298. package/dist/mcp/tools.js.map +1 -1
  299. package/dist/observability/aggregator.d.ts +20 -1
  300. package/dist/observability/aggregator.d.ts.map +1 -1
  301. package/dist/observability/aggregator.js +121 -12
  302. package/dist/observability/aggregator.js.map +1 -1
  303. package/dist/observability/event-tap.d.ts +11 -0
  304. package/dist/observability/event-tap.d.ts.map +1 -1
  305. package/dist/observability/event-tap.js.map +1 -1
  306. package/dist/observability/service.d.ts +7 -0
  307. package/dist/observability/service.d.ts.map +1 -1
  308. package/dist/observability/service.js +29 -1
  309. package/dist/observability/service.js.map +1 -1
  310. package/dist/observability/types.d.ts +38 -0
  311. package/dist/observability/types.d.ts.map +1 -1
  312. package/dist/observability/types.js.map +1 -1
  313. package/dist/retrieval/index-lifecycle.js +2 -2
  314. package/dist/retrieval/index-lifecycle.js.map +1 -1
  315. package/dist/retrieval/orchestrator.d.ts +1 -0
  316. package/dist/retrieval/orchestrator.d.ts.map +1 -1
  317. package/dist/retrieval/orchestrator.js +79 -8
  318. package/dist/retrieval/orchestrator.js.map +1 -1
  319. package/dist/retrieval/types.d.ts +4 -0
  320. package/dist/retrieval/types.d.ts.map +1 -1
  321. package/dist/runtime/deferred-work-state.d.ts +28 -0
  322. package/dist/runtime/deferred-work-state.d.ts.map +1 -0
  323. package/dist/runtime/deferred-work-state.js +70 -0
  324. package/dist/runtime/deferred-work-state.js.map +1 -0
  325. package/dist/runtime/executor.d.ts.map +1 -1
  326. package/dist/runtime/executor.js +15 -1
  327. package/dist/runtime/executor.js.map +1 -1
  328. package/dist/runtime/runtimes.d.ts +1 -0
  329. package/dist/runtime/runtimes.d.ts.map +1 -1
  330. package/dist/runtime/runtimes.js +7 -0
  331. package/dist/runtime/runtimes.js.map +1 -1
  332. package/dist/runtime/types.d.ts +4 -0
  333. package/dist/runtime/types.d.ts.map +1 -1
  334. package/dist/server.d.ts +20 -0
  335. package/dist/server.d.ts.map +1 -1
  336. package/dist/server.js +237 -69
  337. package/dist/server.js.map +1 -1
  338. package/dist/startup/derived-state-recovery.d.ts +23 -0
  339. package/dist/startup/derived-state-recovery.d.ts.map +1 -0
  340. package/dist/startup/derived-state-recovery.js +74 -0
  341. package/dist/startup/derived-state-recovery.js.map +1 -0
  342. package/dist/startup/prefetch-startup.d.ts +3 -0
  343. package/dist/startup/prefetch-startup.d.ts.map +1 -0
  344. package/dist/startup/prefetch-startup.js +21 -0
  345. package/dist/startup/prefetch-startup.js.map +1 -0
  346. package/dist/ui/admin-shell.css +58 -0
  347. package/dist/ui/config.css +130 -0
  348. package/dist/ui/config.d.ts +3 -0
  349. package/dist/ui/config.d.ts.map +1 -0
  350. package/dist/ui/config.html +96 -0
  351. package/dist/ui/config.js +1050 -0
  352. package/dist/ui/config.js.map +1 -0
  353. package/dist/ui/graph.css +108 -0
  354. package/dist/ui/graph.html +52 -0
  355. package/dist/ui/graph.js +213 -181
  356. package/dist/ui/observability.css +1336 -0
  357. package/dist/ui/observability.html +374 -0
  358. package/dist/ui/observability.js +869 -703
  359. package/dist/ui/observability.js.map +1 -1
  360. package/dist/util/concurrency.d.ts +16 -0
  361. package/dist/util/concurrency.d.ts.map +1 -1
  362. package/dist/util/concurrency.js +14 -1
  363. package/dist/util/concurrency.js.map +1 -1
  364. package/dist/util/shutdown.d.ts +2 -2
  365. package/dist/util/shutdown.d.ts.map +1 -1
  366. package/dist/util/shutdown.js +15 -2
  367. package/dist/util/shutdown.js.map +1 -1
  368. package/package.json +3 -3
  369. package/templates/AGENTS.md.template +7 -1
  370. package/templates/CLAUDE.md.template +7 -1
  371. package/templates/CODEX.md.template +7 -1
  372. package/templates/SDL.md +243 -227
@@ -1 +1 @@
1
- {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/agent/executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAoBV,MAAM,EACN,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,QAAQ,EACT,MAAM,YAAY,CAAC;AAcpB,OAAO,KAAK,EACV,iBAAiB,EACjB,kBAAkB,EAClB,UAAU,EACX,MAAM,oBAAoB,CAAC;AAO5B,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,EAC3B,MAAM,4BAA4B,CAAC;AAEpC,MAAM,MAAM,aAAa,GAAG,CAC1B,OAAO,EAAE,iBAAiB,EAC1B,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,UAAU,CAAA;CAAE,KACnD,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAEjC;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,aAuBlC,CAAC;AA0CF;;;GAGG;AACH,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,GAC3B,CAAC;AAEF,qBAAa,QAAQ;IACnB,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,SAAS,CAAK;IAEtB,OAAO,CAAC,eAAe,CAA0C;IACjE,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,WAAW,CAAkD;IACrE,OAAO,CAAC,SAAS,CAAqB;gBAE1B,aAAa,CAAC,EAAE,aAAa;IAczC,OAAO,CAAC,OAAO;IAOT,OAAO,CACX,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,QAAQ,EAAE,EACjB,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC;QACT,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,QAAQ,EAAE,QAAQ,EAAE,CAAC;QACrB,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC;IAgGF,OAAO,CAAC,qBAAqB;YAYf,WAAW;IA0CzB;;;OAGG;YACW,kBAAkB;IAyDhC;;;OAGG;YACW,uBAAuB;IAqBrC;;;OAGG;YACW,gBAAgB;YAyBhB,eAAe;YAsNf,mBAAmB;YA+FnB,kBAAkB;YAsElB,cAAc;IAuG5B;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAkBlC,OAAO,CAAC,gBAAgB;IAIxB;;;;OAIG;IACH,UAAU,IAAI,gBAAgB;IAI9B,iBAAiB,IAAI,MAAM,GAAG,SAAS;IAgBvC,KAAK,IAAI,IAAI;CAkBd"}
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/agent/executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAoBV,MAAM,EACN,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,QAAQ,EACR,oBAAoB,EACrB,MAAM,YAAY,CAAC;AASpB,OAAO,KAAK,SAAS,MAAM,0BAA0B,CAAC;AAMtD,OAAO,KAAK,EACV,iBAAiB,EACjB,kBAAkB,EAClB,UAAU,EACX,MAAM,oBAAoB,CAAC;AAO5B,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,EAC3B,MAAM,4BAA4B,CAAC;AAEpC,MAAM,MAAM,aAAa,GAAG,CAC1B,OAAO,EAAE,iBAAiB,EAC1B,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,UAAU,CAAA;CAAE,KACnD,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAEjC,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,OAAO,SAAS,EACd,mBAAmB,GACnB,oBAAoB,GACpB,kBAAkB,GAClB,kBAAkB,GAClB,mBAAmB,GACnB,sBAAsB,GACtB,iBAAiB,GACjB,eAAe,CAClB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,aAuBlC,CAAC;AA2CF;;;GAGG;AACH,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,GAC3B,CAAC;AAEF,qBAAa,QAAQ;IACnB,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,SAAS,CAAK;IAEtB,OAAO,CAAC,eAAe,CAA0C;IACjE,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,WAAW,CAAkD;IACrE,OAAO,CAAC,SAAS,CAAoB;IAErC,OAAO,CAAC,SAAS,CAAqB;gBAGpC,aAAa,CAAC,EAAE,aAAa,EAC7B,SAAS,GAAE,iBAA6B;IAgB1C,OAAO,CAAC,OAAO;IAOT,OAAO,CACX,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,QAAQ,EAAE,EACjB,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,GAAE,oBAAoB,EAAO,GAC1C,OAAO,CAAC;QACT,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,QAAQ,EAAE,QAAQ,EAAE,CAAC;QACrB,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC;IAgGF,OAAO,CAAC,qBAAqB;YAYf,WAAW;IA2CzB;;;OAGG;YACW,kBAAkB;IAwDhC;;;;;;OAMG;YACW,uBAAuB;IA0KrC;;;OAGG;YACW,gBAAgB;IA6C9B,OAAO,CAAC,uBAAuB;YAuDjB,yBAAyB;IA0DvC,OAAO,CAAC,sBAAsB;YAmBhB,eAAe;YA+Of,mBAAmB;YAuHnB,kBAAkB;YA2FlB,cAAc;IAuG5B;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAkBlC,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,0BAA0B;IAsBlC,OAAO,CAAC,6BAA6B;IAOrC,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,gBAAgB;IAIxB;;;;OAIG;IACH,UAAU,IAAI,gBAAgB;IAI9B,iBAAiB,IAAI,MAAM,GAAG,SAAS;IAgBvC,KAAK,IAAI,IAAI;CAkBd"}
@@ -60,6 +60,7 @@ const MAX_HOTPATH_SYMBOLS = 5;
60
60
  const MAX_RAW_SYMBOLS = 3;
61
61
  const MAX_SEARCH_FALLBACK = 10;
62
62
  const MAX_ESCALATIONS = 2;
63
+ const GENERIC_FILE_BASENAMES = new Set(["engine", "index", "types"]);
63
64
  /** Map rung types to action type strings for error reporting. */
64
65
  const RUNG_TO_ACTION_TYPE = {
65
66
  card: "getCard",
@@ -90,10 +91,12 @@ export class Executor {
90
91
  policyDecisions = new Map();
91
92
  gateEvaluator;
92
93
  connPromise = null;
94
+ dbQueries;
93
95
  cardCache = new Set();
94
- constructor(gateEvaluator) {
96
+ constructor(gateEvaluator, dbQueries = ladybugDb) {
95
97
  this.evidenceCapture = new EvidenceCapture();
96
98
  this.gateEvaluator = gateEvaluator ?? defaultGateEvaluator;
99
+ this.dbQueries = dbQueries;
97
100
  this.metrics = {
98
101
  totalDurationMs: 0,
99
102
  totalTokens: 0,
@@ -109,14 +112,14 @@ export class Executor {
109
112
  }
110
113
  return this.connPromise;
111
114
  }
112
- async execute(task, rungs, context) {
115
+ async execute(task, rungs, context, seedCandidates = []) {
113
116
  this.startTime = Date.now();
114
117
  const mutableRungs = [...rungs];
115
118
  let escalationCount = 0;
116
119
  for (let i = 0; i < mutableRungs.length; i++) {
117
120
  const rung = mutableRungs[i];
118
121
  const evidenceBefore = this.evidenceCapture.getAllEvidence().length;
119
- await this.executeRung(task, rung, context);
122
+ await this.executeRung(task, rung, context, seedCandidates);
120
123
  // Track tokens: use actual evidence-based count when available,
121
124
  // fall back to static estimates otherwise
122
125
  const rungEvidence = this.evidenceCapture.getAllEvidence();
@@ -191,17 +194,17 @@ export class Executor {
191
194
  const next = RUNG_ESCALATION_ORDER[currentIndex + 1];
192
195
  return existingRungs.includes(next) ? undefined : next;
193
196
  }
194
- async executeRung(task, rung, context) {
197
+ async executeRung(task, rung, context, seedCandidates) {
195
198
  try {
196
199
  switch (rung) {
197
200
  case "card":
198
- await this.executeCardRung(task, context);
201
+ await this.executeCardRung(task, context, seedCandidates);
199
202
  break;
200
203
  case "skeleton":
201
- await this.executeSkeletonRung(task, context);
204
+ await this.executeSkeletonRung(task, context, seedCandidates);
202
205
  break;
203
206
  case "hotPath":
204
- await this.executeHotPathRung(task, context);
207
+ await this.executeHotPathRung(task, context, seedCandidates);
205
208
  break;
206
209
  case "raw":
207
210
  await this.executeRawRung(task, context);
@@ -239,12 +242,10 @@ export class Executor {
239
242
  for (const relPath of filePaths) {
240
243
  try {
241
244
  // Try exact file match first
242
- const file = await ladybugDb.getFileByRepoPath(conn, repoId, relPath);
245
+ const file = await this.dbQueries.getFileByRepoPath(conn, repoId, relPath);
243
246
  if (file) {
244
- const symbols = await ladybugDb.getSymbolsByFile(conn, file.fileId);
245
- const behavioral = symbols.filter((s) => BEHAVIORAL_KINDS.has(s.kind));
246
- const preferred = behavioral.length > 0 ? behavioral : symbols;
247
- results.push(preferred.slice(0, 50).map((sym) => sym.symbolId));
247
+ const symbolIds = await this.dbQueries.getSymbolIdsByFile(conn, file.fileId);
248
+ results.push(symbolIds.slice(0, 5));
248
249
  continue;
249
250
  }
250
251
  // If exact match fails, treat as directory prefix and find files under it.
@@ -252,11 +253,11 @@ export class Executor {
252
253
  const normalizedPrefix = relPath.endsWith("/")
253
254
  ? relPath
254
255
  : relPath + "/";
255
- const filesUnderDir = await ladybugDb.getFilesByPrefix(conn, repoId, normalizedPrefix);
256
+ const filesUnderDir = await this.dbQueries.getFilesByPrefix(conn, repoId, normalizedPrefix);
256
257
  if (filesUnderDir.length > 0) {
257
258
  const symbolResults = [];
258
259
  for (const f of filesUnderDir.slice(0, 10)) {
259
- const symbols = await ladybugDb.getSymbolsByFile(conn, f.fileId);
260
+ const symbols = await this.dbQueries.getSymbolsByFile(conn, f.fileId);
260
261
  const beh = symbols.filter((s) => BEHAVIORAL_KINDS.has(s.kind));
261
262
  symbolResults.push((beh.length > 0 ? beh : symbols)
262
263
  .slice(0, 5)
@@ -277,48 +278,270 @@ export class Executor {
277
278
  return results.flat();
278
279
  }
279
280
  /**
280
- * Extract symbol IDs and file paths from context entries,
281
- * resolving file: entries to their constituent symbol IDs.
281
+ * Extract symbol IDs and file paths from context entries.
282
+ *
283
+ * Non-symbol retrieval entities are expanded into representative symbols and
284
+ * carry their original seed score forward so final ranking can still use the
285
+ * retrieval prior that found the entity.
282
286
  */
283
- async resolveContextToSymbols(context, repoId) {
287
+ async resolveContextToSymbols(context, task, seedCandidates = []) {
288
+ const repoId = task.repoId;
284
289
  const directSymbols = context
285
290
  .filter((c) => c.startsWith("symbol:"))
286
291
  .map((s) => s.slice("symbol:".length));
287
292
  const filePaths = context
288
293
  .filter((c) => c.startsWith("file:"))
289
294
  .map((f) => f.slice("file:".length));
295
+ const fileSummaryIds = context
296
+ .filter((c) => c.startsWith("fileSummary:"))
297
+ .map((f) => f.slice("fileSummary:".length));
298
+ const clusterIds = context
299
+ .filter((c) => c.startsWith("cluster:"))
300
+ .map((c) => c.slice("cluster:".length));
301
+ const processIds = context
302
+ .filter((c) => c.startsWith("process:"))
303
+ .map((p) => p.slice("process:".length));
290
304
  let resolvedSymbols = [];
291
305
  if (filePaths.length > 0) {
292
306
  resolvedSymbols = await this.resolveFileSymbols(filePaths, repoId);
293
307
  }
308
+ const seedByRef = new Map(seedCandidates.map((c) => [c.contextRef, c]));
309
+ const expandedSeedCandidates = seedCandidates.filter((c) => c.contextRef.startsWith("symbol:"));
310
+ const expandedRefs = new Set(expandedSeedCandidates.map((c) => c.contextRef));
311
+ for (const [index, symbolId] of directSymbols.entries()) {
312
+ const symbolRef = `symbol:${symbolId}`;
313
+ if (expandedRefs.has(symbolRef))
314
+ continue;
315
+ expandedRefs.add(symbolRef);
316
+ expandedSeedCandidates.push({
317
+ contextRef: symbolRef,
318
+ source: "lexical",
319
+ score: 1,
320
+ sourceRank: -1000 + index,
321
+ entityType: "symbol",
322
+ expansionReason: "directContext",
323
+ });
324
+ }
325
+ const addExpandedSeed = (symbolId, sourceRef, index, scoreScale, expansionReason) => {
326
+ const source = seedByRef.get(sourceRef);
327
+ if (!source)
328
+ return;
329
+ const symbolRef = `symbol:${symbolId}`;
330
+ if (expandedRefs.has(symbolRef))
331
+ return;
332
+ expandedRefs.add(symbolRef);
333
+ expandedSeedCandidates.push({
334
+ ...source,
335
+ contextRef: symbolRef,
336
+ entityType: "symbol",
337
+ expandedFrom: sourceRef,
338
+ expansionReason,
339
+ score: Math.max(0, Math.min(1, source.score * scoreScale)),
340
+ sourceRank: source.sourceRank + index + 1,
341
+ });
342
+ };
343
+ if (fileSummaryIds.length > 0 || clusterIds.length > 0 || processIds.length > 0) {
344
+ const conn = await this.getConn();
345
+ const identifiers = this.extractIdentifiersFromTask(task);
346
+ const rankExpandedFileSymbols = (fileId, symbols) => {
347
+ if (symbols.length === 0)
348
+ return [];
349
+ const source = seedByRef.get(`fileSummary:${fileId}`);
350
+ const symbolIds = symbols.map((symbol) => symbol.symbolId);
351
+ if (identifiers.length === 0 || !source) {
352
+ return symbolIds.slice(0, 8);
353
+ }
354
+ const symbolMap = new Map(symbols.map((symbol) => [symbol.symbolId, symbol]));
355
+ const fileSeedCandidates = symbols.map((symbol, index) => ({
356
+ ...source,
357
+ contextRef: `symbol:${symbol.symbolId}`,
358
+ entityType: "symbol",
359
+ expandedFrom: `fileSummary:${fileId}`,
360
+ expansionReason: "fileSummary",
361
+ score: Math.max(0, Math.min(1, source.score * 0.92)),
362
+ sourceRank: source.sourceRank + index + 1,
363
+ }));
364
+ return rankSymbols(symbolIds, symbolMap, identifiers, task, {
365
+ seedCandidates: fileSeedCandidates,
366
+ anchorSymbolIds: directSymbols,
367
+ })
368
+ .ranked.slice(0, 8)
369
+ .map((ranked) => ranked.symbolId);
370
+ };
371
+ for (const fileId of fileSummaryIds.slice(0, 8)) {
372
+ const symbols = await this.dbQueries.getSymbolsByFile(conn, fileId);
373
+ const symbolIds = rankExpandedFileSymbols(fileId, symbols);
374
+ resolvedSymbols.push(...symbolIds);
375
+ symbolIds.forEach((symbolId, index) => addExpandedSeed(symbolId, `fileSummary:${fileId}`, index, 0.92, "fileSummary"));
376
+ }
377
+ for (const clusterId of clusterIds.slice(0, 8)) {
378
+ const members = (await this.dbQueries.getClusterMembers(conn, clusterId))
379
+ .sort((a, b) => b.membershipScore - a.membershipScore)
380
+ .slice(0, 8);
381
+ resolvedSymbols.push(...members.map((m) => m.symbolId));
382
+ members.forEach((member, index) => addExpandedSeed(member.symbolId, `cluster:${clusterId}`, index, 0.86, "clusterMember"));
383
+ }
384
+ if (processIds.length > 0) {
385
+ const wantedProcesses = new Set(processIds.slice(0, 8));
386
+ const steps = (await this.dbQueries.getProcessStepsByIds(conn, repoId, [...wantedProcesses]))
387
+ .filter((step) => wantedProcesses.has(step.processId))
388
+ .sort((a, b) => a.stepOrder - b.stepOrder);
389
+ const countByProcess = new Map();
390
+ for (const step of steps) {
391
+ const count = countByProcess.get(step.processId) ?? 0;
392
+ if (count >= 8)
393
+ continue;
394
+ countByProcess.set(step.processId, count + 1);
395
+ resolvedSymbols.push(step.symbolId);
396
+ addExpandedSeed(step.symbolId, `process:${step.processId}`, count, 0.88, "processStep");
397
+ }
398
+ }
399
+ }
294
400
  const symbolIds = [...new Set([...directSymbols, ...resolvedSymbols])];
295
- return { symbolIds, filePaths };
401
+ return { symbolIds, filePaths, seedCandidates: expandedSeedCandidates };
296
402
  }
297
403
  /**
298
404
  * Select the top symbols based on multi-factor ranking with adaptive cutoff.
299
405
  * Delegates scoring to context-ranking.ts for evidence-aware symbol selection.
300
406
  */
301
- async selectTopSymbols(symbolIds, task, maxCount) {
407
+ async selectTopSymbols(symbolIds, task, maxCount, seedCandidates = []) {
302
408
  if (!task.taskText || symbolIds.length === 0) {
303
409
  return symbolIds.slice(0, maxCount);
304
410
  }
305
411
  const identifiers = this.extractIdentifiersFromTask(task);
306
- if (identifiers.length === 0)
412
+ if (identifiers.length === 0 && seedCandidates.length === 0) {
307
413
  return symbolIds.slice(0, maxCount);
414
+ }
308
415
  const conn = await this.getConn();
309
- const symbolMap = await ladybugDb.getSymbolsByIds(conn, symbolIds);
310
- const ranking = rankSymbols(symbolIds, symbolMap, identifiers, task);
416
+ const symbolMap = await this.dbQueries.getSymbolsByIds(conn, symbolIds);
417
+ const anchorSymbolIds = seedCandidates
418
+ .map((candidate) => candidate.contextRef.startsWith("symbol:")
419
+ ? candidate.contextRef.slice("symbol:".length)
420
+ : undefined)
421
+ .filter((symbolId) => !!symbolId);
422
+ const ranking = rankSymbols(symbolIds, symbolMap, identifiers, task, {
423
+ seedCandidates,
424
+ anchorSymbolIds,
425
+ });
311
426
  const isPrecise = task.options?.contextMode === "precise";
312
427
  const hasScope = !!(task.options?.focusPaths?.length || task.options?.focusSymbols?.length);
313
- return applyAdaptiveCutoff(ranking, maxCount, isPrecise, hasScope);
428
+ const selected = applyAdaptiveCutoff(ranking, maxCount, isPrecise, hasScope);
429
+ return this.ensureFocusPathCoverage(selected, ranking.ranked.map((ranked) => ranked.symbolId), symbolMap, task.options?.inferredFocusPaths ?? [], maxCount);
314
430
  }
315
- async executeCardRung(task, context) {
431
+ ensureFocusPathCoverage(selected, rankedSymbolIds, symbolMap, focusPaths, maxCount) {
432
+ if (focusPaths.length === 0 || selected.length === 0)
433
+ return selected;
434
+ const selectedSet = new Set(selected);
435
+ const additions = [];
436
+ const perPathLimit = focusPaths.some((path) => path.split("/").pop()?.includes("."))
437
+ ? 4
438
+ : 2;
439
+ for (const focusPath of focusPaths) {
440
+ let addedForPath = 0;
441
+ for (const symbolId of rankedSymbolIds) {
442
+ if (selectedSet.has(symbolId))
443
+ continue;
444
+ const symbol = symbolMap.get(symbolId);
445
+ if (!this.symbolMatchesFocusPath(symbol, focusPath))
446
+ continue;
447
+ selectedSet.add(symbolId);
448
+ additions.push(symbolId);
449
+ addedForPath++;
450
+ if (addedForPath >= perPathLimit)
451
+ break;
452
+ }
453
+ }
454
+ if (additions.length === 0)
455
+ return selected;
456
+ const focusSet = new Set();
457
+ for (const symbolId of rankedSymbolIds) {
458
+ const symbol = symbolMap.get(symbolId);
459
+ if (focusPaths.some((focusPath) => this.symbolMatchesFocusPath(symbol, focusPath))) {
460
+ focusSet.add(symbolId);
461
+ }
462
+ }
463
+ const merged = [...selected];
464
+ for (const symbolId of additions) {
465
+ if (merged.length < maxCount) {
466
+ merged.push(symbolId);
467
+ continue;
468
+ }
469
+ const replaceIndex = merged.findLastIndex((existing) => !focusSet.has(existing));
470
+ if (replaceIndex < 0)
471
+ break;
472
+ merged[replaceIndex] = symbolId;
473
+ }
474
+ return merged;
475
+ }
476
+ async buildRelatedSymbolNameMap(conn, selectedSymbols, task) {
477
+ const shouldSurfaceRelated = task.options?.semantic === true ||
478
+ (task.options?.inferredFocusPaths?.length ?? 0) > 0;
479
+ if (!shouldSurfaceRelated || selectedSymbols.length === 0) {
480
+ return new Map();
481
+ }
482
+ const inferredFocusPaths = task.options?.inferredFocusPaths ?? [];
483
+ const identifiers = this.extractIdentifiersFromTask(task);
484
+ const selectedByFile = new Map();
485
+ for (const symbol of selectedSymbols) {
486
+ if (!symbol.fileId)
487
+ continue;
488
+ if (inferredFocusPaths.length > 0 &&
489
+ !inferredFocusPaths.some((focusPath) => this.symbolMatchesFocusPath(symbol, focusPath))) {
490
+ continue;
491
+ }
492
+ if (!selectedByFile.has(symbol.fileId)) {
493
+ selectedByFile.set(symbol.fileId, new Set());
494
+ }
495
+ selectedByFile.get(symbol.fileId).add(symbol.symbolId);
496
+ if (selectedByFile.size >= 6)
497
+ break;
498
+ }
499
+ const relatedByFile = new Map();
500
+ for (const [fileId, selectedIds] of selectedByFile) {
501
+ const fileSymbols = await this.dbQueries.getSymbolsByFile(conn, fileId);
502
+ if (fileSymbols.length === 0)
503
+ continue;
504
+ const symbolIds = fileSymbols.map((symbol) => symbol.symbolId);
505
+ const fileSymbolMap = new Map(fileSymbols.map((symbol) => [symbol.symbolId, symbol]));
506
+ const ranking = rankSymbols(symbolIds, fileSymbolMap, identifiers, task);
507
+ const names = [];
508
+ const seenNames = new Set();
509
+ for (const ranked of ranking.ranked) {
510
+ if (selectedIds.has(ranked.symbolId))
511
+ continue;
512
+ const symbol = fileSymbolMap.get(ranked.symbolId);
513
+ if (!symbol || seenNames.has(symbol.name))
514
+ continue;
515
+ seenNames.add(symbol.name);
516
+ names.push(symbol.name);
517
+ if (names.length >= 14)
518
+ break;
519
+ }
520
+ if (names.length > 0) {
521
+ relatedByFile.set(fileId, names);
522
+ }
523
+ }
524
+ return relatedByFile;
525
+ }
526
+ symbolMatchesFocusPath(symbol, focusPath) {
527
+ const fileId = symbol?.fileId;
528
+ if (!fileId)
529
+ return false;
530
+ const relPath = fileId.includes(":")
531
+ ? fileId.slice(fileId.indexOf(":") + 1)
532
+ : fileId;
533
+ const normalizedRelPath = relPath.replace(/\\/g, "/").toLowerCase();
534
+ const normalizedFocus = focusPath.replace(/\\/g, "/").toLowerCase();
535
+ return (normalizedRelPath === normalizedFocus ||
536
+ normalizedRelPath.startsWith(normalizedFocus.endsWith("/") ? normalizedFocus : `${normalizedFocus}/`));
537
+ }
538
+ async executeCardRung(task, context, seedCandidates) {
316
539
  const actionId = this.generateActionId();
317
540
  const startTime = Date.now();
318
541
  try {
319
- const { symbolIds: rawSymbols } = await this.resolveContextToSymbols(context, task.repoId);
542
+ const { symbolIds: rawSymbols, seedCandidates: expandedSeedCandidates } = await this.resolveContextToSymbols(context, task, seedCandidates);
320
543
  let allSymbols = rawSymbols.length > 0 && task.taskText
321
- ? await this.selectTopSymbols(rawSymbols, task, MAX_CARD_SYMBOLS)
544
+ ? await this.selectTopSymbols(rawSymbols, task, MAX_CARD_SYMBOLS, expandedSeedCandidates)
322
545
  : rawSymbols.slice(0, MAX_CARD_SYMBOLS);
323
546
  // Fallback: identifier-based search with per-term resolution
324
547
  if (allSymbols.length === 0 && task.taskText) {
@@ -331,7 +554,8 @@ export class Executor {
331
554
  ? task.options.searchTerms.slice(0, maxTerms)
332
555
  : this.extractIdentifiersFromTask(task).slice(0, maxTerms);
333
556
  const seen = new Set();
334
- const useHybrid = await isHybridRetrievalAvailable();
557
+ const useHybrid = task.options?.semantic !== false &&
558
+ (await isHybridRetrievalAvailable());
335
559
  // 2. Search for each identifier individually and combine results
336
560
  for (const term of searchTerms) {
337
561
  if (useHybrid) {
@@ -350,7 +574,7 @@ export class Executor {
350
574
  }
351
575
  else {
352
576
  const conn = await this.getConn();
353
- const searchResults = await ladybugDb.searchSymbols(conn, task.repoId, term, Math.ceil(searchFallbackLimit / Math.max(searchTerms.length, 1)));
577
+ const searchResults = await this.dbQueries.searchSymbols(conn, task.repoId, term, Math.ceil(searchFallbackLimit / Math.max(searchTerms.length, 1)));
354
578
  for (const result of searchResults) {
355
579
  if (!seen.has(result.symbolId)) {
356
580
  seen.add(result.symbolId);
@@ -374,7 +598,7 @@ export class Executor {
374
598
  }
375
599
  else {
376
600
  const conn = await this.getConn();
377
- const searchResults = await ladybugDb.searchSymbols(conn, task.repoId, task.taskText, searchFallbackLimit);
601
+ const searchResults = await this.dbQueries.searchSymbols(conn, task.repoId, task.taskText, searchFallbackLimit);
378
602
  for (const result of searchResults) {
379
603
  allSymbols.push(result.symbolId);
380
604
  }
@@ -432,7 +656,8 @@ export class Executor {
432
656
  else {
433
657
  // Fetch real symbol data from DB
434
658
  const conn = await this.getConn();
435
- const symbolMap = await ladybugDb.getSymbolsByIds(conn, allSymbols);
659
+ const symbolMap = await this.dbQueries.getSymbolsByIds(conn, allSymbols);
660
+ const relatedSymbolsByFile = await this.buildRelatedSymbolNameMap(conn, [...symbolMap.values()], task);
436
661
  // Iterate in ranked order to preserve relevance in evidence
437
662
  for (const symbolId of allSymbols) {
438
663
  const sym = symbolMap.get(symbolId);
@@ -452,6 +677,16 @@ export class Executor {
452
677
  const parts = [`${sym.kind} ${sym.name}`];
453
678
  if (relPath)
454
679
  parts.push(relPath);
680
+ const fileAlias = this.fileAliasForPath(relPath);
681
+ if (fileAlias && fileAlias !== sym.name) {
682
+ parts.push(`fileAlias: ${fileAlias}`);
683
+ }
684
+ const relatedSymbols = sym.fileId
685
+ ? relatedSymbolsByFile.get(sym.fileId)
686
+ : undefined;
687
+ if (relatedSymbols && relatedSymbols.length > 0) {
688
+ parts.push(`relatedSymbols: ${relatedSymbols.join(", ")}`);
689
+ }
455
690
  if (sym.signatureJson) {
456
691
  try {
457
692
  const sig = JSON.parse(sym.signatureJson);
@@ -494,21 +729,30 @@ export class Executor {
494
729
  throw new IndexError(`Card rung execution failed: ${error instanceof Error ? error.message : String(error)}`);
495
730
  }
496
731
  }
497
- async executeSkeletonRung(task, context) {
732
+ async executeSkeletonRung(task, context, seedCandidates) {
498
733
  const actionId = this.generateActionId();
499
734
  const startTime = Date.now();
500
735
  try {
501
- const { symbolIds: rawSkeletonSymbols, filePaths } = await this.resolveContextToSymbols(context, task.repoId);
736
+ const { symbolIds: rawSkeletonSymbols, filePaths, seedCandidates: expandedSeedCandidates, } = await this.resolveContextToSymbols(context, task, seedCandidates);
737
+ const skeletonSymbolLimit = this.rungSymbolLimit(task, MAX_SKELETON_SYMBOLS);
502
738
  const symbolIds = rawSkeletonSymbols.length > 0 && task.taskText
503
- ? await this.selectTopSymbols(rawSkeletonSymbols, task, MAX_SKELETON_SYMBOLS)
504
- : rawSkeletonSymbols.slice(0, MAX_SKELETON_SYMBOLS);
739
+ ? await this.selectTopSymbols(rawSkeletonSymbols, task, skeletonSymbolLimit, expandedSeedCandidates)
740
+ : rawSkeletonSymbols.slice(0, skeletonSymbolLimit);
505
741
  let processedCount = 0;
742
+ const hydrateEvidencePrefixes = this.shouldHydrateEvidencePrefixes(task);
743
+ const conn = hydrateEvidencePrefixes && symbolIds.length > 0
744
+ ? await this.getConn()
745
+ : undefined;
746
+ const symbolMap = conn
747
+ ? await this.dbQueries.getSymbolsByIds(conn, symbolIds)
748
+ : new Map();
506
749
  // Generate skeletons for symbol IDs (skip degenerate < 10 tokens)
507
750
  for (const symbolId of symbolIds) {
508
751
  try {
509
752
  const result = await generateSkeletonIR(task.repoId, symbolId, {});
510
753
  if (result && result.estimatedTokens >= 10) {
511
- this.evidenceCapture.captureSkeleton(symbolId, `Skeleton (${result.originalLines} lines, ~${result.estimatedTokens} tokens): ${result.skeletonText.slice(0, 200)}`);
754
+ const prefix = this.formatSymbolEvidencePrefix(symbolMap.get(symbolId));
755
+ this.evidenceCapture.captureSkeleton(symbolId, `${prefix} | Skeleton (${result.originalLines} lines, ~${result.estimatedTokens} tokens): ${result.skeletonText.slice(0, 200)}`);
512
756
  processedCount++;
513
757
  }
514
758
  }
@@ -526,7 +770,7 @@ export class Executor {
526
770
  ? 0
527
771
  : processedCount > 0
528
772
  ? 1
529
- : MAX_SKELETON_SYMBOLS;
773
+ : skeletonSymbolLimit;
530
774
  for (const filePath of filePaths.slice(0, maxFileSks)) {
531
775
  try {
532
776
  const result = await generateFileSkeleton(task.repoId, filePath, false, {});
@@ -564,21 +808,30 @@ export class Executor {
564
808
  throw new IndexError(`Skeleton rung execution failed: ${error instanceof Error ? error.message : String(error)}`);
565
809
  }
566
810
  }
567
- async executeHotPathRung(task, context) {
811
+ async executeHotPathRung(task, context, seedCandidates) {
568
812
  const actionId = this.generateActionId();
569
813
  const startTime = Date.now();
570
814
  try {
571
- const { symbolIds: rawHotpathSymbols } = await this.resolveContextToSymbols(context, task.repoId);
815
+ const { symbolIds: rawHotpathSymbols, seedCandidates: expandedSeedCandidates } = await this.resolveContextToSymbols(context, task, seedCandidates);
816
+ const hotPathSymbolLimit = this.rungSymbolLimit(task, MAX_HOTPATH_SYMBOLS);
572
817
  const symbols = rawHotpathSymbols.length > 0 && task.taskText
573
- ? await this.selectTopSymbols(rawHotpathSymbols, task, MAX_HOTPATH_SYMBOLS)
574
- : rawHotpathSymbols.slice(0, MAX_HOTPATH_SYMBOLS);
818
+ ? await this.selectTopSymbols(rawHotpathSymbols, task, hotPathSymbolLimit, expandedSeedCandidates)
819
+ : rawHotpathSymbols.slice(0, hotPathSymbolLimit);
575
820
  const identifiers = this.extractIdentifiersFromTask(task);
576
821
  let processedCount = 0;
822
+ const hydrateEvidencePrefixes = this.shouldHydrateEvidencePrefixes(task);
823
+ const conn = hydrateEvidencePrefixes && symbols.length > 0
824
+ ? await this.getConn()
825
+ : undefined;
826
+ const symbolMap = conn
827
+ ? await this.dbQueries.getSymbolsByIds(conn, symbols)
828
+ : new Map();
577
829
  for (const symbolId of symbols) {
578
830
  try {
579
831
  const result = await extractHotPath(task.repoId, symbolId, identifiers, {});
580
832
  if (result) {
581
- this.evidenceCapture.captureHotPath(symbolId, `Hot path (${result.matchedIdentifiers.length} matches, ~${result.estimatedTokens} tokens): ${result.excerpt.slice(0, 200)}`);
833
+ const prefix = this.formatSymbolEvidencePrefix(symbolMap.get(symbolId));
834
+ this.evidenceCapture.captureHotPath(symbolId, `${prefix} | Hot path (${result.matchedIdentifiers.length} matches, ~${result.estimatedTokens} tokens): ${result.excerpt.slice(0, 200)}`);
582
835
  processedCount++;
583
836
  }
584
837
  }
@@ -615,7 +868,7 @@ export class Executor {
615
868
  const actionId = this.generateActionId();
616
869
  const startTime = Date.now();
617
870
  try {
618
- const { symbolIds: symbols } = await this.resolveContextToSymbols(context, task.repoId);
871
+ const { symbolIds: symbols } = await this.resolveContextToSymbols(context, task);
619
872
  const identifiers = this.extractIdentifiersFromTask(task);
620
873
  let processedCount = 0;
621
874
  for (const symbolId of symbols.slice(0, MAX_RAW_SYMBOLS)) {
@@ -702,6 +955,58 @@ export class Executor {
702
955
  }
703
956
  return [...new Set(identifiers)].slice(0, MAX_IDENTIFIERS);
704
957
  }
958
+ fileAliasForPath(relPath) {
959
+ if (!relPath)
960
+ return undefined;
961
+ const parts = relPath.split(/[\\/]+/).filter(Boolean);
962
+ const fileName = parts.at(-1);
963
+ if (!fileName)
964
+ return undefined;
965
+ const base = fileName.replace(/\.[^.]+$/, "");
966
+ const parent = parts.length >= 2 ? parts.at(-2) : undefined;
967
+ const aliasBase = parent && GENERIC_FILE_BASENAMES.has(base.toLowerCase())
968
+ ? `${parent}-${base}`
969
+ : base;
970
+ const words = aliasBase
971
+ .replace(/([a-z0-9])([A-Z])/g, "$1-$2")
972
+ .split(/[^A-Za-z0-9]+/)
973
+ .filter(Boolean);
974
+ if (words.length === 0)
975
+ return undefined;
976
+ return words
977
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
978
+ .join("");
979
+ }
980
+ formatSymbolEvidencePrefix(sym) {
981
+ if (!sym)
982
+ return "symbol";
983
+ const relPath = sym.fileId?.includes(":")
984
+ ? sym.fileId.slice(sym.fileId.indexOf(":") + 1)
985
+ : sym.fileId;
986
+ const parts = [`${sym.kind} ${sym.name}`];
987
+ if (relPath)
988
+ parts.push(relPath);
989
+ const fileAlias = this.fileAliasForPath(relPath);
990
+ if (fileAlias && fileAlias !== sym.name) {
991
+ parts.push(`fileAlias: ${fileAlias}`);
992
+ }
993
+ return parts.join(" | ");
994
+ }
995
+ shouldHydrateEvidencePrefixes(task) {
996
+ const hasExplicitScope = !!(task.options?.focusPaths?.length || task.options?.focusSymbols?.length);
997
+ return task.options?.semantic === true || !hasExplicitScope;
998
+ }
999
+ rungSymbolLimit(task, defaultMax) {
1000
+ const hasExplicitScope = !!(task.options?.focusPaths?.length || task.options?.focusSymbols?.length);
1001
+ const hasInferredScope = (task.options?.inferredFocusPaths?.length ?? 0) > 0;
1002
+ if (task.options?.contextMode === "precise" &&
1003
+ hasExplicitScope &&
1004
+ !hasInferredScope &&
1005
+ task.options?.semantic !== true) {
1006
+ return Math.min(2, defaultMax);
1007
+ }
1008
+ return defaultMax;
1009
+ }
705
1010
  generateActionId() {
706
1011
  return `action-${this.actions.length}-${Date.now()}-${randomUUID().slice(0, 8)}`;
707
1012
  }