dexterm-cli 0.1.6 → 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 (331) hide show
  1. package/dist/packages/agents/src/schema.js +22 -1
  2. package/dist/packages/agents/src/story.js +11 -2
  3. package/dist/packages/agents/src/tiers.js +27 -2
  4. package/dist/packages/agents/src/tools.js +30 -2
  5. package/dist/packages/autotrade/assets/exit-profile.schema.json +492 -0
  6. package/dist/packages/autotrade/assets/profiles/moonbag.json +46 -0
  7. package/dist/packages/autotrade/assets/profiles/runner.json +88 -0
  8. package/dist/packages/autotrade/assets/profiles/scalp.json +88 -0
  9. package/dist/packages/autotrade/assets/profiles/swing.json +88 -0
  10. package/dist/packages/autotrade/assets/strategies/moonbag.json +101 -0
  11. package/dist/packages/autotrade/assets/strategies/runner.json +101 -0
  12. package/dist/packages/autotrade/assets/strategies/sample-dip-ladder.json +188 -0
  13. package/dist/packages/autotrade/assets/strategies/scalp.json +98 -0
  14. package/dist/packages/autotrade/assets/strategies/swing.json +97 -0
  15. package/dist/packages/autotrade/assets/strategies/yolo.json +157 -0
  16. package/dist/packages/autotrade/assets/tapes/yolo-rehearsal.json +1 -0
  17. package/dist/packages/autotrade/src/account.js +74 -0
  18. package/dist/packages/autotrade/src/backtest.js +357 -0
  19. package/dist/packages/autotrade/src/basis-text.js +32 -0
  20. package/dist/packages/autotrade/src/chat/approvals.js +484 -0
  21. package/dist/packages/autotrade/src/chat/audit.js +140 -0
  22. package/dist/packages/autotrade/src/chat/config.js +93 -0
  23. package/dist/packages/autotrade/src/chat/connector.js +24 -0
  24. package/dist/packages/autotrade/src/chat/control.js +103 -0
  25. package/dist/packages/autotrade/src/chat/fake.js +100 -0
  26. package/dist/packages/autotrade/src/chat/format.js +71 -0
  27. package/dist/packages/autotrade/src/chat/hub.js +187 -0
  28. package/dist/packages/autotrade/src/chat/index.js +18 -0
  29. package/dist/packages/autotrade/src/chat/notify.js +292 -0
  30. package/dist/packages/autotrade/src/chat/pairing.js +46 -0
  31. package/dist/packages/autotrade/src/chat/redact.js +48 -0
  32. package/dist/packages/autotrade/src/chat/secrets.js +99 -0
  33. package/dist/packages/autotrade/src/chat/service.js +248 -0
  34. package/dist/packages/autotrade/src/chat/telegram.js +290 -0
  35. package/dist/packages/autotrade/src/desk-executor.js +188 -0
  36. package/dist/packages/autotrade/src/engine.js +387 -0
  37. package/dist/packages/autotrade/src/execution-port.js +97 -0
  38. package/dist/packages/autotrade/src/fleet-config.js +169 -0
  39. package/dist/packages/autotrade/src/fleet-control.js +276 -0
  40. package/dist/packages/autotrade/src/fleet.js +639 -0
  41. package/dist/packages/autotrade/src/index.js +53 -0
  42. package/dist/packages/autotrade/src/ledger.js +108 -0
  43. package/dist/packages/autotrade/src/live-source.js +182 -0
  44. package/dist/packages/autotrade/src/monitor-daemon.js +715 -0
  45. package/dist/packages/autotrade/src/monitor.js +190 -0
  46. package/dist/packages/autotrade/src/ollama-sessions.js +137 -0
  47. package/dist/packages/autotrade/src/paper-accounts.js +72 -0
  48. package/dist/packages/autotrade/src/replay.js +198 -0
  49. package/dist/packages/autotrade/src/runner-config.js +99 -0
  50. package/dist/packages/autotrade/src/runner.js +872 -0
  51. package/dist/packages/autotrade/src/safety.js +243 -0
  52. package/dist/packages/autotrade/src/session.js +269 -0
  53. package/dist/packages/autotrade/src/sessions.js +503 -0
  54. package/dist/packages/autotrade/src/store.js +250 -0
  55. package/dist/packages/autotrade/src/strategy.js +256 -0
  56. package/dist/packages/autotrade/src/trade-ledger.js +241 -0
  57. package/dist/packages/autotrade/src/yolo.js +140 -0
  58. package/dist/packages/cli/assets/claude/analyst-system.md +4 -4
  59. package/dist/packages/cli/assets/claude/plugin/skills/token-dossier/SKILL.md +1 -1
  60. package/dist/packages/cli/src/ai-cmd.js +412 -0
  61. package/dist/packages/cli/src/analyst/backend.js +82 -15
  62. package/dist/packages/cli/src/analyst/codex.js +14 -9
  63. package/dist/packages/cli/src/analyst/ollama.js +263 -0
  64. package/dist/packages/cli/src/analyst/session.js +5 -2
  65. package/dist/packages/cli/src/app-help-gen.js +44 -8
  66. package/dist/packages/cli/src/autotrade-cmd/audit.js +57 -0
  67. package/dist/packages/cli/src/autotrade-cmd/backtest.js +199 -0
  68. package/dist/packages/cli/src/autotrade-cmd/flatten.js +64 -0
  69. package/dist/packages/cli/src/autotrade-cmd/fleet.js +397 -0
  70. package/dist/packages/cli/src/autotrade-cmd/requests.js +79 -0
  71. package/dist/packages/cli/src/autotrade-cmd/run.js +413 -0
  72. package/dist/packages/cli/src/autotrade-cmd/stop.js +76 -0
  73. package/dist/packages/cli/src/autotrade-cmd/strategies.js +198 -0
  74. package/dist/packages/cli/src/autotrade-cmd/strategy-control.js +174 -0
  75. package/dist/packages/cli/src/autotrade-cmd/telegram-host.js +101 -0
  76. package/dist/packages/cli/src/autotrade-cmd.js +168 -0
  77. package/dist/packages/cli/src/display.js +156 -17
  78. package/dist/packages/cli/src/doctor.js +62 -3
  79. package/dist/packages/cli/src/export.js +10 -2
  80. package/dist/packages/cli/src/index.js +1 -1
  81. package/dist/packages/cli/src/ledger-cmd.js +288 -0
  82. package/dist/packages/cli/src/live/chart-fills.js +46 -0
  83. package/dist/packages/cli/src/live/index.js +23 -89
  84. package/dist/packages/cli/src/live/screens/token-live.js +9 -6
  85. package/dist/packages/cli/src/live/trade.js +12 -457
  86. package/dist/packages/cli/src/live/watchlist.js +1 -1
  87. package/dist/packages/cli/src/main.js +147 -190
  88. package/dist/packages/cli/src/mcp-cmd.js +7 -1
  89. package/dist/packages/cli/src/plan-cmd.js +1 -1
  90. package/dist/packages/cli/src/pnl-app.js +31 -21
  91. package/dist/packages/cli/src/pnl-card.js +158 -21
  92. package/dist/packages/cli/src/popup.js +22 -6
  93. package/dist/packages/cli/src/record-cmd.js +141 -20
  94. package/dist/packages/cli/src/screens/agent-hud.js +34 -2
  95. package/dist/packages/cli/src/screens/analyst-session.js +7 -4
  96. package/dist/packages/cli/src/screens/analyst.js +3 -2
  97. package/dist/packages/cli/src/screens/autotrade-keys.js +169 -0
  98. package/dist/packages/cli/src/screens/autotrade-proposals.js +123 -0
  99. package/dist/packages/cli/src/screens/autotrade-screen.js +725 -0
  100. package/dist/packages/cli/src/screens/autotrade-ui.js +640 -0
  101. package/dist/packages/cli/src/screens/autotrade-worker.js +89 -0
  102. package/dist/packages/cli/src/screens/brain.js +37 -11
  103. package/dist/packages/cli/src/screens/overlay.js +5 -2
  104. package/dist/packages/cli/src/screens/plans.js +5 -17
  105. package/dist/packages/cli/src/screens/pnl-chip.js +9 -8
  106. package/dist/packages/cli/src/screens/positions.js +6 -28
  107. package/dist/packages/cli/src/screens/ticket.js +38 -205
  108. package/dist/packages/cli/src/screens/token.js +3 -3
  109. package/dist/packages/cli/src/state.js +25 -19
  110. package/dist/packages/cli/src/telegram-cmd.js +451 -0
  111. package/dist/packages/cli/src/trade.js +3 -128
  112. package/dist/packages/cli/src/version.js +1 -1
  113. package/dist/packages/cli/src/wallet-cmd.js +39 -340
  114. package/dist/packages/cli/src/wallet-command.js +8 -11
  115. package/dist/packages/cli/src/widgets.js +0 -12
  116. package/dist/packages/custom/src/config.js +20 -2
  117. package/dist/packages/custom/src/schema.js +35 -10
  118. package/dist/packages/custom/src/workspace.js +3 -3
  119. package/dist/packages/data/src/basis.js +191 -0
  120. package/dist/packages/data/src/detail.js +53 -2
  121. package/dist/packages/data/src/index.js +0 -14
  122. package/dist/packages/data/src/store.js +14 -5
  123. package/dist/packages/data/src/trade/agent/paper-desk.js +228 -16
  124. package/dist/packages/data/src/trade/agent/rendezvous.js +3 -2
  125. package/dist/packages/data/src/trade/bridge.js +4 -102
  126. package/dist/packages/data/src/trade/ledger/export.js +101 -0
  127. package/dist/packages/data/src/trade/ledger/file.js +135 -0
  128. package/dist/packages/data/src/trade/ledger/fold.js +191 -0
  129. package/dist/packages/data/src/trade/ledger/index.js +9 -0
  130. package/dist/packages/data/src/trade/ledger/schema.js +83 -0
  131. package/dist/packages/data/src/trade/ledger/sources.js +307 -0
  132. package/dist/packages/data/src/trade/ledger/stats.js +123 -0
  133. package/dist/packages/data/src/trade/ledger/tags.js +116 -0
  134. package/dist/packages/data/src/trade/ledger/view.js +51 -0
  135. package/dist/packages/data/src/trade/plans/index.js +0 -1
  136. package/dist/packages/data/src/trade/plans/service.js +3 -27
  137. package/dist/packages/mcp/assets/kb/app-help/autotrade-chat.md +48 -0
  138. package/dist/packages/mcp/assets/kb/app-help/autotrade-parallel.md +42 -0
  139. package/dist/packages/mcp/assets/kb/app-help/autotrade-runner.md +35 -0
  140. package/dist/packages/mcp/assets/kb/app-help/autotrade-stop.md +37 -0
  141. package/dist/packages/mcp/assets/kb/app-help/autotrade-strategies.md +35 -0
  142. package/dist/packages/mcp/assets/kb/app-help/autotrade-telegram.md +40 -0
  143. package/dist/packages/mcp/assets/kb/app-help/chart-trade-markers.md +42 -0
  144. package/dist/packages/mcp/assets/kb/app-help/link-a-wallet.md +4 -10
  145. package/dist/packages/mcp/assets/kb/app-help/live-trading.md +38 -0
  146. package/dist/packages/mcp/assets/kb/app-help/live-yolo.md +34 -0
  147. package/dist/packages/mcp/assets/kb/app-help/order-plans.md +1 -1
  148. package/dist/packages/mcp/assets/kb/app-help/price-or-marketcap.md +5 -2
  149. package/dist/packages/mcp/assets/kb/app-help/screen-analyst.md +3 -0
  150. package/dist/packages/mcp/assets/kb/app-help/screen-autotrade.md +217 -0
  151. package/dist/packages/mcp/assets/kb/app-help/screen-kol.md +3 -0
  152. package/dist/packages/mcp/assets/kb/app-help/screen-newpairs.md +3 -0
  153. package/dist/packages/mcp/assets/kb/app-help/screen-positions.md +3 -0
  154. package/dist/packages/mcp/assets/kb/app-help/screen-screener.md +3 -0
  155. package/dist/packages/mcp/assets/kb/app-help/screen-token.md +3 -0
  156. package/dist/packages/mcp/assets/kb/app-help/screen-trending.md +3 -0
  157. package/dist/packages/mcp/assets/kb/app-help/screen-watchlist.md +3 -0
  158. package/dist/packages/mcp/assets/kb/app-help/standing-mandates.md +1 -1
  159. package/dist/packages/mcp/assets/kb/app-help/trade-ledger.md +54 -0
  160. package/dist/packages/mcp/assets/kb/app-help/use-local-model.md +38 -0
  161. package/dist/packages/mcp/assets/kb/docs/docs-agents-agent-paper-trading.md +4 -1
  162. package/dist/packages/mcp/assets/kb/docs/docs-agents-reading-your-trade-ledger.md +31 -0
  163. package/dist/packages/mcp/assets/kb/docs/docs-agents-untrusted-by-default.md +1 -1
  164. package/dist/packages/mcp/assets/kb/docs/docs-analyst-if-claude-is-missing.md +1 -1
  165. package/dist/packages/mcp/assets/kb/docs/docs-analyst-use-a-local-model-instead.md +27 -0
  166. package/dist/packages/mcp/assets/kb/docs/docs-analyst-what-it-sees.md +2 -0
  167. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-backtests-and-their-limits.md +56 -0
  168. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-change-a-strategy-by-chat.md +49 -0
  169. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-checking-the-record-of-a-run.md +28 -0
  170. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-comparing-them.md +41 -0
  171. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-exits-and-wakes.md +76 -0
  172. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-how-a-stop-reaches-the-runner.md +32 -0
  173. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-on-the-q-screen.md +37 -0
  174. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-one-strategy-or-all-of-them.md +35 -0
  175. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-paper-accounts.md +50 -0
  176. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-presets.md +37 -0
  177. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-running-it-all-day.md +31 -0
  178. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-sessions-and-their-limits.md +31 -0
  179. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-several-strategies-at-once.md +33 -0
  180. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-stopping-it.md +35 -0
  181. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-strategies-and-presets.md +34 -0
  182. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-autotrade-json-file.md +48 -0
  183. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-heartbeat.md +27 -0
  184. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-run-file-and-the-heartbeat.md +34 -0
  185. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-runner-and-candidate-sessions.md +45 -0
  186. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-each-session-shows-first.md +31 -0
  187. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-costs-claude-usage-per-session.md +58 -0
  188. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-is-paper-self-directed.md +43 -0
  189. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-will-not-do.md +31 -0
  190. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-which-account-day-caps-and-the-usage-guard.md +44 -0
  191. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-your-strategies.md +37 -0
  192. package/dist/packages/mcp/assets/kb/docs/docs-autotrade.md +22 -0
  193. package/dist/packages/mcp/assets/kb/docs/docs-beginners-before-any-experimental-trading.md +2 -2
  194. package/dist/packages/mcp/assets/kb/docs/docs-beginners.md +1 -1
  195. package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-markers.md +30 -0
  196. package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-y-axis.md +1 -1
  197. package/dist/packages/mcp/assets/kb/docs/docs-configuration-environment-variables.md +4 -1
  198. package/dist/packages/mcp/assets/kb/docs/docs-configuration-files-on-disk.md +1 -0
  199. package/dist/packages/mcp/assets/kb/docs/docs-configuration-headless-recorder-dexterm-record.md +3 -1
  200. package/dist/packages/mcp/assets/kb/docs/docs-configuration-price-display-mode.md +8 -6
  201. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-2-the-one-key-mirror-ticket-a-proposal.md +1 -1
  202. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-3-capped-auto-mirror-default-off-less.md +1 -1
  203. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-what-is-proven-what-is-not.md +1 -1
  204. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading.md +1 -1
  205. package/dist/packages/mcp/assets/kb/docs/docs-data-sources-recorded-history-and-retention.md +36 -0
  206. package/dist/packages/mcp/assets/kb/docs/docs-data-sources-sources.md +1 -0
  207. package/dist/packages/mcp/assets/kb/docs/docs-getting-started-first-run.md +1 -1
  208. package/dist/packages/mcp/assets/kb/docs/docs-getting-started-install.md +3 -3
  209. package/dist/packages/mcp/assets/kb/docs/docs-getting-started-requirements.md +1 -1
  210. package/dist/packages/mcp/assets/kb/docs/docs-getting-started.md +1 -1
  211. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-changed-in-0-1-7.md +26 -0
  212. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-stopping.md +28 -0
  213. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-the-short-version.md +34 -0
  214. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-using-a-trading-bot-with-dexterm.md +33 -0
  215. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does-not-do.md +30 -0
  216. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does.md +29 -0
  217. package/dist/packages/mcp/assets/kb/docs/docs-live-trading.md +23 -0
  218. package/dist/packages/mcp/assets/kb/docs/docs-ollama-another-machine.md +28 -0
  219. package/dist/packages/mcp/assets/kb/docs/docs-ollama-autotrade-on-a-local-model.md +29 -0
  220. package/dist/packages/mcp/assets/kb/docs/docs-ollama-check-your-model-dexterm-ai-probe.md +38 -0
  221. package/dist/packages/mcp/assets/kb/docs/docs-ollama-how-we-checked.md +27 -0
  222. package/dist/packages/mcp/assets/kb/docs/docs-ollama-models-without-tool-calling.md +32 -0
  223. package/dist/packages/mcp/assets/kb/docs/docs-ollama-pick-the-engine-globally-or-per-surface.md +43 -0
  224. package/dist/packages/mcp/assets/kb/docs/docs-ollama-restriction-profiles.md +35 -0
  225. package/dist/packages/mcp/assets/kb/docs/docs-ollama-set-it-up-in-two-minutes.md +39 -0
  226. package/dist/packages/mcp/assets/kb/docs/docs-ollama-troubleshooting.md +35 -0
  227. package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-runs-on-a-local-model.md +39 -0
  228. package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-stays-outside-the-model.md +36 -0
  229. package/dist/packages/mcp/assets/kb/docs/docs-ollama-which-model.md +38 -0
  230. package/dist/packages/mcp/assets/kb/docs/docs-ollama-your-own-agent-on-the-local-model.md +28 -0
  231. package/dist/packages/mcp/assets/kb/docs/docs-ollama.md +28 -0
  232. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-letting-an-agent-paper-trade-experimental.md +3 -4
  233. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet-read-only.md +30 -0
  234. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-order-plans-and-standing-mandates.md +3 -4
  235. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-panic.md +4 -7
  236. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-paper-only-mandates.md +6 -7
  237. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-pnl-cards.md +7 -7
  238. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-safety-model.md +34 -0
  239. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-ticket.md +3 -4
  240. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-trade-ledger.md +42 -0
  241. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-wallet.md +4 -5
  242. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-trade-moments.md +4 -5
  243. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading.md +4 -5
  244. package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-buy-and-sell-markers.md +37 -0
  245. package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-what-it-shows.md +2 -1
  246. package/dist/packages/mcp/assets/kb/docs/docs-screens-autotrade-paper.md +26 -0
  247. package/dist/packages/mcp/assets/kb/docs/docs-screens-order-plans.md +1 -1
  248. package/dist/packages/mcp/assets/kb/docs/docs-screens-token-screen.md +2 -0
  249. package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-brain-view-and-the-pnl-chip.md +1 -1
  250. package/dist/packages/mcp/assets/kb/docs/docs-telegram-approve-one-tap-entries.md +50 -0
  251. package/dist/packages/mcp/assets/kb/docs/docs-telegram-control-the-commands.md +43 -0
  252. package/dist/packages/mcp/assets/kb/docs/docs-telegram-if-something-goes-wrong.md +30 -0
  253. package/dist/packages/mcp/assets/kb/docs/docs-telegram-notify-what-reaches-your-phone.md +41 -0
  254. package/dist/packages/mcp/assets/kb/docs/docs-telegram-set-it-up.md +47 -0
  255. package/dist/packages/mcp/assets/kb/docs/docs-telegram-the-record.md +26 -0
  256. package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-is.md +33 -0
  257. package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-will-not-do.md +31 -0
  258. package/dist/packages/mcp/assets/kb/docs/docs-telegram.md +23 -0
  259. package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-common-questions.md +1 -1
  260. package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-doctor-lines.md +4 -0
  261. package/dist/packages/mcp/assets/kb/docs/docs-voice-linux-and-windows.md +1 -1
  262. package/dist/packages/mcp/assets/kb/docs/docs-voice.md +1 -1
  263. package/dist/packages/mcp/assets/kb/docs/docs-yolo-1-replay-it-on-your-own-history.md +42 -0
  264. package/dist/packages/mcp/assets/kb/docs/docs-yolo-2-run-it-on-paper.md +34 -0
  265. package/dist/packages/mcp/assets/kb/docs/docs-yolo-3-watch-it-and-stop-it.md +32 -0
  266. package/dist/packages/mcp/assets/kb/docs/docs-yolo-the-rules.md +37 -0
  267. package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-is.md +34 -0
  268. package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-will-not-do.md +31 -0
  269. package/dist/packages/mcp/assets/kb/docs/docs-yolo.md +26 -0
  270. package/dist/packages/mcp/assets/kb/entries/autotrade.md +38 -0
  271. package/dist/packages/mcp/src/app-help.js +1 -1
  272. package/dist/packages/mcp/src/autotrade-tools.js +944 -0
  273. package/dist/packages/mcp/src/backtest-requests.js +71 -0
  274. package/dist/packages/mcp/src/engine/config.js +159 -0
  275. package/dist/packages/mcp/src/engine/index.js +10 -0
  276. package/dist/packages/mcp/src/engine/loop.js +101 -0
  277. package/dist/packages/mcp/src/engine/mcp-client.js +123 -0
  278. package/dist/packages/mcp/src/engine/ollama.js +258 -0
  279. package/dist/packages/mcp/src/engine/probe.js +110 -0
  280. package/dist/packages/mcp/src/engine/reason.js +35 -0
  281. package/dist/packages/mcp/src/engine/restrictions.js +111 -0
  282. package/dist/packages/mcp/src/index.js +7 -1
  283. package/dist/packages/mcp/src/ledger-tools.js +346 -0
  284. package/dist/packages/mcp/src/paper-agent.js +2 -0
  285. package/dist/packages/mcp/src/server.js +127 -19
  286. package/dist/packages/packs/src/backtest.js +3 -1
  287. package/dist/packages/popup/src/pages/chart-lib.js +134 -21
  288. package/dist/packages/popup/src/pages/chart.css +9 -0
  289. package/dist/packages/popup/src/pages/chart.html +3 -1
  290. package/dist/packages/popup/src/pages/chart.js +104 -7
  291. package/dist/packages/popup/src/protocol.js +2 -0
  292. package/dist/packages/popup/src/server.js +4 -0
  293. package/dist/packages/recorder/src/index.js +2 -0
  294. package/dist/packages/recorder/src/recorder.js +63 -6
  295. package/dist/packages/recorder/src/retention.js +100 -0
  296. package/dist/packages/recorder/src/schema.js +34 -1
  297. package/dist/packages/recorder/src/ticks.js +237 -0
  298. package/dist/packages/tui/src/index.js +1 -0
  299. package/dist/packages/tui/src/keymap.js +21 -1
  300. package/dist/packages/tui/src/markers.js +219 -0
  301. package/dist/packages/tui/src/widgets.js +149 -2
  302. package/package.json +2 -1
  303. package/dist/packages/data/src/trade/caps.js +0 -323
  304. package/dist/packages/data/src/trade/executor.js +0 -933
  305. package/dist/packages/data/src/trade/plans/executor-live.js +0 -220
  306. package/dist/packages/data/src/trade/rpc-exec.js +0 -229
  307. package/dist/packages/data/src/trade/signer/client.js +0 -197
  308. package/dist/packages/data/src/trade/signer/fast-wallet.js +0 -154
  309. package/dist/packages/data/src/trade/signer/host.js +0 -97
  310. package/dist/packages/data/src/trade/signer/main.js +0 -121
  311. package/dist/packages/data/src/trade/signer/probe-builder.js +0 -85
  312. package/dist/packages/data/src/trade/signer/protocol.js +0 -92
  313. package/dist/packages/data/src/trade/signer/service.js +0 -400
  314. package/dist/packages/data/src/trade/signer/sol-usd-feed.js +0 -98
  315. package/dist/packages/data/src/trade/sol-usd.js +0 -86
  316. package/dist/packages/data/src/trade/swap-build.js +0 -108
  317. package/dist/packages/data/src/trade/token-delta.js +0 -201
  318. package/dist/packages/data/vendor/solana-web3/LICENSE +0 -20
  319. package/dist/packages/data/vendor/solana-web3/NOTICE.md +0 -13
  320. package/dist/packages/data/vendor/solana-web3/index.iife.min.js +0 -20
  321. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-a-live-ticket.md +0 -42
  322. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-before-you-press-size-vs-caps.md +0 -34
  323. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-devnet-signer-mainnet-token.md +0 -35
  324. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-jupiter-rate-limits.md +0 -33
  325. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet.md +0 -32
  326. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-live-trading-devnet-first.md +0 -30
  327. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-mainnet.md +0 -31
  328. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-live-fire-path-devnet-the-fast-wallet.md +0 -41
  329. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-signer-process.md +0 -34
  330. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-what-the-live-path-keeps.md +0 -37
  331. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-your-first-live-trade.md +0 -41
