trail-code 0.0.0-stage → 0.28.0-semantic.3

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 (593) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +567 -2
  3. package/dist/ai/crux.d.ts +88 -0
  4. package/dist/ai/crux.d.ts.map +1 -0
  5. package/dist/ai/crux.js +219 -0
  6. package/dist/ai/crux.js.map +1 -0
  7. package/dist/ai/failure.d.ts +60 -0
  8. package/dist/ai/failure.d.ts.map +1 -0
  9. package/dist/ai/failure.js +86 -0
  10. package/dist/ai/failure.js.map +1 -0
  11. package/dist/ai/llm/anthropic.d.ts +37 -0
  12. package/dist/ai/llm/anthropic.d.ts.map +1 -0
  13. package/dist/ai/llm/anthropic.js +144 -0
  14. package/dist/ai/llm/anthropic.js.map +1 -0
  15. package/dist/ai/llm/factory.d.ts +28 -0
  16. package/dist/ai/llm/factory.d.ts.map +1 -0
  17. package/dist/ai/llm/factory.js +36 -0
  18. package/dist/ai/llm/factory.js.map +1 -0
  19. package/dist/ai/llm/litellm.d.ts +34 -0
  20. package/dist/ai/llm/litellm.d.ts.map +1 -0
  21. package/dist/ai/llm/litellm.js +45 -0
  22. package/dist/ai/llm/litellm.js.map +1 -0
  23. package/dist/ai/llm/openai.d.ts +145 -0
  24. package/dist/ai/llm/openai.d.ts.map +1 -0
  25. package/dist/ai/llm/openai.js +629 -0
  26. package/dist/ai/llm/openai.js.map +1 -0
  27. package/dist/ai/llm/orcarouter.d.ts +34 -0
  28. package/dist/ai/llm/orcarouter.d.ts.map +1 -0
  29. package/dist/ai/llm/orcarouter.js +45 -0
  30. package/dist/ai/llm/orcarouter.js.map +1 -0
  31. package/dist/ai/llm/recover-tool.d.ts +21 -0
  32. package/dist/ai/llm/recover-tool.d.ts.map +1 -0
  33. package/dist/ai/llm/recover-tool.js +109 -0
  34. package/dist/ai/llm/recover-tool.js.map +1 -0
  35. package/dist/ai/llm/types.d.ts +122 -0
  36. package/dist/ai/llm/types.d.ts.map +1 -0
  37. package/dist/ai/llm/types.js +33 -0
  38. package/dist/ai/llm/types.js.map +1 -0
  39. package/dist/ai/providers.d.ts +59 -0
  40. package/dist/ai/providers.d.ts.map +1 -0
  41. package/dist/ai/providers.js +54 -0
  42. package/dist/ai/providers.js.map +1 -0
  43. package/dist/ai/summarize.d.ts +25 -0
  44. package/dist/ai/summarize.d.ts.map +1 -0
  45. package/dist/ai/summarize.js +34 -0
  46. package/dist/ai/summarize.js.map +1 -0
  47. package/dist/ai/synthesize.d.ts +40 -0
  48. package/dist/ai/synthesize.d.ts.map +1 -0
  49. package/dist/ai/synthesize.js +230 -0
  50. package/dist/ai/synthesize.js.map +1 -0
  51. package/dist/ask/ask.d.ts +199 -0
  52. package/dist/ask/ask.d.ts.map +1 -0
  53. package/dist/ask/ask.js +1291 -0
  54. package/dist/ask/ask.js.map +1 -0
  55. package/dist/ask/file-rank.d.ts +72 -0
  56. package/dist/ask/file-rank.d.ts.map +1 -0
  57. package/dist/ask/file-rank.js +160 -0
  58. package/dist/ask/file-rank.js.map +1 -0
  59. package/dist/ask/file-selection.d.ts +22 -0
  60. package/dist/ask/file-selection.d.ts.map +1 -0
  61. package/dist/ask/file-selection.js +66 -0
  62. package/dist/ask/file-selection.js.map +1 -0
  63. package/dist/ask/fuse.d.ts +195 -0
  64. package/dist/ask/fuse.d.ts.map +1 -0
  65. package/dist/ask/fuse.js +344 -0
  66. package/dist/ask/fuse.js.map +1 -0
  67. package/dist/ask/graphrank.d.ts +61 -0
  68. package/dist/ask/graphrank.d.ts.map +1 -0
  69. package/dist/ask/graphrank.js +130 -0
  70. package/dist/ask/graphrank.js.map +1 -0
  71. package/dist/ask/index-file.d.ts +44 -0
  72. package/dist/ask/index-file.d.ts.map +1 -0
  73. package/dist/ask/index-file.js +128 -0
  74. package/dist/ask/index-file.js.map +1 -0
  75. package/dist/ask/semantic.d.ts +42 -0
  76. package/dist/ask/semantic.d.ts.map +1 -0
  77. package/dist/ask/semantic.js +293 -0
  78. package/dist/ask/semantic.js.map +1 -0
  79. package/dist/bin/graft.d.ts +3 -0
  80. package/dist/bin/graft.d.ts.map +1 -0
  81. package/dist/bin/graft.js +14 -0
  82. package/dist/bin/graft.js.map +1 -0
  83. package/dist/bin/trail.d.ts +3 -0
  84. package/dist/bin/trail.d.ts.map +1 -0
  85. package/dist/bin/trail.js +13 -0
  86. package/dist/bin/trail.js.map +1 -0
  87. package/dist/blast/blast-cli.d.ts +35 -0
  88. package/dist/blast/blast-cli.d.ts.map +1 -0
  89. package/dist/blast/blast-cli.js +155 -0
  90. package/dist/blast/blast-cli.js.map +1 -0
  91. package/dist/blast/blast.d.ts +128 -0
  92. package/dist/blast/blast.d.ts.map +1 -0
  93. package/dist/blast/blast.js +383 -0
  94. package/dist/blast/blast.js.map +1 -0
  95. package/dist/blast/diff.d.ts +53 -0
  96. package/dist/blast/diff.d.ts.map +1 -0
  97. package/dist/blast/diff.js +193 -0
  98. package/dist/blast/diff.js.map +1 -0
  99. package/dist/blast/evidence.d.ts +51 -0
  100. package/dist/blast/evidence.d.ts.map +1 -0
  101. package/dist/blast/evidence.js +162 -0
  102. package/dist/blast/evidence.js.map +1 -0
  103. package/dist/blast/modules.d.ts +33 -0
  104. package/dist/blast/modules.d.ts.map +1 -0
  105. package/dist/blast/modules.js +83 -0
  106. package/dist/blast/modules.js.map +1 -0
  107. package/dist/blast/name.d.ts +74 -0
  108. package/dist/blast/name.d.ts.map +1 -0
  109. package/dist/blast/name.js +269 -0
  110. package/dist/blast/name.js.map +1 -0
  111. package/dist/blast/owners.d.ts +85 -0
  112. package/dist/blast/owners.d.ts.map +1 -0
  113. package/dist/blast/owners.js +272 -0
  114. package/dist/blast/owners.js.map +1 -0
  115. package/dist/blast/render.d.ts +46 -0
  116. package/dist/blast/render.d.ts.map +1 -0
  117. package/dist/blast/render.js +422 -0
  118. package/dist/blast/render.js.map +1 -0
  119. package/dist/blast/viz.d.ts +37 -0
  120. package/dist/blast/viz.d.ts.map +1 -0
  121. package/dist/blast/viz.js +180 -0
  122. package/dist/blast/viz.js.map +1 -0
  123. package/dist/brand.d.ts +111 -0
  124. package/dist/brand.d.ts.map +1 -0
  125. package/dist/brand.js +282 -0
  126. package/dist/brand.js.map +1 -0
  127. package/dist/claude/build-progress.d.ts +30 -0
  128. package/dist/claude/build-progress.d.ts.map +1 -0
  129. package/dist/claude/build-progress.js +81 -0
  130. package/dist/claude/build-progress.js.map +1 -0
  131. package/dist/claude/hermes-skill-template.d.ts +16 -0
  132. package/dist/claude/hermes-skill-template.d.ts.map +1 -0
  133. package/dist/claude/hermes-skill-template.js +154 -0
  134. package/dist/claude/hermes-skill-template.js.map +1 -0
  135. package/dist/claude/init.d.ts +65 -0
  136. package/dist/claude/init.d.ts.map +1 -0
  137. package/dist/claude/init.js +258 -0
  138. package/dist/claude/init.js.map +1 -0
  139. package/dist/claude/paths.d.ts +9 -0
  140. package/dist/claude/paths.d.ts.map +1 -0
  141. package/dist/claude/paths.js +22 -0
  142. package/dist/claude/paths.js.map +1 -0
  143. package/dist/claude/session-metrics.d.ts +73 -0
  144. package/dist/claude/session-metrics.d.ts.map +1 -0
  145. package/dist/claude/session-metrics.js +209 -0
  146. package/dist/claude/session-metrics.js.map +1 -0
  147. package/dist/claude/settings-merge.d.ts +76 -0
  148. package/dist/claude/settings-merge.d.ts.map +1 -0
  149. package/dist/claude/settings-merge.js +283 -0
  150. package/dist/claude/settings-merge.js.map +1 -0
  151. package/dist/claude/skill-template.d.ts +13 -0
  152. package/dist/claude/skill-template.d.ts.map +1 -0
  153. package/dist/claude/skill-template.js +290 -0
  154. package/dist/claude/skill-template.js.map +1 -0
  155. package/dist/claude/state.d.ts +85 -0
  156. package/dist/claude/state.d.ts.map +1 -0
  157. package/dist/claude/state.js +88 -0
  158. package/dist/claude/state.js.map +1 -0
  159. package/dist/claude/stats.d.ts +5 -0
  160. package/dist/claude/stats.d.ts.map +1 -0
  161. package/dist/claude/stats.js +24 -0
  162. package/dist/claude/stats.js.map +1 -0
  163. package/dist/cli-epilogue.d.ts +12 -0
  164. package/dist/cli-epilogue.d.ts.map +1 -0
  165. package/dist/cli-epilogue.js +72 -0
  166. package/dist/cli-epilogue.js.map +1 -0
  167. package/dist/cli-meta.d.ts +82 -0
  168. package/dist/cli-meta.d.ts.map +1 -0
  169. package/dist/cli-meta.js +238 -0
  170. package/dist/cli-meta.js.map +1 -0
  171. package/dist/cli-picker.d.ts +139 -0
  172. package/dist/cli-picker.d.ts.map +1 -0
  173. package/dist/cli-picker.js +439 -0
  174. package/dist/cli-picker.js.map +1 -0
  175. package/dist/cli.d.ts +3 -0
  176. package/dist/cli.d.ts.map +1 -0
  177. package/dist/cli.js +1638 -0
  178. package/dist/cli.js.map +1 -0
  179. package/dist/context/batches.d.ts +29 -0
  180. package/dist/context/batches.d.ts.map +1 -0
  181. package/dist/context/batches.js +130 -0
  182. package/dist/context/batches.js.map +1 -0
  183. package/dist/context/build.d.ts +57 -0
  184. package/dist/context/build.d.ts.map +1 -0
  185. package/dist/context/build.js +396 -0
  186. package/dist/context/build.js.map +1 -0
  187. package/dist/context/check.d.ts +42 -0
  188. package/dist/context/check.d.ts.map +1 -0
  189. package/dist/context/check.js +162 -0
  190. package/dist/context/check.js.map +1 -0
  191. package/dist/context/map-dir.d.ts +13 -0
  192. package/dist/context/map-dir.d.ts.map +1 -0
  193. package/dist/context/map-dir.js +81 -0
  194. package/dist/context/map-dir.js.map +1 -0
  195. package/dist/context/node-file.d.ts +109 -0
  196. package/dist/context/node-file.d.ts.map +1 -0
  197. package/dist/context/node-file.js +390 -0
  198. package/dist/context/node-file.js.map +1 -0
  199. package/dist/context/price.d.ts +49 -0
  200. package/dist/context/price.d.ts.map +1 -0
  201. package/dist/context/price.js +83 -0
  202. package/dist/context/price.js.map +1 -0
  203. package/dist/context/savings.d.ts +67 -0
  204. package/dist/context/savings.d.ts.map +1 -0
  205. package/dist/context/savings.js +125 -0
  206. package/dist/context/savings.js.map +1 -0
  207. package/dist/engine.d.ts +85 -0
  208. package/dist/engine.d.ts.map +1 -0
  209. package/dist/engine.js +122 -0
  210. package/dist/engine.js.map +1 -0
  211. package/dist/graph/bindings.d.ts +64 -0
  212. package/dist/graph/bindings.d.ts.map +1 -0
  213. package/dist/graph/bindings.js +713 -0
  214. package/dist/graph/bindings.js.map +1 -0
  215. package/dist/graph/build-run.d.ts +25 -0
  216. package/dist/graph/build-run.d.ts.map +1 -0
  217. package/dist/graph/build-run.js +121 -0
  218. package/dist/graph/build-run.js.map +1 -0
  219. package/dist/graph/build.d.ts +88 -0
  220. package/dist/graph/build.d.ts.map +1 -0
  221. package/dist/graph/build.js +386 -0
  222. package/dist/graph/build.js.map +1 -0
  223. package/dist/graph/cards.d.ts +46 -0
  224. package/dist/graph/cards.d.ts.map +1 -0
  225. package/dist/graph/cards.js +280 -0
  226. package/dist/graph/cards.js.map +1 -0
  227. package/dist/graph/check.d.ts +25 -0
  228. package/dist/graph/check.d.ts.map +1 -0
  229. package/dist/graph/check.js +192 -0
  230. package/dist/graph/check.js.map +1 -0
  231. package/dist/graph/container.d.ts +63 -0
  232. package/dist/graph/container.d.ts.map +1 -0
  233. package/dist/graph/container.js +191 -0
  234. package/dist/graph/container.js.map +1 -0
  235. package/dist/graph/depth-parser.d.ts +61 -0
  236. package/dist/graph/depth-parser.d.ts.map +1 -0
  237. package/dist/graph/depth-parser.js +153 -0
  238. package/dist/graph/depth-parser.js.map +1 -0
  239. package/dist/graph/enrich.d.ts +62 -0
  240. package/dist/graph/enrich.d.ts.map +1 -0
  241. package/dist/graph/enrich.js +258 -0
  242. package/dist/graph/enrich.js.map +1 -0
  243. package/dist/graph/extract-cache.d.ts +101 -0
  244. package/dist/graph/extract-cache.d.ts.map +1 -0
  245. package/dist/graph/extract-cache.js +199 -0
  246. package/dist/graph/extract-cache.js.map +1 -0
  247. package/dist/graph/extract.d.ts +85 -0
  248. package/dist/graph/extract.d.ts.map +1 -0
  249. package/dist/graph/extract.js +2377 -0
  250. package/dist/graph/extract.js.map +1 -0
  251. package/dist/graph/fingerprint.d.ts +76 -0
  252. package/dist/graph/fingerprint.d.ts.map +1 -0
  253. package/dist/graph/fingerprint.js +160 -0
  254. package/dist/graph/fingerprint.js.map +1 -0
  255. package/dist/graph/generic.d.ts +74 -0
  256. package/dist/graph/generic.d.ts.map +1 -0
  257. package/dist/graph/generic.js +773 -0
  258. package/dist/graph/generic.js.map +1 -0
  259. package/dist/graph/invariants.d.ts +33 -0
  260. package/dist/graph/invariants.d.ts.map +1 -0
  261. package/dist/graph/invariants.js +52 -0
  262. package/dist/graph/invariants.js.map +1 -0
  263. package/dist/graph/load.d.ts +29 -0
  264. package/dist/graph/load.d.ts.map +1 -0
  265. package/dist/graph/load.js +97 -0
  266. package/dist/graph/load.js.map +1 -0
  267. package/dist/graph/lsp/client.d.ts +61 -0
  268. package/dist/graph/lsp/client.d.ts.map +1 -0
  269. package/dist/graph/lsp/client.js +217 -0
  270. package/dist/graph/lsp/client.js.map +1 -0
  271. package/dist/graph/lsp/enrich.d.ts +11 -0
  272. package/dist/graph/lsp/enrich.d.ts.map +1 -0
  273. package/dist/graph/lsp/enrich.js +163 -0
  274. package/dist/graph/lsp/enrich.js.map +1 -0
  275. package/dist/graph/lsp/registry.d.ts +22 -0
  276. package/dist/graph/lsp/registry.d.ts.map +1 -0
  277. package/dist/graph/lsp/registry.js +71 -0
  278. package/dist/graph/lsp/registry.js.map +1 -0
  279. package/dist/graph/map.d.ts +107 -0
  280. package/dist/graph/map.d.ts.map +1 -0
  281. package/dist/graph/map.js +239 -0
  282. package/dist/graph/map.js.map +1 -0
  283. package/dist/graph/markdown.d.ts +22 -0
  284. package/dist/graph/markdown.d.ts.map +1 -0
  285. package/dist/graph/markdown.js +143 -0
  286. package/dist/graph/markdown.js.map +1 -0
  287. package/dist/graph/native.d.ts +46 -0
  288. package/dist/graph/native.d.ts.map +1 -0
  289. package/dist/graph/native.js +169 -0
  290. package/dist/graph/native.js.map +1 -0
  291. package/dist/graph/queries/c.scm +13 -0
  292. package/dist/graph/queries/c_sharp.scm +19 -0
  293. package/dist/graph/queries/clojure.scm +58 -0
  294. package/dist/graph/queries/cpp.scm +23 -0
  295. package/dist/graph/queries/dart.scm +42 -0
  296. package/dist/graph/queries/elixir.scm +54 -0
  297. package/dist/graph/queries/gleam.scm +51 -0
  298. package/dist/graph/queries/java.scm +20 -0
  299. package/dist/graph/queries/kotlin.scm +43 -0
  300. package/dist/graph/queries/lua.scm +36 -0
  301. package/dist/graph/queries/nix.scm +32 -0
  302. package/dist/graph/queries/php.scm +40 -0
  303. package/dist/graph/queries/ruby.scm +65 -0
  304. package/dist/graph/queries/rust.scm +41 -0
  305. package/dist/graph/queries/scala.scm +66 -0
  306. package/dist/graph/queries/solidity.scm +43 -0
  307. package/dist/graph/queries/swift.scm +51 -0
  308. package/dist/graph/refresh.d.ts +106 -0
  309. package/dist/graph/refresh.d.ts.map +1 -0
  310. package/dist/graph/refresh.js +430 -0
  311. package/dist/graph/refresh.js.map +1 -0
  312. package/dist/graph/relations.d.ts +14 -0
  313. package/dist/graph/relations.d.ts.map +1 -0
  314. package/dist/graph/relations.js +8 -0
  315. package/dist/graph/relations.js.map +1 -0
  316. package/dist/graph/resolve.d.ts +17 -0
  317. package/dist/graph/resolve.d.ts.map +1 -0
  318. package/dist/graph/resolve.js +716 -0
  319. package/dist/graph/resolve.js.map +1 -0
  320. package/dist/graph/root.d.ts +11 -0
  321. package/dist/graph/root.d.ts.map +1 -0
  322. package/dist/graph/root.js +40 -0
  323. package/dist/graph/root.js.map +1 -0
  324. package/dist/graph/scopes.d.ts +40 -0
  325. package/dist/graph/scopes.d.ts.map +1 -0
  326. package/dist/graph/scopes.js +383 -0
  327. package/dist/graph/scopes.js.map +1 -0
  328. package/dist/graph/seed.d.ts +38 -0
  329. package/dist/graph/seed.d.ts.map +1 -0
  330. package/dist/graph/seed.js +229 -0
  331. package/dist/graph/seed.js.map +1 -0
  332. package/dist/graph/source-files.d.ts +46 -0
  333. package/dist/graph/source-files.d.ts.map +1 -0
  334. package/dist/graph/source-files.js +118 -0
  335. package/dist/graph/source-files.js.map +1 -0
  336. package/dist/graph/traverse-cli.d.ts +55 -0
  337. package/dist/graph/traverse-cli.d.ts.map +1 -0
  338. package/dist/graph/traverse-cli.js +189 -0
  339. package/dist/graph/traverse-cli.js.map +1 -0
  340. package/dist/graph/traverse.d.ts +112 -0
  341. package/dist/graph/traverse.d.ts.map +1 -0
  342. package/dist/graph/traverse.js +192 -0
  343. package/dist/graph/traverse.js.map +1 -0
  344. package/dist/graph/types.d.ts +78 -0
  345. package/dist/graph/types.d.ts.map +1 -0
  346. package/dist/graph/types.js +14 -0
  347. package/dist/graph/types.js.map +1 -0
  348. package/dist/graph/wasm-runtime.d.ts +19 -0
  349. package/dist/graph/wasm-runtime.d.ts.map +1 -0
  350. package/dist/graph/wasm-runtime.js +38 -0
  351. package/dist/graph/wasm-runtime.js.map +1 -0
  352. package/dist/graph/workspace-cli.d.ts +56 -0
  353. package/dist/graph/workspace-cli.d.ts.map +1 -0
  354. package/dist/graph/workspace-cli.js +111 -0
  355. package/dist/graph/workspace-cli.js.map +1 -0
  356. package/dist/graph/workspace.d.ts +172 -0
  357. package/dist/graph/workspace.d.ts.map +1 -0
  358. package/dist/graph/workspace.js +714 -0
  359. package/dist/graph/workspace.js.map +1 -0
  360. package/dist/graph/write.d.ts +13 -0
  361. package/dist/graph/write.d.ts.map +1 -0
  362. package/dist/graph/write.js +86 -0
  363. package/dist/graph/write.js.map +1 -0
  364. package/dist/hosts/antigravity.d.ts +14 -0
  365. package/dist/hosts/antigravity.d.ts.map +1 -0
  366. package/dist/hosts/antigravity.js +59 -0
  367. package/dist/hosts/antigravity.js.map +1 -0
  368. package/dist/hosts/auto.d.ts +37 -0
  369. package/dist/hosts/auto.d.ts.map +1 -0
  370. package/dist/hosts/auto.js +141 -0
  371. package/dist/hosts/auto.js.map +1 -0
  372. package/dist/hosts/claude-global.d.ts +72 -0
  373. package/dist/hosts/claude-global.d.ts.map +1 -0
  374. package/dist/hosts/claude-global.js +230 -0
  375. package/dist/hosts/claude-global.js.map +1 -0
  376. package/dist/hosts/config-write.d.ts +36 -0
  377. package/dist/hosts/config-write.d.ts.map +1 -0
  378. package/dist/hosts/config-write.js +64 -0
  379. package/dist/hosts/config-write.js.map +1 -0
  380. package/dist/hosts/init.d.ts +28 -0
  381. package/dist/hosts/init.d.ts.map +1 -0
  382. package/dist/hosts/init.js +89 -0
  383. package/dist/hosts/init.js.map +1 -0
  384. package/dist/hosts/instructions.d.ts +14 -0
  385. package/dist/hosts/instructions.d.ts.map +1 -0
  386. package/dist/hosts/instructions.js +95 -0
  387. package/dist/hosts/instructions.js.map +1 -0
  388. package/dist/hosts/mcp-config.d.ts +78 -0
  389. package/dist/hosts/mcp-config.d.ts.map +1 -0
  390. package/dist/hosts/mcp-config.js +251 -0
  391. package/dist/hosts/mcp-config.js.map +1 -0
  392. package/dist/hosts/plan.d.ts +32 -0
  393. package/dist/hosts/plan.d.ts.map +1 -0
  394. package/dist/hosts/plan.js +73 -0
  395. package/dist/hosts/plan.js.map +1 -0
  396. package/dist/hosts/registry.d.ts +41 -0
  397. package/dist/hosts/registry.d.ts.map +1 -0
  398. package/dist/hosts/registry.js +164 -0
  399. package/dist/hosts/registry.js.map +1 -0
  400. package/dist/hosts/retract.d.ts +47 -0
  401. package/dist/hosts/retract.d.ts.map +1 -0
  402. package/dist/hosts/retract.js +520 -0
  403. package/dist/hosts/retract.js.map +1 -0
  404. package/dist/hosts/sections.d.ts +47 -0
  405. package/dist/hosts/sections.d.ts.map +1 -0
  406. package/dist/hosts/sections.js +127 -0
  407. package/dist/hosts/sections.js.map +1 -0
  408. package/dist/index.d.ts +41 -0
  409. package/dist/index.d.ts.map +1 -0
  410. package/dist/index.js +32 -0
  411. package/dist/index.js.map +1 -0
  412. package/dist/ingest/fs.d.ts +79 -0
  413. package/dist/ingest/fs.d.ts.map +1 -0
  414. package/dist/ingest/fs.js +306 -0
  415. package/dist/ingest/fs.js.map +1 -0
  416. package/dist/init-guard.d.ts +16 -0
  417. package/dist/init-guard.d.ts.map +1 -0
  418. package/dist/init-guard.js +27 -0
  419. package/dist/init-guard.js.map +1 -0
  420. package/dist/mcp/instructions.d.ts +5 -0
  421. package/dist/mcp/instructions.d.ts.map +1 -0
  422. package/dist/mcp/instructions.js +64 -0
  423. package/dist/mcp/instructions.js.map +1 -0
  424. package/dist/mcp/kept-listing.d.ts +27 -0
  425. package/dist/mcp/kept-listing.d.ts.map +1 -0
  426. package/dist/mcp/kept-listing.js +63 -0
  427. package/dist/mcp/kept-listing.js.map +1 -0
  428. package/dist/mcp/server.d.ts +4 -0
  429. package/dist/mcp/server.d.ts.map +1 -0
  430. package/dist/mcp/server.js +147 -0
  431. package/dist/mcp/server.js.map +1 -0
  432. package/dist/mcp/tool-names.d.ts +27 -0
  433. package/dist/mcp/tool-names.d.ts.map +1 -0
  434. package/dist/mcp/tool-names.js +47 -0
  435. package/dist/mcp/tool-names.js.map +1 -0
  436. package/dist/mcp/tools.d.ts +22 -0
  437. package/dist/mcp/tools.d.ts.map +1 -0
  438. package/dist/mcp/tools.js +440 -0
  439. package/dist/mcp/tools.js.map +1 -0
  440. package/dist/node-version.d.ts +15 -0
  441. package/dist/node-version.d.ts.map +1 -0
  442. package/dist/node-version.js +23 -0
  443. package/dist/node-version.js.map +1 -0
  444. package/dist/search/grep-cli.d.ts +35 -0
  445. package/dist/search/grep-cli.d.ts.map +1 -0
  446. package/dist/search/grep-cli.js +115 -0
  447. package/dist/search/grep-cli.js.map +1 -0
  448. package/dist/search/grep.d.ts +60 -0
  449. package/dist/search/grep.d.ts.map +1 -0
  450. package/dist/search/grep.js +143 -0
  451. package/dist/search/grep.js.map +1 -0
  452. package/dist/search/ignored-code.d.ts +9 -0
  453. package/dist/search/ignored-code.d.ts.map +1 -0
  454. package/dist/search/ignored-code.js +73 -0
  455. package/dist/search/ignored-code.js.map +1 -0
  456. package/dist/search/user-regexp.d.ts +26 -0
  457. package/dist/search/user-regexp.d.ts.map +1 -0
  458. package/dist/search/user-regexp.js +150 -0
  459. package/dist/search/user-regexp.js.map +1 -0
  460. package/dist/telemetry/contract.d.ts +117 -0
  461. package/dist/telemetry/contract.d.ts.map +1 -0
  462. package/dist/telemetry/contract.js +341 -0
  463. package/dist/telemetry/contract.js.map +1 -0
  464. package/dist/telemetry/flush.d.ts +21 -0
  465. package/dist/telemetry/flush.d.ts.map +1 -0
  466. package/dist/telemetry/flush.js +85 -0
  467. package/dist/telemetry/flush.js.map +1 -0
  468. package/dist/telemetry/gate.d.ts +30 -0
  469. package/dist/telemetry/gate.d.ts.map +1 -0
  470. package/dist/telemetry/gate.js +81 -0
  471. package/dist/telemetry/gate.js.map +1 -0
  472. package/dist/telemetry/identity.d.ts +40 -0
  473. package/dist/telemetry/identity.d.ts.map +1 -0
  474. package/dist/telemetry/identity.js +80 -0
  475. package/dist/telemetry/identity.js.map +1 -0
  476. package/dist/telemetry/index.d.ts +18 -0
  477. package/dist/telemetry/index.d.ts.map +1 -0
  478. package/dist/telemetry/index.js +16 -0
  479. package/dist/telemetry/index.js.map +1 -0
  480. package/dist/telemetry/key.d.ts +21 -0
  481. package/dist/telemetry/key.d.ts.map +1 -0
  482. package/dist/telemetry/key.js +49 -0
  483. package/dist/telemetry/key.js.map +1 -0
  484. package/dist/telemetry/notice.d.ts +19 -0
  485. package/dist/telemetry/notice.d.ts.map +1 -0
  486. package/dist/telemetry/notice.js +93 -0
  487. package/dist/telemetry/notice.js.map +1 -0
  488. package/dist/telemetry/queue.d.ts +35 -0
  489. package/dist/telemetry/queue.d.ts.map +1 -0
  490. package/dist/telemetry/queue.js +162 -0
  491. package/dist/telemetry/queue.js.map +1 -0
  492. package/dist/telemetry/send.d.ts +19 -0
  493. package/dist/telemetry/send.d.ts.map +1 -0
  494. package/dist/telemetry/send.js +84 -0
  495. package/dist/telemetry/send.js.map +1 -0
  496. package/dist/telemetry/sessions.d.ts +25 -0
  497. package/dist/telemetry/sessions.d.ts.map +1 -0
  498. package/dist/telemetry/sessions.js +104 -0
  499. package/dist/telemetry/sessions.js.map +1 -0
  500. package/dist/telemetry/track.d.ts +62 -0
  501. package/dist/telemetry/track.d.ts.map +1 -0
  502. package/dist/telemetry/track.js +143 -0
  503. package/dist/telemetry/track.js.map +1 -0
  504. package/dist/upkeep-run.d.ts +22 -0
  505. package/dist/upkeep-run.d.ts.map +1 -0
  506. package/dist/upkeep-run.js +85 -0
  507. package/dist/upkeep-run.js.map +1 -0
  508. package/dist/upkeep.d.ts +127 -0
  509. package/dist/upkeep.d.ts.map +1 -0
  510. package/dist/upkeep.js +252 -0
  511. package/dist/upkeep.js.map +1 -0
  512. package/dist/util/actions-folder.d.ts +2 -0
  513. package/dist/util/actions-folder.d.ts.map +1 -0
  514. package/dist/util/actions-folder.js +9 -0
  515. package/dist/util/actions-folder.js.map +1 -0
  516. package/dist/util/browser.d.ts +3 -0
  517. package/dist/util/browser.d.ts.map +1 -0
  518. package/dist/util/browser.js +14 -0
  519. package/dist/util/browser.js.map +1 -0
  520. package/dist/util/child-process.d.ts +15 -0
  521. package/dist/util/child-process.d.ts.map +1 -0
  522. package/dist/util/child-process.js +15 -0
  523. package/dist/util/child-process.js.map +1 -0
  524. package/dist/util/front-matter.d.ts +46 -0
  525. package/dist/util/front-matter.d.ts.map +1 -0
  526. package/dist/util/front-matter.js +113 -0
  527. package/dist/util/front-matter.js.map +1 -0
  528. package/dist/util/id.d.ts +7 -0
  529. package/dist/util/id.d.ts.map +1 -0
  530. package/dist/util/id.js +14 -0
  531. package/dist/util/id.js.map +1 -0
  532. package/dist/util/paths.d.ts +29 -0
  533. package/dist/util/paths.d.ts.map +1 -0
  534. package/dist/util/paths.js +71 -0
  535. package/dist/util/paths.js.map +1 -0
  536. package/dist/util/private-file.d.ts +14 -0
  537. package/dist/util/private-file.d.ts.map +1 -0
  538. package/dist/util/private-file.js +82 -0
  539. package/dist/util/private-file.js.map +1 -0
  540. package/dist/util/source.d.ts +4 -0
  541. package/dist/util/source.d.ts.map +1 -0
  542. package/dist/util/source.js +12 -0
  543. package/dist/util/source.js.map +1 -0
  544. package/dist/util/spinner.d.ts +15 -0
  545. package/dist/util/spinner.d.ts.map +1 -0
  546. package/dist/util/spinner.js +52 -0
  547. package/dist/util/spinner.js.map +1 -0
  548. package/dist/util/state.d.ts +120 -0
  549. package/dist/util/state.d.ts.map +1 -0
  550. package/dist/util/state.js +264 -0
  551. package/dist/util/state.js.map +1 -0
  552. package/dist/vendor/grammars/tree-sitter-go.LICENSE +21 -0
  553. package/dist/vendor/grammars/tree-sitter-go.wasm +0 -0
  554. package/dist/vendor/grammars/tree-sitter-java.LICENSE +21 -0
  555. package/dist/vendor/grammars/tree-sitter-java.wasm +0 -0
  556. package/dist/vendor/grammars/tree-sitter-kotlin.LICENSE +9 -0
  557. package/dist/vendor/grammars/tree-sitter-kotlin.wasm +0 -0
  558. package/dist/vendor/grammars/tree-sitter-php.LICENSE +22 -0
  559. package/dist/vendor/grammars/tree-sitter-php.wasm +0 -0
  560. package/dist/vendor/grammars/tree-sitter-python.LICENSE +21 -0
  561. package/dist/vendor/grammars/tree-sitter-python.wasm +0 -0
  562. package/dist/vendor/grammars/tree-sitter-r.LICENSE +9 -0
  563. package/dist/vendor/grammars/tree-sitter-r.wasm +0 -0
  564. package/dist/vendor/grammars/tree-sitter-swift.LICENSE +21 -0
  565. package/dist/vendor/grammars/tree-sitter-swift.wasm +0 -0
  566. package/dist/vendor/grammars/tree-sitter-tsx.wasm +0 -0
  567. package/dist/vendor/grammars/tree-sitter-typescript.LICENSE +21 -0
  568. package/dist/vendor/grammars/tree-sitter-typescript.wasm +0 -0
  569. package/dist/viewer/app.js +2 -0
  570. package/dist/viewer/index.html +49 -0
  571. package/dist/viewer/style.css +154 -0
  572. package/dist/viz/assemble.d.ts +83 -0
  573. package/dist/viz/assemble.d.ts.map +1 -0
  574. package/dist/viz/assemble.js +101 -0
  575. package/dist/viz/assemble.js.map +1 -0
  576. package/dist/viz/export.d.ts +39 -0
  577. package/dist/viz/export.d.ts.map +1 -0
  578. package/dist/viz/export.js +98 -0
  579. package/dist/viz/export.js.map +1 -0
  580. package/dist/viz/serve.d.ts +13 -0
  581. package/dist/viz/serve.d.ts.map +1 -0
  582. package/dist/viz/serve.js +130 -0
  583. package/dist/viz/serve.js.map +1 -0
  584. package/package.json +115 -4
  585. package/scripts/build-grammar-wasm.mjs +112 -0
  586. package/scripts/build-viewer.mjs +44 -0
  587. package/scripts/graph-quality.mjs +117 -0
  588. package/scripts/pack-trail.mjs +53 -0
  589. package/scripts/postinstall.mjs +65 -0
  590. package/scripts/run-tests.mjs +72 -0
  591. package/scripts/stamp-telemetry-key.mjs +56 -0
  592. package/scripts/tally-audit.mjs +140 -0
  593. package/scripts/vendor-grammars.mjs +53 -0
