dexterm-cli 0.1.5 → 0.1.7

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 (379) hide show
  1. package/dist/packages/agents/src/index.js +2 -0
  2. package/dist/packages/agents/src/schema.js +22 -1
  3. package/dist/packages/agents/src/spectator.js +54 -0
  4. package/dist/packages/agents/src/story.js +532 -0
  5. package/dist/packages/agents/src/tiers.js +28 -2
  6. package/dist/packages/agents/src/tools.js +31 -2
  7. package/dist/packages/autotrade/assets/exit-profile.schema.json +492 -0
  8. package/dist/packages/autotrade/assets/profiles/moonbag.json +46 -0
  9. package/dist/packages/autotrade/assets/profiles/runner.json +88 -0
  10. package/dist/packages/autotrade/assets/profiles/scalp.json +88 -0
  11. package/dist/packages/autotrade/assets/profiles/swing.json +88 -0
  12. package/dist/packages/autotrade/assets/strategies/moonbag.json +101 -0
  13. package/dist/packages/autotrade/assets/strategies/runner.json +101 -0
  14. package/dist/packages/autotrade/assets/strategies/sample-dip-ladder.json +188 -0
  15. package/dist/packages/autotrade/assets/strategies/scalp.json +98 -0
  16. package/dist/packages/autotrade/assets/strategies/swing.json +97 -0
  17. package/dist/packages/autotrade/assets/strategies/yolo.json +157 -0
  18. package/dist/packages/autotrade/assets/tapes/yolo-rehearsal.json +1 -0
  19. package/dist/packages/autotrade/src/account.js +74 -0
  20. package/dist/packages/autotrade/src/backtest.js +357 -0
  21. package/dist/packages/autotrade/src/basis-text.js +32 -0
  22. package/dist/packages/autotrade/src/chat/approvals.js +484 -0
  23. package/dist/packages/autotrade/src/chat/audit.js +140 -0
  24. package/dist/packages/autotrade/src/chat/config.js +93 -0
  25. package/dist/packages/autotrade/src/chat/connector.js +24 -0
  26. package/dist/packages/autotrade/src/chat/control.js +103 -0
  27. package/dist/packages/autotrade/src/chat/fake.js +100 -0
  28. package/dist/packages/autotrade/src/chat/format.js +71 -0
  29. package/dist/packages/autotrade/src/chat/hub.js +187 -0
  30. package/dist/packages/autotrade/src/chat/index.js +18 -0
  31. package/dist/packages/autotrade/src/chat/notify.js +292 -0
  32. package/dist/packages/autotrade/src/chat/pairing.js +46 -0
  33. package/dist/packages/autotrade/src/chat/redact.js +48 -0
  34. package/dist/packages/autotrade/src/chat/secrets.js +99 -0
  35. package/dist/packages/autotrade/src/chat/service.js +248 -0
  36. package/dist/packages/autotrade/src/chat/telegram.js +290 -0
  37. package/dist/packages/autotrade/src/desk-executor.js +188 -0
  38. package/dist/packages/autotrade/src/engine.js +387 -0
  39. package/dist/packages/autotrade/src/execution-port.js +97 -0
  40. package/dist/packages/autotrade/src/fleet-config.js +169 -0
  41. package/dist/packages/autotrade/src/fleet-control.js +276 -0
  42. package/dist/packages/autotrade/src/fleet.js +639 -0
  43. package/dist/packages/autotrade/src/index.js +53 -0
  44. package/dist/packages/autotrade/src/ledger.js +108 -0
  45. package/dist/packages/autotrade/src/live-source.js +182 -0
  46. package/dist/packages/autotrade/src/monitor-daemon.js +715 -0
  47. package/dist/packages/autotrade/src/monitor.js +190 -0
  48. package/dist/packages/autotrade/src/ollama-sessions.js +137 -0
  49. package/dist/packages/autotrade/src/paper-accounts.js +72 -0
  50. package/dist/packages/autotrade/src/replay.js +198 -0
  51. package/dist/packages/autotrade/src/runner-config.js +99 -0
  52. package/dist/packages/autotrade/src/runner.js +872 -0
  53. package/dist/packages/autotrade/src/safety.js +243 -0
  54. package/dist/packages/autotrade/src/session.js +269 -0
  55. package/dist/packages/autotrade/src/sessions.js +503 -0
  56. package/dist/packages/autotrade/src/store.js +250 -0
  57. package/dist/packages/autotrade/src/strategy.js +256 -0
  58. package/dist/packages/autotrade/src/trade-ledger.js +241 -0
  59. package/dist/packages/autotrade/src/yolo.js +140 -0
  60. package/dist/packages/cli/assets/claude/analyst-system.md +4 -4
  61. package/dist/packages/cli/assets/claude/plugin/skills/REGISTRY.json +1 -1
  62. package/dist/packages/cli/assets/claude/plugin/skills/larp-check/SKILL.md +15 -8
  63. package/dist/packages/cli/assets/claude/plugin/skills/token-dossier/SKILL.md +1 -1
  64. package/dist/packages/cli/src/agent-cmd.js +6 -4
  65. package/dist/packages/cli/src/agent-spectator.js +17 -1
  66. package/dist/packages/cli/src/ai-cmd.js +412 -0
  67. package/dist/packages/cli/src/analyst/backend.js +105 -15
  68. package/dist/packages/cli/src/analyst/codex.js +14 -9
  69. package/dist/packages/cli/src/analyst/larp-gauge.js +60 -0
  70. package/dist/packages/cli/src/analyst/ollama.js +263 -0
  71. package/dist/packages/cli/src/analyst/session.js +17 -3
  72. package/dist/packages/cli/src/app-help-gen.js +51 -15
  73. package/dist/packages/cli/src/autotrade-cmd/audit.js +57 -0
  74. package/dist/packages/cli/src/autotrade-cmd/backtest.js +199 -0
  75. package/dist/packages/cli/src/autotrade-cmd/flatten.js +64 -0
  76. package/dist/packages/cli/src/autotrade-cmd/fleet.js +397 -0
  77. package/dist/packages/cli/src/autotrade-cmd/requests.js +79 -0
  78. package/dist/packages/cli/src/autotrade-cmd/run.js +413 -0
  79. package/dist/packages/cli/src/autotrade-cmd/stop.js +76 -0
  80. package/dist/packages/cli/src/autotrade-cmd/strategies.js +198 -0
  81. package/dist/packages/cli/src/autotrade-cmd/strategy-control.js +174 -0
  82. package/dist/packages/cli/src/autotrade-cmd/telegram-host.js +101 -0
  83. package/dist/packages/cli/src/autotrade-cmd.js +168 -0
  84. package/dist/packages/cli/src/backtest-cmd.js +13 -2
  85. package/dist/packages/cli/src/display.js +208 -23
  86. package/dist/packages/cli/src/doctor.js +62 -3
  87. package/dist/packages/cli/src/export.js +10 -2
  88. package/dist/packages/cli/src/index.js +1 -1
  89. package/dist/packages/cli/src/ledger-cmd.js +288 -0
  90. package/dist/packages/cli/src/live/chart-fills.js +46 -0
  91. package/dist/packages/cli/src/live/dev-history.js +31 -15
  92. package/dist/packages/cli/src/live/index.js +28 -90
  93. package/dist/packages/cli/src/live/screens/newpairs-live.js +1 -1
  94. package/dist/packages/cli/src/live/screens/token-live.js +48 -15
  95. package/dist/packages/cli/src/live/screens/watchlist-live.js +1 -1
  96. package/dist/packages/cli/src/live/trade.js +30 -453
  97. package/dist/packages/cli/src/live/watchlist.js +1 -1
  98. package/dist/packages/cli/src/main.js +290 -199
  99. package/dist/packages/cli/src/mcp-cmd.js +7 -1
  100. package/dist/packages/cli/src/mcp-follow.js +103 -6
  101. package/dist/packages/cli/src/plan-cmd.js +15 -5
  102. package/dist/packages/cli/src/pnl-app.js +31 -21
  103. package/dist/packages/cli/src/pnl-card.js +158 -21
  104. package/dist/packages/cli/src/popup.js +38 -6
  105. package/dist/packages/cli/src/record-cmd.js +141 -20
  106. package/dist/packages/cli/src/scan/ui.js +7 -1
  107. package/dist/packages/cli/src/screens/agent-hud.js +773 -0
  108. package/dist/packages/cli/src/screens/analyst-session.js +11 -4
  109. package/dist/packages/cli/src/screens/analyst.js +3 -2
  110. package/dist/packages/cli/src/screens/autotrade-keys.js +169 -0
  111. package/dist/packages/cli/src/screens/autotrade-proposals.js +123 -0
  112. package/dist/packages/cli/src/screens/autotrade-screen.js +725 -0
  113. package/dist/packages/cli/src/screens/autotrade-ui.js +640 -0
  114. package/dist/packages/cli/src/screens/autotrade-worker.js +89 -0
  115. package/dist/packages/cli/src/screens/brain.js +634 -0
  116. package/dist/packages/cli/src/screens/newpairs.js +1 -1
  117. package/dist/packages/cli/src/screens/overlay.js +5 -2
  118. package/dist/packages/cli/src/screens/plans.js +5 -17
  119. package/dist/packages/cli/src/screens/pnl-chip.js +144 -0
  120. package/dist/packages/cli/src/screens/positions.js +6 -28
  121. package/dist/packages/cli/src/screens/screener.js +1 -0
  122. package/dist/packages/cli/src/screens/ticket.js +38 -205
  123. package/dist/packages/cli/src/screens/token.js +18 -9
  124. package/dist/packages/cli/src/screens/trending.js +1 -1
  125. package/dist/packages/cli/src/state.js +88 -18
  126. package/dist/packages/cli/src/telegram-cmd.js +451 -0
  127. package/dist/packages/cli/src/trade.js +3 -128
  128. package/dist/packages/cli/src/version.js +1 -1
  129. package/dist/packages/cli/src/wallet-cmd.js +39 -340
  130. package/dist/packages/cli/src/wallet-command.js +8 -11
  131. package/dist/packages/cli/src/widgets.js +0 -12
  132. package/dist/packages/custom/src/config.js +20 -2
  133. package/dist/packages/custom/src/schema.js +41 -10
  134. package/dist/packages/custom/src/workspace.js +3 -3
  135. package/dist/packages/data/src/basis.js +191 -0
  136. package/dist/packages/data/src/detail.js +53 -2
  137. package/dist/packages/data/src/index.js +2 -14
  138. package/dist/packages/data/src/larp/score.js +220 -0
  139. package/dist/packages/data/src/larp/x-account.js +316 -0
  140. package/dist/packages/data/src/store.js +14 -5
  141. package/dist/packages/data/src/trade/agent/paper-desk.js +300 -23
  142. package/dist/packages/data/src/trade/agent/rendezvous.js +3 -2
  143. package/dist/packages/data/src/trade/bridge.js +4 -102
  144. package/dist/packages/data/src/trade/ledger/export.js +101 -0
  145. package/dist/packages/data/src/trade/ledger/file.js +135 -0
  146. package/dist/packages/data/src/trade/ledger/fold.js +191 -0
  147. package/dist/packages/data/src/trade/ledger/index.js +9 -0
  148. package/dist/packages/data/src/trade/ledger/schema.js +83 -0
  149. package/dist/packages/data/src/trade/ledger/sources.js +307 -0
  150. package/dist/packages/data/src/trade/ledger/stats.js +123 -0
  151. package/dist/packages/data/src/trade/ledger/tags.js +116 -0
  152. package/dist/packages/data/src/trade/ledger/view.js +51 -0
  153. package/dist/packages/data/src/trade/plans/engine.js +7 -0
  154. package/dist/packages/data/src/trade/plans/index.js +0 -1
  155. package/dist/packages/data/src/trade/plans/mandate.js +28 -15
  156. package/dist/packages/data/src/trade/plans/service.js +4 -28
  157. package/dist/packages/mcp/assets/kb/app-help/autotrade-chat.md +48 -0
  158. package/dist/packages/mcp/assets/kb/app-help/autotrade-parallel.md +42 -0
  159. package/dist/packages/mcp/assets/kb/app-help/autotrade-runner.md +35 -0
  160. package/dist/packages/mcp/assets/kb/app-help/autotrade-stop.md +37 -0
  161. package/dist/packages/mcp/assets/kb/app-help/autotrade-strategies.md +35 -0
  162. package/dist/packages/mcp/assets/kb/app-help/autotrade-telegram.md +40 -0
  163. package/dist/packages/mcp/assets/kb/app-help/chart-trade-markers.md +42 -0
  164. package/dist/packages/mcp/assets/kb/app-help/dev-history.md +1 -1
  165. package/dist/packages/mcp/assets/kb/app-help/larp-check.md +5 -1
  166. package/dist/packages/mcp/assets/kb/app-help/link-a-wallet.md +4 -10
  167. package/dist/packages/mcp/assets/kb/app-help/live-trading.md +38 -0
  168. package/dist/packages/mcp/assets/kb/app-help/live-yolo.md +34 -0
  169. package/dist/packages/mcp/assets/kb/app-help/order-plans.md +1 -1
  170. package/dist/packages/mcp/assets/kb/app-help/price-or-marketcap.md +5 -2
  171. package/dist/packages/mcp/assets/kb/app-help/scan-mode.md +1 -1
  172. package/dist/packages/mcp/assets/kb/app-help/screen-analyst.md +3 -0
  173. package/dist/packages/mcp/assets/kb/app-help/screen-autotrade.md +217 -0
  174. package/dist/packages/mcp/assets/kb/app-help/screen-kol.md +3 -0
  175. package/dist/packages/mcp/assets/kb/app-help/screen-newpairs.md +3 -0
  176. package/dist/packages/mcp/assets/kb/app-help/screen-positions.md +3 -0
  177. package/dist/packages/mcp/assets/kb/app-help/screen-screener.md +3 -0
  178. package/dist/packages/mcp/assets/kb/app-help/screen-token.md +6 -0
  179. package/dist/packages/mcp/assets/kb/app-help/screen-trending.md +3 -0
  180. package/dist/packages/mcp/assets/kb/app-help/screen-watchlist.md +3 -0
  181. package/dist/packages/mcp/assets/kb/app-help/spectate-an-agent.md +2 -1
  182. package/dist/packages/mcp/assets/kb/app-help/standing-mandates.md +1 -1
  183. package/dist/packages/mcp/assets/kb/app-help/trade-ledger.md +54 -0
  184. package/dist/packages/mcp/assets/kb/app-help/use-local-model.md +38 -0
  185. package/dist/packages/mcp/assets/kb/docs/docs-agents-agent-paper-trading.md +7 -3
  186. package/dist/packages/mcp/assets/kb/docs/docs-agents-reading-your-trade-ledger.md +31 -0
  187. package/dist/packages/mcp/assets/kb/docs/docs-agents-untrusted-by-default.md +1 -1
  188. package/dist/packages/mcp/assets/kb/docs/docs-analyst-if-claude-is-missing.md +1 -1
  189. package/dist/packages/mcp/assets/kb/docs/docs-analyst-starting-a-run.md +2 -0
  190. package/dist/packages/mcp/assets/kb/docs/docs-analyst-use-a-local-model-instead.md +27 -0
  191. package/dist/packages/mcp/assets/kb/docs/docs-analyst-what-it-sees.md +2 -0
  192. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-backtests-and-their-limits.md +56 -0
  193. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-change-a-strategy-by-chat.md +49 -0
  194. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-checking-the-record-of-a-run.md +28 -0
  195. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-comparing-them.md +41 -0
  196. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-exits-and-wakes.md +76 -0
  197. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-how-a-stop-reaches-the-runner.md +32 -0
  198. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-on-the-q-screen.md +37 -0
  199. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-one-strategy-or-all-of-them.md +35 -0
  200. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-paper-accounts.md +50 -0
  201. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-presets.md +37 -0
  202. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-running-it-all-day.md +31 -0
  203. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-sessions-and-their-limits.md +31 -0
  204. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-several-strategies-at-once.md +33 -0
  205. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-stopping-it.md +35 -0
  206. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-strategies-and-presets.md +34 -0
  207. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-autotrade-json-file.md +48 -0
  208. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-heartbeat.md +27 -0
  209. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-run-file-and-the-heartbeat.md +34 -0
  210. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-runner-and-candidate-sessions.md +45 -0
  211. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-each-session-shows-first.md +31 -0
  212. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-costs-claude-usage-per-session.md +58 -0
  213. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-is-paper-self-directed.md +43 -0
  214. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-will-not-do.md +31 -0
  215. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-which-account-day-caps-and-the-usage-guard.md +44 -0
  216. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-your-strategies.md +37 -0
  217. package/dist/packages/mcp/assets/kb/docs/docs-autotrade.md +22 -0
  218. package/dist/packages/mcp/assets/kb/docs/docs-beginners-before-any-experimental-trading.md +2 -2
  219. package/dist/packages/mcp/assets/kb/docs/docs-beginners.md +1 -1
  220. package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-markers.md +30 -0
  221. package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-y-axis.md +32 -0
  222. package/dist/packages/mcp/assets/kb/docs/docs-configuration-environment-variables.md +4 -1
  223. package/dist/packages/mcp/assets/kb/docs/docs-configuration-files-on-disk.md +1 -0
  224. package/dist/packages/mcp/assets/kb/docs/docs-configuration-headless-recorder-dexterm-record.md +3 -1
  225. package/dist/packages/mcp/assets/kb/docs/docs-configuration-price-display-mode.md +9 -7
  226. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-2-the-one-key-mirror-ticket-a-proposal.md +1 -1
  227. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-3-capped-auto-mirror-default-off-less.md +1 -1
  228. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-what-is-proven-what-is-not.md +1 -1
  229. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading.md +1 -1
  230. package/dist/packages/mcp/assets/kb/docs/docs-data-sources-recorded-history-and-retention.md +36 -0
  231. package/dist/packages/mcp/assets/kb/docs/docs-data-sources-sources.md +1 -0
  232. package/dist/packages/mcp/assets/kb/docs/docs-getting-started-first-run.md +1 -1
  233. package/dist/packages/mcp/assets/kb/docs/docs-getting-started-install.md +3 -3
  234. package/dist/packages/mcp/assets/kb/docs/docs-getting-started-requirements.md +1 -1
  235. package/dist/packages/mcp/assets/kb/docs/docs-getting-started-running-the-tests.md +1 -1
  236. package/dist/packages/mcp/assets/kb/docs/docs-getting-started.md +1 -1
  237. package/dist/packages/mcp/assets/kb/docs/docs-larp-measured-accuracy.md +1 -0
  238. package/dist/packages/mcp/assets/kb/docs/docs-larp-the-larp-score.md +60 -0
  239. package/dist/packages/mcp/assets/kb/docs/docs-larp-the-verdict.md +0 -2
  240. package/dist/packages/mcp/assets/kb/docs/docs-larp-what-it-looks-at.md +4 -1
  241. package/dist/packages/mcp/assets/kb/docs/docs-larp.md +1 -1
  242. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-changed-in-0-1-7.md +26 -0
  243. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-stopping.md +28 -0
  244. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-the-short-version.md +34 -0
  245. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-using-a-trading-bot-with-dexterm.md +33 -0
  246. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does-not-do.md +30 -0
  247. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does.md +29 -0
  248. package/dist/packages/mcp/assets/kb/docs/docs-live-trading.md +23 -0
  249. package/dist/packages/mcp/assets/kb/docs/docs-ollama-another-machine.md +28 -0
  250. package/dist/packages/mcp/assets/kb/docs/docs-ollama-autotrade-on-a-local-model.md +29 -0
  251. package/dist/packages/mcp/assets/kb/docs/docs-ollama-check-your-model-dexterm-ai-probe.md +38 -0
  252. package/dist/packages/mcp/assets/kb/docs/docs-ollama-how-we-checked.md +27 -0
  253. package/dist/packages/mcp/assets/kb/docs/docs-ollama-models-without-tool-calling.md +32 -0
  254. package/dist/packages/mcp/assets/kb/docs/docs-ollama-pick-the-engine-globally-or-per-surface.md +43 -0
  255. package/dist/packages/mcp/assets/kb/docs/docs-ollama-restriction-profiles.md +35 -0
  256. package/dist/packages/mcp/assets/kb/docs/docs-ollama-set-it-up-in-two-minutes.md +39 -0
  257. package/dist/packages/mcp/assets/kb/docs/docs-ollama-troubleshooting.md +35 -0
  258. package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-runs-on-a-local-model.md +39 -0
  259. package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-stays-outside-the-model.md +36 -0
  260. package/dist/packages/mcp/assets/kb/docs/docs-ollama-which-model.md +38 -0
  261. package/dist/packages/mcp/assets/kb/docs/docs-ollama-your-own-agent-on-the-local-model.md +28 -0
  262. package/dist/packages/mcp/assets/kb/docs/docs-ollama.md +28 -0
  263. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-letting-an-agent-paper-trade-experimental.md +3 -4
  264. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet-read-only.md +30 -0
  265. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-order-plans-and-standing-mandates.md +4 -13
  266. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-panic.md +4 -7
  267. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-paper-only-mandates.md +40 -0
  268. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-pnl-cards.md +7 -7
  269. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-safety-model.md +34 -0
  270. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-ticket.md +3 -4
  271. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-trade-ledger.md +42 -0
  272. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-wallet.md +4 -5
  273. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-trade-moments.md +4 -5
  274. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading.md +4 -5
  275. package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-buy-and-sell-markers.md +37 -0
  276. package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-market-cap-axis.md +1 -1
  277. package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-what-it-shows.md +3 -1
  278. package/dist/packages/mcp/assets/kb/docs/docs-scan-the-read.md +2 -0
  279. package/dist/packages/mcp/assets/kb/docs/docs-screens-autotrade-paper.md +26 -0
  280. package/dist/packages/mcp/assets/kb/docs/docs-screens-dev-history.md +10 -7
  281. package/dist/packages/mcp/assets/kb/docs/docs-screens-order-plans.md +1 -1
  282. package/dist/packages/mcp/assets/kb/docs/docs-screens-token-screen.md +2 -0
  283. package/dist/packages/mcp/assets/kb/docs/docs-spectator-follow-over-mcp-in-the-running-terminal.md +1 -1
  284. package/dist/packages/mcp/assets/kb/docs/docs-spectator-limits.md +2 -0
  285. package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-agent-hud-spectator-v2.md +58 -0
  286. package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-brain-view-and-the-pnl-chip.md +46 -0
  287. package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-three-surfaces.md +1 -1
  288. package/dist/packages/mcp/assets/kb/docs/docs-spectator.md +1 -1
  289. package/dist/packages/mcp/assets/kb/docs/docs-telegram-approve-one-tap-entries.md +50 -0
  290. package/dist/packages/mcp/assets/kb/docs/docs-telegram-control-the-commands.md +43 -0
  291. package/dist/packages/mcp/assets/kb/docs/docs-telegram-if-something-goes-wrong.md +30 -0
  292. package/dist/packages/mcp/assets/kb/docs/docs-telegram-notify-what-reaches-your-phone.md +41 -0
  293. package/dist/packages/mcp/assets/kb/docs/docs-telegram-set-it-up.md +47 -0
  294. package/dist/packages/mcp/assets/kb/docs/docs-telegram-the-record.md +26 -0
  295. package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-is.md +33 -0
  296. package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-will-not-do.md +31 -0
  297. package/dist/packages/mcp/assets/kb/docs/docs-telegram.md +23 -0
  298. package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-common-questions.md +1 -1
  299. package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-doctor-lines.md +4 -0
  300. package/dist/packages/mcp/assets/kb/docs/docs-voice-linux-and-windows.md +1 -1
  301. package/dist/packages/mcp/assets/kb/docs/docs-voice.md +1 -1
  302. package/dist/packages/mcp/assets/kb/docs/docs-yolo-1-replay-it-on-your-own-history.md +42 -0
  303. package/dist/packages/mcp/assets/kb/docs/docs-yolo-2-run-it-on-paper.md +34 -0
  304. package/dist/packages/mcp/assets/kb/docs/docs-yolo-3-watch-it-and-stop-it.md +32 -0
  305. package/dist/packages/mcp/assets/kb/docs/docs-yolo-the-rules.md +37 -0
  306. package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-is.md +34 -0
  307. package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-will-not-do.md +31 -0
  308. package/dist/packages/mcp/assets/kb/docs/docs-yolo.md +26 -0
  309. package/dist/packages/mcp/assets/kb/entries/autotrade.md +38 -0
  310. package/dist/packages/mcp/src/app-help.js +1 -1
  311. package/dist/packages/mcp/src/autotrade-tools.js +944 -0
  312. package/dist/packages/mcp/src/backtest-requests.js +71 -0
  313. package/dist/packages/mcp/src/engine/config.js +159 -0
  314. package/dist/packages/mcp/src/engine/index.js +10 -0
  315. package/dist/packages/mcp/src/engine/loop.js +101 -0
  316. package/dist/packages/mcp/src/engine/mcp-client.js +123 -0
  317. package/dist/packages/mcp/src/engine/ollama.js +258 -0
  318. package/dist/packages/mcp/src/engine/probe.js +110 -0
  319. package/dist/packages/mcp/src/engine/reason.js +35 -0
  320. package/dist/packages/mcp/src/engine/restrictions.js +111 -0
  321. package/dist/packages/mcp/src/index.js +7 -1
  322. package/dist/packages/mcp/src/ledger-tools.js +346 -0
  323. package/dist/packages/mcp/src/paper-agent.js +5 -2
  324. package/dist/packages/mcp/src/server.js +285 -36
  325. package/dist/packages/mcp/src/spectator-sink.js +85 -0
  326. package/dist/packages/packs/src/backtest.js +3 -1
  327. package/dist/packages/packs/src/index.js +1 -0
  328. package/dist/packages/packs/src/larp-score-backtest.js +119 -0
  329. package/dist/packages/popup/src/pages/chart-lib.js +169 -35
  330. package/dist/packages/popup/src/pages/chart.css +18 -0
  331. package/dist/packages/popup/src/pages/chart.html +6 -1
  332. package/dist/packages/popup/src/pages/chart.js +136 -10
  333. package/dist/packages/popup/src/pages/spectator.css +45 -0
  334. package/dist/packages/popup/src/pages/spectator.html +1 -0
  335. package/dist/packages/popup/src/pages/spectator.js +69 -0
  336. package/dist/packages/popup/src/protocol.js +4 -0
  337. package/dist/packages/popup/src/server.js +9 -1
  338. package/dist/packages/recorder/src/dev-history.js +7 -3
  339. package/dist/packages/recorder/src/index.js +2 -0
  340. package/dist/packages/recorder/src/recorder.js +63 -6
  341. package/dist/packages/recorder/src/retention.js +100 -0
  342. package/dist/packages/recorder/src/schema.js +34 -1
  343. package/dist/packages/recorder/src/ticks.js +237 -0
  344. package/dist/packages/tui/src/canvas.js +7 -0
  345. package/dist/packages/tui/src/fmt.js +53 -0
  346. package/dist/packages/tui/src/index.js +1 -0
  347. package/dist/packages/tui/src/keymap.js +25 -1
  348. package/dist/packages/tui/src/markers.js +219 -0
  349. package/dist/packages/tui/src/widgets.js +158 -6
  350. package/package.json +2 -1
  351. package/dist/packages/data/src/trade/caps.js +0 -323
  352. package/dist/packages/data/src/trade/executor.js +0 -933
  353. package/dist/packages/data/src/trade/plans/executor-live.js +0 -220
  354. package/dist/packages/data/src/trade/rpc-exec.js +0 -229
  355. package/dist/packages/data/src/trade/signer/client.js +0 -197
  356. package/dist/packages/data/src/trade/signer/fast-wallet.js +0 -154
  357. package/dist/packages/data/src/trade/signer/host.js +0 -97
  358. package/dist/packages/data/src/trade/signer/main.js +0 -121
  359. package/dist/packages/data/src/trade/signer/probe-builder.js +0 -85
  360. package/dist/packages/data/src/trade/signer/protocol.js +0 -92
  361. package/dist/packages/data/src/trade/signer/service.js +0 -400
  362. package/dist/packages/data/src/trade/signer/sol-usd-feed.js +0 -98
  363. package/dist/packages/data/src/trade/sol-usd.js +0 -86
  364. package/dist/packages/data/src/trade/swap-build.js +0 -108
  365. package/dist/packages/data/src/trade/token-delta.js +0 -201
  366. package/dist/packages/data/vendor/solana-web3/LICENSE +0 -20
  367. package/dist/packages/data/vendor/solana-web3/NOTICE.md +0 -13
  368. package/dist/packages/data/vendor/solana-web3/index.iife.min.js +0 -20
  369. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-a-live-ticket.md +0 -42
  370. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-before-you-press-size-vs-caps.md +0 -34
  371. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-devnet-signer-mainnet-token.md +0 -35
  372. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-jupiter-rate-limits.md +0 -33
  373. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet.md +0 -32
  374. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-live-trading-devnet-first.md +0 -30
  375. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-mainnet.md +0 -31
  376. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-live-fire-path-devnet-the-fast-wallet.md +0 -41
  377. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-signer-process.md +0 -34
  378. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-what-the-live-path-keeps.md +0 -37
  379. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-your-first-live-trade.md +0 -41
