@senpi/runtime 3.0.6-dev.skill-manager-v2.20260629194505 → 3.0.9-dev.runtime-phase-2.20260707070820

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 (458) hide show
  1. package/dist/actions/action-events.d.ts +67 -0
  2. package/dist/actions/action-events.d.ts.map +1 -0
  3. package/dist/actions/action-events.js +164 -0
  4. package/dist/actions/action-events.js.map +1 -0
  5. package/dist/actions/close-position/close-position.action.d.ts +1 -1
  6. package/dist/actions/close-position/close-position.action.d.ts.map +1 -1
  7. package/dist/actions/close-position/close-position.action.js +108 -86
  8. package/dist/actions/close-position/close-position.action.js.map +1 -1
  9. package/dist/actions/decision-engine.d.ts.map +1 -1
  10. package/dist/actions/decision-engine.js +40 -28
  11. package/dist/actions/decision-engine.js.map +1 -1
  12. package/dist/actions/event-derivation.d.ts +61 -0
  13. package/dist/actions/event-derivation.d.ts.map +1 -0
  14. package/dist/actions/event-derivation.js +180 -0
  15. package/dist/actions/event-derivation.js.map +1 -0
  16. package/dist/actions/llm-decision/anthropic-llm-decision.d.ts +5 -9
  17. package/dist/actions/llm-decision/anthropic-llm-decision.d.ts.map +1 -1
  18. package/dist/actions/llm-decision/anthropic-llm-decision.js +6 -87
  19. package/dist/actions/llm-decision/anthropic-llm-decision.js.map +1 -1
  20. package/dist/actions/llm-decision/factory.d.ts +0 -6
  21. package/dist/actions/llm-decision/factory.d.ts.map +1 -1
  22. package/dist/actions/llm-decision/factory.js +0 -2
  23. package/dist/actions/llm-decision/factory.js.map +1 -1
  24. package/dist/actions/llm-decision/openclaw-llm-decision.d.ts.map +1 -1
  25. package/dist/actions/llm-decision/openclaw-llm-decision.js +26 -7
  26. package/dist/actions/llm-decision/openclaw-llm-decision.js.map +1 -1
  27. package/dist/actions/open-position/open-position.action.d.ts +1 -1
  28. package/dist/actions/open-position/open-position.action.d.ts.map +1 -1
  29. package/dist/actions/open-position/open-position.action.js +282 -224
  30. package/dist/actions/open-position/open-position.action.js.map +1 -1
  31. package/dist/actions/position-tracker/position-tracker.action.d.ts.map +1 -1
  32. package/dist/actions/position-tracker/position-tracker.action.js +3 -6
  33. package/dist/actions/position-tracker/position-tracker.action.js.map +1 -1
  34. package/dist/cli/guide-commands.d.ts.map +1 -1
  35. package/dist/cli/guide-commands.js +61 -0
  36. package/dist/cli/guide-commands.js.map +1 -1
  37. package/dist/cli/senpi-commands.d.ts +14 -0
  38. package/dist/cli/senpi-commands.d.ts.map +1 -1
  39. package/dist/cli/senpi-commands.js +390 -2
  40. package/dist/cli/senpi-commands.js.map +1 -1
  41. package/dist/dsl/engine-client/event-mapping.d.ts.map +1 -1
  42. package/dist/dsl/engine-client/event-mapping.js +0 -3
  43. package/dist/dsl/engine-client/event-mapping.js.map +1 -1
  44. package/dist/dsl/events/build-closed-event.d.ts.map +1 -1
  45. package/dist/dsl/events/build-closed-event.js +0 -1
  46. package/dist/dsl/events/build-closed-event.js.map +1 -1
  47. package/dist/dsl/events/handlers.d.ts.map +1 -1
  48. package/dist/dsl/events/handlers.js +2 -4
  49. package/dist/dsl/events/handlers.js.map +1 -1
  50. package/dist/dsl/events/initial-state.d.ts.map +1 -1
  51. package/dist/dsl/events/initial-state.js +1 -0
  52. package/dist/dsl/events/initial-state.js.map +1 -1
  53. package/dist/dsl/monitor/create-monitor.d.ts +3 -0
  54. package/dist/dsl/monitor/create-monitor.d.ts.map +1 -1
  55. package/dist/dsl/monitor/create-monitor.js +76 -58
  56. package/dist/dsl/monitor/create-monitor.js.map +1 -1
  57. package/dist/dsl/monitor/dsl-failure-events.d.ts +42 -0
  58. package/dist/dsl/monitor/dsl-failure-events.d.ts.map +1 -0
  59. package/dist/dsl/monitor/dsl-failure-events.js +73 -0
  60. package/dist/dsl/monitor/dsl-failure-events.js.map +1 -0
  61. package/dist/dsl/monitor/process-one-position.d.ts +2 -1
  62. package/dist/dsl/monitor/process-one-position.d.ts.map +1 -1
  63. package/dist/dsl/monitor/process-one-position.js +130 -196
  64. package/dist/dsl/monitor/process-one-position.js.map +1 -1
  65. package/dist/dsl/plugin/index.d.ts +10 -0
  66. package/dist/dsl/plugin/index.d.ts.map +1 -1
  67. package/dist/dsl/plugin/index.js +48 -4
  68. package/dist/dsl/plugin/index.js.map +1 -1
  69. package/dist/dsl/plugin/options.d.ts +3 -0
  70. package/dist/dsl/plugin/options.d.ts.map +1 -1
  71. package/dist/health/types.d.ts +14 -0
  72. package/dist/health/types.d.ts.map +1 -1
  73. package/dist/health/types.js.map +1 -1
  74. package/dist/index.d.ts +1 -0
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +255 -77
  77. package/dist/index.js.map +1 -1
  78. package/dist/risk/risk-audit-log.d.ts +7 -0
  79. package/dist/risk/risk-audit-log.d.ts.map +1 -1
  80. package/dist/risk/risk-audit-log.js +48 -1
  81. package/dist/risk/risk-audit-log.js.map +1 -1
  82. package/dist/runtime/__tests__/helpers/runtime-gateway-harness.d.ts +2 -0
  83. package/dist/runtime/__tests__/helpers/runtime-gateway-harness.d.ts.map +1 -1
  84. package/dist/runtime/__tests__/helpers/runtime-gateway-harness.js +24 -3
  85. package/dist/runtime/__tests__/helpers/runtime-gateway-harness.js.map +1 -1
  86. package/dist/runtime/auto-update/coordinator.js +2 -2
  87. package/dist/runtime/auto-update/coordinator.js.map +1 -1
  88. package/dist/runtime/create-actions.d.ts.map +1 -1
  89. package/dist/runtime/create-actions.js +40 -15
  90. package/dist/runtime/create-actions.js.map +1 -1
  91. package/dist/runtime/create-runtime-context.d.ts +1 -1
  92. package/dist/runtime/create-runtime-context.d.ts.map +1 -1
  93. package/dist/runtime/create-scanner-module.d.ts +2 -1
  94. package/dist/runtime/create-scanner-module.d.ts.map +1 -1
  95. package/dist/runtime/create-scanner-module.js +2 -1
  96. package/dist/runtime/create-scanner-module.js.map +1 -1
  97. package/dist/runtime/domain-events.d.ts +43 -0
  98. package/dist/runtime/domain-events.d.ts.map +1 -0
  99. package/dist/runtime/domain-events.js +181 -0
  100. package/dist/runtime/domain-events.js.map +1 -0
  101. package/dist/runtime/lifecycle-events.d.ts +86 -0
  102. package/dist/runtime/lifecycle-events.d.ts.map +1 -0
  103. package/dist/runtime/lifecycle-events.js +200 -0
  104. package/dist/runtime/lifecycle-events.js.map +1 -0
  105. package/dist/runtime/notifications.js +2 -2
  106. package/dist/runtime/notifications.js.map +1 -1
  107. package/dist/{tracking → runtime}/position-id-registry.d.ts +14 -1
  108. package/dist/runtime/position-id-registry.d.ts.map +1 -0
  109. package/dist/{tracking → runtime}/position-id-registry.js +20 -3
  110. package/dist/runtime/position-id-registry.js.map +1 -0
  111. package/dist/runtime/run.d.ts +2 -4
  112. package/dist/runtime/run.d.ts.map +1 -1
  113. package/dist/runtime/run.js.map +1 -1
  114. package/dist/runtime/runtime-schema.d.ts +276 -588
  115. package/dist/runtime/runtime-schema.d.ts.map +1 -1
  116. package/dist/runtime/runtime-schema.js +8 -28
  117. package/dist/runtime/runtime-schema.js.map +1 -1
  118. package/dist/runtime/runtime.d.ts +23 -9
  119. package/dist/runtime/runtime.d.ts.map +1 -1
  120. package/dist/runtime/runtime.js +276 -248
  121. package/dist/runtime/runtime.js.map +1 -1
  122. package/dist/runtime/strategy-lifecycle.d.ts.map +1 -1
  123. package/dist/runtime/strategy-lifecycle.js +13 -1
  124. package/dist/runtime/strategy-lifecycle.js.map +1 -1
  125. package/dist/runtime/supervisor/long-running-supervisor.d.ts +3 -0
  126. package/dist/runtime/supervisor/long-running-supervisor.d.ts.map +1 -1
  127. package/dist/runtime/supervisor/long-running-supervisor.js +27 -53
  128. package/dist/runtime/supervisor/long-running-supervisor.js.map +1 -1
  129. package/dist/runtime-api/intake/intake-events.d.ts +44 -0
  130. package/dist/runtime-api/intake/intake-events.d.ts.map +1 -0
  131. package/dist/runtime-api/intake/intake-events.js +131 -0
  132. package/dist/runtime-api/intake/intake-events.js.map +1 -0
  133. package/dist/runtime-api/intake/scanner-launcher.d.ts +2 -0
  134. package/dist/runtime-api/intake/scanner-launcher.d.ts.map +1 -1
  135. package/dist/runtime-api/intake/scanner-launcher.js +58 -15
  136. package/dist/runtime-api/intake/scanner-launcher.js.map +1 -1
  137. package/dist/runtime-api/intake/scanner-registry.d.ts +3 -0
  138. package/dist/runtime-api/intake/scanner-registry.d.ts.map +1 -1
  139. package/dist/runtime-api/intake/scanner-registry.js +3 -0
  140. package/dist/runtime-api/intake/scanner-registry.js.map +1 -1
  141. package/dist/runtime-api/intake/supervisor-events.d.ts +61 -0
  142. package/dist/runtime-api/intake/supervisor-events.d.ts.map +1 -0
  143. package/dist/runtime-api/intake/supervisor-events.js +173 -0
  144. package/dist/runtime-api/intake/supervisor-events.js.map +1 -0
  145. package/dist/runtime-api/routes/signals.d.ts +1 -1
  146. package/dist/runtime-api/routes/signals.d.ts.map +1 -1
  147. package/dist/runtime-api/routes/signals.js +121 -35
  148. package/dist/runtime-api/routes/signals.js.map +1 -1
  149. package/dist/runtime-api/server.d.ts.map +1 -1
  150. package/dist/runtime-api/server.js +10 -1
  151. package/dist/runtime-api/server.js.map +1 -1
  152. package/dist/scanners/engine/data-providers.d.ts +3 -0
  153. package/dist/scanners/engine/data-providers.d.ts.map +1 -1
  154. package/dist/scanners/engine/data-providers.js.map +1 -1
  155. package/dist/scanners/engine/engine.d.ts +18 -0
  156. package/dist/scanners/engine/engine.d.ts.map +1 -1
  157. package/dist/scanners/engine/engine.js +96 -2
  158. package/dist/scanners/engine/engine.js.map +1 -1
  159. package/dist/scanners/engine/input-resolver.d.ts.map +1 -1
  160. package/dist/scanners/engine/input-resolver.js +9 -7
  161. package/dist/scanners/engine/input-resolver.js.map +1 -1
  162. package/dist/scanners/runtime-module.d.ts +3 -0
  163. package/dist/scanners/runtime-module.d.ts.map +1 -1
  164. package/dist/scanners/runtime-module.js +7 -0
  165. package/dist/scanners/runtime-module.js.map +1 -1
  166. package/dist/senpi/client.d.ts +10 -0
  167. package/dist/senpi/client.d.ts.map +1 -1
  168. package/dist/senpi/client.js +113 -46
  169. package/dist/senpi/client.js.map +1 -1
  170. package/dist/skills-manager/bootstrap.d.ts.map +1 -1
  171. package/dist/skills-manager/bootstrap.js +22 -33
  172. package/dist/skills-manager/bootstrap.js.map +1 -1
  173. package/dist/skills-manager/clone-groups.d.ts +20 -0
  174. package/dist/skills-manager/clone-groups.d.ts.map +1 -0
  175. package/dist/skills-manager/clone-groups.js +45 -0
  176. package/dist/skills-manager/clone-groups.js.map +1 -0
  177. package/dist/skills-manager/coordinator.d.ts.map +1 -1
  178. package/dist/skills-manager/coordinator.js +111 -75
  179. package/dist/skills-manager/coordinator.js.map +1 -1
  180. package/dist/skills-manager/manifest.d.ts +24 -0
  181. package/dist/skills-manager/manifest.d.ts.map +1 -1
  182. package/dist/skills-manager/manifest.js +23 -10
  183. package/dist/skills-manager/manifest.js.map +1 -1
  184. package/dist/skills-manager/skills-manifest.json +12 -7
  185. package/dist/skills-manager/types.d.ts +12 -0
  186. package/dist/skills-manager/types.d.ts.map +1 -1
  187. package/dist/state/state-events.d.ts +13 -0
  188. package/dist/state/state-events.d.ts.map +1 -0
  189. package/dist/state/state-events.js +22 -0
  190. package/dist/state/state-events.js.map +1 -0
  191. package/dist/state/state-manager.d.ts.map +1 -1
  192. package/dist/state/state-manager.js +14 -1
  193. package/dist/state/state-manager.js.map +1 -1
  194. package/dist/telemetry/attributes.d.ts +13 -0
  195. package/dist/telemetry/attributes.d.ts.map +1 -0
  196. package/dist/telemetry/attributes.js +22 -0
  197. package/dist/telemetry/attributes.js.map +1 -0
  198. package/dist/{tracking → telemetry}/context.d.ts +12 -5
  199. package/dist/telemetry/context.d.ts.map +1 -0
  200. package/dist/{tracking → telemetry}/context.js +4 -4
  201. package/dist/telemetry/context.js.map +1 -0
  202. package/dist/{recording/records.d.ts → telemetry/event-builders.d.ts} +145 -33
  203. package/dist/telemetry/event-builders.d.ts.map +1 -0
  204. package/dist/{recording/wiring/record-builders.js → telemetry/event-builders.js} +94 -40
  205. package/dist/telemetry/event-builders.js.map +1 -0
  206. package/dist/telemetry/event-store.d.ts +66 -0
  207. package/dist/telemetry/event-store.d.ts.map +1 -0
  208. package/dist/telemetry/event-store.js +202 -0
  209. package/dist/telemetry/event-store.js.map +1 -0
  210. package/dist/telemetry/identity.d.ts +72 -0
  211. package/dist/telemetry/identity.d.ts.map +1 -0
  212. package/dist/{recording/wiring → telemetry}/identity.js +6 -2
  213. package/dist/telemetry/identity.js.map +1 -0
  214. package/dist/telemetry/metrics.d.ts +169 -0
  215. package/dist/telemetry/metrics.d.ts.map +1 -0
  216. package/dist/telemetry/metrics.js +437 -0
  217. package/dist/telemetry/metrics.js.map +1 -0
  218. package/dist/telemetry/otel-sdk.d.ts +93 -0
  219. package/dist/telemetry/otel-sdk.d.ts.map +1 -0
  220. package/dist/telemetry/otel-sdk.js +297 -0
  221. package/dist/telemetry/otel-sdk.js.map +1 -0
  222. package/dist/telemetry/spans/constants.d.ts +12 -0
  223. package/dist/telemetry/spans/constants.d.ts.map +1 -0
  224. package/dist/telemetry/spans/constants.js +12 -0
  225. package/dist/telemetry/spans/constants.js.map +1 -0
  226. package/dist/telemetry/spans/gen-ai.d.ts +74 -0
  227. package/dist/telemetry/spans/gen-ai.d.ts.map +1 -0
  228. package/dist/telemetry/spans/gen-ai.js +339 -0
  229. package/dist/telemetry/spans/gen-ai.js.map +1 -0
  230. package/dist/telemetry/spans/index.d.ts +11 -0
  231. package/dist/telemetry/spans/index.d.ts.map +1 -0
  232. package/dist/telemetry/spans/index.js +11 -0
  233. package/dist/telemetry/spans/index.js.map +1 -0
  234. package/dist/{tracking → telemetry}/spans/redact-pii.d.ts +19 -21
  235. package/dist/telemetry/spans/redact-pii.d.ts.map +1 -0
  236. package/dist/{tracking → telemetry}/spans/redact-pii.js +35 -32
  237. package/dist/telemetry/spans/redact-pii.js.map +1 -0
  238. package/dist/telemetry/spans/sanitize-payload.d.ts.map +1 -0
  239. package/dist/telemetry/spans/sanitize-payload.js.map +1 -0
  240. package/dist/telemetry/spans/span-hooks.d.ts +18 -0
  241. package/dist/telemetry/spans/span-hooks.d.ts.map +1 -0
  242. package/dist/telemetry/spans/span-hooks.js +764 -0
  243. package/dist/telemetry/spans/span-hooks.js.map +1 -0
  244. package/dist/telemetry/tool-plane.d.ts +31 -0
  245. package/dist/telemetry/tool-plane.d.ts.map +1 -0
  246. package/dist/telemetry/tool-plane.js +70 -0
  247. package/dist/telemetry/tool-plane.js.map +1 -0
  248. package/dist/telemetry/trace-identity.d.ts +32 -0
  249. package/dist/telemetry/trace-identity.d.ts.map +1 -0
  250. package/dist/telemetry/trace-identity.js +62 -0
  251. package/dist/telemetry/trace-identity.js.map +1 -0
  252. package/dist/telemetry/tracing.d.ts +33 -0
  253. package/dist/telemetry/tracing.d.ts.map +1 -0
  254. package/dist/telemetry/tracing.js +70 -0
  255. package/dist/telemetry/tracing.js.map +1 -0
  256. package/dist/types/dsl/index.d.ts +8 -9
  257. package/dist/types/dsl/index.d.ts.map +1 -1
  258. package/dist/types/runtime.d.ts +1 -1
  259. package/dist/types/runtime.d.ts.map +1 -1
  260. package/dist/types/scanner.d.ts +2 -0
  261. package/dist/types/scanner.d.ts.map +1 -1
  262. package/dist/utils/event-catalog.d.ts +506 -0
  263. package/dist/utils/event-catalog.d.ts.map +1 -0
  264. package/dist/utils/event-catalog.js +142 -0
  265. package/dist/utils/event-catalog.js.map +1 -0
  266. package/dist/utils/logger.d.ts +63 -5
  267. package/dist/utils/logger.d.ts.map +1 -1
  268. package/dist/utils/logger.js +360 -27
  269. package/dist/utils/logger.js.map +1 -1
  270. package/dist/utils/wallet-address.d.ts +3 -0
  271. package/dist/utils/wallet-address.d.ts.map +1 -0
  272. package/dist/utils/wallet-address.js +17 -0
  273. package/dist/utils/wallet-address.js.map +1 -0
  274. package/openclaw.plugin.json +20 -6
  275. package/package.json +10 -2
  276. package/dist/actions/tracking-helpers.d.ts +0 -28
  277. package/dist/actions/tracking-helpers.d.ts.map +0 -1
  278. package/dist/actions/tracking-helpers.js +0 -93
  279. package/dist/actions/tracking-helpers.js.map +0 -1
  280. package/dist/recording/emitter.d.ts +0 -27
  281. package/dist/recording/emitter.d.ts.map +0 -1
  282. package/dist/recording/emitter.js +0 -2
  283. package/dist/recording/emitter.js.map +0 -1
  284. package/dist/recording/identity.d.ts +0 -34
  285. package/dist/recording/identity.d.ts.map +0 -1
  286. package/dist/recording/identity.js +0 -2
  287. package/dist/recording/identity.js.map +0 -1
  288. package/dist/recording/index.d.ts +0 -11
  289. package/dist/recording/index.d.ts.map +0 -1
  290. package/dist/recording/index.js +0 -2
  291. package/dist/recording/index.js.map +0 -1
  292. package/dist/recording/noop-emitter.d.ts +0 -23
  293. package/dist/recording/noop-emitter.d.ts.map +0 -1
  294. package/dist/recording/noop-emitter.js +0 -22
  295. package/dist/recording/noop-emitter.js.map +0 -1
  296. package/dist/recording/otel/attributes.d.ts +0 -35
  297. package/dist/recording/otel/attributes.d.ts.map +0 -1
  298. package/dist/recording/otel/attributes.js +0 -131
  299. package/dist/recording/otel/attributes.js.map +0 -1
  300. package/dist/recording/otel/constants.d.ts +0 -123
  301. package/dist/recording/otel/constants.d.ts.map +0 -1
  302. package/dist/recording/otel/constants.js +0 -172
  303. package/dist/recording/otel/constants.js.map +0 -1
  304. package/dist/recording/otel/ids.d.ts +0 -25
  305. package/dist/recording/otel/ids.d.ts.map +0 -1
  306. package/dist/recording/otel/ids.js +0 -37
  307. package/dist/recording/otel/ids.js.map +0 -1
  308. package/dist/recording/otel/index.d.ts +0 -13
  309. package/dist/recording/otel/index.d.ts.map +0 -1
  310. package/dist/recording/otel/index.js +0 -9
  311. package/dist/recording/otel/index.js.map +0 -1
  312. package/dist/recording/otel/mappers.d.ts +0 -100
  313. package/dist/recording/otel/mappers.d.ts.map +0 -1
  314. package/dist/recording/otel/mappers.js +0 -683
  315. package/dist/recording/otel/mappers.js.map +0 -1
  316. package/dist/recording/otel/otel-emitter.d.ts +0 -43
  317. package/dist/recording/otel/otel-emitter.d.ts.map +0 -1
  318. package/dist/recording/otel/otel-emitter.js +0 -99
  319. package/dist/recording/otel/otel-emitter.js.map +0 -1
  320. package/dist/recording/otel/redaction.d.ts +0 -47
  321. package/dist/recording/otel/redaction.d.ts.map +0 -1
  322. package/dist/recording/otel/redaction.js +0 -88
  323. package/dist/recording/otel/redaction.js.map +0 -1
  324. package/dist/recording/records.d.ts.map +0 -1
  325. package/dist/recording/records.js +0 -14
  326. package/dist/recording/records.js.map +0 -1
  327. package/dist/recording/transport/batcher.d.ts +0 -59
  328. package/dist/recording/transport/batcher.d.ts.map +0 -1
  329. package/dist/recording/transport/batcher.js +0 -234
  330. package/dist/recording/transport/batcher.js.map +0 -1
  331. package/dist/recording/transport/client.d.ts +0 -41
  332. package/dist/recording/transport/client.d.ts.map +0 -1
  333. package/dist/recording/transport/client.js +0 -69
  334. package/dist/recording/transport/client.js.map +0 -1
  335. package/dist/recording/transport/config.d.ts +0 -53
  336. package/dist/recording/transport/config.d.ts.map +0 -1
  337. package/dist/recording/transport/config.js +0 -41
  338. package/dist/recording/transport/config.js.map +0 -1
  339. package/dist/recording/transport/index.d.ts +0 -16
  340. package/dist/recording/transport/index.d.ts.map +0 -1
  341. package/dist/recording/transport/index.js +0 -12
  342. package/dist/recording/transport/index.js.map +0 -1
  343. package/dist/recording/transport/rows.d.ts +0 -88
  344. package/dist/recording/transport/rows.d.ts.map +0 -1
  345. package/dist/recording/transport/rows.js +0 -15
  346. package/dist/recording/transport/rows.js.map +0 -1
  347. package/dist/recording/wiring/emitter-factory.d.ts +0 -39
  348. package/dist/recording/wiring/emitter-factory.d.ts.map +0 -1
  349. package/dist/recording/wiring/emitter-factory.js +0 -62
  350. package/dist/recording/wiring/emitter-factory.js.map +0 -1
  351. package/dist/recording/wiring/identity.d.ts +0 -27
  352. package/dist/recording/wiring/identity.d.ts.map +0 -1
  353. package/dist/recording/wiring/identity.js.map +0 -1
  354. package/dist/recording/wiring/index.d.ts +0 -12
  355. package/dist/recording/wiring/index.d.ts.map +0 -1
  356. package/dist/recording/wiring/index.js +0 -9
  357. package/dist/recording/wiring/index.js.map +0 -1
  358. package/dist/recording/wiring/record-builders.d.ts +0 -107
  359. package/dist/recording/wiring/record-builders.d.ts.map +0 -1
  360. package/dist/recording/wiring/record-builders.js.map +0 -1
  361. package/dist/recording/wiring/subscriber.d.ts +0 -28
  362. package/dist/recording/wiring/subscriber.d.ts.map +0 -1
  363. package/dist/recording/wiring/subscriber.js +0 -173
  364. package/dist/recording/wiring/subscriber.js.map +0 -1
  365. package/dist/recording/wiring/values.d.ts +0 -19
  366. package/dist/recording/wiring/values.d.ts.map +0 -1
  367. package/dist/recording/wiring/values.js +0 -49
  368. package/dist/recording/wiring/values.js.map +0 -1
  369. package/dist/tracking/build-rehydrate-items.d.ts +0 -15
  370. package/dist/tracking/build-rehydrate-items.d.ts.map +0 -1
  371. package/dist/tracking/build-rehydrate-items.js +0 -19
  372. package/dist/tracking/build-rehydrate-items.js.map +0 -1
  373. package/dist/tracking/constants.d.ts +0 -24
  374. package/dist/tracking/constants.d.ts.map +0 -1
  375. package/dist/tracking/constants.js +0 -52
  376. package/dist/tracking/constants.js.map +0 -1
  377. package/dist/tracking/context.d.ts.map +0 -1
  378. package/dist/tracking/context.js.map +0 -1
  379. package/dist/tracking/index.d.ts +0 -16
  380. package/dist/tracking/index.d.ts.map +0 -1
  381. package/dist/tracking/index.js +0 -11
  382. package/dist/tracking/index.js.map +0 -1
  383. package/dist/tracking/plugin-event-tracker.d.ts +0 -13
  384. package/dist/tracking/plugin-event-tracker.d.ts.map +0 -1
  385. package/dist/tracking/plugin-event-tracker.js +0 -27
  386. package/dist/tracking/plugin-event-tracker.js.map +0 -1
  387. package/dist/tracking/position-id-registry.d.ts.map +0 -1
  388. package/dist/tracking/position-id-registry.js.map +0 -1
  389. package/dist/tracking/spans/constants.d.ts +0 -19
  390. package/dist/tracking/spans/constants.d.ts.map +0 -1
  391. package/dist/tracking/spans/constants.js +0 -31
  392. package/dist/tracking/spans/constants.js.map +0 -1
  393. package/dist/tracking/spans/fan-out-span-transport.d.ts +0 -22
  394. package/dist/tracking/spans/fan-out-span-transport.d.ts.map +0 -1
  395. package/dist/tracking/spans/fan-out-span-transport.js +0 -49
  396. package/dist/tracking/spans/fan-out-span-transport.js.map +0 -1
  397. package/dist/tracking/spans/index.d.ts +0 -13
  398. package/dist/tracking/spans/index.d.ts.map +0 -1
  399. package/dist/tracking/spans/index.js +0 -16
  400. package/dist/tracking/spans/index.js.map +0 -1
  401. package/dist/tracking/spans/otel/fit-row-budget.d.ts +0 -22
  402. package/dist/tracking/spans/otel/fit-row-budget.d.ts.map +0 -1
  403. package/dist/tracking/spans/otel/fit-row-budget.js +0 -91
  404. package/dist/tracking/spans/otel/fit-row-budget.js.map +0 -1
  405. package/dist/tracking/spans/otel/map-span-to-trace-row.d.ts +0 -16
  406. package/dist/tracking/spans/otel/map-span-to-trace-row.d.ts.map +0 -1
  407. package/dist/tracking/spans/otel/map-span-to-trace-row.js +0 -227
  408. package/dist/tracking/spans/otel/map-span-to-trace-row.js.map +0 -1
  409. package/dist/tracking/spans/otel/recording-span-transport.d.ts +0 -43
  410. package/dist/tracking/spans/otel/recording-span-transport.d.ts.map +0 -1
  411. package/dist/tracking/spans/otel/recording-span-transport.js +0 -67
  412. package/dist/tracking/spans/otel/recording-span-transport.js.map +0 -1
  413. package/dist/tracking/spans/otel/span-ids.d.ts +0 -22
  414. package/dist/tracking/spans/otel/span-ids.d.ts.map +0 -1
  415. package/dist/tracking/spans/otel/span-ids.js +0 -32
  416. package/dist/tracking/spans/otel/span-ids.js.map +0 -1
  417. package/dist/tracking/spans/plugin-span-tracker.d.ts +0 -9
  418. package/dist/tracking/spans/plugin-span-tracker.d.ts.map +0 -1
  419. package/dist/tracking/spans/plugin-span-tracker.js +0 -115
  420. package/dist/tracking/spans/plugin-span-tracker.js.map +0 -1
  421. package/dist/tracking/spans/redact-pii.d.ts.map +0 -1
  422. package/dist/tracking/spans/redact-pii.js.map +0 -1
  423. package/dist/tracking/spans/sanitize-payload.d.ts.map +0 -1
  424. package/dist/tracking/spans/sanitize-payload.js.map +0 -1
  425. package/dist/tracking/spans/span-hooks.d.ts +0 -28
  426. package/dist/tracking/spans/span-hooks.d.ts.map +0 -1
  427. package/dist/tracking/spans/span-hooks.js +0 -409
  428. package/dist/tracking/spans/span-hooks.js.map +0 -1
  429. package/dist/tracking/spans/span-tracker.d.ts +0 -133
  430. package/dist/tracking/spans/span-tracker.d.ts.map +0 -1
  431. package/dist/tracking/spans/span-tracker.js +0 -721
  432. package/dist/tracking/spans/span-tracker.js.map +0 -1
  433. package/dist/tracking/spans/span-transport.d.ts +0 -71
  434. package/dist/tracking/spans/span-transport.d.ts.map +0 -1
  435. package/dist/tracking/spans/span-transport.js +0 -240
  436. package/dist/tracking/spans/span-transport.js.map +0 -1
  437. package/dist/tracking/spans/types.d.ts +0 -101
  438. package/dist/tracking/spans/types.d.ts.map +0 -1
  439. package/dist/tracking/spans/types.js +0 -6
  440. package/dist/tracking/spans/types.js.map +0 -1
  441. package/dist/tracking/tracker.d.ts +0 -30
  442. package/dist/tracking/tracker.d.ts.map +0 -1
  443. package/dist/tracking/tracker.js +0 -66
  444. package/dist/tracking/tracker.js.map +0 -1
  445. package/dist/tracking/tracking-handler.d.ts +0 -12
  446. package/dist/tracking/tracking-handler.d.ts.map +0 -1
  447. package/dist/tracking/tracking-handler.js +0 -148
  448. package/dist/tracking/tracking-handler.js.map +0 -1
  449. package/dist/tracking/transport.d.ts +0 -35
  450. package/dist/tracking/transport.d.ts.map +0 -1
  451. package/dist/tracking/transport.js +0 -133
  452. package/dist/tracking/transport.js.map +0 -1
  453. package/dist/tracking/types.d.ts +0 -21
  454. package/dist/tracking/types.d.ts.map +0 -1
  455. package/dist/tracking/types.js +0 -6
  456. package/dist/tracking/types.js.map +0 -1
  457. /package/dist/{tracking → telemetry}/spans/sanitize-payload.d.ts +0 -0
  458. /package/dist/{tracking → telemetry}/spans/sanitize-payload.js +0 -0