@@ -0,0 +1,89 @@
1
+ // dexterm — AUTOTRADE screen backtests off the render loop (task-1508). A lockstep backtest over two weeks of
2
+ // recorded history is CPU-bound for seconds and a sweep for much longer, so the Q screen runs them in a worker
3
+ // thread: the worker opens the recorder DB read-only, builds the tape once, runs the engine and posts the
4
+ // report back. PAPER, recorded data only: no network, no model, no keys. The same module is the worker entry
5
+ // (it checks workerData) and the main-thread client (workerJobs). Tests use inlineJobs over a fixture tape.
6
+ import { existsSync } from 'node:fs';
7
+ import { Worker, isMainThread, parentPort, workerData } from 'node:worker_threads';
8
+ import { defaultDbPath } from '../../../data/src/index.js';
9
+ import { openHistoryReadOnly } from '../../../recorder/src/index.js';
10
+ import { backtest, sweep, tapeFromDb, tapeFromDoc } from '../../../autotrade/src/index.js';
11
+ const DAY_MS = 86_400_000;
12
+ /** The equity curve is resampled to this many points before it crosses the thread boundary (it feeds a sparkline). */
13
+ const CURVE_POINTS = 240;
14
+ const TAG = 'dexterm-autotrade-job/1';
15
+ function resample(xs, n) {
16
+ if (xs.length <= n)
17
+ return xs;
18
+ return Array.from({ length: n }, (_, i) => xs[Math.round((i * (xs.length - 1)) / (n - 1))]);
19
+ }
20
+ /** The recorder's history as a tape, read-only (the same window rules as `dexterm autotrade backtest --days N`). */
21
+ export function tapeFromRecorder(dbPath, days, until) {
22
+ const none = `no recorded history in ${dbPath} (run the app with the recorder on first)`;
23
+ if (!existsSync(dbPath))
24
+ throw new Error(none);
25
+ let db;
26
+ try {
27
+ db = openHistoryReadOnly(dbPath);
28
+ }
29
+ catch {
30
+ throw new Error(none);
31
+ }
32
+ if (!db)
33
+ throw new Error(none);
34
+ try {
35
+ return tapeFromDoc(tapeFromDb(db, { since: until - days * DAY_MS, until, minPeakLiqUsd: 20_000, spanHours: 80 }));
36
+ }
37
+ finally {
38
+ db.close();
39
+ }
40
+ }
41
+ export async function backtestOn(tape, ss) {
42
+ const out = [];
43
+ for (const s of ss) {
44
+ const { report, run } = await backtest(s, tape);
45
+ out.push({ report, curve: resample(run.equityCurve.map((p) => p.equity), CURVE_POINTS) });
46
+ }
47
+ return out;
48
+ }
49
+ /** Jobs that run on the calling thread over a tape the caller supplies (tests, over a committed fixture tape). */
50
+ export function inlineJobs(tape) {
51
+ return {
52
+ backtest: async (ss) => backtestOn(tape(), ss),
53
+ sweep: async (s, grid) => sweep(s, tape(), grid),
54
+ };
55
+ }
56
+ /** Jobs in a worker thread over the recorder DB (the app). One worker per job; it exits when done. */
57
+ export function workerJobs(env = process.env) {
58
+ const dbPath = env.DEXTERM_DB_PATH || defaultDbPath(env);
59
+ const run = (job) => new Promise((resolve, reject) => {
60
+ const w = new Worker(new URL(import.meta.url), { workerData: { tag: TAG, job } });
61
+ w.unref();
62
+ w.once('message', (m) => { if (m.ok)
63
+ resolve(m.value);
64
+ else
65
+ reject(new Error(m.error)); });
66
+ w.once('error', reject);
67
+ w.once('exit', (code) => { if (code !== 0)
68
+ reject(new Error(`backtest worker exited with code ${code}`)); });
69
+ });
70
+ return {
71
+ backtest: (strategies, o) => run({ kind: 'backtest', strategies, days: o.days, until: o.until, dbPath }),
72
+ sweep: (strategy, grid, o) => run({ kind: 'sweep', strategy, grid, days: o.days, until: o.until, dbPath }),
73
+ };
74
+ }
75
+ // ───────────────────────────── worker entry ─────────────────────────────
76
+ if (!isMainThread && parentPort && workerData?.tag === TAG) {
77
+ const job = workerData.job;
78
+ const port = parentPort;
79
+ void (async () => {
80
+ try {
81
+ const tape = tapeFromRecorder(job.dbPath, job.days, job.until);
82
+ const value = job.kind === 'backtest' ? await backtestOn(tape, job.strategies) : await sweep(job.strategy, tape, job.grid);
83
+ port.postMessage({ ok: true, value });
84
+ }
85
+ catch (e) {
86
+ port.postMessage({ ok: false, error: e.message ?? String(e) });
87
+ }
88
+ })();
89
+ }
@@ -6,7 +6,8 @@
6
6
  // mode: the scan's own log plus the scan analyst's answer.