@@ -2,20 +2,21 @@
2
2
  // run, created over the screener feed's data layer so every screen shares the cache, limiter, health
3
3
  // registry and (when the Helius key is configured) the credit meter. Screens stay pure renderers: the
4
4
  // context owns the loaders and tells the UI loop when to redraw.
5
- import { PumpPortalClient, PUMPPORTAL_WS, WatchlistStore, PaperWallet, PaperExecutor, FastLane, WalletLinkStore, WalletBridge, KillSwitch, CapLedger, SignerClient, defaultLiveLedgerPath, defaultLinkPath, defaultPanicPath, defaultCapLedgerPath, shortPubkey, } from '../../../data/src/index.js';
5
+ import { PumpPortalClient, PUMPPORTAL_WS, WatchlistStore, PaperWallet, PaperExecutor, FastLane, WalletLinkStore, WalletBridge, KillSwitch, defaultLinkPath, defaultPanicPath, shortPubkey, } from '../../../data/src/index.js';
6
6
  import { SocialFeed, KolStore, socialDeps, chainSignalsFromToken, chainSignalsFromIntel, chainSignalToRaw, RSS_FEEDS, JUPITER_HOSTS } from '../../../data/src/index.js';
7
7
  import { XSource, XApi, XOAuth, XTokenStore, XSpendMeter } from '../../../data/src/index.js';
