@senpi/runtime 3.0.132 → 3.0.138

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 (287) hide show
  1. package/README.md +4 -12
  2. package/dist/actions/action-events.d.ts +7 -21
  3. package/dist/actions/action-events.d.ts.map +1 -1
  4. package/dist/actions/action-events.js +26 -54
  5. package/dist/actions/action-events.js.map +1 -1
  6. package/dist/actions/action-runtime-module.d.ts.map +1 -1
  7. package/dist/actions/action-runtime-module.js +7 -38
  8. package/dist/actions/action-runtime-module.js.map +1 -1
  9. package/dist/actions/close-position/close-position.action.d.ts.map +1 -1
  10. package/dist/actions/close-position/close-position.action.js +15 -122
  11. package/dist/actions/close-position/close-position.action.js.map +1 -1
  12. package/dist/actions/decision-engine.d.ts.map +1 -1
  13. package/dist/actions/decision-engine.js +2 -15
  14. package/dist/actions/decision-engine.js.map +1 -1
  15. package/dist/actions/event-derivation.d.ts +2 -71
  16. package/dist/actions/event-derivation.d.ts.map +1 -1
  17. package/dist/actions/event-derivation.js +8 -251
  18. package/dist/actions/event-derivation.js.map +1 -1
  19. package/dist/actions/open-position/open-position.action.d.ts +2 -12
  20. package/dist/actions/open-position/open-position.action.d.ts.map +1 -1
  21. package/dist/actions/open-position/open-position.action.js +41 -144
  22. package/dist/actions/open-position/open-position.action.js.map +1 -1
  23. package/dist/actions/position-tracker/position-tracker.action.d.ts +1 -2
  24. package/dist/actions/position-tracker/position-tracker.action.d.ts.map +1 -1
  25. package/dist/actions/position-tracker/position-tracker.action.js +17 -62
  26. package/dist/actions/position-tracker/position-tracker.action.js.map +1 -1
  27. package/dist/actions/store/types.d.ts +2 -9
  28. package/dist/actions/store/types.d.ts.map +1 -1
  29. package/dist/actions/store/types.js.map +1 -1
  30. package/dist/actions/types.d.ts +0 -13
  31. package/dist/actions/types.d.ts.map +1 -1
  32. package/dist/actions/types.js +0 -13
  33. package/dist/actions/types.js.map +1 -1
  34. package/dist/cli/guide-commands.d.ts.map +1 -1
  35. package/dist/cli/guide-commands.js +13 -8
  36. package/dist/cli/guide-commands.js.map +1 -1
  37. package/dist/cli/senpi-commands.d.ts.map +1 -1
  38. package/dist/cli/senpi-commands.js +11 -4
  39. package/dist/cli/senpi-commands.js.map +1 -1
  40. package/dist/constants/dsl/index.d.ts +0 -6
  41. package/dist/constants/dsl/index.d.ts.map +1 -1
  42. package/dist/constants/dsl/index.js +0 -6
  43. package/dist/constants/dsl/index.js.map +1 -1
  44. package/dist/dsl/engine-client/event-mapping.d.ts.map +1 -1
  45. package/dist/dsl/engine-client/event-mapping.js +0 -14
  46. package/dist/dsl/engine-client/event-mapping.js.map +1 -1
  47. package/dist/dsl/events/build-closed-event.d.ts +1 -16
  48. package/dist/dsl/events/build-closed-event.d.ts.map +1 -1
  49. package/dist/dsl/events/build-closed-event.js +0 -6
  50. package/dist/dsl/events/build-closed-event.js.map +1 -1
  51. package/dist/dsl/events/handlers.d.ts +0 -7
  52. package/dist/dsl/events/handlers.d.ts.map +1 -1
  53. package/dist/dsl/events/handlers.js +7 -37
  54. package/dist/dsl/events/handlers.js.map +1 -1
  55. package/dist/dsl/monitor/create-monitor.d.ts +2 -6
  56. package/dist/dsl/monitor/create-monitor.d.ts.map +1 -1
  57. package/dist/dsl/monitor/create-monitor.js +9 -82
  58. package/dist/dsl/monitor/create-monitor.js.map +1 -1
  59. package/dist/dsl/monitor/dsl-failure-events.d.ts +2 -45
  60. package/dist/dsl/monitor/dsl-failure-events.d.ts.map +1 -1
  61. package/dist/dsl/monitor/dsl-failure-events.js +3 -52
  62. package/dist/dsl/monitor/dsl-failure-events.js.map +1 -1
  63. package/dist/dsl/monitor/process-one-position.d.ts +0 -1
  64. package/dist/dsl/monitor/process-one-position.d.ts.map +1 -1
  65. package/dist/dsl/monitor/process-one-position.js +36 -159
  66. package/dist/dsl/monitor/process-one-position.js.map +1 -1
  67. package/dist/dsl/plugin/index.d.ts +2 -8
  68. package/dist/dsl/plugin/index.d.ts.map +1 -1
  69. package/dist/dsl/plugin/index.js +6 -8
  70. package/dist/dsl/plugin/index.js.map +1 -1
  71. package/dist/health/types.d.ts +0 -13
  72. package/dist/health/types.d.ts.map +1 -1
  73. package/dist/health/types.js +0 -12
  74. package/dist/health/types.js.map +1 -1
  75. package/dist/index.d.ts +4 -27
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +41 -271
  78. package/dist/index.js.map +1 -1
  79. package/dist/runtime/action-registry.d.ts.map +1 -1
  80. package/dist/runtime/action-registry.js +3 -4
  81. package/dist/runtime/action-registry.js.map +1 -1
  82. package/dist/runtime/auto-update/coordinator.d.ts +6 -13
  83. package/dist/runtime/auto-update/coordinator.d.ts.map +1 -1
  84. package/dist/runtime/auto-update/coordinator.js +18 -86
  85. package/dist/runtime/auto-update/coordinator.js.map +1 -1
  86. package/dist/runtime/auto-update/run-update-command.d.ts.map +1 -1
  87. package/dist/runtime/auto-update/run-update-command.js +3 -4
  88. package/dist/runtime/auto-update/run-update-command.js.map +1 -1
  89. package/dist/runtime/auto-update/types.d.ts +5 -11
  90. package/dist/runtime/auto-update/types.d.ts.map +1 -1
  91. package/dist/runtime/auto-update/types.js +0 -11
  92. package/dist/runtime/auto-update/types.js.map +1 -1
  93. package/dist/runtime/domain-events.d.ts.map +1 -1
  94. package/dist/runtime/domain-events.js +0 -7
  95. package/dist/runtime/domain-events.js.map +1 -1
  96. package/dist/runtime/lifecycle-events.d.ts +3 -15
  97. package/dist/runtime/lifecycle-events.d.ts.map +1 -1
  98. package/dist/runtime/lifecycle-events.js +3 -17
  99. package/dist/runtime/lifecycle-events.js.map +1 -1
  100. package/dist/runtime/lifecycle-reaper.d.ts +6 -4
  101. package/dist/runtime/lifecycle-reaper.d.ts.map +1 -1
  102. package/dist/runtime/lifecycle-reaper.js +6 -4
  103. package/dist/runtime/lifecycle-reaper.js.map +1 -1
  104. package/dist/runtime/reconcile-run.d.ts +3 -13
  105. package/dist/runtime/reconcile-run.d.ts.map +1 -1
  106. package/dist/runtime/reconcile-run.js +3 -4
  107. package/dist/runtime/reconcile-run.js.map +1 -1
  108. package/dist/runtime/reconcile-state.d.ts +0 -8
  109. package/dist/runtime/reconcile-state.d.ts.map +1 -1
  110. package/dist/runtime/reconcile-state.js +1 -4
  111. package/dist/runtime/reconcile-state.js.map +1 -1
  112. package/dist/runtime/risk-guard.d.ts +20 -1
  113. package/dist/runtime/risk-guard.d.ts.map +1 -1
  114. package/dist/runtime/risk-guard.js +47 -6
  115. package/dist/runtime/risk-guard.js.map +1 -1
  116. package/dist/runtime/run.d.ts +0 -1
  117. package/dist/runtime/run.d.ts.map +1 -1
  118. package/dist/runtime/run.js.map +1 -1
  119. package/dist/runtime/runtime-schema.js +3 -3
  120. package/dist/runtime/runtime-schema.js.map +1 -1
  121. package/dist/runtime/runtime.d.ts +3 -2
  122. package/dist/runtime/runtime.d.ts.map +1 -1
  123. package/dist/runtime/runtime.js +30 -37
  124. package/dist/runtime/runtime.js.map +1 -1
  125. package/dist/runtime/strategy-lifecycle.d.ts +108 -2
  126. package/dist/runtime/strategy-lifecycle.d.ts.map +1 -1
  127. package/dist/runtime/strategy-lifecycle.js +325 -4
  128. package/dist/runtime/strategy-lifecycle.js.map +1 -1
  129. package/dist/runtime/supervisor/long-running-supervisor.d.ts +0 -13
  130. package/dist/runtime/supervisor/long-running-supervisor.d.ts.map +1 -1
  131. package/dist/runtime/supervisor/long-running-supervisor.js +0 -1
  132. package/dist/runtime/supervisor/long-running-supervisor.js.map +1 -1
  133. package/dist/runtime/validate-dsl-position-tracking.d.ts.map +1 -1
  134. package/dist/runtime/validate-dsl-position-tracking.js +1 -2
  135. package/dist/runtime/validate-dsl-position-tracking.js.map +1 -1
  136. package/dist/runtime-api/handlers/ingest-signals.d.ts.map +1 -1
  137. package/dist/runtime-api/handlers/ingest-signals.js +0 -1
  138. package/dist/runtime-api/handlers/ingest-signals.js.map +1 -1
  139. package/dist/runtime-api/handlers/types.d.ts +0 -5
  140. package/dist/runtime-api/handlers/types.d.ts.map +1 -1
  141. package/dist/runtime-api/intake/intake-events.d.ts +1 -1
  142. package/dist/runtime-api/intake/intake-events.d.ts.map +1 -1
  143. package/dist/runtime-api/intake/intake-events.js +3 -9
  144. package/dist/runtime-api/intake/intake-events.js.map +1 -1
  145. package/dist/runtime-api/intake/intake-mount.d.ts.map +1 -1
  146. package/dist/runtime-api/intake/intake-mount.js +19 -4
  147. package/dist/runtime-api/intake/intake-mount.js.map +1 -1
  148. package/dist/runtime-api/intake/process-error-post.d.ts +1 -6
  149. package/dist/runtime-api/intake/process-error-post.d.ts.map +1 -1
  150. package/dist/runtime-api/intake/process-error-post.js +1 -5
  151. package/dist/runtime-api/intake/process-error-post.js.map +1 -1
  152. package/dist/runtime-api/intake/process-signal-post.d.ts +1 -7
  153. package/dist/runtime-api/intake/process-signal-post.d.ts.map +1 -1
  154. package/dist/runtime-api/intake/process-signal-post.js +0 -5
  155. package/dist/runtime-api/intake/process-signal-post.js.map +1 -1
  156. package/dist/runtime-api/intake/scaffold-error-router.js.map +1 -1
  157. package/dist/runtime-api/intake/scanner-launcher.d.ts.map +1 -1
  158. package/dist/runtime-api/intake/scanner-launcher.js +0 -15
  159. package/dist/runtime-api/intake/scanner-launcher.js.map +1 -1
  160. package/dist/runtime-api/intake/types.d.ts +0 -55
  161. package/dist/runtime-api/intake/types.d.ts.map +1 -1
  162. package/dist/runtime-api/routes/signals.d.ts +0 -2
  163. package/dist/runtime-api/routes/signals.d.ts.map +1 -1
  164. package/dist/runtime-api/routes/signals.js +1 -5
  165. package/dist/runtime-api/routes/signals.js.map +1 -1
  166. package/dist/runtime-api/routes/signals.schema.d.ts +0 -43
  167. package/dist/runtime-api/routes/signals.schema.d.ts.map +1 -1
  168. package/dist/runtime-api/routes/signals.schema.js +0 -43
  169. package/dist/runtime-api/routes/signals.schema.js.map +1 -1
  170. package/dist/runtime-api/server.d.ts +1 -7
  171. package/dist/runtime-api/server.d.ts.map +1 -1
  172. package/dist/runtime-api/server.js +0 -1
  173. package/dist/runtime-api/server.js.map +1 -1
  174. package/dist/scanners/engine/engine.d.ts +1 -22
  175. package/dist/scanners/engine/engine.d.ts.map +1 -1
  176. package/dist/scanners/engine/engine.js +11 -78
  177. package/dist/scanners/engine/engine.js.map +1 -1
  178. package/dist/scanners/engine/lifecycle.d.ts +1 -7
  179. package/dist/scanners/engine/lifecycle.d.ts.map +1 -1
  180. package/dist/scanners/events.d.ts +0 -4
  181. package/dist/scanners/events.d.ts.map +1 -1
  182. package/dist/scanners/events.js +0 -2
  183. package/dist/scanners/events.js.map +1 -1
  184. package/dist/scanners/external/scaffold/delivery.py +25 -194
  185. package/dist/scanners/external/scaffold/scaffold.py +31 -172
  186. package/dist/scanners/external/scaffold/senpi_mcp.py +8 -150
  187. package/dist/scanners/external-scanner-receiver.d.ts +0 -17
  188. package/dist/scanners/external-scanner-receiver.d.ts.map +1 -1
  189. package/dist/scanners/external-scanner-receiver.js +0 -8
  190. package/dist/scanners/external-scanner-receiver.js.map +1 -1
  191. package/dist/scanners/runtime-module.d.ts +0 -1
  192. package/dist/scanners/runtime-module.d.ts.map +1 -1
  193. package/dist/scanners/runtime-module.js +9 -66
  194. package/dist/scanners/runtime-module.js.map +1 -1
  195. package/dist/telemetry/attributes.d.ts +0 -20
  196. package/dist/telemetry/attributes.d.ts.map +1 -1
  197. package/dist/telemetry/attributes.js +0 -24
  198. package/dist/telemetry/attributes.js.map +1 -1
  199. package/dist/telemetry/event-builders.d.ts +6 -81
  200. package/dist/telemetry/event-builders.d.ts.map +1 -1
  201. package/dist/telemetry/event-builders.js +17 -141
  202. package/dist/telemetry/event-builders.js.map +1 -1
  203. package/dist/telemetry/event-store.d.ts +0 -6
  204. package/dist/telemetry/event-store.d.ts.map +1 -1
  205. package/dist/telemetry/event-store.js +8 -12
  206. package/dist/telemetry/event-store.js.map +1 -1
  207. package/dist/telemetry/metrics.d.ts +2 -14
  208. package/dist/telemetry/metrics.d.ts.map +1 -1
  209. package/dist/telemetry/metrics.js +4 -19
  210. package/dist/telemetry/metrics.js.map +1 -1
  211. package/dist/telemetry/spans/redact-pii.d.ts.map +1 -1
  212. package/dist/telemetry/spans/redact-pii.js +2 -18
  213. package/dist/telemetry/spans/redact-pii.js.map +1 -1
  214. package/dist/telemetry/tracing.d.ts +0 -9
  215. package/dist/telemetry/tracing.d.ts.map +1 -1
  216. package/dist/telemetry/tracing.js +0 -36
  217. package/dist/telemetry/tracing.js.map +1 -1
  218. package/dist/types/dsl/index.d.ts +0 -48
  219. package/dist/types/dsl/index.d.ts.map +1 -1
  220. package/dist/types/scanner.d.ts +0 -15
  221. package/dist/types/scanner.d.ts.map +1 -1
  222. package/dist/utils/event-catalog.d.ts +0 -202
  223. package/dist/utils/event-catalog.d.ts.map +1 -1
  224. package/dist/utils/event-catalog.js +0 -26
  225. package/dist/utils/event-catalog.js.map +1 -1
  226. package/dist/utils/logger.d.ts +1 -4
  227. package/dist/utils/logger.d.ts.map +1 -1
  228. package/dist/utils/logger.js.map +1 -1
  229. package/dist/validate/recipe-checks.d.ts.map +1 -1
  230. package/dist/validate/recipe-checks.js +2 -2
  231. package/dist/validate/recipe-checks.js.map +1 -1
  232. package/openclaw.plugin.json +4 -8
  233. package/package.json +1 -1
  234. package/dist/actions/skipped-signal-results.d.ts +0 -25
  235. package/dist/actions/skipped-signal-results.d.ts.map +0 -1
  236. package/dist/actions/skipped-signal-results.js +0 -71
  237. package/dist/actions/skipped-signal-results.js.map +0 -1
  238. package/dist/runtime-api/intake/ingest-request.d.ts +0 -17
  239. package/dist/runtime-api/intake/ingest-request.d.ts.map +0 -1
  240. package/dist/runtime-api/intake/ingest-request.js +0 -34
  241. package/dist/runtime-api/intake/ingest-request.js.map +0 -1
  242. package/dist/runtime-api/intake/scaffold-tick-router.d.ts +0 -39
  243. package/dist/runtime-api/intake/scaffold-tick-router.d.ts.map +0 -1
  244. package/dist/runtime-api/intake/scaffold-tick-router.js +0 -122
  245. package/dist/runtime-api/intake/scaffold-tick-router.js.map +0 -1
  246. package/dist/scanners/external/scaffold/tick_facts.py +0 -130
  247. package/dist/scanners/external/scaffold/ulid.py +0 -58
  248. package/dist/telemetry/dsl-positions.d.ts +0 -111
  249. package/dist/telemetry/dsl-positions.d.ts.map +0 -1
  250. package/dist/telemetry/dsl-positions.js +0 -118
  251. package/dist/telemetry/dsl-positions.js.map +0 -1
  252. package/dist/telemetry/live-telemetry.d.ts +0 -257
  253. package/dist/telemetry/live-telemetry.d.ts.map +0 -1
  254. package/dist/telemetry/live-telemetry.js +0 -959
  255. package/dist/telemetry/live-telemetry.js.map +0 -1
  256. package/dist/telemetry/scanner-stats.d.ts +0 -143
  257. package/dist/telemetry/scanner-stats.d.ts.map +0 -1
  258. package/dist/telemetry/scanner-stats.js +0 -426
  259. package/dist/telemetry/scanner-stats.js.map +0 -1
  260. package/dist/telemetry/scanner-tick-feed.d.ts +0 -87
  261. package/dist/telemetry/scanner-tick-feed.d.ts.map +0 -1
  262. package/dist/telemetry/scanner-tick-feed.js +0 -48
  263. package/dist/telemetry/scanner-tick-feed.js.map +0 -1
  264. package/dist/telemetry/strategy-topology.d.ts +0 -99
  265. package/dist/telemetry/strategy-topology.d.ts.map +0 -1
  266. package/dist/telemetry/strategy-topology.js +0 -93
  267. package/dist/telemetry/strategy-topology.js.map +0 -1
  268. package/dist/telemetry/telemetry-publisher.d.ts +0 -83
  269. package/dist/telemetry/telemetry-publisher.d.ts.map +0 -1
  270. package/dist/telemetry/telemetry-publisher.js +0 -256
  271. package/dist/telemetry/telemetry-publisher.js.map +0 -1
  272. package/dist/telemetry/tick-frame.d.ts +0 -212
  273. package/dist/telemetry/tick-frame.d.ts.map +0 -1
  274. package/dist/telemetry/tick-frame.js +0 -421
  275. package/dist/telemetry/tick-frame.js.map +0 -1
  276. package/dist/telemetry/timeline-buffer.d.ts +0 -95
  277. package/dist/telemetry/timeline-buffer.d.ts.map +0 -1
  278. package/dist/telemetry/timeline-buffer.js +0 -237
  279. package/dist/telemetry/timeline-buffer.js.map +0 -1
  280. package/dist/utils/telemetry-required-log.d.ts +0 -60
  281. package/dist/utils/telemetry-required-log.d.ts.map +0 -1
  282. package/dist/utils/telemetry-required-log.js +0 -105
  283. package/dist/utils/telemetry-required-log.js.map +0 -1
  284. package/dist/utils/ulid.d.ts +0 -9
  285. package/dist/utils/ulid.d.ts.map +0 -1
  286. package/dist/utils/ulid.js +0 -43
  287. package/dist/utils/ulid.js.map +0 -1