@@ -6,9 +6,11 @@ import { formatDecisionErrorNotification } from '../../runtime/notifications.js'
6
6
  import { resolveLeverage } from '../../leverage/resolve-leverage.js';
7
7
  import { resolveMarginWithSource } from './resolve-margin.js';
8
8
  import { createLogger } from '../../utils/logger.js';
9
- import { positionRegistryKey } from '../../tracking/position-id-registry.js';
9
+ import { positionRegistryKey } from '../../runtime/position-id-registry.js';
10
10
  import { resolveOpenOrderType, resolveFeeOptimizedLimitOptions } from '../../utils/resolve-order-type.js';
11
- import { emitTrackingDecision, emitTrackingActionResult, emitOrderPlaced, emitOrderFilled, emitOrderFailed } from '../tracking-helpers.js';
11
+ import { emitActionResultEvents, emitOrderPlaced, emitOrderFilled, emitOrderFailed, buildActionEventContext } from '../action-events.js';
12
+ import { withSpan } from '../../telemetry/tracing.js';
13
+ import { SpanStatusCode } from '@opentelemetry/api';
12
14
  const logger = createLogger("[actions][open-position]");
13
15
  /** Hyperliquid minimum notional value (margin × leverage) required to open a position. */
14
16
  const MIN_NOTIONAL_VALUE = 10;