8
8
  import { TokenLive, INTERVALS } from "./token.js";
9
9
  import { NewPairsLive } from "./newpairs.js";
10
10
  import { WatchlistLive } from "./watchlist.js";
11
- import { TradeTicketLive, PositionsLive, LivePositions, CombinedPositions, POSITIONS_REFRESH_MS } from "./trade.js";
11
+ import { TradeTicketLive, PositionsLive, POSITIONS_REFRESH_MS } from "./trade.js";
12
12
  import { IntelLive } from "./intel.js";
13
13
  import { LiveSignalsLive } from "./signals.js";
14
14
  import { CopyLive } from "./copy.js";
15
+ import { ChartFills } from "./chart-fills.js";
15
16
  export { TokenLive, INTERVALS, panelCaption, emptyView } from "./token.js";
16
17
  export { NewPairsLive, latencyStats, percentile, RECENT_POLL_MS, NEW_TOKENS_POLL_MS, ENRICH_POLL_MS } from "./newpairs.js";
17
18
  export { WatchlistLive, WATCH_REFRESH_MS } from "./watchlist.js";
18
- export { TradeTicketLive, PositionsLive, LivePositions, CombinedPositions, POSITIONS_REFRESH_MS } from "./trade.js";
19
+ export { TradeTicketLive, PositionsLive, POSITIONS_REFRESH_MS } from "./trade.js";
19
20
  export { IntelLive, popupBubbleVM, unavailableText, INTEL_AUTOSCAN_DELAY_MS } from "./intel.js";