@@ -2,10 +2,8 @@
2
2
  * Pure builders for the DSL exit-engine's failure-state events — degradation the monitor tracks but
3
3
  * that previously surfaced only as a tick-span error or a `warn` log: an exchange SL push that threw
4
4
  * ({@link buildSlSyncFailedEvent}), a position with no price past the stale threshold
5
- * ({@link buildPriceFetchStaleEvent}), a Phase-2 backend handoff that degraded
6
- * ({@link buildHandoffFailedEvent}), and the widest of them — a monitor tick that aborted before it
7
- * reached a single position ({@link buildTickAbortedEvent}) and the tick that ends the outage
8
- * ({@link buildTickRecoveredEvent}).
5
+ * ({@link buildPriceFetchStaleEvent}), and a Phase-2 backend handoff that degraded
6
+ * ({@link buildHandoffFailedEvent}).
9
7
  *
10
8
  * Pure `(input) => EmittableEvent`; the monitor emits the result through `emitEvent`'s guard, so a
11
9
  * throwing build or a telemetry failure can never disturb a tick. A thrown venue/backend error rides
@@ -15,13 +13,12 @@
15
13
  * events, so it is not passed here.
16
14
  */
17
15
  import { EVENT_NAME, eventAttrs } from "../../utils/event-catalog.js";