@@ -0,0 +1,269 @@
1
+ /**
2
+ * Naming the clusters a diff reaches — the rung of the ladder between a concept
3
+ * node and the symbol backstop (see {@link LabelSource}).
4
+ *
5
+ * The point is scope. Getting labels from `build --deep` means summarising every
6
+ * file in the repo — 356 calls and thirteen minutes on graft's own repo — to put
7
+ * names on the six clusters a PR actually touches, and it still misses: only 40% of
8
+ * this repo's files are claimed by a concept, so the rest fall back to a path. Here
9
+ * the unit of work is the cluster, not the file: one request names all of them from
10
+ * data the graph already holds (paths and symbol names — no file reads), and the
11
+ * answer is cached by content hash so the next PR pays nothing for a cluster whose
12
+ * files did not change.
13
+ *
14
+ * Two rules keep it honest:
15
+ * - a cluster spanning unrelated features must come back "mixed", and then keeps
16
+ * its symbol backstop rather than a flattering name;
17
+ * - a failure of any kind — no key, spent quota, refused call, malformed answer —
18
+ * leaves every label exactly as it was and never fails the caller.
19
+ */
20
+ import { createHash } from "node:crypto";
21
+ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
22
+ import { dirname, join } from "node:path";
23
+ import { CACHE_DIR } from "../context/node-file.js";
24
+ import { shortLabel } from "./modules.js";
25
+ const SYSTEM_PROMPT = `You name parts of a codebase for a pull-request reviewer.
26
+
27
+ You are given clusters of files that a change can affect. For each cluster, answer with the FEATURE or SUBSYSTEM those files implement, as a developer on the team would refer to it in conversation.
28
+
29
+ Rules:
30
+ - 2 to 4 words, Title Case. No trailing "Module", "System", "Layer", "Manager" or "Handler" unless the team would genuinely say it.
31
+ - Name the RESPONSIBILITY, not the mechanics: "Query Freshness Gate", "Workspace Federation", "Asset Bundling". Never restate a path or a directory name, and never name it after the language or the file type.
32
+ - If the files in a cluster serve two or more unrelated responsibilities, answer exactly "mixed" for that cluster. A wrong name is worse than no name, because a reviewer will trust it.
33
+ - Answer for every cluster key you are given, and invent no other keys.`;
34
+ const NAMES_SCHEMA = {
35
+ type: "object",
36
+ properties: {
37
+ names: {
38
+ type: "array",
39
+ items: {
40
+ type: "object",
41
+ properties: {
42
+ key: { type: "string", description: "the cluster key, copied verbatim" },
43
+ name: { type: "string", description: '2-4 word Title Case name, or "mixed"' },
44
+ },
45
+ required: ["key", "name"],
46
+ additionalProperties: false,
47
+ },
48
+ },
49
+ },
50
+ required: ["names"],
51
+ additionalProperties: false,
52
+ };
53
+ /** Symbols shown per cluster. Enough to characterise it; not a file listing. */
54
+ const SYMBOLS_PER_CLUSTER = 8;
55
+ /**
56
+ * Clusters per request. A PR's diagram needs six, so one batch covers it — the cap
57
+ * is for the cache-priming job, which deliberately walks a wide diff and can hand
58
+ * over fifty clusters at once. Past a dozen the prompt stops being a list and the
59
+ * model starts dropping keys.
60
+ */
61
+ const CLUSTERS_PER_CALL = 12;
62
+ function clusterPrompt(clusters) {
63
+ return clusters
64
+ .map((c) => {
65
+ const files = c.files.slice(0, 10).join(", ");
66
+ const symbols = c.symbols.slice(0, SYMBOLS_PER_CLUSTER).join(", ");
67
+ return `key: ${c.key}\n files: ${files}\n symbols: ${symbols || "(none extracted)"}`;
68
+ })
69
+ .join("\n\n");
70
+ }
71
+ /** The production namer: one forced-tool call for every cluster at once. */
72
+ export class ChatNamer {
73
+ model;
74
+ constructor(model) {
75
+ this.model = model;
76
+ }
77
+ async name(clusters) {
78
+ const res = await this.model.create({
79
+ messages: [
80
+ { role: "system", content: SYSTEM_PROMPT },
81
+ { role: "user", content: clusterPrompt(clusters) },
82
+ ],
83
+ tools: [{ name: "record_names", description: "Record one name per cluster.", parameters: NAMES_SCHEMA }],
84
+ responseFormat: { kind: "tool", name: "record_names" },
85
+ temperature: 0,
86
+ maxTokens: 1024,
87
+ });
88
+ const out = new Map();
89
+ const call = res.toolCalls[0]?.args;
90
+ for (const row of call?.names ?? []) {
91
+ if (!row?.key || !row?.name)
92
+ continue;
93
+ const clean = sanitize(row.name);
94
+ // "mixed" is an answer, not a name: the cluster keeps its backstop.
95
+ if (!clean || /^mixed$/i.test(clean))
96
+ continue;
97
+ out.set(row.key, clean);
98
+ }
99
+ return out;
100
+ }
101
+ }
102
+ /**
103
+ * A model-written string on its way into a Mermaid label and a markdown table.
104
+ *
105
+ * Symbol names from a fork's diff reach the prompt, so the answer is untrusted
106
+ * input: anything that could close a label, open a tag or start a table cell is
107
+ * stripped here rather than at each render site.
108
+ */
109
+ export function sanitize(raw) {
110
+ const flat = raw.replace(/[\r\n]+/g, " ").replace(/[<>"'`|(){}[\]#]/g, "").replace(/\s+/g, " ").trim();
111
+ return shortLabel(flat);
112
+ }
113
+ /**
114
+ * The cache key for a cluster: what it contains, not what it is called.
115
+ *
116
+ * Member paths pin the shape and each member's `body_hash` pins the content, so a
117
+ * cluster is renamed only when the code in it actually changes. Without this the
118
+ * same area gets a slightly different name on every PR and two comments stop being
119
+ * comparable — the failure the cache exists to prevent.
120
+ */
121
+ export function clusterHash(files, hashes) {
122
+ const parts = [...files].sort().map((f) => `${f}:${hashes.get(f) ?? "?"}`);
123
+ return createHash("sha256").update(parts.join("\n")).digest("hex").slice(0, 16);
124
+ }
125
+ function cachePath(contextDir) {
126
+ return join(contextDir, CACHE_DIR, "areas.json");
127
+ }
128
+ export function loadNameCache(contextDir) {
129
+ try {
130
+ const raw = JSON.parse(readFileSync(cachePath(contextDir), "utf8"));
131
+ return raw && typeof raw === "object" ? raw : {};
132
+ }
133
+ catch {
134
+ // A missing or corrupt cache is a cache miss, never an error: the names are
135
+ // derivable again, and refusing to run because a cache file is bad is worse.
136
+ return {};
137
+ }
138
+ }
139
+ export function saveNameCache(contextDir, names) {
140
+ const path = cachePath(contextDir);
141
+ try {
142
+ mkdirSync(dirname(path), { recursive: true });
143
+ writeFileSync(path, `${JSON.stringify(names, null, 2)}\n`);
144
+ }
145
+ catch {
146
+ // Best-effort: an unwritable cache costs a call next time, nothing more.
147
+ }
148
+ }
149
+ /** File-node content hashes, which is what a cluster's identity is built from. */
150
+ function fileHashes(graph) {
151
+ const out = new Map();
152
+ for (const n of graph.nodes)
153
+ if (n.kind === "file")
154
+ out.set(n.path, n.body_hash ?? "");
155
+ return out;
156
+ }
157
+ function symbolsOf(c) {
158
+ return "symbols" in c ? c.symbols.map((s) => s.name) : c.seedNames;
159
+ }
160
+ /**
161
+ * Fill in labels for every cluster still sitting on its symbol backstop.
162
+ *
163
+ * Clusters already named by a concept node are left alone: a concept was written
164
+ * from whole file bodies, which is strictly more than the paths and symbol names
165
+ * this pass can see.
166
+ */
167
+ export async function applyNames(graph, report, opts) {
168
+ const stats = { cached: 0, named: 0, declined: 0 };
169
+ // `testModules` are deliberately absent: the comment shows them as a file count in
170
+ // one collapsed line and nowhere else, so naming them buys nothing and can push a
171
+ // normal PR over CLUSTERS_PER_CALL into a second request.
172
+ const targets = [...report.modules, ...report.areas]
173
+ .filter((c) => c.labelSource === "symbol");
174
+ if (targets.length === 0)
175
+ return stats;
176
+ const hashes = fileHashes(graph);
177
+ const cache = loadNameCache(opts.contextDir);
178
+ const pending = [];
179
+ /** Clusters sharing a hash share a name — and one call, not several. */
180
+ const byHash = new Map();
181
+ for (const t of targets) {
182
+ const hash = clusterHash(t.files, hashes);
183
+ byHash.set(hash, [...(byHash.get(hash) ?? []), t]);
184
+ }
185
+ for (const [hash, group] of byHash) {
186
+ const hit = cache[hash];
187
+ if (hit) {
188
+ for (const t of group) {
189
+ t.label = hit;
190
+ t.labelSource = "named";
191
+ }
192
+ stats.cached++;
193
+ continue;
194
+ }
195
+ pending.push({
196
+ cluster: { key: hash, files: group[0].files, symbols: symbolsOf(group[0]) },
197
+ targets: group,
198
+ });
199
+ }
200
+ if (pending.length === 0 || !opts.namer)
201
+ return stats;
202
+ const named = new Map();
203
+ for (let i = 0; i < pending.length; i += CLUSTERS_PER_CALL) {
204
+ const batch = pending.slice(i, i + CLUSTERS_PER_CALL);
205
+ try {
206
+ for (const [k, v] of await opts.namer.name(batch.map((p) => p.cluster)))
207
+ named.set(k, v);
208
+ }
209
+ catch (err) {
210
+ // Every label already holds its backstop, so there is nothing to undo — and a
211
+ // later batch failing must not discard the names an earlier one returned.
212
+ stats.error = err instanceof Error ? err.message : String(err);
213
+ break;
214
+ }
215
+ }
216
+ for (const p of pending) {
217
+ const name = named.get(p.cluster.key);
218
+ if (!name) {
219
+ stats.declined++;
220
+ continue;
221
+ }
222
+ for (const t of p.targets) {
223
+ t.label = name;
224
+ t.labelSource = "named";
225
+ }
226
+ cache[p.cluster.key] = name;
227
+ stats.named++;
228
+ }
229
+ if (stats.named > 0)
230
+ saveNameCache(opts.contextDir, cache);
231
+ return stats;
232
+ }
233
+ /**
234
+ * Name the clusters left on their symbol backstop, and say what it cost.
235
+ *
236
+ * Everything here is best-effort by construction: no key, a spent quota or a
237
+ * refused call leaves the backstop labels in place, because neither a PR check
238
+ * nor a review comment should fail over a cosmetic layer. The note comes back
239
+ * rather than going to a stream, so `graft blast --name` can prefix it and the
240
+ * App can log it against the pull request it belongs to.
241
+ */
242
+ export async function nameReport(graph, report, contextDir) {
243
+ const { resolveConfig } = await import("../ai/providers.js");
244
+ const cfg = resolveConfig({ contextDir });
245
+ let namer;
246
+ if (cfg.chatModel) {
247
+ namer = new ChatNamer(cfg.chatModel);
248
+ }
249
+ else if (cfg.apiKey) {
250
+ const { createChatModel } = await import("../ai/llm/factory.js");
251
+ namer = new ChatNamer(createChatModel({
252
+ provider: cfg.provider, apiKey: cfg.apiKey, model: cfg.model,
253
+ baseUrl: cfg.baseUrl, headers: cfg.headers,
254
+ }));
255
+ }
256
+ const stats = await applyNames(graph, report, { namer, contextDir });
257
+ if (!namer)
258
+ return { stats, note: "no API key (GRAFT_API_KEY), so areas keep their symbol names" };
259
+ if (stats.error)
260
+ return { stats, note: `naming failed (${stats.error}) — areas keep their symbol names` };
261
+ if (stats.named + stats.cached + stats.declined > 0) {
262
+ const bits = [`${stats.named} named`, `${stats.cached} cached`];
263
+ if (stats.declined > 0)
264
+ bits.push(`${stats.declined} left as symbols (mixed)`);
265
+ return { stats, note: bits.join(", ") };
266
+ }
267
+ return { stats, note: null };
268
+ }
269
+ //# sourceMappingURL=name.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"name.js","sourceRoot":"","sources":["../../src/blast/name.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ import type { BlastReport } from "./blast.js";
2
+ /** One person's claim on one area. */
3
+ export interface Owner {
4
+ /** Display name as git reports it, with `.mailmap` already applied. */
5
+ name: string;
6
+ /** GitHub handle, when the commit email carries one. Never guessed. */
7
+ handle?: string;
8
+ /** Commits of theirs that touched this area's files. */
9
+ commits: number;
10
+ /** Recency-weighted weight of those commits — the ranking key. */
11
+ score: number;
12
+ /** Their most recent commit here, ms since the epoch. */
13
+ last: number;
14
+ }
15
+ /** One person's claim across the whole report: what the tag line prints. */
16
+ export interface Reviewer extends Owner {
17
+ /** Area labels they own, heaviest first. */
18
+ areas: string[];
19
+ }
20
+ export interface OwnerOptions {
21
+ /** Logins, names or emails to drop — the PR author, so they are not told to
22
+ * tag themselves. Matched case-insensitively against all three. */
23
+ exclude?: string[];
24
+ /** Clock, so a test can plant history at a fixed distance from "now". */
25
+ now?: number;
26
+ }
27
+ /** Names listed per area, and in the tag line. */
28
+ export declare const MAX_PER_AREA = 2;
29
+ export declare const MAX_REVIEWERS = 3;
30
+ /**
31
+ * A GitHub handle out of a commit email, or null.
32
+ *
33
+ * Both noreply forms are accepted: the modern `12345+name@` and the legacy bare
34
+ * `name@`. The character class is GitHub's own username rule (alphanumerics and
35
+ * interior hyphens, 39 max) so an address that merely ends in the right domain
36
+ * cannot smuggle something unmentionable into a comment body.
37
+ */
38
+ export declare function githubHandle(email: string): string | null;
39
+ /**
40
+ * The people behind `files`, best first.
41
+ *
42
+ * `--no-merges` because a merge commit's author is whoever pressed the button,
43
+ * not whoever wrote the code. `%aN`/`%aE` rather than `%an`/`%ae` so git applies
44
+ * the repository's `.mailmap` for us — which is the supported way to give a
45
+ * contributor whose work address has no handle a noreply one, at no new config
46
+ * cost to graft.
47
+ */
48
+ export declare function ownersFor(root: string, files: string[], opts?: OwnerOptions): Owner[];
49
+ /**
50
+ * Everyone who authored a commit in `base...HEAD` — the people whose work this
51
+ * pull request IS.
52
+ *
53
+ * This is the exclusion that actually fires in CI. The obvious source for "who
54
+ * opened this" is `pull_request.user.email` from the webhook, but GitHub almost
55
+ * never populates it, so excluding on the login alone leaves anyone whose commits
56
+ * carry a work address being suggested as a reviewer of their own PR. The commits
57
+ * in the range carry exactly the name and email git will match on later.
58
+ *
59
+ * Co-authors count too: a pair-programmed commit has two people on it and neither
60
+ * of them is a reviewer of it.
61
+ */
62
+ export declare function diffAuthors(root: string, base: string): string[];
63
+ /**
64
+ * Whoever git would sign a commit as, here and now.
65
+ *
66
+ * The local counterpart of {@link diffAuthors}. `graft blast` with no `--base`
67
+ * compares the working tree against HEAD, so there is no commit range to read
68
+ * authors from — and without this, the one person guaranteed to have written the
69
+ * change being examined is also the top name in its own "who to tag" list.
70
+ */
71
+ export declare function localIdentity(root: string): string[];
72
+ /**
73
+ * Fill in `owners` on every area and module, and rank the report's `reviewers`.
74
+ *
75
+ * Called AFTER `--name`, because a reviewer's reason cites area labels and the
76
+ * naming pass is what gives an area its final label.
77
+ */
78
+ export declare function attachOwners(root: string, report: BlastReport, opts?: OwnerOptions): void;
79
+ /** `9d ago`, `3mo ago` — how a comment says when someone was last in here. */
80
+ export declare function sinceLabel(last: number, now?: number): string;
81
+ /** `@handle`, or the bare name when git carries no handle for them. */
82
+ export declare function mention(o: Owner): string;
83
+ /** ISO day, for an exported page that has to stay truthful when opened later. */
84
+ export declare function isoDay(ms: number): string;
85
+ //# sourceMappingURL=owners.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owners.d.ts","sourceRoot":"","sources":["../../src/blast/owners.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,sCAAsC;AACtC,MAAM,WAAW,KAAK;IACpB,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,4EAA4E;AAC5E,MAAM,WAAW,QAAS,SAAQ,KAAK;IACrC,4CAA4C;IAC5C,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B;uEACmE;IACnE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AA4BD,kDAAkD;AAClD,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,eAAO,MAAM,aAAa,IAAI,CAAC;AAW/B;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGzD;AAkBD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE,YAAiB,GAAG,KAAK,EAAE,CAuEzF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAiBhE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAIpD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,GAAE,YAAiB,GAAG,IAAI,CA+B7F;AAED,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,MAAM,CAOzE;AAED,uEAAuE;AACvE,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,CAExC;AAED,iFAAiF;AACjF,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAEzC"}
@@ -0,0 +1,272 @@
1
+ /**
2
+ * Who to tag on a pull request: the people whose fingerprints are on the areas
3
+ * this diff changes or can affect.
4
+ *
5
+ * The blast report already answers "what does this reach"; the author's next
6
+ * question is "who do I ask about it", and git has the answer without a single
7
+ * API call. One `git log` per area over that area's OWN files, scored by recency,
8
+ * ranked, capped.
9
+ *
10
+ * Two rules keep the output honest, and both exist because a wrong name here is
11
+ * worse than no name:
12
+ *
13
+ * - A handle is only ever printed when git actually carries one (the GitHub
14
+ * noreply address, which anything merged through the web UI has). With no
15
+ * handle the display name is printed unlinked — a guessed `@mention` pings a
16
+ * stranger, and there is no cheap way to verify a guess.
17
+ * - An owner has to hold {@link MIN_SHARE} of an area's weight to be named. That
18
+ * drops a drive-by typo fix next to a real owner, and keeps it when the
19
+ * drive-by is all the history there is.
20
+ *
21
+ * Everything here is best-effort: no git, no repository, a detached tarball
22
+ * checkout or a shallow clone leaves the report exactly as it was and the comment
23
+ * simply says nothing about people.
24
+ */
25
+ import { WINHIDE } from "../util/child-process.js";
26
+ import { spawnSync } from "node:child_process";
27
+ import { resolve } from "node:path";
28
+ /**
29
+ * Recency half-life. A commit from four months ago counts half as much as one
30
+ * from today, so the person who rewrote a module last month outranks the person
31
+ * who created it two years ago and moved on — which is the reviewer an author
32
+ * actually wants.
33
+ */
34
+ const HALF_LIFE_MS = 120 * 24 * 60 * 60 * 1000;
35
+ /**
36
+ * History window and commit cap, per area.
37
+ *
38
+ * Both are bounds on the walk, not on the answer: at 36 months a commit is worth
39
+ * 0.002 of a fresh one, so nothing outside the window could survive the share
40
+ * floor anyway, and the pair keeps one `git log` off a large repo's full history.
41
+ */
42
+ const SINCE = "36.months";
43
+ const MAX_COMMITS = 400;
44
+ /** Files passed to one `git log`. A very wide area is sampled rather than blowing
45
+ * the argument list; the sample is the area's own sorted file list, so it is
46
+ * stable between runs rather than whichever files git happened to yield. */
47
+ const MAX_PATHSPEC = 80;
48
+ /** Share of an area's total weight an owner must hold to be named. */
49
+ const MIN_SHARE = 0.15;
50
+ /** Names listed per area, and in the tag line. */
51
+ export const MAX_PER_AREA = 2;
52
+ export const MAX_REVIEWERS = 3;
53
+ /**
54
+ * Weight of an area a diff only *reaches*, against one it edits.
55
+ *
56
+ * Not zero, because the person whose code your change can break is exactly the
57
+ * reviewer the diff alone would never surface — that is what the blast radius is
58
+ * for. Not one either: the author of the code you edited knows it better.
59
+ */
60
+ const AFFECTED_WEIGHT = 0.6;
61
+ /**
62
+ * A GitHub handle out of a commit email, or null.
63
+ *
64
+ * Both noreply forms are accepted: the modern `12345+name@` and the legacy bare
65
+ * `name@`. The character class is GitHub's own username rule (alphanumerics and
66
+ * interior hyphens, 39 max) so an address that merely ends in the right domain
67
+ * cannot smuggle something unmentionable into a comment body.
68
+ */
69
+ export function githubHandle(email) {
70
+ const m = /^(?:\d+\+)?([A-Za-z0-9](?:-?[A-Za-z0-9]){0,38})@users\.noreply\.github\.com$/i.exec(email.trim());
71
+ return m ? m[1] : null;
72
+ }
73
+ /** Bots write commits and are never reviewers. */
74
+ function isBot(name, email) {
75
+ return /\[bot\]/i.test(name) || /\[bot\]@/i.test(email) || /^(github-actions|dependabot|renovate)(\[bot\])?$/i.test(name.trim());
76
+ }
77
+ /** Run git in `root`, or null when git fails — not a repo, no git, no history. */
78
+ function git(root, args) {
79
+ const res = spawnSync("git", ["-c", "core.quotePath=false", ...args], { ...WINHIDE, cwd: root,
80
+ encoding: "utf8",
81
+ stdio: ["ignore", "pipe", "pipe"],
82
+ maxBuffer: 64 * 1024 * 1024,
83
+ });
84
+ if (res.error || res.status !== 0 || typeof res.stdout !== "string")
85
+ return null;
86
+ return res.stdout;
87
+ }
88
+ /**
89
+ * The people behind `files`, best first.
90
+ *
91
+ * `--no-merges` because a merge commit's author is whoever pressed the button,
92
+ * not whoever wrote the code. `%aN`/`%aE` rather than `%an`/`%ae` so git applies
93
+ * the repository's `.mailmap` for us — which is the supported way to give a
94
+ * contributor whose work address has no handle a noreply one, at no new config
95
+ * cost to graft.
96
+ */
97
+ export function ownersFor(root, files, opts = {}) {
98
+ const paths = [...files].sort().slice(0, MAX_PATHSPEC);
99
+ if (paths.length === 0)
100
+ return [];
101
+ const now = opts.now ?? Date.now();
102
+ const out = git(resolve(root), [
103
+ "log",
104
+ "--no-merges",
105
+ `--since=${SINCE}`,
106
+ "-n",
107
+ String(MAX_COMMITS),
108
+ "--format=\x01%H\x02%aI\x02%aN\x02%aE",
109
+ "--name-only",
110
+ "--",
111
+ ...paths,
112
+ ]);
113
+ if (out === null)
114
+ return [];
115
+ const wanted = new Set(paths);
116
+ const people = new Map();
117
+ let commit = null;
118
+ for (const line of out.split("\n")) {
119
+ if (line.startsWith("\x01")) {
120
+ const [hash, iso, name, email] = line.slice(1).split("\x02");
121
+ const at = Date.parse(iso ?? "");
122
+ commit = Number.isFinite(at)
123
+ ? { hash, at, weight: Math.pow(0.5, (now - at) / HALF_LIFE_MS), name: name ?? "", email: email ?? "" }
124
+ : null;
125
+ continue;
126
+ }
127
+ // A pathspec'd `git log --name-only` already lists only matching files, but
128
+ // the set is re-checked here so a future flag change cannot silently start
129
+ // crediting whoever touched an unrelated file in the same commit.
130
+ if (commit === null || !wanted.has(line))
131
+ continue;
132
+ if (isBot(commit.name, commit.email))
133
+ continue;
134
+ const handle = githubHandle(commit.email) ?? undefined;
135
+ const key = (handle ?? commit.email).toLowerCase();
136
+ const prev = people.get(key);
137
+ if (!prev) {
138
+ people.set(key, {
139
+ name: commit.name, handle, commits: 1, score: commit.weight, last: commit.at,
140
+ seen: new Set([commit.hash]),
141
+ });
142
+ continue;
143
+ }
144
+ // One commit touching six files in the area is one commit, not six.
145
+ if (prev.seen.has(commit.hash))
146
+ continue;
147
+ prev.seen.add(commit.hash);
148
+ prev.commits += 1;
149
+ prev.score += commit.weight;
150
+ prev.last = Math.max(prev.last, commit.at);
151
+ }
152
+ const excluded = new Set((opts.exclude ?? []).map((e) => e.trim().toLowerCase()).filter(Boolean));
153
+ const isExcluded = (o, email) => excluded.has(email.toLowerCase()) ||
154
+ excluded.has(o.name.toLowerCase()) ||
155
+ (o.handle !== undefined && excluded.has(o.handle.toLowerCase()));
156
+ const kept = [...people].filter(([email, o]) => !isExcluded(o, email)).map(([, o]) => o);
157
+ // The floor is a SHARE of what is left after the author is dropped, not of the
158
+ // whole area. On a repo where one person wrote everything, their own PR would
159
+ // otherwise leave every remaining contributor under the floor and report nobody.
160
+ const total = kept.reduce((n, o) => n + o.score, 0);
161
+ return kept
162
+ .filter((o) => total === 0 || o.score / total >= MIN_SHARE)
163
+ .sort((a, b) => b.score - a.score || b.commits - a.commits || a.name.localeCompare(b.name))
164
+ .slice(0, MAX_PER_AREA)
165
+ .map(({ name, handle, commits, score, last }) => ({ name, handle, commits, score, last }));
166
+ }
167
+ /**
168
+ * Everyone who authored a commit in `base...HEAD` — the people whose work this
169
+ * pull request IS.
170
+ *
171
+ * This is the exclusion that actually fires in CI. The obvious source for "who
172
+ * opened this" is `pull_request.user.email` from the webhook, but GitHub almost
173
+ * never populates it, so excluding on the login alone leaves anyone whose commits
174
+ * carry a work address being suggested as a reviewer of their own PR. The commits
175
+ * in the range carry exactly the name and email git will match on later.
176
+ *
177
+ * Co-authors count too: a pair-programmed commit has two people on it and neither
178
+ * of them is a reviewer of it.
179
+ */
180
+ export function diffAuthors(root, base) {
181
+ const out = git(resolve(root), ["log", "--format=%aN%n%aE%n%(trailers:key=Co-authored-by,valueonly)", `${base}...HEAD`]);
182
+ if (out === null)
183
+ return [];
184
+ const names = new Set();
185
+ for (const raw of out.split("\n")) {
186
+ const line = raw.trim();
187
+ if (line === "")
188
+ continue;
189
+ // A co-author trailer is `Name <email>`; both halves are worth excluding.
190
+ const m = /^(.*?)\s*<([^>]+)>$/.exec(line);
191
+ if (m) {
192
+ if (m[1])
193
+ names.add(m[1]);
194
+ names.add(m[2]);
195
+ continue;
196
+ }
197
+ names.add(line);
198
+ }
199
+ return [...names];
200
+ }
201
+ /**
202
+ * Whoever git would sign a commit as, here and now.
203
+ *
204
+ * The local counterpart of {@link diffAuthors}. `graft blast` with no `--base`
205
+ * compares the working tree against HEAD, so there is no commit range to read
206
+ * authors from — and without this, the one person guaranteed to have written the
207
+ * change being examined is also the top name in its own "who to tag" list.
208
+ */
209
+ export function localIdentity(root) {
210
+ const dir = resolve(root);
211
+ const out = [git(dir, ["config", "user.name"]), git(dir, ["config", "user.email"])];
212
+ return out.map((v) => v?.trim() ?? "").filter((v) => v !== "");
213
+ }
214
+ /**
215
+ * Fill in `owners` on every area and module, and rank the report's `reviewers`.
216
+ *
217
+ * Called AFTER `--name`, because a reviewer's reason cites area labels and the
218
+ * naming pass is what gives an area its final label.
219
+ */
220
+ export function attachOwners(root, report, opts = {}) {
221
+ const ranked = new Map();
222
+ const visit = (label, files, weight) => {
223
+ const owners = ownersFor(root, files, opts);
224
+ for (const o of owners) {
225
+ const key = (o.handle ?? o.name).toLowerCase();
226
+ const prev = ranked.get(key);
227
+ if (!prev) {
228
+ ranked.set(key, { ...o, areas: [label], weighted: o.score * weight });
229
+ continue;
230
+ }
231
+ prev.areas.push(label);
232
+ prev.commits += o.commits;
233
+ prev.score += o.score;
234
+ prev.weighted += o.score * weight;
235
+ prev.last = Math.max(prev.last, o.last);
236
+ // A handle found on any one area is the handle: a contributor who has some
237
+ // commits from the web UI and some from a laptop should still be taggable.
238
+ if (prev.handle === undefined && o.handle !== undefined)
239
+ prev.handle = o.handle;
240
+ }
241
+ return owners;
242
+ };
243
+ for (const area of report.areas)
244
+ area.owners = visit(area.label, area.files, 1);
245
+ for (const mod of report.modules)
246
+ mod.owners = visit(mod.label, mod.files, AFFECTED_WEIGHT);
247
+ report.reviewers = [...ranked.values()]
248
+ .sort((a, b) => b.weighted - a.weighted || b.commits - a.commits || a.name.localeCompare(b.name))
249
+ .slice(0, MAX_REVIEWERS)
250
+ .map(({ weighted: _weighted, ...r }) => r);
251
+ }
252
+ /** `9d ago`, `3mo ago` — how a comment says when someone was last in here. */
253
+ export function sinceLabel(last, now = Date.now()) {
254
+ const days = Math.max(0, Math.round((now - last) / (24 * 60 * 60 * 1000)));
255
+ if (days < 1)
256
+ return "today";
257
+ if (days === 1)
258
+ return "yesterday";
259
+ if (days < 31)
260
+ return `${days}d ago`;
261
+ const months = Math.round(days / 30);
262
+ return months < 24 ? `${months}mo ago` : `${Math.round(days / 365)}y ago`;
263
+ }
264
+ /** `@handle`, or the bare name when git carries no handle for them. */
265
+ export function mention(o) {
266
+ return o.handle !== undefined ? `@${o.handle}` : o.name;
267
+ }
268
+ /** ISO day, for an exported page that has to stay truthful when opened later. */
269
+ export function isoDay(ms) {
270
+ return new Date(ms).toISOString().slice(0, 10);
271
+ }
272
+ //# sourceMappingURL=owners.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owners.js","sourceRoot":"","sources":["../../src/blast/owners.ts"],"names":[],"mappings":"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"}