@untangle-code/cli 0.0.0-stage → 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 (571) hide show
  1. package/LICENSE +661 -0
  2. package/NOTICE +90 -0
  3. package/README.md +424 -2
  4. package/THIRD_PARTY_LICENSES.md +152 -0
  5. package/dist/cli/args.d.ts +48 -0
  6. package/dist/cli/args.d.ts.map +1 -0
  7. package/dist/cli/args.js +167 -0
  8. package/dist/cli/args.js.map +1 -0
  9. package/dist/cli/command.d.ts +69 -0
  10. package/dist/cli/command.d.ts.map +1 -0
  11. package/dist/cli/command.js +82 -0
  12. package/dist/cli/command.js.map +1 -0
  13. package/dist/cli/deadline.d.ts +33 -0
  14. package/dist/cli/deadline.d.ts.map +1 -0
  15. package/dist/cli/deadline.js +49 -0
  16. package/dist/cli/deadline.js.map +1 -0
  17. package/dist/cli/embedder-deadline.d.ts +72 -0
  18. package/dist/cli/embedder-deadline.d.ts.map +1 -0
  19. package/dist/cli/embedder-deadline.js +117 -0
  20. package/dist/cli/embedder-deadline.js.map +1 -0
  21. package/dist/cli/exit.d.ts +71 -0
  22. package/dist/cli/exit.d.ts.map +1 -0
  23. package/dist/cli/exit.js +81 -0
  24. package/dist/cli/exit.js.map +1 -0
  25. package/dist/cli/graphs.d.ts +65 -0
  26. package/dist/cli/graphs.d.ts.map +1 -0
  27. package/dist/cli/graphs.js +108 -0
  28. package/dist/cli/graphs.js.map +1 -0
  29. package/dist/cli/index-freshness.d.ts +13 -0
  30. package/dist/cli/index-freshness.d.ts.map +1 -0
  31. package/dist/cli/index-freshness.js +226 -0
  32. package/dist/cli/index-freshness.js.map +1 -0
  33. package/dist/cli/index-refresh.d.ts +10 -0
  34. package/dist/cli/index-refresh.d.ts.map +1 -0
  35. package/dist/cli/index-refresh.js +76 -0
  36. package/dist/cli/index-refresh.js.map +1 -0
  37. package/dist/cli/index-state.d.ts +184 -0
  38. package/dist/cli/index-state.d.ts.map +1 -0
  39. package/dist/cli/index-state.js +852 -0
  40. package/dist/cli/index-state.js.map +1 -0
  41. package/dist/cli/io.d.ts +29 -0
  42. package/dist/cli/io.d.ts.map +1 -0
  43. package/dist/cli/io.js +42 -0
  44. package/dist/cli/io.js.map +1 -0
  45. package/dist/cli/language-support.d.ts +77 -0
  46. package/dist/cli/language-support.d.ts.map +1 -0
  47. package/dist/cli/language-support.js +152 -0
  48. package/dist/cli/language-support.js.map +1 -0
  49. package/dist/cli/renewing-lease.d.ts +26 -0
  50. package/dist/cli/renewing-lease.d.ts.map +1 -0
  51. package/dist/cli/renewing-lease.js +102 -0
  52. package/dist/cli/renewing-lease.js.map +1 -0
  53. package/dist/cli/search-graph-enrichment.d.ts +16 -0
  54. package/dist/cli/search-graph-enrichment.d.ts.map +1 -0
  55. package/dist/cli/search-graph-enrichment.js +428 -0
  56. package/dist/cli/search-graph-enrichment.js.map +1 -0
  57. package/dist/cli/system.d.ts +34 -0
  58. package/dist/cli/system.d.ts.map +1 -0
  59. package/dist/cli/system.js +89 -0
  60. package/dist/cli/system.js.map +1 -0
  61. package/dist/cli/vector-store-policy.d.ts +116 -0
  62. package/dist/cli/vector-store-policy.d.ts.map +1 -0
  63. package/dist/cli/vector-store-policy.js +160 -0
  64. package/dist/cli/vector-store-policy.js.map +1 -0
  65. package/dist/cli/version.d.ts +3 -0
  66. package/dist/cli/version.d.ts.map +1 -0
  67. package/dist/cli/version.js +3 -0
  68. package/dist/cli/version.js.map +1 -0
  69. package/dist/cli/workspace.d.ts +105 -0
  70. package/dist/cli/workspace.d.ts.map +1 -0
  71. package/dist/cli/workspace.js +215 -0
  72. package/dist/cli/workspace.js.map +1 -0
  73. package/dist/commands/complexity.d.ts +72 -0
  74. package/dist/commands/complexity.d.ts.map +1 -0
  75. package/dist/commands/complexity.js +580 -0
  76. package/dist/commands/complexity.js.map +1 -0
  77. package/dist/commands/doctor.d.ts +66 -0
  78. package/dist/commands/doctor.d.ts.map +1 -0
  79. package/dist/commands/doctor.js +764 -0
  80. package/dist/commands/doctor.js.map +1 -0
  81. package/dist/commands/doctor.languages.d.ts +37 -0
  82. package/dist/commands/doctor.languages.d.ts.map +1 -0
  83. package/dist/commands/doctor.languages.js +143 -0
  84. package/dist/commands/doctor.languages.js.map +1 -0
  85. package/dist/commands/doctor.storage.d.ts +17 -0
  86. package/dist/commands/doctor.storage.d.ts.map +1 -0
  87. package/dist/commands/doctor.storage.js +91 -0
  88. package/dist/commands/doctor.storage.js.map +1 -0
  89. package/dist/commands/extensions/add.d.ts +10 -0
  90. package/dist/commands/extensions/add.d.ts.map +1 -0
  91. package/dist/commands/extensions/add.js +213 -0
  92. package/dist/commands/extensions/add.js.map +1 -0
  93. package/dist/commands/extensions/configure.d.ts +5 -0
  94. package/dist/commands/extensions/configure.d.ts.map +1 -0
  95. package/dist/commands/extensions/configure.js +58 -0
  96. package/dist/commands/extensions/configure.js.map +1 -0
  97. package/dist/commands/extensions/container.d.ts +15 -0
  98. package/dist/commands/extensions/container.d.ts.map +1 -0
  99. package/dist/commands/extensions/container.js +135 -0
  100. package/dist/commands/extensions/container.js.map +1 -0
  101. package/dist/commands/extensions/context.d.ts +37 -0
  102. package/dist/commands/extensions/context.d.ts.map +1 -0
  103. package/dist/commands/extensions/context.js +72 -0
  104. package/dist/commands/extensions/context.js.map +1 -0
  105. package/dist/commands/extensions/enable.d.ts +6 -0
  106. package/dist/commands/extensions/enable.d.ts.map +1 -0
  107. package/dist/commands/extensions/enable.js +180 -0
  108. package/dist/commands/extensions/enable.js.map +1 -0
  109. package/dist/commands/extensions/environment.d.ts +74 -0
  110. package/dist/commands/extensions/environment.d.ts.map +1 -0
  111. package/dist/commands/extensions/environment.js +168 -0
  112. package/dist/commands/extensions/environment.js.map +1 -0
  113. package/dist/commands/extensions/feature-scan.d.ts +48 -0
  114. package/dist/commands/extensions/feature-scan.d.ts.map +1 -0
  115. package/dist/commands/extensions/feature-scan.js +156 -0
  116. package/dist/commands/extensions/feature-scan.js.map +1 -0
  117. package/dist/commands/extensions/invoke.d.ts +60 -0
  118. package/dist/commands/extensions/invoke.d.ts.map +1 -0
  119. package/dist/commands/extensions/invoke.js +275 -0
  120. package/dist/commands/extensions/invoke.js.map +1 -0
  121. package/dist/commands/extensions/list.d.ts +5 -0
  122. package/dist/commands/extensions/list.d.ts.map +1 -0
  123. package/dist/commands/extensions/list.js +125 -0
  124. package/dist/commands/extensions/list.js.map +1 -0
  125. package/dist/commands/extensions/logs.d.ts +5 -0
  126. package/dist/commands/extensions/logs.d.ts.map +1 -0
  127. package/dist/commands/extensions/logs.js +74 -0
  128. package/dist/commands/extensions/logs.js.map +1 -0
  129. package/dist/commands/extensions/provision.d.ts +36 -0
  130. package/dist/commands/extensions/provision.d.ts.map +1 -0
  131. package/dist/commands/extensions/provision.js +137 -0
  132. package/dist/commands/extensions/provision.js.map +1 -0
  133. package/dist/commands/extensions/remove.d.ts +5 -0
  134. package/dist/commands/extensions/remove.d.ts.map +1 -0
  135. package/dist/commands/extensions/remove.js +77 -0
  136. package/dist/commands/extensions/remove.js.map +1 -0
  137. package/dist/commands/extensions/render.d.ts +16 -0
  138. package/dist/commands/extensions/render.d.ts.map +1 -0
  139. package/dist/commands/extensions/render.js +25 -0
  140. package/dist/commands/extensions/render.js.map +1 -0
  141. package/dist/commands/extensions/run.d.ts +30 -0
  142. package/dist/commands/extensions/run.d.ts.map +1 -0
  143. package/dist/commands/extensions/run.js +292 -0
  144. package/dist/commands/extensions/run.js.map +1 -0
  145. package/dist/commands/extensions/secret-store.d.ts +15 -0
  146. package/dist/commands/extensions/secret-store.d.ts.map +1 -0
  147. package/dist/commands/extensions/secret-store.js +164 -0
  148. package/dist/commands/extensions/secret-store.js.map +1 -0
  149. package/dist/commands/extensions/setup.d.ts +17 -0
  150. package/dist/commands/extensions/setup.d.ts.map +1 -0
  151. package/dist/commands/extensions/setup.js +94 -0
  152. package/dist/commands/extensions/setup.js.map +1 -0
  153. package/dist/commands/extensions/source.d.ts +47 -0
  154. package/dist/commands/extensions/source.d.ts.map +1 -0
  155. package/dist/commands/extensions/source.js +142 -0
  156. package/dist/commands/extensions/source.js.map +1 -0
  157. package/dist/commands/extensions/state.d.ts +62 -0
  158. package/dist/commands/extensions/state.d.ts.map +1 -0
  159. package/dist/commands/extensions/state.js +177 -0
  160. package/dist/commands/extensions/state.js.map +1 -0
  161. package/dist/commands/extensions/status.d.ts +9 -0
  162. package/dist/commands/extensions/status.d.ts.map +1 -0
  163. package/dist/commands/extensions/status.js +239 -0
  164. package/dist/commands/extensions/status.js.map +1 -0
  165. package/dist/commands/extensions.d.ts +3 -0
  166. package/dist/commands/extensions.d.ts.map +1 -0
  167. package/dist/commands/extensions.js +223 -0
  168. package/dist/commands/extensions.js.map +1 -0
  169. package/dist/commands/flow/index.d.ts +3 -0
  170. package/dist/commands/flow/index.d.ts.map +1 -0
  171. package/dist/commands/flow/index.js +295 -0
  172. package/dist/commands/flow/index.js.map +1 -0
  173. package/dist/commands/flow/limits.d.ts +12 -0
  174. package/dist/commands/flow/limits.d.ts.map +1 -0
  175. package/dist/commands/flow/limits.js +13 -0
  176. package/dist/commands/flow/limits.js.map +1 -0
  177. package/dist/commands/flow/output.d.ts +8 -0
  178. package/dist/commands/flow/output.d.ts.map +1 -0
  179. package/dist/commands/flow/output.js +11 -0
  180. package/dist/commands/flow/output.js.map +1 -0
  181. package/dist/commands/flow/render.d.ts +51 -0
  182. package/dist/commands/flow/render.d.ts.map +1 -0
  183. package/dist/commands/flow/render.js +220 -0
  184. package/dist/commands/flow/render.js.map +1 -0
  185. package/dist/commands/flow/select.d.ts +31 -0
  186. package/dist/commands/flow/select.d.ts.map +1 -0
  187. package/dist/commands/flow/select.js +62 -0
  188. package/dist/commands/flow/select.js.map +1 -0
  189. package/dist/commands/graph/boundaries-input.d.ts +26 -0
  190. package/dist/commands/graph/boundaries-input.d.ts.map +1 -0
  191. package/dist/commands/graph/boundaries-input.js +54 -0
  192. package/dist/commands/graph/boundaries-input.js.map +1 -0
  193. package/dist/commands/graph/boundaries.d.ts +4 -0
  194. package/dist/commands/graph/boundaries.d.ts.map +1 -0
  195. package/dist/commands/graph/boundaries.js +141 -0
  196. package/dist/commands/graph/boundaries.js.map +1 -0
  197. package/dist/commands/graph/bounds.d.ts +16 -0
  198. package/dist/commands/graph/bounds.d.ts.map +1 -0
  199. package/dist/commands/graph/bounds.js +22 -0
  200. package/dist/commands/graph/bounds.js.map +1 -0
  201. package/dist/commands/graph/category-clusters.d.ts +20 -0
  202. package/dist/commands/graph/category-clusters.d.ts.map +1 -0
  203. package/dist/commands/graph/category-clusters.js +158 -0
  204. package/dist/commands/graph/category-clusters.js.map +1 -0
  205. package/dist/commands/graph/feature-3d.d.ts +22 -0
  206. package/dist/commands/graph/feature-3d.d.ts.map +1 -0
  207. package/dist/commands/graph/feature-3d.js +114 -0
  208. package/dist/commands/graph/feature-3d.js.map +1 -0
  209. package/dist/commands/graph/feature-clusters.d.ts +17 -0
  210. package/dist/commands/graph/feature-clusters.d.ts.map +1 -0
  211. package/dist/commands/graph/feature-clusters.js +94 -0
  212. package/dist/commands/graph/feature-clusters.js.map +1 -0
  213. package/dist/commands/graph/feature-html.d.ts +26 -0
  214. package/dist/commands/graph/feature-html.d.ts.map +1 -0
  215. package/dist/commands/graph/feature-html.js +314 -0
  216. package/dist/commands/graph/feature-html.js.map +1 -0
  217. package/dist/commands/graph/feature-map.d.ts +31 -0
  218. package/dist/commands/graph/feature-map.d.ts.map +1 -0
  219. package/dist/commands/graph/feature-map.js +217 -0
  220. package/dist/commands/graph/feature-map.js.map +1 -0
  221. package/dist/commands/graph/feature-model.d.ts +55 -0
  222. package/dist/commands/graph/feature-model.d.ts.map +1 -0
  223. package/dist/commands/graph/feature-model.js +167 -0
  224. package/dist/commands/graph/feature-model.js.map +1 -0
  225. package/dist/commands/graph/feature-untangle-motion.d.ts +33 -0
  226. package/dist/commands/graph/feature-untangle-motion.d.ts.map +1 -0
  227. package/dist/commands/graph/feature-untangle-motion.js +155 -0
  228. package/dist/commands/graph/feature-untangle-motion.js.map +1 -0
  229. package/dist/commands/graph/index.d.ts +3 -0
  230. package/dist/commands/graph/index.d.ts.map +1 -0
  231. package/dist/commands/graph/index.js +414 -0
  232. package/dist/commands/graph/index.js.map +1 -0
  233. package/dist/commands/graph/render.d.ts +63 -0
  234. package/dist/commands/graph/render.d.ts.map +1 -0
  235. package/dist/commands/graph/render.js +352 -0
  236. package/dist/commands/graph/render.js.map +1 -0
  237. package/dist/commands/graph/select.d.ts +34 -0
  238. package/dist/commands/graph/select.d.ts.map +1 -0
  239. package/dist/commands/graph/select.js +55 -0
  240. package/dist/commands/graph/select.js.map +1 -0
  241. package/dist/commands/index/index.d.ts +6 -0
  242. package/dist/commands/index/index.d.ts.map +1 -0
  243. package/dist/commands/index/index.js +461 -0
  244. package/dist/commands/index/index.js.map +1 -0
  245. package/dist/commands/index/render.d.ts +53 -0
  246. package/dist/commands/index/render.d.ts.map +1 -0
  247. package/dist/commands/index/render.js +205 -0
  248. package/dist/commands/index/render.js.map +1 -0
  249. package/dist/commands/index/target.d.ts +34 -0
  250. package/dist/commands/index/target.d.ts.map +1 -0
  251. package/dist/commands/index/target.js +97 -0
  252. package/dist/commands/index/target.js.map +1 -0
  253. package/dist/commands/index-watch.d.ts +30 -0
  254. package/dist/commands/index-watch.d.ts.map +1 -0
  255. package/dist/commands/index-watch.js +138 -0
  256. package/dist/commands/index-watch.js.map +1 -0
  257. package/dist/commands/init/command.d.ts +25 -0
  258. package/dist/commands/init/command.d.ts.map +1 -0
  259. package/dist/commands/init/command.js +198 -0
  260. package/dist/commands/init/command.js.map +1 -0
  261. package/dist/commands/init/config-draft.d.ts +48 -0
  262. package/dist/commands/init/config-draft.d.ts.map +1 -0
  263. package/dist/commands/init/config-draft.js +201 -0
  264. package/dist/commands/init/config-draft.js.map +1 -0
  265. package/dist/commands/init/diff.d.ts +33 -0
  266. package/dist/commands/init/diff.d.ts.map +1 -0
  267. package/dist/commands/init/diff.js +109 -0
  268. package/dist/commands/init/diff.js.map +1 -0
  269. package/dist/commands/init/http-probe.d.ts +26 -0
  270. package/dist/commands/init/http-probe.d.ts.map +1 -0
  271. package/dist/commands/init/http-probe.js +144 -0
  272. package/dist/commands/init/http-probe.js.map +1 -0
  273. package/dist/commands/init/ignore-rules.d.ts +70 -0
  274. package/dist/commands/init/ignore-rules.d.ts.map +1 -0
  275. package/dist/commands/init/ignore-rules.js +146 -0
  276. package/dist/commands/init/ignore-rules.js.map +1 -0
  277. package/dist/commands/init/index.d.ts +33 -0
  278. package/dist/commands/init/index.d.ts.map +1 -0
  279. package/dist/commands/init/index.js +32 -0
  280. package/dist/commands/init/index.js.map +1 -0
  281. package/dist/commands/init/integrations-apply.d.ts +50 -0
  282. package/dist/commands/init/integrations-apply.d.ts.map +1 -0
  283. package/dist/commands/init/integrations-apply.js +452 -0
  284. package/dist/commands/init/integrations-apply.js.map +1 -0
  285. package/dist/commands/init/integrations-plan.d.ts +68 -0
  286. package/dist/commands/init/integrations-plan.d.ts.map +1 -0
  287. package/dist/commands/init/integrations-plan.js +515 -0
  288. package/dist/commands/init/integrations-plan.js.map +1 -0
  289. package/dist/commands/init/integrations.d.ts +5 -0
  290. package/dist/commands/init/integrations.d.ts.map +1 -0
  291. package/dist/commands/init/integrations.js +4 -0
  292. package/dist/commands/init/integrations.js.map +1 -0
  293. package/dist/commands/init/languages.d.ts +55 -0
  294. package/dist/commands/init/languages.d.ts.map +1 -0
  295. package/dist/commands/init/languages.js +245 -0
  296. package/dist/commands/init/languages.js.map +1 -0
  297. package/dist/commands/init/product-context.d.ts +63 -0
  298. package/dist/commands/init/product-context.d.ts.map +1 -0
  299. package/dist/commands/init/product-context.js +390 -0
  300. package/dist/commands/init/product-context.js.map +1 -0
  301. package/dist/commands/init/render.d.ts +38 -0
  302. package/dist/commands/init/render.d.ts.map +1 -0
  303. package/dist/commands/init/render.js +501 -0
  304. package/dist/commands/init/render.js.map +1 -0
  305. package/dist/commands/init/report.d.ts +24 -0
  306. package/dist/commands/init/report.d.ts.map +1 -0
  307. package/dist/commands/init/report.js +163 -0
  308. package/dist/commands/init/report.js.map +1 -0
  309. package/dist/commands/init/run.d.ts +71 -0
  310. package/dist/commands/init/run.d.ts.map +1 -0
  311. package/dist/commands/init/run.js +253 -0
  312. package/dist/commands/init/run.js.map +1 -0
  313. package/dist/commands/init/services.d.ts +82 -0
  314. package/dist/commands/init/services.d.ts.map +1 -0
  315. package/dist/commands/init/services.js +209 -0
  316. package/dist/commands/init/services.js.map +1 -0
  317. package/dist/commands/init/storage.d.ts +8 -0
  318. package/dist/commands/init/storage.d.ts.map +1 -0
  319. package/dist/commands/init/storage.js +102 -0
  320. package/dist/commands/init/storage.js.map +1 -0
  321. package/dist/commands/init/toml.d.ts +65 -0
  322. package/dist/commands/init/toml.d.ts.map +1 -0
  323. package/dist/commands/init/toml.js +159 -0
  324. package/dist/commands/init/toml.js.map +1 -0
  325. package/dist/commands/init/topology.d.ts +54 -0
  326. package/dist/commands/init/topology.d.ts.map +1 -0
  327. package/dist/commands/init/topology.js +146 -0
  328. package/dist/commands/init/topology.js.map +1 -0
  329. package/dist/commands/init/types.d.ts +334 -0
  330. package/dist/commands/init/types.d.ts.map +1 -0
  331. package/dist/commands/init/types.js +31 -0
  332. package/dist/commands/init/types.js.map +1 -0
  333. package/dist/commands/init/wizard-terminal.d.ts +36 -0
  334. package/dist/commands/init/wizard-terminal.d.ts.map +1 -0
  335. package/dist/commands/init/wizard-terminal.js +163 -0
  336. package/dist/commands/init/wizard-terminal.js.map +1 -0
  337. package/dist/commands/init/wizard.d.ts +25 -0
  338. package/dist/commands/init/wizard.d.ts.map +1 -0
  339. package/dist/commands/init/wizard.js +358 -0
  340. package/dist/commands/init/wizard.js.map +1 -0
  341. package/dist/commands/mcp.d.ts +4 -0
  342. package/dist/commands/mcp.d.ts.map +1 -0
  343. package/dist/commands/mcp.js +111 -0
  344. package/dist/commands/mcp.js.map +1 -0
  345. package/dist/commands/product-test-runner.d.ts +4 -0
  346. package/dist/commands/product-test-runner.d.ts.map +1 -0
  347. package/dist/commands/product-test-runner.js +85 -0
  348. package/dist/commands/product-test-runner.js.map +1 -0
  349. package/dist/commands/product.d.ts +16 -0
  350. package/dist/commands/product.d.ts.map +1 -0
  351. package/dist/commands/product.js +262 -0
  352. package/dist/commands/product.js.map +1 -0
  353. package/dist/commands/query.d.ts +114 -0
  354. package/dist/commands/query.d.ts.map +1 -0
  355. package/dist/commands/query.js +783 -0
  356. package/dist/commands/query.js.map +1 -0
  357. package/dist/commands/scan.d.ts +10 -0
  358. package/dist/commands/scan.d.ts.map +1 -0
  359. package/dist/commands/scan.js +302 -0
  360. package/dist/commands/scan.js.map +1 -0
  361. package/dist/commands/sdd.d.ts +24 -0
  362. package/dist/commands/sdd.d.ts.map +1 -0
  363. package/dist/commands/sdd.js +195 -0
  364. package/dist/commands/sdd.js.map +1 -0
  365. package/dist/commands/unavailable.d.ts +40 -0
  366. package/dist/commands/unavailable.d.ts.map +1 -0
  367. package/dist/commands/unavailable.js +73 -0
  368. package/dist/commands/unavailable.js.map +1 -0
  369. package/dist/commands/watch/analyze.d.ts +69 -0
  370. package/dist/commands/watch/analyze.d.ts.map +1 -0
  371. package/dist/commands/watch/analyze.js +402 -0
  372. package/dist/commands/watch/analyze.js.map +1 -0
  373. package/dist/commands/watch/cli.d.ts +8 -0
  374. package/dist/commands/watch/cli.d.ts.map +1 -0
  375. package/dist/commands/watch/cli.js +97 -0
  376. package/dist/commands/watch/cli.js.map +1 -0
  377. package/dist/commands/watch/delta.d.ts +46 -0
  378. package/dist/commands/watch/delta.d.ts.map +1 -0
  379. package/dist/commands/watch/delta.js +170 -0
  380. package/dist/commands/watch/delta.js.map +1 -0
  381. package/dist/commands/watch/events.d.ts +214 -0
  382. package/dist/commands/watch/events.d.ts.map +1 -0
  383. package/dist/commands/watch/events.js +13 -0
  384. package/dist/commands/watch/events.js.map +1 -0
  385. package/dist/commands/watch/index.d.ts +19 -0
  386. package/dist/commands/watch/index.d.ts.map +1 -0
  387. package/dist/commands/watch/index.js +15 -0
  388. package/dist/commands/watch/index.js.map +1 -0
  389. package/dist/commands/watch/options.d.ts +43 -0
  390. package/dist/commands/watch/options.d.ts.map +1 -0
  391. package/dist/commands/watch/options.js +193 -0
  392. package/dist/commands/watch/options.js.map +1 -0
  393. package/dist/commands/watch/render.d.ts +26 -0
  394. package/dist/commands/watch/render.d.ts.map +1 -0
  395. package/dist/commands/watch/render.js +175 -0
  396. package/dist/commands/watch/render.js.map +1 -0
  397. package/dist/commands/watch/run.d.ts +14 -0
  398. package/dist/commands/watch/run.d.ts.map +1 -0
  399. package/dist/commands/watch/run.js +460 -0
  400. package/dist/commands/watch/run.js.map +1 -0
  401. package/dist/commands/watch/runtime.d.ts +67 -0
  402. package/dist/commands/watch/runtime.d.ts.map +1 -0
  403. package/dist/commands/watch/runtime.js +149 -0
  404. package/dist/commands/watch/runtime.js.map +1 -0
  405. package/dist/commands/watch-command.d.ts +3 -0
  406. package/dist/commands/watch-command.d.ts.map +1 -0
  407. package/dist/commands/watch-command.js +273 -0
  408. package/dist/commands/watch-command.js.map +1 -0
  409. package/dist/entry-point.d.ts +11 -0
  410. package/dist/entry-point.d.ts.map +1 -0
  411. package/dist/entry-point.js +65 -0
  412. package/dist/entry-point.js.map +1 -0
  413. package/dist/index.d.ts +38 -0
  414. package/dist/index.d.ts.map +1 -0
  415. package/dist/index.js +245 -0
  416. package/dist/index.js.map +1 -0
  417. package/dist/mcp/boundaries-schema.d.ts +262 -0
  418. package/dist/mcp/boundaries-schema.d.ts.map +1 -0
  419. package/dist/mcp/boundaries-schema.js +183 -0
  420. package/dist/mcp/boundaries-schema.js.map +1 -0
  421. package/dist/mcp/default-runtime.d.ts +16 -0
  422. package/dist/mcp/default-runtime.d.ts.map +1 -0
  423. package/dist/mcp/default-runtime.js +718 -0
  424. package/dist/mcp/default-runtime.js.map +1 -0
  425. package/dist/mcp/envelope.d.ts +13 -0
  426. package/dist/mcp/envelope.d.ts.map +1 -0
  427. package/dist/mcp/envelope.js +29 -0
  428. package/dist/mcp/envelope.js.map +1 -0
  429. package/dist/mcp/index.d.ts +8 -0
  430. package/dist/mcp/index.d.ts.map +1 -0
  431. package/dist/mcp/index.js +8 -0
  432. package/dist/mcp/index.js.map +1 -0
  433. package/dist/mcp/output-schemas.d.ts +5928 -0
  434. package/dist/mcp/output-schemas.d.ts.map +1 -0
  435. package/dist/mcp/output-schemas.js +2814 -0
  436. package/dist/mcp/output-schemas.js.map +1 -0
  437. package/dist/mcp/path-sandbox.d.ts +35 -0
  438. package/dist/mcp/path-sandbox.d.ts.map +1 -0
  439. package/dist/mcp/path-sandbox.js +128 -0
  440. package/dist/mcp/path-sandbox.js.map +1 -0
  441. package/dist/mcp/server.d.ts +155 -0
  442. package/dist/mcp/server.d.ts.map +1 -0
  443. package/dist/mcp/server.js +257 -0
  444. package/dist/mcp/server.js.map +1 -0
  445. package/dist/mcp/stdio.d.ts +20 -0
  446. package/dist/mcp/stdio.d.ts.map +1 -0
  447. package/dist/mcp/stdio.js +71 -0
  448. package/dist/mcp/stdio.js.map +1 -0
  449. package/dist/mcp/tools.d.ts +355 -0
  450. package/dist/mcp/tools.d.ts.map +1 -0
  451. package/dist/mcp/tools.js +319 -0
  452. package/dist/mcp/tools.js.map +1 -0
  453. package/dist/mcp/types.d.ts +15 -0
  454. package/dist/mcp/types.d.ts.map +1 -0
  455. package/dist/mcp/types.js +45 -0
  456. package/dist/mcp/types.js.map +1 -0
  457. package/package.json +99 -3
  458. package/src/cli/args.ts +231 -0
  459. package/src/cli/command.ts +146 -0
  460. package/src/cli/deadline.ts +56 -0
  461. package/src/cli/embedder-deadline.ts +187 -0
  462. package/src/cli/exit.ts +94 -0
  463. package/src/cli/graphs.ts +191 -0
  464. package/src/cli/index-freshness.ts +303 -0
  465. package/src/cli/index-refresh.ts +125 -0
  466. package/src/cli/index-state.ts +1217 -0
  467. package/src/cli/io.ts +56 -0
  468. package/src/cli/language-support.ts +203 -0
  469. package/src/cli/renewing-lease.ts +121 -0
  470. package/src/cli/search-graph-enrichment.ts +639 -0
  471. package/src/cli/system.ts +94 -0
  472. package/src/cli/vector-store-policy.ts +213 -0
  473. package/src/cli/version.ts +2 -0
  474. package/src/cli/workspace.ts +324 -0
  475. package/src/commands/complexity.ts +776 -0
  476. package/src/commands/doctor.languages.ts +187 -0
  477. package/src/commands/doctor.storage.ts +124 -0
  478. package/src/commands/doctor.ts +946 -0
  479. package/src/commands/extensions/add.ts +312 -0
  480. package/src/commands/extensions/configure.ts +82 -0
  481. package/src/commands/extensions/container.ts +209 -0
  482. package/src/commands/extensions/context.ts +109 -0
  483. package/src/commands/extensions/enable.ts +237 -0
  484. package/src/commands/extensions/environment.ts +218 -0
  485. package/src/commands/extensions/feature-scan.ts +232 -0
  486. package/src/commands/extensions/invoke.ts +368 -0
  487. package/src/commands/extensions/list.ts +158 -0
  488. package/src/commands/extensions/logs.ts +104 -0
  489. package/src/commands/extensions/provision.ts +206 -0
  490. package/src/commands/extensions/remove.ts +110 -0
  491. package/src/commands/extensions/render.ts +32 -0
  492. package/src/commands/extensions/run.ts +386 -0
  493. package/src/commands/extensions/secret-store.ts +223 -0
  494. package/src/commands/extensions/setup.ts +140 -0
  495. package/src/commands/extensions/source.ts +189 -0
  496. package/src/commands/extensions/state.ts +252 -0
  497. package/src/commands/extensions/status.ts +320 -0
  498. package/src/commands/extensions.ts +280 -0
  499. package/src/commands/flow/index.ts +402 -0
  500. package/src/commands/flow/limits.ts +14 -0
  501. package/src/commands/flow/output.ts +16 -0
  502. package/src/commands/flow/render.ts +318 -0
  503. package/src/commands/flow/select.ts +101 -0
  504. package/src/commands/graph/boundaries-input.ts +63 -0
  505. package/src/commands/graph/boundaries.ts +182 -0
  506. package/src/commands/graph/bounds.ts +25 -0
  507. package/src/commands/graph/category-clusters.ts +194 -0
  508. package/src/commands/graph/feature-3d.ts +141 -0
  509. package/src/commands/graph/feature-clusters.ts +125 -0
  510. package/src/commands/graph/feature-html.ts +336 -0
  511. package/src/commands/graph/feature-map.ts +270 -0
  512. package/src/commands/graph/feature-model.ts +234 -0
  513. package/src/commands/graph/feature-untangle-motion.ts +192 -0
  514. package/src/commands/graph/index.ts +562 -0
  515. package/src/commands/graph/render.ts +503 -0
  516. package/src/commands/graph/select.ts +77 -0
  517. package/src/commands/index/index.ts +595 -0
  518. package/src/commands/index/render.ts +325 -0
  519. package/src/commands/index/target.ts +136 -0
  520. package/src/commands/index-watch.ts +206 -0
  521. package/src/commands/init/command.ts +238 -0
  522. package/src/commands/init/config-draft.ts +235 -0
  523. package/src/commands/init/diff.ts +117 -0
  524. package/src/commands/init/http-probe.ts +150 -0
  525. package/src/commands/init/ignore-rules.ts +170 -0
  526. package/src/commands/init/index.ts +63 -0
  527. package/src/commands/init/integrations-apply.ts +618 -0
  528. package/src/commands/init/integrations-plan.ts +634 -0
  529. package/src/commands/init/integrations.ts +8 -0
  530. package/src/commands/init/languages.ts +320 -0
  531. package/src/commands/init/product-context.ts +576 -0
  532. package/src/commands/init/render.ts +598 -0
  533. package/src/commands/init/report.ts +204 -0
  534. package/src/commands/init/run.ts +349 -0
  535. package/src/commands/init/services.ts +271 -0
  536. package/src/commands/init/storage.ts +136 -0
  537. package/src/commands/init/toml.ts +174 -0
  538. package/src/commands/init/topology.ts +192 -0
  539. package/src/commands/init/types.ts +366 -0
  540. package/src/commands/init/wizard-terminal.ts +206 -0
  541. package/src/commands/init/wizard.ts +450 -0
  542. package/src/commands/mcp.ts +123 -0
  543. package/src/commands/product-test-runner.ts +80 -0
  544. package/src/commands/product.ts +331 -0
  545. package/src/commands/query.ts +1032 -0
  546. package/src/commands/scan.ts +360 -0
  547. package/src/commands/sdd.ts +243 -0
  548. package/src/commands/unavailable.ts +92 -0
  549. package/src/commands/watch/README.md +160 -0
  550. package/src/commands/watch/analyze.ts +600 -0
  551. package/src/commands/watch/cli.ts +108 -0
  552. package/src/commands/watch/delta.ts +186 -0
  553. package/src/commands/watch/events.ts +235 -0
  554. package/src/commands/watch/index.ts +53 -0
  555. package/src/commands/watch/options.ts +234 -0
  556. package/src/commands/watch/render.ts +240 -0
  557. package/src/commands/watch/run.ts +553 -0
  558. package/src/commands/watch/runtime.ts +167 -0
  559. package/src/commands/watch-command.ts +294 -0
  560. package/src/entry-point.ts +67 -0
  561. package/src/index.ts +291 -0
  562. package/src/mcp/boundaries-schema.ts +193 -0
  563. package/src/mcp/default-runtime.ts +1034 -0
  564. package/src/mcp/envelope.ts +57 -0
  565. package/src/mcp/index.ts +28 -0
  566. package/src/mcp/output-schemas.ts +3071 -0
  567. package/src/mcp/path-sandbox.ts +156 -0
  568. package/src/mcp/server.ts +358 -0
  569. package/src/mcp/stdio.ts +92 -0
  570. package/src/mcp/tools.ts +563 -0
  571. package/src/mcp/types.ts +66 -0