18
- /** The id/asset/dex and tick attributes every DSL failure event carries. */
16
+ /** The id/asset/dex attributes every DSL failure event carries. */
19
17
  function baseAttrs(ctx) {
20
18
  return {
21
19
  "senpi.asset": ctx.asset,
22
20
  "senpi.dex": ctx.dex || undefined,
23
21
  "senpi.position.id": ctx.positionId,
24
- "senpi.tick.id": ctx.tickId,
25
22
  };
26
23
  }
27
24
  /** An exchange SL create/update (`editPosition`) threw — the stop the venue never received. */
@@ -73,50 +70,4 @@ export function buildHandoffFailedEvent(ctx, opts) {
73
70
  ...(opts.error !== undefined ? { error: opts.error } : {}),
74
71
  };
75
72
  }
76
- /** How the body phrases the age, including the case where there is no age to phrase. */
77
- function ageText(ageMs) {
78
- return ageMs == null ? "no tick has completed yet" : `last completed tick ${ageMs}ms ago`;
79
- }
80
- /**
81
- * A monitor tick that aborted at the clearinghouse gate — no position under this monitor was
82
- * evaluated, so no breach, no time cut and no stop sync ran for any of them. The per-position
83
- * staleness counters live past this gate and never advance, which is why this event has to exist:
84
- * `dsl.price_fetch_stale` cannot fire for this failure mode.
85
- *
86
- * The caller latches it, so a sustained outage costs one record rather than one per tick.
87
- */
88
- export function buildTickAbortedEvent(input) {
89
- return {
90
- name: EVENT_NAME.dslTickAborted,
91
- level: "warn",
92
- body: `DSL monitor tick aborted (${input.reason}); ` +
93
- `${input.unevaluatedPositionCount} position(s) unevaluated, ${ageText(input.lastCompletedTickAgeMs)}`,
94
- attributes: eventAttrs({
95
- "senpi.tick.id": input.tickId,
96
- "senpi.dsl.tick_abort_reason": input.reason,
97
- "senpi.dsl.last_completed_tick_age_ms": input.lastCompletedTickAgeMs,
98
- "senpi.dsl.unavailable_address_count": input.unavailableAddressCount,
99
- "senpi.dsl.unevaluated_position_count": input.unevaluatedPositionCount,
100
- }),
101
- ...(input.error !== undefined ? { error: input.error } : {}),
102
- };
103
- }
104
- /**
105
- * The tick that ends an abort outage. Emitted once, on the first tick to complete after one or more
106
- * aborted ones, so a reader told "not protected" is told when that stops being true. Its age field
107
- * is measured before the recovering tick stamps its own completion, so it is the length of the gap.
108
- */
109
- export function buildTickRecoveredEvent(input) {
110
- return {
111
- name: EVENT_NAME.dslTickRecovered,
112
- level: "info",
113
- body: `DSL monitor tick completed after ${input.abortedTickCount} aborted tick(s); ` +
114
- ageText(input.lastCompletedTickAgeMs),
115
- attributes: eventAttrs({
116
- "senpi.tick.id": input.tickId,
117
- "senpi.dsl.last_completed_tick_age_ms": input.lastCompletedTickAgeMs,
118
- "senpi.dsl.aborted_tick_count": input.abortedTickCount,
119
- }),
120
- };
121
- }
122
73
  //# sourceMappingURL=dsl-failure-events.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dsl-failure-events.js","sourceRoot":"","sources":["../../../src/dsl/monitor/dsl-failure-events.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dsl-failure-events.js","sourceRoot":"","sources":["../../../src/dsl/monitor/dsl-failure-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAiB,MAAM,8BAA8B,CAAC;AAerF,mEAAmE;AACnE,SAAS,SAAS,CAAC,GAAsB;IAKvC,OAAO;QACL,aAAa,EAAE,GAAG,CAAC,KAAK;QACxB,WAAW,EAAE,GAAG,CAAC,GAAG,IAAI,SAAS;QACjC,mBAAmB,EAAE,GAAG,CAAC,UAAU;KACpC,CAAC;AACJ,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,sBAAsB,CACpC,GAAsB,EACtB,YAAoB,EACpB,KAAc;IAEd,OAAO;QACL,IAAI,EAAE,UAAU,CAAC,eAAe;QAChC,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,+BAA+B,GAAG,CAAC,KAAK,KAAK,YAAY,eAAe;QAC9E,UAAU,EAAE,UAAU,CAA8C;YAClE,GAAG,SAAS,CAAC,GAAG,CAAC;YACjB,iCAAiC,EAAE,YAAY;SAChD,CAAC;QACF,KAAK;KACN,CAAC;AACJ,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,yBAAyB,CACvC,GAAsB,EACtB,YAAoB;IAEpB,OAAO;QACL,IAAI,EAAE,UAAU,CAAC,kBAAkB;QACnC,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,sCAAsC,GAAG,CAAC,KAAK,KAAK,YAAY,eAAe;QACrF,UAAU,EAAE,UAAU,CAAiD;YACrE,GAAG,SAAS,CAAC,GAAG,CAAC;YACjB,+BAA+B,EAAE,YAAY;SAC9C,CAAC;KACH,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACrC,GAAsB,EACtB,IAKC;IAED,MAAM,IAAI,GACR,IAAI,CAAC,OAAO,KAAK,UAAU;QACzB,CAAC,CAAC,4BAA4B,GAAG,CAAC,KAAK,8BAA8B;QACrE,CAAC,CAAC,IAAI,CAAC,OAAO,KAAK,MAAM;YACvB,CAAC,CAAC,mCAAmC,GAAG,CAAC,KAAK,EAAE;YAChD,CAAC,CAAC,2CAA2C,GAAG,CAAC,KAAK,oBAAoB,CAAC;IACjF,OAAO;QACL,IAAI,EAAE,UAAU,CAAC,gBAAgB;QACjC,KAAK,EAAE,MAAM;QACb,IAAI;QACJ,UAAU,EAAE,UAAU,CAA+C;YACnE,GAAG,SAAS,CAAC,GAAG,CAAC;YACjB,2BAA2B,EAAE,IAAI,CAAC,OAAO;YACzC,+BAA+B,EAAE,IAAI,CAAC,iBAAiB;SACxD,CAAC;QACF,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3D,CAAC;AACJ,CAAC"}