@@ -30,19 +32,18 @@ export class OpenPositionAction {
30
32
  this.decisionEngine.register(new RuleDecisionStrategy());
31
33
  this.decisionEngine.register(new NoDecisionStrategy());
32
34
  }
33
- trackingCtx() {
34
- return {
35
+ eventCtx() {
36
+ return buildActionEventContext({
35
37
  hookSystem: this.context.hookSystem,
36
38
  actionName: this.name,
37
39
  actionType: this.actionType,
38
40
  decisionMode: this.config.decision_mode,
39
41
  decisionModel: this.config.decision_model,
40
42
  minConfidence: this.config.min_confidence,
41
- };
43
+ positionIdRegistry: this.context.positionIdRegistry,
44
+ });
42
45
  }
43
46
  async handle(event) {
44
- // Telemetry: pass start = "action began handling the scan event" (NOT "LLM call dispatched").
45
- const decisionStartedAt = Date.now();
46
47
  logger.info('handling open position', event);
47
48
  //check event type is on_signal_detected
48
49
  if (event.type !== HOOK_EVENT.ON_SIGNAL_DETECTED) {
@@ -125,7 +126,6 @@ export class OpenPositionAction {
125
126
  : undefined;
126
127
  // Get decision
127
128
  let decision;
128
- let decisionEndedAt;
129
129
  try {
130
130
  decision = await this.decisionEngine.decide(this.config.decision_mode, {
131
131
  prompt: interpolatedPrompt,
@@ -134,10 +134,8 @@ export class OpenPositionAction {
134
134
  actionType: this.actionType,
135
135
  event,
136
136
  });
137
- decisionEndedAt = Date.now();
138
137
  }
139
138
  catch (error) {
140
- decisionEndedAt = Date.now();
141
139
  const message = error instanceof Error ? error.message : String(error);
142
140
  logger.error('decision error', message);
143
141
  const notificationMessage = formatDecisionErrorNotification(message, {
@@ -145,8 +143,7 @@ export class OpenPositionAction {
145
143
  model: this.config.decision_model,
146
144
  });
147
145
  await this.context.notifications.notify(notificationMessage).catch(() => { });
148
- const trackingCtx = this.trackingCtx();
149
- emitTrackingDecision(trackingCtx, event, address, scanResult, { error: message }, undefined, interpolatedPrompt, contextData);
146
+ const eventCtx = this.eventCtx();
150
147
  const errorResult = {
151
148
  success: false,
152
149
  action_type: this.actionType,
@@ -165,15 +162,14 @@ export class OpenPositionAction {
165
162
  _decisionPrompt: interpolatedPrompt ?? null,
166
163
  },
167
164
  };
168
- emitTrackingActionResult(trackingCtx, event, address, errorResult, { scanResult, decisionStartedAt, decisionEndedAt });
165
+ emitActionResultEvents(eventCtx, event, address, errorResult, { scanResult });
169
166
  return errorResult;
170
167
  }
171
168
  logger.info('decision', decision);
172
- const trackingCtx = this.trackingCtx();
169
+ const eventCtx = this.eventCtx();
173
170
  const minConfidence = this.config.min_confidence ?? 1;
174
- const trackingExtras = { scanResult, decisionStartedAt, decisionEndedAt, minConfidence };
171
+ const trackingExtras = { scanResult, minConfidence };
175
172
  const isBelowConfidence = decision.execute && decision.confidence < minConfidence;
176
- emitTrackingDecision(trackingCtx, event, address, scanResult, decision, minConfidence, interpolatedPrompt, contextData, isBelowConfidence ? 'below_confidence' : undefined);
177
173
  // Check decision
178
174
  if (!decision.execute) {
179
175
  logger.info('decision no execute', decision);
@@ -190,7 +186,7 @@ export class OpenPositionAction {
190
186
  _decisionPrompt: interpolatedPrompt ?? null,
191
187
  },
192
188
  };
193
- emitTrackingActionResult(trackingCtx, event, address, rejectedResult, trackingExtras);
189
+ emitActionResultEvents(eventCtx, event, address, rejectedResult, trackingExtras);
194
190
  return rejectedResult;
195
191
  }
196
192
  // Check confidence threshold
@@ -209,7 +205,7 @@ export class OpenPositionAction {
209
205
  _decisionPrompt: interpolatedPrompt ?? null,
210
206
  },
211
207
  };
212
- emitTrackingActionResult(trackingCtx, event, address, belowConfResult, trackingExtras);
208
+ emitActionResultEvents(eventCtx, event, address, belowConfResult, trackingExtras);
213
209
  return belowConfResult;
214
210
  }
215
211
  // ── Unified signals path ──
@@ -223,7 +219,7 @@ export class OpenPositionAction {
223
219
  error: 'invalid_payload',
224
220
  data: { _decisionMeta: meta, _decisionPrompt: interpolatedPrompt ?? null },
225
221
  };
226
- emitTrackingActionResult(trackingCtx, event, address, invalidPayloadResult, trackingExtras);
222
+ emitActionResultEvents(eventCtx, event, address, invalidPayloadResult, trackingExtras);
227
223
  return invalidPayloadResult;
228
224
  }
229
225
  return this.handleSignals(signals, event, strategyState, decision.reasoning, meta, interpolatedPrompt, trackingExtras);
@@ -310,7 +306,7 @@ export class OpenPositionAction {
310
306
  _decisionPrompt: decisionPrompt ?? null,
311
307
  },
312
308
  };
313
- emitTrackingActionResult(this.trackingCtx(), event, address, skipResult, trackingExtras);
309
+ emitActionResultEvents(this.eventCtx(), event, address, skipResult, trackingExtras);
314
310
  return skipResult;
315
311
  }
