ashlr-plugin 1.36.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (499) hide show
  1. package/.agents/plugins/marketplace.json +20 -0
  2. package/.claude-plugin/marketplace.json +39 -0
  3. package/.claude-plugin/plugin.json +36 -0
  4. package/.codex/agents/README.md +9 -0
  5. package/.codex/agents/ashlr-explorer.md +36 -0
  6. package/.codex/agents/ashlr-worker.md +38 -0
  7. package/.codex-plugin/plugin.json +45 -0
  8. package/.mcp.json +14 -0
  9. package/LICENSE +21 -0
  10. package/README.md +311 -0
  11. package/agents/ashlr-code.md +69 -0
  12. package/agents/ashlr-explore.md +44 -0
  13. package/agents/ashlr-plan.md +54 -0
  14. package/bench/fixtures/notebook-large.ipynb +660 -0
  15. package/bench/fixtures/notebook-small.ipynb +39 -0
  16. package/bench/fixtures/tasklist-closed.json +62 -0
  17. package/bench/fixtures/tasklist-large-mixed.json +27 -0
  18. package/bench/fixtures/tasklist-sprint-open.json +79 -0
  19. package/bench/fixtures/websearch-bun-runtime.json +32 -0
  20. package/bench/fixtures/websearch-react-hooks-patterns.json +32 -0
  21. package/bench/fixtures/websearch-typescript-generics.json +38 -0
  22. package/bench/refs/node-sdk/.refrev +1 -0
  23. package/bench/refs/node-sdk/README.md +17 -0
  24. package/bench/refs/node-sdk/src/agent/agent.ts +163 -0
  25. package/bench/refs/node-sdk/src/agent/create-agent-ui-stream.ts +83 -0
  26. package/bench/refs/node-sdk/src/agent/tool-loop-agent.ts +238 -0
  27. package/bench/refs/node-sdk/src/embed/embed-many.ts +409 -0
  28. package/bench/refs/node-sdk/src/embed/embed-result.ts +50 -0
  29. package/bench/refs/node-sdk/src/embed/embed.ts +257 -0
  30. package/bench/refs/node-sdk/src/error/invalid-argument-error.ts +34 -0
  31. package/bench/refs/node-sdk/src/error/invalid-tool-input-error.ts +33 -0
  32. package/bench/refs/node-sdk/src/error/no-object-generated-error.ts +70 -0
  33. package/bench/refs/node-sdk/src/generate-image/generate-image-result.ts +42 -0
  34. package/bench/refs/node-sdk/src/generate-image/generate-image.ts +362 -0
  35. package/bench/refs/node-sdk/src/generate-object/generate-object-result.ts +67 -0
  36. package/bench/refs/node-sdk/src/generate-object/generate-object.ts +501 -0
  37. package/bench/refs/node-sdk/src/generate-object/inject-json-instruction.ts +30 -0
  38. package/bench/refs/node-sdk/src/generate-object/output-strategy.ts +415 -0
  39. package/bench/refs/node-sdk/src/generate-object/repair-text.ts +12 -0
  40. package/bench/refs/node-sdk/src/generate-object/stream-object.ts +960 -0
  41. package/bench/refs/node-sdk/src/generate-speech/generate-speech.ts +191 -0
  42. package/bench/refs/node-sdk/src/generate-text/generate-text.ts +1484 -0
  43. package/bench/refs/node-sdk/src/generate-text/stream-text.ts +2708 -0
  44. package/bench/refs/node-sdk/src/generate-text/tool-call.ts +59 -0
  45. package/bench/refs/node-sdk/src/generate-text/tool-result.ts +36 -0
  46. package/bench/refs/node-sdk/src/telemetry/create-telemetry-dispatcher.ts +146 -0
  47. package/bench/refs/node-sdk/src/telemetry/telemetry-registry.ts +15 -0
  48. package/bench/refs/node-sdk/src/telemetry/telemetry.ts +223 -0
  49. package/bench/refs/node-sdk/src/util/async-iterable-stream.ts +94 -0
  50. package/bench/refs/node-sdk/src/util/consume-stream.ts +31 -0
  51. package/bench/refs/node-sdk/src/util/create-stitchable-stream.ts +112 -0
  52. package/bench/refs/node-sdk/src/util/download/download.ts +74 -0
  53. package/bench/refs/node-sdk/src/util/error-handler.ts +1 -0
  54. package/bench/refs/node-sdk/src/util/fix-json.ts +401 -0
  55. package/bench/refs/node-sdk/src/util/merge-objects.ts +79 -0
  56. package/bench/refs/python-lib/.refrev +1 -0
  57. package/bench/refs/python-lib/README.md +18 -0
  58. package/bench/refs/python-lib/pandas/core/_numba/executor.py +249 -0
  59. package/bench/refs/python-lib/pandas/core/_numba/extensions.py +586 -0
  60. package/bench/refs/python-lib/pandas/core/_numba/kernels/mean_.py +198 -0
  61. package/bench/refs/python-lib/pandas/core/_numba/kernels/min_max_.py +178 -0
  62. package/bench/refs/python-lib/pandas/core/_numba/kernels/sum_.py +255 -0
  63. package/bench/refs/python-lib/pandas/core/_numba/kernels/var_.py +251 -0
  64. package/bench/refs/python-lib/pandas/core/accessor.py +520 -0
  65. package/bench/refs/python-lib/pandas/core/api.py +138 -0
  66. package/bench/refs/python-lib/pandas/core/array_algos/masked_accumulations.py +97 -0
  67. package/bench/refs/python-lib/pandas/core/array_algos/masked_reductions.py +252 -0
  68. package/bench/refs/python-lib/pandas/core/array_algos/putmask.py +150 -0
  69. package/bench/refs/python-lib/pandas/core/array_algos/quantile.py +232 -0
  70. package/bench/refs/python-lib/pandas/core/array_algos/replace.py +159 -0
  71. package/bench/refs/python-lib/pandas/core/array_algos/take.py +609 -0
  72. package/bench/refs/python-lib/pandas/core/arraylike.py +534 -0
  73. package/bench/refs/python-lib/pandas/core/arrays/_arrow_string_mixins.py +434 -0
  74. package/bench/refs/python-lib/pandas/core/arrays/_mixins.py +630 -0
  75. package/bench/refs/python-lib/pandas/core/arrays/_ranges.py +276 -0
  76. package/bench/refs/python-lib/pandas/core/arrays/_utils.py +77 -0
  77. package/bench/refs/python-lib/pandas/core/arrays/arrow/accessors.py +521 -0
  78. package/bench/refs/python-lib/pandas/core/arrays/arrow/extension_types.py +174 -0
  79. package/bench/refs/python-lib/pandas/core/arrays/boolean.py +454 -0
  80. package/bench/refs/python-lib/pandas/core/arrays/floating.py +192 -0
  81. package/bench/refs/python-lib/pandas/core/arrays/integer.py +296 -0
  82. package/bench/refs/python-lib/pandas/core/arrays/masked.py +2140 -0
  83. package/bench/refs/python-lib/pandas/core/arrays/numeric.py +305 -0
  84. package/bench/refs/python-lib/pandas/core/arrays/numpy_.py +701 -0
  85. package/bench/refs/python-lib/pandas/core/arrays/period.py +1586 -0
  86. package/bench/refs/python-lib/pandas/core/arrays/sparse/accessor.py +505 -0
  87. package/bench/refs/python-lib/pandas/core/arrays/sparse/scipy_sparse.py +208 -0
  88. package/bench/refs/rust-project/.refrev +1 -0
  89. package/bench/refs/rust-project/README.md +17 -0
  90. package/bench/refs/rust-project/tokio/src/doc/os.rs +68 -0
  91. package/bench/refs/rust-project/tokio/src/fs/dir_builder.rs +129 -0
  92. package/bench/refs/rust-project/tokio/src/fs/file.rs +1113 -0
  93. package/bench/refs/rust-project/tokio/src/fs/mocks.rs +176 -0
  94. package/bench/refs/rust-project/tokio/src/fs/mod.rs +324 -0
  95. package/bench/refs/rust-project/tokio/src/fs/open_options.rs +856 -0
  96. package/bench/refs/rust-project/tokio/src/fs/read.rs +80 -0
  97. package/bench/refs/rust-project/tokio/src/fs/read_dir.rs +357 -0
  98. package/bench/refs/rust-project/tokio/src/fs/write.rs +99 -0
  99. package/bench/refs/rust-project/tokio/src/future/maybe_done.rs +123 -0
  100. package/bench/refs/rust-project/tokio/src/future/try_join.rs +82 -0
  101. package/bench/refs/rust-project/tokio/src/io/async_buf_read.rs +117 -0
  102. package/bench/refs/rust-project/tokio/src/io/async_read.rs +133 -0
  103. package/bench/refs/rust-project/tokio/src/io/async_seek.rs +96 -0
  104. package/bench/refs/rust-project/tokio/src/io/async_write.rs +402 -0
  105. package/bench/refs/rust-project/tokio/src/io/blocking.rs +339 -0
  106. package/bench/refs/rust-project/tokio/src/io/interest.rs +345 -0
  107. package/bench/refs/rust-project/tokio/src/io/join.rs +130 -0
  108. package/bench/refs/rust-project/tokio/src/io/mod.rs +308 -0
  109. package/bench/refs/rust-project/tokio/src/io/poll_evented.rs +319 -0
  110. package/bench/refs/rust-project/tokio/src/io/read_buf.rs +344 -0
  111. package/bench/refs/rust-project/tokio/src/io/ready.rs +322 -0
  112. package/bench/refs/rust-project/tokio/src/io/split.rs +166 -0
  113. package/bench/refs/rust-project/tokio/src/io/stderr.rs +148 -0
  114. package/bench/refs/rust-project/tokio/src/io/stdin.rs +98 -0
  115. package/bench/refs/rust-project/tokio/src/io/stdio_common.rs +222 -0
  116. package/bench/refs/rust-project/tokio/src/io/stdout.rs +197 -0
  117. package/bench/refs/rust-project/tokio/src/io/util/buf_reader.rs +311 -0
  118. package/bench/refs/rust-project/tokio/src/io/util/buf_stream.rs +207 -0
  119. package/bench/refs/rust-project/tokio/src/io/util/buf_writer.rs +310 -0
  120. package/bench/refs/rust-project/tokio/src/io/util/chain.rs +144 -0
  121. package/commands/_spawn-patterns.json +32 -0
  122. package/commands/ashlr-allow.md +21 -0
  123. package/commands/ashlr-benchmark.md +53 -0
  124. package/commands/ashlr-brief.md +97 -0
  125. package/commands/ashlr-budget.md +76 -0
  126. package/commands/ashlr-compact.md +54 -0
  127. package/commands/ashlr-dashboard.md +37 -0
  128. package/commands/ashlr-doctor.md +56 -0
  129. package/commands/ashlr-eco-mode.md +92 -0
  130. package/commands/ashlr-genome-init.md +24 -0
  131. package/commands/ashlr-genome-keygen.md +36 -0
  132. package/commands/ashlr-genome-loop.md +118 -0
  133. package/commands/ashlr-genome-push.md +36 -0
  134. package/commands/ashlr-genome-rewrap.md +48 -0
  135. package/commands/ashlr-genome-team-init.md +67 -0
  136. package/commands/ashlr-handoff.md +23 -0
  137. package/commands/ashlr-help.md +86 -0
  138. package/commands/ashlr-hook-timings.md +30 -0
  139. package/commands/ashlr-leaderboard.md +50 -0
  140. package/commands/ashlr-ollama-setup.md +39 -0
  141. package/commands/ashlr-orchestrate-status.md +72 -0
  142. package/commands/ashlr-orchestrate.md +83 -0
  143. package/commands/ashlr-parallelize.md +63 -0
  144. package/commands/ashlr-report-crash.md +33 -0
  145. package/commands/ashlr-resume.md +72 -0
  146. package/commands/ashlr-savings.md +24 -0
  147. package/commands/ashlr-settings.md +50 -0
  148. package/commands/ashlr-spawn.md +61 -0
  149. package/commands/ashlr-start.md +60 -0
  150. package/commands/ashlr-status.md +64 -0
  151. package/commands/ashlr-team-invite.md +47 -0
  152. package/commands/ashlr-tier.md +122 -0
  153. package/commands/ashlr-tour.md +60 -0
  154. package/commands/ashlr-update.md +155 -0
  155. package/commands/ashlr-upgrade.md +96 -0
  156. package/commands/goal.md +58 -0
  157. package/commands/loop.md +40 -0
  158. package/docs/CNAME +1 -0
  159. package/docs/PRO_TIER.md +104 -0
  160. package/docs/README.md +21 -0
  161. package/docs/architecture.md +415 -0
  162. package/docs/ashlr-pipe.md +161 -0
  163. package/docs/assets/logo.svg +19 -0
  164. package/docs/assets/og.png +0 -0
  165. package/docs/assets/og.svg +41 -0
  166. package/docs/benchmarks-v2.json +355 -0
  167. package/docs/benchmarks.json +102 -0
  168. package/docs/benchmarks.md +211 -0
  169. package/docs/billing.md +185 -0
  170. package/docs/cloud-genome.md +155 -0
  171. package/docs/competitive-wozcode.md +92 -0
  172. package/docs/deploy.md +325 -0
  173. package/docs/email-templates.md +113 -0
  174. package/docs/embed-tuning.md +103 -0
  175. package/docs/genome.md +120 -0
  176. package/docs/github-oauth-onboarding.md +127 -0
  177. package/docs/hero-video-script.md +129 -0
  178. package/docs/index.html +2262 -0
  179. package/docs/install-prompt.md +78 -0
  180. package/docs/install-windows.md +132 -0
  181. package/docs/install.ps1 +171 -0
  182. package/docs/install.sh +146 -0
  183. package/docs/launch/README.md +114 -0
  184. package/docs/launch/hn.md +49 -0
  185. package/docs/launch/reddit.md +45 -0
  186. package/docs/launch/x.md +65 -0
  187. package/docs/launch-post.md +112 -0
  188. package/docs/legal.md +78 -0
  189. package/docs/llm-providers.md +99 -0
  190. package/docs/multi-host-mcp.md +217 -0
  191. package/docs/multi-turn-architecture.md +108 -0
  192. package/docs/operations/deployment.md +108 -0
  193. package/docs/operations/error-monitoring.md +70 -0
  194. package/docs/operations/weekly-digest.md +70 -0
  195. package/docs/operations.md +494 -0
  196. package/docs/platform-support.md +133 -0
  197. package/docs/policy-packs.md +188 -0
  198. package/docs/press-kit/fact-sheet.md +78 -0
  199. package/docs/press-kit/founder-bio.md +3 -0
  200. package/docs/press-kit/logo.svg +33 -0
  201. package/docs/press-kit/screenshots.md +146 -0
  202. package/docs/pricing.md +251 -0
  203. package/docs/pro-backend-architecture.md +523 -0
  204. package/docs/producthunt.md +52 -0
  205. package/docs/router-migration.md +110 -0
  206. package/docs/session-log-schema.md +68 -0
  207. package/docs/social.md +95 -0
  208. package/docs/team-genome.md +528 -0
  209. package/docs/telemetry.md +194 -0
  210. package/docs/test-isolation.md +100 -0
  211. package/docs/upgrade.md +159 -0
  212. package/hooks/_hook-errors.ts +87 -0
  213. package/hooks/_hook-perf-emit.ts +113 -0
  214. package/hooks/_hook-timing-ledger.ts +1133 -0
  215. package/hooks/_nudge-throttle.ts +127 -0
  216. package/hooks/_recent-blocks.ts +127 -0
  217. package/hooks/audit-upload.ts +86 -0
  218. package/hooks/codex-hooks.json +171 -0
  219. package/hooks/commit-attribution.ts +179 -0
  220. package/hooks/edit-batching-nudge.ts +154 -0
  221. package/hooks/genome-scribe-hook.ts +219 -0
  222. package/hooks/hooks.json +294 -0
  223. package/hooks/orient-nudge-hook.ts +242 -0
  224. package/hooks/policy-enforce.ts +214 -0
  225. package/hooks/post-tool-use-embedding.ts +93 -0
  226. package/hooks/post-tool-use-genome.sh +37 -0
  227. package/hooks/post-tool-use-genome.ts +69 -0
  228. package/hooks/posttooluse-correlate.ts +122 -0
  229. package/hooks/posttooluse-dedupe-output.ts +241 -0
  230. package/hooks/posttooluse-genome-refresh.ts +223 -0
  231. package/hooks/posttooluse-native-nudge.ts +205 -0
  232. package/hooks/posttooluse-stale-result.ts +277 -0
  233. package/hooks/pretooluse-bash.ts +63 -0
  234. package/hooks/pretooluse-budget-guard.ts +318 -0
  235. package/hooks/pretooluse-common.ts +985 -0
  236. package/hooks/pretooluse-eco-router.ts +196 -0
  237. package/hooks/pretooluse-edit.sh +93 -0
  238. package/hooks/pretooluse-edit.ts +197 -0
  239. package/hooks/pretooluse-glob.ts +70 -0
  240. package/hooks/pretooluse-grep.sh +85 -0
  241. package/hooks/pretooluse-grep.ts +96 -0
  242. package/hooks/pretooluse-notebookedit.ts +121 -0
  243. package/hooks/pretooluse-read.sh +118 -0
  244. package/hooks/pretooluse-read.ts +118 -0
  245. package/hooks/pretooluse-task.ts +130 -0
  246. package/hooks/pretooluse-webfetch.ts +66 -0
  247. package/hooks/pretooluse-websearch.ts +85 -0
  248. package/hooks/pretooluse-write.ts +128 -0
  249. package/hooks/pulse-emit.ts +197 -0
  250. package/hooks/session-end-consolidate.sh +35 -0
  251. package/hooks/session-end-consolidate.ts +188 -0
  252. package/hooks/session-end-stats-gc.ts +80 -0
  253. package/hooks/session-log-append.sh +94 -0
  254. package/hooks/session-log-append.ts +116 -0
  255. package/hooks/session-start.ts +993 -0
  256. package/hooks/sessionend-hook-health-nudge.ts +451 -0
  257. package/hooks/sessionend-savings-nudge.ts +318 -0
  258. package/hooks/sessionend-status-line-nudge.ts +296 -0
  259. package/hooks/sessionstart-brief.ts +140 -0
  260. package/hooks/sessionstart-cost-refactor.ts +95 -0
  261. package/hooks/sessionstart-efficient.ts +110 -0
  262. package/hooks/sessionstart-genome-author.ts +93 -0
  263. package/hooks/sessionstart-lean-tools.ts +98 -0
  264. package/hooks/sessionstart-search.ts +97 -0
  265. package/hooks/stop-accounting.ts +152 -0
  266. package/hooks/subagent-stop-rollup.ts +162 -0
  267. package/hooks/userpromptsubmit-brief-trigger.ts +156 -0
  268. package/package.json +56 -0
  269. package/ports/README.md +108 -0
  270. package/ports/cursor/mcp.json +11 -0
  271. package/ports/goose/recipe.yaml +26 -0
  272. package/scripts/ashlr-mcp.ts +40 -0
  273. package/scripts/auto-update.ts +177 -0
  274. package/scripts/baseline-scan.ts +831 -0
  275. package/scripts/bench-orchestrate.ts +377 -0
  276. package/scripts/benchmark-refs.ts +292 -0
  277. package/scripts/bootstrap.mjs +100 -0
  278. package/scripts/brief-eval.ts +234 -0
  279. package/scripts/bump-version.ts +82 -0
  280. package/scripts/bun-resolve.d.mts +11 -0
  281. package/scripts/bun-resolve.mjs +59 -0
  282. package/scripts/calibrate-grep.ts +467 -0
  283. package/scripts/capture-grep-workload.ts +260 -0
  284. package/scripts/check-tier.ts +61 -0
  285. package/scripts/check-version-sync.ts +97 -0
  286. package/scripts/cli-orchestrate-status.ts +386 -0
  287. package/scripts/cli-orchestrate.ts +303 -0
  288. package/scripts/cli.ts +478 -0
  289. package/scripts/cloud-smoke-test.ts +313 -0
  290. package/scripts/coach-report.ts +373 -0
  291. package/scripts/context-db-migrate.ts +137 -0
  292. package/scripts/context-status.ts +43 -0
  293. package/scripts/demo-run.ts +255 -0
  294. package/scripts/deploy-smoke.sh +140 -0
  295. package/scripts/doctor.ts +992 -0
  296. package/scripts/embed-file-worker.ts +104 -0
  297. package/scripts/embed-tune.ts +308 -0
  298. package/scripts/errors-report.ts +428 -0
  299. package/scripts/find-test-leak.ts +69 -0
  300. package/scripts/generate-badge.ts +357 -0
  301. package/scripts/genome-auto-consolidate.ts +533 -0
  302. package/scripts/genome-auto-propose.ts +578 -0
  303. package/scripts/genome-cloud-pull.ts +363 -0
  304. package/scripts/genome-cloud-push.ts +382 -0
  305. package/scripts/genome-cloud-sync.ts +587 -0
  306. package/scripts/genome-commit-watcher.ts +295 -0
  307. package/scripts/genome-init.ts +986 -0
  308. package/scripts/genome-key.ts +233 -0
  309. package/scripts/genome-keygen.ts +168 -0
  310. package/scripts/genome-link.ts +59 -0
  311. package/scripts/genome-refresh-worker.ts +364 -0
  312. package/scripts/genome-rewrap.ts +90 -0
  313. package/scripts/genome-synthesizer.ts +679 -0
  314. package/scripts/genome-team-init.ts +312 -0
  315. package/scripts/handoff-pack.ts +438 -0
  316. package/scripts/hook-bootstrap.mjs +75 -0
  317. package/scripts/hook-timing-reader.ts +371 -0
  318. package/scripts/hook-timings-report.ts +554 -0
  319. package/scripts/install-genome-hooks.ts +196 -0
  320. package/scripts/install-onnx-model.ts +154 -0
  321. package/scripts/install-permissions.ts +276 -0
  322. package/scripts/install-status-line.ts +150 -0
  323. package/scripts/mcp-entrypoint.sh +78 -0
  324. package/scripts/mcp-entrypoint.ts +130 -0
  325. package/scripts/mdx-angle-bracket-lint.ts +152 -0
  326. package/scripts/measure-cold-start.ts +126 -0
  327. package/scripts/migrate-stats-to-sqlite.ts +86 -0
  328. package/scripts/ollama-setup.ts +498 -0
  329. package/scripts/onboarding-wizard.ts +1691 -0
  330. package/scripts/orchestrate-emit-telemetry.ts +177 -0
  331. package/scripts/orchestrate-expand.ts +517 -0
  332. package/scripts/orchestrate-run.ts +744 -0
  333. package/scripts/print-legend.ts +50 -0
  334. package/scripts/product-metadata.ts +38 -0
  335. package/scripts/prune-old-memories.ts +208 -0
  336. package/scripts/publish.sh +88 -0
  337. package/scripts/read-calibration.ts +122 -0
  338. package/scripts/report-crash.ts +226 -0
  339. package/scripts/run-benchmark.ts +750 -0
  340. package/scripts/run-root-tests.ts +28 -0
  341. package/scripts/savings-dashboard.ts +1258 -0
  342. package/scripts/savings-report-extras.ts +447 -0
  343. package/scripts/savings-status-line.ts +873 -0
  344. package/scripts/session-event-emit.ts +266 -0
  345. package/scripts/session-greet.ts +686 -0
  346. package/scripts/session-log-report.ts +551 -0
  347. package/scripts/session-resume.ts +614 -0
  348. package/scripts/set-hook-mode.ts +83 -0
  349. package/scripts/smoke-cross-platform.ts +117 -0
  350. package/scripts/smoke-realtime.ts +257 -0
  351. package/scripts/smoke-tools.ts +21 -0
  352. package/scripts/stats-cloud-pull.ts +213 -0
  353. package/scripts/stats-cloud-sync.ts +261 -0
  354. package/scripts/telemetry-flush.ts +160 -0
  355. package/scripts/telemetry-status.ts +266 -0
  356. package/scripts/timing-budget.ts +35 -0
  357. package/scripts/ui-animation.ts +120 -0
  358. package/scripts/ui.ts +431 -0
  359. package/scripts/upgrade-flow.ts +775 -0
  360. package/scripts/weekly-digest.ts +394 -0
  361. package/servers/_accounting.ts +78 -0
  362. package/servers/_ask-router.ts +84 -0
  363. package/servers/_ast-chunker.ts +434 -0
  364. package/servers/_ast-helpers.ts +183 -0
  365. package/servers/_ast-languages.ts +153 -0
  366. package/servers/_ast-refactor/_shared.ts +221 -0
  367. package/servers/_ast-refactor/cross-file-rename.ts +560 -0
  368. package/servers/_ast-refactor/extract-function.ts +357 -0
  369. package/servers/_ast-refactor/file-local-rename.ts +172 -0
  370. package/servers/_ast-refactor.ts +41 -0
  371. package/servers/_ast-skeleton.ts +107 -0
  372. package/servers/_bash-summarizers-registry.ts +1096 -0
  373. package/servers/_crash-dump.ts +210 -0
  374. package/servers/_cwd-clamp.ts +342 -0
  375. package/servers/_edit-log.ts +28 -0
  376. package/servers/_edit-match.ts +236 -0
  377. package/servers/_edit-validate.ts +196 -0
  378. package/servers/_embed-calibration.ts +123 -0
  379. package/servers/_embedding-cache.ts +401 -0
  380. package/servers/_embedding-model.ts +329 -0
  381. package/servers/_events.ts +113 -0
  382. package/servers/_genome-cache.ts +154 -0
  383. package/servers/_genome-commits.ts +172 -0
  384. package/servers/_genome-crypto-v2.ts +242 -0
  385. package/servers/_genome-crypto.ts +259 -0
  386. package/servers/_genome-discoveries.ts +140 -0
  387. package/servers/_genome-embed-populator.ts +216 -0
  388. package/servers/_genome-freshness.ts +134 -0
  389. package/servers/_genome-issues.ts +171 -0
  390. package/servers/_genome-live.ts +263 -0
  391. package/servers/_genome-prs.ts +188 -0
  392. package/servers/_genome-search.ts +479 -0
  393. package/servers/_genome-sync.ts +297 -0
  394. package/servers/_history-tracker.ts +279 -0
  395. package/servers/_http-helpers.ts +151 -0
  396. package/servers/_identity-hash.ts +151 -0
  397. package/servers/_llm-providers/anthropic.ts +132 -0
  398. package/servers/_llm-providers/cloud.ts +195 -0
  399. package/servers/_llm-providers/index.ts +350 -0
  400. package/servers/_llm-providers/local.ts +127 -0
  401. package/servers/_llm-providers/onnx.ts +393 -0
  402. package/servers/_llm-providers/types.ts +27 -0
  403. package/servers/_manifest-v2.ts +447 -0
  404. package/servers/_mcp-host.ts +93 -0
  405. package/servers/_nudge-events.ts +451 -0
  406. package/servers/_orchestrate-executor.ts +316 -0
  407. package/servers/_prefetch.ts +435 -0
  408. package/servers/_pricing.ts +256 -0
  409. package/servers/_pro.ts +381 -0
  410. package/servers/_read-cache.ts +44 -0
  411. package/servers/_router-handlers.ts +46 -0
  412. package/servers/_router.ts +55 -0
  413. package/servers/_run-with-timeout.ts +173 -0
  414. package/servers/_savings-render.ts +214 -0
  415. package/servers/_stats-sqlite.ts +640 -0
  416. package/servers/_stats.ts +1183 -0
  417. package/servers/_status-line-cells.ts +469 -0
  418. package/servers/_streaks.ts +162 -0
  419. package/servers/_summarize.ts +208 -0
  420. package/servers/_task-graph-render.ts +217 -0
  421. package/servers/_task-graph.ts +545 -0
  422. package/servers/_telemetry.ts +719 -0
  423. package/servers/_test-parsers.ts +530 -0
  424. package/servers/_test-watch.ts +626 -0
  425. package/servers/_text-helpers.ts +37 -0
  426. package/servers/_token-measure.ts +160 -0
  427. package/servers/_tool-base.ts +248 -0
  428. package/servers/_weekly-digest.ts +391 -0
  429. package/servers/ask-server-handlers.ts +49 -0
  430. package/servers/ask-server.ts +174 -0
  431. package/servers/bash-server-handlers.ts +138 -0
  432. package/servers/bash-server.ts +1136 -0
  433. package/servers/bench.ts +186 -0
  434. package/servers/diff-semantic-server-handlers.ts +39 -0
  435. package/servers/diff-semantic-server.ts +566 -0
  436. package/servers/diff-server-handlers.ts +317 -0
  437. package/servers/diff-server.ts +20 -0
  438. package/servers/edit-server-handlers.ts +31 -0
  439. package/servers/edit-server.ts +209 -0
  440. package/servers/edit-structural-server-handlers.ts +322 -0
  441. package/servers/efficiency-server-handlers.ts +161 -0
  442. package/servers/efficiency-server.ts +1135 -0
  443. package/servers/flush-server-handlers.ts +21 -0
  444. package/servers/flush-server.ts +19 -0
  445. package/servers/genome-server-handlers.ts +118 -0
  446. package/servers/genome-server.ts +397 -0
  447. package/servers/github-server-handlers.ts +187 -0
  448. package/servers/github-server.ts +856 -0
  449. package/servers/glob-server-handlers.ts +233 -0
  450. package/servers/glob-server.ts +20 -0
  451. package/servers/grep-server-handlers.ts +61 -0
  452. package/servers/grep-server.ts +564 -0
  453. package/servers/http-server-handlers.ts +36 -0
  454. package/servers/http-server.ts +149 -0
  455. package/servers/logs-server-handlers.ts +42 -0
  456. package/servers/logs-server.ts +359 -0
  457. package/servers/ls-server-handlers.ts +166 -0
  458. package/servers/ls-server.ts +20 -0
  459. package/servers/multi-edit-server-handlers.ts +51 -0
  460. package/servers/multi-edit-server.ts +422 -0
  461. package/servers/notebook-edit-server-handlers.ts +34 -0
  462. package/servers/notebook-edit-server.ts +181 -0
  463. package/servers/orient-server-handlers.ts +52 -0
  464. package/servers/orient-server.ts +436 -0
  465. package/servers/pipe-server-handlers.ts +68 -0
  466. package/servers/pipe-server.ts +300 -0
  467. package/servers/read-server-handlers.ts +42 -0
  468. package/servers/read-server.ts +206 -0
  469. package/servers/rename-file-server-handlers.ts +67 -0
  470. package/servers/rename-file-server.ts +699 -0
  471. package/servers/savings-server-handlers.ts +27 -0
  472. package/servers/savings-server.ts +54 -0
  473. package/servers/search-replace-regex-server-handlers.ts +96 -0
  474. package/servers/search-replace-regex-server.ts +751 -0
  475. package/servers/sql-server-handlers.ts +58 -0
  476. package/servers/sql-server.ts +505 -0
  477. package/servers/task-server-handlers.ts +358 -0
  478. package/servers/task-server.ts +24 -0
  479. package/servers/test-server-handlers.ts +351 -0
  480. package/servers/test-server.ts +20 -0
  481. package/servers/tree-server-handlers.ts +503 -0
  482. package/servers/tree-server.ts +20 -0
  483. package/servers/webfetch-server-handlers.ts +166 -0
  484. package/servers/webfetch-server.ts +20 -0
  485. package/servers/websearch-server-handlers.ts +215 -0
  486. package/servers/websearch-server.ts +19 -0
  487. package/servers/write-server-handlers.ts +27 -0
  488. package/servers/write-server.ts +97 -0
  489. package/skills/ashlr-brief/SKILL.md +80 -0
  490. package/skills/ashlr-codex-doctor/SKILL.md +21 -0
  491. package/skills/ashlr-codex-efficient-tools/SKILL.md +17 -0
  492. package/skills/ashlr-codex-genome-refresh/SKILL.md +20 -0
  493. package/skills/ashlr-codex-parallel-explore/SKILL.md +20 -0
  494. package/skills/ashlr-codex-savings/SKILL.md +17 -0
  495. package/skills/ashlr-cost-refactor/SKILL.md +50 -0
  496. package/skills/ashlr-efficient/SKILL.md +64 -0
  497. package/skills/ashlr-genome-author/SKILL.md +43 -0
  498. package/skills/ashlr-lean-tools/SKILL.md +43 -0
  499. package/skills/ashlr-search/SKILL.md +46 -0