7
7
  // 2. VETTING $SYM: the checklist for the coin in focus, each box with the number the app computed and pass / warn /
8
8
  // fail / pending (pending = the number is not in yet). A ◆ marks the checks the agent itself ran.
9
- // 3. DATA: mcap, price, liquidity, 5m / 1h, buy/sell flow, holders, and a candle trace.
9
+ // 3. DATA: mcap, price, liquidity, 5m / 1h, buy/sell flow, holders, and a candle trace (task-1483: with a B / S cell
10
+ // on the candle of every paper / live fill of the coin, from the ledgers; the rest is said, never moved).
10
11
  // 4. PLAN · POSITION (only while a PAPER ticket / position exists): entry, size, TP / stop, mark PnL, peak, time held,
11
12
  // what it is waiting for.
12
13
  // 5. DECISIONS: the session log (passed X because…, rejected Y, entered Z) and the scoreboard (PAPER, simulated).
@@ -15,7 +16,7 @@
15
16
  // panel has no input. Agent text arrives scrubbed and clipped (story.ribbonText) with addresses shortened.
16
17
  // Smaller panels drop blocks in priority order (decisions, then data, then the vetting list folds to two columns);
17
18
  // calm mode shows the same information with no typing; NO_COLOR keeps meaning in glyphs (✓ ! ✗ · ◆ ❯ ›).