20
21
  export { LiveSignalsLive, buildObservation, SIGNALS_LOG_MAX } from "./signals.js";
21
22
  export { renderTokenLive } from "./screens/token-live.js";
@@ -37,17 +38,14 @@ export class LiveContext {
37
38
  watch;
38
39
  /** PAPER trading (task-1310): the simulated wallet, its executor and the two screens' bindings. */
39
40
  wallet;
40
- /** The linked (non-custodial) wallet pubkey, or null. Shown in the status bar (T1). */
41
+ /** The linked wallet's PUBLIC key, or null. Shown in the status bar (display only; nothing signs with it). */
41
42
  linkedWallet = null;
42
43
  executor;
43
44
  positions;
44
- /** LIVE positions from the signer's ledger file (read-only); null when live trading is off for this run. */
45
- livePositions;
46
- /** Paper + live behind the task-1323 PositionSource (token screen row, popup chart). */
45
+ /** The paper ledger behind the task-1323 PositionSource (token screen row, popup chart). */
47
46
  positionSource;
48
- /** The signer process handle once started (lazily, on the first LIVE action). Never respawned. */
49
- signer = null;
50
- signerFailed = null;
47
+ /** task-1483: every paper fill per mint (memoised 1 s) for the chart BUY/SELL markers. */
48
+ chartFills;
51
49
  trade;
52
50
  linkStore;
53
51
  ticket = null;
@@ -68,8 +66,8 @@ export class LiveContext {
68
66
  /** task-1360 copy trading Tier 1: the follow store + wallet tracker (alerts on a followed wallet's buys/sells). */
69
67
  copy;
70
68
  /**
71
- * task-1340 trade moments: set by the UI loop; the ticket calls it once per SETTLED outcome (paper fill, live
72
- * fill, refusal, failure) and never for a quote, plan or in-flight send. Effects + sound hang off this only.
69
+ * task-1340 trade moments: set by the UI loop; the ticket calls it once per SETTLED outcome (paper fill or
70
+ * failure) and never for a quote or an in-flight fill. Effects + sound hang off this only.
73
71
  */
74
72
  onSettled = () => { };
75
73
  /**
@@ -173,12 +171,8 @@ export class LiveContext {
173
171
  this.linkedWallet = this.linkStore.get();
174
172
  this.executor = new PaperExecutor(this.wallet, { clock: dl.clock });
175
173
  this.positions = new PositionsLive(dl, this.wallet, { now: this.now, onChange: () => emit('positions') });
176
- // task-1328: live positions read the signer's ledger file (read-only). Present whenever live trading
177
- // is configured for the run, so a position booked by a previous run shows even before the signer starts.
178
- this.livePositions = this.trade
179
- ? new LivePositions(this.trade.paths?.liveLedger ?? defaultLiveLedgerPath(), { now: this.now, mark: (m) => this.positions.markOf(m), solUsd: () => this.positions.solUsd() ?? this.solUsd })
180
- : null;
181
- this.positionSource = new CombinedPositions(this.positions, this.livePositions);
174
+ this.positionSource = this.positions;
175
+ this.chartFills = new ChartFills({ paper: (n) => this.wallet.trades(n) }, this.now);
182
176
  this.intel = new IntelLive(dl, { now: this.now, onChange: () => { this.syncIntelRows(); this.observeSignals(); emit('intel'); }, isWatched: (mint) => this.watch.has(mint) });
183
177
  // task-1404: the live holder/rug signals engine. A fired signal sets a transient notice and redraws; the
184
178
  // token screen shows the recent signals, and the rules engine reads `signals.fields()` so each is an alert trigger.
@@ -186,64 +180,33 @@ export class LiveContext {
186
180
  // task-1360: followed wallets are polled only in a real live run (replay never spends credits); the store is always readable.
187
181
  this.copy = new CopyLive(opts.mode === 'live' ? dl : null, { onChange: (r) => emit(r), solUsd: () => this.solUsd, env: opts.copy?.env, followsPath: opts.copy?.followsPath, history: opts.copy?.history, pollMs: opts.copy?.pollMs });
188
182
  }
189
- /** Open a trade ticket (PAPER by default; `L` flips it LIVE when a wallet is linked). Replaces any open ticket. */
190
- openTicket(seed, side, mode = 'paper') {
191
- const live = this.trade ? {
192
- signer: () => this.ensureSigner(),
193
- linked: () => this.linkedWallet,
194
- onFill: () => { this.livePositions?.invalidate(); this.onChange('positions'); },
195
- } : undefined;
183
+ /** Open a PAPER trade ticket. Replaces any open ticket. */
184
+ openTicket(seed, side) {
196
185
  const t = new TradeTicketLive(this.dl, this.wallet, this.executor, { mint: seed.mint, symbol: seed.symbol, decimals: seed.decimals, side, mode: 'paper' }, {
197
- now: this.now, onChange: () => this.onChange('ticket'), live, onSettled: (tx) => this.onSettled(tx),
198
- livePositionRaw: (mint) => { const p = this.livePositions?.positions().find((x) => x.mint === mint); return p?.tokensRaw ?? 0n; },
186
+ now: this.now, onChange: () => this.onChange('ticket'), onSettled: (tx) => this.onSettled(tx),
199
187
  });
200
188
  this.ticket = t;
201
- if (mode === 'live')
202
- t.setMode('live');
203
189
  return t;
204
190
  }
205
- /**
206
- * The signer process (task-1328), started on first use with the run's caps argv. A signer that
207
- * failed to start or died is never respawned: LIVE stays off until dexterm restarts (fail closed).
208
- */
209
- ensureSigner() {
210
- if (!this.trade || this.signerFailed)
211
- return this.signer;
212
- if (!this.signer) {
213
- try {
214
- this.signer = this.trade.createSigner ? this.trade.createSigner() : new SignerClient({ argv: this.trade.signerArgv ?? [], log: this.onLog ? (l) => this.onLog?.(` signer ${l}\n`) : undefined });
215
- }
216
- catch (e) {
217
- this.signerFailed = e instanceof Error ? e.message : String(e);
218
- return null;
219
- }
220
- }
221
- return this.signer;
222
- }
223
191
  /** `/wallet …` typed in the app (task-1328). Returns the line to show. */
224
192
  async walletCommand(cmd) {
225
193
  const paths = this.trade?.paths ?? {};
226
194
  switch (cmd) {
227
195
  case 'status': {
228
- const linked = this.linkedWallet ? `linked: ${shortPubkey(this.linkedWallet.publicKey)}` : 'no wallet linked (/wallet link)';
196
+ const linked = this.linkedWallet ? `linked: ${shortPubkey(this.linkedWallet.publicKey)} (public key only)` : 'no wallet linked (/wallet link)';
229
197
  const ks = new KillSwitch(paths.panic ?? defaultPanicPath()).engaged();
230
- const s = this.signer?.alive ? await this.signer.status().catch(() => null) : null;
231
- if (s) {
232
- const caps = s.caps;
233
- return `${linked} · signer ${s.network.toUpperCase()} (${s.rpcHost}) · $${caps.perTradeUsd}/trade $${caps.dailyUsd}/day · spent $${s.spentTodayUsd.toFixed(2)}${s.panic || s.ledgerLocked ? ' · ⛔ PANICKED' : ''}`;
234
- }
235
- return `${linked} · signer ${this.signer ? (this.signerFailed ?? 'stopped') : 'not started (starts on the first LIVE plan)'}${ks ? ' · ⛔ PANICKED' : ''}${this.trade ? '' : ' · live trading off in this run'}`;
198
+ return `${linked}${ks ? ' · ⛔ PANICKED' : ''} · dexterm holds no key and signs nothing`;
236
199
  }
237
200
  case 'link': {
238
201
  if (!this.trade)
239
- return 'live trading is off in this run';
240
- const bridge = new WalletBridge(this.trade.open ? { open: this.trade.open } : {});
202
+ return 'wallet link is off in this run (replay / offline)';
203
+ const bridge = new WalletBridge(this.trade?.open ? { open: this.trade.open } : {});
241
204
  try {
242
205
  const res = await bridge.link();
243
- const rec = this.linkStore.set(res.publicKey, { network: 'devnet' });
206
+ const rec = this.linkStore.set(res.publicKey);
244
207
  this.linkedWallet = rec;
245
208
  this.onChange('wallet');
246
- return `linked: ${shortPubkey(rec.publicKey)} (public key only) · L on a ticket for LIVE`;
209
+ return `linked: ${shortPubkey(rec.publicKey)} (public key only; dexterm never signs with it)`;
247
210
  }
248
211
  catch (e) {
249
212
  return `wallet link failed: ${e instanceof Error ? e.message : String(e)}`;
@@ -252,40 +215,15 @@ export class LiveContext {
252
215
  case 'unlink': {
253
216
  const had = this.linkStore.clear();
254
217
  this.linkedWallet = null;
255
- if (this.ticket?.ticket.mode === 'live')
256
- this.ticket.setMode('paper');
257
218
  this.onChange('wallet');
258
219
  return had ? 'unlinked' : 'no wallet was linked';
259
220
  }
260
221
  case 'panic': {
261
- // Local first (the kill-switch FILE every signer re-reads + the shared ledger lock), then the signer.
222
+ // The kill-switch FILE every autotrade runner and the paper agent desk re-read.
262
223
  const ks = new KillSwitch(paths.panic ?? defaultPanicPath());
263
224
  ks.engage('panic from dexterm UI', this.now());
264
- try {
265
- const l = new CapLedger({ path: paths.capLedger ?? defaultCapLedgerPath(), clock: this.dl.clock });
266
- try {
267
- l.lock('panic from dexterm UI', this.now());
268
- }
269
- finally {
270
- l.close();
271
- }
272
- }
273
- catch { /* the file alone disables trading */ }
274
- if (this.signer?.alive)
275
- await this.signer.panic('panic from dexterm UI').catch(() => { });
276
- if (this.ticket?.ticket.mode === 'live') {
277
- this.ticket.ticket.phase = 'refused';
278
- this.ticket.ticket.message = '⛔ PANIC — live signing disabled';
279
- }
280
225
  this.onChange('wallet');
281
- return '⛔ PANIC: live signing disabled everywhere · re-enable only from a shell: dexterm wallet resume';
282
- }
283
- case 'probe': {
284
- if (!this.trade)
285
- return 'live trading is off in this run';
286
- const t = this.openTicket({ mint: this.WSOL, symbol: 'SOL', decimals: 9 }, 'buy');
287
- const why = t.startProbe();
288
- return why ?? 'devnet probe: review the plan, then Y to sign the wrap-and-unwrap in Phantom (fees only)';
226
+ return '⛔ PANIC: autotrade runs and the paper agent desk halted · clear it only from a shell: dexterm wallet resume';
289
227
  }
290
228
  }
291
229
  return '';
@@ -332,13 +270,17 @@ export class LiveContext {
332
270
  }
333
271
  catch { /* keep the last value */ }
334
272
  }
335
- /** The fast set = the open token first, then the watchlist (the fast lane caps and drops the rest). */
273
+ /** task-1473: a coin the followed agent holds (PAPER): kept in the fast set so its mark survives list changes. */
274
+ heldMint = null;
275
+ /** The fast set = the open token first, then a followed agent's held coin, then the watchlist (the fast lane caps and drops the rest). */
336
276
  syncFastSet() {
337
277
  if (!this.fastLane)
338
278
  return;
339
279
  const mints = [];
340
280
  if (this.token)
341
281
  mints.push(this.token.mint);
282
+ if (this.heldMint && !mints.includes(this.heldMint))
283
+ mints.push(this.heldMint);
342
284
  for (const e of this.watchStore.list())
343
285
  if (!mints.includes(e.mint))
344
286
  mints.push(e.mint);
@@ -556,10 +498,6 @@ export class LiveContext {
556
498
  this.social.close();
557
499
  }
558
500
  catch { /* ignore */ }
559
- try {
560
- this.signer?.close();
561
- }
562
- catch { /* ignore */ }
563
501
  try {
564
502
  this.intel.close();
565
503
  }
@@ -125,7 +125,7 @@ export function renderNewPairsLive(c, state, live) {
125
125
  } },
126
126
  ];
127
127
  if (rows.length)
128
- table(c, box.x + 1, box.y, box.w - 2, box.h, { columns: cols, rows, selected: sel, scroll: 0, bg: box.bg });
128
+ table(c, box.x + 1, box.y, box.w - 2, box.h, { columns: cols, rows, selected: sel, scroll: 0, bg: box.bg, rowKey: (r) => r.mint });
129
129
  else {
130
130
  const s = st.stream;
131
131
  const msg = st.mode === 'off' ? 'push feed off · r to poll jup recent' : s?.state === 'open' ? `connected to pumpportal · waiting for the first create (≈15/min measured)` : `pumpportal ${s?.state ?? 'connecting'}${s?.lastError ? ` · ${s.lastError}` : ''} · polling jup recent`;
@@ -14,11 +14,12 @@ import { renderScanWhy, renderScanTicker } from "../../scan/ui.js";
14
14
  import { drawCoin, imagesOn } from "../../screens/coin.js";
15
15
  import { COIN_HERO_W, COIN_HERO_H } from '../../../../tui/src/index.js';
16
16
  import { renderSocialPanel } from "../../screens/social-panel.js";
17
+ import { brainFor, factsFromView, renderBrainPanel } from "../../screens/brain.js";
17
18
  import { launchIntelCells, holderTags } from "../intel.js";
18
19
  import { devBookOf, devRows } from "../dev-history.js";
19
20
  import { EX_POOL_TAGS } from '../../../../data/src/index.js';
20
21
  import { layoutFor } from "../../custom.js";
21
- import { chartMode, priceModeOf, mcapAt, positionPriceCells } from "../../display.js";
22
+ import { chartMode, chartTitle, priceModeOf, chartAxisOf, chartMarkersOn, mcapAt, positionPriceCells, levelCell, supplyRatio } from "../../display.js";
22
23
  const dash = '—';
23
24
  const EX_POOL_TAG_SET = EX_POOL_TAGS;
24
25
  /** task-1367 holder-class badge colours: venues/escrows accent, the creator/linked warn, the rest muted. */
@@ -87,13 +88,13 @@ export function renderTokenLive(c, state, v) {
87
88
  const shownPx = livePx ?? v.price;
88
89
  // task-1366: mcap mode leads with the market cap (the live price × the polled supply ratio) and keeps the price beside it;
89
90
  // without a supply it shows the price and says so.
90
- const cm = chartMode(priceModeOf(state), v.price, v.mcap);
91
- if (cm.kind === 'mcap' && shownPx !== null) {
92
- x = c.text(x0, y, fmtMcap(mcapAt(shownPx, cm.scale)), { fg: t.text, bg: t.bg, b: true });
91
+ const pm = chartMode(priceModeOf(state), v.price, v.mcap);
92
+ if (pm.kind === 'mcap' && shownPx !== null) {
93
+ x = c.text(x0, y, fmtMcap(mcapAt(shownPx, pm.scale)), { fg: t.text, bg: t.bg, b: true });
93
94
  x = c.text(x + 1, y, `(${fmtPrice(shownPx)})`, { fg: t.dim, bg: t.bg });
94
95
  }
95
96
  else
96
- x = c.text(x0, y, shownPx === null ? dash : fmtPrice(shownPx), { fg: cm.label && shownPx !== null ? t.warn : t.text, bg: t.bg, b: true });
97
+ x = c.text(x0, y, shownPx === null ? dash : fmtPrice(shownPx), { fg: pm.label && shownPx !== null ? t.warn : t.text, bg: t.bg, b: true });
97
98
  if (state.live?.fastLane)
98
99
  x = badge(c, x + 1, y, liveBadge, liveBadge === 'LIVE' ? t.up : t.muted, { on: t.bg });
99
100
  const deltas = [['5m', v.chg.m5], ['1h', v.chg.h1], ['6h', v.chg.h6], ['24h', v.chg.h24]];
@@ -131,20 +132,28 @@ export function renderTokenLive(c, state, v) {
131
132
  const chartH = Math.max(10, Math.floor((bottom - y - posH) * lay.chartFrac));
132
133
  const cp = v.panels.candles;
133
134
  const chartCap = clip(cp.state === 'ok' || cp.fetchedAt !== null ? `ohlcv: geckoterminal${cp.stale || cp.state === 'error' ? ' · stale' : ''}` : panelCaption(cp, now, 'ohlcv unavailable'), 40);
134
- const cb = c.box(0, y, mainW, chartH, { title: cm.label ? (cm.kind === 'mcap' ? `${v.symbol} ${cm.label} · ${v.interval}` : `${v.symbol}/USD · ${cm.label} · ${v.interval}`) : `${v.symbol}/USD · ${v.interval}`, caption: chartCap, captionFg: cp.state === 'error' && cp.fetchedAt === null ? t.warn : undefined });
135
+ // task-1472: the chart's Y axis is its own setting (default MARKET CAP, `A` toggles); the header above keeps `$`.
136
+ const cm = chartMode(chartAxisOf(state), v.price, v.mcap);
137
+ const cb = c.box(0, y, mainW, chartH, { title: chartTitle(v.symbol, v.interval, cm), caption: chartCap, captionFg: cp.state === 'error' && cp.fetchedAt === null ? t.warn : undefined });
135
138
  // timeframe tabs sit on the top border, left of the caption (same spot as the fixture screen)
136
139
  let tx = cb.x + cb.w - 2 - (chartCap.length + 4) - INTERVALS.reduce((s, f) => s + f.length + 1, 0);
137
140
  for (const f of INTERVALS)
138
141
  tx = c.text(tx, cb.y - 1, f, f === v.interval ? { fg: t.accent, bg: cb.bg, b: true } : { fg: t.dim, bg: cb.bg }) + 1;
142
+ // task-1483: BUY / SELL markers for every paper + live fill of this coin (the ledgers, no fetch) and the open position's
143
+ // average entry as a dashed line (the position row's own figure); `display.chartMarkers off` hides them.
144
+ const trades = chartMarkersOn(state) ? { fills: state.live?.chartFills?.for(v.mint) ?? [], avgEntry: prow && prow.avgEntryUsd !== null ? { usd: prow.avgEntryUsd, source: held?.kind ?? src?.kind ?? 'paper' } : null } : null;
139
145
  if (v.candles.length)
140
- candleChart(c, cb.x + 1, cb.y, cb.w - 2, cb.h, v.candles, { bg: cb.bg, interval: v.interval, scale: cm.scale ?? undefined, axisFmt: cm.axisFmt });
146
+ candleChart(c, cb.x + 1, cb.y, cb.w - 2, cb.h, v.candles, { bg: cb.bg, interval: v.interval, scale: cm.scale ?? undefined, axisFmt: cm.axisFmt, trades });
141
147
  else
142
148
  c.textC(cb.x, cb.y + Math.floor(cb.h / 2), cb.w, cp.state === 'loading' ? 'loading candles…' : `no candles · ${cp.reason ?? 'source did not answer'}`, { fg: t.muted, bg: cb.bg, i: true });
143
149
  y += chartH;
144
150
  if (prow && src) {
145
- positionPanel(c, 0, y, mainW, prow, held?.kind ?? src.kind, priceModeOf(state), cm.scale);
151
+ positionPanel(c, 0, y, mainW, prow, held?.kind ?? src.kind, priceModeOf(state), pm.scale);
146
152
  y += posH;
147
153
  }
154
+ // task-1473: what the ON-CHAIN band derived this frame, for the brain view's vetting list (null under SOCIAL)
155
+ let brainTop10 = null;
156
+ let brainDev = null;
148
157
  // ---- task-1330: the SOCIAL panel (`s`) replaces the ON-CHAIN / HOLDERS band; the chart + position stay.
149
158
  if (state.tokenSocial) {
150
159
  renderSocialPanel(c, 0, y, mainW, bottom - y, state, { mint: v.mint, symbol: v.symbol, now });
@@ -182,9 +191,11 @@ export function renderTokenLive(c, state, v) {
182
191
  // 0.1.5 dev history (task-1425): the creator's recorded track record from the local recorder (keyless). The rugs
183
192
  // row sits with the other rug signals; launches / bag-exit / linked wallets follow the safety list.
184
193
  const book = devBookOf(state);
185
- const devAll = book ? devRows(book.forMint(v.mint, v.devAddress ?? null, state.live?.intel?.analysis(v.mint) ?? null)) : [];
194
+ const devAll = book ? devRows(book.forMint(v.mint, v.devAddress ?? null, state.live?.intel?.analysis(v.mint) ?? null, state.live?.intel?.entry(v.mint)?.at ?? null), now) : [];
186
195
  const devHead = devAll.slice(0, 1);
187
196
  const devTail = devAll.slice(1);
197
+ brainTop10 = tags.top10 ? tags.top10.exPool : v.top10;
198
+ brainDev = (devHead[0] ? [`${devHead[0][0]}: ${devHead[0][1]}`, devHead[0][2]] : v.devMints === null ? null : [`${v.devMints} mints by dev (jup)`, v.devMints > 3 ? 'warn' : 'ok']);
188
199
  const sniperRow = [cells.snipers.text, cells.snipers.level];
189
200
  const bundleRow = [cells.bundle.text, cells.bundle.level];
190
201
  const rows = [
@@ -201,7 +212,7 @@ export function renderTokenLive(c, state, v) {
201
212
  ['GoPlus', ...goplusRow(v)],
202
213
  ...devTail,
203
214
  ];
204
- for (const [label, val0, lvl] of rows) {
215
+ for (const [label, val0, lvl] of fitRows(rows, sb.y + sb.h - sy)) {
205
216
  if (sy >= sb.y + sb.h)
206
217
  break;
207
218
  const color = lvl === 'ok' ? t.up : lvl === 'warn' ? t.warn : lvl === 'bad' ? t.down : t.dim;
@@ -314,7 +325,7 @@ export function renderTokenLive(c, state, v) {
314
325
  c.text(hb.x + 1, hy, 'TAPE', { fg: t.dim, bg: hb.bg });
315
326
  c.textR(hb.x + 1, hy, hb.w - 2, tp.state === 'ok' || tp.fetchedAt !== null ? `geckoterminal · 20s poll${tp.stale || tp.state === 'error' ? ' · stale' : ''}` : panelCaption(tp, now, 'tape unavailable'), { fg: tp.state === 'error' && tp.fetchedAt === null ? t.warn : t.dim, bg: hb.bg });
316
327
  hy += 1;
317
- hy += tradeTape(c, hb.x + 1, hy, hb.w - 2, hb.y + hb.h - hy, v.trades, now, { bg: hb.bg });
328
+ hy += tradeTape(c, hb.x + 1, hy, hb.w - 2, hb.y + hb.h - hy, v.trades, now, { bg: hb.bg, priceFmt: (p) => levelCell(priceModeOf(state), supplyRatio(v.price, v.mcap), p) }); // task-1537
318
329
  }
319
330
  else if (flow) {
320
331
  c.text(hb.x + 1, hy, 'BUY/SELL FLOW', { fg: t.dim, bg: hb.bg });
@@ -327,8 +338,15 @@ export function renderTokenLive(c, state, v) {
327
338
  }
328
339
  }
329
340
  }
330
- if (showAi)
331
- analystPlaceholder(c, mainW, top, aiW, bottom - top, v, state);
341
+ if (showAi) {
342
+ // task-1473: in an auto mode (following an agent / AI scan) the panel is the BRAIN VIEW; otherwise the analyst
343
+ const facts = factsFromView(v, { top10: brainTop10, dev: brainDev, larpVerdict: state.larpByMint?.get(v.mint)?.verdict ?? null, price: shownPx, fills: trades?.fills ?? null });
344
+ const brain = brainFor(state, facts, isCalm(state.vfx), state.live?.scanMeterLabel?.() ?? '');
345
+ if (brain)
346
+ renderBrainPanel(c, mainW, top, aiW, bottom - top, brain.model, brain.opts);
347
+ else
348
+ analystPlaceholder(c, mainW, top, aiW, bottom - top, v, state);
349
+ }
332
350
  const watched = state.live?.watch?.has(v.mint) ? 'unwatch' : 'watch';
333
351
  // task-1311: `i` asks claude about this token (chat), `a` runs the paid dossier on demand, `y`
334
352
  // copies the full contract address.
@@ -379,9 +397,9 @@ function positionPanel(c, x, y, w, r, kind, mode = 'price', supply = null) {
379
397
  if (r.realizedSol !== 0)
380
398
  cols.push({ label: 'REALIZED', value: usd && r.realizedUsd !== null ? signedUsd(r.realizedUsd) : `${signedSol(r.realizedSol)} SOL`, st: { fg: pnlColor(r.realizedSol), bg }, prio: 2 });
381
399
  if (r.stopUsd !== null)
382
- cols.push({ label: 'STOP', value: `${fmtPrice(r.stopUsd)}${r.stopDistPct !== null ? ` ${signedPctOf(r.stopDistPct)}` : ''}`, st: { fg: t.down, bg }, prio: 3 });
400
+ cols.push({ label: 'STOP', value: `${levelCell(mode, supply, r.stopUsd)}${r.stopDistPct !== null ? ` ${signedPctOf(r.stopDistPct)}` : ''}`, st: { fg: t.down, bg }, prio: 3 });
383
401
  if (r.targetUsd !== null)
384
- cols.push({ label: 'TARGET', value: `${fmtPrice(r.targetUsd)}${r.targetDistPct !== null ? ` ${signedPctOf(r.targetDistPct)}` : ''}`, st: { fg: t.up, bg }, prio: 3 });
402
+ cols.push({ label: 'TARGET', value: `${levelCell(mode, supply, r.targetUsd)}${r.targetDistPct !== null ? ` ${signedPctOf(r.targetDistPct)}` : ''}`, st: { fg: t.up, bg }, prio: 3 });
385
403
  const gap = 3;
386
404
  const widthOf = (list) => list.reduce((s, k) => s + Math.max(k.label.length, k.value.length) + gap, -gap);
387
405
  const inner = box.w - 2;
@@ -402,6 +420,21 @@ function positionPanel(c, x, y, w, r, kind, mode = 'price', supply = null) {
402
420
  function clip(s, max) {
403
421
  return s.length > max ? s.slice(0, Math.max(1, max - 1)) + '…' : s;
404
422
  }
423
+ /**
424
+ * task-1463: the ON-CHAIN rows for a panel `space` lines tall. When they all fit they are returned unchanged. When
425
+ * they do not, a short panel must not drop a red flag silently (e.g. `Dev rugs 2/3`, the last rows of the list):
426
+ * bad rows are kept first, then warn rows, then the rest in order, the kept rows stay in their order, and the last
427
+ * line says how many rows are hidden.
428
+ */
429
+ export function fitRows(rows, space) {
430
+ if (rows.length <= space || space <= 0)
431
+ return rows;
432
+ const slots = space - 1;
433
+ const rank = (l) => (l === 'bad' ? 0 : l === 'warn' ? 1 : 2);
434
+ const keep = new Set(rows.map((r, i) => [rank(r[2]), i]).sort((a, b) => a[0] - b[0] || a[1] - b[1]).slice(0, slots).map(([, i]) => i));
435
+ const hidden = rows.length - keep.size;
436
+ return [...rows.filter((_, i) => keep.has(i)), [`+${hidden} rows hidden`, 'taller window', 'na']];
437
+ }
405
438
  /** Token amounts up to trillions (fmtNum stops at B). */
406
439
  function fmtAmt(n) {
407
440
  if (n >= 1e12)
@@ -89,7 +89,7 @@ export function renderWatchlistLive(c, state, live) {
89
89
  } });
90
90
  }
91
91
  if (rows.length)
92
- table(c, box.x + 1, box.y, box.w - 2, box.h, { columns: promoteMcap(cols, mode), rows, selected: sel, bg: box.bg });
92
+ table(c, box.x + 1, box.y, box.w - 2, box.h, { columns: promoteMcap(cols, mode), rows, selected: sel, bg: box.bg, rowKey: (r) => r.entry.mint });
93
93
  else
94
94
  c.textC(box.x, box.y + Math.min(3, Math.floor(box.h / 2)), box.w, 'watchlist is empty · press w on any token (screener, new pairs, token screen) to add it', { fg: t.muted, bg: box.bg, i: true });
95
95
  const y2 = top + listH;