@@ -17,7 +17,6 @@ export declare function closeReasonContext(closeReason: string, s: DslState): {
17
17
  closePeakRoe?: number;
18
18
  };
19
19
  export interface MonitorProcessContext {
20
- /** The id for this tick — a ULID, one per `runTick`, on its log lines, events and spans. */
21
20
  tickId: string;
22
21
  ts: string;
23
22
  now: () => string;
@@ -1 +1 @@
1
- {"version":3,"file":"process-one-position.d.ts","sourceRoot":"","sources":["../../../src/dsl/monitor/process-one-position.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAkB,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAsBzD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAiB/C;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,CAAC,EAAE,QAAQ,GACV;IAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAYvD;AAuGD,MAAM,WAAW,qBAAqB;IACpC,4FAA4F;IAC5F,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC3C,GAAG,EAAE,aAAa,CAAC;IACnB,uBAAuB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACnD,6DAA6D;IAC7D,cAAc,CAAC,EAAE,OAAO,sBAAsB,EAAE,cAAc,CAAC;IAC/D,oDAAoD;IACpD,wBAAwB,CAAC,EAAE,OAAO,sBAAsB,EAAE,wBAAwB,CAAC;CACpF;AAgFD,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,qBAAqB,EAC1B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,QAAQ,EACf,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,IAAI,EAAE,IAAI,GACT,OAAO,CAAC,IAAI,CAAC,CAs1Bf"}
1
+ {"version":3,"file":"process-one-position.d.ts","sourceRoot":"","sources":["../../../src/dsl/monitor/process-one-position.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAqBzD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAgB/C;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,CAAC,EAAE,QAAQ,GACV;IAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAYvD;AAkFD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC3C,GAAG,EAAE,aAAa,CAAC;IACnB,uBAAuB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACnD,6DAA6D;IAC7D,cAAc,CAAC,EAAE,OAAO,sBAAsB,EAAE,cAAc,CAAC;IAC/D,oDAAoD;IACpD,wBAAwB,CAAC,EAAE,OAAO,sBAAsB,EAAE,wBAAwB,CAAC;CACpF;AAiCD,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,qBAAqB,EAC1B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,QAAQ,EACf,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,IAAI,EAAE,IAAI,GACT,OAAO,CAAC,IAAI,CAAC,CAozBf"}
@@ -2,7 +2,7 @@
2
2
  * Per-position work for one monitor tick: SL fill check, pending close, dslTick, exchange sync.
3
3
  */
4
4
  import { dslTick, exchangeStopLossTriggerPx } from "../engine/index.js";
5
- import { CLOSE_REASON, MAX_CONSECUTIVE_CLOSE_FAILURES, DSL_EXTERNAL_RETRIES, DSL_EXTERNAL_RETRY_DELAY_MS, DSL_HANDOFF_SL_STATUS_TIMEOUT_MS, DSL_EVENTS, EVENTS, DSL_PRICE_FETCH_FAILURE_WARN_THRESHOLD, DSL_HEARTBEAT_FIRST_HOUR_MS, DSL_HEARTBEAT_INTERVAL_MS, DSL_HEARTBEAT_TIER_SUPPRESS_MS, DSL_VENUE_STATUS_MAX_LENGTH, } from "../../constants/dsl/index.js";
5
+ import { CLOSE_REASON, MAX_CONSECUTIVE_CLOSE_FAILURES, DSL_EXTERNAL_RETRIES, DSL_EXTERNAL_RETRY_DELAY_MS, DSL_HANDOFF_SL_STATUS_TIMEOUT_MS, DSL_EVENTS, EVENTS, DSL_PRICE_FETCH_FAILURE_WARN_THRESHOLD, DSL_HEARTBEAT_FIRST_HOUR_MS, DSL_HEARTBEAT_INTERVAL_MS, DSL_HEARTBEAT_TIER_SUPPRESS_MS, } from "../../constants/dsl/index.js";
6
6
  import { logger } from "../../utils/logger/dsl.js";
7
7
  import { withRetry } from "../../utils/retry.js";
8
8
  import { isRetriableMcpError } from "../../senpi/client.js";
@@ -16,7 +16,6 @@ import { mapBackendEventToBusEvent } from "../engine-client/event-mapping.js";
16
16
  import { buildDslClosedEventFromState } from "../events/build-closed-event.js";
17
17
  import { parseCloseFillDetail } from "../../senpi/client.js";
18
18
  import { emitEvent } from "../../actions/event-derivation.js";
19
- import { PAYLOAD_KEY } from "../../utils/event-catalog.js";
20
19
  import { buildSlSyncFailedEvent, buildPriceFetchStaleEvent, buildHandoffFailedEvent, } from "./dsl-failure-events.js";
21
20
  /**
22
21
  * Structured close-reason context forwarded with a DSL-cut close (notifications 2.3):
@@ -78,35 +77,23 @@ async function setIfStillActive(stateManager, key, address, asset, buildNext, ct
78
77
  });
79
78
  }
80
79
  /**
81
- * Telemetry stamps every emit out of the monitor carries: the cross-flow position.id, the tick that
82
- * produced the emit, and — on the `dsl.*` events, whose consumers read it — who moved the stop.
83
- * Data-only; no consumer branches on these.
80
+ * Telemetry stamps for a flat POSITION_CLOSED emit: the cross-flow position.id plus the
81
+ * closing-order fill detail when a close response (or SL order id) is available. Data-only —
82
+ * no consumer branches on these; the venue `orderId` is the fills-ledger join key for
83
+ * post-hoc lifecycle correlation.
84
84
  */
85
- function emitStamps(state, tickId, source) {
85
+ function closedEmitStamps(state, fill = {}) {
86
86
  return {
87
87
  __positionId: state.positionId ?? state.correlationId,
88
- [PAYLOAD_KEY.tickId]: tickId,
89
- ...(source !== undefined ? { __dslSource: source } : {}),
90
- };
91
- }
92
- /**
93
- * Stamps for a flat POSITION_CLOSED emit: {@link emitStamps} plus the closing-order fill detail when
94
- * a close response (or SL order id) is available. The venue `orderId` is the fills-ledger join key
95
- * for post-hoc lifecycle correlation. No source: the lifecycle record has no field for it.
96
- */
97
- function closedEmitStamps(state, tickId, fill = {}) {
98
- return {
99
- ...emitStamps(state, tickId),
100
88
  ...fill,
101
89
  };
102
90
  }
103
91
  /** The position identity a DSL failure event pins onto its record. */
104
- function failureContext(state, tickId) {
92
+ function failureContext(state) {
105
93
  return {
106
94
  asset: state.asset,
107
95
  dex: state.dex || undefined,
108
96
  positionId: state.positionId ?? state.correlationId,
109
- tickId,
110
97
  };
111
98
  }
112
99
  /**
@@ -139,40 +126,6 @@ function isGoneVenueSlStatus(status) {
139
126
  const s = status.trim().toLowerCase();
140
127
  return GONE_VENUE_SL_STATUSES.has(s) || s.endsWith("rejected");
141
128
  }
142
- /**
143
- * The venue's answer about the stop order, in the shape the state persists it.
144
- *
145
- * `undefined` whenever the venue named no status — a failed lookup, an unreadable response, or a
146
- * response with no status field. Those are not answers, so they write nothing: an absent
147
- * `lastVenueStatus` has to keep meaning "the venue has not told us", which is precisely what a
148
- * reader needs to tell a confirmed stop from a believed one. Nothing is defaulted or synthesised
149
- * for them.
150
- *
151
- * The status is stored verbatim (only length-capped), because the branching above already ignores
152
- * everything outside the known-dead set — the unrecognised answer is the one worth keeping.
153
- */
154
- function venueStatusStamp(status) {
155
- const raw = status?.status;
156
- if (raw == null)
157
- return undefined;
158
- return { lastVenueStatus: raw.slice(0, DSL_VENUE_STATUS_MAX_LENGTH), lastVenueStatusAt: Date.now() };
159
- }
160
- /**
161
- * The venue's answer about the BACKEND ratchet's `activeSLOrderId`, in the shape the state persists.
162
- *
163
- * A different order from the position's own `slOrderId`, so a different pair of fields: the handoff
164
- * asks about the stop the backend placed, and recording that answer as the position's own would
165
- * claim a confirmation the venue never gave for it.
166
- */
167
- function backendSlStatusStamp(status) {
168
- const raw = status?.status;
169
- if (raw == null)
170
- return undefined;
171
- return {
172
- backendSlVenueStatus: raw.slice(0, DSL_VENUE_STATUS_MAX_LENGTH),
173
- backendSlVenueStatusAt: Date.now(),
174
- };
175
- }
176
129
  export async function processOnePosition(ctx, key, state, price, span) {
177
130
  const { tickId, ts, now: isoNow, stateManager, strategyStates, bus, isSlPlacementInProgress = () => false } = ctx;
178
131
  const strategy = strategyStates.get(state.address);
@@ -208,9 +161,6 @@ export async function processOnePosition(ctx, key, state, price, span) {
208
161
  label: "getOrderStatus (SL-hit check)",
209
162
  onRetry: (attempt, remaining, err) => logger.warn("[dsl] getOrderStatus retry", { asset: state.asset, attempt, remaining, err }),
210
163
  }));
211
- // The venue has answered. Every branch below keeps that answer; only a throw or a
212
- // status-less response leaves the fields absent.
213
- const venueStamp = venueStatusStamp(status);
214
164
  if (status?.filled) {
215
165
  span.addEvent("external_close_detected", { source: "sl_order" });
216
166
  span.setAttribute("senpi.dsl.close_reason", CLOSE_REASON.EXCHANGE_SL_HIT);
@@ -220,13 +170,7 @@ export async function processOnePosition(ctx, key, state, price, span) {
220
170
  slOrderId: state.slOrderId,
221
171
  address: state.address,
222
172
  });
223
- const closedState = {
224
- ...state,
225
- ...venueStamp,
226
- active: false,
227
- closedAt: ts,
228
- closeReason: CLOSE_REASON.EXCHANGE_SL_HIT,
229
- };
173
+ const closedState = { ...state, active: false, closedAt: ts, closeReason: CLOSE_REASON.EXCHANGE_SL_HIT };
230
174
  const archived = await archiveIfStillActive(stateManager, key, state.address, state.asset, effectiveDex(state), () => closedState, { tickId, skipMessage: "[dsl] skip SL-hit archive: state already cleared (concurrent close)" });
231
175
  if (!archived)
232
176
  return;
@@ -237,15 +181,13 @@ export async function processOnePosition(ctx, key, state, price, span) {
237
181
  reason: CLOSE_REASON.EXCHANGE_SL_HIT,
238
182
  closeReason: CLOSE_REASON.EXCHANGE_SL_HIT,
239
183
  // The closing order IS the exchange SL order — its id joins the closing fill.
240
- ...closedEmitStamps(state, tickId, state.slOrderId != null ? { orderId: String(state.slOrderId) } : {}),
184
+ ...closedEmitStamps(state, state.slOrderId != null ? { orderId: String(state.slOrderId) } : {}),
241
185
  timestamp: ts,
242
186
  });
243
187
  bus.emit(DSL_EVENTS.CLOSED, buildDslClosedEventFromState(closedState, {
244
188
  reason: CLOSE_REASON.EXCHANGE_SL_HIT,
245
189
  closeReason: CLOSE_REASON.EXCHANGE_SL_HIT,
246
190
  timestamp: ts,
247
- tickId,
248
- source: "runtime",
249
191
  }));
250
192
  return;
251
193
  }
@@ -266,17 +208,8 @@ export async function processOnePosition(ctx, key, state, price, span) {
266
208
  phase: state.phase,
267
209
  });
268
210
  recordDslDegradation({ failure: "sl_gone" });
269
- await setIfStillActive(stateManager, key, state.address, state.asset, (current) => ({ ...current, ...venueStamp, slOrderId: null, lastSyncedFloorPrice: null }), { tickId, skipMessage: "[dsl] skip gone-SL clear: state already cleared (concurrent close)" });
270
- state = { ...state, ...venueStamp, slOrderId: null, lastSyncedFloorPrice: null };
271
- }
272
- else if (venueStamp) {
273
- // The stop is neither filled nor in the known-dead set, so the branching above changes
274
- // nothing — but the answer itself is the evidence, and it is the only thing that separates
275
- // "a stop IS resting" from "we believe one is". Persisted here rather than left to the
276
- // tick's own write, because the paths that return before it (no price, pendingClose error)
277
- // merge onto the re-read state and would drop a stamp held only in this local copy.
278
- await setIfStillActive(stateManager, key, state.address, state.asset, (current) => ({ ...current, ...venueStamp }), { tickId, skipMessage: "[dsl] skip venue-status stamp: state already cleared (concurrent close)" });
279
- state = { ...state, ...venueStamp };
211
+ await setIfStillActive(stateManager, key, state.address, state.asset, (current) => ({ ...current, slOrderId: null, lastSyncedFloorPrice: null }), { tickId, skipMessage: "[dsl] skip gone-SL clear: state already cleared (concurrent close)" });
212
+ state = { ...state, slOrderId: null, lastSyncedFloorPrice: null };
280
213
  }