@@ -0,0 +1,2814 @@
1
+ import { MINIMUM_PRODUCT_COMPLEXITY_SESSIONS, SEARCH_JOURNEY_ABANDON_REASON_CODES, SEARCH_JOURNEY_EXECUTION_CONTEXT_DIMENSIONS, SEARCH_JOURNEY_TARGET_CODE_COMPLEXITY_UNAVAILABLE_REASONS, canonicalJson, searchJourneyValidationIssue, } from "@untangle-code/domain";
2
+ import * as z from "zod/v4";
3
+ import { frontendBoundaryReportSchema } from "./boundaries-schema.js";
4
+ const text = z.string();
5
+ const isoTimestamp = text.refine((value) => Number.isFinite(Date.parse(value)), {
6
+ message: "Expected an ISO timestamp",
7
+ });
8
+ // Validate semantic content without transforming wire values. In particular,
9
+ // raw import specifiers may intentionally carry leading/trailing whitespace
10
+ // and must round-trip byte-for-byte through the MCP response boundary.
11
+ const nonEmpty = text.refine((value) => value.trim().length > 0, {
12
+ message: "Expected a non-empty string",
13
+ });
14
+ const finite = z.number().finite();
15
+ const nonNegative = finite.nonnegative();
16
+ const ratio = finite.min(0).max(1);
17
+ const integer = z.number().int();
18
+ const nonNegativeInt = integer.nonnegative();
19
+ const positiveInt = integer.positive();
20
+ const sha256Fingerprint = text.regex(/^[0-9a-f]{64}$/u);
21
+ const stringArray = z.array(text);
22
+ const stringMap = z.record(z.string(), text);
23
+ const optionalStringMap = z.record(z.string(), text.nullable());
24
+ const numberMap = z.record(z.string(), finite);
25
+ const jsonMap = z.record(z.string(), z.json());
26
+ const sourceRangeSchema = z
27
+ .object({
28
+ startLine: positiveInt,
29
+ endLine: positiveInt,
30
+ startByte: nonNegativeInt,
31
+ endByte: nonNegativeInt,
32
+ })
33
+ .strict();
34
+ const skipLedgerEntrySchema = z
35
+ .object({
36
+ schemaVersion: z.literal(1),
37
+ stage: z.enum([
38
+ "scan",
39
+ "parse",
40
+ "chunk",
41
+ "embed",
42
+ "store",
43
+ "file_graph",
44
+ "symbol_graph",
45
+ "search",
46
+ "findability",
47
+ "extension",
48
+ ]),
49
+ subjectKind: z.enum([
50
+ "file",
51
+ "range",
52
+ "symbol",
53
+ "chunk",
54
+ "file_edge",
55
+ "symbol_edge",
56
+ "search_candidate",
57
+ "artifact",
58
+ "extension",
59
+ ]),
60
+ subjectId: text.optional(),
61
+ path: text.optional(),
62
+ range: sourceRangeSchema.optional(),
63
+ repoId: text.optional(),
64
+ refId: text.optional(),
65
+ reason: z.enum([
66
+ "unsupported_language",
67
+ "parse_failed",
68
+ "file_too_large",
69
+ "binary_content",
70
+ "excluded_by_configuration",
71
+ "token_budget_exceeded",
72
+ "time_budget_exceeded",
73
+ "resolution_failed",
74
+ "ambiguous_resolution",
75
+ "missing_index_entry",
76
+ "provider_unavailable",
77
+ "extension_unavailable",
78
+ "duplicate",
79
+ "no_metric_defined",
80
+ "generated_content",
81
+ "relevance_policy_rejected",
82
+ ]),
83
+ detail: nonEmpty,
84
+ recoverable: z.boolean(),
85
+ })
86
+ .strict();
87
+ const indexCountsSchema = z
88
+ .object({
89
+ filesSeen: nonNegativeInt,
90
+ filesPlanned: nonNegativeInt,
91
+ filesUnchanged: nonNegativeInt,
92
+ filesIgnored: nonNegativeInt,
93
+ filesAnalyzed: nonNegativeInt,
94
+ filesRemoved: nonNegativeInt,
95
+ chunks: nonNegativeInt,
96
+ symbols: nonNegativeInt,
97
+ points: nonNegativeInt,
98
+ embeddingCacheHits: nonNegativeInt,
99
+ embeddingsComputed: nonNegativeInt,
100
+ parseCacheHits: nonNegativeInt,
101
+ parseCacheMisses: nonNegativeInt,
102
+ chunkCacheHits: nonNegativeInt,
103
+ chunkCacheMisses: nonNegativeInt,
104
+ metricsCacheHits: nonNegativeInt,
105
+ metricsCacheMisses: nonNegativeInt,
106
+ truncated: nonNegativeInt,
107
+ fileGraphNodes: nonNegativeInt,
108
+ fileGraphEdges: nonNegativeInt,
109
+ symbolGraphNodes: nonNegativeInt,
110
+ symbolGraphEdges: nonNegativeInt,
111
+ })
112
+ .strict();
113
+ const indexReportSchema = z
114
+ .object({
115
+ schemaVersion: z.literal(1),
116
+ jobId: nonEmpty,
117
+ generationId: text.nullable(),
118
+ workspaceId: nonEmpty,
119
+ repoId: nonEmpty,
120
+ refId: nonEmpty,
121
+ embeddingProfileId: nonEmpty,
122
+ collection: nonEmpty,
123
+ outcome: z.enum(["completed", "failed", "cancelled"]),
124
+ counts: indexCountsSchema,
125
+ failure: z
126
+ .object({ code: nonEmpty, message: nonEmpty, retryable: z.boolean() })
127
+ .strict()
128
+ .optional(),
129
+ skipped: z.array(skipLedgerEntrySchema),
130
+ skippedByReason: z.record(z.string(), nonNegativeInt),
131
+ skippedByStage: z.record(z.string(), nonNegativeInt),
132
+ skippedTruncated: nonNegativeInt,
133
+ })
134
+ .strict();
135
+ const jobStatusSchema = z
136
+ .object({
137
+ jobId: nonEmpty,
138
+ operation: nonEmpty,
139
+ status: z.enum([
140
+ "queued",
141
+ "preparing_infrastructure",
142
+ "discovering_files",
143
+ "parsing_and_chunking",
144
+ "computing_metrics",
145
+ "embedding",
146
+ "storing",
147
+ "checkpointing",
148
+ "building_graphs",
149
+ "indexing_context",
150
+ "finalizing",
151
+ "completed",
152
+ "failed",
153
+ "cancel_requested",
154
+ "cancelled",
155
+ ]),
156
+ workspaceId: nonEmpty,
157
+ generationId: text.optional(),
158
+ updatedAt: text.optional(),
159
+ })
160
+ .strict();
161
+ const checkResultSchema = z
162
+ .object({
163
+ id: nonEmpty,
164
+ title: nonEmpty,
165
+ status: z.enum(["ok", "warn", "fail"]),
166
+ detail: nonEmpty,
167
+ nextStep: nonEmpty.optional(),
168
+ facts: z.record(z.string(), z.union([text, finite, z.boolean()])).optional(),
169
+ })
170
+ .strict();
171
+ const repositoryConfigSchema = z
172
+ .object({
173
+ id: nonEmpty,
174
+ path: nonEmpty,
175
+ label: text.optional(),
176
+ ref: text.optional(),
177
+ include: stringArray.optional(),
178
+ exclude: stringArray.optional(),
179
+ packageAliases: stringMap.optional(),
180
+ metadata: stringMap.optional(),
181
+ })
182
+ .strict();
183
+ const contextArtifactSchema = z
184
+ .object({
185
+ name: nonEmpty,
186
+ path: nonEmpty,
187
+ description: text,
188
+ type: z
189
+ .enum([
190
+ "auto",
191
+ "sql",
192
+ "openapi",
193
+ "asyncapi",
194
+ "protobuf",
195
+ "markdown",
196
+ "terraform",
197
+ "kubernetes",
198
+ "text",
199
+ ])
200
+ .optional(),
201
+ include: stringArray.optional(),
202
+ exclude: stringArray.optional(),
203
+ })
204
+ .strict();
205
+ const warningDataSchema = z
206
+ .object({
207
+ code: nonEmpty,
208
+ message: nonEmpty,
209
+ details: jsonMap.optional(),
210
+ })
211
+ .strict();
212
+ const scoreComponentSchema = z
213
+ .object({
214
+ kind: z.enum([
215
+ "base_hybrid",
216
+ "exact_symbol_boost",
217
+ "exact_path_boost",
218
+ "repo_priority_boost",
219
+ "graph_proximity_boost",
220
+ "recency_boost",
221
+ "duplicate_penalty",
222
+ "complexity_modifier",
223
+ ]),
224
+ rawValue: finite,
225
+ weight: finite,
226
+ contribution: finite,
227
+ evidence: text.optional(),
228
+ })
229
+ .strict();
230
+ const scoreBreakdownSchema = z
231
+ .object({
232
+ schemaVersion: z.literal(1),
233
+ final: finite,
234
+ components: z.array(scoreComponentSchema),
235
+ inputs: z
236
+ .object({
237
+ dense: finite.optional(),
238
+ sparseRank: positiveInt.optional(),
239
+ rrf: finite.optional(),
240
+ denseRank: positiveInt.optional(),
241
+ lexicalScore: finite.optional(),
242
+ lexicalRank: positiveInt.optional(),
243
+ symbolRank: positiveInt.optional(),
244
+ })
245
+ .strict(),
246
+ rankerVersion: nonEmpty,
247
+ clamped: z.boolean(),
248
+ clampReason: text.optional(),
249
+ })
250
+ .strict();
251
+ const complexitySummarySchema = z
252
+ .object({
253
+ metricsScope: z.enum(["symbol", "file", "chunk"]),
254
+ metricsScopeId: nonEmpty,
255
+ metricsVersion: nonEmpty,
256
+ cyclomaticClassic: nonNegativeInt.optional(),
257
+ cyclomaticExtended: nonNegativeInt.optional(),
258
+ cognitive: nonNegativeInt.optional(),
259
+ maxNesting: nonNegativeInt.optional(),
260
+ sloc: nonNegativeInt.optional(),
261
+ halsteadVolume: nonNegative.optional(),
262
+ maintainabilityIndex: finite.min(0).max(100).optional(),
263
+ riskScore: nonNegative.optional(),
264
+ })
265
+ .strict()
266
+ .refine((summary) => summary.cyclomaticClassic !== undefined ||
267
+ summary.cyclomaticExtended !== undefined ||
268
+ summary.cognitive !== undefined ||
269
+ summary.maxNesting !== undefined ||
270
+ summary.sloc !== undefined ||
271
+ summary.halsteadVolume !== undefined ||
272
+ summary.maintainabilityIndex !== undefined ||
273
+ summary.riskScore !== undefined, { message: "complexity summary requires at least one metric" });
274
+ const graphRelationSchema = z
275
+ .object({
276
+ schemaVersion: z.literal(1),
277
+ source: z.enum(["file_graph", "symbol_graph"]),
278
+ edgeId: nonEmpty,
279
+ direction: z.enum(["incoming", "outgoing"]),
280
+ edgeKind: nonEmpty,
281
+ repoId: nonEmpty,
282
+ refId: nonEmpty,
283
+ fileId: nonEmpty,
284
+ path: text,
285
+ crossRepository: z.boolean(),
286
+ symbol: z
287
+ .object({ id: nonEmpty, name: text, qualifiedName: text, kind: text })
288
+ .strict()
289
+ .optional(),
290
+ })
291
+ .strict();
292
+ const graphRelationsSchema = z
293
+ .object({
294
+ schemaVersion: z.literal(1),
295
+ relations: z.array(graphRelationSchema),
296
+ relationLimit: nonNegativeInt,
297
+ truncated: z.boolean(),
298
+ omittedCount: nonNegativeInt,
299
+ omissions: z.array(z
300
+ .object({
301
+ reason: z.enum([
302
+ "graph_unavailable",
303
+ "graph_partial",
304
+ "source_not_in_graph",
305
+ "symbol_id_missing",
306
+ "unresolved_endpoint",
307
+ "heuristic_endpoint",
308
+ "ambiguous_endpoint",
309
+ "endpoint_missing",
310
+ "provider_result_missing",
311
+ "relation_limit",
312
+ ]),
313
+ count: nonNegativeInt,
314
+ detail: nonEmpty,
315
+ })
316
+ .strict()),
317
+ })
318
+ .strict();
319
+ const relatedFragmentSchema = z
320
+ .object({
321
+ chunkId: nonEmpty,
322
+ chunkKind: nonEmpty,
323
+ fragmentIndex: nonNegativeInt.optional(),
324
+ startLine: positiveInt,
325
+ endLine: positiveInt,
326
+ score: finite,
327
+ })
328
+ .strict();
329
+ const findabilitySummarySchema = z
330
+ .object({
331
+ score: ratio,
332
+ isHeuristic: z.literal(true),
333
+ algorithm: nonEmpty,
334
+ primaryCause: z
335
+ .enum(["scattered-responsibility", "weak-naming", "high-entanglement", "undocumented"])
336
+ .optional(),
337
+ primaryCauseConfidence: ratio.optional(),
338
+ })
339
+ .strict();
340
+ const searchHitSchema = z
341
+ .object({
342
+ schemaVersion: z.literal(1),
343
+ rank: positiveInt,
344
+ repoId: nonEmpty,
345
+ repoLabel: text,
346
+ refId: nonEmpty,
347
+ refName: text,
348
+ commitSha: text.optional(),
349
+ fileId: nonEmpty,
350
+ filePath: text,
351
+ range: sourceRangeSchema,
352
+ language: nonEmpty,
353
+ parseQuality: z.enum(["complete", "partial", "failed"]),
354
+ chunkId: nonEmpty,
355
+ chunkKind: nonEmpty,
356
+ fragmentIndex: nonNegativeInt.optional(),
357
+ fragmentCount: positiveInt.optional(),
358
+ symbolId: text.optional(),
359
+ symbolName: text.optional(),
360
+ symbolFqn: text.optional(),
361
+ symbolKind: text.optional(),
362
+ signature: text.optional(),
363
+ score: scoreBreakdownSchema,
364
+ dedupeKey: nonEmpty,
365
+ relatedFragments: z.array(relatedFragmentSchema),
366
+ embeddingProfileId: nonEmpty,
367
+ indexGeneration: nonEmpty,
368
+ complexity: complexitySummarySchema.optional(),
369
+ findability: findabilitySummarySchema.optional(),
370
+ content: text.optional(),
371
+ contentOmittedReason: text.optional(),
372
+ graphContext: graphRelationsSchema.optional(),
373
+ linkedSymbols: graphRelationsSchema.optional(),
374
+ incompletePayloadFields: stringArray.optional(),
375
+ })
376
+ .strict();
377
+ const searchQuerySchema = z
378
+ .object({
379
+ schemaVersion: z.literal(1),
380
+ text: nonEmpty,
381
+ workspaceId: nonEmpty,
382
+ filters: z
383
+ .object({
384
+ repoIds: stringArray,
385
+ refIds: stringArray,
386
+ commitSha: text.optional(),
387
+ languages: stringArray,
388
+ pathGlobs: stringArray,
389
+ symbolNames: stringArray,
390
+ symbolKinds: stringArray,
391
+ chunkKinds: stringArray,
392
+ complexity: z
393
+ .object({
394
+ cyclomaticMin: finite.optional(),
395
+ cyclomaticMax: finite.optional(),
396
+ cognitiveMin: finite.optional(),
397
+ cognitiveMax: finite.optional(),
398
+ riskMin: finite.optional(),
399
+ riskMax: finite.optional(),
400
+ })
401
+ .strict()
402
+ .optional(),
403
+ findability: z
404
+ .object({
405
+ maxScore: finite.optional(),
406
+ minScore: finite.optional(),
407
+ causes: z
408
+ .array(z.enum([
409
+ "scattered-responsibility",
410
+ "weak-naming",
411
+ "high-entanglement",
412
+ "undocumented",
413
+ ]))
414
+ .optional(),
415
+ })
416
+ .strict()
417
+ .optional(),
418
+ changed: z.object({ since: nonEmpty, until: nonEmpty.optional() }).strict().optional(),
419
+ })
420
+ .strict(),
421
+ limit: positiveInt,
422
+ candidateLimit: positiveInt,
423
+ minScore: finite.optional(),
424
+ diversify: z.boolean(),
425
+ includeGraphContext: z.boolean(),
426
+ includeLinked: z.boolean(),
427
+ includeContent: z.boolean(),
428
+ rankerVersion: nonEmpty,
429
+ })
430
+ .strict();
431
+ const searchResultSetSchema = z
432
+ .object({
433
+ schemaVersion: z.literal(1),
434
+ queryFingerprint: nonEmpty,
435
+ indexFreshness: z
436
+ .object({
437
+ status: z.enum(["fresh", "stale", "unknown", "incompatible"]),
438
+ checkedAt: isoTimestamp,
439
+ repositories: z.array(z
440
+ .object({
441
+ repoId: nonEmpty,
442
+ refId: nonEmpty,
443
+ status: z.enum(["fresh", "stale", "unknown", "incompatible"]),
444
+ reason: nonEmpty,
445
+ filesChecked: nonNegativeInt,
446
+ indexedAt: isoTimestamp.optional(),
447
+ indexedCorpusFingerprint: sha256Fingerprint.optional(),
448
+ currentCorpusFingerprint: sha256Fingerprint.optional(),
449
+ })
450
+ .strict()),
451
+ })
452
+ .strict()
453
+ .optional(),
454
+ rankingContextFingerprint: nonEmpty.optional(),
455
+ query: searchQuerySchema,
456
+ groups: z.array(z
457
+ .object({
458
+ embeddingProfileId: nonEmpty,
459
+ indexGenerations: z.array(nonEmpty).optional(),
460
+ corpusRevisionFingerprint: sha256Fingerprint.optional(),
461
+ repoIds: stringArray,
462
+ hits: z.array(searchHitSchema),
463
+ rankNormalized: z.boolean(),
464
+ caveats: stringArray,
465
+ notSearchedReason: text.optional(),
466
+ relevanceDecision: z
467
+ .object({
468
+ abstention: z.enum(["strict", "evidence"]),
469
+ status: z.enum(["accepted", "rejected", "not_evaluated"]),
470
+ basis: nonEmpty,
471
+ calibrationId: nonEmpty.optional(),
472
+ })
473
+ .strict()
474
+ .optional(),
475
+ retrieval: z
476
+ .object({
477
+ branchCandidateCounts: z
478
+ .object({
479
+ dense: nonNegativeInt,
480
+ sparse: nonNegativeInt,
481
+ symbol: nonNegativeInt,
482
+ })
483
+ .strict(),
484
+ uniqueRetrievedCandidateCount: nonNegativeInt,
485
+ eligibleCandidateCount: nonNegativeInt,
486
+ rankedCandidateCount: nonNegativeInt,
487
+ deduplicatedCandidateCount: nonNegativeInt,
488
+ qualifiedHitCount: nonNegativeInt,
489
+ returnedHitCount: nonNegativeInt,
490
+ uniqueEligibleFileCount: nonNegativeInt,
491
+ uniqueEligibleSymbolCount: nonNegativeInt,
492
+ eligibleFileDispersion: ratio,
493
+ topScoreGap: finite.nullable(),
494
+ candidateLimitReached: z.boolean(),
495
+ })
496
+ .strict()
497
+ .optional(),
498
+ })
499
+ .strict()),
500
+ profileSeparation: z.boolean(),
501
+ totalHits: nonNegativeInt,
502
+ skipped: z.array(skipLedgerEntrySchema),
503
+ warnings: z.array(warningDataSchema),
504
+ timings: z
505
+ .object({
506
+ queryEmbeddingMs: nonNegative.optional(),
507
+ vectorSearchMs: nonNegative.optional(),
508
+ totalMs: nonNegative.optional(),
509
+ })
510
+ .strict()
511
+ .optional(),
512
+ searchObservation: z
513
+ .discriminatedUnion("status", [
514
+ z
515
+ .object({
516
+ sessionId: nonEmpty,
517
+ attemptId: nonEmpty,
518
+ status: z.literal("recorded"),
519
+ })
520
+ .strict(),
521
+ z
522
+ .object({
523
+ sessionId: nonEmpty,
524
+ status: z.literal("not_recorded"),
525
+ warningCode: nonEmpty,
526
+ })
527
+ .strict(),
528
+ ])
529
+ .optional(),
530
+ })
531
+ .strict();
532
+ const searchJourneyTargetSchema = z
533
+ .object({
534
+ repoId: nonEmpty.optional(),
535
+ refId: nonEmpty.optional(),
536
+ filePath: nonEmpty.optional(),
537
+ chunkId: nonEmpty.optional(),
538
+ symbolId: nonEmpty.optional(),
539
+ embeddingProfileId: nonEmpty.optional(),
540
+ indexGeneration: nonEmpty.optional(),
541
+ })
542
+ .strict()
543
+ .refine((target) => target.filePath !== undefined ||
544
+ target.chunkId !== undefined ||
545
+ target.symbolId !== undefined, {
546
+ message: "search journey target requires filePath, chunkId or symbolId",
547
+ });
548
+ const searchJourneyCandidateSchema = z
549
+ .object({
550
+ repoId: nonEmpty,
551
+ refId: nonEmpty,
552
+ filePath: text,
553
+ chunkId: nonEmpty,
554
+ symbolId: nonEmpty.optional(),
555
+ symbolFqn: text.optional(),
556
+ embeddingProfileId: nonEmpty,
557
+ indexGeneration: nonEmpty,
558
+ rank: positiveInt,
559
+ score: finite,
560
+ complexity: complexitySummarySchema.optional(),
561
+ incompletePayloadFields: stringArray.optional(),
562
+ })
563
+ .strict();
564
+ const searchJourneyTargetCodeCandidateSchema = z
565
+ .object({
566
+ repoId: nonEmpty,
567
+ refId: nonEmpty,
568
+ filePath: text,
569
+ chunkId: nonEmpty,
570
+ symbolId: nonEmpty.optional(),
571
+ symbolFqn: text.optional(),
572
+ embeddingProfileId: nonEmpty,
573
+ indexGeneration: nonEmpty,
574
+ })
575
+ .strict();
576
+ const searchJourneyTargetCodeComplexitySchema = z.discriminatedUnion("status", [
577
+ z
578
+ .object({
579
+ status: z.literal("observed"),
580
+ source: z.literal("indexed-search-hit"),
581
+ candidate: searchJourneyTargetCodeCandidateSchema,
582
+ complexity: complexitySummarySchema,
583
+ payloadComplete: z.boolean(),
584
+ incompletePayloadFields: stringArray,
585
+ })
586
+ .strict()
587
+ .superRefine((evidence, context) => {
588
+ if (evidence.payloadComplete !== (evidence.incompletePayloadFields.length === 0)) {
589
+ context.addIssue({
590
+ code: "custom",
591
+ path: ["payloadComplete"],
592
+ message: "payload completeness must match incompletePayloadFields",
593
+ });
594
+ }
595
+ if (new Set(evidence.incompletePayloadFields).size !== evidence.incompletePayloadFields.length) {
596
+ context.addIssue({
597
+ code: "custom",
598
+ path: ["incompletePayloadFields"],
599
+ message: "incomplete payload fields must be unique",
600
+ });
601
+ }
602
+ }),
603
+ z
604
+ .object({
605
+ status: z.literal("unavailable"),
606
+ reason: z.enum(SEARCH_JOURNEY_TARGET_CODE_COMPLEXITY_UNAVAILABLE_REASONS),
607
+ })
608
+ .strict(),
609
+ ]);
610
+ const searchRetrievalDiagnosticsSchema = z
611
+ .object({
612
+ branchCandidateCounts: z
613
+ .object({ dense: nonNegativeInt, sparse: nonNegativeInt, symbol: nonNegativeInt })
614
+ .strict(),
615
+ uniqueRetrievedCandidateCount: nonNegativeInt,
616
+ eligibleCandidateCount: nonNegativeInt,
617
+ rankedCandidateCount: nonNegativeInt,
618
+ deduplicatedCandidateCount: nonNegativeInt,
619
+ qualifiedHitCount: nonNegativeInt,
620
+ returnedHitCount: nonNegativeInt,
621
+ uniqueEligibleFileCount: nonNegativeInt,
622
+ uniqueEligibleSymbolCount: nonNegativeInt,
623
+ eligibleFileDispersion: ratio,
624
+ topScoreGap: finite.nullable(),
625
+ candidateLimitReached: z.boolean(),
626
+ })
627
+ .strict();
628
+ const searchJourneyAttemptSchema = z
629
+ .object({
630
+ attemptId: nonEmpty,
631
+ sequence: positiveInt,
632
+ clientStep: positiveInt.optional(),
633
+ observationFingerprint: nonEmpty,
634
+ measurementContextVersion: z.literal(2).optional(),
635
+ abstention: z.enum(["strict", "evidence"]).optional(),
636
+ queryFingerprint: nonEmpty,
637
+ queryText: text.optional(),
638
+ rankerVersion: nonEmpty,
639
+ rankingContextFingerprint: nonEmpty.optional(),
640
+ resultLimit: positiveInt.optional(),
641
+ candidateLimit: positiveInt.optional(),
642
+ observedAt: nonEmpty,
643
+ status: z.enum(["succeeded", "failed"]),
644
+ failureCode: nonEmpty.optional(),
645
+ failureReason: text.optional(),
646
+ warningCodes: stringArray,
647
+ retrievalHealthy: z.boolean(),
648
+ profiles: z.array(z
649
+ .object({
650
+ embeddingProfileId: nonEmpty,
651
+ indexGenerations: stringArray,
652
+ corpusRevisionFingerprint: sha256Fingerprint.optional(),
653
+ retrievalPerformed: z.boolean(),
654
+ notSearchedReason: text.optional(),
655
+ retrieval: searchRetrievalDiagnosticsSchema.optional(),
656
+ candidates: z.array(searchJourneyCandidateSchema),
657
+ })
658
+ .strict()),
659
+ })
660
+ .strict();
661
+ const dynamicSearchComplexitySchema = z
662
+ .object({
663
+ schemaVersion: z.literal(1),
664
+ algorithm: z.literal("untangle-dynamic-search-complexity-v1"),
665
+ isHeuristic: z.literal(true),
666
+ searchesToTarget: positiveInt,
667
+ successfulSearchesToTarget: nonNegativeInt,
668
+ failedSearchesToTarget: nonNegativeInt,
669
+ distinctQueryCount: positiveInt,
670
+ queryReformulations: nonNegativeInt,
671
+ acceptedTargetRank: positiveInt.nullable(),
672
+ reciprocalRank: ratio.nullable(),
673
+ targetWasReturned: z.boolean(),
674
+ targetFirstReturnedAtSearch: positiveInt.nullable(),
675
+ targetAcceptedAtSearch: positiveInt.nullable(),
676
+ selectionLagSearches: nonNegativeInt.nullable(),
677
+ directHit: z.boolean(),
678
+ eligibleCandidatesExamined: nonNegativeInt,
679
+ uniqueCandidatesExposed: nonNegativeInt,
680
+ uniqueFilesExposed: nonNegativeInt,
681
+ navigationEventsToTarget: nonNegativeInt,
682
+ observedToolAndFileHops: positiveInt,
683
+ meanCandidateFileDispersion: ratio.nullable(),
684
+ meanCandidateChurn: ratio.nullable(),
685
+ candidateLimitHitRate: ratio,
686
+ healthyRetrievalRate: ratio,
687
+ acceptedTargetScoreMargin: finite.nullable(),
688
+ acceptedTargetCodeComplexity: searchJourneyTargetCodeComplexitySchema.optional(),
689
+ measurementContextId: nonEmpty,
690
+ measurementContextComplete: z.boolean(),
691
+ caveats: stringArray,
692
+ })
693
+ .strict();
694
+ const journeyExecutionValueSchema = z
695
+ .object({ fingerprint: sha256Fingerprint, text: text.optional() })
696
+ .strict();
697
+ const journeyExecutionContextSchema = z
698
+ .object({
699
+ schemaVersion: z.literal(1),
700
+ source: z.literal("caller-declared"),
701
+ agentModel: journeyExecutionValueSchema,
702
+ harness: journeyExecutionValueSchema,
703
+ searchStrategy: journeyExecutionValueSchema,
704
+ taskClass: journeyExecutionValueSchema,
705
+ taskMix: journeyExecutionValueSchema.optional(),
706
+ priorContext: journeyExecutionValueSchema.optional(),
707
+ })
708
+ .strict();
709
+ const journeyExecutionEvidenceSchema = z
710
+ .object({
711
+ status: z.enum(["caller-declared", "not-recorded"]),
712
+ fingerprint: sha256Fingerprint.optional(),
713
+ uncontrolledDimensions: z.array(z.enum(SEARCH_JOURNEY_EXECUTION_CONTEXT_DIMENSIONS)),
714
+ })
715
+ .strict()
716
+ .superRefine((evidence, context) => {
717
+ if ((evidence.status === "caller-declared") !== (evidence.fingerprint !== undefined)) {
718
+ context.addIssue({
719
+ code: "custom",
720
+ message: "caller-declared conditions require a fingerprint",
721
+ });
722
+ }
723
+ if (new Set(evidence.uncontrolledDimensions).size !== evidence.uncontrolledDimensions.length) {
724
+ context.addIssue({ code: "custom", message: "uncontrolled dimensions must be unique" });
725
+ }
726
+ const allowedMissing = evidence.status === "not-recorded"
727
+ ? SEARCH_JOURNEY_EXECUTION_CONTEXT_DIMENSIONS
728
+ : ["taskMix", "priorContext"];
729
+ if (evidence.uncontrolledDimensions.some((dimension) => !allowedMissing.includes(dimension)) ||
730
+ (evidence.status === "not-recorded" &&
731
+ evidence.uncontrolledDimensions.length !==
732
+ SEARCH_JOURNEY_EXECUTION_CONTEXT_DIMENSIONS.length)) {
733
+ context.addIssue({
734
+ code: "custom",
735
+ message: "missing execution dimensions must agree with declaration status",
736
+ });
737
+ }
738
+ });
739
+ const searchJourneySchema = z
740
+ .object({
741
+ schemaVersion: z.literal(1),
742
+ revision: nonNegativeInt,
743
+ sessionId: nonEmpty,
744
+ workspaceId: nonEmpty,
745
+ status: z.enum(["active", "completed", "abandoned"]),
746
+ recordingConsent: z.literal("explicit"),
747
+ retainText: z.boolean(),
748
+ goal: z.object({ fingerprint: nonEmpty, text: text.optional() }).strict(),
749
+ feature: z
750
+ .object({ fingerprint: sha256Fingerprint, text: text.optional() })
751
+ .strict()
752
+ .optional(),
753
+ executionContext: journeyExecutionContextSchema.optional(),
754
+ createdAt: nonEmpty,
755
+ updatedAt: nonEmpty,
756
+ attempts: z.array(searchJourneyAttemptSchema),
757
+ navigation: z.array(z
758
+ .object({
759
+ eventId: nonEmpty,
760
+ sequence: positiveInt,
761
+ kind: z.enum(["open-file", "open-symbol", "graph-query", "other-tool"]),
762
+ observedAt: nonEmpty,
763
+ toolName: nonEmpty.optional(),
764
+ target: searchJourneyTargetSchema.optional(),
765
+ })
766
+ .strict()),
767
+ outcome: z
768
+ .discriminatedUnion("kind", [
769
+ z
770
+ .object({
771
+ kind: z.literal("completed"),
772
+ completedAt: nonEmpty,
773
+ target: searchJourneyTargetSchema,
774
+ acceptedAttemptId: nonEmpty.optional(),
775
+ assessment: dynamicSearchComplexitySchema,
776
+ })
777
+ .strict(),
778
+ z
779
+ .object({
780
+ kind: z.literal("abandoned"),
781
+ abandonedAt: nonEmpty,
782
+ reasonCode: z.enum(SEARCH_JOURNEY_ABANDON_REASON_CODES).optional(),
783
+ reason: text.optional(),
784
+ })
785
+ .strict(),
786
+ ])
787
+ .optional(),
788
+ })
789
+ .strict()
790
+ .superRefine((session, context) => {
791
+ const validationIssue = searchJourneyValidationIssue(session);
792
+ if (validationIssue !== null) {
793
+ context.addIssue({
794
+ code: "custom",
795
+ message: `invalid search journey: ${validationIssue}`,
796
+ });
797
+ }
798
+ const terminalKind = session.outcome?.kind;
799
+ if ((session.status === "active" && terminalKind !== undefined) ||
800
+ (session.status === "completed" && terminalKind !== "completed") ||
801
+ (session.status === "abandoned" && terminalKind !== "abandoned")) {
802
+ context.addIssue({
803
+ code: "custom",
804
+ message: "search journey status and outcome are inconsistent",
805
+ });
806
+ }
807
+ if (!session.retainText &&
808
+ (session.goal.text !== undefined ||
809
+ session.attempts.some((attempt) => attempt.queryText !== undefined || attempt.failureReason !== undefined))) {
810
+ context.addIssue({
811
+ code: "custom",
812
+ message: "redacted search journey contains retained text",
813
+ });
814
+ }
815
+ if (session.attempts.some((attempt, index) => attempt.sequence !== index + 1)) {
816
+ context.addIssue({ code: "custom", message: "search journey attempts are not ordered" });
817
+ }
818
+ const numbered = session.attempts.filter((attempt) => attempt.clientStep !== undefined);
819
+ if (numbered.length !== 0 && numbered.length !== session.attempts.length) {
820
+ context.addIssue({
821
+ code: "custom",
822
+ message: "search journey mixes numbered and unnumbered attempts",
823
+ });
824
+ }
825
+ });
826
+ const dynamicProductComplexityCohortSchema = z
827
+ .object({
828
+ measurementContextId: sha256Fingerprint,
829
+ completedSessionCount: positiveInt,
830
+ measurementContextComplete: z.boolean(),
831
+ sufficientEvidence: z.boolean(),
832
+ minimumCompletedSessions: z.literal(MINIMUM_PRODUCT_COMPLEXITY_SESSIONS),
833
+ executionContext: journeyExecutionEvidenceSchema.optional(),
834
+ callerConditionsControlled: z.boolean().optional(),
835
+ medianSearchesToTarget: finite.positive(),
836
+ p90SearchesToTarget: finite.positive(),
837
+ medianQueryReformulations: nonNegative,
838
+ medianAcceptedTargetRank: finite.positive().nullable(),
839
+ meanReciprocalRank: ratio.nullable(),
840
+ targetReturnedRate: ratio,
841
+ directHitRate: ratio,
842
+ healthyRetrievalRate: ratio,
843
+ medianEligibleCandidatesExamined: nonNegative,
844
+ medianUniqueFilesExposed: nonNegative,
845
+ meanCandidateFileDispersion: ratio.nullable(),
846
+ meanCandidateChurn: ratio.nullable(),
847
+ candidateLimitHitRate: ratio,
848
+ caveats: stringArray,
849
+ })
850
+ .strict()
851
+ .superRefine((cohort, context) => {
852
+ if (cohort.callerConditionsControlled !== undefined &&
853
+ cohort.callerConditionsControlled !==
854
+ (cohort.executionContext?.status === "caller-declared" &&
855
+ cohort.executionContext.uncontrolledDimensions.length === 0)) {
856
+ context.addIssue({
857
+ code: "custom",
858
+ message: "caller conditions require all declared dimensions",
859
+ });
860
+ }
861
+ const expectedSufficient = cohort.measurementContextComplete &&
862
+ cohort.completedSessionCount >= cohort.minimumCompletedSessions;
863
+ if (cohort.sufficientEvidence !== expectedSufficient) {
864
+ context.addIssue({
865
+ code: "custom",
866
+ path: ["sufficientEvidence"],
867
+ message: "sufficient evidence requires a complete context and the minimum cohort size",
868
+ });
869
+ }
870
+ if (cohort.p90SearchesToTarget < cohort.medianSearchesToTarget) {
871
+ context.addIssue({
872
+ code: "custom",
873
+ path: ["p90SearchesToTarget"],
874
+ message: "p90 searches must not be below the median",
875
+ });
876
+ }
877
+ if (cohort.measurementContextComplete && cohort.healthyRetrievalRate !== 1) {
878
+ context.addIssue({
879
+ code: "custom",
880
+ path: ["healthyRetrievalRate"],
881
+ message: "a complete measurement context requires fully healthy retrieval",
882
+ });
883
+ }
884
+ if (cohort.directHitRate > cohort.targetReturnedRate) {
885
+ context.addIssue({
886
+ code: "custom",
887
+ path: ["directHitRate"],
888
+ message: "the direct-hit rate cannot exceed the target-returned rate",
889
+ });
890
+ }
891
+ });
892
+ const featureCodeComplexityVariantSchema = z
893
+ .object({
894
+ evidence: searchJourneyTargetCodeComplexitySchema,
895
+ completedSessionCount: positiveInt,
896
+ })
897
+ .strict();
898
+ const featureCodeTargetMappingSchema = z
899
+ .object({
900
+ target: searchJourneyTargetSchema,
901
+ completedSessionCount: positiveInt,
902
+ complexityVariants: z.array(featureCodeComplexityVariantSchema).min(1),
903
+ })
904
+ .strict()
905
+ .superRefine((mapping, context) => {
906
+ const variantKeys = mapping.complexityVariants.map((variant) => canonicalJson(variant.evidence));
907
+ if (new Set(variantKeys).size !== variantKeys.length) {
908
+ context.addIssue({
909
+ code: "custom",
910
+ path: ["complexityVariants"],
911
+ message: "complexity evidence variants must be unique",
912
+ });
913
+ }
914
+ for (const [index, variant] of mapping.complexityVariants.entries()) {
915
+ if (variant.evidence.status !== "observed")
916
+ continue;
917
+ const candidate = variant.evidence.candidate;
918
+ const target = mapping.target;
919
+ const matches = (target.repoId === undefined || target.repoId === candidate.repoId) &&
920
+ (target.refId === undefined || target.refId === candidate.refId) &&
921
+ (target.filePath === undefined || target.filePath === candidate.filePath) &&
922
+ (target.chunkId === undefined || target.chunkId === candidate.chunkId) &&
923
+ (target.symbolId === undefined || target.symbolId === candidate.symbolId) &&
924
+ (target.embeddingProfileId === undefined ||
925
+ target.embeddingProfileId === candidate.embeddingProfileId) &&
926
+ (target.indexGeneration === undefined ||
927
+ target.indexGeneration === candidate.indexGeneration);
928
+ if (!matches) {
929
+ context.addIssue({
930
+ code: "custom",
931
+ path: ["complexityVariants", index, "evidence", "candidate"],
932
+ message: "observed complexity candidate must match the confirmed target locator",
933
+ });
934
+ }
935
+ }
936
+ const variantSessions = mapping.complexityVariants.reduce((sum, variant) => sum + variant.completedSessionCount, 0);
937
+ if (variantSessions !== mapping.completedSessionCount) {
938
+ context.addIssue({
939
+ code: "custom",
940
+ path: ["complexityVariants"],
941
+ message: "complexity variants must account for every completed target session",
942
+ });
943
+ }
944
+ });
945
+ const dynamicProductComplexityFeatureMappingSchema = z
946
+ .object({
947
+ featureFingerprint: sha256Fingerprint,
948
+ measurementContextId: sha256Fingerprint,
949
+ distinctGoalCount: positiveInt,
950
+ search: dynamicProductComplexityCohortSchema,
951
+ code: z
952
+ .object({
953
+ confirmedTargetCount: positiveInt,
954
+ observedComplexitySessionCount: nonNegativeInt,
955
+ unavailableComplexitySessionCount: nonNegativeInt,
956
+ targets: z.array(featureCodeTargetMappingSchema).min(1),
957
+ })
958
+ .strict(),
959
+ caveats: stringArray,
960
+ })
961
+ .strict()
962
+ .superRefine((mapping, context) => {
963
+ if (mapping.search.measurementContextId !== mapping.measurementContextId) {
964
+ context.addIssue({
965
+ code: "custom",
966
+ path: ["search", "measurementContextId"],
967
+ message: "feature mapping and search cohort must share a measurement context",
968
+ });
969
+ }
970
+ if (mapping.distinctGoalCount > mapping.search.completedSessionCount) {
971
+ context.addIssue({
972
+ code: "custom",
973
+ path: ["distinctGoalCount"],
974
+ message: "distinct goals cannot exceed completed feature sessions",
975
+ });
976
+ }
977
+ if (mapping.code.confirmedTargetCount !== mapping.code.targets.length) {
978
+ context.addIssue({
979
+ code: "custom",
980
+ path: ["code", "confirmedTargetCount"],
981
+ message: "confirmed target count must equal the target mapping count",
982
+ });
983
+ }
984
+ const targetKeys = mapping.code.targets.map((target) => canonicalJson(target.target));
985
+ if (new Set(targetKeys).size !== targetKeys.length) {
986
+ context.addIssue({
987
+ code: "custom",
988
+ path: ["code", "targets"],
989
+ message: "confirmed feature targets must be unique",
990
+ });
991
+ }
992
+ const targetSessions = mapping.code.targets.reduce((sum, target) => sum + target.completedSessionCount, 0);
993
+ if (targetSessions !== mapping.search.completedSessionCount) {
994
+ context.addIssue({
995
+ code: "custom",
996
+ path: ["code", "targets"],
997
+ message: "target mappings must account for every completed feature session",
998
+ });
999
+ }
1000
+ const observedSessions = mapping.code.targets.reduce((sum, target) => sum +
1001
+ target.complexityVariants.reduce((targetSum, variant) => targetSum +
1002
+ (variant.evidence.status === "observed" ? variant.completedSessionCount : 0), 0), 0);
1003
+ if (observedSessions !== mapping.code.observedComplexitySessionCount ||
1004
+ targetSessions - observedSessions !== mapping.code.unavailableComplexitySessionCount) {
1005
+ context.addIssue({
1006
+ code: "custom",
1007
+ path: ["code"],
1008
+ message: "observed and unavailable complexity counts must partition feature sessions",
1009
+ });
1010
+ }
1011
+ });
1012
+ const journeyOutcomeCohortSchema = z
1013
+ .object({
1014
+ measurementContextId: sha256Fingerprint,
1015
+ retrievalContextId: sha256Fingerprint,
1016
+ executionContext: journeyExecutionEvidenceSchema,
1017
+ featureFingerprint: sha256Fingerprint.optional(),
1018
+ distinctGoalCount: positiveInt,
1019
+ sessionCounts: z
1020
+ .object({
1021
+ total: positiveInt,
1022
+ active: nonNegativeInt,
1023
+ completed: nonNegativeInt,
1024
+ abandoned: nonNegativeInt,
1025
+ terminal: nonNegativeInt,
1026
+ })
1027
+ .strict(),
1028
+ terminalCompletionRate: ratio.nullable(),
1029
+ retrievalContextComplete: z.boolean(),
1030
+ statusEffort: z.array(z
1031
+ .object({
1032
+ status: z.enum(["active", "completed", "abandoned"]),
1033
+ sessionCount: nonNegativeInt,
1034
+ sessionsWithSearches: nonNegativeInt,
1035
+ totalSearches: nonNegativeInt,
1036
+ failedSearches: nonNegativeInt,
1037
+ totalNavigationEvents: nonNegativeInt,
1038
+ totalObservedHops: nonNegativeInt,
1039
+ medianSearches: nonNegative.nullable(),
1040
+ })
1041
+ .strict()),
1042
+ abandonmentReasons: z.array(z
1043
+ .object({
1044
+ reasonCode: z.enum([...SEARCH_JOURNEY_ABANDON_REASON_CODES, "not-recorded"]),
1045
+ count: positiveInt,
1046
+ })
1047
+ .strict()),
1048
+ caveats: stringArray,
1049
+ })
1050
+ .strict()
1051
+ .superRefine((cohort, context) => {
1052
+ const counts = cohort.sessionCounts;
1053
+ if (counts.total !== counts.active + counts.completed + counts.abandoned ||
1054
+ counts.terminal !== counts.completed + counts.abandoned ||
1055
+ cohort.distinctGoalCount > counts.total) {
1056
+ context.addIssue({
1057
+ code: "custom",
1058
+ message: "outcome session counts must partition their cohort",
1059
+ });
1060
+ }
1061
+ const expectedRate = counts.terminal === 0 ? null : counts.completed / counts.terminal;
1062
+ if (cohort.terminalCompletionRate !== expectedRate) {
1063
+ context.addIssue({
1064
+ code: "custom",
1065
+ message: "completion rate must use completed plus abandoned sessions",
1066
+ });
1067
+ }
1068
+ if (cohort.statusEffort.length !== 3 ||
1069
+ new Set(cohort.statusEffort.map((effort) => effort.status)).size !== 3) {
1070
+ context.addIssue({
1071
+ code: "custom",
1072
+ message: "outcome effort must include each session status once",
1073
+ });
1074
+ }
1075
+ for (const effort of cohort.statusEffort) {
1076
+ if (effort.sessionCount !== counts[effort.status] ||
1077
+ effort.sessionsWithSearches > effort.sessionCount ||
1078
+ effort.sessionsWithSearches > effort.totalSearches ||
1079
+ effort.failedSearches > effort.totalSearches ||
1080
+ effort.totalObservedHops !== effort.totalSearches + effort.totalNavigationEvents ||
1081
+ (effort.sessionCount === 0) !== (effort.medianSearches === null) ||
1082
+ (effort.sessionCount === 0 && effort.totalObservedHops !== 0) ||
1083
+ (effort.sessionsWithSearches === 0) !== (effort.totalSearches === 0) ||
1084
+ (effort.medianSearches !== null && effort.medianSearches > effort.totalSearches)) {
1085
+ context.addIssue({
1086
+ code: "custom",
1087
+ message: "outcome effort must account for its status sessions and observations",
1088
+ });
1089
+ }
1090
+ }
1091
+ if (cohort.abandonmentReasons.reduce((sum, reason) => sum + reason.count, 0) !==
1092
+ counts.abandoned ||
1093
+ new Set(cohort.abandonmentReasons.map((reason) => reason.reasonCode)).size !==
1094
+ cohort.abandonmentReasons.length) {
1095
+ context.addIssue({
1096
+ code: "custom",
1097
+ message: "abandonment reasons must partition abandoned sessions",
1098
+ });
1099
+ }
1100
+ });
1101
+ const dynamicProductComplexityReportSchema = z
1102
+ .object({
1103
+ schemaVersion: z.literal(1),
1104
+ algorithm: z.literal("untangle-dynamic-search-complexity-v1"),
1105
+ isHeuristic: z.literal(true),
1106
+ workspaceId: nonEmpty,
1107
+ generatedAt: nonEmpty,
1108
+ sessionCounts: z
1109
+ .object({
1110
+ total: nonNegativeInt,
1111
+ active: nonNegativeInt,
1112
+ completed: nonNegativeInt,
1113
+ featureTaggedCompleted: nonNegativeInt,
1114
+ abandoned: nonNegativeInt,
1115
+ })
1116
+ .strict(),
1117
+ cohorts: z.array(dynamicProductComplexityCohortSchema),
1118
+ featureMappings: z.array(dynamicProductComplexityFeatureMappingSchema),
1119
+ outcomeCohorts: z.array(journeyOutcomeCohortSchema).optional(),
1120
+ caveats: stringArray,
1121
+ })
1122
+ .strict()
1123
+ .superRefine((report, context) => {
1124
+ const counts = report.sessionCounts;
1125
+ if (report.outcomeCohorts !== undefined) {
1126
+ const keys = report.outcomeCohorts.map((cohort) => `${cohort.measurementContextId}:${cohort.featureFingerprint ?? ""}`);
1127
+ for (const status of ["total", "active", "completed", "abandoned"]) {
1128
+ if (report.outcomeCohorts.reduce((sum, cohort) => sum + cohort.sessionCounts[status], 0) !==
1129
+ counts[status]) {
1130
+ context.addIssue({
1131
+ code: "custom",
1132
+ message: "outcome cohorts must partition all recorded sessions",
1133
+ });
1134
+ }
1135
+ }
1136
+ if (new Set(keys).size !== keys.length) {
1137
+ context.addIssue({
1138
+ code: "custom",
1139
+ message: "outcome context and feature pairs must be unique",
1140
+ });
1141
+ }
1142
+ }
1143
+ if (counts.total !== counts.active + counts.completed + counts.abandoned) {
1144
+ context.addIssue({
1145
+ code: "custom",
1146
+ path: ["sessionCounts", "total"],
1147
+ message: "total sessions must equal active, completed and abandoned sessions",
1148
+ });
1149
+ }
1150
+ if (counts.featureTaggedCompleted > counts.completed) {
1151
+ context.addIssue({
1152
+ code: "custom",
1153
+ path: ["sessionCounts", "featureTaggedCompleted"],
1154
+ message: "feature-tagged completed sessions cannot exceed completed sessions",
1155
+ });
1156
+ }
1157
+ const contextIds = report.cohorts.map((cohort) => cohort.measurementContextId);
1158
+ if (new Set(contextIds).size !== contextIds.length) {
1159
+ context.addIssue({
1160
+ code: "custom",
1161
+ path: ["cohorts"],
1162
+ message: "measurement context IDs must be unique",
1163
+ });
1164
+ }
1165
+ const cohortSessions = report.cohorts.reduce((sum, cohort) => sum + cohort.completedSessionCount, 0);
1166
+ if (cohortSessions !== counts.completed) {
1167
+ context.addIssue({
1168
+ code: "custom",
1169
+ path: ["cohorts"],
1170
+ message: "every completed session must belong to exactly one cohort",
1171
+ });
1172
+ }
1173
+ const featureKeys = report.featureMappings.map((mapping) => `${mapping.featureFingerprint}\u001f${mapping.measurementContextId}`);
1174
+ if (new Set(featureKeys).size !== featureKeys.length) {
1175
+ context.addIssue({
1176
+ code: "custom",
1177
+ path: ["featureMappings"],
1178
+ message: "feature and measurement-context pairs must be unique",
1179
+ });
1180
+ }
1181
+ const featureSessions = report.featureMappings.reduce((sum, mapping) => sum + mapping.search.completedSessionCount, 0);
1182
+ if (featureSessions !== counts.featureTaggedCompleted) {
1183
+ context.addIssue({
1184
+ code: "custom",
1185
+ path: ["featureMappings"],
1186
+ message: "feature mappings must account for every feature-tagged completed session",
1187
+ });
1188
+ }
1189
+ const knownContexts = new Set(contextIds);
1190
+ for (const [index, mapping] of report.featureMappings.entries()) {
1191
+ if (!knownContexts.has(mapping.measurementContextId)) {
1192
+ context.addIssue({
1193
+ code: "custom",
1194
+ path: ["featureMappings", index, "measurementContextId"],
1195
+ message: "feature mapping must reference an existing workspace cohort",
1196
+ });
1197
+ }
1198
+ }
1199
+ for (const cohort of report.cohorts) {
1200
+ const taggedInContext = report.featureMappings
1201
+ .filter((mapping) => mapping.measurementContextId === cohort.measurementContextId)
1202
+ .reduce((sum, mapping) => sum + mapping.search.completedSessionCount, 0);
1203
+ if (taggedInContext > cohort.completedSessionCount) {
1204
+ context.addIssue({
1205
+ code: "custom",
1206
+ path: ["featureMappings"],
1207
+ message: "feature sessions in a context cannot exceed its completed cohort sessions",
1208
+ });
1209
+ }
1210
+ }
1211
+ });
1212
+ const searchSessionResultSchema = z.discriminatedUnion("action", [
1213
+ z.object({ action: z.literal("start"), session: searchJourneySchema }).strict(),
1214
+ z.object({ action: z.literal("get"), session: searchJourneySchema }).strict(),
1215
+ z.object({ action: z.literal("observe"), session: searchJourneySchema }).strict(),
1216
+ z.object({ action: z.literal("complete"), session: searchJourneySchema }).strict(),
1217
+ z.object({ action: z.literal("abandon"), session: searchJourneySchema }).strict(),
1218
+ z.object({ action: z.literal("report"), report: dynamicProductComplexityReportSchema }).strict(),
1219
+ ]);
1220
+ const graphConfidenceSchema = z
1221
+ .object({ value: ratio, basis: z.enum(["deterministic", "heuristic"]), signals: stringArray })
1222
+ .strict();
1223
+ const symbolNodeSchema = z
1224
+ .object({
1225
+ id: nonEmpty,
1226
+ name: text,
1227
+ qualifiedName: text,
1228
+ kind: text,
1229
+ signature: text.optional(),
1230
+ repoId: nonEmpty,
1231
+ refId: nonEmpty,
1232
+ fileId: nonEmpty,
1233
+ filePath: text,
1234
+ language: text,
1235
+ startLine: positiveInt,
1236
+ endLine: positiveInt,
1237
+ startByte: nonNegativeInt,
1238
+ endByte: nonNegativeInt,
1239
+ exportedAs: stringArray.optional(),
1240
+ visibility: text.optional(),
1241
+ contentHash: text,
1242
+ })
1243
+ .strict();
1244
+ const symbolEdgeTargetSchema = z
1245
+ .object({
1246
+ symbolId: nonEmpty,
1247
+ qualifiedName: text,
1248
+ repoId: nonEmpty,
1249
+ refId: nonEmpty,
1250
+ filePath: text,
1251
+ })
1252
+ .strict();
1253
+ const symbolEdgeSchema = z
1254
+ .object({
1255
+ schemaVersion: z.literal(1),
1256
+ edgeId: nonEmpty,
1257
+ workspaceId: nonEmpty,
1258
+ repoId: nonEmpty,
1259
+ refId: nonEmpty,
1260
+ fromSymbolId: nonEmpty,
1261
+ kind: z.enum(["calls", "references", "extends", "implements", "overrides", "unresolved"]),
1262
+ toName: text,
1263
+ toQualifier: text.optional(),
1264
+ resolution: z.enum(["exact", "heuristic", "ambiguous", "unresolved"]),
1265
+ target: symbolEdgeTargetSchema.optional(),
1266
+ candidates: z.array(symbolEdgeTargetSchema.extend({ weight: ratio }).strict()).optional(),
1267
+ unresolvedReason: z
1268
+ .enum([
1269
+ "no_candidate_found",
1270
+ "target_outside_index",
1271
+ "target_in_unparsed_file",
1272
+ "dynamic_dispatch_not_statically_analyzable",
1273
+ "import_unresolved",
1274
+ "budget_exceeded",
1275
+ ])
1276
+ .optional(),
1277
+ unresolvedDetail: text.optional(),
1278
+ confidence: graphConfidenceSchema,
1279
+ crossRepo: z.boolean(),
1280
+ sites: z.array(z
1281
+ .object({
1282
+ repoId: nonEmpty,
1283
+ refId: nonEmpty,
1284
+ filePath: text,
1285
+ range: sourceRangeSchema,
1286
+ column: positiveInt.optional(),
1287
+ })
1288
+ .strict()),
1289
+ sitesMissingReason: text.optional(),
1290
+ occurrenceOrdinal: nonNegativeInt,
1291
+ graphGeneration: nonEmpty,
1292
+ graphVersion: nonEmpty,
1293
+ })
1294
+ .strict();
1295
+ const symbolBindingSchema = z
1296
+ .object({
1297
+ symbolId: nonEmpty,
1298
+ edgeId: nonEmpty,
1299
+ resolution: z.enum(["exact", "heuristic", "ambiguous", "unresolved"]),
1300
+ weight: ratio,
1301
+ ambiguous: z.boolean(),
1302
+ })
1303
+ .strict();
1304
+ const traversalLimitsSchema = z
1305
+ .object({
1306
+ maxDepth: nonNegativeInt,
1307
+ maxNodes: positiveInt,
1308
+ maxEdges: positiveInt,
1309
+ maxWallTimeMs: positiveInt,
1310
+ })
1311
+ .strict();
1312
+ const traversalResultSchema = z
1313
+ .object({
1314
+ schemaVersion: z.literal(1),
1315
+ direction: z.enum(["forward", "reverse"]),
1316
+ rootSymbolIds: stringArray,
1317
+ visitedSymbolIds: stringArray,
1318
+ edgeIds: stringArray,
1319
+ depthReached: nonNegativeInt,
1320
+ truncated: z.boolean(),
1321
+ truncationReason: z
1322
+ .enum(["max_depth", "max_nodes", "max_edges", "max_wall_time", "cancelled"])
1323
+ .optional(),
1324
+ revisitSkippedSymbolIds: stringArray,
1325
+ limits: traversalLimitsSchema,
1326
+ })
1327
+ .strict();
1328
+ const callPathSchema = z
1329
+ .object({
1330
+ schemaVersion: z.literal(1),
1331
+ symbolIds: stringArray,
1332
+ edgeIds: stringArray,
1333
+ depth: nonNegativeInt,
1334
+ confidence: ratio,
1335
+ weakestResolution: z.enum(["exact", "heuristic", "ambiguous", "unresolved"]),
1336
+ containsAmbiguous: z.boolean(),
1337
+ })
1338
+ .strict();
1339
+ const shortestPathSchema = z
1340
+ .object({
1341
+ schemaVersion: z.literal(1),
1342
+ path: callPathSchema.nullable(),
1343
+ missReason: z
1344
+ .enum(["unknown_source_symbol", "unknown_target_symbol", "no_path_within_limits"])
1345
+ .optional(),
1346
+ missDetail: text.optional(),
1347
+ truncated: z.boolean(),
1348
+ truncationReason: z
1349
+ .enum(["max_depth", "max_nodes", "max_edges", "max_wall_time", "cancelled"])
1350
+ .optional(),
1351
+ limits: traversalLimitsSchema,
1352
+ })
1353
+ .strict();
1354
+ const allPathsSchema = z
1355
+ .object({
1356
+ schemaVersion: z.literal(1),
1357
+ paths: z.array(callPathSchema),
1358
+ missReason: z
1359
+ .enum(["unknown_source_symbol", "unknown_target_symbol", "no_path_within_limits"])
1360
+ .optional(),
1361
+ missDetail: text.optional(),
1362
+ truncated: z.boolean(),
1363
+ truncationReason: z
1364
+ .enum(["max_depth", "max_nodes", "max_edges", "max_wall_time", "max_paths", "cancelled"])
1365
+ .optional(),
1366
+ droppedPathCount: nonNegativeInt,
1367
+ droppedPathCountExact: z.boolean(),
1368
+ pathLimitReached: z.boolean(),
1369
+ skipped: z.array(skipLedgerEntrySchema),
1370
+ maxDepth: nonNegativeInt,
1371
+ })
1372
+ .strict();
1373
+ const impactResultSchema = z
1374
+ .object({
1375
+ schemaVersion: z.literal(1),
1376
+ rootSymbolIds: stringArray,
1377
+ affected: z.array(z
1378
+ .object({
1379
+ symbolId: nonEmpty,
1380
+ qualifiedName: text,
1381
+ filePath: text,
1382
+ repoId: nonEmpty,
1383
+ depth: nonNegativeInt,
1384
+ minDepth: nonNegativeInt,
1385
+ confidence: ratio,
1386
+ weakestResolution: z.enum(["exact", "heuristic", "ambiguous", "unresolved"]),
1387
+ viaEdgeIds: stringArray,
1388
+ throughAmbiguous: z.boolean(),
1389
+ })
1390
+ .strict()),
1391
+ containsAmbiguousEdges: z.boolean(),
1392
+ ambiguousEdgeIds: stringArray,
1393
+ minConfidence: ratio,
1394
+ traversal: traversalResultSchema,
1395
+ skipped: z.array(skipLedgerEntrySchema),
1396
+ })
1397
+ .strict();
1398
+ const fileNodeSchema = z
1399
+ .object({
1400
+ schemaVersion: z.literal(1),
1401
+ workspaceId: nonEmpty,
1402
+ repoId: nonEmpty,
1403
+ refId: nonEmpty,
1404
+ fileId: nonEmpty,
1405
+ filePath: text,
1406
+ language: text,
1407
+ contentHash: text,
1408
+ imports: stringArray,
1409
+ dependencies: stringArray,
1410
+ dependents: stringArray,
1411
+ graphGeneration: nonEmpty,
1412
+ packageName: text.optional(),
1413
+ containerService: text.optional(),
1414
+ unresolvedImportCount: nonNegativeInt,
1415
+ })
1416
+ .strict();
1417
+ const fileEdgeResolutionSchema = z.discriminatedUnion("status", [
1418
+ z
1419
+ .object({
1420
+ status: z.literal("resolved"),
1421
+ mechanism: nonEmpty,
1422
+ targetFileId: nonEmpty,
1423
+ targetRepoId: nonEmpty,
1424
+ targetRefId: nonEmpty,
1425
+ targetPath: text,
1426
+ viaPackageName: text.optional(),
1427
+ })
1428
+ .strict(),
1429
+ z
1430
+ .object({
1431
+ status: z.literal("external"),
1432
+ mechanism: nonEmpty,
1433
+ packageName: nonEmpty,
1434
+ declaredVersion: text.optional(),
1435
+ })
1436
+ .strict(),
1437
+ z
1438
+ .object({
1439
+ status: z.literal("unresolved"),
1440
+ reason: nonEmpty,
1441
+ detail: nonEmpty,
1442
+ rejectedCandidates: stringArray.optional(),
1443
+ })
1444
+ .strict(),
1445
+ ]);
1446
+ const fileEdgeSchema = z
1447
+ .object({
1448
+ schemaVersion: z.literal(1),
1449
+ edgeId: nonEmpty,
1450
+ workspaceId: nonEmpty,
1451
+ repoId: nonEmpty,
1452
+ refId: nonEmpty,
1453
+ fromFileId: nonEmpty,
1454
+ fromPath: text,
1455
+ kind: z.enum([
1456
+ "import",
1457
+ "re-export",
1458
+ "dynamic-import",
1459
+ "asset-reference",
1460
+ "config-reference",
1461
+ "unresolved",
1462
+ ]),
1463
+ rawSpecifier: nonEmpty,
1464
+ resolution: fileEdgeResolutionSchema,
1465
+ boundary: z
1466
+ .object({
1467
+ crossRepo: z.boolean(),
1468
+ crossPackage: z.boolean(),
1469
+ crossContainer: z.boolean(),
1470
+ fromPackageName: text.optional(),
1471
+ toPackageName: text.optional(),
1472
+ fromContainerService: text.optional(),
1473
+ toContainerService: text.optional(),
1474
+ })
1475
+ .strict(),
1476
+ sites: z.array(z
1477
+ .object({
1478
+ range: sourceRangeSchema,
1479
+ importedNames: stringArray.optional(),
1480
+ typeOnly: z.boolean().optional(),
1481
+ })
1482
+ .strict()),
1483
+ sitesMissingReason: text.optional(),
1484
+ occurrenceOrdinal: nonNegativeInt,
1485
+ graphGeneration: nonEmpty,
1486
+ graphVersion: nonEmpty,
1487
+ })
1488
+ .strict();
1489
+ const centralitySchema = z
1490
+ .object({
1491
+ fileId: nonEmpty,
1492
+ filePath: text,
1493
+ inDegree: nonNegativeInt,
1494
+ outDegree: nonNegativeInt,
1495
+ centrality: ratio,
1496
+ })
1497
+ .strict();
1498
+ const fileGraphMetricsSchema = z
1499
+ .object({
1500
+ schemaVersion: z.literal(1),
1501
+ workspaceId: nonEmpty,
1502
+ graphGeneration: nonEmpty,
1503
+ graphVersion: nonEmpty,
1504
+ nodeCount: nonNegativeInt,
1505
+ edgeCount: nonNegativeInt,
1506
+ orphanFileIds: stringArray,
1507
+ stronglyConnectedComponents: z.array(stringArray),
1508
+ cycles: z.array(stringArray),
1509
+ importResolution: z
1510
+ .object({
1511
+ resolvedCount: nonNegativeInt,
1512
+ externalCount: nonNegativeInt,
1513
+ unresolvedCount: nonNegativeInt,
1514
+ rate: ratio,
1515
+ })
1516
+ .strict(),
1517
+ repositoryDistribution: numberMap,
1518
+ languageDistribution: numberMap,
1519
+ topCentralFiles: z.array(centralitySchema),
1520
+ centralityFormula: nonEmpty,
1521
+ truncationReason: text.optional(),
1522
+ })
1523
+ .strict();
1524
+ const snapshotReadIssueSchema = z
1525
+ .object({
1526
+ kind: z.enum([
1527
+ "missing_meta",
1528
+ "missing_path_index",
1529
+ "missing_file_shard",
1530
+ "malformed_payload",
1531
+ "count_mismatch",
1532
+ "workspace_scope_required",
1533
+ "scope_mismatch",
1534
+ ]),
1535
+ message: nonEmpty,
1536
+ })
1537
+ .strict();
1538
+ const fileTraversalSchema = z
1539
+ .object({
1540
+ schemaVersion: z.literal(1),
1541
+ direction: z.enum(["forward", "reverse"]),
1542
+ rootFileIds: stringArray,
1543
+ visitedFileIds: stringArray,
1544
+ edgeIds: stringArray,
1545
+ depthReached: nonNegativeInt,
1546
+ truncated: z.boolean(),
1547
+ truncationReason: z
1548
+ .enum(["max_depth", "max_nodes", "max_edges", "max_wall_time", "cancelled"])
1549
+ .optional(),
1550
+ revisitSkippedFileIds: stringArray,
1551
+ cycles: z.array(stringArray),
1552
+ unvisitedRootFileIds: stringArray.optional(),
1553
+ unknownRootFileIds: stringArray.optional(),
1554
+ limits: traversalLimitsSchema,
1555
+ visitedPaths: stringArray,
1556
+ cyclePaths: z.array(stringArray),
1557
+ })
1558
+ .strict();
1559
+ const boundaryCountsSchema = z
1560
+ .object({
1561
+ crossRepo: nonNegativeInt,
1562
+ crossPackage: nonNegativeInt,
1563
+ crossContainer: nonNegativeInt,
1564
+ })
1565
+ .strict();
1566
+ const graphFileViewSchema = z
1567
+ .object({
1568
+ generationId: nonEmpty,
1569
+ workspaceId: nonEmpty,
1570
+ node: fileNodeSchema,
1571
+ edges: z.array(fileEdgeSchema),
1572
+ dependencies: fileTraversalSchema.optional(),
1573
+ dependents: fileTraversalSchema.optional(),
1574
+ issues: z.array(snapshotReadIssueSchema),
1575
+ })
1576
+ .strict();
1577
+ const boundedGraphFileViewSchema = graphFileViewSchema.extend({
1578
+ truncated: z.boolean(),
1579
+ omittedCount: nonNegativeInt,
1580
+ });
1581
+ const graphViewStatsSchema = z
1582
+ .object({
1583
+ inputNodeCount: nonNegativeInt,
1584
+ shownNodeCount: nonNegativeInt,
1585
+ nodeLimitDroppedCount: nonNegativeInt,
1586
+ sourceEdgeCount: nonNegativeInt,
1587
+ candidateLinkCount: nonNegativeInt,
1588
+ renderableLinkCount: nonNegativeInt,
1589
+ shownLinkCount: nonNegativeInt,
1590
+ unrenderableSourceEdgeCount: nonNegativeInt,
1591
+ missingEndpointLinkCount: nonNegativeInt,
1592
+ nodeLimitDroppedLinkCount: nonNegativeInt,
1593
+ edgeLimitDroppedLinkCount: nonNegativeInt,
1594
+ })
1595
+ .strict();
1596
+ const graphVisualizationArtifactShape = {
1597
+ path: nonEmpty,
1598
+ bytes: positiveInt,
1599
+ sha256: text.regex(/^[0-9a-f]{64}$/u),
1600
+ limits: z.object({ maxNodes: positiveInt, maxEdges: positiveInt }).strict(),
1601
+ };
1602
+ const graphVisualizationShape = {
1603
+ generationId: nonEmpty,
1604
+ workspaceId: nonEmpty,
1605
+ issues: z.array(snapshotReadIssueSchema),
1606
+ };
1607
+ const graphVisualizationSchema = z.union([
1608
+ z
1609
+ .object({
1610
+ ...graphVisualizationShape,
1611
+ artifact: z
1612
+ .object({
1613
+ ...graphVisualizationArtifactShape,
1614
+ views: z.object({ file: graphViewStatsSchema, symbol: graphViewStatsSchema }).strict(),
1615
+ })
1616
+ .strict(),
1617
+ symbolGraph: z.object({ available: z.literal(true) }).strict(),
1618
+ })
1619
+ .strict(),
1620
+ z
1621
+ .object({
1622
+ ...graphVisualizationShape,
1623
+ artifact: z
1624
+ .object({
1625
+ ...graphVisualizationArtifactShape,
1626
+ views: z.object({ file: graphViewStatsSchema, symbol: z.null() }).strict(),
1627
+ })
1628
+ .strict(),
1629
+ symbolGraph: z.object({ available: z.literal(false), missingReason: nonEmpty }).strict(),
1630
+ })
1631
+ .strict(),
1632
+ ]);
1633
+ const symbolListSchema = z
1634
+ .object({
1635
+ generationId: nonEmpty,
1636
+ symbols: z.array(symbolNodeSchema),
1637
+ total: nonNegativeInt,
1638
+ truncated: z.boolean(),
1639
+ })
1640
+ .strict();
1641
+ const symbolDetailSchema = z
1642
+ .object({
1643
+ generationId: nonEmpty,
1644
+ matchedBy: z.enum(["symbol_id", "qualified_name", "file_and_name", "name"]).optional(),
1645
+ symbol: symbolNodeSchema,
1646
+ outgoing: z.array(symbolEdgeSchema),
1647
+ callers: z.array(symbolBindingSchema),
1648
+ })
1649
+ .strict();
1650
+ const boundedFlowSymbolDetailSchema = symbolDetailSchema.extend({
1651
+ truncated: z.boolean(),
1652
+ omittedCount: nonNegativeInt,
1653
+ });
1654
+ const flowSchema = z.union([
1655
+ boundedFlowSymbolDetailSchema,
1656
+ z
1657
+ .object({
1658
+ generationId: nonEmpty,
1659
+ from: symbolNodeSchema,
1660
+ to: symbolNodeSchema,
1661
+ shortest: shortestPathSchema,
1662
+ all: allPathsSchema,
1663
+ })
1664
+ .strict(),
1665
+ ]);
1666
+ const impactSchema = z
1667
+ .object({
1668
+ generationId: nonEmpty,
1669
+ root: symbolNodeSchema,
1670
+ impact: impactResultSchema,
1671
+ truncated: z.boolean(),
1672
+ omittedCount: nonNegativeInt,
1673
+ })
1674
+ .strict();
1675
+ const proseNumberSchema = z
1676
+ .object({
1677
+ proseMeasurement: z.literal(true),
1678
+ value: finite,
1679
+ unit: z.enum(["levels", "lines", "per_100_lines", "ratio", "count"]),
1680
+ })
1681
+ .strict();
1682
+ const complexitySymbolSchema = z
1683
+ .object({
1684
+ filePath: text,
1685
+ name: text,
1686
+ kind: text,
1687
+ line: positiveInt,
1688
+ executionUnit: z.boolean(),
1689
+ cognitive: nonNegative,
1690
+ cyclomatic: nonNegative,
1691
+ sloc: nonNegative,
1692
+ })
1693
+ .strict();
1694
+ const complexityViolationSchema = z
1695
+ .object({
1696
+ filePath: text,
1697
+ line: positiveInt,
1698
+ name: text,
1699
+ metric: z.enum(["cognitive", "cyclomatic"]),
1700
+ value: nonNegative,
1701
+ threshold: finite,
1702
+ })
1703
+ .strict();
1704
+ const proseSummarySchema = z
1705
+ .object({
1706
+ path: text,
1707
+ metricsVersion: nonEmpty,
1708
+ structureLoad: proseNumberSchema,
1709
+ sectionCount: proseNumberSchema,
1710
+ sectionDepth: proseNumberSchema,
1711
+ maxSectionLines: proseNumberSchema,
1712
+ linkDensity: proseNumberSchema,
1713
+ unresolvedLinkRatio: proseNumberSchema.nullable(),
1714
+ repetitionRatio: proseNumberSchema,
1715
+ contentLines: proseNumberSchema,
1716
+ })
1717
+ .strict();
1718
+ const complexityReportSchema = z
1719
+ .object({
1720
+ schemaVersion: z.literal(1),
1721
+ root: nonEmpty,
1722
+ filesDiscovered: nonNegativeInt,
1723
+ filesAnalyzed: nonNegativeInt,
1724
+ filesProse: nonNegativeInt,
1725
+ totalsReading: z.enum(["execution_unit"]).optional(),
1726
+ totals: z
1727
+ .object({
1728
+ executionUnits: nonNegativeInt,
1729
+ executionUnitRoots: nonNegativeInt.optional(),
1730
+ cognitive: nonNegative,
1731
+ cyclomatic: nonNegative,
1732
+ })
1733
+ .strict(),
1734
+ hotspots: z.array(complexitySymbolSchema),
1735
+ violations: z.array(complexityViolationSchema),
1736
+ prose: z.array(proseSummarySchema),
1737
+ skipped: z.array(skipLedgerEntrySchema),
1738
+ })
1739
+ .strict();
1740
+ const metricContributionSchema = z
1741
+ .object({
1742
+ line: positiveInt,
1743
+ column: positiveInt.optional(),
1744
+ kind: nonEmpty,
1745
+ value: finite,
1746
+ note: text.optional(),
1747
+ })
1748
+ .strict();
1749
+ const cognitiveContributionSchema = z
1750
+ .object({
1751
+ line: positiveInt,
1752
+ column: positiveInt.optional(),
1753
+ kind: nonEmpty,
1754
+ base: finite,
1755
+ nestingPenalty: finite,
1756
+ total: finite,
1757
+ note: text.optional(),
1758
+ })
1759
+ .strict();
1760
+ const complexitySnapshotSchema = z
1761
+ .object({
1762
+ snapshotId: nonEmpty,
1763
+ scope: z.enum(["symbol", "file", "repository", "workspace"]),
1764
+ scopeId: nonEmpty,
1765
+ repoId: nonEmpty,
1766
+ refId: nonEmpty,
1767
+ commitSha: text.optional(),
1768
+ metricsVersion: nonEmpty,
1769
+ measuredAt: nonEmpty,
1770
+ parseQuality: z.enum(["complete", "partial", "failed"]),
1771
+ cyclomatic: z
1772
+ .object({
1773
+ classic: finite,
1774
+ extended: finite,
1775
+ contributors: z.array(metricContributionSchema),
1776
+ })
1777
+ .strict(),
1778
+ cognitive: z
1779
+ .object({
1780
+ value: finite,
1781
+ algorithm: nonEmpty,
1782
+ contributors: z.array(cognitiveContributionSchema),
1783
+ })
1784
+ .strict(),
1785
+ structural: numberMap,
1786
+ textual: numberMap,
1787
+ syntactic: numberMap,
1788
+ halstead: numberMap,
1789
+ maintainabilityIndex: finite,
1790
+ maintainabilityFormula: nonEmpty,
1791
+ })
1792
+ .strict();
1793
+ const metricDeltaSchema = z
1794
+ .object({
1795
+ metric: nonEmpty,
1796
+ baseValue: finite.nullable(),
1797
+ headValue: finite.nullable(),
1798
+ delta: finite.nullable(),
1799
+ relativeDelta: finite.nullable(),
1800
+ })
1801
+ .strict();
1802
+ const changeEventSchema = z
1803
+ .object({
1804
+ schemaVersion: z.literal(1),
1805
+ changeId: nonEmpty,
1806
+ workspaceId: nonEmpty,
1807
+ repoId: nonEmpty,
1808
+ baseRef: nonEmpty,
1809
+ headRef: nonEmpty,
1810
+ baseCommit: text.optional(),
1811
+ headCommit: text.optional(),
1812
+ changedAt: nonEmpty,
1813
+ changeKind: z.enum(["added", "modified", "deleted", "renamed", "moved", "moved_and_renamed"]),
1814
+ oldSymbolId: text.optional(),
1815
+ newSymbolId: text.optional(),
1816
+ oldFilePath: text.optional(),
1817
+ newFilePath: text.optional(),
1818
+ textDiffSummary: z
1819
+ .object({
1820
+ linesAdded: nonNegativeInt,
1821
+ linesRemoved: nonNegativeInt,
1822
+ hunkCount: nonNegativeInt,
1823
+ binary: z.boolean(),
1824
+ bytesAdded: nonNegativeInt.optional(),
1825
+ bytesRemoved: nonNegativeInt.optional(),
1826
+ })
1827
+ .strict(),
1828
+ astDiffSummary: z
1829
+ .object({
1830
+ nodesAdded: nonNegativeInt,
1831
+ nodesRemoved: nonNegativeInt,
1832
+ nodesMoved: nonNegativeInt,
1833
+ nodesUpdated: nonNegativeInt,
1834
+ affectedNodeKinds: stringArray,
1835
+ fingerprintChanged: z.boolean(),
1836
+ })
1837
+ .strict()
1838
+ .optional(),
1839
+ complexityDelta: z
1840
+ .object({
1841
+ metricsVersion: nonEmpty,
1842
+ epsilon: nonNegative,
1843
+ entries: z.array(metricDeltaSchema),
1844
+ })
1845
+ .strict()
1846
+ .optional(),
1847
+ graphDelta: z
1848
+ .object({
1849
+ addedFileImports: z.array(z
1850
+ .object({
1851
+ fromId: nonEmpty,
1852
+ toId: nonEmpty,
1853
+ edgeKind: nonEmpty,
1854
+ crossRepo: z.boolean(),
1855
+ })
1856
+ .strict()),
1857
+ removedFileImports: z.array(z
1858
+ .object({
1859
+ fromId: nonEmpty,
1860
+ toId: nonEmpty,
1861
+ edgeKind: nonEmpty,
1862
+ crossRepo: z.boolean(),
1863
+ })
1864
+ .strict()),
1865
+ addedSymbolCalls: z.array(z
1866
+ .object({
1867
+ fromId: nonEmpty,
1868
+ toId: nonEmpty,
1869
+ edgeKind: nonEmpty,
1870
+ crossRepo: z.boolean(),
1871
+ })
1872
+ .strict()),
1873
+ removedSymbolCalls: z.array(z
1874
+ .object({
1875
+ fromId: nonEmpty,
1876
+ toId: nonEmpty,
1877
+ edgeKind: nonEmpty,
1878
+ crossRepo: z.boolean(),
1879
+ })
1880
+ .strict()),
1881
+ addedCrossRepoEdges: z.array(z
1882
+ .object({
1883
+ fromId: nonEmpty,
1884
+ toId: nonEmpty,
1885
+ edgeKind: nonEmpty,
1886
+ crossRepo: z.boolean(),
1887
+ })
1888
+ .strict()),
1889
+ removedCrossRepoEdges: z.array(z
1890
+ .object({
1891
+ fromId: nonEmpty,
1892
+ toId: nonEmpty,
1893
+ edgeKind: nonEmpty,
1894
+ crossRepo: z.boolean(),
1895
+ })
1896
+ .strict()),
1897
+ addedCycles: z.array(stringArray),
1898
+ removedCycles: z.array(stringArray),
1899
+ fanChanges: z.array(z
1900
+ .object({
1901
+ nodeId: nonEmpty,
1902
+ fanInBefore: nonNegativeInt,
1903
+ fanInAfter: nonNegativeInt,
1904
+ fanOutBefore: nonNegativeInt,
1905
+ fanOutAfter: nonNegativeInt,
1906
+ })
1907
+ .strict()),
1908
+ impactSizeBefore: nonNegativeInt,
1909
+ impactSizeAfter: nonNegativeInt,
1910
+ })
1911
+ .strict()
1912
+ .optional(),
1913
+ blastRadius: z
1914
+ .object({
1915
+ impactedFileCount: nonNegativeInt,
1916
+ impactedSymbolCount: nonNegativeInt,
1917
+ impactedRepoIds: stringArray,
1918
+ maxDepthReached: nonNegativeInt,
1919
+ truncated: z.boolean(),
1920
+ truncationReason: text.optional(),
1921
+ sampleImpactedSymbolIds: stringArray,
1922
+ })
1923
+ .strict()
1924
+ .optional(),
1925
+ risk: z
1926
+ .object({
1927
+ value: ratio,
1928
+ level: z.enum(["low", "medium", "high", "critical"]),
1929
+ algorithm: nonEmpty,
1930
+ components: z.record(z.string(), z.object({ value: finite, weight: finite, contribution: finite }).strict()),
1931
+ caveats: stringArray,
1932
+ })
1933
+ .strict()
1934
+ .optional(),
1935
+ })
1936
+ .strict();
1937
+ const qualityGateSchema = z
1938
+ .object({
1939
+ status: z.enum(["passed", "warning", "failed", "incomplete"]),
1940
+ base: nonEmpty,
1941
+ head: nonEmpty,
1942
+ violations: z.array(z
1943
+ .object({
1944
+ rule: nonEmpty,
1945
+ severity: z.enum(["warning", "error"]),
1946
+ scope: z.enum(["symbol", "file", "workspace"]),
1947
+ scopeId: nonEmpty,
1948
+ filePath: text.optional(),
1949
+ symbolId: text.optional(),
1950
+ symbolFqn: text.optional(),
1951
+ metric: text.optional(),
1952
+ baseValue: finite.optional(),
1953
+ headValue: finite.optional(),
1954
+ threshold: finite.optional(),
1955
+ newViolation: z.boolean(),
1956
+ worsened: z.boolean(),
1957
+ message: nonEmpty,
1958
+ })
1959
+ .strict()),
1960
+ improvements: z.array(z
1961
+ .object({
1962
+ rule: nonEmpty,
1963
+ scope: z.enum(["symbol", "file", "workspace"]),
1964
+ scopeId: nonEmpty,
1965
+ filePath: text.optional(),
1966
+ symbolId: text.optional(),
1967
+ symbolFqn: text.optional(),
1968
+ metric: text.optional(),
1969
+ baseValue: finite.optional(),
1970
+ headValue: finite.optional(),
1971
+ message: nonEmpty,
1972
+ })
1973
+ .strict()),
1974
+ analysisCoverage: z
1975
+ .object({
1976
+ filesChanged: nonNegativeInt,
1977
+ filesAnalyzed: nonNegativeInt,
1978
+ symbolsChanged: nonNegativeInt,
1979
+ parseFailures: nonNegativeInt,
1980
+ })
1981
+ .strict(),
1982
+ })
1983
+ .strict();
1984
+ // Portfolio contracts: portfolio.md sections 7 and 14.2.
1985
+ const portfolioEvidenceKindSchema = z.enum([
1986
+ "manifest",
1987
+ "lockfile",
1988
+ "config",
1989
+ "import_graph",
1990
+ "symbol_graph",
1991
+ "ci",
1992
+ "container",
1993
+ "iac",
1994
+ "change_history",
1995
+ "heuristic",
1996
+ ]);
1997
+ const portfolioProvenanceSchema = z
1998
+ .object({
1999
+ workspaceId: nonEmpty,
2000
+ repoId: nonEmpty,
2001
+ refId: nonEmpty,
2002
+ commitSha: text.optional(),
2003
+ sourceFile: text,
2004
+ startLine: positiveInt.optional(),
2005
+ endLine: positiveInt.optional(),
2006
+ detectorId: nonEmpty,
2007
+ detectorVersion: nonEmpty,
2008
+ evidenceKind: portfolioEvidenceKindSchema,
2009
+ })
2010
+ .strict();
2011
+ const portfolioConfidenceSchema = z
2012
+ .object({ value: ratio, basis: z.enum(["deterministic", "heuristic"]), signals: stringArray })
2013
+ .strict();
2014
+ const repositoryHealthSchema = z
2015
+ .object({
2016
+ metricsVersion: nonEmpty,
2017
+ measuredAt: nonEmpty,
2018
+ maintainabilityIndexMedian: finite.optional(),
2019
+ cognitiveP90: finite.optional(),
2020
+ cyclomaticP90: finite.optional(),
2021
+ dependencyCycleCount: nonNegativeInt.optional(),
2022
+ hotspotShare: ratio.optional(),
2023
+ unresolvedImportRatio: ratio.optional(),
2024
+ parseFailureRatio: ratio.optional(),
2025
+ caveats: stringArray,
2026
+ })
2027
+ .strict();
2028
+ const stackMatrixEntrySchema = z
2029
+ .object({
2030
+ technologyId: nonEmpty,
2031
+ name: nonEmpty,
2032
+ category: nonEmpty,
2033
+ ecosystem: text.optional(),
2034
+ problemDomain: text.optional(),
2035
+ adoption: z
2036
+ .object({ repoCount: nonNegativeInt, repoShare: ratio, repoIds: stringArray })
2037
+ .strict(),
2038
+ versionSpread: z
2039
+ .object({
2040
+ distinctVersions: stringArray,
2041
+ byRepo: optionalStringMap,
2042
+ majorSpread: nonNegativeInt,
2043
+ comparable: z.boolean(),
2044
+ })
2045
+ .strict(),
2046
+ usageDepth: z
2047
+ .object({
2048
+ importingFilesByRepo: z.record(z.string(), nonNegativeInt),
2049
+ declaredOnlyRepos: stringArray,
2050
+ importOnlyRepos: stringArray,
2051
+ })
2052
+ .strict(),
2053
+ firstSeenAt: text.optional(),
2054
+ lastSeenAt: text.optional(),
2055
+ confidence: portfolioConfidenceSchema,
2056
+ })
2057
+ .strict();
2058
+ export const stackMatrixResultSchema = z
2059
+ .object({
2060
+ schemaVersion: z.literal(1),
2061
+ matrixId: nonEmpty,
2062
+ workspaceId: nonEmpty,
2063
+ generationId: nonEmpty,
2064
+ generatedAt: nonEmpty,
2065
+ analyzerVersion: nonEmpty,
2066
+ repositories: z.array(z.object({ repoId: nonEmpty, refId: nonEmpty, profileId: nonEmpty }).strict()),
2067
+ entries: z.array(stackMatrixEntrySchema),
2068
+ warnings: stringArray,
2069
+ })
2070
+ .strict();
2071
+ const conventionRuleSchema = z
2072
+ .object({
2073
+ ruleKind: z.enum([
2074
+ "path_exists",
2075
+ "path_layout",
2076
+ "naming_pattern",
2077
+ "dependency_present",
2078
+ "layering",
2079
+ "symbol_pattern",
2080
+ "config_pattern",
2081
+ ]),
2082
+ expression: jsonMap,
2083
+ humanReadable: nonEmpty,
2084
+ })
2085
+ .strict();
2086
+ const conventionSchema = z
2087
+ .object({
2088
+ schemaVersion: z.literal(1),
2089
+ conventionId: nonEmpty,
2090
+ workspaceId: nonEmpty,
2091
+ generationId: nonEmpty,
2092
+ kind: z.enum([
2093
+ "directory_layout",
2094
+ "layering",
2095
+ "naming",
2096
+ "test_setup",
2097
+ "error_handling",
2098
+ "config_handling",
2099
+ "logging",
2100
+ ]),
2101
+ title: nonEmpty,
2102
+ description: text,
2103
+ rule: conventionRuleSchema,
2104
+ evidence: z
2105
+ .object({
2106
+ applicableRepos: stringArray,
2107
+ supportingRepos: stringArray,
2108
+ matchCount: nonNegativeInt,
2109
+ counterexamples: z.array(z
2110
+ .object({
2111
+ repoId: nonEmpty,
2112
+ provenance: portfolioProvenanceSchema,
2113
+ note: text.optional(),
2114
+ })
2115
+ .strict()),
2116
+ sampleProvenance: z.array(portfolioProvenanceSchema),
2117
+ })
2118
+ .strict(),
2119
+ confidence: portfolioConfidenceSchema,
2120
+ detectorId: nonEmpty,
2121
+ detectorVersion: nonEmpty,
2122
+ heuristic: z.boolean(),
2123
+ })
2124
+ .strict();
2125
+ const archetypeNameSchema = z.enum([
2126
+ "layered_service",
2127
+ "hexagonal_service",
2128
+ "modular_monolith",
2129
+ "api_service",
2130
+ "worker",
2131
+ "cli_tool",
2132
+ "library",
2133
+ "frontend_app",
2134
+ "mcp_server",
2135
+ "infra_repo",
2136
+ "monorepo_root",
2137
+ "unclassified",
2138
+ ]);
2139
+ const archetypeSchema = z
2140
+ .object({
2141
+ schemaVersion: z.literal(1),
2142
+ archetypeId: nonEmpty,
2143
+ workspaceId: nonEmpty,
2144
+ repoId: nonEmpty,
2145
+ refId: nonEmpty,
2146
+ generationId: nonEmpty,
2147
+ classifierVersion: nonEmpty,
2148
+ archetype: archetypeNameSchema,
2149
+ score: ratio,
2150
+ alternatives: z.array(z.object({ archetype: archetypeNameSchema, score: ratio }).strict()),
2151
+ signals: z.array(z
2152
+ .object({
2153
+ signalId: nonEmpty,
2154
+ description: nonEmpty,
2155
+ weight: finite,
2156
+ matched: z.boolean(),
2157
+ contribution: finite,
2158
+ provenance: portfolioProvenanceSchema.optional(),
2159
+ heuristic: z.boolean(),
2160
+ })
2161
+ .strict()),
2162
+ confidence: portfolioConfidenceSchema,
2163
+ })
2164
+ .strict();
2165
+ const radarEntrySchema = z
2166
+ .object({
2167
+ schemaVersion: z.literal(1),
2168
+ entryId: nonEmpty,
2169
+ workspaceId: nonEmpty,
2170
+ generationId: nonEmpty,
2171
+ radarVersion: nonEmpty,
2172
+ technologyId: nonEmpty,
2173
+ name: nonEmpty,
2174
+ category: nonEmpty,
2175
+ problemDomain: text.optional(),
2176
+ ring: z.enum(["adopt", "maintain", "consolidate", "retire"]),
2177
+ ringReason: stringArray,
2178
+ versionDrift: z
2179
+ .object({
2180
+ distinctVersions: stringArray,
2181
+ majorSpread: nonNegativeInt,
2182
+ byRepo: optionalStringMap,
2183
+ comparable: z.boolean(),
2184
+ })
2185
+ .strict(),
2186
+ duplicates: z.array(z.object({ problemDomain: nonEmpty, competingTechnologyIds: stringArray }).strict()),
2187
+ trend: z
2188
+ .object({
2189
+ direction: z.enum(["converging", "diverging", "stable", "declining", "new", "unknown"]),
2190
+ points: z.array(z
2191
+ .object({
2192
+ window: nonEmpty,
2193
+ repoCount: nonNegativeInt,
2194
+ distinctVersionCount: nonNegativeInt,
2195
+ })
2196
+ .strict()),
2197
+ })
2198
+ .strict(),
2199
+ evidence: z.array(portfolioProvenanceSchema),
2200
+ confidence: portfolioConfidenceSchema,
2201
+ })
2202
+ .strict();
2203
+ const blueprintKindSchema = z.enum([
2204
+ "api-service",
2205
+ "worker",
2206
+ "cli",
2207
+ "library",
2208
+ "web-app",
2209
+ "mcp-server",
2210
+ ]);
2211
+ const blueprintFileSchema = z
2212
+ .object({
2213
+ path: text,
2214
+ templateId: nonEmpty,
2215
+ contentPreviewHash: nonEmpty,
2216
+ sizeBytes: nonNegativeInt,
2217
+ })
2218
+ .strict();
2219
+ const blueprintDependencySchema = z
2220
+ .object({
2221
+ technologyId: nonEmpty,
2222
+ name: nonEmpty,
2223
+ ecosystem: nonEmpty,
2224
+ version: nonEmpty,
2225
+ usage: z.enum(["runtime", "dev"]),
2226
+ recommendationId: nonEmpty,
2227
+ })
2228
+ .strict();
2229
+ const recommendationComponentSchema = z
2230
+ .object({
2231
+ name: z.enum(["adoption", "recency", "health", "version_consistency"]),
2232
+ value: ratio,
2233
+ weight: finite,
2234
+ contribution: finite,
2235
+ inputs: jsonMap,
2236
+ })
2237
+ .strict();
2238
+ const blueprintSchema = z
2239
+ .object({
2240
+ schemaVersion: z.literal(1),
2241
+ blueprintId: nonEmpty,
2242
+ workspaceId: nonEmpty,
2243
+ generationId: nonEmpty,
2244
+ advisorVersion: nonEmpty,
2245
+ generatedAt: nonEmpty,
2246
+ kind: blueprintKindSchema,
2247
+ language: nonEmpty,
2248
+ runtime: z.object({ name: nonEmpty, versionRange: nonEmpty }).strict(),
2249
+ directoryLayout: z.array(z
2250
+ .object({
2251
+ path: text,
2252
+ kind: z.enum(["directory", "file"]),
2253
+ purpose: nonEmpty,
2254
+ sourceConventionId: text.optional(),
2255
+ })
2256
+ .strict()),
2257
+ dependencies: z.array(blueprintDependencySchema),
2258
+ toolchain: z.array(blueprintDependencySchema),
2259
+ testSetup: z
2260
+ .object({ framework: nonEmpty, layout: nonEmpty, recommendationId: nonEmpty })
2261
+ .strict(),
2262
+ ciSkeleton: z
2263
+ .object({ system: nonEmpty, workflowFiles: stringArray, recommendationId: nonEmpty })
2264
+ .strict(),
2265
+ appliedConventionIds: stringArray,
2266
+ recommendationIds: stringArray,
2267
+ files: z.array(blueprintFileSchema).optional(),
2268
+ evidenceSummary: z
2269
+ .object({
2270
+ reposConsidered: nonNegativeInt,
2271
+ reposMatchingKind: stringArray,
2272
+ portfolioGenerationId: nonEmpty,
2273
+ })
2274
+ .strict(),
2275
+ warnings: stringArray,
2276
+ })
2277
+ .strict();
2278
+ const blueprintRecommendationSchema = z
2279
+ .object({
2280
+ schemaVersion: z.literal(1),
2281
+ recommendationId: nonEmpty,
2282
+ blueprintId: nonEmpty,
2283
+ workspaceId: nonEmpty,
2284
+ generationId: nonEmpty,
2285
+ advisorVersion: nonEmpty,
2286
+ topic: nonEmpty,
2287
+ recommended: z
2288
+ .object({ technologyId: nonEmpty, name: nonEmpty, version: text.optional() })
2289
+ .strict(),
2290
+ fitScore: ratio,
2291
+ components: z.array(recommendationComponentSchema),
2292
+ evidence: z
2293
+ .object({
2294
+ supportingRepoIds: stringArray,
2295
+ supportingRecordIds: stringArray,
2296
+ healthByRepo: z.record(z.string(), repositoryHealthSchema.nullable()),
2297
+ })
2298
+ .strict(),
2299
+ alternatives: z.array(z
2300
+ .object({
2301
+ technologyId: nonEmpty,
2302
+ name: nonEmpty,
2303
+ version: text.optional(),
2304
+ fitScore: ratio,
2305
+ components: z.array(recommendationComponentSchema),
2306
+ note: text.optional(),
2307
+ })
2308
+ .strict()),
2309
+ risks: z.array(z
2310
+ .object({
2311
+ kind: z.enum([
2312
+ "outdated_version",
2313
+ "low_adoption",
2314
+ "high_hotspot_share",
2315
+ "version_divergence",
2316
+ "single_repo_evidence",
2317
+ "declared_only_evidence",
2318
+ "heuristic_evidence",
2319
+ ]),
2320
+ severity: z.enum(["info", "warning", "critical"]),
2321
+ message: nonEmpty,
2322
+ evidence: z.array(portfolioProvenanceSchema),
2323
+ })
2324
+ .strict()),
2325
+ confidence: portfolioConfidenceSchema,
2326
+ })
2327
+ .strict();
2328
+ export const portfolioScanResultSchema = z
2329
+ .object({
2330
+ schemaVersion: z.literal(1),
2331
+ jobId: nonEmpty,
2332
+ generationId: nonEmpty,
2333
+ status: z.enum(["queued", "running", "completed", "failed", "cancelled"]),
2334
+ repositoriesPlanned: nonNegativeInt,
2335
+ repositoriesCompleted: nonNegativeInt,
2336
+ technologiesDetected: nonNegativeInt.optional(),
2337
+ conventionsDetected: nonNegativeInt.optional(),
2338
+ warnings: stringArray,
2339
+ })
2340
+ .strict();
2341
+ export const whoUsesResultSchema = z
2342
+ .object({
2343
+ schemaVersion: z.literal(1),
2344
+ technology: z
2345
+ .object({
2346
+ technologyId: nonEmpty,
2347
+ name: nonEmpty,
2348
+ category: nonEmpty,
2349
+ ecosystem: text.optional(),
2350
+ })
2351
+ .strict(),
2352
+ generationId: nonEmpty,
2353
+ usages: z.array(z
2354
+ .object({
2355
+ repoId: nonEmpty,
2356
+ repoLabel: text,
2357
+ refId: nonEmpty,
2358
+ versionRaw: text.optional(),
2359
+ versionResolved: text.optional(),
2360
+ usage: nonEmpty,
2361
+ declaredOnly: z.boolean(),
2362
+ importOnly: z.boolean(),
2363
+ importingFileCount: nonNegativeInt.optional(),
2364
+ firstSeenAt: text.optional(),
2365
+ lastSeenAt: text.optional(),
2366
+ provenance: z.array(portfolioProvenanceSchema),
2367
+ })
2368
+ .strict()),
2369
+ notUsingRepoIds: stringArray,
2370
+ warnings: stringArray,
2371
+ })
2372
+ .strict();
2373
+ export const conventionsResultSchema = z
2374
+ .object({
2375
+ schemaVersion: z.literal(1),
2376
+ generationId: nonEmpty,
2377
+ conventions: z.array(conventionSchema),
2378
+ suppressedCount: nonNegativeInt,
2379
+ warnings: stringArray,
2380
+ })
2381
+ .strict();
2382
+ export const archetypesResultSchema = z
2383
+ .object({
2384
+ schemaVersion: z.literal(1),
2385
+ generationId: nonEmpty,
2386
+ classifierVersion: nonEmpty,
2387
+ assignments: z.array(archetypeSchema),
2388
+ warnings: stringArray,
2389
+ })
2390
+ .strict();
2391
+ export const techRadarResultSchema = z
2392
+ .object({
2393
+ schemaVersion: z.literal(1),
2394
+ generationId: nonEmpty,
2395
+ radarVersion: nonEmpty,
2396
+ entries: z.array(radarEntrySchema),
2397
+ historyAvailable: z.boolean(),
2398
+ warnings: stringArray,
2399
+ })
2400
+ .strict();
2401
+ export const blueprintResultSchema = z
2402
+ .object({
2403
+ schemaVersion: z.literal(1),
2404
+ blueprint: blueprintSchema,
2405
+ recommendations: z.array(blueprintRecommendationSchema),
2406
+ scaffold: z
2407
+ .object({
2408
+ mode: z.enum(["dry_run", "applied"]),
2409
+ targetDir: nonEmpty,
2410
+ files: z.array(blueprintFileSchema),
2411
+ manifestPath: text.optional(),
2412
+ })
2413
+ .strict()
2414
+ .optional(),
2415
+ warnings: stringArray,
2416
+ })
2417
+ .strict();
2418
+ const graphStatusSchema = z
2419
+ .object({
2420
+ generationId: nonEmpty,
2421
+ workspaceId: nonEmpty,
2422
+ metrics: fileGraphMetricsSchema,
2423
+ issues: z.array(snapshotReadIssueSchema),
2424
+ })
2425
+ .strict();
2426
+ const graphStatsSchema = z
2427
+ .object({
2428
+ generationId: nonEmpty,
2429
+ metrics: fileGraphMetricsSchema,
2430
+ boundaries: boundaryCountsSchema,
2431
+ issues: z.array(snapshotReadIssueSchema),
2432
+ })
2433
+ .strict();
2434
+ const graphCyclesSchema = z
2435
+ .object({
2436
+ generationId: nonEmpty,
2437
+ cycles: z.array(stringArray),
2438
+ total: nonNegativeInt,
2439
+ issues: z.array(snapshotReadIssueSchema),
2440
+ })
2441
+ .strict();
2442
+ const aboutSchema = z
2443
+ .object({
2444
+ name: z.literal("untangle"),
2445
+ version: nonEmpty,
2446
+ license: z.literal("AGPL-3.0-only"),
2447
+ source: nonEmpty,
2448
+ commit: nonEmpty,
2449
+ availableTools: z.array(nonEmpty),
2450
+ unavailableToolsReturn: z.literal("FEATURE_UNAVAILABLE"),
2451
+ })
2452
+ .strict();
2453
+ /** Tool-specific success payload contracts; none falls back to an arbitrary object. */
2454
+ const productSourceReferenceSchema = z.object({ path: text, heading: text }).strict();
2455
+ const productFileSelectionSchema = z
2456
+ .object({ include: stringArray, exclude: stringArray.optional() })
2457
+ .strict();
2458
+ const productManifestSchema = z
2459
+ .object({
2460
+ schemaVersion: z.literal(1),
2461
+ owners: z.array(z
2462
+ .object({
2463
+ id: text,
2464
+ label: text,
2465
+ kind: z.enum(["person", "team", "role"]),
2466
+ status: z.enum(["declared", "confirmed"]),
2467
+ confirmedBy: text.optional(),
2468
+ sources: z.array(productSourceReferenceSchema),
2469
+ })
2470
+ .strict()),
2471
+ features: z.array(z
2472
+ .object({
2473
+ id: text,
2474
+ title: text,
2475
+ stage: z.enum(["implemented", "planned"]),
2476
+ review: z.enum(["proposed", "confirmed"]),
2477
+ confirmedBy: text.optional(),
2478
+ intent: z.array(productSourceReferenceSchema.extend({ role: z.enum(["vision", "specification"]) })),
2479
+ owners: stringArray,
2480
+ code: productFileSelectionSchema,
2481
+ tests: productFileSelectionSchema,
2482
+ criteria: z.array(z
2483
+ .object({
2484
+ id: text,
2485
+ description: text,
2486
+ tests: stringArray,
2487
+ testNames: stringArray.optional(),
2488
+ })
2489
+ .strict()),
2490
+ dependsOn: stringArray,
2491
+ budgets: z
2492
+ .object({
2493
+ maxCognitivePerUnit: nonNegative.optional(),
2494
+ maxCognitiveTotal: nonNegative.optional(),
2495
+ maxCodeFiles: nonNegativeInt.optional(),
2496
+ maxOwners: nonNegativeInt.optional(),
2497
+ })
2498
+ .strict()
2499
+ .optional(),
2500
+ })
2501
+ .strict()),
2502
+ })
2503
+ .strict();
2504
+ const productSourceEvidenceSchema = productSourceReferenceSchema.extend({
2505
+ status: z.enum(["resolved", "missing", "ambiguous", "not_in_scan", "changed", "unreadable"]),
2506
+ contentHash: sha256Fingerprint.optional(),
2507
+ startLine: positiveInt.optional(),
2508
+ endLine: positiveInt.optional(),
2509
+ });
2510
+ const productFileEvidenceSchema = z
2511
+ .object({
2512
+ path: nonEmpty,
2513
+ status: z.enum([
2514
+ "measured",
2515
+ "not_in_scan",
2516
+ "changed",
2517
+ "unreadable",
2518
+ "unsupported",
2519
+ "partial",
2520
+ "invalid_metrics",
2521
+ ]),
2522
+ contentHash: sha256Fingerprint.optional(),
2523
+ scannedContentHash: sha256Fingerprint.optional(),
2524
+ })
2525
+ .strict();
2526
+ const productMetricReadingsSchema = z
2527
+ .object({ top_level: nonNegative, execution_unit: nonNegative, self: nonNegative })
2528
+ .strict();
2529
+ const productCodeMetricsSchema = z
2530
+ .object({
2531
+ metricsVersion: nonEmpty,
2532
+ cognitiveAlgorithm: nonEmpty,
2533
+ cognitive: productMetricReadingsSchema,
2534
+ cyclomaticClassic: productMetricReadingsSchema,
2535
+ cyclomaticExtended: productMetricReadingsSchema,
2536
+ files: nonNegativeInt,
2537
+ scopes: nonNegativeInt,
2538
+ executionUnitRoots: nonNegativeInt,
2539
+ sloc: nonNegativeInt,
2540
+ cyclomaticPerScopeBase: z.literal(1),
2541
+ })
2542
+ .strict();
2543
+ const productMeasuredSelectionSchema = z
2544
+ .object({
2545
+ complete: z.boolean(),
2546
+ files: z.array(productFileEvidenceSchema),
2547
+ metrics: productCodeMetricsSchema.nullable(),
2548
+ })
2549
+ .strict();
2550
+ const productHotspotSchema = z
2551
+ .object({
2552
+ path: nonEmpty,
2553
+ contentHash: sha256Fingerprint,
2554
+ symbol: nonEmpty,
2555
+ scopeId: nonEmpty,
2556
+ startLine: positiveInt,
2557
+ endLine: positiveInt,
2558
+ cognitive: nonNegative,
2559
+ cyclomaticClassic: nonNegative,
2560
+ cyclomaticExtended: nonNegative,
2561
+ })
2562
+ .strict();
2563
+ const productAgentHintSchema = z
2564
+ .object({
2565
+ code: nonEmpty,
2566
+ severity: z.enum(["info", "warning", "error"]),
2567
+ message: text,
2568
+ paths: stringArray,
2569
+ suggestedAction: text,
2570
+ search: z
2571
+ .object({ symbol: nonEmpty, path: nonEmpty, requireFresh: z.literal(true) })
2572
+ .strict()
2573
+ .optional(),
2574
+ })
2575
+ .strict();
2576
+ const productFeatureAlignmentSchema = z
2577
+ .object({
2578
+ id: nonEmpty,
2579
+ title: text,
2580
+ stage: z.enum(["implemented", "planned"]),
2581
+ review: z.enum(["proposed", "confirmed"]),
2582
+ status: z.enum(["evidence_consistent", "needs_review", "incomplete", "violated"]),
2583
+ intent: z.array(productSourceEvidenceSchema.extend({ role: z.enum(["vision", "specification"]) })),
2584
+ ownership: z.array(z
2585
+ .object({
2586
+ id: nonEmpty,
2587
+ label: text.optional(),
2588
+ status: z.enum(["declared", "confirmed", "missing"]),
2589
+ sources: z.array(productSourceEvidenceSchema),
2590
+ })
2591
+ .strict()),
2592
+ code: productMeasuredSelectionSchema.extend({ hotspots: z.array(productHotspotSchema) }),
2593
+ tests: productMeasuredSelectionSchema,
2594
+ testEvidence: z
2595
+ .object({
2596
+ status: z.enum(["bound_passed", "bound_failed", "not_run", "stale", "invalid"]),
2597
+ passed: nonNegativeInt,
2598
+ failed: nonNegativeInt,
2599
+ skipped: nonNegativeInt,
2600
+ proof: z.enum(["supplied_source_bound_report", "none"]),
2601
+ })
2602
+ .strict(),
2603
+ criteria: z.array(z
2604
+ .object({
2605
+ id: nonEmpty,
2606
+ description: text,
2607
+ matchedFiles: stringArray,
2608
+ status: z.enum(["passed", "failed", "not_run", "missing_tests", "unverified"]),
2609
+ })
2610
+ .strict()),
2611
+ dimensions: z
2612
+ .object({
2613
+ requirements: nonNegativeInt,
2614
+ owners: nonNegativeInt,
2615
+ codeFiles: nonNegativeInt,
2616
+ testFiles: nonNegativeInt,
2617
+ sharedCodeFiles: nonNegativeInt,
2618
+ declaredDependencies: nonNegativeInt,
2619
+ dependentFeatures: nonNegativeInt,
2620
+ })
2621
+ .strict(),
2622
+ dependsOn: stringArray,
2623
+ agentHints: z.array(productAgentHintSchema),
2624
+ issues: stringArray,
2625
+ })
2626
+ .strict();
2627
+ const productAlignmentReportSchema = z
2628
+ .object({
2629
+ schemaVersion: z.literal(1),
2630
+ root: nonEmpty,
2631
+ status: z.enum([
2632
+ "needs_manifest",
2633
+ "invalid_manifest",
2634
+ "evidence_consistent",
2635
+ "needs_review",
2636
+ "incomplete",
2637
+ "violated",
2638
+ ]),
2639
+ manifest: z
2640
+ .object({
2641
+ path: nonEmpty,
2642
+ status: z.enum(["missing", "loaded", "invalid", "not_in_scan", "changed", "unreadable"]),
2643
+ contentHash: sha256Fingerprint.optional(),
2644
+ })
2645
+ .strict(),
2646
+ sourceTreeDigest: sha256Fingerprint,
2647
+ inventory: z
2648
+ .object({ files: nonNegativeInt, truncated: z.boolean(), excluded: nonNegativeInt })
2649
+ .strict(),
2650
+ semanticConformance: z.literal("not_independently_proven"),
2651
+ ownershipAuthority: z.literal("manifest_declarations"),
2652
+ selection: z
2653
+ .object({
2654
+ path: nonEmpty,
2655
+ status: z.enum(["matched", "unmapped", "missing", "not_in_scan", "changed", "unreadable"]),
2656
+ matches: z.array(z
2657
+ .object({
2658
+ featureId: nonEmpty,
2659
+ roles: z.array(z.enum(["code", "test", "intent", "ownership"])),
2660
+ })
2661
+ .strict()),
2662
+ })
2663
+ .strict()
2664
+ .optional(),
2665
+ testRun: z
2666
+ .object({
2667
+ status: z.enum([
2668
+ "completed",
2669
+ "stale",
2670
+ "invalid_report",
2671
+ "spawn_failed",
2672
+ "timed_out",
2673
+ "output_limit",
2674
+ "cancelled",
2675
+ ]),
2676
+ directory: nonEmpty,
2677
+ receiptPath: nonEmpty,
2678
+ exitCode: integer.nullable(),
2679
+ issue: text.optional(),
2680
+ })
2681
+ .strict()
2682
+ .optional(),
2683
+ features: z.array(productFeatureAlignmentSchema),
2684
+ coverage: z
2685
+ .object({
2686
+ measuredCodeFiles: nonNegativeInt,
2687
+ mappedCodeFiles: nonNegativeInt,
2688
+ unmappedCodeFiles: stringArray,
2689
+ unmappedCodeFileCount: nonNegativeInt,
2690
+ sharedFiles: z.array(z.object({ path: nonEmpty, featureIds: stringArray }).strict()),
2691
+ mappedCodeUnion: productCodeMetricsSchema.nullable(),
2692
+ })
2693
+ .strict(),
2694
+ dependencyCycles: z.array(stringArray),
2695
+ issues: stringArray,
2696
+ limitations: stringArray,
2697
+ draft: productManifestSchema.nullable(),
2698
+ })
2699
+ .strict();
2700
+ export const UNTANGLE_MCP_SUCCESS_DATA_SCHEMAS = {
2701
+ untangle_index: indexReportSchema,
2702
+ untangle_update: indexReportSchema,
2703
+ untangle_stop: z.object({ job: jobStatusSchema, cancellationRequested: z.boolean() }).strict(),
2704
+ untangle_watch: z.object({ job: jobStatusSchema, watching: z.boolean() }).strict(),
2705
+ untangle_status: z.object({ jobs: z.array(jobStatusSchema) }).strict(),
2706
+ untangle_health: z
2707
+ .object({ schemaVersion: z.literal(1), ok: z.boolean(), checks: z.array(checkResultSchema) })
2708
+ .strict(),
2709
+ untangle_projects: z
2710
+ .object({
2711
+ root: nonEmpty,
2712
+ repositories: z.array(repositoryConfigSchema),
2713
+ projectId: text.optional(),
2714
+ })
2715
+ .strict(),
2716
+ untangle_search: searchResultSetSchema,
2717
+ untangle_search_session: searchSessionResultSchema,
2718
+ untangle_context_list: z
2719
+ .object({ artifacts: z.array(contextArtifactSchema), configured: nonNegativeInt })
2720
+ .strict(),
2721
+ untangle_context_index: z
2722
+ .object({
2723
+ generationId: nonEmpty,
2724
+ artifacts: z.array(nonEmpty),
2725
+ indexedDocuments: nonNegativeInt,
2726
+ })
2727
+ .strict(),
2728
+ untangle_context_search: z
2729
+ .object({
2730
+ query: nonEmpty,
2731
+ results: z.array(z
2732
+ .object({
2733
+ artifactName: nonEmpty,
2734
+ chunkId: nonEmpty,
2735
+ path: text,
2736
+ kind: nonEmpty,
2737
+ title: text.optional(),
2738
+ score: finite,
2739
+ content: text.optional(),
2740
+ })
2741
+ .strict()),
2742
+ total: nonNegativeInt,
2743
+ })
2744
+ .strict(),
2745
+ untangle_context_remove: z
2746
+ .object({ target: nonEmpty, removed: z.boolean(), removedDocumentCount: nonNegativeInt })
2747
+ .strict(),
2748
+ untangle_graph_build: z
2749
+ .object({
2750
+ generationId: nonEmpty,
2751
+ workspaceId: nonEmpty,
2752
+ fileGraph: z.object({ nodeCount: nonNegativeInt, edgeCount: nonNegativeInt }).strict(),
2753
+ symbolGraph: z.object({ nodeCount: nonNegativeInt, edgeCount: nonNegativeInt }).strict(),
2754
+ skipped: z.array(skipLedgerEntrySchema),
2755
+ })
2756
+ .strict(),
2757
+ untangle_graph_status: graphStatusSchema,
2758
+ untangle_graph_query: boundedGraphFileViewSchema,
2759
+ untangle_graph_stats: graphStatsSchema,
2760
+ untangle_graph_cycles: graphCyclesSchema,
2761
+ untangle_graph_visualize: graphVisualizationSchema,
2762
+ untangle_graph_remove: z
2763
+ .object({ target: nonEmpty, generationId: nonEmpty, removed: z.boolean() })
2764
+ .strict(),
2765
+ untangle_symbols: symbolListSchema,
2766
+ untangle_symbol: symbolDetailSchema,
2767
+ untangle_flow: flowSchema,
2768
+ untangle_impact: impactSchema,
2769
+ untangle_cross_repo_impact: z
2770
+ .object({
2771
+ generationId: nonEmpty,
2772
+ root: symbolNodeSchema,
2773
+ impact: impactResultSchema,
2774
+ repoIds: stringArray,
2775
+ })
2776
+ .strict(),
2777
+ untangle_complexity: complexityReportSchema,
2778
+ untangle_complexity_explain: z
2779
+ .object({ symbol: symbolNodeSchema, snapshot: complexitySnapshotSchema })
2780
+ .strict(),
2781
+ untangle_hotspots: complexityReportSchema,
2782
+ untangle_complexity_diff: z
2783
+ .object({
2784
+ base: nonEmpty,
2785
+ head: nonEmpty,
2786
+ metricsVersion: nonEmpty,
2787
+ entries: z.array(metricDeltaSchema),
2788
+ warnings: stringArray,
2789
+ })
2790
+ .strict(),
2791
+ untangle_changes: z
2792
+ .object({
2793
+ base: nonEmpty,
2794
+ head: nonEmpty,
2795
+ changes: z.array(changeEventSchema),
2796
+ total: nonNegativeInt,
2797
+ })
2798
+ .strict(),
2799
+ untangle_change_search: z
2800
+ .object({ query: nonEmpty, changes: z.array(changeEventSchema), total: nonNegativeInt })
2801
+ .strict(),
2802
+ untangle_quality_gate: qualityGateSchema,
2803
+ untangle_about: aboutSchema,
2804
+ untangle_portfolio_scan: portfolioScanResultSchema,
2805
+ untangle_stack_matrix: stackMatrixResultSchema,
2806
+ untangle_who_uses: whoUsesResultSchema,
2807
+ untangle_conventions: conventionsResultSchema,
2808
+ untangle_archetypes: archetypesResultSchema,
2809
+ untangle_tech_radar: techRadarResultSchema,
2810
+ untangle_blueprint: blueprintResultSchema,
2811
+ untangle_product: productAlignmentReportSchema,
2812
+ untangle_boundaries: frontendBoundaryReportSchema,
2813
+ };
2814
+ //# sourceMappingURL=output-schemas.js.map