@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
@@ -1,130 +0,0 @@
1
- """Per-tick observability facts the scaffold hands to the intake.
2
-
3
- A scanner tick produces nothing on roughly 99% of ticks, so the only thing a
4
- live screen can show about a working box is what the tick itself reports. These
5
- facts are assembled here, once per tick, and ride the POST the delivery sink
6
- already makes every tick — `/signals` on a clean tick, `/errors` on a failed
7
- one. There is no second channel and no extra request.
8
-
9
- ABSENT IS NOT ZERO. Every field is omitted when its value is unknown, never
10
- defaulted. A `candidate_count` of 0 is a scanner that found nothing; an absent
11
- one would be a scanner that did not say. The distinction has to survive from
12
- here to the screen, so nothing in this module substitutes one for the other.
13
-
14
- The state projection is the LAST COMMITTED row, which makes it stale by one tick
15
- whenever the current tick failed. That is deliberate: a tick that could not
16
- commit is exactly when the last agreed state is worth seeing.
17
- """
18
-
19
- from __future__ import annotations
20
-
21
- from typing import Any, Optional
22
-
23
-
24
- # Per-value character ceiling inside a projected row. An author may park a whole
25
- # serialised payload in one state key; this bounds what one tick can put on the
26
- # wire without bounding what the author may store.
27
- MAX_STATE_VALUE_CHARS = 1024
28
-
29
- # Keys projected out of one state row. Bounds an author's open-ended row the way
30
- # the runtime bounds an open attribute bag.
31
- MAX_STATE_KEYS = 32
32
-
33
-
34
- def _is_scalar(value: Any) -> bool:
35
- """A value a consumer can parse: str, bool, or a FINITE number.
36
-
37
- bool is checked before the numeric branch only implicitly — it is accepted
38
- either way. NaN and the infinities are rejected: they are not JSON, and a
39
- consumer reading one has no way to tell it from a real measurement.
40
- """
41
- if isinstance(value, bool) or isinstance(value, str):
42
- return True
43
- if isinstance(value, (int, float)):
44
- return value == value and value not in (float("inf"), float("-inf"))
45
- return False
46
-
47
-
48
- def project_state_row(row: Any) -> dict:
49
- """The scalar fields of one state row, capped and bounded.
50
-
51
- Returns {} for anything that is not a dict — a row the author replaced with
52
- a list or a string projects to nothing rather than raising inside the loop.
53
- """
54
- if not isinstance(row, dict):
55
- return {}
56
- projected: dict = {}
57
- for key in list(row.keys())[:MAX_STATE_KEYS]:
58
- if not isinstance(key, str):
59
- continue
60
- value = row[key]
61
- if not _is_scalar(value):
62
- continue
63
- projected[key] = value[:MAX_STATE_VALUE_CHARS] if isinstance(value, str) else value
64
- return projected
65
-
66
-
67
- def count_changed(current: dict, previous: Optional[dict]) -> int:
68
- """How many projected fields moved since the previously reported row.
69
-
70
- A first row counts every field as changed: nothing was known before it, so
71
- every value is new information. A key that disappeared counts too — its
72
- absence is a change the operator should see.
73
- """
74
- if previous is None:
75
- return len(current)
76
- keys = set(current) | set(previous)
77
- return sum(1 for key in keys if current.get(key) != previous.get(key))
78
-
79
-
80
- def build_tick_facts(
81
- *,
82
- tick_id: str,
83
- status: str,
84
- candidate_count: int,
85
- duration_ms: int,
86
- commit: Optional[str],
87
- quiet_ticks: int,
88
- lag_ms: Optional[int],
89
- mcp_snapshot: Optional[dict],
90
- call_snapshot: Optional[dict],
91
- state_row: Any,
92
- state_fields: Optional[int],
93
- state_changed: Optional[int],
94
- ) -> dict:
95
- """Assemble one tick's facts for the wire.
96
-
97
- `mcp_snapshot` / `call_snapshot` are the MCP boundary's own per-tick tallies,
98
- or None when the tick ran without an MCP client — which is not the same as a
99
- tick that made no calls, so both keys are then left off entirely.
100
- """
101
- facts: dict = {
102
- "tick_id": tick_id,
103
- "status": status,
104
- "candidate_count": candidate_count,
105
- "duration_ms": duration_ms,
106
- # Always known: the loop either commits, rolls back, or fails to persist.
107
- **({"commit": commit} if commit else {}),
108
- # Zero is a real answer here (this tick produced a signal), so it is sent.
109
- "quiet_ticks": quiet_ticks,
110
- }
111
- # Unknown on the very first tick of a process: there is no previous tick to
112
- # measure the gap against, and a 0 would claim the scanner was exactly on time.
113
- if lag_ms is not None:
114
- facts["lag_ms"] = lag_ms
115
- if mcp_snapshot is not None:
116
- # Every failure the boundary saw this tick. The overwhelming case is a failure the
117
- # author's own `except` caught and turned into an empty return — the one thing that
118
- # otherwise leaves no trace at all. A failure that escaped scan() is in the count too,
119
- # and needs no separating out: it already failed the tick, so `status` names it.
120
- facts["mcp_failures"] = int(mcp_snapshot.get("count") or 0)
121
- if call_snapshot is not None:
122
- facts["mcp_ms"] = call_snapshot.get("total_ms", 0)
123
- facts["mcp_calls"] = call_snapshot.get("calls", [])
124
- projected = project_state_row(state_row)
125
- if state_fields is not None:
126
- facts["state"] = projected
127
- facts["state_fields"] = state_fields
128
- if state_changed is not None:
129
- facts["state_changed"] = state_changed
130
- return facts
@@ -1,58 +0,0 @@
1
- """ULID minting: a 26-character, lexicographically sortable id — 48 bits of millisecond timestamp
2
- followed by 80 bits of randomness, rendered in Crockford's base32. Sortable ids are what let two
3
- ticks be ordered without carrying a second field, and 80 random bits make a collision between two
4
- ticks of the same millisecond unreachable.
5
-
6
- Mirrors src/utils/ulid.ts so a scaffold id and a runtime id are the same kind of value. The random
7
- half is read out of a `uuid.uuid4()`, taking only the ten bytes that carry no version or variant
8
- bits, so all 80 of them are random.
9
- """
10
-
11
- from __future__ import annotations
12
-
13
- import math
14
- import time
15
- import uuid
16
-
17
- # Crockford's base32: no I, L, O or U, so a transcribed id cannot be misread.
18
- CROCKFORD = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
19
-
20
- TIME_CHARS = 10
21
- RANDOM_CHARS = 16
22
- MAX_TIME = 2 ** 48 - 1
23
-
24
-
25
- def _encode_time(ms) -> str:
26
- """Render `ms` as the 10-character time prefix.
27
-
28
- Clamped, and never raised from: a clock that reads non-finite, negative, or past the 48-bit
29
- ceiling must still yield a valid id rather than kill the tick that asked for one.
30
- """
31
- try:
32
- remaining = min(max(math.floor(ms), 0), MAX_TIME)
33
- except (OverflowError, ValueError, TypeError):
34
- remaining = 0
35
- out = ""
36
- for _ in range(TIME_CHARS):
37
- out = CROCKFORD[remaining % 32] + out
38
- remaining //= 32
39
- return out
40
-
41
-
42
- def _encode_random() -> str:
43
- """Render 80 random bits as the 16-character suffix, five bits at a time."""
44
- # uuid4 holds its version and variant in bytes 6 and 8; the ten bytes taken here are the
45
- # fully random ones.
46
- raw = uuid.uuid4().bytes
47
- acc = int.from_bytes(raw[:6] + raw[9:13], "big")
48
- return "".join(
49
- CROCKFORD[(acc >> shift) & 31]
50
- for shift in range(RANDOM_CHARS * 5 - 5, -1, -5)
51
- )
52
-
53
-
54
- def new_ulid(now_ms: int | None = None) -> str:
55
- """Mint a ULID. `now_ms` is injectable so a caller can pin the time half in a test."""
56
- if now_ms is None:
57
- now_ms = int(time.time() * 1000)
58
- return _encode_time(now_ms) + _encode_random()
@@ -1,111 +0,0 @@
1
- /**
2
- * Builder for the `plugin.senpi.dsl` payload — what the box believes about the protection on each
3
- * open position it holds DSL state for.
4
- *
5
- * Pure. Every fact arrives as an input; nothing is read from a state manager or a runtime handle
6
- * here, so the shape on the wire is testable without booting a runtime.
7
- *
8
- * Three properties this module exists to hold:
9
- *
10
- * - **Absence is a claim, and it is never spelled as a value.** A field the box has not measured is
11
- * omitted from the entry. `slOrderId: null` says there is no stop; an absent `slOrderId` says this
12
- * box cannot say. A `0`, a `""` or a synthesised timestamp in either place would read as a
13
- * measurement that was never taken, and the reader has no way to tell the difference afterwards.
14
- * That is why every field is copied through a presence test rather than defaulted, and why the
15
- * wire type marks them optional: the payload has to be able to make both statements.
16
- * - **The venue's answer is carried beside the belief, never folded into it.** `lastVenueStatus` is
17
- * what the venue said about the position's own {@link DslState.slOrderId}; `backendSlVenueStatus`
18
- * is what it said about the backend ratchet's `activeSLOrderId`. They are different orders, and a
19
- * panel that showed one under the other's name would state a confirmation the box never got.
20
- * - **The payload is bounded in bytes, not in entries.** See {@link capDslPositions}.
21
- */
22
- import type { DslState, HandoffStatus } from "../types/dsl/index.js";
23
- /** Payload schema version. Bump when a field changes meaning, not when one is added. */
24
- export declare const DSL_POSITIONS_VERSION = 1;
25
- /** One active DSL state, with the runtime that holds it. */
26
- export interface DslPositionSource {
27
- runtimeId: string;
28
- state: DslState;
29
- }
30
- /**
31
- * One position's protection, as it goes on the wire.
32
- *
33
- * Every field but the three identity ones is optional, and that is the contract rather than a
34
- * looseness: a state row that does not hold a field yields an entry that does not carry it, and a
35
- * client reads the missing key as "this box has not measured that" — the one reading it must never
36
- * confuse with a measured zero.
37
- */
38
- export interface DslPositionEntry {
39
- /** The runtime holding the state. Present always: it is the map key the source was read under. */
40
- runtimeId: string;
41
- /** Normalized, so this joins to the other payloads' `address` on the same spelling. */
42
- address: string;
43
- asset: string;
44
- /** The book. `""` is the default perp book and a real answer, which is why it is not a default. */
45
- dex?: string;
46
- direction?: "LONG" | "SHORT";
47
- entryPrice?: number;
48
- size?: number;
49
- leverage?: number;
50
- phase?: 1 | 2;
51
- /** The floor the breach check compares the mark against, as of the last evaluated tick. */
52
- floorPrice?: number;
53
- /** `phase1.absoluteFloor` — the max-loss level, the only thing the venue holds in phase 1. */
54
- absoluteFloor?: number;
55
- /** `null` means no stop is cached. Absent means this box has not measured one. */
56
- slOrderId?: number | null;
57
- /** The price REQUESTED of the venue, never one read back. */
58
- lastSyncedFloorPrice?: number | null;
59
- /** A write timestamp, not a confirmation timestamp. */
60
- slOrderIdUpdatedAt?: string | null;
61
- handoffStatus?: HandoffStatus | null;
62
- currentBreachCount?: number;
63
- /** `phase1.consecutiveBreachesRequired`, which the engine applies in both phases. */
64
- consecutiveBreachesRequired?: number;
65
- slSyncFailureCount?: number;
66
- pendingClose?: boolean;
67
- consecutiveFetchFailures?: number;
68
- /** The venue's last answer about {@link slOrderId}, verbatim. Absent until the venue answered. */
69
- lastVenueStatus?: string;
70
- lastVenueStatusAt?: number;
71
- /**
72
- * The venue's last answer about the BACKEND ratchet's `activeSLOrderId` — a different order from
73
- * {@link slOrderId}. It is what says why a handoff is sitting at `"pending"`.
74
- */
75
- backendSlVenueStatus?: string;
76
- backendSlVenueStatusAt?: number;
77
- }
78
- export interface DslPositionsPayload {
79
- v: number;
80
- epoch: string;
81
- generatedAt: number;
82
- positions: DslPositionEntry[];
83
- /**
84
- * Positions this frame could not carry within the byte budget. Always present: it is measured on
85
- * every build, so `0` here is the box saying it withheld nothing, not a field it never filled.
86
- */
87
- dropped: number;
88
- }
89
- export interface BuildDslPositionsInput {
90
- /** The buffer's epoch ULID. A change means the plugin restarted. */
91
- epoch: string;
92
- positions: DslPositionSource[];
93
- /** Injectable clock for deterministic tests. */
94
- now?: () => number;
95
- }
96
- /** Builds one `plugin.senpi.dsl` payload from an already-gathered set of active states. */
97
- export declare function buildDslPositions(input: BuildDslPositionsInput): DslPositionsPayload;
98
- /**
99
- * The payload, trimmed to fit one frame.
100
- *
101
- * Bytes and not an entry count, for the same reason the tick frame counts bytes: one non-ASCII
102
- * character in a venue-authored status costs up to three of them, and the read limit at the far end
103
- * counts bytes. A frame past that limit does not cost the one frame — it closes the client's socket
104
- * and costs the stream — so a box with more positions than fit sends the ones that do and states how
105
- * many it withheld, rather than sending an oversized frame or silently shortening the list.
106
- *
107
- * Taken on the SCRUBBED payload and never before it: a redaction can be longer than the text it
108
- * replaced, so a cut taken first bounds the input rather than what leaves.
109
- */
110
- export declare function capDslPositions(payload: DslPositionsPayload, maxBytes: number): DslPositionsPayload;
111
- //# sourceMappingURL=dsl-positions.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"dsl-positions.d.ts","sourceRoot":"","sources":["../../src/telemetry/dsl-positions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAErE,wFAAwF;AACxF,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAKvC,4DAA4D;AAC5D,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,kGAAkG;IAClG,SAAS,EAAE,MAAM,CAAC;IAClB,uFAAuF;IACvF,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,mGAAmG;IACnG,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACd,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8FAA8F;IAC9F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,6DAA6D;IAC7D,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,uDAAuD;IACvD,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qFAAqF;IACrF,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,kGAAkG;IAClG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,mBAAmB;IAClC,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,gDAAgD;IAChD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAwDD,2FAA2F;AAC3F,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,mBAAmB,CASpF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,mBAAmB,EAC5B,QAAQ,EAAE,MAAM,GACf,mBAAmB,CAiBrB"}
@@ -1,118 +0,0 @@
1
- /**
2
- * Builder for the `plugin.senpi.dsl` payload — what the box believes about the protection on each
3
- * open position it holds DSL state for.
4
- *
5
- * Pure. Every fact arrives as an input; nothing is read from a state manager or a runtime handle
6
- * here, so the shape on the wire is testable without booting a runtime.
7
- *
8
- * Three properties this module exists to hold:
9
- *
10
- * - **Absence is a claim, and it is never spelled as a value.** A field the box has not measured is
11
- * omitted from the entry. `slOrderId: null` says there is no stop; an absent `slOrderId` says this
12
- * box cannot say. A `0`, a `""` or a synthesised timestamp in either place would read as a
13
- * measurement that was never taken, and the reader has no way to tell the difference afterwards.
14
- * That is why every field is copied through a presence test rather than defaulted, and why the
15
- * wire type marks them optional: the payload has to be able to make both statements.
16
- * - **The venue's answer is carried beside the belief, never folded into it.** `lastVenueStatus` is
17
- * what the venue said about the position's own {@link DslState.slOrderId}; `backendSlVenueStatus`
18
- * is what it said about the backend ratchet's `activeSLOrderId`. They are different orders, and a
19
- * panel that showed one under the other's name would state a confirmation the box never got.
20
- * - **The payload is bounded in bytes, not in entries.** See {@link capDslPositions}.
21
- */
22
- import { normalizeStrategyAddress } from "./event-store.js";
23
- /** Payload schema version. Bump when a field changes meaning, not when one is added. */
24
- export const DSL_POSITIONS_VERSION = 1;
25
- /** The comma JSON puts between two array entries. Counted, so the budget is the frame's real size. */
26
- const SEPARATOR_BYTES = 1;
27
- function isNumber(value) {
28
- return typeof value === "number" && Number.isFinite(value);
29
- }
30
- /** One entry, assembled field by field. Never spread the state: it carries free text and secrets' neighbours. */
31
- function buildEntry(source) {
32
- const s = source.state;
33
- const phase1 = (s.phase1 ?? {});
34
- return {
35
- runtimeId: source.runtimeId,
36
- // `(address, asset)` is how a client joins this row to the timeline's `dsl.*` records and to the
37
- // topology's strategy row. A checksummed EIP-55 wallet reaching the wire raw would spell this
38
- // position differently from every other payload, and nothing downstream rejects that — the join
39
- // just returns nothing.
40
- address: normalizeStrategyAddress(s.address),
41
- asset: s.asset,
42
- ...(typeof s.dex === "string" ? { dex: s.dex } : {}),
43
- ...(s.direction === "LONG" || s.direction === "SHORT" ? { direction: s.direction } : {}),
44
- ...(isNumber(s.entryPrice) ? { entryPrice: s.entryPrice } : {}),
45
- ...(isNumber(s.size) ? { size: s.size } : {}),
46
- ...(isNumber(s.leverage) ? { leverage: s.leverage } : {}),
47
- ...(s.phase === 1 || s.phase === 2 ? { phase: s.phase } : {}),
48
- ...(isNumber(s.floorPrice) ? { floorPrice: s.floorPrice } : {}),
49
- ...(isNumber(phase1.absoluteFloor) ? { absoluteFloor: phase1.absoluteFloor } : {}),
50
- ...(s.slOrderId === null || isNumber(s.slOrderId) ? { slOrderId: s.slOrderId } : {}),
51
- ...(s.lastSyncedFloorPrice === null || isNumber(s.lastSyncedFloorPrice)
52
- ? { lastSyncedFloorPrice: s.lastSyncedFloorPrice }
53
- : {}),
54
- ...(s.slOrderIdUpdatedAt === null || typeof s.slOrderIdUpdatedAt === "string"
55
- ? { slOrderIdUpdatedAt: s.slOrderIdUpdatedAt }
56
- : {}),
57
- ...(s.handoffStatus === null || typeof s.handoffStatus === "string"
58
- ? { handoffStatus: s.handoffStatus }
59
- : {}),
60
- ...(isNumber(s.currentBreachCount) ? { currentBreachCount: s.currentBreachCount } : {}),
61
- ...(isNumber(phase1.consecutiveBreachesRequired)
62
- ? { consecutiveBreachesRequired: phase1.consecutiveBreachesRequired }
63
- : {}),
64
- ...(isNumber(s.slSyncFailureCount) ? { slSyncFailureCount: s.slSyncFailureCount } : {}),
65
- ...(typeof s.pendingClose === "boolean" ? { pendingClose: s.pendingClose } : {}),
66
- ...(isNumber(s.consecutiveFetchFailures)
67
- ? { consecutiveFetchFailures: s.consecutiveFetchFailures }
68
- : {}),
69
- ...(typeof s.lastVenueStatus === "string" ? { lastVenueStatus: s.lastVenueStatus } : {}),
70
- ...(isNumber(s.lastVenueStatusAt) ? { lastVenueStatusAt: s.lastVenueStatusAt } : {}),
71
- ...(typeof s.backendSlVenueStatus === "string"
72
- ? { backendSlVenueStatus: s.backendSlVenueStatus }
73
- : {}),
74
- ...(isNumber(s.backendSlVenueStatusAt)
75
- ? { backendSlVenueStatusAt: s.backendSlVenueStatusAt }
76
- : {}),
77
- };
78
- }
79
- /** Builds one `plugin.senpi.dsl` payload from an already-gathered set of active states. */
80
- export function buildDslPositions(input) {
81
- const now = input.now ?? Date.now;
82
- return {
83
- v: DSL_POSITIONS_VERSION,
84
- epoch: input.epoch,
85
- generatedAt: now(),
86
- positions: input.positions.map(buildEntry),
87
- dropped: 0,
88
- };
89
- }
90
- /**
91
- * The payload, trimmed to fit one frame.
92
- *
93
- * Bytes and not an entry count, for the same reason the tick frame counts bytes: one non-ASCII
94
- * character in a venue-authored status costs up to three of them, and the read limit at the far end
95
- * counts bytes. A frame past that limit does not cost the one frame — it closes the client's socket
96
- * and costs the stream — so a box with more positions than fit sends the ones that do and states how
97
- * many it withheld, rather than sending an oversized frame or silently shortening the list.
98
- *
99
- * Taken on the SCRUBBED payload and never before it: a redaction can be longer than the text it
100
- * replaced, so a cut taken first bounds the input rather than what leaves.
101
- */
102
- export function capDslPositions(payload, maxBytes) {
103
- // The envelope is measured with `dropped` at its largest possible value, so admitting an entry can
104
- // never be undone by the counter growing a digit.
105
- const envelopeBytes = Buffer.byteLength(JSON.stringify({ ...payload, positions: [], dropped: payload.positions.length }));
106
- let bytes = envelopeBytes;
107
- const positions = [];
108
- for (const entry of payload.positions) {
109
- const size = Buffer.byteLength(JSON.stringify(entry)) + (positions.length > 0 ? SEPARATOR_BYTES : 0);
110
- if (bytes + size > maxBytes)
111
- break;
112
- positions.push(entry);
113
- bytes += size;
114
- }
115
- const dropped = payload.positions.length - positions.length;
116
- return dropped === 0 ? payload : { ...payload, positions, dropped };
117
- }
118
- //# sourceMappingURL=dsl-positions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"dsl-positions.js","sourceRoot":"","sources":["../../src/telemetry/dsl-positions.ts"],"names":[],"mappings":"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"}