seer-mcp 0.1.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 (371) hide show
  1. package/.vscode/settings.json +3 -0
  2. package/LICENSE +176 -0
  3. package/README.md +272 -0
  4. package/README_dev.md +199 -0
  5. package/dist/bundle/ci.d.ts +47 -0
  6. package/dist/bundle/ci.d.ts.map +1 -0
  7. package/dist/bundle/ci.js +113 -0
  8. package/dist/bundle/ci.js.map +1 -0
  9. package/dist/bundle/contract.d.ts +111 -0
  10. package/dist/bundle/contract.d.ts.map +1 -0
  11. package/dist/bundle/contract.js +352 -0
  12. package/dist/bundle/contract.js.map +1 -0
  13. package/dist/bundle/export.d.ts +36 -0
  14. package/dist/bundle/export.d.ts.map +1 -0
  15. package/dist/bundle/export.js +152 -0
  16. package/dist/bundle/export.js.map +1 -0
  17. package/dist/bundle/external.d.ts +66 -0
  18. package/dist/bundle/external.d.ts.map +1 -0
  19. package/dist/bundle/external.js +238 -0
  20. package/dist/bundle/external.js.map +1 -0
  21. package/dist/bundle/format.d.ts +94 -0
  22. package/dist/bundle/format.d.ts.map +1 -0
  23. package/dist/bundle/format.js +42 -0
  24. package/dist/bundle/format.js.map +1 -0
  25. package/dist/bundle/import.d.ts +49 -0
  26. package/dist/bundle/import.d.ts.map +1 -0
  27. package/dist/bundle/import.js +116 -0
  28. package/dist/bundle/import.js.map +1 -0
  29. package/dist/cli/index.d.ts +3 -0
  30. package/dist/cli/index.d.ts.map +1 -0
  31. package/dist/cli/index.js +1402 -0
  32. package/dist/cli/index.js.map +1 -0
  33. package/dist/cli/init.d.ts +48 -0
  34. package/dist/cli/init.d.ts.map +1 -0
  35. package/dist/cli/init.js +284 -0
  36. package/dist/cli/init.js.map +1 -0
  37. package/dist/db/schema.d.ts +3 -0
  38. package/dist/db/schema.d.ts.map +1 -0
  39. package/dist/db/schema.js +616 -0
  40. package/dist/db/schema.js.map +1 -0
  41. package/dist/db/store.d.ts +1011 -0
  42. package/dist/db/store.d.ts.map +1 -0
  43. package/dist/db/store.js +3888 -0
  44. package/dist/db/store.js.map +1 -0
  45. package/dist/graph/pagerank.d.ts +9 -0
  46. package/dist/graph/pagerank.d.ts.map +1 -0
  47. package/dist/graph/pagerank.js +47 -0
  48. package/dist/graph/pagerank.js.map +1 -0
  49. package/dist/indexer/architecture.d.ts +72 -0
  50. package/dist/indexer/architecture.d.ts.map +1 -0
  51. package/dist/indexer/architecture.js +112 -0
  52. package/dist/indexer/architecture.js.map +1 -0
  53. package/dist/indexer/behavior.d.ts +75 -0
  54. package/dist/indexer/behavior.d.ts.map +1 -0
  55. package/dist/indexer/behavior.js +395 -0
  56. package/dist/indexer/behavior.js.map +1 -0
  57. package/dist/indexer/boundaries.d.ts +60 -0
  58. package/dist/indexer/boundaries.d.ts.map +1 -0
  59. package/dist/indexer/boundaries.js +366 -0
  60. package/dist/indexer/boundaries.js.map +1 -0
  61. package/dist/indexer/churn.d.ts +15 -0
  62. package/dist/indexer/churn.d.ts.map +1 -0
  63. package/dist/indexer/churn.js +49 -0
  64. package/dist/indexer/churn.js.map +1 -0
  65. package/dist/indexer/classify.d.ts +9 -0
  66. package/dist/indexer/classify.d.ts.map +1 -0
  67. package/dist/indexer/classify.js +90 -0
  68. package/dist/indexer/classify.js.map +1 -0
  69. package/dist/indexer/context.d.ts +176 -0
  70. package/dist/indexer/context.d.ts.map +1 -0
  71. package/dist/indexer/context.js +193 -0
  72. package/dist/indexer/context.js.map +1 -0
  73. package/dist/indexer/continuity.d.ts +67 -0
  74. package/dist/indexer/continuity.d.ts.map +1 -0
  75. package/dist/indexer/continuity.js +288 -0
  76. package/dist/indexer/continuity.js.map +1 -0
  77. package/dist/indexer/detectchanges.d.ts +32 -0
  78. package/dist/indexer/detectchanges.d.ts.map +1 -0
  79. package/dist/indexer/detectchanges.js +74 -0
  80. package/dist/indexer/detectchanges.js.map +1 -0
  81. package/dist/indexer/discovery.d.ts +37 -0
  82. package/dist/indexer/discovery.d.ts.map +1 -0
  83. package/dist/indexer/discovery.js +136 -0
  84. package/dist/indexer/discovery.js.map +1 -0
  85. package/dist/indexer/externaldeps.d.ts +18 -0
  86. package/dist/indexer/externaldeps.d.ts.map +1 -0
  87. package/dist/indexer/externaldeps.js +288 -0
  88. package/dist/indexer/externaldeps.js.map +1 -0
  89. package/dist/indexer/freshness.d.ts +48 -0
  90. package/dist/indexer/freshness.d.ts.map +1 -0
  91. package/dist/indexer/freshness.js +128 -0
  92. package/dist/indexer/freshness.js.map +1 -0
  93. package/dist/indexer/git.d.ts +144 -0
  94. package/dist/indexer/git.d.ts.map +1 -0
  95. package/dist/indexer/git.js +444 -0
  96. package/dist/indexer/git.js.map +1 -0
  97. package/dist/indexer/index.d.ts +145 -0
  98. package/dist/indexer/index.d.ts.map +1 -0
  99. package/dist/indexer/index.js +930 -0
  100. package/dist/indexer/index.js.map +1 -0
  101. package/dist/indexer/modules.d.ts +62 -0
  102. package/dist/indexer/modules.d.ts.map +1 -0
  103. package/dist/indexer/modules.js +293 -0
  104. package/dist/indexer/modules.js.map +1 -0
  105. package/dist/indexer/preflight.d.ts +154 -0
  106. package/dist/indexer/preflight.d.ts.map +1 -0
  107. package/dist/indexer/preflight.js +399 -0
  108. package/dist/indexer/preflight.js.map +1 -0
  109. package/dist/indexer/protoScanner.d.ts +34 -0
  110. package/dist/indexer/protoScanner.d.ts.map +1 -0
  111. package/dist/indexer/protoScanner.js +133 -0
  112. package/dist/indexer/protoScanner.js.map +1 -0
  113. package/dist/indexer/risk.d.ts +115 -0
  114. package/dist/indexer/risk.d.ts.map +1 -0
  115. package/dist/indexer/risk.js +194 -0
  116. package/dist/indexer/risk.js.map +1 -0
  117. package/dist/indexer/serviceHostScanner.d.ts +25 -0
  118. package/dist/indexer/serviceHostScanner.d.ts.map +1 -0
  119. package/dist/indexer/serviceHostScanner.js +95 -0
  120. package/dist/indexer/serviceHostScanner.js.map +1 -0
  121. package/dist/indexer/serviceLinks.d.ts +105 -0
  122. package/dist/indexer/serviceLinks.d.ts.map +1 -0
  123. package/dist/indexer/serviceLinks.js +509 -0
  124. package/dist/indexer/serviceLinks.js.map +1 -0
  125. package/dist/indexer/shapehash.d.ts +98 -0
  126. package/dist/indexer/shapehash.d.ts.map +1 -0
  127. package/dist/indexer/shapehash.js +354 -0
  128. package/dist/indexer/shapehash.js.map +1 -0
  129. package/dist/indexer/skeleton.d.ts +15 -0
  130. package/dist/indexer/skeleton.d.ts.map +1 -0
  131. package/dist/indexer/skeleton.js +136 -0
  132. package/dist/indexer/skeleton.js.map +1 -0
  133. package/dist/indexer/symbolhistory.d.ts +41 -0
  134. package/dist/indexer/symbolhistory.d.ts.map +1 -0
  135. package/dist/indexer/symbolhistory.js +124 -0
  136. package/dist/indexer/symbolhistory.js.map +1 -0
  137. package/dist/indexer/watcher.d.ts +68 -0
  138. package/dist/indexer/watcher.d.ts.map +1 -0
  139. package/dist/indexer/watcher.js +179 -0
  140. package/dist/indexer/watcher.js.map +1 -0
  141. package/dist/mcp/server.d.ts +80 -0
  142. package/dist/mcp/server.d.ts.map +1 -0
  143. package/dist/mcp/server.js +1610 -0
  144. package/dist/mcp/server.js.map +1 -0
  145. package/dist/parser/index.d.ts +8 -0
  146. package/dist/parser/index.d.ts.map +1 -0
  147. package/dist/parser/index.js +33 -0
  148. package/dist/parser/index.js.map +1 -0
  149. package/dist/parser/languages/cpp.d.ts +3 -0
  150. package/dist/parser/languages/cpp.d.ts.map +1 -0
  151. package/dist/parser/languages/cpp.js +350 -0
  152. package/dist/parser/languages/cpp.js.map +1 -0
  153. package/dist/parser/languages/csharp.d.ts +3 -0
  154. package/dist/parser/languages/csharp.d.ts.map +1 -0
  155. package/dist/parser/languages/csharp.js +239 -0
  156. package/dist/parser/languages/csharp.js.map +1 -0
  157. package/dist/parser/languages/go.d.ts +3 -0
  158. package/dist/parser/languages/go.d.ts.map +1 -0
  159. package/dist/parser/languages/go.js +259 -0
  160. package/dist/parser/languages/go.js.map +1 -0
  161. package/dist/parser/languages/java.d.ts +3 -0
  162. package/dist/parser/languages/java.d.ts.map +1 -0
  163. package/dist/parser/languages/java.js +391 -0
  164. package/dist/parser/languages/java.js.map +1 -0
  165. package/dist/parser/languages/python.d.ts +3 -0
  166. package/dist/parser/languages/python.d.ts.map +1 -0
  167. package/dist/parser/languages/python.js +396 -0
  168. package/dist/parser/languages/python.js.map +1 -0
  169. package/dist/parser/languages/rust.d.ts +3 -0
  170. package/dist/parser/languages/rust.d.ts.map +1 -0
  171. package/dist/parser/languages/rust.js +159 -0
  172. package/dist/parser/languages/rust.js.map +1 -0
  173. package/dist/parser/languages/typescript.d.ts +3 -0
  174. package/dist/parser/languages/typescript.d.ts.map +1 -0
  175. package/dist/parser/languages/typescript.js +1442 -0
  176. package/dist/parser/languages/typescript.js.map +1 -0
  177. package/dist/parser/parserContext.d.ts +77 -0
  178. package/dist/parser/parserContext.d.ts.map +1 -0
  179. package/dist/parser/parserContext.js +354 -0
  180. package/dist/parser/parserContext.js.map +1 -0
  181. package/dist/parser/walker.d.ts +81 -0
  182. package/dist/parser/walker.d.ts.map +1 -0
  183. package/dist/parser/walker.js +217 -0
  184. package/dist/parser/walker.js.map +1 -0
  185. package/dist/parser/worker.d.ts +66 -0
  186. package/dist/parser/worker.d.ts.map +1 -0
  187. package/dist/parser/worker.js +129 -0
  188. package/dist/parser/worker.js.map +1 -0
  189. package/dist/parser/workerpool.d.ts +107 -0
  190. package/dist/parser/workerpool.d.ts.map +1 -0
  191. package/dist/parser/workerpool.js +383 -0
  192. package/dist/parser/workerpool.js.map +1 -0
  193. package/dist/scip/format.d.ts +87 -0
  194. package/dist/scip/format.d.ts.map +1 -0
  195. package/dist/scip/format.js +31 -0
  196. package/dist/scip/format.js.map +1 -0
  197. package/dist/scip/import.d.ts +37 -0
  198. package/dist/scip/import.d.ts.map +1 -0
  199. package/dist/scip/import.js +180 -0
  200. package/dist/scip/import.js.map +1 -0
  201. package/dist/types.d.ts +392 -0
  202. package/dist/types.d.ts.map +1 -0
  203. package/dist/types.js +4 -0
  204. package/dist/types.js.map +1 -0
  205. package/docs/architecture.md +105 -0
  206. package/docs/benchmarks/methodology.md +134 -0
  207. package/docs/benchmarks/raw-results.md +71 -0
  208. package/docs/benchmarks.md +74 -0
  209. package/docs/cli.md +148 -0
  210. package/docs/examples/behavior-tests.md +70 -0
  211. package/docs/examples/change-history.md +85 -0
  212. package/docs/examples/pre-edit-context.md +81 -0
  213. package/docs/examples/service-links.md +88 -0
  214. package/docs/examples.md +80 -0
  215. package/docs/faq.md +70 -0
  216. package/docs/internals.md +104 -0
  217. package/docs/languages.md +70 -0
  218. package/docs/limits.md +52 -0
  219. package/docs/mcp.md +199 -0
  220. package/docs/quickstart.md +119 -0
  221. package/docs/testing.md +123 -0
  222. package/docs/tools.md +115 -0
  223. package/package.json +52 -0
  224. package/research-codebase.md +578 -0
  225. package/seer-cli-docs.md +326 -0
  226. package/seer-master-guide.md +246 -0
  227. package/src/bundle/ci.ts +141 -0
  228. package/src/bundle/contract.ts +387 -0
  229. package/src/bundle/export.ts +175 -0
  230. package/src/bundle/external.ts +285 -0
  231. package/src/bundle/format.ts +92 -0
  232. package/src/bundle/import.ts +157 -0
  233. package/src/cli/index.ts +1249 -0
  234. package/src/cli/init.ts +389 -0
  235. package/src/db/schema.ts +614 -0
  236. package/src/db/store.ts +4306 -0
  237. package/src/graph/pagerank.ts +53 -0
  238. package/src/indexer/architecture.ts +148 -0
  239. package/src/indexer/behavior.ts +466 -0
  240. package/src/indexer/boundaries.ts +374 -0
  241. package/src/indexer/churn.ts +58 -0
  242. package/src/indexer/classify.ts +96 -0
  243. package/src/indexer/context.ts +340 -0
  244. package/src/indexer/continuity.ts +322 -0
  245. package/src/indexer/detectchanges.ts +94 -0
  246. package/src/indexer/discovery.ts +176 -0
  247. package/src/indexer/externaldeps.ts +243 -0
  248. package/src/indexer/freshness.ts +166 -0
  249. package/src/indexer/git.ts +453 -0
  250. package/src/indexer/index.ts +1092 -0
  251. package/src/indexer/modules.ts +358 -0
  252. package/src/indexer/preflight.ts +548 -0
  253. package/src/indexer/protoScanner.ts +147 -0
  254. package/src/indexer/risk.ts +304 -0
  255. package/src/indexer/serviceHostScanner.ts +92 -0
  256. package/src/indexer/serviceLinks.ts +543 -0
  257. package/src/indexer/shapehash.ts +370 -0
  258. package/src/indexer/skeleton.ts +169 -0
  259. package/src/indexer/symbolhistory.ts +172 -0
  260. package/src/indexer/watcher.ts +206 -0
  261. package/src/mcp/server.ts +1659 -0
  262. package/src/parser/index.ts +37 -0
  263. package/src/parser/languages/cpp.ts +361 -0
  264. package/src/parser/languages/csharp.ts +235 -0
  265. package/src/parser/languages/go.ts +259 -0
  266. package/src/parser/languages/java.ts +382 -0
  267. package/src/parser/languages/python.ts +370 -0
  268. package/src/parser/languages/rust.ts +164 -0
  269. package/src/parser/languages/typescript.ts +1435 -0
  270. package/src/parser/parserContext.ts +392 -0
  271. package/src/parser/walker.ts +306 -0
  272. package/src/parser/worker.ts +181 -0
  273. package/src/parser/workerpool.ts +448 -0
  274. package/src/scip/format.ts +83 -0
  275. package/src/scip/import.ts +216 -0
  276. package/src/types.ts +457 -0
  277. package/tests/benchmark-service-links.ts +244 -0
  278. package/tests/bug-regressions.ts +626 -0
  279. package/tests/filters.ts +264 -0
  280. package/tests/fixtures/Counter.tsx +38 -0
  281. package/tests/fixtures/caller.ts +7 -0
  282. package/tests/fixtures/collisions.ts +23 -0
  283. package/tests/fixtures/local_helper.ts +5 -0
  284. package/tests/fixtures/overloads.java +17 -0
  285. package/tests/fixtures/remote_helper.ts +4 -0
  286. package/tests/fixtures/sample.c +15 -0
  287. package/tests/fixtures/sample.cpp +47 -0
  288. package/tests/fixtures/sample.cs +62 -0
  289. package/tests/fixtures/sample.go +68 -0
  290. package/tests/fixtures/sample.h +30 -0
  291. package/tests/fixtures/sample.java +85 -0
  292. package/tests/fixtures/sample.py +46 -0
  293. package/tests/fixtures/sample.rs +78 -0
  294. package/tests/fixtures/sample.ts +76 -0
  295. package/tests/fixtures-service/HttpClients.cs +30 -0
  296. package/tests/fixtures-service/HttpClients.java +24 -0
  297. package/tests/fixtures-service/billing.ts +15 -0
  298. package/tests/fixtures-service/docker-compose.yml +15 -0
  299. package/tests/fixtures-service/gateway.ts +10 -0
  300. package/tests/fixtures-service/get_user.ts +11 -0
  301. package/tests/fixtures-service/graphql_client.ts +63 -0
  302. package/tests/fixtures-service/graphql_server.ts +30 -0
  303. package/tests/fixtures-service/grpc_client.go +30 -0
  304. package/tests/fixtures-service/http_clients.go +23 -0
  305. package/tests/fixtures-service/http_clients.py +38 -0
  306. package/tests/fixtures-service/http_clients.ts +49 -0
  307. package/tests/fixtures-service/k8s/payment-service.yaml +22 -0
  308. package/tests/fixtures-service/k8s_calls.ts +20 -0
  309. package/tests/fixtures-service/messaging.ts +87 -0
  310. package/tests/fixtures-service/trpc_client.ts +39 -0
  311. package/tests/fixtures-service/trpc_server.ts +39 -0
  312. package/tests/fixtures-service/user_service.proto +33 -0
  313. package/tests/fixtures-trackcd/Cargo.toml +11 -0
  314. package/tests/fixtures-trackcd/SpringController.java +36 -0
  315. package/tests/fixtures-trackcd/auth_service.ts +19 -0
  316. package/tests/fixtures-trackcd/complex_module.py +50 -0
  317. package/tests/fixtures-trackcd/express_app.js +30 -0
  318. package/tests/fixtures-trackcd/fastapi_app.py +49 -0
  319. package/tests/fixtures-trackcd/fastify_object_routes.js +32 -0
  320. package/tests/fixtures-trackcd/go.mod +8 -0
  321. package/tests/fixtures-trackcd/package.json +15 -0
  322. package/tests/fixtures-trackcd/requirements.txt +4 -0
  323. package/tests/fixtures-trackcd/tests/auth_service.test.ts +13 -0
  324. package/tests/fixtures-tracke/auth/AuthService.ts +23 -0
  325. package/tests/fixtures-tracke/auth/crypto.ts +7 -0
  326. package/tests/fixtures-tracke/billing/Billing.ts +20 -0
  327. package/tests/fixtures-tracke/billing/Invoice.ts +10 -0
  328. package/tests/fixtures-tracke/billing/server.ts +17 -0
  329. package/tests/fixtures-tracke/package.json +7 -0
  330. package/tests/fixtures-tracke/tests/auth.test.ts +23 -0
  331. package/tests/fixtures-tracke/tests/billing.test.ts +14 -0
  332. package/tests/fixtures-trackf/package.json +5 -0
  333. package/tests/fixtures-trackf/src/auth.ts +26 -0
  334. package/tests/fixtures-trackf/src/handlers.ts +35 -0
  335. package/tests/fixtures-tracki/billing/routes.ts +12 -0
  336. package/tests/fixtures-tracki/gateway/client.ts +13 -0
  337. package/tests/git-features.ts +267 -0
  338. package/tests/init.ts +141 -0
  339. package/tests/mcp-jit.ts +130 -0
  340. package/tests/mcp-smoke.ts +191 -0
  341. package/tests/mcp-trackcd.ts +169 -0
  342. package/tests/mcp-tracke.ts +229 -0
  343. package/tests/mcp-trackf.ts +330 -0
  344. package/tests/mcp-trackg.ts +219 -0
  345. package/tests/mcp-tracki.ts +174 -0
  346. package/tests/mcp-watcher.ts +126 -0
  347. package/tests/optspec.ts +194 -0
  348. package/tests/parallel-index.ts +333 -0
  349. package/tests/parallel-read.ts +125 -0
  350. package/tests/parallel-recovery.ts +241 -0
  351. package/tests/perf-callers.ts +145 -0
  352. package/tests/query-parity.ts +184 -0
  353. package/tests/query-perf.ts +55 -0
  354. package/tests/scale-parallel-parity.ts +225 -0
  355. package/tests/scale-test.ts +523 -0
  356. package/tests/smoke.ts +396 -0
  357. package/tests/trackcd.ts +325 -0
  358. package/tests/tracke-collisions.ts +255 -0
  359. package/tests/tracke.ts +314 -0
  360. package/tests/trackf-bugs.ts +406 -0
  361. package/tests/trackf.ts +390 -0
  362. package/tests/trackg.ts +1372 -0
  363. package/tests/tracki-boundaries.ts +202 -0
  364. package/tests/tracki-continuity.ts +253 -0
  365. package/tests/tracki-contract-diff.ts +249 -0
  366. package/tests/tracki-external-bundles.ts +341 -0
  367. package/tests/tracki-preflight.ts +251 -0
  368. package/tests/verify-roles.ts +51 -0
  369. package/tests/worker-parity.ts +286 -0
  370. package/tests/worker-pool.ts +262 -0
  371. package/tsconfig.json +20 -0
