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,208 @@
1
+ /**
2
+ * Shared LLM summarization helper for ashlr MCP tools.
3
+ *
4
+ * Replaces dumb truncation with smart summarization for the cases where
5
+ * the middle of a large output actually matters (large source files, big
6
+ * diffs, log tails with errors buried mid-stream, etc.).
7
+ *
8
+ * Architecture (v1.22 Track D — LLM Hybrid Strategy)
9
+ * - Provider hierarchy: Anthropic Haiku 4.5 → ONNX (stubbed) → Local LM Studio → snipCompact
10
+ * - ASHLR_LLM_PROVIDER controls selection: "auto" (default) | "anthropic" | "onnx" | "local" | "off"
11
+ * - "auto" tries Anthropic first (ANTHROPIC_API_KEY or ~/.claude/.credentials.json),
12
+ * then ONNX (when bundled), then local LM Studio at ASHLR_LLM_URL
13
+ * - SHA-256 cache at ~/.ashlr/summary-cache/<hash>.txt (1h TTL)
14
+ * - Always appends a one-line hint so the agent knows it can ask for the
15
+ * full output via bypassSummary:true
16
+ *
17
+ * Public API: summarizeIfLarge() — re-exported from ./_llm-providers/index.ts.
18
+ * All callers import from this file; internal implementation lives in
19
+ * ./_llm-providers/ to keep concerns separated.
20
+ */
21
+
22
+ // ---------------------------------------------------------------------------
23
+ // Confidence badge — pure helper, no I/O
24
+ // ---------------------------------------------------------------------------
25
+
26
+ export interface ConfidenceBadgeOpts {
27
+ /** Tool name for the escalation hint (e.g. "ashlr__read"). */
28
+ toolName: string;
29
+ /** Raw bytes before compression. */
30
+ rawBytes: number;
31
+ /** Output bytes after compression. */
32
+ outputBytes: number;
33
+ /** True if the LLM fell back to truncation. Always → low tier. */
34
+ fellBack?: boolean;
35
+ /** True if the command exited non-zero AND bytes were elided. Always → low. */
36
+ nonZeroExit?: boolean;
37
+ /** Optional extra tag appended before the closing bracket (e.g. "mtime=123"). */
38
+ extra?: string;
39
+ }
40
+
41
+ type ConfidenceTier = "high" | "medium" | "low";
42
+
43
+ function _tier(opts: ConfidenceBadgeOpts): ConfidenceTier {
44
+ if (opts.fellBack || opts.nonZeroExit) return "low";
45
+ // Nothing to compress → trivially "high" (no information lost).
46
+ if (opts.rawBytes <= 0) return "high";
47
+ // Everything was elided — the exact opposite of high confidence.
48
+ if (opts.outputBytes <= 0) return "low";
49
+ const ratio = opts.outputBytes / opts.rawBytes;
50
+ if (ratio >= 1 / 3) return "high";
51
+ if (ratio >= 1 / 8) return "medium";
52
+ return "low";
53
+ }
54
+
55
+ /** Exposed so call sites can branch on tier (e.g. to emit a logEvent). */
56
+ export function confidenceTier(opts: ConfidenceBadgeOpts): ConfidenceTier {
57
+ return _tier(opts);
58
+ }
59
+
60
+ /**
61
+ * Return a one-line confidence footer to append to compressed tool output.
62
+ * Returns an empty string when no compression occurred (rawBytes ≤ outputBytes)
63
+ * so call sites can always do `text + confidenceBadge(...)` safely.
64
+ *
65
+ * The returned string (when non-empty) is ≤ 80 chars and starts with "\n".
66
+ */
67
+ export function confidenceBadge(opts: ConfidenceBadgeOpts): string {
68
+ // No compression and no failure signal → no badge. Also skip when the
69
+ // raw payload is tiny — a badge on a sub-512-byte response is more noise
70
+ // than signal. fellBack/nonZeroExit still emit (they're load-bearing
71
+ // quality signals regardless of payload size).
72
+ if (!opts.fellBack && !opts.nonZeroExit) {
73
+ if (opts.rawBytes <= opts.outputBytes) return "";
74
+ if (opts.rawBytes < 512) return "";
75
+ }
76
+
77
+ const tier = _tier(opts);
78
+ const rawKB = (opts.rawBytes / 1024).toFixed(0) + "KB";
79
+ const outKB = (opts.outputBytes / 1024).toFixed(0) + "KB";
80
+ const extraPart = opts.extra ? ` · ${opts.extra}` : "";
81
+
82
+ // 80-char budget. Required pieces (always included): tier name + the
83
+ // actionable `bypassSummary:true` hint. Optional pieces dropped under
84
+ // pressure in order: (1) byte numbers, (2) the hint wording shortens.
85
+ // `extra` (when caller passes one) is treated as required — it's how
86
+ // callers thread debug context (e.g. mtime) into the badge.
87
+ const BUDGET = 80;
88
+ const hint = tier === "low"
89
+ ? "bypassSummary:true to recover fidelity"
90
+ : "bypassSummary:true recovers fidelity";
91
+
92
+ const withBytes = `[ashlr confidence: ${tier} · ${rawKB}→${outKB}${extraPart} · ${hint}]`;
93
+ const withoutBytes = `[ashlr confidence: ${tier}${extraPart} · ${hint}]`;
94
+ const minimal = `[ashlr confidence: ${tier} · ${hint}]`;
95
+
96
+ let line = withBytes;
97
+ if (line.length > BUDGET) line = withoutBytes;
98
+ if (line.length > BUDGET) line = minimal;
99
+ if (line.length > BUDGET) line = line.slice(0, BUDGET - 1) + "]";
100
+
101
+ return "\n" + line;
102
+ }
103
+
104
+ // ---------------------------------------------------------------------------
105
+ // Config
106
+ // ---------------------------------------------------------------------------
107
+
108
+ export const DEFAULT_THRESHOLD_BYTES = 16_384;
109
+
110
+ // ---------------------------------------------------------------------------
111
+ // Public API — re-exported from provider abstraction layer
112
+ // ---------------------------------------------------------------------------
113
+
114
+ export type { SummarizeOpts, SummarizeResult } from "./_llm-providers/index.ts";
115
+ export { summarizeIfLarge } from "./_llm-providers/index.ts";
116
+
117
+
118
+ // ---------------------------------------------------------------------------
119
+ // Per-tool prompts (exported so wiring code references them by name, not by string)
120
+ // ---------------------------------------------------------------------------
121
+
122
+ export const PROMPTS = {
123
+ read:
124
+ "You are summarizing a source code file for an AI coding agent. Output ≤500 chars. " +
125
+ "Preserve: file purpose (1 sentence), key functions/classes (1 line each with line ranges). " +
126
+ "Preserve VERBATIM with line numbers: every @-prefixed decorator or annotation (@deprecated, " +
127
+ "@Injectable, @staticmethod, etc.) with its associated symbol; every " +
128
+ "TODO|FIXME|XXX|HACK|WARNING|THREAD-UNSAFE|DEPRECATED|NOTE|SAFETY marker; " +
129
+ "every top-level export/module.exports/__all__ statement (symbol name only, not body). " +
130
+ "Output as plain text — no markdown headers.",
131
+
132
+ diff:
133
+ "You are summarizing a git diff for an AI coding agent. Output ≤500 chars. " +
134
+ "Preserve: changed file paths (each on its own line with +adds/-dels), refactor signatures " +
135
+ "(X→Y renames, signature changes), breaking changes (interface/export changes), " +
136
+ "test-coverage shifts. Preserve hunk headers like '@@ -45,6 +45,14 @@' verbatim where they exist. " +
137
+ "Skip pure-formatting changes. Output as plain text.",
138
+
139
+ logs:
140
+ "You are extracting signal from a log file for a debugging agent. Output ≤600 chars. " +
141
+ "Preserve VERBATIM: the first error and its full stack trace, the most recent error and its trace, " +
142
+ "any 'caused by' chains. Summarize: count of errors/warnings by category, " +
143
+ "deduplicated repetition patterns ('connection timeout x47'), notable preceding warnings. " +
144
+ "Output as plain text. Do not invent context that isn't in the logs.",
145
+
146
+ grep:
147
+ "You are summarizing grep results for a code-navigation agent. Output ≤400 chars. " +
148
+ "Preserve VERBATIM: the top 3 matches with full file:line:content. " +
149
+ "Summarize: total matches, file distribution (which files have the most), dominant pattern type. " +
150
+ "Output as plain text — keep file paths fully qualified.",
151
+
152
+ bash:
153
+ "You are summarizing shell command output for an AI agent. Output ≤500 chars. " +
154
+ "Preserve VERBATIM: errors with full stack traces, the final result line " +
155
+ "(e.g. '187 passed', 'Build failed', exit code), key counts/identifiers. " +
156
+ "Summarize: progress phases (compile → test → build), warnings by category. " +
157
+ "Output as plain text. Do not embellish.",
158
+
159
+ sql:
160
+ "You are summarizing a SQL query result for a data-exploration agent. Output ≤400 chars. " +
161
+ "Preserve VERBATIM: the first 3 and last 2 rows. " +
162
+ "Summarize: total row count, column types, dominant values per column (e.g. 'status: 80% active, 15% pending'), " +
163
+ "notable outliers (max, min, NULL counts). Output as plain text — keep numbers exact.",
164
+
165
+ webfetch:
166
+ "You are summarizing a fetched web page for an AI coding agent. Output ≤500 chars. " +
167
+ "Preserve VERBATIM: the page title, all headings (as '# Heading' / '## Sub'), the first paragraph, " +
168
+ "all hyperlinks with anchor text and URL (format: 'text (url)'), any error or warning messages. " +
169
+ "Summarize: the main topic, key findings or data points, and any actionable content. " +
170
+ "Omit boilerplate, nav menus, cookie notices, and marketing copy. Output as plain text.",
171
+
172
+ http:
173
+ "You are summarizing an HTTP response for an AI coding agent. Output ≤500 chars. " +
174
+ "Preserve VERBATIM: status code, content-type, all headings, the first paragraph, key data fields " +
175
+ "(especially IDs, URLs, error codes, and counts), all hyperlinks. " +
176
+ "For JSON: preserve top-level keys, the first 3 array items verbatim, and total array lengths. " +
177
+ "For HTML: same rules as webfetch — title, headings, first paragraph, links. " +
178
+ "Omit boilerplate, nav, and cookie notices. Output as plain text.",
179
+
180
+ glob:
181
+ "You are summarizing a file glob result for an AI coding agent. Output ≤400 chars. " +
182
+ "Preserve VERBATIM: the top 5 matching paths. " +
183
+ "Summarize: total match count, top-level directory distribution with counts (e.g. 'src/: 42, tests/: 18'), " +
184
+ "any non-obvious structural cues (e.g. nested package layout, monorepo roots). " +
185
+ "Output as plain text — keep file paths fully qualified.",
186
+
187
+ tree:
188
+ "You are summarizing a project directory tree for an AI coding agent. Output ≤400 chars. " +
189
+ "Preserve VERBATIM: the top-level directory names and their immediate children counts. " +
190
+ "Summarize: total dirs and files, dominant file types by extension with counts, " +
191
+ "any non-obvious structural cues (e.g. monorepo packages/, multiple entry points, config clusters). " +
192
+ "Output as plain text — no markdown headers.",
193
+
194
+ diff_semantic:
195
+ "You are summarizing an AST-aware semantic diff for an AI coding agent. Output ≤500 chars. " +
196
+ "Preserve VERBATIM: every detected rename row (old→new), signature-only change rows " +
197
+ "(file:line: old-sig → new-sig), and the final counts header line. " +
198
+ "Summarize: the total files touched, dominant change category (rename | signature | format | mixed), " +
199
+ "whether any breaking-surface (exported symbol) changed. Drop pure-formatting chatter. " +
200
+ "Output as plain text — no markdown headers.",
201
+
202
+ genome_synthesize:
203
+ "You are consolidating N raw auto-observations about a codebase into a short, curated genome section. Output rules:\n\n" +
204
+ "- If the observations contain NO novel insight (all are restatements of things the genome likely already records — library names, file paths without context, generic boilerplate), output EXACTLY this single line:\n" +
205
+ " {\"novel\": false, \"reason\": \"<one sentence why>\"}\n\n" +
206
+ "- Otherwise output 1-3 bullet points, each ≤ 200 chars, in plain markdown (no header, no fences). Each bullet must be a genuine insight tied to a concrete file, symbol, decision, or invariant. Deduplicate — if two observations say the same thing, merge them. Skip observations that are pure noise (tool output dumps, test names, generic changelog chatter).\n\n" +
207
+ "- No prose preamble. No 'Here are the bullets:'. Just the bullets (or the novel:false sentinel).",
208
+ } as const;
@@ -0,0 +1,217 @@
1
+ /**
2
+ * _task-graph-render.ts — Track B rich renderer for the orchestration DAG.
3
+ *
4
+ * Renders a TaskGraph as a numbered topological tree with per-node agent kind,
5
+ * token budget, scope truncation, and dep markers. The slash command + tests
6
+ * assert against the output; the CLI prints it ahead of the y/n/e confirm.
7
+ *
8
+ * Public surface (stable contract with Track C):
9
+ *
10
+ * renderTaskGraph(g: TaskGraph, opts?: RenderOptions): string
11
+ *
12
+ * Guarantees:
13
+ * - Never throws. Falls back to a plain-text dump if anything goes sideways.
14
+ * - Deterministic: stable topo order (input order is a tiebreaker).
15
+ * - Color OFF by default — keeps test goldens stable.
16
+ * - Empty graph → "Orchestration plan — empty graph (0 nodes)".
17
+ * - Single node → no "depends on" markers.
18
+ */
19
+
20
+ import type { TaskGraph, TaskNode } from "./_task-graph.ts";
21
+
22
+ export interface RenderOptions {
23
+ /** Enable ANSI color sequences (default: false for deterministic tests). */
24
+ color?: boolean;
25
+ /** Truncate per-node scope listings beyond this many entries (default: 5). */
26
+ maxScopeFiles?: number;
27
+ }
28
+
29
+ // ---------------------------------------------------------------------------
30
+ // Public API
31
+ // ---------------------------------------------------------------------------
32
+
33
+ export function renderTaskGraph(g: TaskGraph, opts: RenderOptions = {}): string {
34
+ try {
35
+ return doRender(g, opts);
36
+ } catch {
37
+ // Renderer must NEVER throw — fall back to a plain-text dump that callers
38
+ // can still display while we investigate the failure mode.
39
+ return safeFallback(g);
40
+ }
41
+ }
42
+
43
+ // ---------------------------------------------------------------------------
44
+ // Implementation
45
+ // ---------------------------------------------------------------------------
46
+
47
+ function doRender(g: TaskGraph, opts: RenderOptions): string {
48
+ const maxScope = Number.isFinite(opts.maxScopeFiles) && (opts.maxScopeFiles as number) >= 0
49
+ ? Math.floor(opts.maxScopeFiles as number)
50
+ : 5;
51
+ const useColor = opts.color === true;
52
+
53
+ const bold = (s: string): string => (useColor ? `\x1b[1m${s}\x1b[0m` : s);
54
+ const dim = (s: string): string => (useColor ? `\x1b[2m${s}\x1b[0m` : s);
55
+ const cyan = (s: string): string => (useColor ? `\x1b[36m${s}\x1b[0m` : s);
56
+
57
+ const lines: string[] = [];
58
+
59
+ // Empty graph — short-circuit before topo sort.
60
+ if (!g.nodes || g.nodes.length === 0) {
61
+ lines.push(bold(`Orchestration plan`) + ` — empty graph (0 nodes)`);
62
+ if (g.goal) lines.push(` goal: ${quote(g.goal)}`);
63
+ if (g.scope) lines.push(` scope: ${g.scope}`);
64
+ return lines.join("\n");
65
+ }
66
+
67
+ // -- Header -----------------------------------------------------------------
68
+ const nodeCount = g.nodes.length;
69
+ const budget = typeof g.metadata?.totalTokenBudget === "number"
70
+ ? g.metadata.totalTokenBudget
71
+ : g.nodes.reduce((s, n) => s + (Number.isFinite(n.estimatedTokens) ? n.estimatedTokens : 0), 0);
72
+
73
+ lines.push(`${bold("Orchestration plan")} — goal: ${quote(g.goal ?? "")}`);
74
+ if (g.scope) lines.push(`scope: ${g.scope}`);
75
+ lines.push(
76
+ `tier: ${g.tier} · ${nodeCount} ${nodeCount === 1 ? "node" : "nodes"} · ~${formatTokens(budget)} token budget`,
77
+ );
78
+
79
+ // -- Topological order ------------------------------------------------------
80
+ const ordered = topoSort(g.nodes);
81
+ const positionById = new Map<string, number>();
82
+ ordered.forEach((n, i) => positionById.set(n.id, i + 1));
83
+
84
+ for (let i = 0; i < ordered.length; i++) {
85
+ const n = ordered[i]!;
86
+ lines.push(""); // blank line between nodes
87
+ const idx = i + 1;
88
+ const tok = formatTokens(Number.isFinite(n.estimatedTokens) ? n.estimatedTokens : 0);
89
+ const head = `[${idx}] ${bold(n.id)} (${n.agentKind} · ~${tok} tok)`;
90
+
91
+ // Dep marker — only meaningful when there are deps AND >1 node.
92
+ const deps = Array.isArray(n.deps) ? n.deps : [];
93
+ let depSuffix = "";
94
+ if (nodeCount > 1 && deps.length > 0) {
95
+ const positions = deps
96
+ .map((d) => positionById.get(d))
97
+ .filter((p): p is number => typeof p === "number")
98
+ .sort((a, b) => a - b);
99
+ if (positions.length > 0) {
100
+ const tag = positions.map((p) => `[${p}]`).join(", ");
101
+ depSuffix = ` ${cyan("⤴")} ${dim(`depends on ${tag}`)}`;
102
+ }
103
+ }
104
+ lines.push(head + depSuffix);
105
+
106
+ // Goal line.
107
+ lines.push(` ├─ goal: ${n.goal}`);
108
+
109
+ // Scope line — truncate at maxScope.
110
+ const scope = Array.isArray(n.scope) ? n.scope : [];
111
+ if (scope.length > 0) {
112
+ const shown = scope.slice(0, maxScope);
113
+ const more = scope.length - shown.length;
114
+ const suffix = more > 0 ? ` (+${more} more)` : "";
115
+ lines.push(` ├─ scope: ${shown.join(", ")}${suffix}`);
116
+ } else {
117
+ lines.push(` ├─ scope: (none)`);
118
+ }
119
+
120
+ // Deps line — explicit list (or "none") at the bottom for clarity.
121
+ if (deps.length === 0) {
122
+ lines.push(` └─ deps: none`);
123
+ } else {
124
+ lines.push(` └─ deps: ${deps.join(", ")}`);
125
+ }
126
+ }
127
+
128
+ lines.push("");
129
+ lines.push(dim("Press y to execute, n to cancel, e to edit YAML."));
130
+
131
+ return lines.join("\n");
132
+ }
133
+
134
+ // ---------------------------------------------------------------------------
135
+ // Topological sort — Kahn's algorithm with stable input-order tiebreaker.
136
+ // ---------------------------------------------------------------------------
137
+
138
+ function topoSort(nodes: readonly TaskNode[]): TaskNode[] {
139
+ const byId = new Map<string, TaskNode>();
140
+ const indegree = new Map<string, number>();
141
+ const inputOrder = new Map<string, number>();
142
+
143
+ nodes.forEach((n, i) => {
144
+ byId.set(n.id, n);
145
+ inputOrder.set(n.id, i);
146
+ if (!indegree.has(n.id)) indegree.set(n.id, 0);
147
+ });
148
+
149
+ // Build adjacency list + indegrees from deps (deps point INTO a node).
150
+ const successors = new Map<string, string[]>();
151
+ for (const n of nodes) {
152
+ const deps = Array.isArray(n.deps) ? n.deps : [];
153
+ indegree.set(n.id, deps.filter((d) => byId.has(d)).length);
154
+ for (const d of deps) {
155
+ if (!byId.has(d)) continue;
156
+ const list = successors.get(d) ?? [];
157
+ list.push(n.id);
158
+ successors.set(d, list);
159
+ }
160
+ }
161
+
162
+ const ready: string[] = [];
163
+ for (const [id, deg] of indegree) if (deg === 0) ready.push(id);
164
+ ready.sort((a, b) => (inputOrder.get(a) ?? 0) - (inputOrder.get(b) ?? 0));
165
+
166
+ const out: TaskNode[] = [];
167
+ const visited = new Set<string>();
168
+
169
+ while (ready.length > 0) {
170
+ const id = ready.shift()!;
171
+ if (visited.has(id)) continue;
172
+ visited.add(id);
173
+ const n = byId.get(id);
174
+ if (n) out.push(n);
175
+ for (const s of successors.get(id) ?? []) {
176
+ const prev = indegree.get(s) ?? 0;
177
+ const next = prev - 1;
178
+ indegree.set(s, next);
179
+ if (next === 0 && !visited.has(s)) ready.push(s);
180
+ }
181
+ ready.sort((a, b) => (inputOrder.get(a) ?? 0) - (inputOrder.get(b) ?? 0));
182
+ }
183
+
184
+ // Cycle fallback — validator should have rejected this, but be defensive.
185
+ if (out.length < nodes.length) {
186
+ for (const n of nodes) if (!visited.has(n.id)) out.push(n);
187
+ }
188
+
189
+ return out;
190
+ }
191
+
192
+ // ---------------------------------------------------------------------------
193
+ // Helpers
194
+ // ---------------------------------------------------------------------------
195
+
196
+ function formatTokens(n: number): string {
197
+ if (!Number.isFinite(n) || n < 0) return "0";
198
+ if (n < 1000) return String(Math.floor(n));
199
+ // Round to nearest hundred so we get e.g. ~5,200 not ~5,237.
200
+ const rounded = Math.round(n / 100) * 100;
201
+ return rounded.toLocaleString("en-US");
202
+ }
203
+
204
+ function quote(s: string): string {
205
+ return `"${s}"`;
206
+ }
207
+
208
+ function safeFallback(g: TaskGraph | null | undefined): string {
209
+ try {
210
+ const head = `Orchestration plan — goal: "${(g?.goal ?? "").toString()}"`;
211
+ const count = Array.isArray(g?.nodes) ? g!.nodes.length : 0;
212
+ const ids = Array.isArray(g?.nodes) ? g!.nodes.map((n) => String(n?.id ?? "?")).join(", ") : "";
213
+ return `${head}\nnodes: ${count}${ids ? ` (${ids})` : ""}`;
214
+ } catch {
215
+ return "Orchestration plan — render fallback";
216
+ }
217
+ }