@@ -0,0 +1,479 @@
1
+ /**
2
+ * _genome-search.ts — Inverted-index layer over .ashlrcode/genome/knowledge/*.md
3
+ *
4
+ * Builds a token → sections map from the genome knowledge corpus. The index
5
+ * is cached to ~/.ashlr/genome-index-<repoSha>.cache (JSON) and invalidated
6
+ * when the genome dir's mtime, file count, or sample filenames change.
7
+ *
8
+ * Design constraints:
9
+ * - Pure mechanical — zero LLM calls.
10
+ * - Build cost < 50ms for the 248KB corpus.
11
+ * - Thread-safe via a simple per-repoRoot in-process singleton.
12
+ * - Never throws — callers should degrade gracefully on index failure.
13
+ */
14
+
15
+ import { createHash } from "crypto";
16
+ import {
17
+ existsSync,
18
+ mkdirSync,
19
+ readFileSync,
20
+ statSync,
21
+ writeFileSync,
22
+ } from "fs";
23
+ import { readdirSync } from "fs";
24
+ import { homedir } from "os";
25
+ import { dirname, join } from "path";
26
+
27
+ // ---------------------------------------------------------------------------
28
+ // Public types
29
+ // ---------------------------------------------------------------------------
30
+
31
+ export interface GenomeSearchResult {
32
+ /** The section header (e.g. "## Architecture decisions") */
33
+ section: string;
34
+ /** Absolute path to the .md file */
35
+ file: string;
36
+ /** 1-based line number of the section header */
37
+ line: number;
38
+ /** First non-empty content line(s) of the section (up to 200 chars) */
39
+ snippet: string;
40
+ }
41
+
42
+ export interface GenomeSearchIndex {
43
+ lookup(pattern: string | RegExp): GenomeSearchResult[];
44
+ isComplete(): boolean;
45
+ invalidate(): void;
46
+ }
47
+
48
+ // ---------------------------------------------------------------------------
49
+ // Internal types
50
+ // ---------------------------------------------------------------------------
51
+
52
+ interface IndexEntry {
53
+ token: string;
54
+ results: GenomeSearchResult[];
55
+ }
56
+
57
+ interface CacheShape {
58
+ /** Fingerprint of the genome dir state when this cache was built. */
59
+ fingerprint: string;
60
+ /** Map of lowercased token → results. Stored as entries array for JSON. */
61
+ entries: IndexEntry[];
62
+ builtAt: number;
63
+ }
64
+
65
+ interface InMemoryIndex {
66
+ fingerprint: string;
67
+ map: Map<string, GenomeSearchResult[]>;
68
+ complete: boolean;
69
+ }
70
+
71
+ // ---------------------------------------------------------------------------
72
+ // Constants
73
+ // ---------------------------------------------------------------------------
74
+
75
+ const CACHE_DIR = join(process.env.HOME ?? homedir(), ".ashlr");
76
+ const MIN_TOKEN_LEN = 3;
77
+ const MAX_SNIPPET_LEN = 200;
78
+
79
+ // ---------------------------------------------------------------------------
80
+ // Fingerprinting
81
+ // ---------------------------------------------------------------------------
82
+
83
+ /**
84
+ * Compute a cheap fingerprint of the genome knowledge dir:
85
+ * SHA-256 of (total mtime of all md files + file count + sorted filenames sample)
86
+ */
87
+ function fingerprintGenomeDir(knowledgeDir: string): string {
88
+ try {
89
+ if (!existsSync(knowledgeDir)) return "empty";
90
+ const files = listMdFiles(knowledgeDir);
91
+ if (files.length === 0) return "empty";
92
+ let mtimeSum = 0;
93
+ for (const f of files) {
94
+ try {
95
+ mtimeSum += statSync(f).mtimeMs;
96
+ } catch {
97
+ // ignore
98
+ }
99
+ }
100
+ const sampleNames = files
101
+ .slice(0, 10)
102
+ .map((f) => f.split("/").pop() ?? "")
103
+ .sort()
104
+ .join("|");
105
+ const raw = `${mtimeSum}:${files.length}:${sampleNames}`;
106
+ return createHash("sha256").update(raw).digest("hex").slice(0, 16);
107
+ } catch {
108
+ return "error";
109
+ }
110
+ }
111
+
112
+ function listMdFiles(dir: string): string[] {
113
+ const results: string[] = [];
114
+ try {
115
+ const entries = readdirSync(dir, { withFileTypes: true });
116
+ for (const e of entries) {
117
+ const full = join(dir, e.name);
118
+ if (e.isDirectory()) {
119
+ results.push(...listMdFiles(full));
120
+ } else if (e.isFile() && e.name.endsWith(".md")) {
121
+ results.push(full);
122
+ }
123
+ }
124
+ } catch {
125
+ // ignore unreadable dirs
126
+ }
127
+ return results.sort();
128
+ }
129
+
130
+ // ---------------------------------------------------------------------------
131
+ // Cache path (per-repo, keyed by SHA of repo root path)
132
+ // ---------------------------------------------------------------------------
133
+
134
+ function cachePathFor(repoRoot: string): string {
135
+ const repoSha = createHash("sha256").update(repoRoot).digest("hex").slice(0, 12);
136
+ return join(CACHE_DIR, `genome-index-${repoSha}.cache`);
137
+ }
138
+
139
+ // ---------------------------------------------------------------------------
140
+ // Index building
141
+ // ---------------------------------------------------------------------------
142
+
143
+ /**
144
+ * Parse a single .md file into sections. Each section starts at a `##` header
145
+ * (we skip `#` top-level titles). Returns array of parsed sections.
146
+ */
147
+ function parseMdSections(
148
+ filePath: string,
149
+ ): Array<{ header: string; line: number; body: string }> {
150
+ let raw: string;
151
+ try {
152
+ raw = readFileSync(filePath, "utf-8");
153
+ } catch {
154
+ return [];
155
+ }
156
+ const lines = raw.split("\n");
157
+ const sections: Array<{ header: string; line: number; body: string }> = [];
158
+ let current: { header: string; line: number; bodyLines: string[] } | null = null;
159
+
160
+ for (let i = 0; i < lines.length; i++) {
161
+ const line = lines[i]!;
162
+ // Match ## or deeper headers
163
+ if (/^#{2,}\s+/.test(line)) {
164
+ if (current) {
165
+ sections.push({
166
+ header: current.header,
167
+ line: current.line,
168
+ body: current.bodyLines.join("\n"),
169
+ });
170
+ }
171
+ current = { header: line.replace(/^#+\s+/, "").trim(), line: i + 1, bodyLines: [] };
172
+ } else if (current) {
173
+ current.bodyLines.push(line);
174
+ }
175
+ }
176
+ if (current) {
177
+ sections.push({
178
+ header: current.header,
179
+ line: current.line,
180
+ body: current.bodyLines.join("\n"),
181
+ });
182
+ }
183
+ return sections;
184
+ }
185
+
186
+ /**
187
+ * Tokenize a string into lowercase alpha-numeric tokens of length >= MIN_TOKEN_LEN.
188
+ */
189
+ function tokenize(text: string): string[] {
190
+ return text
191
+ .toLowerCase()
192
+ .split(/[^a-z0-9_\-]+/)
193
+ .filter((t) => t.length >= MIN_TOKEN_LEN);
194
+ }
195
+
196
+ function extractSnippet(body: string): string {
197
+ const firstMeaningfulLine = body
198
+ .split("\n")
199
+ .map((l) => l.trim())
200
+ .find((l) => l.length > 0 && !l.startsWith("#") && !l.startsWith("```"));
201
+ if (!firstMeaningfulLine) return "";
202
+ return firstMeaningfulLine.slice(0, MAX_SNIPPET_LEN);
203
+ }
204
+
205
+ /**
206
+ * Build the full inverted index from the knowledge dir.
207
+ * Returns a Map<token, GenomeSearchResult[]>.
208
+ */
209
+ function buildIndex(knowledgeDir: string): Map<string, GenomeSearchResult[]> {
210
+ const map = new Map<string, GenomeSearchResult[]>();
211
+ const files = listMdFiles(knowledgeDir);
212
+
213
+ for (const file of files) {
214
+ const sections = parseMdSections(file);
215
+ for (const sec of sections) {
216
+ const result: GenomeSearchResult = {
217
+ section: sec.header,
218
+ file,
219
+ line: sec.line,
220
+ snippet: extractSnippet(sec.body),
221
+ };
222
+ // Index tokens from both header and body
223
+ const tokens = new Set([
224
+ ...tokenize(sec.header),
225
+ ...tokenize(sec.body),
226
+ ]);
227
+ for (const token of tokens) {
228
+ const existing = map.get(token);
229
+ if (existing) {
230
+ existing.push(result);
231
+ } else {
232
+ map.set(token, [result]);
233
+ }
234
+ }
235
+ }
236
+ }
237
+ return map;
238
+ }
239
+
240
+ // ---------------------------------------------------------------------------
241
+ // Cache persistence
242
+ // ---------------------------------------------------------------------------
243
+
244
+ function loadCache(cachePath: string): CacheShape | null {
245
+ try {
246
+ if (!existsSync(cachePath)) return null;
247
+ const raw = readFileSync(cachePath, "utf-8");
248
+ return JSON.parse(raw) as CacheShape;
249
+ } catch {
250
+ return null;
251
+ }
252
+ }
253
+
254
+ function saveCache(cachePath: string, fingerprint: string, map: Map<string, GenomeSearchResult[]>): void {
255
+ try {
256
+ mkdirSync(dirname(cachePath), { recursive: true });
257
+ const entries: IndexEntry[] = [];
258
+ for (const [token, results] of map.entries()) {
259
+ entries.push({ token, results });
260
+ }
261
+ const shape: CacheShape = {
262
+ fingerprint,
263
+ entries,
264
+ builtAt: Date.now(),
265
+ };
266
+ writeFileSync(cachePath, JSON.stringify(shape), "utf-8");
267
+ } catch {
268
+ // Cache write failure is non-fatal — index is still usable in memory.
269
+ }
270
+ }
271
+
272
+ function cacheToMap(cache: CacheShape): Map<string, GenomeSearchResult[]> {
273
+ const map = new Map<string, GenomeSearchResult[]>();
274
+ for (const entry of cache.entries) {
275
+ map.set(entry.token, entry.results);
276
+ }
277
+ return map;
278
+ }
279
+
280
+ // ---------------------------------------------------------------------------
281
+ // Per-repoRoot singleton registry
282
+ // ---------------------------------------------------------------------------
283
+
284
+ const _indexRegistry = new Map<string, InMemoryIndex>();
285
+
286
+ function getOrBuildIndex(repoRoot: string): InMemoryIndex {
287
+ const knowledgeDir = join(repoRoot, ".ashlrcode", "genome", "knowledge");
288
+ const fingerprint = fingerprintGenomeDir(knowledgeDir);
289
+ const cachePath = cachePathFor(repoRoot);
290
+
291
+ const existing = _indexRegistry.get(repoRoot);
292
+ if (existing && existing.fingerprint === fingerprint && existing.complete) {
293
+ return existing;
294
+ }
295
+
296
+ // Try loading from disk cache.
297
+ const cached = loadCache(cachePath);
298
+ if (cached && cached.fingerprint === fingerprint) {
299
+ const map = cacheToMap(cached);
300
+ const idx: InMemoryIndex = { fingerprint, map, complete: true };
301
+ _indexRegistry.set(repoRoot, idx);
302
+ return idx;
303
+ }
304
+
305
+ // Cache miss or stale — rebuild.
306
+ const map = buildIndex(knowledgeDir);
307
+ saveCache(cachePath, fingerprint, map);
308
+ const idx: InMemoryIndex = { fingerprint, map, complete: true };
309
+ _indexRegistry.set(repoRoot, idx);
310
+ return idx;
311
+ }
312
+
313
+ // ---------------------------------------------------------------------------
314
+ // Public API
315
+ // ---------------------------------------------------------------------------
316
+
317
+ /**
318
+ * Deduplicate results by (file, line) to avoid returning the same section
319
+ * multiple times when multiple tokens from a pattern match it.
320
+ */
321
+ function dedupeResults(results: GenomeSearchResult[]): GenomeSearchResult[] {
322
+ const seen = new Set<string>();
323
+ return results.filter((r) => {
324
+ const key = `${r.file}:${r.line}`;
325
+ if (seen.has(key)) return false;
326
+ seen.add(key);
327
+ return true;
328
+ });
329
+ }
330
+
331
+ /**
332
+ * v1.34: TF-IDF re-ranking using the inverted index's own token frequencies.
333
+ * IDF = log((N+1)/(df+1)) + 1 (BM25-style smoothed, N = total distinct tokens).
334
+ * Additive: empty/cold corpus (map.size===0) → all scores 0 → original order preserved.
335
+ * Also expands camelCase/snake_case query tokens for better single-token coverage.
336
+ */
337
+ function tfidfRerank(
338
+ results: GenomeSearchResult[],
339
+ queryTokens: string[],
340
+ indexMap: Map<string, GenomeSearchResult[]>,
341
+ ): GenomeSearchResult[] {
342
+ if (results.length <= 1 || queryTokens.length === 0 || indexMap.size === 0) return results;
343
+
344
+ // Expand: camelCase + snake_case → sub-tokens
345
+ const expandedTokens = new Set<string>();
346
+ for (const t of queryTokens) {
347
+ expandedTokens.add(t);
348
+ for (const p of t.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().split(/\s+/))
349
+ if (p.length >= 3) expandedTokens.add(p);
350
+ for (const p of t.split("_")) if (p.length >= 3) expandedTokens.add(p.toLowerCase());
351
+ }
352
+
353
+ const N = indexMap.size; // total distinct tokens as doc-count proxy
354
+ const scores = new Map<string, number>();
355
+ for (const token of expandedTokens) {
356
+ const postings = indexMap.get(token);
357
+ if (!postings || postings.length === 0) continue;
358
+ const idf = Math.log((N + 1) / (postings.length + 1)) + 1;
359
+ const postingKeys = new Set(postings.map((r) => `${r.file}:${r.line}`));
360
+ for (const r of results) {
361
+ const key = `${r.file}:${r.line}`;
362
+ if (postingKeys.has(key)) scores.set(key, (scores.get(key) ?? 0) + idf);
363
+ }
364
+ }
365
+
366
+ return results.slice().sort((a, b) => {
367
+ const sa = scores.get(`${a.file}:${a.line}`) ?? 0;
368
+ const sb = scores.get(`${b.file}:${b.line}`) ?? 0;
369
+ return sb - sa; // ties preserve original (stable sort)
370
+ });
371
+ }
372
+
373
+ export function getGenomeSearchIndex(repoRoot: string): GenomeSearchIndex {
374
+ return {
375
+ lookup(pattern: string | RegExp): GenomeSearchResult[] {
376
+ try {
377
+ const idx = getOrBuildIndex(repoRoot);
378
+ const results: GenomeSearchResult[] = [];
379
+
380
+ if (pattern instanceof RegExp) {
381
+ // For RegExp: scan all tokens whose key matches the pattern, or
382
+ // do a full scan of all results for content matching.
383
+ for (const [token, entries] of idx.map.entries()) {
384
+ if (pattern.test(token)) {
385
+ results.push(...entries);
386
+ }
387
+ }
388
+ // Also filter by testing snippet + section against the regex
389
+ const byContent: GenomeSearchResult[] = [];
390
+ const seen = new Set<string>();
391
+ for (const [, entries] of idx.map.entries()) {
392
+ for (const entry of entries) {
393
+ const key = `${entry.file}:${entry.line}`;
394
+ if (seen.has(key)) continue;
395
+ if (pattern.test(entry.section) || pattern.test(entry.snippet)) {
396
+ seen.add(key);
397
+ byContent.push(entry);
398
+ }
399
+ }
400
+ }
401
+ results.push(...byContent);
402
+ } else {
403
+ // String pattern: tokenize it, then intersect (AND semantics for
404
+ // multi-token patterns; OR fallback for single token).
405
+ const tokens = tokenize(pattern);
406
+ if (tokens.length === 0) return [];
407
+
408
+ if (tokens.length === 1) {
409
+ const token = tokens[0]!;
410
+ // Exact match first, then prefix match.
411
+ const exact = idx.map.get(token) ?? [];
412
+ results.push(...exact);
413
+ // Also search for the raw pattern as substring in section/snippet
414
+ const lower = pattern.toLowerCase();
415
+ for (const [, entries] of idx.map.entries()) {
416
+ for (const entry of entries) {
417
+ if (
418
+ entry.section.toLowerCase().includes(lower) ||
419
+ entry.snippet.toLowerCase().includes(lower)
420
+ ) {
421
+ results.push(entry);
422
+ }
423
+ }
424
+ }
425
+ } else {
426
+ // Multi-token: find results that appear in ALL token sets (AND).
427
+ const sets = tokens.map((t) => new Set((idx.map.get(t) ?? []).map((r) => `${r.file}:${r.line}`)));
428
+ const intersection = sets.reduce((a, b) => new Set([...a].filter((x) => b.has(x))));
429
+ for (const key of intersection) {
430
+ // Retrieve one result for this key from any set.
431
+ const entry = (idx.map.get(tokens[0]!) ?? []).find((r) => `${r.file}:${r.line}` === key);
432
+ if (entry) results.push(entry);
433
+ }
434
+ }
435
+ }
436
+
437
+ const deduped = dedupeResults(results);
438
+ // v1.34: TF-IDF re-rank for string queries (RegExp keeps document order).
439
+ if (typeof pattern === "string") {
440
+ const qTokens = tokenize(pattern);
441
+ return tfidfRerank(deduped, qTokens, idx.map);
442
+ }
443
+ return deduped;
444
+ } catch {
445
+ return [];
446
+ }
447
+ },
448
+
449
+ isComplete(): boolean {
450
+ const existing = _indexRegistry.get(repoRoot);
451
+ return existing?.complete ?? false;
452
+ },
453
+
454
+ invalidate(): void {
455
+ _indexRegistry.delete(repoRoot);
456
+ // Also remove disk cache.
457
+ try {
458
+ const cachePath = cachePathFor(repoRoot);
459
+ if (existsSync(cachePath)) {
460
+ require("fs").unlinkSync(cachePath);
461
+ }
462
+ } catch {
463
+ // best-effort
464
+ }
465
+ },
466
+ };
467
+ }
468
+
469
+ // ---------------------------------------------------------------------------
470
+ // Warm-start helper — called once on server startup (fire-and-forget)
471
+ // ---------------------------------------------------------------------------
472
+
473
+ export function warmGenomeIndex(repoRoot: string): void {
474
+ try {
475
+ getOrBuildIndex(repoRoot);
476
+ } catch {
477
+ // warmup must never throw
478
+ }
479
+ }