281
214
  }
282
215
  catch (e) {
@@ -329,15 +262,13 @@ export async function processOnePosition(ctx, key, state, price, span) {
329
262
  wallet: state.wallet,
330
263
  reason: closeReasonToUse,
331
264
  closeReason: closeReasonToUse,
332
- ...closedEmitStamps(state, tickId, closeFill),
265
+ ...closedEmitStamps(state, closeFill),
333
266
  timestamp: ts,
334
267
  });
335
268
  bus.emit(DSL_EVENTS.CLOSED, buildDslClosedEventFromState(closedState, {
336
269
  reason: closeReasonToUse,
337
270
  closeReason: closeReasonToUse,
338
271
  timestamp: ts,
339
- tickId,
340
- source: "runtime",
341
272
  }));
342
273
  }
343
274
  catch (e) {
@@ -356,15 +287,13 @@ export async function processOnePosition(ctx, key, state, price, span) {
356
287
  wallet: state.wallet,
357
288
  reason: "error",
358
289
  closeReason: CLOSE_REASON.CLOSE_POSITION_FAILED,
359
- ...closedEmitStamps(state, tickId),
290
+ ...closedEmitStamps(state),
360
291
  timestamp: isoNow(),
361
292
  });
362
293
  bus.emit(DSL_EVENTS.CLOSED, buildDslClosedEventFromState(failedCloseState, {
363
294
  reason: "error",
364
295
  closeReason: CLOSE_REASON.CLOSE_POSITION_FAILED,
365
296
  timestamp: isoNow(),
366
- tickId,
367
- source: "runtime",
368
297
  }));