18
- import { mix, clock, decryptText, fmtUsd, fmtPrice, fmtNum, wrap } from '../../../tui/src/index.js';
19
+ import { mix, clock, decryptText, fmtUsd, fmtPrice, fmtMcap, fmtNum, wrap, chartMarkers, markerLetter, MARKER_PERIOD_MS } from '../../../tui/src/index.js';
19
20
  import { ribbonText, ribbonLines, fmtPx } from '../../../agents/src/index.js';
20
21
  // ---------------------------------------------------------------------------------------------------------------
21
22
  // formatting (deterministic, no locale)
@@ -73,8 +74,18 @@ export function factsFromView(v, extra = {}) {
73
74
  holders: v.holders, top10: extra.top10 ?? v.top10, mintAuth: v.mintAuth, freezeAuth: v.freezeAuth, lpLocked: v.lpLocked,
74
75
  dev: extra.dev ?? (v.devMints === null ? null : [`${v.devMints} mints by dev (jup)`, v.devMints > 3 ? 'warn' : 'ok']),
75
76
  rugScore: v.rug?.score ?? null, larpVerdict: extra.larpVerdict ?? null, closes: v.candles.map((k) => k.c),
77
+ closeTimes: v.candles.map((k) => k.t), periodMs: MARKER_PERIOD_MS[v.interval], fills: extra.fills ?? undefined,
76
78
  };
