@reefclaw/connect 0.1.10 → 0.1.12

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 (396) hide show
  1. package/assets/bridge/gateway/event-parser.d.ts +6 -1
  2. package/assets/bridge/gateway/event-parser.js +19 -2
  3. package/assets/bridge/gateway/heartbeat-cron.d.ts +27 -0
  4. package/assets/bridge/gateway/heartbeat-cron.js +85 -0
  5. package/assets/bridge/gateway/poller.d.ts +1 -0
  6. package/assets/bridge/gateway/poller.js +14 -2
  7. package/assets/bridge/providers/gateway.d.ts +24 -2
  8. package/assets/bridge/providers/gateway.js +124 -25
  9. package/assets/bridge/setup.js +6 -51
  10. package/assets/shared/signals/conditions/registry.js +11 -2
  11. package/assets/shared/signals/strategy-adapter.js +17 -7
  12. package/assets/skill/SKILL.md +2 -0
  13. package/dist/deps.js +2 -2
  14. package/dist/plugin.js +35 -7
  15. package/package.json +1 -1
  16. package/assets/plugin/audit/mode-transition-audit.d.ts +0 -11
  17. package/assets/plugin/audit/mode-transition-audit.js +0 -29
  18. package/assets/plugin/balance-utils.d.ts +0 -36
  19. package/assets/plugin/balance-utils.js +0 -98
  20. package/assets/plugin/ccxt/binance-ban-gate.d.ts +0 -47
  21. package/assets/plugin/ccxt/binance-ban-gate.js +0 -420
  22. package/assets/plugin/ccxt/binance-private.d.ts +0 -346
  23. package/assets/plugin/ccxt/binance-private.js +0 -1525
  24. package/assets/plugin/ccxt/binance-public.d.ts +0 -34
  25. package/assets/plugin/ccxt/binance-public.js +0 -180
  26. package/assets/plugin/ccxt/intel-public.d.ts +0 -25
  27. package/assets/plugin/ccxt/intel-public.js +0 -80
  28. package/assets/plugin/ccxt/public-market-data-api.d.ts +0 -12
  29. package/assets/plugin/ccxt/public-market-data-api.js +0 -9
  30. package/assets/plugin/config/agent-config-client.d.ts +0 -77
  31. package/assets/plugin/config/agent-config-client.js +0 -188
  32. package/assets/plugin/config/agent-config-poller.d.ts +0 -32
  33. package/assets/plugin/config/agent-config-poller.js +0 -101
  34. package/assets/plugin/config/brackets-config.d.ts +0 -22
  35. package/assets/plugin/config/brackets-config.js +0 -58
  36. package/assets/plugin/config/entitlement-gate.d.ts +0 -51
  37. package/assets/plugin/config/entitlement-gate.js +0 -137
  38. package/assets/plugin/config/gate-store.d.ts +0 -18
  39. package/assets/plugin/config/gate-store.js +0 -61
  40. package/assets/plugin/config/plugin-config-io.d.ts +0 -215
  41. package/assets/plugin/config/plugin-config-io.js +0 -111
  42. package/assets/plugin/config/position-review-config.d.ts +0 -35
  43. package/assets/plugin/config/position-review-config.js +0 -105
  44. package/assets/plugin/config/tool-gate.d.ts +0 -53
  45. package/assets/plugin/config/tool-gate.js +0 -128
  46. package/assets/plugin/config/user-data-stream-config.d.ts +0 -89
  47. package/assets/plugin/config/user-data-stream-config.js +0 -239
  48. package/assets/plugin/connector-supervisor.d.ts +0 -36
  49. package/assets/plugin/connector-supervisor.js +0 -149
  50. package/assets/plugin/exchange-adapter.d.ts +0 -65
  51. package/assets/plugin/exchange-adapter.js +0 -4
  52. package/assets/plugin/index.d.ts +0 -30
  53. package/assets/plugin/index.js +0 -2678
  54. package/assets/plugin/ingest/pending-entry-metadata.d.ts +0 -74
  55. package/assets/plugin/ingest/pending-entry-metadata.js +0 -236
  56. package/assets/plugin/ingest/position-auto-capture.d.ts +0 -103
  57. package/assets/plugin/ingest/position-auto-capture.js +0 -411
  58. package/assets/plugin/ingest/position-decisions-client.d.ts +0 -322
  59. package/assets/plugin/ingest/position-decisions-client.js +0 -296
  60. package/assets/plugin/ingest/readiness-reporter.d.ts +0 -42
  61. package/assets/plugin/ingest/readiness-reporter.js +0 -163
  62. package/assets/plugin/ingest/reconcile-db-vs-exchange.d.ts +0 -13
  63. package/assets/plugin/ingest/reconcile-db-vs-exchange.js +0 -114
  64. package/assets/plugin/ingest/reconciler-cleanup.d.ts +0 -37
  65. package/assets/plugin/ingest/reconciler-cleanup.js +0 -147
  66. package/assets/plugin/ingest/rest-gap-filler.d.ts +0 -191
  67. package/assets/plugin/ingest/rest-gap-filler.js +0 -565
  68. package/assets/plugin/ingest/touched-symbols-store.d.ts +0 -25
  69. package/assets/plugin/ingest/touched-symbols-store.js +0 -96
  70. package/assets/plugin/ingest/trade-store-client.d.ts +0 -40
  71. package/assets/plugin/ingest/trade-store-client.js +0 -125
  72. package/assets/plugin/ingest/ws-ingest.d.ts +0 -43
  73. package/assets/plugin/ingest/ws-ingest.js +0 -126
  74. package/assets/plugin/learning/setup-family.d.ts +0 -21
  75. package/assets/plugin/learning/setup-family.js +0 -103
  76. package/assets/plugin/lifecycle/install-signal-handlers.d.ts +0 -33
  77. package/assets/plugin/lifecycle/install-signal-handlers.js +0 -112
  78. package/assets/plugin/lifecycle/shutdown-coordinator.d.ts +0 -43
  79. package/assets/plugin/lifecycle/shutdown-coordinator.js +0 -131
  80. package/assets/plugin/lifecycle/trading-operation-lock.d.ts +0 -17
  81. package/assets/plugin/lifecycle/trading-operation-lock.js +0 -14
  82. package/assets/plugin/live/bracket-id.d.ts +0 -26
  83. package/assets/plugin/live/bracket-id.js +0 -112
  84. package/assets/plugin/live/bracket-ledger.d.ts +0 -54
  85. package/assets/plugin/live/bracket-ledger.js +0 -267
  86. package/assets/plugin/live/bracket-manager.d.ts +0 -82
  87. package/assets/plugin/live/bracket-manager.js +0 -478
  88. package/assets/plugin/live/bracket-params.d.ts +0 -22
  89. package/assets/plugin/live/bracket-params.js +0 -124
  90. package/assets/plugin/live/bracket-reconciler.d.ts +0 -95
  91. package/assets/plugin/live/bracket-reconciler.js +0 -573
  92. package/assets/plugin/live/bracket-types.d.ts +0 -102
  93. package/assets/plugin/live/bracket-types.js +0 -8
  94. package/assets/plugin/live/deposit-tracker.d.ts +0 -62
  95. package/assets/plugin/live/deposit-tracker.js +0 -97
  96. package/assets/plugin/live/emergency-controls.d.ts +0 -32
  97. package/assets/plugin/live/emergency-controls.js +0 -226
  98. package/assets/plugin/live/exchange-errors.d.ts +0 -12
  99. package/assets/plugin/live/exchange-errors.js +0 -130
  100. package/assets/plugin/live/exchange-info-cache.d.ts +0 -37
  101. package/assets/plugin/live/exchange-info-cache.js +0 -134
  102. package/assets/plugin/live/fact-subscriber.d.ts +0 -78
  103. package/assets/plugin/live/fact-subscriber.js +0 -182
  104. package/assets/plugin/live/intent-journal.d.ts +0 -42
  105. package/assets/plugin/live/intent-journal.js +0 -122
  106. package/assets/plugin/live/listen-key-manager.d.ts +0 -70
  107. package/assets/plugin/live/listen-key-manager.js +0 -169
  108. package/assets/plugin/live/live-adapter.d.ts +0 -287
  109. package/assets/plugin/live/live-adapter.js +0 -1777
  110. package/assets/plugin/live/live-balance-enricher.d.ts +0 -32
  111. package/assets/plugin/live/live-balance-enricher.js +0 -104
  112. package/assets/plugin/live/live-bracket-api.d.ts +0 -13
  113. package/assets/plugin/live/live-bracket-api.js +0 -20
  114. package/assets/plugin/live/live-state-store.d.ts +0 -194
  115. package/assets/plugin/live/live-state-store.js +0 -450
  116. package/assets/plugin/live/local-signal-service.d.ts +0 -57
  117. package/assets/plugin/live/local-signal-service.js +0 -151
  118. package/assets/plugin/live/local-strategy-evaluator.d.ts +0 -62
  119. package/assets/plugin/live/local-strategy-evaluator.js +0 -131
  120. package/assets/plugin/live/microstructure-assembler.d.ts +0 -54
  121. package/assets/plugin/live/microstructure-assembler.js +0 -148
  122. package/assets/plugin/live/order-poller.d.ts +0 -29
  123. package/assets/plugin/live/order-poller.js +0 -125
  124. package/assets/plugin/live/position-state-store.d.ts +0 -83
  125. package/assets/plugin/live/position-state-store.js +0 -237
  126. package/assets/plugin/live/proposal-decision-listener.d.ts +0 -70
  127. package/assets/plugin/live/proposal-decision-listener.js +0 -292
  128. package/assets/plugin/live/proposal-manager.d.ts +0 -76
  129. package/assets/plugin/live/proposal-manager.js +0 -140
  130. package/assets/plugin/live/rate-limiter.d.ts +0 -47
  131. package/assets/plugin/live/rate-limiter.js +0 -159
  132. package/assets/plugin/live/reconciler.d.ts +0 -39
  133. package/assets/plugin/live/reconciler.js +0 -175
  134. package/assets/plugin/live/setup-buckets.d.ts +0 -7
  135. package/assets/plugin/live/setup-buckets.js +0 -33
  136. package/assets/plugin/live/slippage-tracker.d.ts +0 -45
  137. package/assets/plugin/live/slippage-tracker.js +0 -78
  138. package/assets/plugin/live/stop-watcher.d.ts +0 -60
  139. package/assets/plugin/live/stop-watcher.js +0 -215
  140. package/assets/plugin/live/user-data-active-probe.d.ts +0 -54
  141. package/assets/plugin/live/user-data-active-probe.js +0 -180
  142. package/assets/plugin/live/user-data-stream-controller.d.ts +0 -200
  143. package/assets/plugin/live/user-data-stream-controller.js +0 -579
  144. package/assets/plugin/live/user-data-stream-ws.d.ts +0 -22
  145. package/assets/plugin/live/user-data-stream-ws.js +0 -63
  146. package/assets/plugin/live/user-data-stream.d.ts +0 -243
  147. package/assets/plugin/live/user-data-stream.js +0 -704
  148. package/assets/plugin/logger.d.ts +0 -2
  149. package/assets/plugin/logger.js +0 -2
  150. package/assets/plugin/mfe.d.ts +0 -21
  151. package/assets/plugin/mfe.js +0 -68
  152. package/assets/plugin/onboarding/mode-ladder.d.ts +0 -1
  153. package/assets/plugin/onboarding/mode-ladder.js +0 -3
  154. package/assets/plugin/onboarding/runtime.d.ts +0 -84
  155. package/assets/plugin/onboarding/runtime.js +0 -173
  156. package/assets/plugin/openclaw.plugin.json +0 -92
  157. package/assets/plugin/paper-adapter.d.ts +0 -24
  158. package/assets/plugin/paper-adapter.js +0 -91
  159. package/assets/plugin/persistence/state-manager.d.ts +0 -66
  160. package/assets/plugin/persistence/state-manager.js +0 -222
  161. package/assets/plugin/pinned-plan.d.ts +0 -9
  162. package/assets/plugin/pinned-plan.js +0 -23
  163. package/assets/plugin/portfolio/wave9-admission.d.ts +0 -67
  164. package/assets/plugin/portfolio/wave9-admission.js +0 -262
  165. package/assets/plugin/portfolio/wave9-policy.d.ts +0 -36
  166. package/assets/plugin/portfolio/wave9-policy.js +0 -183
  167. package/assets/plugin/risk/pre-trade-check.d.ts +0 -38
  168. package/assets/plugin/risk/pre-trade-check.js +0 -345
  169. package/assets/plugin/risk/pre-trade-types.d.ts +0 -60
  170. package/assets/plugin/risk/pre-trade-types.js +0 -3
  171. package/assets/plugin/shadow/shadow-tracker.d.ts +0 -36
  172. package/assets/plugin/shadow/shadow-tracker.js +0 -151
  173. package/assets/plugin/shadow/types.d.ts +0 -42
  174. package/assets/plugin/shadow/types.js +0 -20
  175. package/assets/plugin/shared/indicators-extended.d.ts +0 -52
  176. package/assets/plugin/shared/indicators-extended.js +0 -291
  177. package/assets/plugin/shared/indicators.d.ts +0 -15
  178. package/assets/plugin/shared/indicators.js +0 -114
  179. package/assets/plugin/signals/conditions/registry.d.ts +0 -16
  180. package/assets/plugin/signals/conditions/registry.js +0 -1324
  181. package/assets/plugin/signals/conditions/types.d.ts +0 -1
  182. package/assets/plugin/signals/conditions/types.js +0 -4
  183. package/assets/plugin/signals/direction-rules.d.ts +0 -3
  184. package/assets/plugin/signals/direction-rules.js +0 -24
  185. package/assets/plugin/signals/entry-rules.d.ts +0 -6
  186. package/assets/plugin/signals/entry-rules.js +0 -33
  187. package/assets/plugin/signals/serialize-context.d.ts +0 -4
  188. package/assets/plugin/signals/serialize-context.js +0 -39
  189. package/assets/plugin/signals/stop-rules.d.ts +0 -3
  190. package/assets/plugin/signals/stop-rules.js +0 -48
  191. package/assets/plugin/signals/strategy-adapter.d.ts +0 -47
  192. package/assets/plugin/signals/strategy-adapter.js +0 -199
  193. package/assets/plugin/signals/types.d.ts +0 -1
  194. package/assets/plugin/signals/types.js +0 -8
  195. package/assets/plugin/simulator/exchange-simulator.d.ts +0 -93
  196. package/assets/plugin/simulator/exchange-simulator.js +0 -689
  197. package/assets/plugin/simulator/fill-engine.d.ts +0 -53
  198. package/assets/plugin/simulator/fill-engine.js +0 -280
  199. package/assets/plugin/simulator/paper-market-feed.d.ts +0 -26
  200. package/assets/plugin/simulator/paper-market-feed.js +0 -104
  201. package/assets/plugin/simulator/realistic-fills.d.ts +0 -59
  202. package/assets/plugin/simulator/realistic-fills.js +0 -175
  203. package/assets/plugin/simulator/types.d.ts +0 -224
  204. package/assets/plugin/simulator/types.js +0 -43
  205. package/assets/plugin/strategy/builtin-strategies.d.ts +0 -2
  206. package/assets/plugin/strategy/builtin-strategies.js +0 -113
  207. package/assets/plugin/strategy/condition-registry.d.ts +0 -3
  208. package/assets/plugin/strategy/condition-registry.js +0 -153
  209. package/assets/plugin/strategy/evaluator.d.ts +0 -70
  210. package/assets/plugin/strategy/evaluator.js +0 -98
  211. package/assets/plugin/tools/assessment-validation.d.ts +0 -120
  212. package/assets/plugin/tools/assessment-validation.js +0 -415
  213. package/assets/plugin/tools/attach-brackets.d.ts +0 -39
  214. package/assets/plugin/tools/attach-brackets.js +0 -399
  215. package/assets/plugin/tools/audit-bracket-protection.d.ts +0 -49
  216. package/assets/plugin/tools/audit-bracket-protection.js +0 -527
  217. package/assets/plugin/tools/cancel-all-orders.d.ts +0 -9
  218. package/assets/plugin/tools/cancel-all-orders.js +0 -8
  219. package/assets/plugin/tools/cancel-order.d.ts +0 -14
  220. package/assets/plugin/tools/cancel-order.js +0 -60
  221. package/assets/plugin/tools/check-position-health.d.ts +0 -46
  222. package/assets/plugin/tools/check-position-health.js +0 -194
  223. package/assets/plugin/tools/clear-exchange-credentials.d.ts +0 -24
  224. package/assets/plugin/tools/clear-exchange-credentials.js +0 -70
  225. package/assets/plugin/tools/close-position.d.ts +0 -45
  226. package/assets/plugin/tools/close-position.js +0 -722
  227. package/assets/plugin/tools/create-order.d.ts +0 -82
  228. package/assets/plugin/tools/create-order.js +0 -1516
  229. package/assets/plugin/tools/exit-gate.d.ts +0 -58
  230. package/assets/plugin/tools/exit-gate.js +0 -162
  231. package/assets/plugin/tools/fetch-balance.d.ts +0 -5
  232. package/assets/plugin/tools/fetch-balance.js +0 -4
  233. package/assets/plugin/tools/fetch-ohlcv.d.ts +0 -11
  234. package/assets/plugin/tools/fetch-ohlcv.js +0 -8
  235. package/assets/plugin/tools/fetch-open-orders.d.ts +0 -7
  236. package/assets/plugin/tools/fetch-open-orders.js +0 -4
  237. package/assets/plugin/tools/fetch-positions.d.ts +0 -7
  238. package/assets/plugin/tools/fetch-positions.js +0 -4
  239. package/assets/plugin/tools/fetch-ticker.d.ts +0 -11
  240. package/assets/plugin/tools/fetch-ticker.js +0 -5
  241. package/assets/plugin/tools/get-agent-profile.d.ts +0 -4
  242. package/assets/plugin/tools/get-agent-profile.js +0 -6
  243. package/assets/plugin/tools/get-analytics.d.ts +0 -6
  244. package/assets/plugin/tools/get-analytics.js +0 -7
  245. package/assets/plugin/tools/get-backtest.d.ts +0 -12
  246. package/assets/plugin/tools/get-backtest.js +0 -91
  247. package/assets/plugin/tools/get-basis.d.ts +0 -7
  248. package/assets/plugin/tools/get-basis.js +0 -7
  249. package/assets/plugin/tools/get-bracket-config.d.ts +0 -11
  250. package/assets/plugin/tools/get-bracket-config.js +0 -24
  251. package/assets/plugin/tools/get-cascade-risk.d.ts +0 -7
  252. package/assets/plugin/tools/get-cascade-risk.js +0 -8
  253. package/assets/plugin/tools/get-crypto-metrics.d.ts +0 -18
  254. package/assets/plugin/tools/get-crypto-metrics.js +0 -62
  255. package/assets/plugin/tools/get-cvd.d.ts +0 -6
  256. package/assets/plugin/tools/get-cvd.js +0 -6
  257. package/assets/plugin/tools/get-divergences.d.ts +0 -6
  258. package/assets/plugin/tools/get-divergences.js +0 -6
  259. package/assets/plugin/tools/get-funding-context.d.ts +0 -6
  260. package/assets/plugin/tools/get-funding-context.js +0 -16
  261. package/assets/plugin/tools/get-liquidation-levels.d.ts +0 -7
  262. package/assets/plugin/tools/get-liquidation-levels.js +0 -7
  263. package/assets/plugin/tools/get-liquidation-pulse.d.ts +0 -9
  264. package/assets/plugin/tools/get-liquidation-pulse.js +0 -22
  265. package/assets/plugin/tools/get-market-breadth.d.ts +0 -6
  266. package/assets/plugin/tools/get-market-breadth.js +0 -8
  267. package/assets/plugin/tools/get-market-intel.d.ts +0 -19
  268. package/assets/plugin/tools/get-market-intel.js +0 -116
  269. package/assets/plugin/tools/get-market-structure.d.ts +0 -47
  270. package/assets/plugin/tools/get-market-structure.js +0 -198
  271. package/assets/plugin/tools/get-my-mined-patterns.d.ts +0 -20
  272. package/assets/plugin/tools/get-my-mined-patterns.js +0 -61
  273. package/assets/plugin/tools/get-my-proposed-learnings.d.ts +0 -20
  274. package/assets/plugin/tools/get-my-proposed-learnings.js +0 -55
  275. package/assets/plugin/tools/get-my-recent-reviews.d.ts +0 -22
  276. package/assets/plugin/tools/get-my-recent-reviews.js +0 -66
  277. package/assets/plugin/tools/get-orderbook.d.ts +0 -21
  278. package/assets/plugin/tools/get-orderbook.js +0 -32
  279. package/assets/plugin/tools/get-pattern-scan.d.ts +0 -7
  280. package/assets/plugin/tools/get-pattern-scan.js +0 -8
  281. package/assets/plugin/tools/get-regime.d.ts +0 -6
  282. package/assets/plugin/tools/get-regime.js +0 -7
  283. package/assets/plugin/tools/get-relevant-learnings.d.ts +0 -21
  284. package/assets/plugin/tools/get-relevant-learnings.js +0 -65
  285. package/assets/plugin/tools/get-resting-liquidity.d.ts +0 -6
  286. package/assets/plugin/tools/get-resting-liquidity.js +0 -11
  287. package/assets/plugin/tools/get-risk-scenario.d.ts +0 -29
  288. package/assets/plugin/tools/get-risk-scenario.js +0 -47
  289. package/assets/plugin/tools/get-risk-summary.d.ts +0 -51
  290. package/assets/plugin/tools/get-risk-summary.js +0 -118
  291. package/assets/plugin/tools/get-sentiment.d.ts +0 -4
  292. package/assets/plugin/tools/get-sentiment.js +0 -6
  293. package/assets/plugin/tools/get-session-review.d.ts +0 -7
  294. package/assets/plugin/tools/get-session-review.js +0 -8
  295. package/assets/plugin/tools/get-setup-detail.d.ts +0 -7
  296. package/assets/plugin/tools/get-setup-detail.js +0 -311
  297. package/assets/plugin/tools/get-signals.d.ts +0 -15
  298. package/assets/plugin/tools/get-signals.js +0 -54
  299. package/assets/plugin/tools/get-sizing.d.ts +0 -6
  300. package/assets/plugin/tools/get-sizing.js +0 -6
  301. package/assets/plugin/tools/get-trade-feedback.d.ts +0 -7
  302. package/assets/plugin/tools/get-trade-feedback.js +0 -8
  303. package/assets/plugin/tools/get-trade-flow.d.ts +0 -7
  304. package/assets/plugin/tools/get-trade-flow.js +0 -7
  305. package/assets/plugin/tools/get-volume-analysis.d.ts +0 -21
  306. package/assets/plugin/tools/get-volume-analysis.js +0 -74
  307. package/assets/plugin/tools/get-volume-profile.d.ts +0 -7
  308. package/assets/plugin/tools/get-volume-profile.js +0 -7
  309. package/assets/plugin/tools/get-wave9-status.d.ts +0 -127
  310. package/assets/plugin/tools/get-wave9-status.js +0 -796
  311. package/assets/plugin/tools/helpers.d.ts +0 -26
  312. package/assets/plugin/tools/helpers.js +0 -39
  313. package/assets/plugin/tools/intel-api.d.ts +0 -34
  314. package/assets/plugin/tools/intel-api.js +0 -119
  315. package/assets/plugin/tools/intel-cache.d.ts +0 -25
  316. package/assets/plugin/tools/intel-cache.js +0 -148
  317. package/assets/plugin/tools/list-strategies.d.ts +0 -17
  318. package/assets/plugin/tools/list-strategies.js +0 -23
  319. package/assets/plugin/tools/modify-stop.d.ts +0 -21
  320. package/assets/plugin/tools/modify-stop.js +0 -120
  321. package/assets/plugin/tools/modify-target.d.ts +0 -21
  322. package/assets/plugin/tools/modify-target.js +0 -110
  323. package/assets/plugin/tools/propose-learning.d.ts +0 -22
  324. package/assets/plugin/tools/propose-learning.js +0 -65
  325. package/assets/plugin/tools/query-review-outcomes.d.ts +0 -30
  326. package/assets/plugin/tools/query-review-outcomes.js +0 -64
  327. package/assets/plugin/tools/query-trades.d.ts +0 -21
  328. package/assets/plugin/tools/query-trades.js +0 -37
  329. package/assets/plugin/tools/record-position-reviews.d.ts +0 -38
  330. package/assets/plugin/tools/record-position-reviews.js +0 -147
  331. package/assets/plugin/tools/save-strategy.d.ts +0 -16
  332. package/assets/plugin/tools/save-strategy.js +0 -46
  333. package/assets/plugin/tools/scan-pairs.d.ts +0 -18
  334. package/assets/plugin/tools/scan-pairs.js +0 -231
  335. package/assets/plugin/tools/score-setup.d.ts +0 -31
  336. package/assets/plugin/tools/score-setup.js +0 -268
  337. package/assets/plugin/tools/set-bracket-requirement.d.ts +0 -18
  338. package/assets/plugin/tools/set-bracket-requirement.js +0 -81
  339. package/assets/plugin/tools/set-exchange-credentials.d.ts +0 -25
  340. package/assets/plugin/tools/set-exchange-credentials.js +0 -80
  341. package/assets/plugin/tools/set-trading-mode.d.ts +0 -26
  342. package/assets/plugin/tools/set-trading-mode.js +0 -135
  343. package/assets/plugin/tools/test-exchange-credentials.d.ts +0 -16
  344. package/assets/plugin/tools/test-exchange-credentials.js +0 -100
  345. package/assets/plugin/tools/toggle-strategy.d.ts +0 -8
  346. package/assets/plugin/tools/toggle-strategy.js +0 -15
  347. package/assets/plugin/trading-params-cache.d.ts +0 -26
  348. package/assets/plugin/trading-params-cache.js +0 -52
  349. package/assets/plugin/types.d.ts +0 -134
  350. package/assets/plugin/types.js +0 -7
  351. package/assets/plugin/util/plugin-paths.d.ts +0 -3
  352. package/assets/plugin/util/plugin-paths.js +0 -15
  353. package/assets/plugin/venues/hyperliquid/hl-balance.d.ts +0 -116
  354. package/assets/plugin/venues/hyperliquid/hl-balance.js +0 -145
  355. package/assets/plugin/venues/hyperliquid/hl-brackets.d.ts +0 -102
  356. package/assets/plugin/venues/hyperliquid/hl-brackets.js +0 -172
  357. package/assets/plugin/venues/hyperliquid/hl-cloid.d.ts +0 -22
  358. package/assets/plugin/venues/hyperliquid/hl-cloid.js +0 -82
  359. package/assets/plugin/venues/hyperliquid/hl-info-cache.d.ts +0 -46
  360. package/assets/plugin/venues/hyperliquid/hl-info-cache.js +0 -125
  361. package/assets/plugin/venues/hyperliquid/hl-live-adapter.d.ts +0 -88
  362. package/assets/plugin/venues/hyperliquid/hl-live-adapter.js +0 -353
  363. package/assets/plugin/venues/hyperliquid/hl-precision.d.ts +0 -61
  364. package/assets/plugin/venues/hyperliquid/hl-precision.js +0 -176
  365. package/assets/plugin/venues/hyperliquid/hl-private.d.ts +0 -88
  366. package/assets/plugin/venues/hyperliquid/hl-private.js +0 -357
  367. package/assets/plugin/venues/hyperliquid/hl-public.d.ts +0 -79
  368. package/assets/plugin/venues/hyperliquid/hl-public.js +0 -429
  369. package/assets/plugin/venues/hyperliquid/hl-rate-gate.d.ts +0 -57
  370. package/assets/plugin/venues/hyperliquid/hl-rate-gate.js +0 -220
  371. package/assets/plugin/venues/hyperliquid/hl-user-stream.d.ts +0 -90
  372. package/assets/plugin/venues/hyperliquid/hl-user-stream.js +0 -220
  373. package/assets/plugin/venues/registry.d.ts +0 -38
  374. package/assets/plugin/venues/registry.js +0 -46
  375. package/assets/plugin/venues/symbols.d.ts +0 -43
  376. package/assets/plugin/venues/symbols.js +0 -107
  377. package/assets/plugin/wave9/live-account-capture.d.ts +0 -67
  378. package/assets/plugin/wave9/live-account-capture.js +0 -435
  379. package/assets/plugin/wave9/live-autonomous-protection.d.ts +0 -39
  380. package/assets/plugin/wave9/live-autonomous-protection.js +0 -112
  381. package/assets/plugin/wave9/live-durable-reconciliation-scheduler.d.ts +0 -33
  382. package/assets/plugin/wave9/live-durable-reconciliation-scheduler.js +0 -115
  383. package/assets/plugin/wave9/live-execution-ledger.d.ts +0 -107
  384. package/assets/plugin/wave9/live-execution-ledger.js +0 -498
  385. package/assets/plugin/wave9/live-position-confirmation.d.ts +0 -18
  386. package/assets/plugin/wave9/live-position-confirmation.js +0 -111
  387. package/assets/plugin/wave9/live-residual-protection.d.ts +0 -18
  388. package/assets/plugin/wave9/live-residual-protection.js +0 -250
  389. package/assets/plugin/wave9/live-startup-reconciliation.d.ts +0 -38
  390. package/assets/plugin/wave9/live-startup-reconciliation.js +0 -454
  391. package/assets/plugin/wave9/live-symbol-ownership.d.ts +0 -20
  392. package/assets/plugin/wave9/live-symbol-ownership.js +0 -132
  393. package/assets/plugin/wave9/paper-admission-guard.d.ts +0 -199
  394. package/assets/plugin/wave9/paper-admission-guard.js +0 -650
  395. package/assets/plugin/wave9/usdm-evidence-provider.d.ts +0 -42
  396. package/assets/plugin/wave9/usdm-evidence-provider.js +0 -133