369
298
  }
370
299
  else {
@@ -374,7 +303,7 @@ export async function processOnePosition(ctx, key, state, price, span) {
374
303
  asset: state.asset,
375
304
  attempt: next.consecutiveCloseFailures,
376
305
  triggerReason: state.triggerReason,
377
- ...emitStamps(state, tickId, "runtime"),
306
+ __positionId: state.positionId ?? state.correlationId,
378
307
  timestamp: isoNow(),
379
308
  });
380
309
  }
@@ -399,7 +328,7 @@ export async function processOnePosition(ctx, key, state, price, span) {
399
328
  ...(shouldEmitStale ? { priceFetchStaleEmitted: true } : {}),
400
329
  }), { tickId, skipMessage: "[dsl] skip no-price counter write: state already cleared (concurrent close)" });
401
330
  if (shouldEmitStale) {
402
- emitEvent(logger, () => buildPriceFetchStaleEvent(failureContext(state, tickId), next.consecutiveFetchFailures));
331
+ emitEvent(logger, () => buildPriceFetchStaleEvent(failureContext(state), next.consecutiveFetchFailures));
403
332
  recordDslDegradation({ failure: "price_stale" });
404
333
  }
405
334
  logger.info("[dsl] monitor no price for position, skipping dslTick", {
@@ -569,15 +498,13 @@ export async function processOnePosition(ctx, key, state, price, span) {
569
498
  wallet: state.wallet,
570
499
  reason: "error",
571
500
  closeReason: CLOSE_REASON.CLOSE_POSITION_FAILED,
572
- ...closedEmitStamps(state, tickId),
501
+ ...closedEmitStamps(state),
573
502
  timestamp: isoNow(),
574
503
  });
575
504
  bus.emit(DSL_EVENTS.CLOSED, buildDslClosedEventFromState(failedCloseState, {
576
505
  reason: "error",
577
506
  closeReason: CLOSE_REASON.CLOSE_POSITION_FAILED,
578
507
  timestamp: isoNow(),
579
- tickId,
580
- source: "runtime",
581
508
  }));
582
509
  }
583
510
  else {
@@ -587,7 +514,7 @@ export async function processOnePosition(ctx, key, state, price, span) {
587
514
  asset: state.asset,
588
515
  attempt: pending.consecutiveCloseFailures,
589
516
  triggerReason: state.triggerReason,
590
- ...emitStamps(state, tickId, "runtime"),
517
+ __positionId: state.positionId ?? state.correlationId,
591
518
  timestamp: isoNow(),
592
519
  });