77
79
  }
80
+ /** task-1483: the trace's B / S cells for the last `width` closes (the same model as the charts; display only). */
81
+ export function traceMarks(f, width = 240) {
82
+ if (!f || !f.fills?.length || !f.closeTimes || f.closeTimes.length !== f.closes.length || !f.periodMs)
83
+ return null;
84
+ const times = f.closeTimes.slice(-width);
85
+ const set = chartMarkers(f.fills, { periodMs: f.periodMs, barTimes: times });
86
+ const off0 = f.closes.length - times.length;
87
+ return { cells: set.markers.map((m) => ({ index: off0 + m.index, side: m.side, source: m.source, count: m.count })), off: set.before + set.after + set.gap };
88
+ }
78
89
  // ---------------------------------------------------------------------------------------------------------------
79
90
  // 1) reasoning stream
80
91
  /** Agent thoughts and dexterm narration, newest last (≤ max). */
@@ -216,12 +227,18 @@ export function planFromThoughts(thoughts, since) {
216
227
  return { tp, stop };
217
228
  }
218
229
  /** The PLAN / POSITION block for the agent's PAPER arc (null when there is no ticket or position). */
219
- export function planVM(v, now) {
230
+ /** task-1537: the coin's supply from its facts (mcap ÷ price at the same tick), null when either is missing. */
231
+ function capScale(f) {
232
+ return f.mcap !== null && f.price !== null && f.price > 0 && f.mcap > 0 ? { mint: f.mint, supply: f.mcap / f.price } : null;
233
+ }
234
+ export function planVM(v, now, cap = null) {
220
235
  const a = v.arc;
221
236
  if (!a || a.stage === 'closed' || a.stage === 'refused')
222
237
  return null;
223
238
  const said = planFromThoughts(v.thoughts, a.openedAt);
224
239
  const open = a.stage === 'open';
240
+ // task-1537: entry / mark as market caps when the card's coin has a known supply, else prices
241
+ const lvl = (u) => (cap && cap.mint === a.mint ? fmtMcap(u * cap.supply) : `$${fmtPx(u)}`);
225
242
  const pnlUsd = open && a.pnlPct !== null && a.sizeUsd !== null ? a.sizeUsd * a.pnlPct : null;
226
243
  const dd = open && a.pnlPct !== null && a.peakPct !== null ? (1 + a.pnlPct) / (1 + a.peakPct) - 1 : null;
227
244
  const tp = said.tp ? `TP ${said.tp} (agent's plan)` : 'TP agent-managed';
@@ -231,12 +248,12 @@ export function planVM(v, now) {
231
248
  : said.tp ? `TP ${said.tp} · agent-managed exit, no resting order on PAPER` : 'the agent\'s exit call · no resting orders on PAPER';
232
249
  return {
233
250
  symbol: a.symbol, stage: a.stage,
234
- entry: a.entryUsd !== null ? `$${fmtPx(a.entryUsd)}` : '—',
251
+ entry: a.entryUsd !== null ? lvl(a.entryUsd) : '—',
235
252
  size: a.sizeUsd !== null ? `$${a.sizeUsd.toFixed(2)}${a.spentSol > 0 ? ` (${a.spentSol.toFixed(4)} SOL)` : ''}` : a.spentSol > 0 ? `${a.spentSol.toFixed(4)} SOL` : 'sizing…',
236
253
  tp, stop,
237
254
  pnlPct: open ? a.pnlPct : null, pnlUsd, peakPct: open ? a.peakPct : null, ddPct: dd,
238
255
  heldMs: open && a.filledAt !== null ? now - a.filledAt : null,
239
- mark: a.mark ? `$${fmtPx(a.mark.priceUsd)}` : '—',
256
+ mark: a.mark ? lvl(a.mark.priceUsd) : '—',
240
257
  waiting, trace: a.trace.map((s) => s.pct),
241
258
  refused: open && a.refusal && v.beats.refusedAt !== null && now - v.beats.refusedAt < 3500 ? a.refusal : null,
242
259
  };
@@ -261,15 +278,15 @@ export function scanLogLines(log, tz) {
261
278
  }
262
279
  // ---------------------------------------------------------------------------------------------------------------
263
280
  // the whole model
264
- export function agentBrainModel(v, facts, now, tz) {
281
+ export function agentBrainModel(v, facts, now, tz, mcap = false) {
265
282
  const s = agentStream(v, tz);
266
283
  const status = v.control === 'paused' ? '❚❚ paused by you · its next call is held' : v.control === 'takeover' ? 'you are driving · the agent is frozen' : null;
267
284
  return {
268
285
  mode: 'agent', title: `✦ BRAIN · ${v.agent}`, streamLabel: s.label, demo: s.demo, stream: s.lines, status,
269
286
  coin: facts ? { symbol: facts.symbol, mint: facts.mint } : v.focus ? { symbol: v.focus.symbol, mint: v.focus.mint } : null,
270
287
  vet: facts ? vetRows(facts, v.focus) : [],
271
- data: facts ? dataCells(facts) : [], closes: facts?.closes ?? [],
272
- plan: planVM(v, now), log: decisionLog(v, tz), score: scoreLine(v.score),
288
+ data: facts ? dataCells(facts) : [], closes: facts?.closes ?? [], marks: traceMarks(facts),
289
+ plan: planVM(v, now, mcap && facts ? capScale(facts) : null), log: decisionLog(v, tz), score: scoreLine(v.score),
273
290
  };
274
291
  }
275
292
  export function scanBrainModel(s, facts, tz) {
@@ -279,7 +296,7 @@ export function scanBrainModel(s, facts, tz) {
279
296
  mode: 'scan', title: '✦ BRAIN · AI scan', streamLabel: 'scan log + the scan analyst (observe-only)', demo: false,
280
297
  stream: scanStream(s.log, s.answer, tz), status: `◉ ${s.mode}${s.lock ? ` $${s.lock.symbol} · score ${s.lock.score} · read ${s.lock.reads}` : ''} · ${s.scanned} coins${s.note ? ` · ${s.note}` : ''}`,
281
298
  coin: facts ? { symbol: facts.symbol, mint: facts.mint } : null,
282
- vet: facts ? vetRows(facts, null, s.floorUsd) : [], data: facts ? dataCells(facts) : [], closes: facts?.closes ?? [],
299
+ vet: facts ? vetRows(facts, null, s.floorUsd) : [], data: facts ? dataCells(facts) : [], closes: facts?.closes ?? [], marks: traceMarks(facts),
283
300
  plan: null, log: scanLogLines(s.log, tz), score: `locks ${locks} · reads ${reads} · ${s.usage || 'ai cap'} · observe-only · never trades`,
284
301
  };
285
302
  }
@@ -491,7 +508,7 @@ function drawVet(c, x, y, w, rows, m, compact, bg) {
491
508
  }
492
509
  function drawData(c, x, y, w, m, bg) {
493
510
  const t = c.theme;
494
- section(c, x, y, w, 'DATA', 'app numbers · no extra fetch', bg, t.accent);
511
+ section(c, x, y, w, 'DATA', m.marks?.cells.length ? 'app numbers · B/S = your fills' : 'app numbers · no extra fetch', bg, t.accent);
495
512
  let cx = x + 1;
496
513
  for (const d of m.data) {
497
514
  const need = d.k.length + 1 + d.v.length + 2;
@@ -510,6 +527,15 @@ function drawData(c, x, y, w, m, bg) {
510
527
  const up = cl[cl.length - 1] >= cl[0];
511
528
  c.text(x + 1, y + 2, up ? '▲' : '▼', { fg: up ? t.up : t.down, bg, b: true });
512
529
  cl.forEach((v, i) => c.put(x + 3 + i, y + 2, LV[Math.round(((v - lo) / span) * 7)], { fg: mix(bg, up ? t.up : t.down, 0.45 + 0.55 * (i / Math.max(1, cl.length - 1))), bg, soft: true }));
530
+ // task-1483: a B / S cell on the candle of each fill (live = solid, paper = tinted); a buy wins a shared cell's colour
531
+ const first = m.closes.length - cl.length;
532
+ for (const mk of m.marks?.cells ?? []) {
533
+ const i = mk.index - first;
534
+ if (i < 0 || i >= cl.length)
535
+ continue;
536
+ const col = mk.side === 'buy' ? t.up : t.down;
537
+ c.put(x + 3 + i, y + 2, markerLetter(mk.side), mk.source === 'live' ? { fg: '#000000', bg: col, b: true, hard: true } : { fg: col, bg: mix(bg, col, 0.25), b: true, hard: true });
538
+ }
513
539
  }
514
540
  else
515
541
  c.text(x + 1, y + 2, '· no candles yet', { fg: t.dim, bg, i: true });
@@ -586,7 +612,7 @@ export function brainFor(h, facts, calm, scanUsage = '') {
586
612
  const now = hud.clock();
587
613
  const v = hud.story.view(now);
588
614
  if (agentBrainActive(v, now))
589
- return { model: agentBrainModel(v, facts, now, h.timeZone), opts: { now, calm: calm || !!hud.reduced, depth: h.colorDepth, frame: h.vfx.frame } };
615
+ return { model: agentBrainModel(v, facts, now, h.timeZone, h.priceMode !== 'price'), opts: { now, calm: calm || !!hud.reduced, depth: h.colorDepth, frame: h.vfx.frame } };
590
616
  }
591
617
  const scan = h.scan;
592
618
  if (scan?.engine.on) {
@@ -49,13 +49,15 @@ function keysDisplay(b) {
49
49
  * `--fixtures`.
50
50
  */
51
51
  export function OVERLAY_HINTS(screen, fixtures) {
52
+ // task-1508: on the AUTOTRADE screen c / n / u / d / x are its own verbs (the loop skips calm and the demo keys there).
53
+ const own = screen === 'autotrade';
52
54
  const rows = [
53
- { keys: 'c', label: 'calm mode (effects off)' },
55
+ ...(own ? [] : [{ keys: 'c', label: 'calm mode (effects off)' }]),
54
56
  { keys: '?', label: 'this help' },
55
57
  ];
56
58
  if (screen === 'analyst')
57
59
  rows.unshift({ keys: 'type', label: 'ask a follow-up · ⏎ send · esc clear/back' });
58
- if (fixtures)
60
+ if (fixtures && !own)
59
61
  rows.push({ keys: 'n/u/d/x', label: 'demo: new pair · pump · dump · rug' });
60
62
  return rows;
61
63
  }
@@ -102,6 +104,7 @@ const SCREEN_TITLE = {
102
104
  ticket: 'Paper trade ticket', positions: 'Paper positions',
103
105
  trending: 'Trending in the space', kol: 'KOL lists', bubbles: 'Bubble map', narrative: 'Narrative board',
104
106
  plans: 'Order plans & mandates', follows: 'Followed wallets', rules: 'Rules (alerts + proposals only)',
107
+ autotrade: 'Autotrade (paper)',
105
108
  };
106
109
  /** Draw a centered modal card and return its inner rect, or null when the terminal is too small. */
107
110
  function card(c, want, title, caption) {
@@ -27,11 +27,10 @@ export function renderPlans(c, state) {
27
27
  const top = 2, bottom = c.h - 1;
28
28
  const risk = svc ? svc.riskStatus() : { gateOff: false, acceptedAt: null, expiresAt: null, active: false };
29
29
  const gateLabel = risk.active ? 'HANDS-FREE' : 'GATE ON';
30
- // task-1363: the fire path. Anything not provably paper renders LIVE (fail-safe).
31
- const liveFire = svc ? svc.mode() === 'live' : false;
32
- const fireLabel = liveFire ? '◉ LIVE · DEVNET · FAST WALLET' : 'PAPER';
30
+ // task-1571: plans fire on PAPER only (dexterm holds no key; there is no live fire path).
31
+ const fireLabel = 'PAPER';
33
32
  const title = `ORDER PLANS & MANDATES · ${tab === 'plans' ? `${plans.length} plans` : `${mandates.length} mandates`} · ${fireLabel} · ${gateLabel}`;
34
- const caption = bp === 'compact' ? undefined : 'voice/agents PROPOSE only · arming needs a physical keypress hold · caps are signer-side · panic revokes all';
33
+ const caption = bp === 'compact' ? undefined : 'voice/agents PROPOSE only · arming needs a physical keypress hold · paper fills only · panic revokes all';
35
34
  const box = c.box(0, top, c.w, bottom - top, { title, caption, focus: true });
36
35
  const bg = box.bg;
37
36
  const now = state.now.getTime();
@@ -89,7 +88,7 @@ export function renderPlans(c, state) {
89
88
  const mbox = c.box(mx, my, mw, mh, { title: '⚠ ARM — physical keypress', focus: true });
90
89
  const label = a.kind === 'plan' ? `Arm plan ${a.id} into ${a.mandateId}?` : `Arm standing mandate ${a.id}?`;
91
90
  c.textC(mbox.x, mbox.y, mbox.w, label, { fg: t.text, bg: mbox.bg, b: true });
92
- c.textC(mbox.x, mbox.y + 1, mbox.w, a.kind === 'mandate' ? 'armed plans can fire at machine speed from the capped fast wallet' : 'the signer re-checks caps on every fill; voice/agents can never arm', { fg: t.muted, bg: mbox.bg });
91
+ c.textC(mbox.x, mbox.y + 1, mbox.w, a.kind === 'mandate' ? 'armed plans can fire at machine speed on paper (simulated fills)' : 'the caps are re-checked on every paper fill; voice/agents can never arm', { fg: t.muted, bg: mbox.bg });
93
92
  c.textC(mbox.x, mbox.y + 3, mbox.w, 'Hold and release [enter] or [y] to confirm · [esc] cancels · a pipe/agent cannot arm', { fg: t.accent, bg: mbox.bg });
94
93
  }
95
94
  // The "less safe" hands-free opt-in modal (Tier 4): keypress-only, journaled, auto-expires 24h, reversible.
@@ -102,17 +101,6 @@ export function renderPlans(c, state) {
102
101
  c.textC(mbox.x, mbox.y + 3, mbox.w, 'signer caps, allow-lists and panic still apply · this auto-expires in 24h · logged to the journal', { fg: t.muted, bg: mbox.bg });
103
102
  c.textC(mbox.x, mbox.y + 5, mbox.w, risk.active ? 'Hold+release [enter]/[y] to restore the gate · [esc] cancels' : 'Hold+release [enter]/[y] to accept (keypress only) · [esc] cancels · a pipe/agent cannot', { fg: t.accent, bg: mbox.bg });
104
103
  }
105
- // task-1363: the FIRE PATH modal (paper ⇄ live). Switched by a captured keypress in the loop; this paints the prompt.
106
- if (ui?.liveModal) {
107
- const mw = Math.min(box.w - 4, 78), mh = 9;
108
- const mx = box.x + Math.floor((box.w - mw) / 2), my = box.y + Math.floor((box.h - mh) / 2);
109
- const mbox = c.box(mx, my, mw, mh, { title: liveFire ? 'FIRE PATH — back to PAPER' : '⚠ FIRE PATH — go LIVE on DEVNET', focus: true });
110
- c.textC(mbox.x, mbox.y, mbox.w, liveFire ? 'Switch plan fills back to the paper executor?' : 'Fire armed plans through the SIGNER from the capped fast wallet (devnet)?', { fg: t.text, bg: mbox.bg, b: true });
111
- c.textC(mbox.x, mbox.y + 2, mbox.w, liveFire ? 'fills are then simulated again at the tick price; nothing on chain' : 'real devnet lamports move (fees of a wrap-and-unwrap sized to the plan); the token leg is modelled — Jupiter has no devnet', { fg: liveFire ? t.muted : t.down, bg: mbox.bg });
112
- c.textC(mbox.x, mbox.y + 3, mbox.w, 'the signer re-checks policy, simulation, USD per-trade/daily caps and the 0.05 SOL per-fill ceiling on every fill', { fg: t.muted, bg: mbox.bg });
113
- c.textC(mbox.x, mbox.y + 4, mbox.w, 'needs: a live run with the signer, `dexterm wallet fast create`, no armed/filled plans · never mainnet · journaled', { fg: t.muted, bg: mbox.bg });
114
- c.textC(mbox.x, mbox.y + 6, mbox.w, 'Hold+release [enter]/[y] to switch (keypress only) · [esc] cancels · a pipe/agent/voice cannot', { fg: t.accent, bg: mbox.bg });
115
- }
116
104
  // task-1366: the selected plan's levels with BOTH market cap and price (display only; mc first in mcap mode)
117
105
  if (tab === 'plans' && svc && !ui?.notice) {
118
106
  const r = rows[sel];
@@ -122,5 +110,5 @@ export function renderPlans(c, state) {
122
110
  }
123
111
  if (ui?.notice)
124
112
  c.text(box.x + 1, box.y + box.h - 1, ui.notice, { fg: t.accent, bg });
125
- footer(c, [['↑↓', 'move'], ['tab', 'plans/mandates'], ['a', 'arm (hold)'], tab === 'plans' ? ['c', 'cancel'] : ['r', 'revoke'], ['L', liveFire ? 'paper' : 'live (devnet)'], ['G', risk.active ? 'gate on' : 'hands-free'], ['!', 'PANIC'], ['esc', 'back'], ['q', 'quit']], t.name);
113
+ footer(c, [['↑↓', 'move'], ['tab', 'plans/mandates'], ['a', 'arm (hold)'], tab === 'plans' ? ['c', 'cancel'] : ['r', 'revoke'], ['G', risk.active ? 'gate on' : 'hands-free'], ['!', 'PANIC'], ['esc', 'back'], ['q', 'quit']], t.name);
126
114
  }
@@ -11,8 +11,9 @@ import { mix } from '../../../tui/src/index.js';
11
11
  import { fmtPx } from '../../../agents/src/index.js';
12
12
  import { planFromThoughts, fmtDur } from "./brain.js";
13
13
  export const PEAK_FLASH_MS = 1200;
14
- /** The chip for the followed agent's open PAPER position, or null when nothing is held. */
15
- export function pnlChipVM(v, now) {
14
+ export const CHIP_PRICE_LEVEL = (u) => `$${fmtPx(u)}`;
15
+ const PRICE_LEVEL = CHIP_PRICE_LEVEL;
16
+ export function pnlChipVM(v, now, lvl = PRICE_LEVEL) {
16
17
  const a = v.arc;
17
18
  if (!a || a.stage !== 'open')
18
19
  return null;
@@ -22,8 +23,8 @@ export function pnlChipVM(v, now) {
22
23
  symbol: a.symbol,
23
24
  pnlPct: a.pnlPct,
24
25
  pnlUsd: a.pnlPct !== null && a.sizeUsd !== null ? a.sizeUsd * a.pnlPct : null,
25
- entry: a.entryUsd !== null ? `$${fmtPx(a.entryUsd)}` : '—',
26
- mark: a.mark ? `$${fmtPx(a.mark.priceUsd)}` : '—',
26
+ entry: a.entryUsd !== null ? lvl(a.entryUsd, a.mint) : '—',
27
+ mark: a.mark ? lvl(a.mark.priceUsd, a.mint) : '—',
27
28
  peakPct: a.peakPct,
28
29
  ddPct: dd,
29
30
  heldMs: a.filledAt !== null ? now - a.filledAt : null,
@@ -53,7 +54,7 @@ export class OwnPnlTracker {
53
54
  }
54
55
  }
55
56
  get mint() { return this.cur?.s.mint ?? null; }
56
- vm(now) {
57
+ vm(now, lvl = PRICE_LEVEL) {
57
58
  const c = this.cur;
58
59
  if (!c)
59
60
  return null;
@@ -64,12 +65,12 @@ export class OwnPnlTracker {
64
65
  symbol: s.symbol,
65
66
  pnlPct: s.pnlPct,
66
67
  pnlUsd: s.pnlUsd,
67
- entry: s.entryUsd !== null ? `$${fmtPx(s.entryUsd)}` : '—',
68
- mark: s.markUsd !== null ? `$${fmtPx(s.markUsd)}` : '—',
68
+ entry: s.entryUsd !== null ? lvl(s.entryUsd, s.mint) : '—',
69
+ mark: s.markUsd !== null ? lvl(s.markUsd, s.mint) : '—',
69
70
  peakPct: c.peakPct,
70
71
  ddPct: dd,
71
72
  heldMs: s.openedAt !== null ? Math.max(0, now - s.openedAt) : null,
72
- tp: s.targetUsd !== null ? `$${fmtPx(s.targetUsd)}` : null,
73
+ tp: s.targetUsd !== null ? lvl(s.targetUsd, s.mint) : null,
73
74
  tpNone: 'not set',
74
75
  newPeak: c.peakAt !== null && now - c.peakAt < PEAK_FLASH_MS && c.peakPct !== null && c.peakPct > 0,
75
76
  };
@@ -4,7 +4,7 @@
4
4
  import { Canvas, header, footer, breakpoint, mix, isCalm, fmtPriceBare, fmtMcap, fmtNum, fmtPct, fmtAgeSec, shortAddr, } from '../../../tui/src/index.js';
5
5
  import { lamportsToSol, rawToTokens, positionPnl } from '../../../data/src/index.js';
6
6
  import { headerModel } from "../state.js";
7
- import { priceModeOf, supplyRatio, FALLBACK_MARK } from "../display.js";
7
+ import { priceModeOf, supplyRatio, supplyForMint, FALLBACK_MARK } from "../display.js";
8
8
  export function sol(n, digits = 4) {
9
9
  return `${n >= 0 ? '' : '-'}${Math.abs(n).toFixed(digits)}`;
10
10
  }
@@ -75,7 +75,7 @@ export function renderPositions(c, state) {
75
75
  // task-1366: mcap mode reads AVG / PRICE as market cap = SOL price × SOL/USD × the token's CURRENT supply (from the
76
76
  // screener rows); a token without a supply (or no SOL/USD yet) keeps its SOL price, marked ᵖ. PnL stays SOL.
77
77
  const mode = priceModeOf(state);
78
- const supplyOf = (mint) => { const row = state.screener.rows.find((x) => x.mint === mint); return row ? supplyRatio(row.price, row.mcap) : null; };
78
+ const supplyOf = (mint) => supplyForMint(state, mint); // task-1537: + the open token view and pump.fun's 1B
79
79
  const mcCell = (pSol, mint) => {
80
80
  if (pSol === null)
81
81
  return '—';
@@ -126,33 +126,9 @@ export function renderPositions(c, state) {
126
126
  }
127
127
  py += 1;
128
128
  }
129
- // task-1328: LIVE positions (the signer's ledger file, read-only), only when there are any.
130
- const liveSrc = state.live?.livePositions ?? null;
131
- const livePos = liveSrc ? liveSrc.positions().filter((p) => p.tokensRaw > 0n) : [];
132
129
  y += half;
133
- if (livePos.length > 0) {
134
- const lh = Math.min(livePos.length + 3, Math.max(5, Math.floor((bottom - y) * 0.4)));
135
- const lb = c.box(0, y, c.w, lh, { title: '◉ LIVE POSITIONS', titleFg: t.up, caption: 'confirmed on-chain fills · signer ledger' });
136
- let ly = lb.y;
137
- for (const p of livePos) {
138
- if (ly >= lb.y + lb.h)
139
- break;
140
- const mark = liveSrc?.held(p.mint)?.markSol ?? null;
141
- const pnl = positionPnl(p, mark);
142
- let cx = c.text(lb.x + 1, ly, `$${p.symbol}`, { fg: t.text, bg: lb.bg, b: true });
143
- cx = c.text(cx + 2, ly, fmtNum(rawToTokens(p.tokensRaw, p.decimals)), { fg: t.muted, bg: lb.bg });
144
- cx = c.text(cx + 2, ly, `cost ${sol(pnl.costSol)} SOL`, { fg: t.dim, bg: lb.bg });
145
- if (pnl.avgEntrySol !== null)
146
- cx = c.text(cx + 2, ly, `avg ${fmtPriceBare(pnl.avgEntrySol)}`, { fg: t.dim, bg: lb.bg });
147
- if (pnl.unrealizedSol !== null)
148
- c.text(cx + 2, ly, `uPnL ${signedSol(pnl.unrealizedSol)} SOL${pnl.unrealizedPct !== null ? ` ${fmtPct(pnl.unrealizedPct * 100)}` : ''}`, { fg: pnl.unrealizedSol >= 0 ? t.up : t.down, bg: lb.bg, b: true });
149
- c.textR(lb.x + 1, ly, lb.w - 2, `${shortAddr(p.mint, 4)} · LIVE`, { fg: t.up, bg: lb.bg });
150
- ly += 1;
151
- }
152
- y += lh;
153
- }
154
130
  // history
155
- const hb = c.box(0, y, c.w, bottom - y, { title: 'TRADE HISTORY', caption: `${v.history.length} paper fills${liveSrc ? ` · ${liveSrc.records(50).length} live` : ''}` });
131
+ const hb = c.box(0, y, c.w, bottom - y, { title: 'TRADE HISTORY', caption: `${v.history.length} paper fills` });
156
132
  let yy = hb.y;
157
133
  for (const h of v.history) {
158
134
  if (yy >= hb.y + hb.h)
@@ -163,7 +139,9 @@ export function renderPositions(c, state) {
163
139
  let cx = c.text(hb.x + 1, yy, fmtAgeSec(Math.max(0, Math.round((state.now.getTime() - h.t) / 1000))).padStart(4), { fg: t.dim, bg: hb.bg });
164
140
  cx = c.text(cx + 1, yy, h.side === 'buy' ? '▲ BUY ' : '▼ SELL', { fg: sideColor, bg: hb.bg, b: true });
165
141
  cx = c.text(cx + 1, yy, `$${h.symbol}`, { fg: t.text, bg: hb.bg, b: true });
166
- cx = c.text(cx + 1, yy, `${fmtNum(gotTokens)} @ ${fmtPriceBare(h.priceSol)} SOL`, { fg: t.muted, bg: hb.bg });
142
+ // task-1537: a fill reads as the market cap it filled at (the coin's current known supply), the SOL price kept
143
+ const hsup = mode === 'mcap' ? supplyOf(h.mint) : null;
144
+ cx = c.text(cx + 1, yy, `${fmtNum(gotTokens)} @ ${hsup !== null && v.solPriceUsd ? `${fmtMcap(h.priceSol * v.solPriceUsd * hsup)} mcap (${fmtPriceBare(h.priceSol)} SOL)` : `${fmtPriceBare(h.priceSol)} SOL`}`, { fg: t.muted, bg: hb.bg });
167
145
  cx = c.text(cx + 2, yy, `${signedSol(solAmt)} SOL`, { fg: solAmt >= 0 ? t.up : t.muted, bg: hb.bg });
168
146
  if (h.side === 'sell')
169
147
  c.text(cx + 2, yy, `pnl ${signedSol(lamportsToSol(h.realizedLamports))}`, { fg: h.realizedLamports >= 0n ? t.up : t.down, bg: hb.bg });