dexterm-cli 0.0.0-stage → 0.1.2

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 (377) hide show
  1. package/LICENSE +661 -0
  2. package/dist/packages/agents/src/audit.js +122 -0
  3. package/dist/packages/agents/src/bus.js +394 -0
  4. package/dist/packages/agents/src/executor.js +202 -0
  5. package/dist/packages/agents/src/gate.js +179 -0
  6. package/dist/packages/agents/src/identity.js +218 -0
  7. package/dist/packages/agents/src/index.js +15 -0
  8. package/dist/packages/agents/src/proposals.js +153 -0
  9. package/dist/packages/agents/src/schema.js +87 -0
  10. package/dist/packages/agents/src/sdk.js +140 -0
  11. package/dist/packages/agents/src/tiers.js +119 -0
  12. package/dist/packages/agents/src/tools.js +72 -0
  13. package/dist/packages/agents/src/ws.js +158 -0
  14. package/dist/packages/cli/assets/claude/analyst-system.md +76 -0
  15. package/dist/packages/cli/assets/claude/plugin/.claude-plugin/plugin.json +5 -0
  16. package/dist/packages/cli/assets/claude/plugin/skills/REGISTRY.json +16 -0
  17. package/dist/packages/cli/assets/claude/plugin/skills/larp-check/SKILL.md +75 -0
  18. package/dist/packages/cli/assets/claude/plugin/skills/rug-check/SKILL.md +74 -0
  19. package/dist/packages/cli/assets/claude/plugin/skills/token-dossier/SKILL.md +63 -0
  20. package/dist/packages/cli/assets/claude/plugin/skills/trench-scan/SKILL.md +44 -0
  21. package/dist/packages/cli/assets/claude/schemas/larp.schema.json +117 -0
  22. package/dist/packages/cli/assets/claude/schemas/trench-scan.schema.json +71 -0
  23. package/dist/packages/cli/assets/claude/schemas/verdict.schema.json +115 -0
  24. package/dist/packages/cli/bin/dexterm.mjs +11 -0
  25. package/dist/packages/cli/src/agent-cmd.js +336 -0
  26. package/dist/packages/cli/src/agent-roster.js +26 -0
  27. package/dist/packages/cli/src/alerts/adapters/desktop.js +40 -0
  28. package/dist/packages/cli/src/alerts/adapters/discord.js +36 -0
  29. package/dist/packages/cli/src/alerts/adapters/telegram.js +43 -0
  30. package/dist/packages/cli/src/alerts/adapters/toast.js +16 -0
  31. package/dist/packages/cli/src/alerts/creds.js +83 -0
  32. package/dist/packages/cli/src/alerts/format.js +41 -0
  33. package/dist/packages/cli/src/alerts/index.js +10 -0
  34. package/dist/packages/cli/src/alerts/notifier.js +53 -0
  35. package/dist/packages/cli/src/alerts/route.js +19 -0
  36. package/dist/packages/cli/src/alerts/types.js +1 -0
  37. package/dist/packages/cli/src/alerts-cmd.js +212 -0
  38. package/dist/packages/cli/src/analyst/backend.js +526 -0
  39. package/dist/packages/cli/src/analyst/results.js +38 -0
  40. package/dist/packages/cli/src/analyst/session.js +319 -0
  41. package/dist/packages/cli/src/audit.js +51 -0
  42. package/dist/packages/cli/src/backtest-cmd.js +208 -0
  43. package/dist/packages/cli/src/boot-state.js +62 -0
  44. package/dist/packages/cli/src/coin-target.js +2 -0
  45. package/dist/packages/cli/src/custom.js +261 -0
  46. package/dist/packages/cli/src/display.js +191 -0
  47. package/dist/packages/cli/src/doctor.js +375 -0
  48. package/dist/packages/cli/src/export.js +235 -0
  49. package/dist/packages/cli/src/feed.js +634 -0
  50. package/dist/packages/cli/src/fixtures.js +275 -0
  51. package/dist/packages/cli/src/follow-cmd.js +221 -0
  52. package/dist/packages/cli/src/images-config.js +59 -0
  53. package/dist/packages/cli/src/index.js +31 -0
  54. package/dist/packages/cli/src/kb-skill-cmd.js +240 -0
  55. package/dist/packages/cli/src/larp-record.js +21 -0
  56. package/dist/packages/cli/src/live/copy.js +80 -0
  57. package/dist/packages/cli/src/live/flow.js +233 -0
  58. package/dist/packages/cli/src/live/index.js +511 -0
  59. package/dist/packages/cli/src/live/intel.js +227 -0
  60. package/dist/packages/cli/src/live/newpairs.js +334 -0
  61. package/dist/packages/cli/src/live/screens/newpairs-live.js +219 -0
  62. package/dist/packages/cli/src/live/screens/token-live.js +459 -0
  63. package/dist/packages/cli/src/live/screens/watchlist-live.js +149 -0
  64. package/dist/packages/cli/src/live/token.js +585 -0
  65. package/dist/packages/cli/src/live/trade.js +929 -0
  66. package/dist/packages/cli/src/live/watchlist.js +178 -0
  67. package/dist/packages/cli/src/main.js +5785 -0
  68. package/dist/packages/cli/src/mcp-cmd.js +326 -0
  69. package/dist/packages/cli/src/narrative-cmd.js +76 -0
  70. package/dist/packages/cli/src/pack-cmd.js +323 -0
  71. package/dist/packages/cli/src/plan-cmd.js +278 -0
  72. package/dist/packages/cli/src/popup.js +810 -0
  73. package/dist/packages/cli/src/rules-cmd.js +131 -0
  74. package/dist/packages/cli/src/rules.js +358 -0
  75. package/dist/packages/cli/src/scan/command.js +57 -0
  76. package/dist/packages/cli/src/scan/engine.js +419 -0
  77. package/dist/packages/cli/src/scan/observe.js +64 -0
  78. package/dist/packages/cli/src/scan/ui.js +98 -0
  79. package/dist/packages/cli/src/screener/filter.js +241 -0
  80. package/dist/packages/cli/src/screener/presets.js +80 -0
  81. package/dist/packages/cli/src/screener/rows.js +146 -0
  82. package/dist/packages/cli/src/screener/rug.js +50 -0
  83. package/dist/packages/cli/src/screener/sort.js +52 -0
  84. package/dist/packages/cli/src/screener/view.js +183 -0
  85. package/dist/packages/cli/src/screens/analyst-session.js +343 -0
  86. package/dist/packages/cli/src/screens/analyst.js +326 -0
  87. package/dist/packages/cli/src/screens/boot.js +74 -0
  88. package/dist/packages/cli/src/screens/bubbles.js +255 -0
  89. package/dist/packages/cli/src/screens/coin.js +33 -0
  90. package/dist/packages/cli/src/screens/follows.js +201 -0
  91. package/dist/packages/cli/src/screens/kol.js +90 -0
  92. package/dist/packages/cli/src/screens/narrative.js +90 -0
  93. package/dist/packages/cli/src/screens/newpairs.js +150 -0
  94. package/dist/packages/cli/src/screens/overlay.js +257 -0
  95. package/dist/packages/cli/src/screens/plans.js +126 -0
  96. package/dist/packages/cli/src/screens/positions.js +176 -0
  97. package/dist/packages/cli/src/screens/rules.js +170 -0
  98. package/dist/packages/cli/src/screens/screener.js +459 -0
  99. package/dist/packages/cli/src/screens/social-panel.js +107 -0
  100. package/dist/packages/cli/src/screens/ticket.js +342 -0
  101. package/dist/packages/cli/src/screens/token.js +312 -0
  102. package/dist/packages/cli/src/screens/trending.js +181 -0
  103. package/dist/packages/cli/src/screens/watchlist.js +104 -0
  104. package/dist/packages/cli/src/skill-eval-build.js +109 -0
  105. package/dist/packages/cli/src/social/demo.js +96 -0
  106. package/dist/packages/cli/src/social/view.js +250 -0
  107. package/dist/packages/cli/src/state.js +463 -0
  108. package/dist/packages/cli/src/theme-cmd.js +126 -0
  109. package/dist/packages/cli/src/trade.js +319 -0
  110. package/dist/packages/cli/src/update.js +294 -0
  111. package/dist/packages/cli/src/version.js +3 -0
  112. package/dist/packages/cli/src/voice-cmd.js +119 -0
  113. package/dist/packages/cli/src/voice-hud.js +42 -0
  114. package/dist/packages/cli/src/wallet-cmd.js +440 -0
  115. package/dist/packages/cli/src/wallet-command.js +31 -0
  116. package/dist/packages/cli/src/watch-cmd.js +190 -0
  117. package/dist/packages/cli/src/widgets.js +208 -0
  118. package/dist/packages/cli/src/workspace-cmd.js +68 -0
  119. package/dist/packages/cli/src/x-cmd.js +154 -0
  120. package/dist/packages/custom/src/config.js +213 -0
  121. package/dist/packages/custom/src/index.js +10 -0
  122. package/dist/packages/custom/src/keymap.js +107 -0
  123. package/dist/packages/custom/src/layout.js +235 -0
  124. package/dist/packages/custom/src/packs.js +633 -0
  125. package/dist/packages/custom/src/rules.js +704 -0
  126. package/dist/packages/custom/src/schema.js +538 -0
  127. package/dist/packages/custom/src/themes.js +176 -0
  128. package/dist/packages/custom/src/widget-html.js +222 -0
  129. package/dist/packages/custom/src/workspace.js +141 -0
  130. package/dist/packages/data/src/analyst-actions.js +133 -0
  131. package/dist/packages/data/src/budget.js +88 -0
  132. package/dist/packages/data/src/cache.js +142 -0
  133. package/dist/packages/data/src/candles.js +168 -0
  134. package/dist/packages/data/src/clock.js +64 -0
  135. package/dist/packages/data/src/coin-target.js +82 -0
  136. package/dist/packages/data/src/credits.js +137 -0
  137. package/dist/packages/data/src/detail.js +97 -0
  138. package/dist/packages/data/src/fast-lane.js +321 -0
  139. package/dist/packages/data/src/fixtures.js +135 -0
  140. package/dist/packages/data/src/health.js +245 -0
  141. package/dist/packages/data/src/http.js +277 -0
  142. package/dist/packages/data/src/images/cache.js +141 -0
  143. package/dist/packages/data/src/images/decode-worker.js +28 -0
  144. package/dist/packages/data/src/images/decode.js +81 -0
  145. package/dist/packages/data/src/images/fetch.js +162 -0
  146. package/dist/packages/data/src/images/gif.js +214 -0
  147. package/dist/packages/data/src/images/index.js +10 -0
  148. package/dist/packages/data/src/images/jpeg.js +544 -0
  149. package/dist/packages/data/src/images/png.js +310 -0
  150. package/dist/packages/data/src/images/service.js +334 -0
  151. package/dist/packages/data/src/images/types.js +27 -0
  152. package/dist/packages/data/src/index.js +211 -0
  153. package/dist/packages/data/src/intel/helius-history.js +70 -0
  154. package/dist/packages/data/src/intel/holder-class.js +125 -0
  155. package/dist/packages/data/src/intel/rules.js +421 -0
  156. package/dist/packages/data/src/intel/scan.js +170 -0
  157. package/dist/packages/data/src/larp/evidence.js +288 -0
  158. package/dist/packages/data/src/larp/link-baseline.js +196 -0
  159. package/dist/packages/data/src/larp/links.js +137 -0
  160. package/dist/packages/data/src/larp/robots.js +90 -0
  161. package/dist/packages/data/src/larp/safe-fetch.js +389 -0
  162. package/dist/packages/data/src/limiter.js +341 -0
  163. package/dist/packages/data/src/model.js +12 -0
  164. package/dist/packages/data/src/paper.js +331 -0
  165. package/dist/packages/data/src/rpc-config.js +126 -0
  166. package/dist/packages/data/src/rpc-pool.js +166 -0
  167. package/dist/packages/data/src/social/chain.js +83 -0
  168. package/dist/packages/data/src/social/dedupe.js +205 -0
  169. package/dist/packages/data/src/social/feed.js +462 -0
  170. package/dist/packages/data/src/social/firewall.js +110 -0
  171. package/dist/packages/data/src/social/index.js +11 -0
  172. package/dist/packages/data/src/social/kol.js +269 -0
  173. package/dist/packages/data/src/social/model.js +11 -0
  174. package/dist/packages/data/src/social/rank.js +184 -0
  175. package/dist/packages/data/src/social/rss.js +113 -0
  176. package/dist/packages/data/src/social/summary.js +104 -0
  177. package/dist/packages/data/src/social/venues.js +186 -0
  178. package/dist/packages/data/src/sources/dexscreener.js +184 -0
  179. package/dist/packages/data/src/sources/geckoterminal.js +133 -0
  180. package/dist/packages/data/src/sources/goplus.js +161 -0
  181. package/dist/packages/data/src/sources/jupiter-swap.js +236 -0
  182. package/dist/packages/data/src/sources/jupiter.js +198 -0
  183. package/dist/packages/data/src/sources/pda.js +113 -0
  184. package/dist/packages/data/src/sources/pump-curve.js +58 -0
  185. package/dist/packages/data/src/sources/pumpportal.js +252 -0
  186. package/dist/packages/data/src/sources/rugcheck.js +71 -0
  187. package/dist/packages/data/src/sources/solana-rpc.js +299 -0
  188. package/dist/packages/data/src/sources/solana-ws.js +287 -0
  189. package/dist/packages/data/src/store.js +289 -0
  190. package/dist/packages/data/src/trade/bridge.js +464 -0
  191. package/dist/packages/data/src/trade/caps.js +323 -0
  192. package/dist/packages/data/src/trade/copy/auto.js +385 -0
  193. package/dist/packages/data/src/trade/copy/follows.js +103 -0
  194. package/dist/packages/data/src/trade/copy/index.js +9 -0
  195. package/dist/packages/data/src/trade/copy/mirror.js +91 -0
  196. package/dist/packages/data/src/trade/copy/stats.js +120 -0
  197. package/dist/packages/data/src/trade/copy/tracker.js +158 -0
  198. package/dist/packages/data/src/trade/copy/trades.js +87 -0
  199. package/dist/packages/data/src/trade/copy/types.js +6 -0
  200. package/dist/packages/data/src/trade/executor.js +933 -0
  201. package/dist/packages/data/src/trade/kill-switch.js +47 -0
  202. package/dist/packages/data/src/trade/link-store.js +52 -0
  203. package/dist/packages/data/src/trade/plans/confirm.js +157 -0
  204. package/dist/packages/data/src/trade/plans/engine.js +784 -0
  205. package/dist/packages/data/src/trade/plans/executor-live.js +220 -0
  206. package/dist/packages/data/src/trade/plans/executor-paper.js +44 -0
  207. package/dist/packages/data/src/trade/plans/executor.js +11 -0
  208. package/dist/packages/data/src/trade/plans/index.js +12 -0
  209. package/dist/packages/data/src/trade/plans/journal.js +77 -0
  210. package/dist/packages/data/src/trade/plans/mandate.js +129 -0
  211. package/dist/packages/data/src/trade/plans/plan.js +179 -0
  212. package/dist/packages/data/src/trade/plans/service.js +168 -0
  213. package/dist/packages/data/src/trade/plans/types.js +6 -0
  214. package/dist/packages/data/src/trade/rpc-exec.js +229 -0
  215. package/dist/packages/data/src/trade/signer/client.js +197 -0
  216. package/dist/packages/data/src/trade/signer/fast-wallet.js +154 -0
  217. package/dist/packages/data/src/trade/signer/host.js +97 -0
  218. package/dist/packages/data/src/trade/signer/main.js +121 -0
  219. package/dist/packages/data/src/trade/signer/probe-builder.js +85 -0
  220. package/dist/packages/data/src/trade/signer/protocol.js +92 -0
  221. package/dist/packages/data/src/trade/signer/service.js +400 -0
  222. package/dist/packages/data/src/trade/signer/sol-usd-feed.js +98 -0
  223. package/dist/packages/data/src/trade/sol-usd.js +86 -0
  224. package/dist/packages/data/src/trade/swap-build.js +108 -0
  225. package/dist/packages/data/src/trade/token-delta.js +201 -0
  226. package/dist/packages/data/src/trade/tx-decode.js +632 -0
  227. package/dist/packages/data/src/util.js +24 -0
  228. package/dist/packages/data/src/watchlist.js +176 -0
  229. package/dist/packages/data/src/x/api.js +256 -0
  230. package/dist/packages/data/src/x/budget.js +66 -0
  231. package/dist/packages/data/src/x/config.js +49 -0
  232. package/dist/packages/data/src/x/index.js +10 -0
  233. package/dist/packages/data/src/x/mock-server.js +217 -0
  234. package/dist/packages/data/src/x/oauth.js +242 -0
  235. package/dist/packages/data/src/x/pkce.js +21 -0
  236. package/dist/packages/data/src/x/source.js +285 -0
  237. package/dist/packages/data/src/x/token-store.js +134 -0
  238. package/dist/packages/data/src/x/transport.js +71 -0
  239. package/dist/packages/data/vendor/solana-web3/LICENSE +20 -0
  240. package/dist/packages/data/vendor/solana-web3/NOTICE.md +13 -0
  241. package/dist/packages/data/vendor/solana-web3/index.iife.min.js +20 -0
  242. package/dist/packages/mcp/assets/cases.json +1194 -0
  243. package/dist/packages/mcp/assets/kb/entries/cabal-and-coordinated-launches.md +28 -0
  244. package/dist/packages/mcp/assets/kb/entries/common-rug-patterns.md +40 -0
  245. package/dist/packages/mcp/assets/kb/entries/dbc-mechanics.md +30 -0
  246. package/dist/packages/mcp/assets/kb/entries/dev-wallet-behaviour.md +33 -0
  247. package/dist/packages/mcp/assets/kb/entries/glossary.md +35 -0
  248. package/dist/packages/mcp/assets/kb/entries/holder-concentration.md +30 -0
  249. package/dist/packages/mcp/assets/kb/entries/jito-bundles.md +29 -0
  250. package/dist/packages/mcp/assets/kb/entries/launchlab-curve.md +31 -0
  251. package/dist/packages/mcp/assets/kb/entries/lp-burn-vs-lock.md +31 -0
  252. package/dist/packages/mcp/assets/kb/entries/metadata-and-copycats.md +29 -0
  253. package/dist/packages/mcp/assets/kb/entries/mint-freeze-authority.md +31 -0
  254. package/dist/packages/mcp/assets/kb/entries/narrative-lifecycle.md +32 -0
  255. package/dist/packages/mcp/assets/kb/entries/pump-bonding-curve.md +33 -0
  256. package/dist/packages/mcp/assets/kb/entries/pumpswap-migration.md +29 -0
  257. package/dist/packages/mcp/assets/kb/entries/sniping-and-snipers.md +29 -0
  258. package/dist/packages/mcp/assets/kb/entries/token2022-extensions-risk.md +32 -0
  259. package/dist/packages/mcp/assets/kb/entries/wash-trading-fake-volume.md +33 -0
  260. package/dist/packages/mcp/assets/skills/rug-check.md +52 -0
  261. package/dist/packages/mcp/assets/skills/token-dossier.md +57 -0
  262. package/dist/packages/mcp/assets/skills/trench-scan.md +40 -0
  263. package/dist/packages/mcp/bin/dexterm-mcp.mjs +16 -0
  264. package/dist/packages/mcp/src/dossier.js +78 -0
  265. package/dist/packages/mcp/src/firewall.js +21 -0
  266. package/dist/packages/mcp/src/index.js +22 -0
  267. package/dist/packages/mcp/src/server.js +936 -0
  268. package/dist/packages/mcp/src/user-content.js +434 -0
  269. package/dist/packages/packs/src/backtest.js +183 -0
  270. package/dist/packages/packs/src/digest.js +95 -0
  271. package/dist/packages/packs/src/firewall.js +57 -0
  272. package/dist/packages/packs/src/index.js +20 -0
  273. package/dist/packages/packs/src/larp-eval.js +100 -0
  274. package/dist/packages/packs/src/narrative.js +309 -0
  275. package/dist/packages/packs/src/reason.js +135 -0
  276. package/dist/packages/packs/src/rug-model.js +137 -0
  277. package/dist/packages/packs/src/schema.js +54 -0
  278. package/dist/packages/packs/src/skill-backtest.js +300 -0
  279. package/dist/packages/packs/src/token-dossier.js +174 -0
  280. package/dist/packages/packs/src/verdicts.js +17 -0
  281. package/dist/packages/packs/src/wallet-dossier.js +105 -0
  282. package/dist/packages/popup/src/config.js +71 -0
  283. package/dist/packages/popup/src/dock.js +271 -0
  284. package/dist/packages/popup/src/host.js +210 -0
  285. package/dist/packages/popup/src/index.js +12 -0
  286. package/dist/packages/popup/src/loopback.js +53 -0
  287. package/dist/packages/popup/src/open.js +183 -0
  288. package/dist/packages/popup/src/pages/bubbles-lib.js +160 -0
  289. package/dist/packages/popup/src/pages/bubbles.css +23 -0
  290. package/dist/packages/popup/src/pages/bubbles.html +36 -0
  291. package/dist/packages/popup/src/pages/bubbles.js +214 -0
  292. package/dist/packages/popup/src/pages/chart-lib.js +262 -0
  293. package/dist/packages/popup/src/pages/chart.css +50 -0
  294. package/dist/packages/popup/src/pages/chart.html +56 -0
  295. package/dist/packages/popup/src/pages/chart.js +554 -0
  296. package/dist/packages/popup/src/pages/common.css +34 -0
  297. package/dist/packages/popup/src/pages/common.js +187 -0
  298. package/dist/packages/popup/src/pages/feeds.html +20 -0
  299. package/dist/packages/popup/src/pages/feeds.js +77 -0
  300. package/dist/packages/popup/src/pages/narrative.html +20 -0
  301. package/dist/packages/popup/src/pages/narrative.js +61 -0
  302. package/dist/packages/popup/src/pages/plans.css +30 -0
  303. package/dist/packages/popup/src/pages/plans.html +26 -0
  304. package/dist/packages/popup/src/pages/plans.js +82 -0
  305. package/dist/packages/popup/src/pages/roster.css +41 -0
  306. package/dist/packages/popup/src/pages/roster.html +25 -0
  307. package/dist/packages/popup/src/pages/roster.js +75 -0
  308. package/dist/packages/popup/src/pages/token.html +20 -0
  309. package/dist/packages/popup/src/pages/token.js +112 -0
  310. package/dist/packages/popup/src/pages/widget-sdk.js +224 -0
  311. package/dist/packages/popup/src/pages/widget.css +5 -0
  312. package/dist/packages/popup/src/pages/widget.html +21 -0
  313. package/dist/packages/popup/src/pages/widget.js +85 -0
  314. package/dist/packages/popup/src/protocol.js +31 -0
  315. package/dist/packages/popup/src/selftest.js +156 -0
  316. package/dist/packages/popup/src/server.js +582 -0
  317. package/dist/packages/popup/src/sinkproxy.js +167 -0
  318. package/dist/packages/popup/src/widget-html.js +231 -0
  319. package/dist/packages/popup/vendor/lightweight-charts/LICENSE +201 -0
  320. package/dist/packages/popup/vendor/lightweight-charts/NOTICE +2 -0
  321. package/dist/packages/popup/vendor/lightweight-charts/README.md +30 -0
  322. package/dist/packages/popup/vendor/lightweight-charts/VERSION +1 -0
  323. package/dist/packages/popup/vendor/lightweight-charts/lightweight-charts.standalone.production.js +7 -0
  324. package/dist/packages/recorder/bin/dexterm-recorder.mjs +11 -0
  325. package/dist/packages/recorder/src/cli.js +113 -0
  326. package/dist/packages/recorder/src/export.js +71 -0
  327. package/dist/packages/recorder/src/index.js +20 -0
  328. package/dist/packages/recorder/src/labels.js +151 -0
  329. package/dist/packages/recorder/src/open.js +29 -0
  330. package/dist/packages/recorder/src/recorder.js +553 -0
  331. package/dist/packages/recorder/src/schedule.js +43 -0
  332. package/dist/packages/recorder/src/schema.js +135 -0
  333. package/dist/packages/recorder/src/snapshot.js +191 -0
  334. package/dist/packages/recorder/src/sweep.js +52 -0
  335. package/dist/packages/recorder/src/verdicts.js +52 -0
  336. package/dist/packages/tui/src/bubbles.js +415 -0
  337. package/dist/packages/tui/src/canvas.js +370 -0
  338. package/dist/packages/tui/src/chrome.js +85 -0
  339. package/dist/packages/tui/src/color.js +133 -0
  340. package/dist/packages/tui/src/flush.js +62 -0
  341. package/dist/packages/tui/src/fmt.js +188 -0
  342. package/dist/packages/tui/src/fx-trade.js +278 -0
  343. package/dist/packages/tui/src/fx.js +527 -0
  344. package/dist/packages/tui/src/images/blocks.js +141 -0
  345. package/dist/packages/tui/src/images/coin.js +22 -0
  346. package/dist/packages/tui/src/images/detect.js +140 -0
  347. package/dist/packages/tui/src/images/index.js +7 -0
  348. package/dist/packages/tui/src/images/layer.js +146 -0
  349. package/dist/packages/tui/src/images/pixels.js +157 -0
  350. package/dist/packages/tui/src/images/protocols.js +87 -0
  351. package/dist/packages/tui/src/index.js +18 -0
  352. package/dist/packages/tui/src/keymap.js +357 -0
  353. package/dist/packages/tui/src/layout.js +11 -0
  354. package/dist/packages/tui/src/raster-font.js +195 -0
  355. package/dist/packages/tui/src/raster.js +213 -0
  356. package/dist/packages/tui/src/sound.js +177 -0
  357. package/dist/packages/tui/src/theme.js +182 -0
  358. package/dist/packages/tui/src/widgets.js +598 -0
  359. package/dist/packages/voice/src/controller.js +407 -0
  360. package/dist/packages/voice/src/doctor.js +131 -0
  361. package/dist/packages/voice/src/download.js +184 -0
  362. package/dist/packages/voice/src/engines.js +84 -0
  363. package/dist/packages/voice/src/index.js +20 -0
  364. package/dist/packages/voice/src/router.js +502 -0
  365. package/dist/packages/voice/src/stt/apple-helper.swift.js +103 -0
  366. package/dist/packages/voice/src/stt/apple.js +179 -0
  367. package/dist/packages/voice/src/stt/fake.js +34 -0
  368. package/dist/packages/voice/src/stt/whisper.js +112 -0
  369. package/dist/packages/voice/src/summary.js +44 -0
  370. package/dist/packages/voice/src/tts/espeak.js +131 -0
  371. package/dist/packages/voice/src/tts/fake.js +30 -0
  372. package/dist/packages/voice/src/tts/piper.js +206 -0
  373. package/dist/packages/voice/src/tts/say.js +132 -0
  374. package/dist/packages/voice/src/tts/voices.js +206 -0
  375. package/dist/packages/voice/src/types.js +3 -0
  376. package/package.json +38 -4
  377. package/README.md +0 -3