593
520
  }
@@ -609,15 +536,13 @@ export async function processOnePosition(ctx, key, state, price, span) {
609
536
  wallet: state.wallet,
610
537
  reason: closeReasonToUse,
611
538
  closeReason: closeReasonToUse,
612
- ...closedEmitStamps(state, tickId, closeFill),
539
+ ...closedEmitStamps(state, closeFill),
613
540
  timestamp: ts,
614
541
  });
615
542
  bus.emit(DSL_EVENTS.CLOSED, buildDslClosedEventFromState(closedState, {
616
543
  reason: closeReasonToUse,
617
544
  closeReason: closeReasonToUse,
618
545
  timestamp: ts,
619
- tickId,
620
- source: "runtime",
621
546
  }));
622
547
  return;
623
548
  }
@@ -637,7 +562,7 @@ export async function processOnePosition(ctx, key, state, price, span) {
637
562
  triggerPct: tier.triggerPct,
638
563
  newFloorPrice: dslEffectiveFloor,
639
564
  triggerReason: next.triggerReason,
640
- ...emitStamps(next, tickId, "runtime"),
565
+ __positionId: next.positionId ?? next.correlationId,
641
566
  timestamp: ts,
642
567
  direction: next.direction,
643
568
  entryPrice: next.entryPrice,
@@ -667,7 +592,7 @@ export async function processOnePosition(ctx, key, state, price, span) {
667
592
  phase: result.newPhase ?? 2,
668
593
  tierIndex: result.newTierIndex ?? 0,
669
594
  triggerReason: next.triggerReason,
670
- ...emitStamps(next, tickId, "runtime"),
595
+ __positionId: next.positionId ?? next.correlationId,
671
596
  timestamp: ts,
672
597
  });
673
598
  }
@@ -781,7 +706,7 @@ export async function processOnePosition(ctx, key, state, price, span) {
781
706
  newSLPrice: exchangeTriggerPx,
782
707
  slOrderId: synced.slOrderId ?? 0,
783
708
  triggerReason: synced.triggerReason,
784
- ...emitStamps(synced, tickId, "runtime"),
709
+ __positionId: synced.positionId ?? synced.correlationId,
785
710
  direction: synced.direction,
786
711
  // Stop-raise copy inputs: position leverage, the high-water price behind
787
712
  // the raise ("new high …"), and entry price (leverage + entry → the
@@ -807,7 +732,7 @@ export async function processOnePosition(ctx, key, state, price, span) {
807
732
  }, { tickId, skipMessage: "[dsl] skip SL sync-failure write: state no longer active (concurrent close)" });
808
733
  if (syncFailureCount == null)
809
734
  return;
810
- emitEvent(logger, () => buildSlSyncFailedEvent(failureContext(state, tickId), syncFailureCount ?? 0, e));
735
+ emitEvent(logger, () => buildSlSyncFailedEvent(failureContext(state), syncFailureCount ?? 0, e));
811
736
  recordDslDegradation({ failure: "sl_sync", errorType: errorTypeOf(e) });
812
737
  }
813
738
  }
