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,50 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * print-legend.ts
4
+ *
5
+ * Emits a plain-text ASCII legend for every element in the ashlr status line.
6
+ * Invoked by the /ashlr-legend skill. No I/O dependencies beyond stdout.
7
+ *
8
+ * Output is designed for a monospace terminal, <=60 visible chars per line
9
+ * for the structured rows (the description wraps with a hanging indent).
10
+ * Box-drawing characters (U+256x) are used for the header/footer frame;
11
+ * they render as plain hyphens in terminals that strip Unicode.
12
+ */
13
+
14
+ const LEGEND = `\u256d\u2500\u2500\u2500\u2500 ashlr status-line legend \u2500\u2500\u2500\u2500\u256e
15
+
16
+ ashlr \u00b7 brand label + activity dot.
17
+ Dim when idle; pulses during a saving event.
18
+
19
+ \u00b7 \u2014 separator glyph between segments (middle dot).
20
+
21
+ \u2840\u2844\u2847\u28FF \u2014 heartbeat glyph between "ashlr" and the sparkline.
22
+ Braille wave when active (last 4s); dim dot
23
+ when idle.
24
+
25
+ 7d \u2581\u2582\u2583\u2585\u2587\u2588\u2587 \u2014 7-day sparkline. Each cell = one day of savings,
26
+ tallest cell = busiest day (scaled to full
27
+ block). "7d" label shown when terminal >100
28
+ cols; dropped on narrow windows.
29
+
30
+ ctx:NN% \u2014 context-window pressure (how full your Claude
31
+ Code context is). Color tiers:
32
+ green 0-60% \u2022 yellow 60-80%
33
+ orange 80-95% \u2022 red+bold 95%+
34
+
35
+ session +N \u2014 tokens saved in THIS terminal since the
36
+ session started.
37
+
38
+ lifetime +M \u2014 tokens saved across every session, ever.
39
+
40
+ tip:\u2026 \u2014 rotating daily hint (one tip per day, cycles
41
+ through the built-in tip list). Toggle off:
42
+ /ashlr-settings set statusLineTips false
43
+
44
+ \u2570\u2500 run /ashlr-savings for totals \u00b7 /ashlr-tour to see it in action \u2500\u256f`;
45
+
46
+ if (import.meta.main) {
47
+ process.stdout.write(LEGEND + "\n");
48
+ }
49
+
50
+ export { LEGEND };
@@ -0,0 +1,38 @@
1
+ import { readdir } from "fs/promises";
2
+ import { dirname, join, resolve } from "path";
3
+ import { fileURLToPath } from "url";
4
+
5
+ import { listTools } from "../servers/_tool-base";
6
+ import "../servers/_router-handlers";
7
+
8
+ export interface PublicProductCounts {
9
+ mcpTools: number;
10
+ slashCommands: number;
11
+ }
12
+
13
+ export const PUBLIC_PRODUCT_COUNTS = {
14
+ mcpTools: 40,
15
+ slashCommands: 34,
16
+ } as const satisfies PublicProductCounts;
17
+
18
+ export const PUBLIC_PRODUCT_TELEMETRY = "off by default; explicit opt-in only";
19
+
20
+ export function repoRoot(): string {
21
+ return resolve(dirname(fileURLToPath(import.meta.url)), "..");
22
+ }
23
+
24
+ export function registeredMcpToolCount(): number {
25
+ return new Set(listTools().map((tool) => tool.name)).size;
26
+ }
27
+
28
+ export async function slashCommandCount(root = repoRoot()): Promise<number> {
29
+ const entries = await readdir(join(root, "commands"));
30
+ return entries.filter((name) => /^ashlr-.+\.md$/.test(name)).length;
31
+ }
32
+
33
+ export async function publicProductCounts(root = repoRoot()): Promise<PublicProductCounts> {
34
+ return {
35
+ mcpTools: registeredMcpToolCount(),
36
+ slashCommands: await slashCommandCount(root),
37
+ };
38
+ }
@@ -0,0 +1,208 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * prune-old-memories.ts — surface auto-memory entries (under
4
+ * `<claude-projects-dir>/memory/`) that are stale candidates for deletion.
5
+ *
6
+ * Read-only by default — prints a candidate report and exits 0. Pass
7
+ * `--apply` to actually delete the flagged files.
8
+ *
9
+ * Heuristics for "candidate":
10
+ * 1. File has not been modified in > N days (default: 30; --days=N to override)
11
+ * 2. There is a NEWER entry whose name starts with the same project_v<major>
12
+ * prefix (e.g. project_v1.13_*.md is superseded by project_v1.14_*.md)
13
+ * 3. Or the entry's title contains an explicit "(superseded ...)" marker
14
+ *
15
+ * Usage:
16
+ * bun run scripts/prune-old-memories.ts # report only
17
+ * bun run scripts/prune-old-memories.ts --days=60 # 60-day cutoff
18
+ * bun run scripts/prune-old-memories.ts --dir=/path/to/memory # explicit dir
19
+ * bun run scripts/prune-old-memories.ts --apply # actually delete
20
+ *
21
+ * Files removed are also removed from MEMORY.md if a single-line link to them
22
+ * is found (`- [.*](filename.md) — ...`).
23
+ *
24
+ * This is a hygiene tool — never run automatically. Operator-driven.
25
+ */
26
+
27
+ import { existsSync, readFileSync, readdirSync, statSync, unlinkSync, writeFileSync } from "fs";
28
+ import { homedir } from "os";
29
+ import { basename, dirname, join } from "path";
30
+
31
+ interface PruneCandidate {
32
+ path: string;
33
+ name: string;
34
+ ageDays: number;
35
+ reason: string;
36
+ }
37
+
38
+ function parseArgs(argv: string[]): { dir?: string; days: number; apply: boolean } {
39
+ const out = { days: 30, apply: false } as { dir?: string; days: number; apply: boolean };
40
+ for (const a of argv) {
41
+ if (a === "--apply") out.apply = true;
42
+ else if (a.startsWith("--days=")) out.days = parseInt(a.slice("--days=".length), 10) || 30;
43
+ else if (a.startsWith("--dir=")) out.dir = a.slice("--dir=".length);
44
+ }
45
+ return out;
46
+ }
47
+
48
+ /** Find the default Claude Code project memory directory for this CWD. */
49
+ function defaultMemoryDir(): string | null {
50
+ const home = process.env.HOME ?? homedir();
51
+ const cwd = process.cwd();
52
+ // Convention: <home>/.claude/projects/<encoded-cwd>/memory/
53
+ // The encoding replaces / with -, e.g. /Users/masonwyatt/foo → -Users-masonwyatt-foo
54
+ const encoded = "-" + cwd.replace(/^\//, "").replace(/\//g, "-");
55
+ const dir = join(home, ".claude", "projects", encoded, "memory");
56
+ if (existsSync(dir)) return dir;
57
+ return null;
58
+ }
59
+
60
+ function listMemoryFiles(dir: string): string[] {
61
+ return readdirSync(dir).filter((f) => f.endsWith(".md") && f !== "MEMORY.md");
62
+ }
63
+
64
+ /** Extract the version-major prefix from a project memory filename. e.g. "project_v123_..." → "v123" */
65
+ function versionPrefix(name: string): string | null {
66
+ const m = name.match(/^project_v(\d+(?:[a-z\d_]*)?)/i);
67
+ return m ? `v${m[1]!.split("_")[0]!}` : null;
68
+ }
69
+
70
+ /** Compare two project memory entries by version prefix (semver-ish). */
71
+ function compareVersions(a: string, b: string): number {
72
+ // Strip non-digit suffix and compare numerically
73
+ const an = parseInt(a.replace(/[^\d]/g, ""), 10);
74
+ const bn = parseInt(b.replace(/[^\d]/g, ""), 10);
75
+ return an - bn;
76
+ }
77
+
78
+ function findCandidates(dir: string, days: number): PruneCandidate[] {
79
+ const files = listMemoryFiles(dir);
80
+ const now = Date.now();
81
+ const cutoff = now - days * 24 * 60 * 60 * 1000;
82
+
83
+ // Group by major-version prefix
84
+ const byPrefix = new Map<string, Array<{ file: string; mtime: number }>>();
85
+ for (const file of files) {
86
+ const full = join(dir, file);
87
+ const mtime = statSync(full).mtimeMs;
88
+ const prefix = versionPrefix(file);
89
+ if (!prefix) continue;
90
+ if (!byPrefix.has(prefix)) byPrefix.set(prefix, []);
91
+ byPrefix.get(prefix)!.push({ file, mtime });
92
+ }
93
+
94
+ // For each prefix group, find the newest version. Older same-prefix files are candidates.
95
+ const candidates: PruneCandidate[] = [];
96
+ // Sort prefixes by version number; older versions whose newer-version sibling exists are candidates.
97
+ const prefixes = [...byPrefix.keys()].sort(compareVersions);
98
+ for (let i = 0; i < prefixes.length - 1; i++) {
99
+ const olderPrefix = prefixes[i]!;
100
+ const newerPrefix = prefixes[i + 1]!;
101
+ const olderEntries = byPrefix.get(olderPrefix) ?? [];
102
+ for (const { file, mtime } of olderEntries) {
103
+ if (mtime > cutoff) continue;
104
+ const ageDays = Math.round((now - mtime) / (24 * 60 * 60 * 1000));
105
+ candidates.push({
106
+ path: join(dir, file),
107
+ name: file,
108
+ ageDays,
109
+ reason: `superseded by ${newerPrefix}_*.md (older than ${days}d cutoff)`,
110
+ });
111
+ }
112
+ }
113
+
114
+ // Also flag any file with an explicit "(superseded" marker in its body
115
+ for (const file of files) {
116
+ const full = join(dir, file);
117
+ const mtime = statSync(full).mtimeMs;
118
+ if (mtime > cutoff) continue;
119
+ let content = "";
120
+ try { content = readFileSync(full, "utf-8"); } catch { continue; }
121
+ if (/\(superseded by/i.test(content) && !candidates.some((c) => c.path === full)) {
122
+ const ageDays = Math.round((now - mtime) / (24 * 60 * 60 * 1000));
123
+ candidates.push({
124
+ path: full,
125
+ name: file,
126
+ ageDays,
127
+ reason: `body contains "(superseded by ...)" marker`,
128
+ });
129
+ }
130
+ }
131
+
132
+ return candidates;
133
+ }
134
+
135
+ function pruneFromIndex(memoryDir: string, removedNames: string[]): number {
136
+ const indexPath = join(memoryDir, "MEMORY.md");
137
+ if (!existsSync(indexPath)) return 0;
138
+ const lines = readFileSync(indexPath, "utf-8").split("\n");
139
+ const removedSet = new Set(removedNames);
140
+ const kept: string[] = [];
141
+ let pruned = 0;
142
+ for (const line of lines) {
143
+ const m = line.match(/\(([^)]+\.md)\)/);
144
+ if (m && removedSet.has(basename(m[1]!))) {
145
+ pruned++;
146
+ continue;
147
+ }
148
+ kept.push(line);
149
+ }
150
+ if (pruned > 0) {
151
+ writeFileSync(indexPath, kept.join("\n"));
152
+ }
153
+ return pruned;
154
+ }
155
+
156
+ async function main(): Promise<void> {
157
+ const args = parseArgs(process.argv.slice(2));
158
+ const dir = args.dir ?? defaultMemoryDir();
159
+ if (!dir || !existsSync(dir)) {
160
+ process.stderr.write(
161
+ `prune-old-memories: no memory dir found.\n` +
162
+ `Try: bun run scripts/prune-old-memories.ts --dir=<path>\n` +
163
+ `Default location: ~/.claude/projects/<encoded-cwd>/memory/\n`,
164
+ );
165
+ process.exit(1);
166
+ }
167
+
168
+ const candidates = findCandidates(dir, args.days);
169
+
170
+ if (candidates.length === 0) {
171
+ process.stdout.write(`prune-old-memories: no candidates older than ${args.days} days found in ${dir}\n`);
172
+ return;
173
+ }
174
+
175
+ process.stdout.write(`prune-old-memories: ${candidates.length} candidate(s) older than ${args.days} days in:\n`);
176
+ process.stdout.write(` ${dir}\n\n`);
177
+ for (const c of candidates) {
178
+ process.stdout.write(` • ${c.name} (${c.ageDays}d old)\n`);
179
+ process.stdout.write(` reason: ${c.reason}\n`);
180
+ }
181
+
182
+ if (!args.apply) {
183
+ process.stdout.write(`\nDry run — no files removed. Re-run with --apply to delete + remove from MEMORY.md.\n`);
184
+ return;
185
+ }
186
+
187
+ // Apply mode
188
+ let removed = 0;
189
+ const removedNames: string[] = [];
190
+ for (const c of candidates) {
191
+ try {
192
+ unlinkSync(c.path);
193
+ removed++;
194
+ removedNames.push(c.name);
195
+ } catch (e) {
196
+ process.stderr.write(` ✗ failed to delete ${c.name}: ${(e as Error).message}\n`);
197
+ }
198
+ }
199
+ const indexPruned = pruneFromIndex(dir, removedNames);
200
+ process.stdout.write(`\nremoved ${removed} memory file(s); pruned ${indexPruned} MEMORY.md entry(ies).\n`);
201
+ }
202
+
203
+ if (import.meta.main) {
204
+ void main();
205
+ }
206
+
207
+ // Re-export for testing
208
+ export { findCandidates, defaultMemoryDir, parseArgs, versionPrefix };
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env bash
2
+ # Publish ashlr-plugin to GitHub (public) and enable Pages for the /docs site.
3
+ # Also publishes @ashlr/core-efficiency if the sibling repo exists locally and
4
+ # hasn't been pushed yet. Safe to re-run — each step is a no-op if already done.
5
+ #
6
+ # Requires: gh CLI authed (gh auth status).
7
+ # Usage: ./scripts/publish.sh [--dry-run]
8
+
9
+ set -euo pipefail
10
+
11
+ DRY_RUN=0
12
+ [ "${1:-}" = "--dry-run" ] && DRY_RUN=1
13
+
14
+ cyan() { printf "\033[36m%s\033[0m\n" "$*"; }
15
+ green() { printf "\033[32m%s\033[0m\n" "$*"; }
16
+ yellow() { printf "\033[33m%s\033[0m\n" "$*"; }
17
+ red() { printf "\033[31m%s\033[0m\n" "$*"; }
18
+
19
+ run() {
20
+ cyan "\$ $*"
21
+ if [ "$DRY_RUN" -eq 0 ]; then eval "$@"; fi
22
+ }
23
+
24
+ if ! command -v gh >/dev/null; then
25
+ red "gh CLI not installed. https://cli.github.com"
26
+ exit 1
27
+ fi
28
+
29
+ gh auth status >/dev/null 2>&1 || { red "gh not authed. Run: gh auth login"; exit 1; }
30
+ USER=$(gh api user --jq .login)
31
+ green "Authed as: $USER"
32
+ echo
33
+
34
+ STACK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
35
+ CORE_DIR="$(cd "$STACK_DIR/../ashlr-core-efficiency" 2>/dev/null && pwd || true)"
36
+
37
+ # --- 0. Pre-flight: verify the public manifests agree on the version ---
38
+ yellow "→ Checking version manifest sync…"
39
+ if ! (cd "$STACK_DIR" && bun run version:check); then
40
+ red "Version manifests are out of sync. Run: bun run version:bump <new-version>"
41
+ exit 1
42
+ fi
43
+ echo
44
+
45
+ # --- 1. Publish @ashlr/core-efficiency (public) ---
46
+ if [ -n "$CORE_DIR" ] && [ -d "$CORE_DIR/.git" ]; then
47
+ cd "$CORE_DIR"
48
+ if ! git remote get-url origin >/dev/null 2>&1; then
49
+ yellow "→ ashlr-core-efficiency has no remote. Creating…"
50
+ run "gh repo create $USER/ashlr-core-efficiency --public --source . --description 'Token-efficiency primitives for Claude Code: genome, compression, provider-aware budgeting.' --push"
51
+ else
52
+ green "✓ ashlr-core-efficiency already has remote: $(git remote get-url origin)"
53
+ run "git push -u origin main 2>/dev/null || git push"
54
+ fi
55
+ else
56
+ yellow "⚠ skipping ashlr-core-efficiency — sibling repo not found at $STACK_DIR/../ashlr-core-efficiency"
57
+ fi
58
+ echo
59
+
60
+ # --- 2. Publish ashlr-plugin ---
61
+ cd "$STACK_DIR"
62
+ if ! git remote get-url origin >/dev/null 2>&1; then
63
+ yellow "→ ashlr-plugin has no remote. Creating…"
64
+ run "gh repo create $USER/ashlr-plugin --public --source . --description 'Open-source Claude Code plugin — token-efficient Read/Grep/Edit via @ashlr/core-efficiency. MIT.' --push"
65
+ else
66
+ green "✓ ashlr-plugin already has remote: $(git remote get-url origin)"
67
+ run "git push -u origin main 2>/dev/null || git push"
68
+ fi
69
+ echo
70
+
71
+ # --- 3. Enable GitHub Pages from /docs ---
72
+ yellow "→ Enabling GitHub Pages from /docs folder…"
73
+ PAGES_JSON=$(cat <<EOF
74
+ {"source":{"branch":"main","path":"/docs"}}
75
+ EOF
76
+ )
77
+ run "gh api -X POST /repos/$USER/ashlr-plugin/pages --input - <<< '$PAGES_JSON' 2>/dev/null || gh api -X PUT /repos/$USER/ashlr-plugin/pages --input - <<< '$PAGES_JSON' 2>/dev/null || echo '(pages may already be enabled)'"
78
+ echo
79
+
80
+ # --- 4. Report final URLs ---
81
+ green "Done."
82
+ echo " Plugin repo: https://github.com/$USER/ashlr-plugin"
83
+ echo " Landing page: https://plugin.ashlr.ai/"
84
+ echo " Core library repo: https://github.com/$USER/ashlr-core-efficiency"
85
+ echo
86
+ yellow "Install inside Claude Code:"
87
+ echo " /plugin marketplace add $USER/ashlr-plugin"
88
+ echo " /plugin install ashlr@ashlr-marketplace"
@@ -0,0 +1,122 @@
1
+ /**
2
+ * read-calibration — loads the empirical grep multiplier from
3
+ * ~/.ashlr/calibration.json (written by scripts/calibrate-grep.ts).
4
+ *
5
+ * Exports `getCalibrationMultiplier()` which efficiency-server.ts calls when
6
+ * computing the "tokens saved" credit for genome-routed greps.
7
+ *
8
+ * Caching: the result is memoized for the process lifetime. The calibration
9
+ * file is written rarely (only when the user explicitly runs calibrate-grep),
10
+ * so re-reading on every tool call is wasteful.
11
+ */
12
+
13
+ import { existsSync, readFileSync } from "fs";
14
+ import { homedir } from "os";
15
+ import { join } from "path";
16
+
17
+ // Use process.env.HOME when set so test subprocesses on Windows can override
18
+ // the home directory (os.homedir() on Windows reads USERPROFILE, not HOME).
19
+ export const CALIBRATION_PATH = join(
20
+ process.env.HOME ?? homedir(),
21
+ ".ashlr",
22
+ "calibration.json",
23
+ );
24
+
25
+ /** Default when no calibration has been run — conservative guess. */
26
+ export const DEFAULT_MULTIPLIER = 4;
27
+
28
+ export interface CalibrationFile {
29
+ updatedAt: string;
30
+ samples: CalibrationSample[];
31
+ meanRatio: number;
32
+ p50: number;
33
+ p90: number;
34
+ /** Mean ratio across only pattern-matched genome retrievals (excludes core-fallback + synthetic). */
35
+ measuredMean?: number;
36
+ /** Mean ratio across synthetic-only samples (no genome hit). */
37
+ syntheticMean?: number;
38
+ /** Number of samples that used a real pattern-matched genome retrieval. */
39
+ measuredCount?: number;
40
+ /** Mean ratio across core-fallback samples (genome present but pattern scored 0; constant-core output). */
41
+ coreFallbackMean?: number;
42
+ /** Number of samples that hit the core-fallback path. */
43
+ coreFallbackCount?: number;
44
+ }
45
+
46
+ export interface CalibrationSample {
47
+ cwd: string;
48
+ pattern: string;
49
+ rawBytes: number;
50
+ compressedBytes: number;
51
+ ratio: number;
52
+ /**
53
+ * "measured" — pattern scored > 0 against genome sections; compressedBytes is the real retrieval output.
54
+ * "core-fallback" — pattern scored 0; compressedBytes is the constant core-section output (north-star + milestone).
55
+ * Reflects real ashlr__grep behavior for non-matching queries, but the ratio is dominated by the constant
56
+ * numerator, not pattern-specific compression.
57
+ * "synthetic" — no genome present at all; compressedBytes = rawBytes / 4 (estimate, ratio always 4.0).
58
+ */
59
+ quality: "measured" | "core-fallback" | "synthetic";
60
+ }
61
+
62
+ // In-process cache so we pay the file read exactly once per MCP server
63
+ // lifetime. Set to `null` to force a re-read (tests can clear this).
64
+ let _cached: number | null = null;
65
+
66
+ /**
67
+ * Returns the empirical mean ratio from ~/.ashlr/calibration.json, or
68
+ * DEFAULT_MULTIPLIER if the file is absent or malformed.
69
+ *
70
+ * The returned value is the multiplier applied to the genome-compressed output
71
+ * size to estimate what full ripgrep output would have cost.
72
+ */
73
+ export function getCalibrationMultiplier(
74
+ calibrationPath: string = CALIBRATION_PATH,
75
+ ): number {
76
+ // Return memoized value if already loaded (and using default path).
77
+ if (_cached !== null && calibrationPath === CALIBRATION_PATH) {
78
+ return _cached;
79
+ }
80
+
81
+ try {
82
+ if (!existsSync(calibrationPath)) {
83
+ _cached = DEFAULT_MULTIPLIER;
84
+ return DEFAULT_MULTIPLIER;
85
+ }
86
+ const raw = readFileSync(calibrationPath, "utf-8");
87
+ const parsed = JSON.parse(raw) as unknown;
88
+ if (
89
+ typeof parsed !== "object" ||
90
+ parsed === null ||
91
+ typeof (parsed as Record<string, unknown>).meanRatio !== "number" ||
92
+ !Number.isFinite((parsed as Record<string, unknown>).meanRatio as number) ||
93
+ ((parsed as Record<string, unknown>).meanRatio as number) <= 0
94
+ ) {
95
+ _cached = DEFAULT_MULTIPLIER;
96
+ return DEFAULT_MULTIPLIER;
97
+ }
98
+ const file = parsed as CalibrationFile;
99
+ // Preference order:
100
+ // 1. measuredMean — pattern-matched genome retrievals (best signal)
101
+ // 2. coreFallbackMean — real ashlr__grep output for non-matching queries
102
+ // (still a measurement, just of the constant-core path)
103
+ // 3. meanRatio — overall, may be diluted by synthetic 4× estimates
104
+ const isUsable = (n: unknown): n is number =>
105
+ typeof n === "number" && Number.isFinite(n) && (n as number) > 0;
106
+ const ratio = isUsable(file.measuredMean) && (file.measuredCount ?? 0) > 0
107
+ ? file.measuredMean
108
+ : isUsable(file.coreFallbackMean) && (file.coreFallbackCount ?? 0) > 0
109
+ ? file.coreFallbackMean
110
+ : file.meanRatio;
111
+ if (calibrationPath === CALIBRATION_PATH) _cached = ratio;
112
+ return ratio;
113
+ } catch {
114
+ if (calibrationPath === CALIBRATION_PATH) _cached = DEFAULT_MULTIPLIER;
115
+ return DEFAULT_MULTIPLIER;
116
+ }
117
+ }
118
+
119
+ /** Clear the in-process cache (useful in tests). */
120
+ export function clearCalibrationCache(): void {
121
+ _cached = null;
122
+ }