@@ -1,722 +0,0 @@
1
- // Tool: close_position — close a position at market (paper or live)
2
- // NO readiness gate — emergency control (flatten), must always work.
3
- //
4
- // SKILL.md v2.10.0 gate (Position Management Discipline): the agent must
5
- // submit a documented `reason` and (except for operator_command) a
6
- // structured `assessment` describing the reasoning behind the close. The
7
- // LLM's value is context-sensitive reasoning; we enforce the reasoning
8
- // at the API boundary via a schema, not a time floor.
9
- //
10
- // 2026-04-21 false-bracket_integrity safeguard: audit_bracket_protection
11
- // was observed reporting has_stop=false while the reconciler (same data
12
- // source, same call) consistently confirmed 2 live bracket orders on the
13
- // exchange. Agent used this false negative to trigger close_position with
14
- // reason=bracket_integrity, burning ~8–20 bps per cycle, 14+ cycles today.
15
- // Fix: before executing a bracket_integrity close, the plugin independently
16
- // verifies the ledger + exchange state. If the bracket is genuinely live
17
- // (ledger active/partial AND an exchange order matches the stored cid),
18
- // reject the close — audit was wrong, the position is protected. This is
19
- // a same-signal re-check at the API boundary, not a duplicate of the
20
- // audit tool; it catches the observed class of false negatives without
21
- // trusting the audit's own verdict.
22
- import { formatError, logger } from '../logger.js';
23
- import { fetchCurrentPrice, fetchOrderBook, isError } from './helpers.js';
24
- import { validateClosePosition, } from './assessment-validation.js';
25
- import { onClosePositionFilled } from '../ingest/position-auto-capture.js';
26
- import { evaluateExitGate, } from './exit-gate.js';
27
- import { getRecentAuditVerdictHistory } from './audit-bracket-protection.js';
28
- import { loadExitGateMode } from '../config/position-review-config.js';
29
- import { confirmWave9LivePositionFlat } from '../wave9/live-position-confirmation.js';
30
- import { reprotectWave9LiveResidual, } from '../wave9/live-residual-protection.js';
31
- import { captureWave9PaperPositionFingerprint, isWave9ManagedPosition, WAVE9_MECHANICAL_EXIT_REASON, } from '../wave9/paper-admission-guard.js';
32
- const TAG = 'close-position';
33
- function currentWave9ExecutionMode(deps) {
34
- const runtimeMode = deps.wave9TradingModeCheck?.() ?? deps.adapter.mode;
35
- if (!deps.adapter.isLive && deps.adapter.mode === 'PAPER' && runtimeMode === 'PAPER')
36
- return 'PAPER';
37
- if (deps.adapter.isLive && deps.adapter.mode === 'LIVE' && runtimeMode === 'LIVE')
38
- return 'LIVE';
39
- return null;
40
- }
41
- // Bracket-integrity circuit-breaker. Counts SUCCESSFUL close_position calls
42
- // with reason='bracket_integrity' in a rolling 60-min window. When the 3rd
43
- // such close is attempted, reject — repeated bracket-integrity flushes in
44
- // the same hour means EITHER the bracket subsystem is actually broken (in
45
- // which case the operator needs to know, not the agent quietly burning more
46
- // positions) OR the audit tool is false-negativing (same outcome: stop the
47
- // burn). 2026-05-15 session ran this exact pattern 3 times in 4 hours and
48
- // realised −$3.20 of bracket-integrity flushes before the operator caught it.
49
- const BRACKET_INTEGRITY_WINDOW_MS = 60 * 60 * 1000;
50
- const BRACKET_INTEGRITY_LIMIT = 3;
51
- let bracketIntegrityCloses = []; // timestamps of successful closes
52
- export async function closePositionTool(args, deps) {
53
- // Schema gate FIRST — reject before touching the exchange.
54
- const wave9ExitClaimed = args.reason !== 'operator_command' && (args.reason === WAVE9_MECHANICAL_EXIT_REASON
55
- || args.wave9_exit_token !== undefined
56
- || args.candidate_id !== undefined);
57
- if (wave9ExitClaimed && deps.wave9VenueCheck?.() !== 'binance') {
58
- return { error: 'Wave 9 reversal close refused: execution is pinned to Binance USD-M futures.' };
59
- }
60
- if (wave9ExitClaimed && !deps.operationLock) {
61
- return { error: 'Wave 9 reversal close refused: process-local trading operation lock is unavailable.' };
62
- }
63
- const initialWave9Mode = wave9ExitClaimed ? currentWave9ExecutionMode(deps) : null;
64
- let wave9Lease;
65
- if (wave9ExitClaimed) {
66
- if (!initialWave9Mode) {
67
- return {
68
- error: 'Wave 9 reversal close refused: capability execution requires an exact PAPER/paper-adapter ' +
69
- 'or LIVE/live-adapter runtime match.',
70
- };
71
- }
72
- if (args.reason !== WAVE9_MECHANICAL_EXIT_REASON
73
- || !args.wave9_exit_token
74
- || !args.candidate_id
75
- || !deps.wave9AdmissionGuard) {
76
- return { error: 'Wave 9 reversal close requires its exact reason, candidate identity, and short-lived exit token.' };
77
- }
78
- const executionCanonical = args.symbol.toUpperCase().replace(/[^A-Z0-9]/g, '').replace(/USDTUSDT$/, 'USDT');
79
- if (!executionCanonical.endsWith('USDT') || executionCanonical.length <= 4) {
80
- return { error: `Wave 9 reversal close refused: unsupported execution symbol ${args.symbol}.` };
81
- }
82
- if (initialWave9Mode === 'LIVE' && (!deps.captureWave9PositionFingerprint || !deps.wave9LiveLedger)) {
83
- return {
84
- error: 'Wave 9 live reversal close refused: authoritative live position capture and the durable ' +
85
- 'execution ledger are required.',
86
- };
87
- }
88
- args = { ...args, symbol: `${executionCanonical.slice(0, -4)}/USDT:USDT` };
89
- try {
90
- wave9Lease = await deps.operationLock.withAccountLock(`wave9-begin-close:${args.candidate_id ?? args.symbol}`, async () => {
91
- if (currentWave9ExecutionMode(deps) !== initialWave9Mode) {
92
- throw new Error('adapter or trading mode changed before Wave 9 reversal began');
93
- }
94
- let position;
95
- let positionFingerprint;
96
- if (initialWave9Mode === 'LIVE') {
97
- const capture = await deps.captureWave9PositionFingerprint(args.symbol);
98
- position = capture.position;
99
- positionFingerprint = capture.fingerprint;
100
- }
101
- else {
102
- deps.refreshPaperState?.();
103
- const positions = await deps.adapter.getPositionsOrNull();
104
- if (positions === null)
105
- throw new Error('paper position snapshot unavailable');
106
- const canonical = (value) => value.toUpperCase().replace(/[^A-Z0-9]/g, '').replace(/USDTUSDT$/, 'USDT');
107
- const matches = positions.filter((candidate) => canonical(candidate.symbol) === canonical(args.symbol));
108
- if (matches.length !== 1)
109
- throw new Error('exactly one matching held position is required');
110
- position = matches[0];
111
- positionFingerprint = captureWave9PaperPositionFingerprint(deps.adapter, args.symbol).fingerprint;
112
- }
113
- if (!isWave9ManagedPosition(position)
114
- || position.candidateId !== args.candidate_id
115
- || !position.missionId) {
116
- throw new Error('held position lacks exact Wave 9 identity/geometry');
117
- }
118
- return deps.wave9AdmissionGuard.beginExit({
119
- token: args.wave9_exit_token,
120
- candidateId: args.candidate_id,
121
- missionId: position.missionId,
122
- symbol: args.symbol,
123
- positionSide: position.side,
124
- setupType: position.setupType,
125
- reason: args.reason,
126
- positionFingerprint,
127
- tradingMode: initialWave9Mode,
128
- });
129
- });
130
- }
131
- catch (err) {
132
- return { error: `Wave 9 reversal close refused: ${formatError(err)}` };
133
- }
134
- }
135
- else {
136
- // Preserve the generic tool contract: malformed calls are rejected before
137
- // any adapter read. Wave 9 classification is an additional check only for
138
- // already-valid, non-operator risk-reducing closes.
139
- const v = validateClosePosition(args);
140
- if (!v.ok) {
141
- logger.warn(TAG, `close_position rejected: ${v.error} (symbol=${args.symbol}, reason=${args.reason ?? 'missing'})`);
142
- return { error: v.error ?? 'Invalid close_position arguments.' };
143
- }
144
- if (args.reason !== 'operator_command'
145
- && deps.adapter.isLive
146
- && deps.checkWave9LiveSymbolOwnership
147
- && !deps.operationLock) {
148
- return {
149
- error: 'Generic live close_position refused: the shared trading operation lock is required ' +
150
- 'while Wave 9 LIVE ownership checks are enabled.',
151
- };
152
- }
153
- // When a trusted position snapshot is available, do not route a held
154
- // Wave 9 position through a generic thesis/risk/bracket reason. Snapshot
155
- // failure stays fail-open because an ordinary risk-reducing close must not
156
- // be trapped by extra strategy-lifecycle I/O. Operator remains unconditional.
157
- if (args.reason !== 'operator_command') {
158
- try {
159
- const getTrusted = deps.adapter.getPositionsOrNull?.bind(deps.adapter);
160
- const held = getTrusted ? await getTrusted() : undefined;
161
- if (held) {
162
- const canonical = (value) => value.toUpperCase().replace(/[^A-Z0-9]/g, '').replace(/USDTUSDT$/, 'USDT');
163
- if (held.some((position) => canonical(position.symbol) === canonical(args.symbol)
164
- && isWave9ManagedPosition(position))) {
165
- return {
166
- error: `Wave 9 position close refused: call get_wave9_status and use reason=${WAVE9_MECHANICAL_EXIT_REASON} ` +
167
- 'with its single-use exit token. Only an explicit operator_command bypasses the strategy exit policy.',
168
- };
169
- }
170
- }
171
- else if (held === null) {
172
- logger.warn(TAG, 'Wave 9 generic-close classification unavailable; proceeding with legacy risk-reducing close semantics.');
173
- }
174
- }
175
- catch (err) {
176
- logger.warn(TAG, `Wave 9 generic-close classification failed (${formatError(err)}); proceeding with legacy risk-reducing close semantics.`);
177
- }
178
- }
179
- }
180
- // Exit-gate check — see docs/EXIT_GATE_DESIGN.md. The gate is orthogonal to
181
- // the bracket_integrity safeguard below; both can fire on the same call.
182
- // Behaviour by mode:
183
- // off — gate skipped entirely (no input fetch, no log).
184
- // shadow — gate runs, verdict logged to close_assessment.metadata.gate_eval,
185
- // close_position always proceeds.
186
- // observe — gate runs; on BLOCK we still proceed but the verdict is logged
187
- // and a warning printed to journalctl.
188
- // enforce — gate runs; on BLOCK we hard-reject with the recovery hint.
189
- const gateMode = deps.exitGateMode ?? loadExitGateMode();
190
- let gateVerdict = null;
191
- // 0a (2026-06-16): hoist the gate inputs to function scope so the post-close
192
- // capture block can persist a full inputs snapshot. Previously `inputs` was a
193
- // block-local const that went out of scope before the capture write, which is
194
- // why only {mode,outcome,tier,code} ever reached the journal (the §5 `inputs`
195
- // snapshot was never constructed). See docs/EXIT_DISCIPLINE_BUILD_PLAN.md
196
- // Step 0a + docs/EXIT_GATE_DESIGN.md §5.
197
- let gateInputs = null;
198
- if (!wave9ExitClaimed && gateMode !== 'off') {
199
- gateInputs = await buildExitGateInputs(args, deps);
200
- gateVerdict = evaluateExitGate(gateInputs);
201
- logger.info(TAG, `exit_gate mode=${gateMode} ${gateVerdict.outcome} tier=${gateVerdict.tier} code=${gateVerdict.code} (symbol=${args.symbol}, reason=${args.reason})`);
202
- if (gateVerdict.outcome === 'BLOCK' && gateMode === 'enforce') {
203
- logger.warn(TAG, `close_position REJECTED by exit gate (enforce): ${gateVerdict.code} — ${gateVerdict.recovery_hint ?? '(no hint)'}`);
204
- return {
205
- error: `close_position blocked by exit gate (${gateVerdict.code}). ` +
206
- (gateVerdict.recovery_hint ?? 'See docs/EXIT_GATE_DESIGN.md.'),
207
- };
208
- }
209
- if (gateVerdict.outcome === 'BLOCK' && gateMode === 'observe') {
210
- logger.warn(TAG, `close_position WOULD BE BLOCKED by exit gate (observe): ${gateVerdict.code} — ${gateVerdict.recovery_hint ?? '(no hint)'} — proceeding because mode=observe`);
211
- }
212
- }
213
- // In paper mode, fetch latest ticker + order book for realistic fills
214
- if (!deps.adapter.isLive) {
215
- try {
216
- const paperDeps = { binanceApi: deps.binanceApi, simulator: deps.adapter.getSimulator() };
217
- const [priceResult] = await Promise.all([
218
- fetchCurrentPrice(args.symbol, paperDeps),
219
- fetchOrderBook(args.symbol, paperDeps),
220
- ]);
221
- if (!isError(priceResult)) {
222
- // The helper updates the simulator mark used by the actual close fill.
223
- }
224
- else {
225
- if (wave9Lease) {
226
- deps.wave9AdmissionGuard.abort(wave9Lease, 'exit_market_data_unavailable', { retryable: true });
227
- wave9Lease = undefined;
228
- }
229
- return priceResult;
230
- }
231
- }
232
- catch (err) {
233
- if (wave9Lease) {
234
- deps.wave9AdmissionGuard.abort(wave9Lease, 'exit_market_data_threw', { retryable: true });
235
- wave9Lease = undefined;
236
- }
237
- return { error: `close_position market-data refresh failed: ${formatError(err)}` };
238
- }
239
- }
240
- // Log the assessment so every agent close is auditable in the journal.
241
- // We log after validation (we've confirmed the shape is sound) and before
242
- // the adapter call so the record is written even if the close fails.
243
- const reason = args.reason;
244
- const summary = formatAssessmentSummary(args.assessment);
245
- logger.info(TAG, `close_position ${args.symbol} reason=${reason}${summary ? ' | ' + summary : ''}`);
246
- // Circuit-breaker: if we've already let 2 bracket_integrity closes through
247
- // in the last hour, the 3rd is almost certainly the audit lying to us
248
- // rather than a real protection failure. Force the operator to either ack
249
- // by retrying with a different reason (regime_flip / risk_limit /
250
- // operator_command) or investigate the bracket subsystem.
251
- if (reason === 'bracket_integrity' && deps.adapter.isLive) {
252
- const now = Date.now();
253
- const windowStart = now - BRACKET_INTEGRITY_WINDOW_MS;
254
- bracketIntegrityCloses = bracketIntegrityCloses.filter(ts => ts >= windowStart);
255
- if (bracketIntegrityCloses.length >= BRACKET_INTEGRITY_LIMIT - 1) {
256
- logger.warn(TAG, `BRACKET-INTEGRITY CIRCUIT-BREAKER TRIPPED for ${args.symbol}: ` +
257
- `${bracketIntegrityCloses.length} prior bracket_integrity closes in the last ` +
258
- `${BRACKET_INTEGRITY_WINDOW_MS / 60_000} min. Refusing the ${bracketIntegrityCloses.length + 1}th. ` +
259
- `Audit-vs-reality bug is likelier than ${bracketIntegrityCloses.length + 1} consecutive real protection losses.`);
260
- return {
261
- error: `close_position rejected: circuit-breaker tripped — ` +
262
- `${bracketIntegrityCloses.length} bracket_integrity closes already fired in the last ` +
263
- `${BRACKET_INTEGRITY_WINDOW_MS / 60_000} min. This pattern almost always means the audit ` +
264
- `is unreliable, not that brackets are repeatedly failing on the exchange. ` +
265
- `Investigation steps: (1) run audit_bracket_protection and inspect 'reason' + ` +
266
- `ledger_state; (2) check the journal for 'AUDIT FLICKER' warnings; ` +
267
- `(3) if you truly need to exit, use reason='operator_command' (bypasses this check) ` +
268
- `or escalate to the operator.`,
269
- };
270
- }
271
- }
272
- // False-bracket_integrity safeguard — see module header comment.
273
- if (reason === 'bracket_integrity' && deps.adapter.isLive) {
274
- const integrity = await verifyBracketsGenuinelyMissing(deps.adapter, args.symbol);
275
- if (integrity.protected) {
276
- logger.warn(TAG, `close_position REJECTED — reason=bracket_integrity but plugin verified brackets live: ${integrity.detail} (symbol=${args.symbol}). This is the audit-vs-reality bug; the position is protected. If you want to close anyway, use reason=regime_flip, risk_limit, or operator_command.`);
277
- return {
278
- error: `close_position rejected: bracket_integrity claim contradicted by plugin (${integrity.detail}). ` +
279
- `Brackets are live on exchange. Use a different reason if you want to exit.`,
280
- };
281
- }
282
- logger.info(TAG, `bracket_integrity safeguard: ${integrity.detail} — allowing close`);
283
- }
284
- try {
285
- const close = async () => {
286
- if (!wave9ExitClaimed && !deps.adapter.isLive && reason !== 'operator_command') {
287
- deps.refreshPaperState?.();
288
- const positions = await deps.adapter.getPositionsOrNull();
289
- if (positions === null) {
290
- // Preserve the existing risk-reduction contract: the extra
291
- // classification read cannot trap an ordinary close.
292
- logger.warn(TAG, 'Wave 9 final close classification unavailable; proceeding risk-reducing fail-open.');
293
- }
294
- else {
295
- const canonical = (value) => value.toUpperCase().replace(/[^A-Z0-9]/g, '').replace(/USDTUSDT$/, 'USDT');
296
- const target = positions.find((position) => canonical(position.symbol) === canonical(args.symbol));
297
- if (target && isWave9ManagedPosition(target)) {
298
- throw new Error(`Generic close_position refused at mutation boundary: ${args.symbol} is now held by Wave 9.`);
299
- }
300
- }
301
- }
302
- if (!wave9ExitClaimed
303
- && deps.adapter.isLive
304
- && reason !== 'operator_command'
305
- && deps.checkWave9LiveSymbolOwnership) {
306
- let ownership;
307
- try {
308
- ownership = await deps.checkWave9LiveSymbolOwnership(args.symbol);
309
- }
310
- catch (err) {
311
- throw new Error(`Generic close_position refused at mutation boundary: Wave 9 LIVE ownership ` +
312
- `check failed for ${args.symbol} (${formatError(err)}).`);
313
- }
314
- if (ownership.status === 'owned' || ownership.status === 'ambiguous') {
315
- throw new Error(`Generic close_position refused at mutation boundary: ${args.symbol} has ` +
316
- `${ownership.status} Wave 9 LIVE ownership (${ownership.reason}). ` +
317
- 'Use get_wave9_status for a reversal authorization or operator_command for an emergency close.');
318
- }
319
- }
320
- return wave9ExitClaimed
321
- ? deps.adapter.closePosition(args.symbol, 'wave9_signal_reversal')
322
- : deps.adapter.closePosition(args.symbol);
323
- };
324
- const closeWave9 = async () => {
325
- if (!wave9Lease)
326
- throw new Error('Wave 9 exit lease is unavailable at mutation boundary.');
327
- if (currentWave9ExecutionMode(deps) !== initialWave9Mode) {
328
- deps.wave9AdmissionGuard.abort(wave9Lease, 'trading_mode_changed_before_exit_mutation', { retryable: true });
329
- wave9Lease = undefined;
330
- throw new Error('Wave 9 reversal close refused: adapter or trading mode changed before mutation.');
331
- }
332
- if (deps.wave9VenueCheck?.() !== 'binance') {
333
- deps.wave9AdmissionGuard.abort(wave9Lease, 'execution_venue_changed_before_exit_mutation', { retryable: true });
334
- wave9Lease = undefined;
335
- throw new Error('Wave 9 reversal close refused: execution venue changed away from Binance before mutation.');
336
- }
337
- let currentFingerprint;
338
- if (initialWave9Mode === 'LIVE') {
339
- const capture = await deps.captureWave9PositionFingerprint(args.symbol);
340
- if (!isWave9ManagedPosition(capture.position)
341
- || capture.position.candidateId !== args.candidate_id
342
- || !capture.position.missionId) {
343
- throw new Error('held live position no longer matches its exact Wave 9 identity');
344
- }
345
- currentFingerprint = capture.fingerprint;
346
- }
347
- else {
348
- deps.refreshPaperState?.();
349
- currentFingerprint = captureWave9PaperPositionFingerprint(deps.adapter, args.symbol).fingerprint;
350
- }
351
- deps.wave9AdmissionGuard.revalidate(wave9Lease, currentFingerprint);
352
- let order;
353
- let closeError;
354
- try {
355
- order = await close();
356
- }
357
- catch (err) {
358
- if (initialWave9Mode !== 'LIVE')
359
- throw err;
360
- closeError = formatError(err);
361
- }
362
- if (initialWave9Mode === 'LIVE') {
363
- const flat = await confirmWave9LivePositionFlat(deps.adapter, args.symbol);
364
- if (!flat.confirmed) {
365
- let protection;
366
- try {
367
- protection = await (deps.reprotectWave9LiveResidual ?? reprotectWave9LiveResidual)(deps.adapter, deps.wave9LiveLedger, args.candidate_id, args.symbol);
368
- }
369
- catch (err) {
370
- deps.wave9AdmissionGuard.abort(wave9Lease, `live_close_residual_reprotection_threw:${formatError(err)}`, { retryable: true });
371
- wave9Lease = undefined;
372
- throw new Error(`CRITICAL: Wave 9 LIVE reversal is not stably flat (${flat.detail}), and residual ` +
373
- `re-protection threw (${formatError(err)}). Durable ownership remains OPEN. ` +
374
- 'IMMEDIATE MANUAL INTERVENTION REQUIRED; a fresh exit authorization may retry.');
375
- }
376
- if (protection.status === 'protected') {
377
- deps.wave9AdmissionGuard.abort(wave9Lease, `live_close_residual_reprotected:${protection.stopClientOrderId ?? 'exact_stop'}`, { retryable: true });
378
- wave9Lease = undefined;
379
- throw new Error(`Wave 9 LIVE reversal close${closeError ? ` threw (${closeError}) and` : ''} left ` +
380
- `${protection.residualQuantity ?? 'a'} residual ` +
381
- `contract position. Durable ownership remains OPEN and the exact frozen stop ` +
382
- `${protection.stopPrice} is proven live; refresh get_wave9_status and use the ` +
383
- 'fresh exit authorization to retry the reduce-only close.');
384
- }
385
- deps.wave9AdmissionGuard.abort(wave9Lease, `live_close_residual_requires_manual_intervention:${protection.detail}`, { retryable: true });
386
- wave9Lease = undefined;
387
- throw new Error(`CRITICAL: Wave 9 LIVE reversal close${closeError ? ` threw (${closeError}) and` : ''} ` +
388
- `stable flat was not confirmed ` +
389
- `(${flat.detail}). Durable ownership remains OPEN. ${protection.detail}`);
390
- }
391
- await deps.wave9LiveLedger.markClosed(args.candidate_id);
392
- }
393
- deps.wave9AdmissionGuard.commit(wave9Lease);
394
- wave9Lease = undefined;
395
- if (closeError) {
396
- throw new Error(`Wave 9 LIVE reversal close acknowledgement failed (${closeError}), but stable flat was ` +
397
- 'proven and durable ownership is CLOSED. Do not retry this candidate.');
398
- }
399
- return order;
400
- };
401
- const order = wave9ExitClaimed
402
- ? await deps.operationLock.withAccountLock(`wave9-close-final:${args.symbol}`, closeWave9)
403
- : reason !== 'operator_command' && deps.operationLock
404
- ? await deps.operationLock.withAccountLock(`generic-close-final:${args.symbol}`, close)
405
- : await close();
406
- // Successful close — record the bracket_integrity timestamp so the
407
- // circuit-breaker can see the trend on the next attempt.
408
- if (reason === 'bracket_integrity' && deps.adapter.isLive) {
409
- bracketIntegrityCloses.push(Date.now());
410
- }
411
- // Auto-capture close to the Position Decision Journal — fail-open.
412
- if (deps.autoCapture) {
413
- const a = args.assessment;
414
- const assessmentForCapture = {
415
- ...a ?? {},
416
- };
417
- if (gateVerdict) {
418
- // 0a: persist the full inputs snapshot + would_have_blocked so shadow
419
- // verdicts are auditable from the journal (EXIT_GATE_DESIGN.md §5).
420
- // Keys are snake_case per the canonical-JSONB-key rule; every input is
421
- // null-coalesced so a MISSING input is recorded explicitly (that is the
422
- // point — it makes the inputs_unavailable_* skips diagnosable). The key
423
- // stays `outcome` (not §5's older `verdict`) to match the 148 historical
424
- // rows. `gateInputs` is non-null whenever `gateVerdict` is set (both are
425
- // assigned together when gateMode!=='off'); `gi` guard is for the type.
426
- const gi = gateInputs;
427
- const stopAtBE = gi && gi.side && typeof gi.stopPrice === 'number' && typeof gi.entryPrice === 'number'
428
- ? gi.side === 'long'
429
- ? gi.stopPrice >= gi.entryPrice
430
- : gi.stopPrice <= gi.entryPrice
431
- : null;
432
- assessmentForCapture.metadata = {
433
- ...assessmentForCapture.metadata ?? {},
434
- gate_eval: {
435
- mode: gateMode,
436
- outcome: gateVerdict.outcome,
437
- tier: gateVerdict.tier,
438
- code: gateVerdict.code,
439
- would_have_blocked: gateVerdict.outcome === 'BLOCK',
440
- ...(gateVerdict.discipline_failure
441
- ? { discipline_failure: gateVerdict.discipline_failure }
442
- : {}),
443
- ...(gi
444
- ? {
445
- inputs: {
446
- mfe_r_peak: gi.mfe_r_peak ?? null,
447
- current_r: gi.current_r ?? null,
448
- stop_at_BE: stopAtBE,
449
- last_review_verdict: gi.lastReview?.verdict ?? null,
450
- last_review_age_minutes: gi.lastReview
451
- ? Math.round((gi.now_ms - gi.lastReview.review_at_ms) / 6000) / 10
452
- : null,
453
- thesis_status: gi.lastReview?.thesis_status ?? null,
454
- // vol_shock is never computed by buildExitGateInputs yet, so
455
- // this is always false until the 3xATR shock is wired — do
456
- // NOT read it as a real signal during the soak.
457
- vol_shock: gi.volShock ?? false,
458
- // Provenance (set in buildExitGateInputs): which source
459
- // supplied each value — makes the inputs_unavailable_* and
460
- // computed-fallback paths diagnosable from the journal.
461
- mfe_src: gi.mfe_src ?? null,
462
- current_r_src: gi.current_r_src ?? null,
463
- },
464
- }
465
- : {}),
466
- },
467
- };
468
- }
469
- // Forensics: snapshot the audit verdict history (last 60min, up to
470
- // 120 samples) so the dashboard Position Timeline drawer can flag
471
- // closes that look like audit-flicker artefacts rather than real
472
- // market exits. The flicker-warn line in journal logs the same data
473
- // in real time; this lets us audit historical closes after the fact.
474
- // 2026-05-15 spiral root-cause work, item #8 of the bundle.
475
- if (deps.adapter.isLive) {
476
- const history = getRecentAuditVerdictHistory(args.symbol);
477
- if (history.length > 0) {
478
- assessmentForCapture.metadata = {
479
- ...assessmentForCapture.metadata ?? {},
480
- bracket_health_history: history,
481
- };
482
- }
483
- }
484
- onClosePositionFilled(deps.autoCapture, {
485
- symbol: args.symbol,
486
- closeReason: reason,
487
- closeAssessment: assessmentForCapture,
488
- scorecardVerdict: typeof a?.current_score === 'number' ? undefined : undefined,
489
- confluenceScore: typeof a?.current_score === 'number' ? a.current_score : undefined,
490
- regime: a?.current_regime,
491
- regimeConfidence: undefined,
492
- }, order).catch((err) => {
493
- // eslint-disable-next-line no-console
494
- console.warn(`[position-auto-capture] close capture threw: ${formatError(err)}`);
495
- });
496
- }
497
- return order;
498
- }
499
- catch (err) {
500
- if (wave9Lease) {
501
- deps.wave9AdmissionGuard.abort(wave9Lease, `exit_execution_failed:${formatError(err)}`, { retryable: initialWave9Mode === 'LIVE' });
502
- wave9Lease = undefined;
503
- }
504
- return { error: formatError(err) };
505
- }
506
- }
507
- /** Independent check used by the bracket_integrity safeguard. Looks at the
508
- * plugin's bracket ledger + a fresh exchange-side open-orders fetch; returns
509
- * `{protected: true}` only when BOTH confirm a live bracket (ledger row in a
510
- * non-terminal state with stored cids, AND at least one exchange order
511
- * carrying a matching `rc-<bracketId>-s` or `rc-<bracketId>-t` cid). Any
512
- * uncertainty (no ledger row, cids not stored, fetch error, nothing on
513
- * exchange) returns `{protected: false}` so the close is allowed — we only
514
- * block when we can definitively prove the audit was wrong. */
515
- async function verifyBracketsGenuinelyMissing(adapter, symbol) {
516
- const ledger = adapter.getBracketLedger?.();
517
- if (!ledger)
518
- return { protected: false, detail: 'brackets disabled' };
519
- const row = ledger.getBySymbol(symbol);
520
- if (!row)
521
- return { protected: false, detail: 'no ledger row' };
522
- const NON_TERMINAL = new Set(['pending_entry', 'attaching', 'active', 'partial']);
523
- if (!NON_TERMINAL.has(row.state)) {
524
- return { protected: false, detail: `ledger state=${row.state} (terminal)` };
525
- }
526
- if (!row.slCid && !row.tpCid) {
527
- return { protected: false, detail: `ledger state=${row.state} but no cids stored` };
528
- }
529
- let open = [];
530
- try {
531
- open = await adapter.getOpenOrders(symbol);
532
- }
533
- catch (err) {
534
- return { protected: false, detail: `getOpenOrders failed: ${formatError(err)}` };
535
- }
536
- const liveCids = new Set();
537
- for (const o of open) {
538
- if (o.clientOrderId)
539
- liveCids.add(o.clientOrderId);
540
- }
541
- const slLive = Boolean(row.slCid && liveCids.has(row.slCid));
542
- const tpLive = Boolean(row.tpCid && liveCids.has(row.tpCid));
543
- // Block the close only when BOTH bracket legs are live — that's the only
544
- // shape that proves the audit was definitively wrong (the original 2026-04-21
545
- // symbol-mapping bug). A position with only one leg live is half-bracketed:
546
- // the audit's `has_stop=false` (or `has_target=false`) is correct, the
547
- // operator/agent needs to flatten or re-attach, and the safeguard would
548
- // wrongly trap them. Per the docstring: only block when we can prove the
549
- // audit was wrong; one-leg-live does not prove that.
550
- if (slLive && tpLive) {
551
- return {
552
- protected: true,
553
- detail: `ledger state=${row.state}, exchange has SL(${row.slCid}) + TP(${row.tpCid}) open (${open.length} total orders on ${symbol})`,
554
- };
555
- }
556
- const observed = [];
557
- if (slLive)
558
- observed.push(`SL(${row.slCid}) only`);
559
- if (tpLive)
560
- observed.push(`TP(${row.tpCid}) only`);
561
- if (observed.length === 0)
562
- observed.push('neither cid on exchange');
563
- return {
564
- protected: false,
565
- detail: `ledger state=${row.state} (slCid=${row.slCid ?? '-'}, tpCid=${row.tpCid ?? '-'}) — ${observed.join(', ')} (${open.length} orders)`,
566
- };
567
- }
568
- /** Gather inputs for the exit gate from adapter + bracket ledger + state store.
569
- * Best-effort: any missing piece becomes `undefined` so the pure gate function
570
- * can decide whether to PASS('skipped') or proceed. Never throws — gate
571
- * evaluation must never crash close_position.
572
- */
573
- async function buildExitGateInputs(args, deps) {
574
- const reason = (args.reason ?? 'regime_flip');
575
- const a = args.assessment;
576
- const inputs = {
577
- reason,
578
- now_ms: Date.now(),
579
- mfe_r_peak: typeof a?.mfe_r_peak === 'number' ? a.mfe_r_peak : undefined,
580
- current_r: typeof a?.r_multiple_at_close === 'number' ? a.r_multiple_at_close : undefined,
581
- };
582
- // Provenance: agent-supplied values win (set the src tags now); the adapter
583
- // and computed fallbacks below only fire when these stay undefined.
584
- if (inputs.mfe_r_peak !== undefined)
585
- inputs.mfe_src = 'assessment';
586
- if (inputs.current_r !== undefined)
587
- inputs.current_r_src = 'assessment';
588
- // Bracket ledger — stop price + (canonical) ledger entry.
589
- // Only LiveAdapter exposes getBracketLedger; paper adapter falls back.
590
- try {
591
- const ledger = deps.adapter.getBracketLedger?.();
592
- if (ledger) {
593
- const row = ledger.getBySymbol(args.symbol);
594
- if (row) {
595
- if (typeof row.stopPrice === 'number' && Number.isFinite(row.stopPrice)) {
596
- inputs.stopPrice = row.stopPrice;
597
- }
598
- if (row.entrySide === 'buy')
599
- inputs.side = 'long';
600
- else if (row.entrySide === 'sell')
601
- inputs.side = 'short';
602
- }
603
- }
604
- }
605
- catch (err) {
606
- logger.warn(TAG, `exit_gate input fetch (bracket ledger): ${formatError(err)}`);
607
- }
608
- // Position — for entryPrice + side fallback, plus mfeR + bracket fallbacks.
609
- // LiveAdapter.getPositions decorates each row with a running mfeR (updated
610
- // from mark price on every call) and a bracket snapshot. When the agent
611
- // omits `assessment.mfe_r_peak` (observed on ~77% of closes during the
612
- // 2026-05-14 shadow soak), we read mfeR from the adapter so the gate can
613
- // still tier the close instead of returning inputs_unavailable_mfe.
614
- try {
615
- const positions = await deps.adapter.getPositions(args.symbol);
616
- const pos = positions.find((p) => p.contracts && p.contracts > 0);
617
- if (pos) {
618
- if (typeof pos.entryPrice === 'number' && Number.isFinite(pos.entryPrice)) {
619
- inputs.entryPrice = pos.entryPrice;
620
- }
621
- if (!inputs.side && pos.side === 'long')
622
- inputs.side = 'long';
623
- if (!inputs.side && pos.side === 'short')
624
- inputs.side = 'short';
625
- if (inputs.mfe_r_peak === undefined
626
- && typeof pos.mfeR === 'number'
627
- && Number.isFinite(pos.mfeR)) {
628
- inputs.mfe_r_peak = pos.mfeR;
629
- inputs.mfe_src = 'pos.mfeR';
630
- }
631
- if (inputs.stopPrice === undefined
632
- && pos.bracket
633
- && typeof pos.bracket.slPrice === 'number'
634
- && Number.isFinite(pos.bracket.slPrice)) {
635
- inputs.stopPrice = pos.bracket.slPrice;
636
- }
637
- // 0b: plugin-computed fallbacks for current_r (SIGNED) + an mfe peak-FLOOR
638
- // when the agent AND the adapter both left them undefined — the
639
- // inputs_unavailable_* skips (~16-30% of evals). R denominator is the
640
- // frozen entry→stop distance (originalStopPrice preferred; else the bracket
641
- // stop resolved above). Both gated on `=== undefined` so agent-supplied
642
- // values still win. current_r MUST stay signed (the T1-escape check
643
- // compares current_r <= -0.5R); the mfe value is a NON-NEGATIVE FLOOR (true
644
- // peak >= current excursion) — it lets the gate tier the close instead of
645
- // skipping, at the cost of under-classifying a round-tripped winner as T1
646
- // (acceptable: errs toward BLOCK in enforce). A position with no frozen
647
- // stop (no originalStopPrice, no bracket) still legitimately skips.
648
- // See docs/EXIT_DISCIPLINE_BUILD_PLAN.md Step 0b.
649
- const denomStop = typeof pos.originalStopPrice === 'number' && Number.isFinite(pos.originalStopPrice)
650
- ? pos.originalStopPrice
651
- : inputs.stopPrice;
652
- if (inputs.side
653
- && typeof pos.entryPrice === 'number' && Number.isFinite(pos.entryPrice)
654
- && typeof pos.markPrice === 'number' && Number.isFinite(pos.markPrice)
655
- && typeof denomStop === 'number' && Number.isFinite(denomStop)) {
656
- const denom = Math.abs(pos.entryPrice - denomStop);
657
- if (denom > 0) {
658
- const fav = inputs.side === 'long'
659
- ? pos.markPrice - pos.entryPrice
660
- : pos.entryPrice - pos.markPrice;
661
- if (inputs.current_r === undefined) {
662
- inputs.current_r = fav / denom; // signed
663
- inputs.current_r_src = 'computed';
664
- }
665
- if (inputs.mfe_r_peak === undefined) {
666
- inputs.mfe_r_peak = Math.max(0, fav / denom); // non-negative floor
667
- inputs.mfe_src = 'computed_floor';
668
- }
669
- }
670
- }
671
- }
672
- }
673
- catch (err) {
674
- logger.warn(TAG, `exit_gate input fetch (positions): ${formatError(err)}`);
675
- }
676
- // Last review — from state store, for contradicts-own-review + review override.
677
- try {
678
- const entry = deps.autoCapture?.stateStore?.get(args.symbol);
679
- if (entry?.lastVerdict && typeof entry.lastReviewAt === 'number') {
680
- inputs.lastReview = {
681
- verdict: entry.lastVerdict,
682
- thesis_status: entry.lastThesisStatus ?? 'intact',
683
- review_at_ms: entry.lastReviewAt,
684
- };
685
- }
686
- }
687
- catch (err) {
688
- logger.warn(TAG, `exit_gate input fetch (state store): ${formatError(err)}`);
689
- }
690
- return inputs;
691
- }
692
- /** Test seam — clears the circuit-breaker state between unit tests. */
693
- export const __testing__ = {
694
- resetCircuitBreaker() {
695
- bracketIntegrityCloses = [];
696
- },
697
- /** Inspect current circuit-breaker state — for assertions. */
698
- getCircuitBreakerCount() {
699
- const windowStart = Date.now() - BRACKET_INTEGRITY_WINDOW_MS;
700
- return bracketIntegrityCloses.filter(ts => ts >= windowStart).length;
701
- },
702
- };
703
- function formatAssessmentSummary(a) {
704
- if (!a)
705
- return '';
706
- const parts = [];
707
- if (typeof a.entry_score === 'number')
708
- parts.push(`entry=${a.entry_score}`);
709
- if (typeof a.current_score === 'number')
710
- parts.push(`current=${a.current_score}`);
711
- if (a.entry_regime)
712
- parts.push(`er=${a.entry_regime}`);
713
- if (a.current_regime)
714
- parts.push(`cr=${a.current_regime}`);
715
- if (a.contradicting_metric)
716
- parts.push(`metric="${a.contradicting_metric.slice(0, 80)}"`);
717
- if (typeof a.position_age_seconds === 'number')
718
- parts.push(`age=${a.position_age_seconds}s`);
719
- if (typeof a.r_multiple_at_close === 'number')
720
- parts.push(`R=${a.r_multiple_at_close}`);
721
- return parts.join(' ');
722
- }