@@ -0,0 +1,135 @@
1
+ // dexterm history recorder: schema (lane R-01, AI-SUITE-DESIGN §4.1; prototyped in
2
+ // dexterm/research/task-1287/recorder/schema.sql). Lives in the app's SQLite file (the one `--db`
3
+ // controls, next to the cache / watchlist / paper wallet tables) on node:sqlite, WAL mode.
4
+ //
5
+ // Differences from the prototype, all on purpose:
6
+ // - no `runs` table: the app has no sweep runs, it observes rows as the data layer normalises them.
7
+ // `sweeps` records the outcome re-observation calls instead (the request ledger the budget needs).
8
+ // - token_snapshots gains `kind` ('live' = observed from the app's own rows, 'sweep' = an outcome
9
+ // re-observation that cost a request), `hash` (change detection), `is_t0` (a labelling anchor),
10
+ // `horizons_done` (bitmask of horizons already labelled for a t0 row) and `focus` (the row was a
11
+ // watchlist / open-token row when written: the only rows that keep raw JSON).
12
+ // - `mints` is a per-mint summary the sweep scheduler reads instead of scanning snapshots.
13
+ // - feed_members is keyed on (t, feed, rank): the refresh tick is the run.
14
+ // - chain_events and verdicts are created here (one schema owner) but written by R-02 / L-01.
15
+ export const SCHEMA_VERSION = 1;
16
+ export const HORIZONS_SEC = [3600, 7200, 21600, 86400, 259200];
17
+ /** Every horizon labelled: the bitmask value of `horizons_done` for a finished t0 row. */
18
+ export const ALL_HORIZONS_MASK = (1 << HORIZONS_SEC.length) - 1;
19
+ export const SCHEMA_SQL = `
20
+ CREATE TABLE IF NOT EXISTS recorder_meta (
21
+ key TEXT PRIMARY KEY,
22
+ value TEXT NOT NULL
23
+ ) WITHOUT ROWID;
24
+
25
+ CREATE TABLE IF NOT EXISTS feed_members (
26
+ t INTEGER NOT NULL, -- refresh tick (unix ms) the list was observed at
27
+ feed TEXT NOT NULL, -- the data layer's discovery sub-feed id (jup:toptrending-1h, ds:boosts-top, ...)
28
+ rank INTEGER NOT NULL,
29
+ mint TEXT NOT NULL,
30
+ PRIMARY KEY (t, feed, rank)
31
+ ) WITHOUT ROWID;
32
+ CREATE INDEX IF NOT EXISTS feed_members_mint_t ON feed_members (mint, t);
33
+
34
+ CREATE TABLE IF NOT EXISTS token_snapshots (
35
+ snap_id INTEGER PRIMARY KEY AUTOINCREMENT,
36
+ mint TEXT NOT NULL,
37
+ t INTEGER NOT NULL, -- unix ms when the record was fetched (the newest part's fetchedAt)
38
+ kind TEXT NOT NULL, -- 'live' | 'sweep'
39
+ hash TEXT NOT NULL, -- change-detection hash of the normalised columns
40
+ is_t0 INTEGER NOT NULL DEFAULT 0,
41
+ horizons_done INTEGER NOT NULL DEFAULT 0,
42
+ next_due_t INTEGER NOT NULL DEFAULT 0, -- t0 rows: when the labeler should look at this row next
43
+ focus INTEGER NOT NULL DEFAULT 0,
44
+ symbol TEXT, name TEXT, -- stored FIREWALLED: control/bidi/zero-width stripped, length-capped
45
+ launchpad TEXT,
46
+ created_at INTEGER,
47
+ age_sec INTEGER,
48
+ price_usd REAL, mcap REAL, mcap_resolved REAL, mcap_flagged INTEGER, fdv REAL, liquidity_usd REAL,
49
+ vol_m5 REAL, vol_h1 REAL, vol_h6 REAL, vol_h24 REAL,
50
+ buys_m5 INTEGER, sells_m5 INTEGER, buys_h1 INTEGER, sells_h1 INTEGER, buys_h24 INTEGER, sells_h24 INTEGER,
51
+ chg_m5 REAL, chg_h1 REAL, chg_h6 REAL, chg_h24 REAL,
52
+ pair_address TEXT, dex TEXT, pair_created_at INTEGER,
53
+ src_market TEXT NOT NULL, -- 'dexscreener' | 'jupiter-tokens' | 'none'
54
+ holder_count INTEGER, holders_chg_pct REAL,
55
+ top_holders_pct REAL, dev_pct REAL, dev_mints INTEGER,
56
+ organic_score REAL,
57
+ num_traders_h1 INTEGER, net_buyers_h1 INTEGER,
58
+ buy_vol_h1 REAL, sell_vol_h1 REAL,
59
+ mint_auth_enabled INTEGER, freeze_auth_enabled INTEGER,
60
+ is_verified INTEGER, is_sus INTEGER,
61
+ src_audit TEXT,
62
+ rug_score REAL, lp_locked_pct REAL, src_risk TEXT,
63
+ sources TEXT NOT NULL, -- JSON array of SourceId that contributed
64
+ raw_json TEXT -- normalised Token+Pair+Stats+Audit record; focus rows only; pruned after 7 d
65
+ );
66
+ CREATE INDEX IF NOT EXISTS token_snapshots_mint_t ON token_snapshots (mint, t);
67
+ CREATE INDEX IF NOT EXISTS token_snapshots_t ON token_snapshots (t);
68
+ CREATE INDEX IF NOT EXISTS token_snapshots_t0_pending ON token_snapshots (next_due_t) WHERE is_t0 = 1 AND horizons_done < ${ALL_HORIZONS_MASK};
69
+
70
+ CREATE TABLE IF NOT EXISTS mints (
71
+ mint TEXT PRIMARY KEY,
72
+ first_t INTEGER NOT NULL,
73
+ last_live_t INTEGER NOT NULL, -- newest 'live' snapshot
74
+ last_any_t INTEGER NOT NULL, -- newest snapshot of any kind
75
+ last_t0_t INTEGER NOT NULL, -- newest is_t0 anchor
76
+ last_hash TEXT NOT NULL,
77
+ snapshots INTEGER NOT NULL DEFAULT 0
78
+ ) WITHOUT ROWID;
79
+ CREATE INDEX IF NOT EXISTS mints_last_live ON mints (last_live_t);
80
+
81
+ CREATE TABLE IF NOT EXISTS sweeps (
82
+ sweep_id INTEGER PRIMARY KEY AUTOINCREMENT,
83
+ started_at INTEGER NOT NULL,
84
+ finished_at INTEGER,
85
+ mints INTEGER NOT NULL, -- mints re-observed
86
+ calls INTEGER NOT NULL, -- DexScreener token-batch calls issued (30 mints each)
87
+ answered INTEGER NOT NULL DEFAULT 0, -- mints DexScreener returned a pair for
88
+ error TEXT
89
+ );
90
+
91
+ CREATE TABLE IF NOT EXISTS chain_events (
92
+ mint TEXT NOT NULL,
93
+ t INTEGER NOT NULL,
94
+ slot INTEGER,
95
+ signature TEXT NOT NULL,
96
+ kind TEXT NOT NULL,
97
+ actor TEXT,
98
+ amount REAL,
99
+ evidence TEXT NOT NULL,
100
+ PRIMARY KEY (signature, kind)
101
+ );
102
+ CREATE INDEX IF NOT EXISTS chain_events_mint_t ON chain_events (mint, t);
103
+
104
+ CREATE TABLE IF NOT EXISTS outcomes (
105
+ mint TEXT NOT NULL,
106
+ t0 INTEGER NOT NULL,
107
+ horizon_sec INTEGER NOT NULL,
108
+ t1 INTEGER, -- the observation used (first at/after t0+horizon, within 2x); NULL when unobserved
109
+ label TEXT NOT NULL, -- 'rug' | 'dead' | 'fade' | 'flat' | 'runner' | 'unobserved'
110
+ label_tier TEXT NOT NULL, -- 'keyless-proxy' | 'chain-verified'
111
+ mcap_ratio REAL, liq_ratio REAL, price_ratio REAL,
112
+ max_mcap_ratio REAL,
113
+ evidence TEXT NOT NULL, -- JSON: the numbers and the rule that fired
114
+ labeler_version TEXT NOT NULL,
115
+ PRIMARY KEY (mint, t0, horizon_sec)
116
+ ) WITHOUT ROWID;
117
+ CREATE INDEX IF NOT EXISTS outcomes_label ON outcomes (label, horizon_sec);
118
+
119
+ CREATE TABLE IF NOT EXISTS verdicts (
120
+ verdict_id INTEGER PRIMARY KEY AUTOINCREMENT,
121
+ mint TEXT NOT NULL,
122
+ t INTEGER NOT NULL,
123
+ pack TEXT NOT NULL,
124
+ pack_version TEXT NOT NULL,
125
+ model TEXT,
126
+ verdict TEXT,
127
+ rug_p REAL,
128
+ confidence REAL,
129
+ score REAL,
130
+ cost_usd REAL, wall_ms INTEGER,
131
+ input_hash TEXT NOT NULL,
132
+ run_file TEXT
133
+ );
134
+ CREATE INDEX IF NOT EXISTS verdicts_mint_t ON verdicts (mint, t);
135
+ `;
@@ -0,0 +1,191 @@
1
+ // Normalised record -> snapshot columns. Pure functions over the data layer's `EnrichedRow` (the
2
+ // screener's normalised Token+Pair+Stats+Audit record, AI-SUITE-DESIGN §4.1 "hook on the data layer's
3
+ // normaliser") and over a bare `DsTokenView` (what an outcome sweep gets back). The change-detection
4
+ // hash covers every stored column except the ones derived from the clock (t, age_sec), so a refresh
5
+ // that returns the same numbers writes nothing.
6
+ import { createHash } from 'node:crypto';
7
+ /** Max stored length of a symbol / name (firewalled strings, SPEC §5.3). */
8
+ export const SYMBOL_MAX = 16;
9
+ export const NAME_MAX = 64;
10
+ /**
11
+ * Terminal/model safety for stored strings: drop control, bidi, zero-width and BOM code points,
12
+ * collapse whitespace, cap the length. Same intent as the prototype's `clean()`; names are never
13
+ * fed to a model raw (they go through the Analyst firewall when they are).
14
+ */
15
+ export function cleanText(s, max) {
16
+ if (s === null || s === undefined)
17
+ return null;
18
+ let out = '';
19
+ for (const ch of String(s).normalize('NFC')) {
20
+ const cp = ch.codePointAt(0);
21
+ if (cp < 0x20 || (cp >= 0x7f && cp <= 0x9f))
22
+ continue;
23
+ if (cp === 0x200b || cp === 0x200c || cp === 0x200d || cp === 0x2060 || cp === 0xfeff)
24
+ continue;
25
+ if ((cp >= 0x200e && cp <= 0x200f) || (cp >= 0x202a && cp <= 0x202e) || (cp >= 0x2066 && cp <= 0x2069))
26
+ continue;
27
+ out += ch;
28
+ }
29
+ out = out.replace(/\s+/g, ' ').trim();
30
+ return out.length > max ? out.slice(0, max) + '…' : out;
31
+ }
32
+ const fin = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : null);
33
+ const bool = (v) => (v === null || v === undefined ? null : v ? 1 : 0);
34
+ /** Snapshot columns from the screener's normalised row; `hash` is the exact-record hash (identity, not the change rule). */
35
+ export function fromEnrichedRow(r) {
36
+ const { token, pair, stats, audit } = r;
37
+ const h1 = stats?.perWindow.h1 ?? null;
38
+ const src = pair.source === 'dexscreener' ? 'dexscreener' : pair.source === 'jupiter-tokens' ? 'jupiter-tokens' : 'none';
39
+ const columns = {
40
+ mint: r.mint,
41
+ symbol: cleanText(token.symbol, SYMBOL_MAX),
42
+ name: cleanText(token.name, NAME_MAX),
43
+ launchpad: token.launchpad ?? null,
44
+ created_at: fin(token.createdAt ?? pair.createdAt),
45
+ price_usd: fin(pair.priceUsd),
46
+ mcap: fin(pair.mcap),
47
+ mcap_resolved: fin(r.mcap?.value),
48
+ mcap_flagged: r.mcap ? (r.mcap.flagged ? 1 : 0) : null,
49
+ fdv: fin(pair.fdv),
50
+ liquidity_usd: fin(pair.liquidityUsd),
51
+ vol_m5: fin(pair.volume.m5), vol_h1: fin(pair.volume.h1), vol_h6: fin(pair.volume.h6), vol_h24: fin(pair.volume.h24),
52
+ buys_m5: fin(pair.txns.m5?.buys), sells_m5: fin(pair.txns.m5?.sells),
53
+ buys_h1: fin(pair.txns.h1?.buys), sells_h1: fin(pair.txns.h1?.sells),
54
+ buys_h24: fin(pair.txns.h24?.buys), sells_h24: fin(pair.txns.h24?.sells),
55
+ chg_m5: fin(pair.priceChange.m5), chg_h1: fin(pair.priceChange.h1), chg_h6: fin(pair.priceChange.h6), chg_h24: fin(pair.priceChange.h24),
56
+ pair_address: pair.pairAddress || null,
57
+ dex: pair.dex && pair.dex !== 'unknown' ? pair.dex : null,
58
+ pair_created_at: src === 'dexscreener' ? fin(pair.createdAt) : null,
59
+ src_market: src,
60
+ holder_count: fin(stats?.holderCount),
61
+ holders_chg_pct: fin(stats?.holders24hDelta),
62
+ top_holders_pct: fin(audit?.top10Pct),
63
+ dev_pct: fin(audit?.devPct),
64
+ dev_mints: fin(audit?.devMints),
65
+ organic_score: fin(stats?.organicScore),
66
+ num_traders_h1: fin(h1?.numTraders),
67
+ net_buyers_h1: fin(h1?.numNetBuyers),
68
+ buy_vol_h1: fin(h1?.buyVol),
69
+ sell_vol_h1: fin(h1?.sellVol),
70
+ mint_auth_enabled: bool(audit?.mintAuthority),
71
+ freeze_auth_enabled: bool(audit?.freezeAuthority),
72
+ is_verified: bool(token.verified),
73
+ is_sus: bool(token.sus),
74
+ src_audit: audit?.source ?? null,
75
+ rug_score: fin(audit?.rugScore),
76
+ lp_locked_pct: fin(audit?.lpLockedPct),
77
+ src_risk: null,
78
+ sources: [...r.sources],
79
+ };
80
+ const t = Math.max(token.fetchedAt || 0, pair.fetchedAt || 0, stats?.fetchedAt ?? 0, audit?.fetchedAt ?? 0);
81
+ return { columns, t, hash: hashColumns(columns), raw: { token, pair, stats: stats ?? null, audit: audit ?? null, mcap: r.mcap ?? null } };
82
+ }
83
+ /**
84
+ * Snapshot columns from a DexScreener pair view (an outcome sweep). Identity fields the pair does not
85
+ * carry (launchpad, created_at from Jupiter) are taken from `base`, the mint's last stored row.
86
+ */
87
+ export function fromDsView(mint, view, base, fetchedAt) {
88
+ const empty = {
89
+ mint, symbol: base?.symbol ?? null, name: base?.name ?? null, launchpad: base?.launchpad ?? null, created_at: base?.created_at ?? null,
90
+ price_usd: null, mcap: null, mcap_resolved: null, mcap_flagged: null, fdv: null, liquidity_usd: null,
91
+ vol_m5: null, vol_h1: null, vol_h6: null, vol_h24: null, buys_m5: null, sells_m5: null, buys_h1: null, sells_h1: null, buys_h24: null, sells_h24: null,
92
+ chg_m5: null, chg_h1: null, chg_h6: null, chg_h24: null, pair_address: null, dex: null, pair_created_at: null, src_market: 'none',
93
+ holder_count: null, holders_chg_pct: null, top_holders_pct: null, dev_pct: null, dev_mints: null, organic_score: null,
94
+ num_traders_h1: null, net_buyers_h1: null, buy_vol_h1: null, sell_vol_h1: null, mint_auth_enabled: null, freeze_auth_enabled: null,
95
+ is_verified: null, is_sus: null, src_audit: null, rug_score: null, lp_locked_pct: null, src_risk: null, sources: [],
96
+ };
97
+ if (!view)
98
+ return { columns: empty, t: fetchedAt, hash: hashColumns(empty), raw: { note: 'no DexScreener pair returned' } };
99
+ const { pair, token } = view;
100
+ const columns = {
101
+ ...empty,
102
+ symbol: empty.symbol ?? cleanText(token.symbol, SYMBOL_MAX),
103
+ name: empty.name ?? cleanText(token.name, NAME_MAX),
104
+ launchpad: empty.launchpad ?? token.launchpad ?? null,
105
+ created_at: empty.created_at ?? fin(pair.createdAt),
106
+ price_usd: fin(pair.priceUsd), mcap: fin(pair.mcap), fdv: fin(pair.fdv), liquidity_usd: fin(pair.liquidityUsd),
107
+ vol_m5: fin(pair.volume.m5), vol_h1: fin(pair.volume.h1), vol_h6: fin(pair.volume.h6), vol_h24: fin(pair.volume.h24),
108
+ buys_m5: fin(pair.txns.m5?.buys), sells_m5: fin(pair.txns.m5?.sells), buys_h1: fin(pair.txns.h1?.buys), sells_h1: fin(pair.txns.h1?.sells),
109
+ buys_h24: fin(pair.txns.h24?.buys), sells_h24: fin(pair.txns.h24?.sells),
110
+ chg_m5: fin(pair.priceChange.m5), chg_h1: fin(pair.priceChange.h1), chg_h6: fin(pair.priceChange.h6), chg_h24: fin(pair.priceChange.h24),
111
+ pair_address: pair.pairAddress || null, dex: pair.dex || null, pair_created_at: fin(pair.createdAt),
112
+ src_market: 'dexscreener', sources: ['dexscreener'],
113
+ };
114
+ return { columns, t: pair.fetchedAt || fetchedAt, hash: hashColumns(columns), raw: { token, pair } };
115
+ }
116
+ /** Stable hash of the columns (key order fixed by the interface literal above). */
117
+ export function hashColumns(c) {
118
+ return createHash('sha256').update(JSON.stringify(c)).digest('base64url').slice(0, 22);
119
+ }
120
+ /**
121
+ * Material change (task-1329 measurements). The live app holds a ~500-row pool that is re-enriched about
122
+ * once a minute and almost every memecoin price moves a little every time: "hash of the exact record"
123
+ * wrote ~4 rows/s (≈ 120 MB per 8 h day, columns only) and 1 % thresholds + a 5 min heartbeat still
124
+ * ≈ 120 MB/day, against the design's 10 MB estimate for 60 rows. A snapshot is worth a row when
125
+ * something MATERIAL moved against the LAST WRITTEN row (hysteresis: a slow drift is written once it adds
126
+ * up, a value sitting on a threshold never flaps): price / market cap / liquidity by ≥ 5 %, holders by
127
+ * ≥ 10 %, volumes by ≥ 20 %, trade counts by ≥ 25 %, a percentage-change field by ≥ 5 points, a share /
128
+ * score by ≥ 2 points, or any identity / authority / source field at all. The labels work on ratios of
129
+ * 0.5× and 2×, so 5 % resolution loses nothing they can see; the hourly t0 anchor and the heartbeat
130
+ * (30 min) bound how stale a stored row can be.
131
+ */
132
+ export const MATERIAL = {
133
+ rel5: ['price_usd', 'mcap', 'mcap_resolved', 'fdv', 'liquidity_usd'],
134
+ rel10: ['holder_count'],
135
+ rel20: ['vol_m5', 'vol_h1', 'vol_h6', 'vol_h24', 'buy_vol_h1', 'sell_vol_h1'],
136
+ rel25: ['buys_m5', 'sells_m5', 'buys_h1', 'sells_h1', 'buys_h24', 'sells_h24', 'num_traders_h1', 'net_buyers_h1'],
137
+ abs5: ['chg_m5', 'chg_h1', 'chg_h6', 'chg_h24', 'holders_chg_pct'],
138
+ abs2: ['top_holders_pct', 'dev_pct', 'organic_score', 'rug_score', 'lp_locked_pct'],
139
+ };
140
+ const NUMERIC = new Set([...MATERIAL.rel5, ...MATERIAL.rel10, ...MATERIAL.rel20, ...MATERIAL.rel25, ...MATERIAL.abs5, ...MATERIAL.abs2]);
141
+ /** Relative to the previous (written) value: 100 → 110 is a 10 % move, 0 → anything is a move. */
142
+ function relMoved(a, b, frac) {
143
+ if (a === null || b === null)
144
+ return a !== b;
145
+ if (a === b)
146
+ return false;
147
+ if (a === 0)
148
+ return true;
149
+ return Math.abs(a - b) / Math.abs(a) >= frac;
150
+ }
151
+ function absMoved(a, b, unit) {
152
+ if (a === null || b === null)
153
+ return a !== b;
154
+ return Math.abs(a - b) >= unit;
155
+ }
156
+ /** True when `next` differs materially from `prev` (the last written row of the same mint). */
157
+ export function isMaterialChange(prev, next) {
158
+ for (const k of MATERIAL.rel5)
159
+ if (relMoved(prev[k], next[k], 0.05))
160
+ return true;
161
+ for (const k of MATERIAL.rel10)
162
+ if (relMoved(prev[k], next[k], 0.10))
163
+ return true;
164
+ for (const k of MATERIAL.rel20)
165
+ if (relMoved(prev[k], next[k], 0.20))
166
+ return true;
167
+ for (const k of MATERIAL.rel25)
168
+ if (relMoved(prev[k], next[k], 0.25))
169
+ return true;
170
+ for (const k of MATERIAL.abs5)
171
+ if (absMoved(prev[k], next[k], 5))
172
+ return true;
173
+ for (const k of MATERIAL.abs2)
174
+ if (absMoved(prev[k], next[k], 2))
175
+ return true;
176
+ for (const k of COLUMN_NAMES) {
177
+ if (NUMERIC.has(k))
178
+ continue;
179
+ if (prev[k] !== next[k])
180
+ return true;
181
+ }
182
+ return prev.sources.join() !== next.sources.join();
183
+ }
184
+ /** Column names in insert order (everything in SnapshotColumns except `sources`, which is JSON). */
185
+ export const COLUMN_NAMES = [
186
+ 'mint', 'symbol', 'name', 'launchpad', 'created_at', 'price_usd', 'mcap', 'mcap_resolved', 'mcap_flagged', 'fdv', 'liquidity_usd',
187
+ 'vol_m5', 'vol_h1', 'vol_h6', 'vol_h24', 'buys_m5', 'sells_m5', 'buys_h1', 'sells_h1', 'buys_h24', 'sells_h24',
188
+ 'chg_m5', 'chg_h1', 'chg_h6', 'chg_h24', 'pair_address', 'dex', 'pair_created_at', 'src_market',
189
+ 'holder_count', 'holders_chg_pct', 'top_holders_pct', 'dev_pct', 'dev_mints', 'organic_score', 'num_traders_h1', 'net_buyers_h1',
190
+ 'buy_vol_h1', 'sell_vol_h1', 'mint_auth_enabled', 'freeze_auth_enabled', 'is_verified', 'is_sus', 'src_audit', 'rug_score', 'lp_locked_pct', 'src_risk',
191
+ ];
@@ -0,0 +1,52 @@
1
+ // Outcome-sweep scheduling (AI-SUITE-DESIGN §4.1 "outcome": re-observe every recorded mint at the
2
+ // horizons 1 h, 2 h, 6 h, 24 h, 72 h). Pure functions over the per-mint summary so the rule is testable
3
+ // without a database.
4
+ //
5
+ // The rule. The app observes a token continuously while it is on screen (every refresh writes a row
6
+ // when something changed, and a heartbeat row otherwise), so a horizon measured from any t0 while the
7
+ // token stayed visible is already covered by the live rows. A re-observation is only needed once the
8
+ // token has LEFT the screen: with L = the newest live observation of a mint and A = its newest
9
+ // observation of any kind, horizon h is due iff
10
+ // h <= now - L < 2h (the window [L+h, L+2h] is open; labels.md: first observation at or after
11
+ // t0+h within 2x)
12
+ // A < L + h (nothing, live or sweep, has been seen since the window opened)
13
+ // One sweep row at `now` then serves every t0 of that mint whose window contains `now` — including the
14
+ // earlier t0s (first sighting F): if the token was visible for less than h, L+h lands inside
15
+ // [F+h, F+2h]; if it was visible longer, the live rows already covered F's horizon h.
16
+ // Because a sweep row is `kind = 'sweep'`, it moves A but not L, so the same horizon is never re-swept
17
+ // and the next horizon comes due relative to the same L: five re-observations per departure, no more.
18
+ import { HORIZONS_SEC } from "./schema.js";
19
+ /** Horizons due for one mint at `now`, smallest first. */
20
+ export function dueHorizons(m, now, horizons = HORIZONS_SEC) {
21
+ const out = [];
22
+ const age = now - m.last_live_t;
23
+ for (const h of horizons) {
24
+ const ms = h * 1000;
25
+ if (age >= ms && age < 2 * ms && m.last_any_t < m.last_live_t + ms)
26
+ out.push(h);
27
+ }
28
+ return out;
29
+ }
30
+ /**
31
+ * The mints to re-observe now, at most `max`, soonest-closing window first. A mint with several horizons
32
+ * due at once (it left the screen hours ago and the app was closed) is listed once: one observation
33
+ * serves all of them.
34
+ */
35
+ export function selectDue(rows, now, max, horizons = HORIZONS_SEC) {
36
+ const due = [];
37
+ for (const m of rows) {
38
+ const hs = dueHorizons(m, now, horizons);
39
+ if (!hs.length)
40
+ continue;
41
+ const h = hs[0];
42
+ due.push({ mint: m.mint, horizon_sec: h, closes_at: m.last_live_t + 2 * h * 1000 });
43
+ }
44
+ due.sort((a, b) => a.closes_at - b.closes_at || a.mint.localeCompare(b.mint));
45
+ return due.slice(0, max);
46
+ }
47
+ /** Bounds on `last_live_t` outside which no horizon can be due: [now - 2*maxH, now - minH]. */
48
+ export function dueBounds(now, horizons = HORIZONS_SEC) {
49
+ const min = Math.min(...horizons) * 1000;
50
+ const max = Math.max(...horizons) * 1000;
51
+ return { from: now - 2 * max, to: now - min };
52
+ }
@@ -0,0 +1,52 @@
1
+ // LARP verdict join (task-1359): the app writes the LARP detector's settled product verdicts into the recorder's
2
+ // `verdicts` table (pack `larp-check`, via @dexterm/packs recordVerdict) and the LARP eval reads them back here,
3
+ // joined to the outcome labels. The prototype DB (research/task-1287/recorder/history.sqlite) has the same
4
+ // `verdicts` + `outcomes` columns, so the join runs on both. Reads never throw on a missing table.
5
+ import { isPositive } from "./labels.js";
6
+ /** The pack name a LARP-detector verdict is stored under. */
7
+ export const LARP_PACK = 'larp-check';
8
+ /** The product-assessment verdicts the analyst may return (analyst/session.ts). */
9
+ export const LARP_VERDICTS = ['REAL_PRODUCT', 'EARLY_BUT_REAL', 'LARP', 'UNVERIFIABLE'];
10
+ const hasTable = (db, name) => {
11
+ try {
12
+ return !!db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(name);
13
+ }
14
+ catch {
15
+ return false;
16
+ }
17
+ };
18
+ /**
19
+ * Join every recorded LARP verdict to an outcome label: the latest t0 anchor of the same mint at or before the
20
+ * verdict, no more than `slackSec` earlier (default 10 % of the horizon). The label then describes what the coin
21
+ * did from (just before) the verdict to the horizon; an anchor long before the verdict would let the verdict see
22
+ * most of the outcome window, so it is not matched. `unobserved` labels count as unmatched.
23
+ */
24
+ export function readLarpJoin(db, horizonSec, slackSec = Math.round(horizonSec * 0.1)) {
25
+ const out = { horizon_sec: horizonSec, slack_sec: slackSec, verdicts_recorded: 0, rows: [], outcomes_at_horizon: 0, outcome_counts: {}, unobserved_at_horizon: 0 };
26
+ if (hasTable(db, 'outcomes')) {
27
+ const counts = db.prepare('SELECT label, COUNT(*) AS n FROM outcomes WHERE horizon_sec = ? GROUP BY label').all(horizonSec);
28
+ for (const c of counts) {
29
+ if (c.label === 'unobserved') {
30
+ out.unobserved_at_horizon += c.n;
31
+ continue;
32
+ }
33
+ out.outcome_counts[c.label] = c.n;
34
+ out.outcomes_at_horizon += c.n;
35
+ }
36
+ }
37
+ if (!hasTable(db, 'verdicts'))
38
+ return out;
39
+ const verdicts = db.prepare('SELECT mint, t, verdict, confidence FROM verdicts WHERE pack = ? AND verdict IS NOT NULL ORDER BY t').all(LARP_PACK);
40
+ out.verdicts_recorded = verdicts.length;
41
+ const canJoin = hasTable(db, 'outcomes');
42
+ const q = canJoin ? db.prepare('SELECT t0, label, label_tier FROM outcomes WHERE mint = ? AND horizon_sec = ? AND t0 <= ? AND t0 >= ? ORDER BY t0 DESC LIMIT 1') : null;
43
+ for (const v of verdicts) {
44
+ const o = q?.get(v.mint, horizonSec, v.t, v.t - slackSec * 1000);
45
+ const observed = o && o.label !== 'unobserved' ? o : null;
46
+ out.rows.push({
47
+ mint: v.mint, t: v.t, verdict: v.verdict, confidence: typeof v.confidence === 'number' ? v.confidence : null,
48
+ label: observed?.label ?? null, tier: observed?.label_tier ?? null, positive: observed ? isPositive(observed.label, observed.label_tier) : null, t0: observed?.t0 ?? null,
49
+ });
50
+ }
51
+ return out;
52
+ }