@@ -0,0 +1,115 @@
1
+ import { Store } from '../db/store.js';
2
+ /**
3
+ * Deterministic edit-risk profile for a symbol.
4
+ *
5
+ * Risk is decomposed: every signal that contributes is returned alongside
6
+ * the score so an agent can see WHY the verdict is "high" instead of
7
+ * trusting the number. The exit criteria for Track-E explicitly call this
8
+ * out: "seer_risk returns decomposed deterministic signals, not unexplained
9
+ * vibes."
10
+ *
11
+ * Signals (with deterministic weights):
12
+ * directCallers +1 per caller up to 30
13
+ * transitiveCallers +ln(1 + transitive) * 4 (bounded BFS, depth 3)
14
+ * routeExposed +20 if symbol is a route handler
15
+ * directTests -10 per direct test, capped at -30 (good coverage
16
+ * reduces risk)
17
+ * indirectTests -2 per indirect test, capped at -8
18
+ * assertionCount -2 per assertion across direct tests, capped at -10
19
+ * recentCommits +ln(1 + history.length) * 4
20
+ * distinctAuthors +3 per distinct author beyond 1, capped at +15
21
+ * cyclomatic max(0, cyclomatic - 8) * 1
22
+ * cognitive max(0, cognitive - 12) * 0.5
23
+ * configKeys +3 per distinct config key, capped at +15
24
+ * moduleBoundaryCrossings +2 per distinct neighboring module, capped at +20
25
+ *
26
+ * The score is bucketed into `low` (<20), `medium` (<50), or `high` (>=50).
27
+ * The thresholds are conservative — easy to bias toward "high" — so the
28
+ * agent gets shown evidence even when the verdict is in doubt.
29
+ */
30
+ export interface RiskSignals {
31
+ directCallers: number;
32
+ transitiveCallers: number;
33
+ routeExposed: boolean;
34
+ routes: Array<{
35
+ method: string;
36
+ path: string;
37
+ framework: string;
38
+ }>;
39
+ directTests: number;
40
+ indirectTests: number;
41
+ assertionCount: number;
42
+ recentCommits: number;
43
+ distinctAuthors: number;
44
+ cyclomatic: number | null;
45
+ cognitive: number | null;
46
+ configKeys: number;
47
+ moduleBoundaryCrossings: number;
48
+ /**
49
+ * v8 Track-G — number of distinct outbound service calls this symbol makes
50
+ * (e.g. fetch/axios.get calls). Higher = symbol depends on more external
51
+ * services, which is a real risk surface for edits.
52
+ */
53
+ outboundServiceCalls: number;
54
+ /**
55
+ * v8 Track-G — number of inbound service_links pointing at this symbol as
56
+ * the handler. Higher = changes here likely affect other services.
57
+ */
58
+ inboundServiceLinks: number;
59
+ /**
60
+ * v8 Track-G — number of service_links whose handler lives in a different
61
+ * module than the caller. Cross-module client/handler dependency is a sign
62
+ * of architectural distance and risk.
63
+ */
64
+ crossModuleServiceLinks: number;
65
+ /**
66
+ * v8 Track-G — service_links involving this symbol whose match_kind is
67
+ * route_pattern (not literal_path). Pattern-only matches carry residual
68
+ * ambiguity and are worth surfacing as a soft signal.
69
+ */
70
+ ambiguousServiceLinks: number;
71
+ /**
72
+ * v10 — number of distinct neighboring boundaries this symbol's call graph
73
+ * reaches OUT of its own boundary. Advisory; never raises the verdict by
74
+ * itself.
75
+ */
76
+ boundaryCrossings: number;
77
+ }
78
+ export interface RiskResult {
79
+ symbol: {
80
+ id: number;
81
+ name: string;
82
+ qualifiedName: string | null;
83
+ kind: string;
84
+ file: string;
85
+ lineStart: number;
86
+ lineEnd: number;
87
+ };
88
+ risk: 'low' | 'medium' | 'high';
89
+ score: number;
90
+ signals: RiskSignals;
91
+ signalContributions: Array<{
92
+ signal: string;
93
+ value: number;
94
+ contribution: number;
95
+ }>;
96
+ /** Module the symbol's file belongs to, when clustering has run. */
97
+ module: {
98
+ id: number;
99
+ label: string;
100
+ } | null;
101
+ /** v10 boundary the symbol's file belongs to. NULL when none detected. */
102
+ boundary: {
103
+ id: number;
104
+ label: string;
105
+ kind: string;
106
+ rootRelPath: string;
107
+ } | null;
108
+ source: 'tree-sitter';
109
+ }
110
+ interface RiskOptions {
111
+ callerDepth?: number;
112
+ }
113
+ export declare function computeRisk(store: Store, nameOrId: string | number, options?: RiskOptions): RiskResult | null;
114
+ export {};
115
+ //# sourceMappingURL=risk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"risk.d.ts","sourceRoot":"","sources":["../../src/indexer/risk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAIvC;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnE,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,uBAAuB,EAAE,MAAM,CAAC;IAChC;;;;OAIG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,uBAAuB,EAAE,MAAM,CAAC;IAChC;;;;OAIG;IACH,qBAAqB,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE;QACN,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,CAAC;IACrB,mBAAmB,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpF,oEAAoE;IACpE,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7C,0EAA0E;IAC1E,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAClF,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,UAAU,WAAW;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,GAAG,MAAM,EACzB,OAAO,GAAE,WAAgB,GACxB,UAAU,GAAG,IAAI,CA0InB"}
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.computeRisk = computeRisk;
4
+ const behavior_js_1 = require("./behavior.js");
5
+ function computeRisk(store, nameOrId, options = {}) {
6
+ const callerDepth = options.callerDepth ?? 3;
7
+ let target = null;
8
+ if (typeof nameOrId === 'number') {
9
+ target = store.getSymbolById(nameOrId);
10
+ }
11
+ else {
12
+ const defs = store.getDefinition(nameOrId);
13
+ if (defs.length === 0)
14
+ return null;
15
+ target = defs[0];
16
+ }
17
+ if (!target)
18
+ return null;
19
+ // Direct + transitive callers (call graph fan-in).
20
+ // ID-based count so short-name siblings (Alpha.run vs Beta.run) don't
21
+ // inflate this symbol's fan-in.
22
+ const directCallers = store.countCallersById(target.id);
23
+ const transitiveRows = store.reverseReachableWithDepth(target.id, callerDepth);
24
+ // Exclude direct callers from the transitive count so we don't double-count.
25
+ const transitiveCallers = transitiveRows.filter(r => r.depth > 1).length;
26
+ // Route exposure.
27
+ const routes = store.routesForHandler(target.id);
28
+ const routeExposed = routes.length > 0;
29
+ // Behavioral coverage — reuse the ranked behavior since it already does
30
+ // direct vs indirect deduplication and assertion counting.
31
+ const behavior = (0, behavior_js_1.rankedBehavior)(store, target.id, { limit: 200 });
32
+ const directTests = behavior?.direct ?? 0;
33
+ const indirectTests = behavior?.indirect ?? 0;
34
+ const assertionCount = sumAssertions(behavior);
35
+ // Symbol history.
36
+ const historyRows = store.getSymbolHistory(target.id, { limit: 200 });
37
+ const recentCommits = historyRows.length;
38
+ const distinctAuthors = new Set(historyRows.map(h => (h.authorEmail ?? h.authorName ?? '').toLowerCase()).filter(s => s)).size;
39
+ // Complexity.
40
+ const cyclomatic = target.cyclomatic ?? null;
41
+ const cognitive = target.cognitive ?? null;
42
+ // Config reads.
43
+ const configKeys = store.configKeysForSymbol(target.id).length;
44
+ // Module-boundary crossings: how many distinct neighbor modules this
45
+ // symbol's call graph reaches OUT of its own module.
46
+ const myFileModule = store.moduleForFile(target.fileId);
47
+ let moduleBoundaryCrossings = 0;
48
+ if (myFileModule) {
49
+ const neighborModules = new Set(store.calleeModulesOf(target.id)
50
+ .filter(m => m.moduleId !== myFileModule.id)
51
+ .map(m => m.moduleId));
52
+ moduleBoundaryCrossings = neighborModules.size;
53
+ }
54
+ // v8 Track-G service-link signals.
55
+ let outboundServiceCalls = 0;
56
+ let inboundServiceLinks = 0;
57
+ let crossModuleServiceLinks = 0;
58
+ let ambiguousServiceLinks = 0;
59
+ try {
60
+ outboundServiceCalls = store.listServiceCalls({ callerSymbolId: target.id, limit: 1000 }).length;
61
+ }
62
+ catch { /* */ }
63
+ try {
64
+ const inbound = store.serviceLinksForHandler(target.id, { limit: 1000 });
65
+ inboundServiceLinks = inbound.length;
66
+ ambiguousServiceLinks += inbound.filter(l => l.matchKind === 'route_pattern').length;
67
+ if (myFileModule) {
68
+ for (const link of inbound) {
69
+ if (link.callerSymbolId == null)
70
+ continue;
71
+ const callerSym = store.getSymbolById(link.callerSymbolId);
72
+ if (!callerSym)
73
+ continue;
74
+ const callerMod = store.moduleForFile(callerSym.fileId);
75
+ if (callerMod && callerMod.id !== myFileModule.id)
76
+ crossModuleServiceLinks++;
77
+ }
78
+ }
79
+ }
80
+ catch { /* */ }
81
+ try {
82
+ const outbound = store.serviceLinksForCaller(target.id, { limit: 1000 });
83
+ ambiguousServiceLinks += outbound.filter(l => l.matchKind === 'route_pattern').length;
84
+ if (myFileModule) {
85
+ for (const link of outbound) {
86
+ if (link.handlerSymbolId == null)
87
+ continue;
88
+ const handlerSym = store.getSymbolById(link.handlerSymbolId);
89
+ if (!handlerSym)
90
+ continue;
91
+ const handlerMod = store.moduleForFile(handlerSym.fileId);
92
+ if (handlerMod && handlerMod.id !== myFileModule.id)
93
+ crossModuleServiceLinks++;
94
+ }
95
+ }
96
+ }
97
+ catch { /* */ }
98
+ // v10 — boundary crossings (calls into another package/service boundary).
99
+ let boundaryCrossings = 0;
100
+ const myBoundary = store.boundaryForFile(target.fileId);
101
+ if (myBoundary) {
102
+ const neighborBoundaries = new Set(store.calleeBoundariesOf(target.id)
103
+ .filter(b => b.boundaryId !== myBoundary.id)
104
+ .map(b => b.boundaryId));
105
+ boundaryCrossings = neighborBoundaries.size;
106
+ }
107
+ const signals = {
108
+ directCallers, transitiveCallers, routeExposed, routes,
109
+ directTests, indirectTests, assertionCount,
110
+ recentCommits, distinctAuthors,
111
+ cyclomatic, cognitive,
112
+ configKeys, moduleBoundaryCrossings,
113
+ outboundServiceCalls, inboundServiceLinks,
114
+ crossModuleServiceLinks, ambiguousServiceLinks,
115
+ boundaryCrossings,
116
+ };
117
+ const contributions = scoreContributions(signals);
118
+ const score = contributions.reduce((acc, c) => acc + c.contribution, 0);
119
+ const risk = score >= 50 ? 'high' : score >= 20 ? 'medium' : 'low';
120
+ return {
121
+ symbol: {
122
+ id: target.id,
123
+ name: target.name,
124
+ qualifiedName: target.qualifiedName,
125
+ kind: target.kind,
126
+ file: target.filePath,
127
+ lineStart: target.lineStart,
128
+ lineEnd: target.lineEnd,
129
+ },
130
+ risk, score, signals,
131
+ signalContributions: contributions,
132
+ module: myFileModule,
133
+ boundary: myBoundary,
134
+ source: 'tree-sitter',
135
+ };
136
+ }
137
+ function sumAssertions(b) {
138
+ if (!b)
139
+ return 0;
140
+ let n = 0;
141
+ for (const t of b.tests) {
142
+ if (t.relationship === 'direct-call')
143
+ n += t.assertionCount;
144
+ }
145
+ return n;
146
+ }
147
+ function scoreContributions(s) {
148
+ const out = [];
149
+ out.push({ signal: 'directCallers', value: s.directCallers,
150
+ contribution: Math.min(30, s.directCallers) });
151
+ out.push({ signal: 'transitiveCallers', value: s.transitiveCallers,
152
+ contribution: Math.log1p(s.transitiveCallers) * 4 });
153
+ out.push({ signal: 'routeExposed', value: s.routeExposed ? 1 : 0,
154
+ contribution: s.routeExposed ? 20 : 0 });
155
+ // Coverage reduces risk (negative contribution).
156
+ out.push({ signal: 'directTests', value: s.directTests,
157
+ contribution: -Math.min(30, s.directTests * 10) });
158
+ out.push({ signal: 'indirectTests', value: s.indirectTests,
159
+ contribution: -Math.min(8, s.indirectTests * 2) });
160
+ out.push({ signal: 'assertionCount', value: s.assertionCount,
161
+ contribution: -Math.min(10, s.assertionCount * 2) });
162
+ out.push({ signal: 'recentCommits', value: s.recentCommits,
163
+ contribution: Math.log1p(s.recentCommits) * 4 });
164
+ out.push({ signal: 'distinctAuthors', value: s.distinctAuthors,
165
+ contribution: s.distinctAuthors <= 1 ? 0 : Math.min(15, (s.distinctAuthors - 1) * 3) });
166
+ out.push({ signal: 'cyclomatic', value: s.cyclomatic ?? 0,
167
+ contribution: s.cyclomatic == null ? 0 : Math.max(0, s.cyclomatic - 8) });
168
+ out.push({ signal: 'cognitive', value: s.cognitive ?? 0,
169
+ contribution: s.cognitive == null ? 0 : Math.max(0, s.cognitive - 12) * 0.5 });
170
+ out.push({ signal: 'configKeys', value: s.configKeys,
171
+ contribution: Math.min(15, s.configKeys * 3) });
172
+ out.push({ signal: 'moduleBoundaryCrossings', value: s.moduleBoundaryCrossings,
173
+ contribution: Math.min(20, s.moduleBoundaryCrossings * 2) });
174
+ // v8 Track-G — service-link contributions. Conservative weights so they
175
+ // surface as evidence without dominating the score on small fixtures.
176
+ out.push({ signal: 'outboundServiceCalls', value: s.outboundServiceCalls,
177
+ contribution: Math.min(10, s.outboundServiceCalls * 2) });
178
+ out.push({ signal: 'inboundServiceLinks', value: s.inboundServiceLinks,
179
+ contribution: Math.min(15, s.inboundServiceLinks * 3) });
180
+ out.push({ signal: 'crossModuleServiceLinks', value: s.crossModuleServiceLinks,
181
+ contribution: Math.min(10, s.crossModuleServiceLinks * 2) });
182
+ out.push({ signal: 'ambiguousServiceLinks', value: s.ambiguousServiceLinks,
183
+ contribution: Math.min(5, s.ambiguousServiceLinks * 1) });
184
+ // v10 boundary crossings — advisory weight: 1.5 per crossing, capped at 12.
185
+ out.push({ signal: 'boundaryCrossings', value: s.boundaryCrossings,
186
+ contribution: Math.min(12, s.boundaryCrossings * 1.5) });
187
+ // Round contributions for stable output.
188
+ return out.map(c => ({ ...c, contribution: roundTo(c.contribution, 2) }));
189
+ }
190
+ function roundTo(n, decimals) {
191
+ const f = Math.pow(10, decimals);
192
+ return Math.round(n * f) / f;
193
+ }
194
+ //# sourceMappingURL=risk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"risk.js","sourceRoot":"","sources":["../../src/indexer/risk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * v9 Track-H — extract service hostnames from Kubernetes manifests and
3
+ * Docker Compose files.
4
+ *
5
+ * The result is a {hostname → file_path[]} map: e.g. "payment-service" was
6
+ * declared in `k8s/payment.yaml`. The resolver uses this to boost confidence
7
+ * on HTTP service_calls whose host_hint matches one of these names — it's
8
+ * evidence, not proof. We only emit a `service_host` link when the call's
9
+ * PATH also matches a route in the workspace (host alone is too noisy).
10
+ *
11
+ * The scanner is intentionally regex-based (no YAML parser dependency) and
12
+ * forgiving — it extracts top-level `name:` values from any document that
13
+ * looks like a `kind: Service` declaration, plus the keys of `services:` in
14
+ * Docker Compose. Unknown YAMLs are skipped silently.
15
+ */
16
+ export interface ServiceHostMap {
17
+ /** lowercase hostname → list of file paths where it was declared */
18
+ hosts: Map<string, string[]>;
19
+ }
20
+ /**
21
+ * Scan a workspace for k8s/Docker service hostnames. Returns the empty map
22
+ * when none are found — callers should treat missing entries as "no boost".
23
+ */
24
+ export declare function scanServiceHosts(absRoot: string): Promise<ServiceHostMap>;
25
+ //# sourceMappingURL=serviceHostScanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serviceHostScanner.d.ts","sourceRoot":"","sources":["../../src/indexer/serviceHostScanner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,MAAM,WAAW,cAAc;IAC7B,oEAAoE;IACpE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC9B;AAQD;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAwD/E"}
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ /**
3
+ * v9 Track-H — extract service hostnames from Kubernetes manifests and
4
+ * Docker Compose files.
5
+ *
6
+ * The result is a {hostname → file_path[]} map: e.g. "payment-service" was
7
+ * declared in `k8s/payment.yaml`. The resolver uses this to boost confidence
8
+ * on HTTP service_calls whose host_hint matches one of these names — it's
9
+ * evidence, not proof. We only emit a `service_host` link when the call's
10
+ * PATH also matches a route in the workspace (host alone is too noisy).
11
+ *
12
+ * The scanner is intentionally regex-based (no YAML parser dependency) and
13
+ * forgiving — it extracts top-level `name:` values from any document that
14
+ * looks like a `kind: Service` declaration, plus the keys of `services:` in
15
+ * Docker Compose. Unknown YAMLs are skipped silently.
16
+ */
17
+ var __importDefault = (this && this.__importDefault) || function (mod) {
18
+ return (mod && mod.__esModule) ? mod : { "default": mod };
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.scanServiceHosts = scanServiceHosts;
22
+ const fs_1 = __importDefault(require("fs"));
23
+ const path_1 = __importDefault(require("path"));
24
+ const fast_glob_1 = __importDefault(require("fast-glob"));
25
+ const K8S_SERVICE_RE = /(?:^|\n)\s*kind\s*:\s*Service[\s\S]*?(?:^|\n)\s*metadata\s*:[\s\S]*?(?:^|\n)\s*name\s*:\s*["']?([A-Za-z0-9_-]+)["']?/g;
26
+ const COMPOSE_SERVICES_RE = /(?:^|\n)services\s*:\s*\n((?:[ \t]+[A-Za-z0-9_-][^\n]*\n?)+)/g;
27
+ /**
28
+ * Scan a workspace for k8s/Docker service hostnames. Returns the empty map
29
+ * when none are found — callers should treat missing entries as "no boost".
30
+ */
31
+ async function scanServiceHosts(absRoot) {
32
+ const entries = await (0, fast_glob_1.default)([
33
+ '**/*.yaml', '**/*.yml',
34
+ '**/docker-compose*.yml', '**/docker-compose*.yaml',
35
+ ], {
36
+ cwd: absRoot,
37
+ ignore: [
38
+ 'node_modules/**', '.git/**', 'dist/**', 'build/**', 'out/**',
39
+ 'vendor/**', '**/vendor/**', '**/__pycache__/**', '.next/**',
40
+ ],
41
+ onlyFiles: true, followSymbolicLinks: false, dot: false,
42
+ });
43
+ entries.sort();
44
+ const hosts = new Map();
45
+ const record = (name, filePath) => {
46
+ if (!name)
47
+ return;
48
+ const key = name.toLowerCase();
49
+ const list = hosts.get(key);
50
+ if (list) {
51
+ if (!list.includes(filePath))
52
+ list.push(filePath);
53
+ }
54
+ else
55
+ hosts.set(key, [filePath]);
56
+ };
57
+ for (const rel of entries) {
58
+ const abs = path_1.default.join(absRoot, rel);
59
+ let src;
60
+ try {
61
+ src = fs_1.default.readFileSync(abs, 'utf8');
62
+ }
63
+ catch {
64
+ continue;
65
+ }
66
+ // ── Kubernetes `kind: Service` ──────────────────────────────────────
67
+ K8S_SERVICE_RE.lastIndex = 0;
68
+ let m;
69
+ while ((m = K8S_SERVICE_RE.exec(src)) !== null)
70
+ record(m[1], rel);
71
+ // ── Docker Compose `services:` ─────────────────────────────────────
72
+ const isCompose = /(?:^|[/\\])docker-compose[^/\\]*\.ya?ml$/i.test(rel) ||
73
+ /(?:^|\n)version\s*:/m.test(src) && /(?:^|\n)services\s*:/m.test(src);
74
+ if (isCompose) {
75
+ COMPOSE_SERVICES_RE.lastIndex = 0;
76
+ let s;
77
+ while ((s = COMPOSE_SERVICES_RE.exec(src)) !== null) {
78
+ const block = s[1];
79
+ // Pull top-level service keys: lines like " name:" with 2-4 space indent.
80
+ const lines = block.split('\n');
81
+ for (const line of lines) {
82
+ const km = line.match(/^([ \t]+)([A-Za-z0-9_-]+)\s*:/);
83
+ if (!km)
84
+ continue;
85
+ // Only first-level keys (consistent indent across the services block).
86
+ // We accept indent ≤ 4 spaces / 1 tab.
87
+ if (km[1].length <= 4)
88
+ record(km[2], rel);
89
+ }
90
+ }
91
+ }
92
+ }
93
+ return { hosts };
94
+ }
95
+ //# sourceMappingURL=serviceHostScanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serviceHostScanner.js","sourceRoot":"","sources":["../../src/indexer/serviceHostScanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Track G — service-link resolver and helpers.
3
+ *
4
+ * Two concerns live here, kept independent so they can be unit-tested in
5
+ * isolation:
6
+ *
7
+ * 1. `normalizeHttpTarget(raw)` — turn a string captured at a client call
8
+ * site (literal URL, template path, env-prefixed concat) into a
9
+ * `{ path, hostHint, envKey }` triple where each field is undefined when
10
+ * it can't be confidently recovered. Pure function; no DB access.
11
+ *
12
+ * 2. `routePatternsMatch(callPath, routePath)` — decide whether a literal
13
+ * caller path matches a (possibly parameterised) framework route.
14
+ * Returns a `{ matched, confidence, reason }` result so the resolver
15
+ * can ranke evidence without recomputing it.
16
+ *
17
+ * 3. `resolveServiceLinks(store)` — the actual post-index resolver.
18
+ * Wipes prior service_links, scans service_calls + routes, and inserts
19
+ * one row per confident rendezvous.
20
+ *
21
+ * Deterministic by construction: the resolver runs candidates in id order
22
+ * and only emits a top match (with ambiguity recorded as evidence) so two
23
+ * runs of the same DB produce the same service_links rows.
24
+ */
25
+ import type { Store } from '../db/store.js';
26
+ import type { ServiceHostMap } from './serviceHostScanner.js';
27
+ export type MatchKind = 'literal_path' | 'env_base' | 'service_host' | 'route_pattern' | 'trpc_procedure' | 'graphql_operation' | 'grpc_method' | 'topic_match' | 'queue_match' | 'exchange_match';
28
+ export interface NormalizedTarget {
29
+ /** /api/users — leading slash, no scheme, no query, no fragment, no trailing slash (except "/"). */
30
+ path?: string;
31
+ /** payment-service / billing.svc.cluster.local / etc. */
32
+ hostHint?: string;
33
+ /** PAYMENT_URL — populated by the extractor when it saw env reference. */
34
+ envKey?: string;
35
+ }
36
+ /**
37
+ * Normalize an HTTP target captured at a client call site.
38
+ *
39
+ * Rules:
40
+ * - strip scheme + host when literal (`https://payment/api/charge` → `/api/charge`, host = `payment`)
41
+ * - keep route paths starting with '/'
42
+ * - drop query string and fragment
43
+ * - normalize trailing slash (but keep root '/'): '/api/users/' → '/api/users'
44
+ * - drop empty paths
45
+ * - do NOT collapse dynamic segments — that's the route-pattern matcher's job.
46
+ */
47
+ export declare function normalizeHttpTarget(raw: string): NormalizedTarget;
48
+ export interface PatternMatch {
49
+ matched: boolean;
50
+ /** 1.0 for exact path+method, 0.95 path only, 0.85 parameterised */
51
+ confidence: number;
52
+ /** Human-readable why; surfaced in evidence_json. */
53
+ reason: string;
54
+ }
55
+ /**
56
+ * Decide whether `callPath` (literal) satisfies a (possibly parameterised)
57
+ * `routePath` like `/users/:id`, `/users/{id}`, `/items/<int:n>`.
58
+ *
59
+ * No method check here — the resolver applies method comparison around this
60
+ * with method-mismatch falling back to a lower confidence.
61
+ *
62
+ * Returns matched=false when the segment count differs OR a literal segment
63
+ * differs. Parameter segments (`:x`, `{x}`, `<...:x>`) match any one segment.
64
+ */
65
+ export declare function routePatternsMatch(callPath: string, routePath: string): PatternMatch;
66
+ /**
67
+ * Compare two HTTP methods, treating 'ANY' (client unknown method) and route's
68
+ * absence of method as wildcards. Returns:
69
+ * 1.0 — methods match exactly (including both 'ANY')
70
+ * 0.9 — caller method known + route is ANY (or vice versa)
71
+ * 0.0 — explicit mismatch (e.g. POST vs GET)
72
+ */
73
+ export declare function methodMatchScore(callMethod: string | null | undefined, routeMethod: string | null | undefined): number;
74
+ /** Result returned by resolveServiceLinks. */
75
+ export interface ResolveResult {
76
+ /** Total service_calls considered (after dropping ones with no path). */
77
+ callsConsidered: number;
78
+ /** New service_links rows inserted. */
79
+ linksInserted: number;
80
+ /** Counts by match_kind. */
81
+ byKind: Record<MatchKind, number>;
82
+ /** v9 Track-H — number of calls whose candidate set was truncated at the
83
+ * ambiguity cap. Surfaced for telemetry / debug. */
84
+ truncated?: number;
85
+ }
86
+ /**
87
+ * Wipe service_links and rebuild from current service_calls + routes.
88
+ * Deterministic: orders candidates by id ascending and ties are broken by id.
89
+ *
90
+ * Match strategy:
91
+ * 1. literal_path — call.path == route.path, method compatible
92
+ * 2. route_pattern — call.path matches a parameterised route, method compatible
93
+ * 3. env_base — call carried an env key; we record the link only when
94
+ * the path *also* matches a route (env alone is not enough).
95
+ *
96
+ * S3 (service_host) — k8s/Docker host resolution — is provided by
97
+ * `scanServiceHosts()` and passed in as optional evidence.
98
+ */
99
+ export declare function resolveServiceLinks(store: Store, options?: {
100
+ hostMap?: ServiceHostMap;
101
+ }): ResolveResult;
102
+ /** Apply the same normalization to a route path as to a call path so the
103
+ * byExactPath comparison is symmetric (strip trailing slash, etc). */
104
+ export declare function normalizeRoutePath(p: string): string;
105
+ //# sourceMappingURL=serviceLinks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serviceLinks.d.ts","sourceRoot":"","sources":["../../src/indexer/serviceLinks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAE9D,MAAM,MAAM,SAAS,GACjB,cAAc,GACd,UAAU,GACV,cAAc,GACd,eAAe,GAEf,gBAAgB,GAChB,mBAAmB,GACnB,aAAa,GACb,aAAa,GACb,aAAa,GACb,gBAAgB,CAAC;AAErB,MAAM,WAAW,gBAAgB;IAC/B,oGAAoG;IACpG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAqCjE;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,CAyBpF;AAUD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACrC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAM/E;AAID,8CAA8C;AAC9C,MAAM,WAAW,aAAa;IAC5B,yEAAyE;IACzE,eAAe,EAAE,MAAM,CAAC;IACxB,uCAAuC;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAClC;yDACqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAYD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,cAAc,CAAA;CAAO,GAAG,aAAa,CA6T3G;AAWD;uEACuE;AACvE,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAKpD"}