@@ -840,7 +765,7 @@ export async function processOnePosition(ctx, key, state, price, span) {
840
765
  currentTierIndex: hbState.currentTierIndex,
841
766
  elapsedMinutes: hbState.elapsedMinutes,
842
767
  triggerReason: hbState.triggerReason,
843
- ...emitStamps(hbState, tickId, "runtime"),
768
+ __positionId: hbState.positionId ?? hbState.correlationId,
844
769
  margin: hbState.leverage > 0
845
770
  ? (hbState.size * hbState.entryPrice) / hbState.leverage
846
771
  : 0,
@@ -883,17 +808,15 @@ const LIVE_VENUE_SL_STATUSES = new Set(["open", "triggered"]);
883
808
  async function backendHasLiveSl(pos, strategy, tickId, asset) {
884
809
  const slOrderId = parseSlOrderId(pos.activeSLOrderId);
885
810
  if (slOrderId == null)
886
- return { live: false };
811
+ return false;
887
812
  try {
888
813
  const status = await withRetry(() => strategy.getOrderStatus(slOrderId, { timeoutMs: DSL_HANDOFF_SL_STATUS_TIMEOUT_MS }), {
889
814
  retries: DSL_EXTERNAL_RETRIES,
890
815
  delayMs: DSL_EXTERNAL_RETRY_DELAY_MS,
891
816
  label: "getOrderStatus (handoff live-SL check)",
892
817
  });
893
- const stamp = backendSlStatusStamp(status);
894
- if (status?.status != null && LIVE_VENUE_SL_STATUSES.has(status.status)) {
895
- return { live: true, ...(stamp === undefined ? {} : { stamp }) };
896
- }
818
+ if (status?.status != null && LIVE_VENUE_SL_STATUSES.has(status.status))
819
+ return true;
897
820
  logger.warn("[dsl] backend ratchet names an exchange SL that is not resting on the venue", {
898
821
  tickId,
899
822
  asset,
@@ -901,7 +824,7 @@ async function backendHasLiveSl(pos, strategy, tickId, asset) {
901
824
  slOrderId,
902
825
  venueStatus: status?.status ?? null,
903
826
  });
904
- return { live: false, ...(stamp === undefined ? {} : { stamp }) };
827
+ return false;
905
828
  }
906
829
  catch (e) {
907
830
  logger.warn("[dsl] could not read the backend ratchet's exchange SL status; treating it as not live", {
@@ -911,36 +834,7 @@ async function backendHasLiveSl(pos, strategy, tickId, asset) {
911
834
  slOrderId,
912
835
  err: e,
913
836
  });
914
- return { live: false };
915
- }
916
- }
917
- /**
918
- * Persist the venue's answer about the backend's stop on a path that writes nothing else.
919
- *
920
- * That path is the one worth recording: the checks above leave the handoff at `"pending"` and
921
- * return, so without this the reason it is stuck exists only in a warn line. A stamp held in a local
922
- * copy would be dropped by the next write, which merges onto the re-read state, so it is written
923
- * under the key lock like every other field.
924
- *
925
- * No stamp means the venue named no status — a failed lookup, or a ratchet with no order id to ask
926
- * about. Nothing is written for those: an absent field has to keep meaning "the venue has not told
927
- * us".
928
- */
929
- async function recordBackendSlStatus(ctx, key, state, stamp) {
930
- if (stamp === undefined)
931
- return;
932
- try {
933
- await setIfStillActive(ctx.stateManager, key, state.address, state.asset, (current) => ({ ...current, ...stamp }), { tickId: ctx.tickId, skipMessage: "[dsl] skip backend SL status stamp: state already cleared (concurrent close)" });
934
- Object.assign(state, stamp);
935
- }
936
- catch (e) {
937
- // One caller sits inside the pre-check's try, whose catch falls through to sending an add. A
938
- // failed write of an observability field must not be the reason a second ratchet is registered.
939
- logger.warn("[dsl] could not persist the backend SL venue status", {
940
- tickId: ctx.tickId,
941
- asset: state.asset,
942
- err: e,
943
- });
837
+ return false;
944
838
  }
945
839
  }
946
840
  async function attemptHandoffRegistration(ctx, key, next, _original, strategy) {
@@ -957,10 +851,8 @@ async function attemptHandoffRegistration(ctx, key, next, _original, strategy) {
957
851
  const active = existing.filter((p) => !BACKEND_TERMINAL_STATUSES.has(p.status));
958
852
  if (active.length > 0) {
959
853
  const adopted = active[0];
960
- const adoptedSlCheck = await backendHasLiveSl(adopted, strategy, tickId, next.asset);
961
- if (!adoptedSlCheck.live) {
854
+ if (!(await backendHasLiveSl(adopted, strategy, tickId, next.asset))) {
962
855
  logger.warn("[dsl] pre-check found backend ratchet without an exchange SL; staying pending so the runtime keeps managing the SL", { tickId, asset: next.asset, adoptedId: adopted.id, status: adopted.status });
963
- await recordBackendSlStatus(ctx, key, next, adoptedSlCheck.stamp);
964
856
  return;
965
857
  }
966
858
  logger.info("[dsl] pre-check found existing backend ratchet, adopting instead of re-adding", {
@@ -979,7 +871,6 @@ async function attemptHandoffRegistration(ctx, key, next, _original, strategy) {
979
871
  const adoptedSl = mapEnginePositionToStateFields(adopted);
980
872
  const updated = {
981
873
  ...next,
982
- ...adoptedSlCheck.stamp,
983
874
  slOrderId: adoptedSl.slOrderId,
984
875
  lastSyncedFloorPrice: adoptedSl.lastSyncedFloorPrice,
985
876
  handoffStatus: "ok",
@@ -1031,8 +922,7 @@ async function attemptHandoffRegistration(ctx, key, next, _original, strategy) {
1031
922
  Object.assign(next, aborted);
1032
923
  return;
1033
924
  }
1034
- const registeredSlCheck = await backendHasLiveSl(result.position, strategy, tickId, next.asset);
1035
- if (!registeredSlCheck.live) {
925
+ if (!(await backendHasLiveSl(result.position, strategy, tickId, next.asset))) {
1036
926
  logger.warn("[dsl] backend created the position but has not placed an exchange SL; staying pending so the runtime keeps managing the SL", {
1037
927
  tickId,
1038
928
  asset: next.asset,
@@ -1040,14 +930,12 @@ async function attemptHandoffRegistration(ctx, key, next, _original, strategy) {
1040
930
  status: result.position.status,
1041
931
  rawResult: JSON.stringify(result).slice(0, 1000),
1042
932
  });
1043
- await recordBackendSlStatus(ctx, key, next, registeredSlCheck.stamp);
1044
933
  return;
1045
934
  }
1046
935
  // Mirror the backend's stop on the registration tick itself — see the adopt site above.
1047
936
  const registeredSl = mapEnginePositionToStateFields(result.position);
1048
937
  const updated = {
1049
938
  ...next,
1050
- ...registeredSlCheck.stamp,
1051
939
  slOrderId: registeredSl.slOrderId,
1052
940
  lastSyncedFloorPrice: registeredSl.lastSyncedFloorPrice,
1053
941
  handoffStatus: "ok",
@@ -1064,7 +952,7 @@ async function attemptHandoffRegistration(ctx, key, next, _original, strategy) {
1064
952
  });
1065
953
  }
1066
954
  else {
1067
- emitEvent(logger, () => buildHandoffFailedEvent(failureContext(next, tickId), {
955
+ emitEvent(logger, () => buildHandoffFailedEvent(failureContext(next), {
1068
956
  failure: "register",
1069
957
  redact: { result: JSON.stringify(result).slice(0, 800) },
1070
958
  }));
@@ -1072,7 +960,7 @@ async function attemptHandoffRegistration(ctx, key, next, _original, strategy) {
1072
960
  }
1073
961
  }
1074
962
  catch (e) {
1075
- emitEvent(logger, () => buildHandoffFailedEvent(failureContext(next, tickId), { failure: "register", error: e }));
963
+ emitEvent(logger, () => buildHandoffFailedEvent(failureContext(next), { failure: "register", error: e }));
1076
964
  recordDslDegradation({ failure: "handoff", handoffFailure: "register", errorType: errorTypeOf(e) });
1077
965
  }
1078
966
  }
@@ -1095,7 +983,7 @@ async function handleHandoffOk(ctx, key, next, original, strategy, span) {
1095
983
  ? positions.filter((p) => !BACKEND_TERMINAL_STATUSES.has(p.status))[0]
1096
984
  : null;
1097
985
  if (!backendPos) {
1098
- emitEvent(logger, () => buildHandoffFailedEvent(failureContext(original, tickId), {
986
+ emitEvent(logger, () => buildHandoffFailedEvent(failureContext(original), {
1099
987
  failure: "rollback",
1100
988
  backendPositionId: next.backendDslPositionId ?? undefined,
1101
989
  }));
@@ -1135,15 +1023,13 @@ async function handleHandoffOk(ctx, key, next, original, strategy, span) {
1135
1023
  reason: closeReason,
1136
1024
  closeReason,
1137
1025
  // Backend-driven close: the closing order id is not locally verifiable — stamp ids only.
1138
- ...closedEmitStamps(updated, tickId),
1026
+ ...closedEmitStamps(updated),
1139
1027
  timestamp: ts,
1140
1028
  });
1141
1029
  bus.emit(DSL_EVENTS.CLOSED, buildDslClosedEventFromState(closedState, {
1142
1030
  reason: closeReason,
1143
1031
  closeReason,
1144
1032
  timestamp: ts,
1145
- tickId,
1146
- source: "backend",
1147
1033
  }));
1148
1034
  return;
1149
1035
  }
@@ -1152,7 +1038,7 @@ async function handleHandoffOk(ctx, key, next, original, strategy, span) {
1152
1038
  }
1153
1039
  }
1154
1040
  catch (e) {
1155
- emitEvent(logger, () => buildHandoffFailedEvent(failureContext(original, tickId), {
1041
+ emitEvent(logger, () => buildHandoffFailedEvent(failureContext(original), {
1156
1042
  failure: "poll",
1157
1043
  backendPositionId: next.backendDslPositionId ?? undefined,
1158
1044
  error: e,
@@ -1222,20 +1108,11 @@ async function handleHandoffOk(ctx, key, next, original, strategy, span) {
1222
1108
  const minClosed = mapped.eventName === DSL_EVENTS.CLOSED
1223
1109
  ? mapped.payload
1224
1110
  : null;
1225
- if (minClosed == null) {
1226
- // Single-owner payload: mapBackendEventToBusEvent built this object for this emit and
1227
- // nothing else holds a reference to it, so the tick stamp goes on in place — cloning
1228
- // it once per backend event buys nothing.
1229
- mapped.payload[PAYLOAD_KEY.tickId] = tickId;
1230
- }
1231
1111
  const emitPayload = minClosed != null
1232
1112
  ? buildDslClosedEventFromState(updated, {
1233
1113
  reason: minClosed.reason,
1234
1114
  closeReason: minClosed.closeReason,
1235
1115
  timestamp: minClosed.timestamp,
1236
- tickId,
1237
- source: "backend",
1238
- backendEventAt: minClosed.__backendEventAt,
1239
1116
  })
1240
1117
  : mapped.payload;
1241
1118
  bus.emit(mapped.eventName, emitPayload);
@@ -1282,7 +1159,7 @@ async function handleHandoffOk(ctx, key, next, original, strategy, span) {
1282
1159
  reason: closeReason,
1283
1160
  closeReason,
1284
1161
  // Backend-driven close: the closing order id is not locally verifiable — stamp ids only.
1285
- ...closedEmitStamps(updated, tickId),
1162
+ ...closedEmitStamps(updated),
1286
1163
  timestamp: ts,
1287
1164
  });
1288
1165
  return;