316
312
  const withdrawable = clearinghouseView.withdrawable;
@@ -324,238 +320,300 @@ export class OpenPositionAction {
324
320
  let submittedCount = 0;
325
321
  let failedCount = 0;
326
322
  for (const signal of sorted) {
327
- // Telemetry: per-signal work window — every result entry below carries startedAt/endedAt.
328
- const signalStartedAt = Date.now();
329
323
  const asset = signal.asset;
330
324
  const direction = signal.direction;
331
325
  const signalScore = signal.score;
332
- const signalDex = signal.dex;
333
- const submittedDex = typeof signalDex === "string" && signalDex.trim() !== "" ? signalDex.trim() : "main";
334
- const dexForLookup = submittedDex === "main" ? undefined : submittedDex;
335
- if (remainingSlots <= 0) {
336
- results.push({ asset, direction, dex: submittedDex, score: signalScore, success: true, reason: 'no_slots', startedAt: signalStartedAt, endedAt: Date.now() });
337
- continue;
338
- }
339
- if (!direction || (direction !== 'LONG' && direction !== 'SHORT')) {
340
- results.push({ asset, direction, dex: submittedDex, score: signalScore, success: false, reason: 'invalid_direction', startedAt: signalStartedAt, endedAt: Date.now() });
341
- failedCount++;
342
- continue;
343
- }
344
- if (strategyState.hasOpenPosition(asset, dexForLookup)) {
345
- results.push({ asset, direction, dex: submittedDex, score: signalScore, success: true, reason: 'position_already_exists', startedAt: signalStartedAt, endedAt: Date.now() });
346
- continue;
347
- }
348
- // Risk guard per-open (real-time via MCP, with per-asset cooldown)
349
- const gate = await this.context.riskGuard.checkGate(address, { candidateAsset: asset });
350
- if (gate.gate !== 'OPEN') {
351
- results.push({ asset, direction, dex: submittedDex, score: signalScore, success: true, reason: `risk_gate_${gate.gate}`, startedAt: signalStartedAt, endedAt: Date.now() });
352
- continue;
353
- }
354
- // Leverage: LLM override > config-based resolution
355
- const llmLeverage = typeof signal.leverage === 'number' ? signal.leverage : undefined;
356
- const maxLeverage = await this.context.maxLeverageCache.get(asset, address) ?? 20;
357
- const leverage = llmLeverage != null && llmLeverage > 0
358
- ? Math.max(MIN_LEVERAGE, Math.min(llmLeverage, maxLeverage))
359
- : resolveLeverage({
360
- tradingRisk: strategyState.config.tradingRisk,
361
- maxLeverage,
362
- defaultLeverage: strategyState.config.defaultLeverage,
363
- leverageMultipliers: strategyState.config.leverageMultipliers,
326
+ await withSpan("signal.evaluation", {
327
+ "senpi.signal.asset": asset,
328
+ "senpi.signal.direction": direction,
329
+ ...(typeof signalScore === "number" ? { "senpi.signal.score": signalScore } : {}),
330
+ }, async (span) => {
331
+ // Terminal outcome on this candidate's span. A failed result also shows red.
332
+ const outcome = (result, reason) => {
333
+ span.setAttribute("senpi.outcome.result", result);
334
+ span.setAttribute("senpi.outcome.reason_code", reason);
335
+ if (result === "failed")
336
+ span.setStatus({ code: SpanStatusCode.ERROR, message: reason });
337
+ };
338
+ // Telemetry: per-signal work window — every result entry below carries startedAt/endedAt.
339
+ const signalStartedAt = Date.now();
340
+ const signalDex = signal.dex;
341
+ const submittedDex = typeof signalDex === "string" && signalDex.trim() !== "" ? signalDex.trim() : "main";
342
+ const dexForLookup = submittedDex === "main" ? undefined : submittedDex;
343
+ if (remainingSlots <= 0) {
344
+ results.push({ asset, direction, dex: submittedDex, score: signalScore, success: true, reason: 'no_slots', startedAt: signalStartedAt, endedAt: Date.now() });
345
+ outcome("skipped", 'no_slots');
346
+ return;
347
+ }
348
+ if (!direction || (direction !== 'LONG' && direction !== 'SHORT')) {
349
+ results.push({ asset, direction, dex: submittedDex, score: signalScore, success: false, reason: 'invalid_direction', startedAt: signalStartedAt, endedAt: Date.now() });
350
+ failedCount++;
351
+ outcome("failed", 'invalid_direction');
352
+ return;
353
+ }
354
+ if (strategyState.hasOpenPosition(asset, dexForLookup)) {
355
+ results.push({ asset, direction, dex: submittedDex, score: signalScore, success: true, reason: 'position_already_exists', startedAt: signalStartedAt, endedAt: Date.now() });
356
+ outcome("skipped", 'position_already_exists');
357
+ return;
358
+ }
359
+ // Risk guard per-open (real-time via MCP, with per-asset cooldown)
360
+ const gate = await withSpan("risk.gate", {}, async (gateSpan) => {
361
+ const g = await this.context.riskGuard.checkGate(address, { candidateAsset: asset });
362
+ gateSpan.setAttribute("senpi.risk.gate", g.gate);
363
+ if (g.gate !== 'OPEN')
364
+ gateSpan.setStatus({ code: SpanStatusCode.ERROR, message: g.reason ?? g.gate });
365
+ return g;
364
366
  });
365
- // Margin: per-signal marginPct (% of withdrawable) > config margin_pct
366
- // > margin_per_slot > budget / slots
367
- const signalMarginPct = typeof signal.marginPct === 'number' ? signal.marginPct : undefined;
368
- const { amount: marginAmount, source: marginSource } = resolveMarginWithSource({
369
- signalMarginPct,
370
- marginPct: strategyState.config.marginPct,
371
- withdrawable,
372
- marginPerSlot: strategyState.config.marginPerSlot,
373
- budget: strategyState.config.budget,
374
- slots: strategyState.config.slots,
375
- });
376
- if (marginAmount == null || marginAmount <= 0) {
377
- logger.warn(`Skipping ${asset}: no margin source resolved. ` +
378
- `Set strategy.margin_per_slot, strategy.margin_pct, or strategy.budget + strategy.slots ` +
379
- `in the recipe, or have the LLM provide a per-signal margin override.`, {
380
- asset,
381
- wallet: address,
367
+ if (gate.gate !== 'OPEN') {
368
+ results.push({ asset, direction, dex: submittedDex, score: signalScore, success: true, reason: `risk_gate_${gate.gate}`, startedAt: signalStartedAt, endedAt: Date.now() });
369
+ outcome("skipped", `risk_gate_${gate.gate}`);
370
+ return;
371
+ }
372
+ // Leverage: LLM override > config-based resolution
373
+ const llmLeverage = typeof signal.leverage === 'number' ? signal.leverage : undefined;
374
+ const maxLeverage = await this.context.maxLeverageCache.get(asset, address) ?? 20;
375
+ const leverage = llmLeverage != null && llmLeverage > 0
376
+ ? Math.max(MIN_LEVERAGE, Math.min(llmLeverage, maxLeverage))
377
+ : resolveLeverage({
378
+ tradingRisk: strategyState.config.tradingRisk,
379
+ maxLeverage,
380
+ defaultLeverage: strategyState.config.defaultLeverage,
381
+ leverageMultipliers: strategyState.config.leverageMultipliers,
382
+ });
383
+ // Margin: per-signal marginPct (% of withdrawable) > config margin_pct
384
+ // > margin_per_slot > budget / slots
385
+ const signalMarginPct = typeof signal.marginPct === 'number' ? signal.marginPct : undefined;
386
+ const { amount: marginAmount, source: marginSource } = resolveMarginWithSource({
382
387
  signalMarginPct,
383
388
  marginPct: strategyState.config.marginPct,
389
+ withdrawable,
384
390
  marginPerSlot: strategyState.config.marginPerSlot,
385
391
  budget: strategyState.config.budget,
386
392
  slots: strategyState.config.slots,
387
- withdrawable,
388
- });
389
- results.push({ asset, direction, dex: submittedDex, score: signalScore, leverage, success: false, reason: 'no_margin_configured', startedAt: signalStartedAt, endedAt: Date.now() });
390
- failedCount++;
391
- continue;
392
- }
393
- const notionalValue = marginAmount * leverage;
394
- if (notionalValue < MIN_NOTIONAL_VALUE) {
395
- logger.warn(`Skipping ${asset}: notional value $${notionalValue.toFixed(2)} ` +
396
- `(margin $${marginAmount.toFixed(2)} × ${leverage}x) is below minimum $${MIN_NOTIONAL_VALUE}`);
397
- results.push({ asset, direction, dex: submittedDex, score: signalScore, leverage, marginAmount, notionalValue, success: false, reason: 'below_min_notional', startedAt: signalStartedAt, endedAt: Date.now() });
398
- failedCount++;
399
- continue;
400
- }
401
- // Free-margin pre-flight: if we know free margin and it can't cover this
402
- // position's margin, skip rather than fire a create the engine will reject
403
- // (CREATE_INSUFFICIENT_FUNDS). Skip the check when free margin is unknown.
404
- if (remainingMargin != null && remainingMargin < marginAmount) {
405
- logger.warn(`Skipping ${asset}: insufficient free margin ` +
406
- `($${remainingMargin.toFixed(2)} available < $${marginAmount.toFixed(2)} required)`);
407
- results.push({ asset, direction, dex: submittedDex, score: signalScore, leverage, marginAmount, requiredMarginAmount: marginAmount, availableMarginAmount: remainingMargin, success: true, reason: 'insufficient_margin', startedAt: signalStartedAt, endedAt: Date.now() });
408
- continue;
409
- }
410
- const signalReason = signal.reason ?? signal.signalType ?? reasoning;
411
- try {
412
- // Sizing breadcrumb: WHICH source set the margin + the numbers behind it,
413
- // so a wrong size is attributable from logs without reverse-engineering.
414
- logger.info('opening position', {
415
- wallet: address,
416
- asset,
417
- direction,
418
- source: marginSource,
419
- withdrawable,
420
- accountValue: clearinghouseView.accountValue,
421
- marginAmount,
422
- leverage,
423
- notional: notionalValue,
424
393
  });
425
- const result = await this.context.senpi.createPosition({
426
- strategyWalletAddress: address,
427
- orders: [
428
- {
429
- coin: asset,
394
+ // The applied percent — only meaningful for the two percent-of-withdrawable branches; the
395
+ // fixed/budget sources have no percent. Rides the result entry so the sizing attribution
396
+ // (source + percent) reaches the signal.outcome event, not just the structured log below.
397
+ const marginPct = marginSource === 'signal_marginPct' ? signalMarginPct
398
+ : marginSource === 'config_margin_pct' ? strategyState.config.marginPct
399
+ : undefined;
400
+ if (marginAmount == null || marginAmount <= 0) {
401
+ logger.warn(`Skipping ${asset}: no margin source resolved. ` +
402
+ `Set strategy.margin_per_slot, strategy.margin_pct, or strategy.budget + strategy.slots ` +
403
+ `in the recipe, or have the LLM provide a per-signal margin override.`, {
404
+ asset,
405
+ wallet: address,
406
+ signalMarginPct,
407
+ marginPct: strategyState.config.marginPct,
408
+ marginPerSlot: strategyState.config.marginPerSlot,
409
+ budget: strategyState.config.budget,
410
+ slots: strategyState.config.slots,
411
+ withdrawable,
412
+ });
413
+ results.push({ asset, direction, dex: submittedDex, score: signalScore, leverage, success: false, reason: 'no_margin_configured', startedAt: signalStartedAt, endedAt: Date.now() });
414
+ failedCount++;
415
+ outcome("failed", 'no_margin_configured');
416
+ return;
417
+ }
418
+ const notionalValue = marginAmount * leverage;
419
+ if (notionalValue < MIN_NOTIONAL_VALUE) {
420
+ logger.warn(`Skipping ${asset}: notional value $${notionalValue.toFixed(2)} ` +
421
+ `(margin $${marginAmount.toFixed(2)} × ${leverage}x) is below minimum $${MIN_NOTIONAL_VALUE}`);
422
+ results.push({ asset, direction, dex: submittedDex, score: signalScore, leverage, marginAmount, marginSource, marginPct, notionalValue, success: false, reason: 'below_min_notional', startedAt: signalStartedAt, endedAt: Date.now() });
423
+ failedCount++;
424
+ outcome("failed", 'below_min_notional');
425
+ return;
426
+ }
427
+ // Free-margin pre-flight: if we know free margin and it can't cover this
428
+ // position's margin, skip rather than fire a create the engine will reject
429
+ // (CREATE_INSUFFICIENT_FUNDS). Skip the check when free margin is unknown.
430
+ if (remainingMargin != null && remainingMargin < marginAmount) {
431
+ logger.warn(`Skipping ${asset}: insufficient free margin ` +
432
+ `($${remainingMargin.toFixed(2)} available < $${marginAmount.toFixed(2)} required)`);
433
+ results.push({ asset, direction, dex: submittedDex, score: signalScore, leverage, marginAmount, marginSource, marginPct, requiredMarginAmount: marginAmount, availableMarginAmount: remainingMargin, success: true, reason: 'insufficient_margin', startedAt: signalStartedAt, endedAt: Date.now() });
434
+ outcome("skipped", 'insufficient_margin');
435
+ return;
436
+ }
437
+ const signalReason = signal.reason ?? signal.signalType ?? reasoning;
438
+ try {
439
+ // Sizing breadcrumb: WHICH source set the margin + the numbers behind it,
440
+ // so a wrong size is attributable from logs without reverse-engineering.
441
+ logger.info('opening position', {
442
+ wallet: address,
443
+ asset,
444
+ direction,
445
+ source: marginSource,
446
+ withdrawable,
447
+ accountValue: clearinghouseView.accountValue,
448
+ marginAmount,
449
+ leverage,
450
+ notional: notionalValue,
451
+ });
452
+ const result = await withSpan("mcp.createPosition", { "senpi.signal.asset": asset, "senpi.signal.direction": direction }, async (mcpSpan) => {
453
+ const r = await this.context.senpi.createPosition({
454
+ strategyWalletAddress: address,
455
+ orders: [
456
+ {
457
+ coin: asset,
458
+ direction,
459
+ leverage,
460
+ marginAmount,
461
+ orderType,
462
+ ...(feeOptimizedLimitOptions ? { feeOptimizedLimitOptions } : {}),
463
+ },
464
+ ],
465
+ reason: signalReason,
466
+ });
467
+ if (!r.success) {
468
+ const orderErrors = r.orders
469
+ .filter((o) => o.error)
470
+ .map((o) => `${o.coin}: ${o.error}`)
471
+ .join('; ');
472
+ const detail = r.error || orderErrors || 'unknown error';
473
+ mcpSpan.addEvent("order.failed");
474
+ mcpSpan.setStatus({ code: SpanStatusCode.ERROR, message: detail });
475
+ }
476
+ else {
477
+ const o = r.orders[0];
478
+ if (o?.orderId != null)
479
+ mcpSpan.setAttribute("senpi.order.id", o.orderId);
480
+ if (o?.filled != null)
481
+ mcpSpan.setAttribute("senpi.outcome.filled", o.filled);
482
+ if (o?.executionAsMaker != null)
483
+ mcpSpan.setAttribute("senpi.outcome.execution_as_maker", o.executionAsMaker);
484
+ if (o?.entryPrice != null)
485
+ mcpSpan.setAttribute("senpi.order.entry_price", o.entryPrice);
486
+ if (o?.size != null)
487
+ mcpSpan.setAttribute("senpi.order.size", o.size);
488
+ mcpSpan.addEvent("order.placed");
489
+ if (o?.filled)
490
+ mcpSpan.addEvent("order.filled");
491
+ }
492
+ return r;
493
+ });
494
+ if (!result.success) {
495
+ const orderErrors = result.orders
496
+ .filter((o) => o.error)
497
+ .map((o) => `${o.coin}: ${o.error}`)
498
+ .join('; ');
499
+ const detail = result.error || orderErrors || 'unknown error';
500
+ results.push({
501
+ asset, direction, dex: submittedDex, score: signalScore,
502
+ leverage, marginAmount, marginSource, marginPct, orderType,
503
+ success: false, reason: 'position_open_failed', error: detail,
504
+ startedAt: signalStartedAt, endedAt: Date.now(),
505
+ });
506
+ // Task 8a: the venue rejected the open submit.
507
+ emitOrderFailed(this.context.hookSystem, event, address, {
508
+ asset,
509
+ direction,
510
+ reason: 'position_open_failed',
511
+ error: detail,
512
+ reduceOnly: false,
513
+ });
514
+ failedCount++;
515
+ outcome("failed", 'position_open_failed');
516
+ return;
517
+ }
518
+ const submittedOrder = result.orders[0];
519
+ // Mint the position.id at intent — the moment the open order is submitted,
520
+ // before the position is confirmed open — so the id rides the action.open
521
+ // emit and the open trace correlates by position.id directly (no ~60s
522
+ // bridge on the read side).
523
+ let mintedPositionId;
524
+ if (this.context.positionIdRegistry) {
525
+ try {
526
+ const minted = this.context.positionIdRegistry.mintOnIntent(positionRegistryKey(address, submittedDex, asset));
527
+ mintedPositionId = minted.positionId;
528
+ }
529
+ catch (err) {
530
+ // The order is already on the exchange — a registry failure must not land in the
531
+ // outer catch, which would mislabel this submit as an exception and skip the
532
+ // slot/margin bookkeeping.
533
+ const message = err instanceof Error ? err.message : String(err);
534
+ logger.warn('position.id mint failed; continuing with submit emit', err, { asset });
535
+ }
536
+ }
537
+ await this.context.hookSystem.fire({
538
+ type: HOOK_EVENT.ON_OPEN_ORDER_SUBMITTED,
539
+ runtimeName: event.runtimeName,
540
+ address,
541
+ data: {
542
+ asset,
430
543
  direction,
431
544
  leverage,
432
545
  marginAmount,
433
546
  orderType,
434
- ...(feeOptimizedLimitOptions ? { feeOptimizedLimitOptions } : {}),
547
+ wallet: address,
548
+ dex: submittedDex,
549
+ reasoning: signalReason,
550
+ orderId: submittedOrder?.orderId,
551
+ entryPrice: submittedOrder?.entryPrice ?? null,
552
+ size: submittedOrder?.size ?? null,
553
+ filled: submittedOrder?.filled ?? null,
554
+ ...(mintedPositionId ? { __positionId: mintedPositionId } : {}),
435
555
  },
436
- ],
437
- reason: signalReason,
438
- });
439
- if (!result.success) {
440
- const orderErrors = result.orders
441
- .filter((o) => o.error)
442
- .map((o) => `${o.coin}: ${o.error}`)
443
- .join('; ');
444
- const detail = result.error || orderErrors || 'unknown error';
556
+ timestamp: new Date().toISOString(),
557
+ });
445
558
  results.push({
446
559
  asset, direction, dex: submittedDex, score: signalScore,
447
- leverage, marginAmount, orderType,
448
- success: false, reason: 'position_open_failed', error: detail,
560
+ leverage, marginAmount, marginSource, marginPct, orderType,
561
+ orderId: submittedOrder?.orderId ?? null,
562
+ entryPrice: submittedOrder?.entryPrice ?? null,
563
+ size: submittedOrder?.size ?? null,
564
+ filled: submittedOrder?.filled ?? null,
565
+ success: true, reason: 'submitted',
449
566
  startedAt: signalStartedAt, endedAt: Date.now(),
450
567
  });
451
- // Task 8a: the venue rejected the open submit.
452
- emitOrderFailed(this.context.hookSystem, event, address, {
568
+ // Task 8a order-event log (additive, fire-and-forget — see emit helpers). The open submit
569
+ // is an `order.placed`; a confirmed fill additionally emits `order.filled`.
570
+ emitOrderPlaced(this.context.hookSystem, event, address, {
571
+ orderId: submittedOrder?.orderId,
572
+ orderType,
453
573
  asset,
454
574
  direction,
455
- reason: 'position_open_failed',
456
- error: detail,
575
+ size: submittedOrder?.size,
457
576
  reduceOnly: false,
577
+ ...(mintedPositionId ? { __positionId: mintedPositionId } : {}),
458
578
  });
459
- failedCount++;
460
- continue;
461
- }
462
- const submittedOrder = result.orders[0];
463
- // Mint the position.id at intent — the moment the open order is submitted,
464
- // before the position is confirmed open — so the id rides the action.open
465
- // emit and the open trace correlates by position.id directly (no ~60s
466
- // bridge on the read side).
467
- let mintedPositionId;
468
- if (this.context.positionIdRegistry) {
469
- try {
470
- const minted = this.context.positionIdRegistry.mintOnIntent(positionRegistryKey(address, submittedDex, asset));
471
- mintedPositionId = minted.positionId;
472
- }
473
- catch (err) {
474
- // The order is already on the exchange — a registry failure must not land in the
475
- // outer catch, which would mislabel this submit as an exception and skip the
476
- // slot/margin bookkeeping.
477
- const message = err instanceof Error ? err.message : String(err);
478
- logger.warn('position.id mint failed; continuing with submit emit', { asset, err: message });
579
+ if (submittedOrder?.filled) {
580
+ emitOrderFilled(this.context.hookSystem, event, address, {
581
+ orderId: submittedOrder?.orderId,
582
+ asset,
583
+ fillPrice: submittedOrder?.entryPrice,
584
+ fillSize: submittedOrder?.size,
585
+ executionAsMaker: submittedOrder?.executionAsMaker,
586
+ ...(mintedPositionId ? { __positionId: mintedPositionId } : {}),
587
+ });
479
588
  }
589
+ submittedCount++;
590
+ remainingSlots--;
591
+ if (remainingMargin != null)
592
+ remainingMargin -= marginAmount;
593
+ outcome("submitted", 'submitted');
480
594
  }
481
- await this.context.hookSystem.fire({
482
- type: HOOK_EVENT.ON_OPEN_ORDER_SUBMITTED,
483
- runtimeName: event.runtimeName,
484
- address,
485
- data: {
595
+ catch (error) {
596
+ const message = error instanceof Error ? error.message : String(error);
597
+ logger.error('open failed', error, { asset });
598
+ results.push({
599
+ asset, direction, dex: submittedDex, score: signalScore,
600
+ leverage, marginAmount, marginSource, marginPct, orderType,
601
+ success: false, reason: 'exception', error: message,
602
+ startedAt: signalStartedAt, endedAt: Date.now(),
603
+ });
604
+ // Task 8a: the open submit threw.
605
+ emitOrderFailed(this.context.hookSystem, event, address, {
486
606
  asset,
487
607
  direction,
488
- leverage,
489
- marginAmount,
490
- orderType,
491
- wallet: address,
492
- dex: submittedDex,
493
- reasoning: signalReason,
494
- orderId: submittedOrder?.orderId,
495
- entryPrice: submittedOrder?.entryPrice ?? null,
496
- size: submittedOrder?.size ?? null,
497
- filled: submittedOrder?.filled ?? null,
498
- __correlationId: event.data.__correlationId,
499
- ...(mintedPositionId ? { __positionId: mintedPositionId } : {}),
500
- },
501
- timestamp: new Date().toISOString(),
502
- });
503
- results.push({
504
- asset, direction, dex: submittedDex, score: signalScore,
505
- leverage, marginAmount, orderType,
506
- orderId: submittedOrder?.orderId ?? null,
507
- entryPrice: submittedOrder?.entryPrice ?? null,
508
- size: submittedOrder?.size ?? null,
509
- filled: submittedOrder?.filled ?? null,
510
- success: true, reason: 'submitted',
511
- startedAt: signalStartedAt, endedAt: Date.now(),
512
- });
513
- // Task 8a order-event log (additive, fire-and-forget — see emit helpers). The open submit
514
- // is an `order.placed`; a confirmed fill additionally emits `order.filled`.
515
- emitOrderPlaced(this.context.hookSystem, event, address, {
516
- orderId: submittedOrder?.orderId,
517
- orderType,
518
- asset,
519
- direction,
520
- size: submittedOrder?.size,
521
- reduceOnly: false,
522
- ...(mintedPositionId ? { __positionId: mintedPositionId } : {}),
523
- });
524
- if (submittedOrder?.filled) {
525
- emitOrderFilled(this.context.hookSystem, event, address, {
526
- orderId: submittedOrder?.orderId,
527
- asset,
528
- fillPrice: submittedOrder?.entryPrice,
529
- fillSize: submittedOrder?.size,
530
- executionAsMaker: submittedOrder?.executionAsMaker,
531
- ...(mintedPositionId ? { __positionId: mintedPositionId } : {}),
608
+ reason: 'exception',
609
+ error: message,
610
+ errorName: error instanceof Error ? error.name : undefined,
611
+ reduceOnly: false,
532
612
  });
613
+ failedCount++;
614
+ outcome("failed", 'exception');
533
615
  }
534
- submittedCount++;
535
- remainingSlots--;
536
- if (remainingMargin != null)
537
- remainingMargin -= marginAmount;
538
- }
539
- catch (error) {
540
- const message = error instanceof Error ? error.message : String(error);
541
- logger.error('open failed', { asset, err: message });
542
- results.push({
543
- asset, direction, dex: submittedDex, score: signalScore,
544
- leverage, marginAmount, orderType,
545
- success: false, reason: 'exception', error: message,
546
- startedAt: signalStartedAt, endedAt: Date.now(),
547
- });
548
- // Task 8a: the open submit threw.
549
- emitOrderFailed(this.context.hookSystem, event, address, {
550
- asset,
551
- direction,
552
- reason: 'exception',
553
- error: message,
554
- errorName: error instanceof Error ? error.name : undefined,
555
- reduceOnly: false,
556
- });
557
- failedCount++;
558
- }
616
+ });
559
617
  }
560
618
  const skippedCount = results.length - submittedCount - failedCount;
561
619
  const actionResult = {
@@ -572,7 +630,7 @@ export class OpenPositionAction {
572
630
  _decisionPrompt: decisionPrompt ?? null,
573
631
  },
574
632
  };
575
- emitTrackingActionResult(this.trackingCtx(), event, address, actionResult, trackingExtras);
633
+ emitActionResultEvents(this.eventCtx(), event, address, actionResult, trackingExtras);
576
634
  return actionResult;
577
635
  }
578
636
  }