@senpi/runtime 3.0.127 → 3.0.128

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 (252) hide show
  1. package/dist/actions/action-events.d.ts +7 -21
  2. package/dist/actions/action-events.d.ts.map +1 -1
  3. package/dist/actions/action-events.js +26 -54
  4. package/dist/actions/action-events.js.map +1 -1
  5. package/dist/actions/action-runtime-module.d.ts.map +1 -1
  6. package/dist/actions/action-runtime-module.js +7 -38
  7. package/dist/actions/action-runtime-module.js.map +1 -1
  8. package/dist/actions/close-position/close-position.action.d.ts.map +1 -1
  9. package/dist/actions/close-position/close-position.action.js +15 -122
  10. package/dist/actions/close-position/close-position.action.js.map +1 -1
  11. package/dist/actions/decision-engine.d.ts.map +1 -1
  12. package/dist/actions/decision-engine.js +2 -15
  13. package/dist/actions/decision-engine.js.map +1 -1
  14. package/dist/actions/event-derivation.d.ts +2 -71
  15. package/dist/actions/event-derivation.d.ts.map +1 -1
  16. package/dist/actions/event-derivation.js +8 -251
  17. package/dist/actions/event-derivation.js.map +1 -1
  18. package/dist/actions/open-position/open-position.action.d.ts +2 -17
  19. package/dist/actions/open-position/open-position.action.d.ts.map +1 -1
  20. package/dist/actions/open-position/open-position.action.js +47 -162
  21. package/dist/actions/open-position/open-position.action.js.map +1 -1
  22. package/dist/actions/position-tracker/position-tracker.action.d.ts +1 -2
  23. package/dist/actions/position-tracker/position-tracker.action.d.ts.map +1 -1
  24. package/dist/actions/position-tracker/position-tracker.action.js +17 -62
  25. package/dist/actions/position-tracker/position-tracker.action.js.map +1 -1
  26. package/dist/actions/store/types.d.ts +2 -9
  27. package/dist/actions/store/types.d.ts.map +1 -1
  28. package/dist/actions/store/types.js.map +1 -1
  29. package/dist/actions/types.d.ts +0 -13
  30. package/dist/actions/types.d.ts.map +1 -1
  31. package/dist/actions/types.js +0 -13
  32. package/dist/actions/types.js.map +1 -1
  33. package/dist/cli/guide-commands.d.ts.map +1 -1
  34. package/dist/cli/guide-commands.js +0 -3
  35. package/dist/cli/guide-commands.js.map +1 -1
  36. package/dist/dsl/engine-client/event-mapping.d.ts.map +1 -1
  37. package/dist/dsl/engine-client/event-mapping.js +0 -14
  38. package/dist/dsl/engine-client/event-mapping.js.map +1 -1
  39. package/dist/dsl/events/build-closed-event.d.ts +1 -16
  40. package/dist/dsl/events/build-closed-event.d.ts.map +1 -1
  41. package/dist/dsl/events/build-closed-event.js +0 -6
  42. package/dist/dsl/events/build-closed-event.js.map +1 -1
  43. package/dist/dsl/events/handlers.d.ts +0 -7
  44. package/dist/dsl/events/handlers.d.ts.map +1 -1
  45. package/dist/dsl/events/handlers.js +7 -37
  46. package/dist/dsl/events/handlers.js.map +1 -1
  47. package/dist/dsl/monitor/create-monitor.d.ts +2 -6
  48. package/dist/dsl/monitor/create-monitor.d.ts.map +1 -1
  49. package/dist/dsl/monitor/create-monitor.js +9 -15
  50. package/dist/dsl/monitor/create-monitor.js.map +1 -1
  51. package/dist/dsl/monitor/dsl-failure-events.d.ts +0 -2
  52. package/dist/dsl/monitor/dsl-failure-events.d.ts.map +1 -1
  53. package/dist/dsl/monitor/dsl-failure-events.js +1 -2
  54. package/dist/dsl/monitor/dsl-failure-events.js.map +1 -1
  55. package/dist/dsl/monitor/process-one-position.d.ts +0 -1
  56. package/dist/dsl/monitor/process-one-position.d.ts.map +1 -1
  57. package/dist/dsl/monitor/process-one-position.js +25 -59
  58. package/dist/dsl/monitor/process-one-position.js.map +1 -1
  59. package/dist/dsl/plugin/index.d.ts +2 -8
  60. package/dist/dsl/plugin/index.d.ts.map +1 -1
  61. package/dist/dsl/plugin/index.js +6 -8
  62. package/dist/dsl/plugin/index.js.map +1 -1
  63. package/dist/health/types.d.ts +0 -13
  64. package/dist/health/types.d.ts.map +1 -1
  65. package/dist/health/types.js +0 -12
  66. package/dist/health/types.js.map +1 -1
  67. package/dist/index.d.ts +4 -27
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +42 -254
  70. package/dist/index.js.map +1 -1
  71. package/dist/runtime/action-registry.d.ts.map +1 -1
  72. package/dist/runtime/action-registry.js +3 -4
  73. package/dist/runtime/action-registry.js.map +1 -1
  74. package/dist/runtime/domain-events.d.ts.map +1 -1
  75. package/dist/runtime/domain-events.js +0 -7
  76. package/dist/runtime/domain-events.js.map +1 -1
  77. package/dist/runtime/lifecycle-events.d.ts +1 -9
  78. package/dist/runtime/lifecycle-events.d.ts.map +1 -1
  79. package/dist/runtime/lifecycle-events.js +2 -11
  80. package/dist/runtime/lifecycle-events.js.map +1 -1
  81. package/dist/runtime/reconcile-run.d.ts +3 -13
  82. package/dist/runtime/reconcile-run.d.ts.map +1 -1
  83. package/dist/runtime/reconcile-run.js +3 -4
  84. package/dist/runtime/reconcile-run.js.map +1 -1
  85. package/dist/runtime/reconcile-state.d.ts +0 -8
  86. package/dist/runtime/reconcile-state.d.ts.map +1 -1
  87. package/dist/runtime/reconcile-state.js +1 -4
  88. package/dist/runtime/reconcile-state.js.map +1 -1
  89. package/dist/runtime/run.d.ts +0 -1
  90. package/dist/runtime/run.d.ts.map +1 -1
  91. package/dist/runtime/run.js.map +1 -1
  92. package/dist/runtime/runtime-schema.js +3 -3
  93. package/dist/runtime/runtime-schema.js.map +1 -1
  94. package/dist/runtime/runtime.d.ts +0 -1
  95. package/dist/runtime/runtime.d.ts.map +1 -1
  96. package/dist/runtime/runtime.js +3 -27
  97. package/dist/runtime/runtime.js.map +1 -1
  98. package/dist/runtime/supervisor/long-running-supervisor.d.ts +0 -13
  99. package/dist/runtime/supervisor/long-running-supervisor.d.ts.map +1 -1
  100. package/dist/runtime/supervisor/long-running-supervisor.js +0 -1
  101. package/dist/runtime/supervisor/long-running-supervisor.js.map +1 -1
  102. package/dist/runtime/validate-dsl-position-tracking.d.ts.map +1 -1
  103. package/dist/runtime/validate-dsl-position-tracking.js +1 -2
  104. package/dist/runtime/validate-dsl-position-tracking.js.map +1 -1
  105. package/dist/runtime-api/handlers/ingest-signals.d.ts.map +1 -1
  106. package/dist/runtime-api/handlers/ingest-signals.js +0 -1
  107. package/dist/runtime-api/handlers/ingest-signals.js.map +1 -1
  108. package/dist/runtime-api/handlers/types.d.ts +0 -5
  109. package/dist/runtime-api/handlers/types.d.ts.map +1 -1
  110. package/dist/runtime-api/intake/intake-events.d.ts +1 -1
  111. package/dist/runtime-api/intake/intake-events.d.ts.map +1 -1
  112. package/dist/runtime-api/intake/intake-events.js +3 -9
  113. package/dist/runtime-api/intake/intake-events.js.map +1 -1
  114. package/dist/runtime-api/intake/intake-mount.d.ts.map +1 -1
  115. package/dist/runtime-api/intake/intake-mount.js +19 -4
  116. package/dist/runtime-api/intake/intake-mount.js.map +1 -1
  117. package/dist/runtime-api/intake/process-error-post.d.ts +1 -6
  118. package/dist/runtime-api/intake/process-error-post.d.ts.map +1 -1
  119. package/dist/runtime-api/intake/process-error-post.js +1 -5
  120. package/dist/runtime-api/intake/process-error-post.js.map +1 -1
  121. package/dist/runtime-api/intake/process-signal-post.d.ts +1 -7
  122. package/dist/runtime-api/intake/process-signal-post.d.ts.map +1 -1
  123. package/dist/runtime-api/intake/process-signal-post.js +0 -5
  124. package/dist/runtime-api/intake/process-signal-post.js.map +1 -1
  125. package/dist/runtime-api/intake/scaffold-error-router.js.map +1 -1
  126. package/dist/runtime-api/intake/scanner-launcher.d.ts.map +1 -1
  127. package/dist/runtime-api/intake/scanner-launcher.js +0 -15
  128. package/dist/runtime-api/intake/scanner-launcher.js.map +1 -1
  129. package/dist/runtime-api/intake/types.d.ts +0 -55
  130. package/dist/runtime-api/intake/types.d.ts.map +1 -1
  131. package/dist/runtime-api/routes/signals.d.ts +0 -2
  132. package/dist/runtime-api/routes/signals.d.ts.map +1 -1
  133. package/dist/runtime-api/routes/signals.js +1 -5
  134. package/dist/runtime-api/routes/signals.js.map +1 -1
  135. package/dist/runtime-api/routes/signals.schema.d.ts +0 -43
  136. package/dist/runtime-api/routes/signals.schema.d.ts.map +1 -1
  137. package/dist/runtime-api/routes/signals.schema.js +0 -43
  138. package/dist/runtime-api/routes/signals.schema.js.map +1 -1
  139. package/dist/runtime-api/server.d.ts +1 -7
  140. package/dist/runtime-api/server.d.ts.map +1 -1
  141. package/dist/runtime-api/server.js +0 -1
  142. package/dist/runtime-api/server.js.map +1 -1
  143. package/dist/scanners/engine/engine.d.ts +1 -22
  144. package/dist/scanners/engine/engine.d.ts.map +1 -1
  145. package/dist/scanners/engine/engine.js +11 -78
  146. package/dist/scanners/engine/engine.js.map +1 -1
  147. package/dist/scanners/engine/lifecycle.d.ts +1 -7
  148. package/dist/scanners/engine/lifecycle.d.ts.map +1 -1
  149. package/dist/scanners/events.d.ts +0 -4
  150. package/dist/scanners/events.d.ts.map +1 -1
  151. package/dist/scanners/events.js +0 -2
  152. package/dist/scanners/events.js.map +1 -1
  153. package/dist/scanners/external/scaffold/delivery.py +25 -194
  154. package/dist/scanners/external/scaffold/scaffold.py +31 -172
  155. package/dist/scanners/external/scaffold/senpi_mcp.py +8 -150
  156. package/dist/scanners/external-scanner-receiver.d.ts +0 -17
  157. package/dist/scanners/external-scanner-receiver.d.ts.map +1 -1
  158. package/dist/scanners/external-scanner-receiver.js +0 -8
  159. package/dist/scanners/external-scanner-receiver.js.map +1 -1
  160. package/dist/scanners/runtime-module.d.ts +0 -1
  161. package/dist/scanners/runtime-module.d.ts.map +1 -1
  162. package/dist/scanners/runtime-module.js +9 -66
  163. package/dist/scanners/runtime-module.js.map +1 -1
  164. package/dist/telemetry/attributes.d.ts +0 -20
  165. package/dist/telemetry/attributes.d.ts.map +1 -1
  166. package/dist/telemetry/attributes.js +0 -24
  167. package/dist/telemetry/attributes.js.map +1 -1
  168. package/dist/telemetry/event-builders.d.ts +6 -81
  169. package/dist/telemetry/event-builders.d.ts.map +1 -1
  170. package/dist/telemetry/event-builders.js +17 -141
  171. package/dist/telemetry/event-builders.js.map +1 -1
  172. package/dist/telemetry/event-store.d.ts +0 -6
  173. package/dist/telemetry/event-store.d.ts.map +1 -1
  174. package/dist/telemetry/event-store.js +8 -12
  175. package/dist/telemetry/event-store.js.map +1 -1
  176. package/dist/telemetry/metrics.d.ts +2 -14
  177. package/dist/telemetry/metrics.d.ts.map +1 -1
  178. package/dist/telemetry/metrics.js +4 -19
  179. package/dist/telemetry/metrics.js.map +1 -1
  180. package/dist/telemetry/spans/redact-pii.d.ts.map +1 -1
  181. package/dist/telemetry/spans/redact-pii.js +2 -18
  182. package/dist/telemetry/spans/redact-pii.js.map +1 -1
  183. package/dist/telemetry/tracing.d.ts +0 -9
  184. package/dist/telemetry/tracing.d.ts.map +1 -1
  185. package/dist/telemetry/tracing.js +0 -36
  186. package/dist/telemetry/tracing.js.map +1 -1
  187. package/dist/types/dsl/index.d.ts +0 -11
  188. package/dist/types/dsl/index.d.ts.map +1 -1
  189. package/dist/types/scanner.d.ts +0 -15
  190. package/dist/types/scanner.d.ts.map +1 -1
  191. package/dist/utils/event-catalog.d.ts +0 -166
  192. package/dist/utils/event-catalog.d.ts.map +1 -1
  193. package/dist/utils/event-catalog.js +0 -18
  194. package/dist/utils/event-catalog.js.map +1 -1
  195. package/dist/utils/logger.d.ts +1 -4
  196. package/dist/utils/logger.d.ts.map +1 -1
  197. package/dist/utils/logger.js.map +1 -1
  198. package/dist/validate/recipe-checks.d.ts.map +1 -1
  199. package/dist/validate/recipe-checks.js +2 -2
  200. package/dist/validate/recipe-checks.js.map +1 -1
  201. package/openclaw.plugin.json +1 -1
  202. package/package.json +1 -1
  203. package/dist/actions/skipped-signal-results.d.ts +0 -25
  204. package/dist/actions/skipped-signal-results.d.ts.map +0 -1
  205. package/dist/actions/skipped-signal-results.js +0 -71
  206. package/dist/actions/skipped-signal-results.js.map +0 -1
  207. package/dist/runtime-api/intake/ingest-request.d.ts +0 -17
  208. package/dist/runtime-api/intake/ingest-request.d.ts.map +0 -1
  209. package/dist/runtime-api/intake/ingest-request.js +0 -34
  210. package/dist/runtime-api/intake/ingest-request.js.map +0 -1
  211. package/dist/runtime-api/intake/scaffold-tick-router.d.ts +0 -39
  212. package/dist/runtime-api/intake/scaffold-tick-router.d.ts.map +0 -1
  213. package/dist/runtime-api/intake/scaffold-tick-router.js +0 -122
  214. package/dist/runtime-api/intake/scaffold-tick-router.js.map +0 -1
  215. package/dist/scanners/external/scaffold/tick_facts.py +0 -130
  216. package/dist/scanners/external/scaffold/ulid.py +0 -58
  217. package/dist/telemetry/live-telemetry.d.ts +0 -238
  218. package/dist/telemetry/live-telemetry.d.ts.map +0 -1
  219. package/dist/telemetry/live-telemetry.js +0 -853
  220. package/dist/telemetry/live-telemetry.js.map +0 -1
  221. package/dist/telemetry/scanner-stats.d.ts +0 -143
  222. package/dist/telemetry/scanner-stats.d.ts.map +0 -1
  223. package/dist/telemetry/scanner-stats.js +0 -426
  224. package/dist/telemetry/scanner-stats.js.map +0 -1
  225. package/dist/telemetry/scanner-tick-feed.d.ts +0 -87
  226. package/dist/telemetry/scanner-tick-feed.d.ts.map +0 -1
  227. package/dist/telemetry/scanner-tick-feed.js +0 -48
  228. package/dist/telemetry/scanner-tick-feed.js.map +0 -1
  229. package/dist/telemetry/strategy-topology.d.ts +0 -99
  230. package/dist/telemetry/strategy-topology.d.ts.map +0 -1
  231. package/dist/telemetry/strategy-topology.js +0 -93
  232. package/dist/telemetry/strategy-topology.js.map +0 -1
  233. package/dist/telemetry/telemetry-publisher.d.ts +0 -63
  234. package/dist/telemetry/telemetry-publisher.d.ts.map +0 -1
  235. package/dist/telemetry/telemetry-publisher.js +0 -229
  236. package/dist/telemetry/telemetry-publisher.js.map +0 -1
  237. package/dist/telemetry/tick-frame.d.ts +0 -212
  238. package/dist/telemetry/tick-frame.d.ts.map +0 -1
  239. package/dist/telemetry/tick-frame.js +0 -421
  240. package/dist/telemetry/tick-frame.js.map +0 -1
  241. package/dist/telemetry/timeline-buffer.d.ts +0 -95
  242. package/dist/telemetry/timeline-buffer.d.ts.map +0 -1
  243. package/dist/telemetry/timeline-buffer.js +0 -237
  244. package/dist/telemetry/timeline-buffer.js.map +0 -1
  245. package/dist/utils/telemetry-required-log.d.ts +0 -60
  246. package/dist/utils/telemetry-required-log.d.ts.map +0 -1
  247. package/dist/utils/telemetry-required-log.js +0 -105
  248. package/dist/utils/telemetry-required-log.js.map +0 -1
  249. package/dist/utils/ulid.d.ts +0 -9
  250. package/dist/utils/ulid.d.ts.map +0 -1
  251. package/dist/utils/ulid.js +0 -43
  252. package/dist/utils/ulid.js.map +0 -1
@@ -1,25 +0,0 @@
1
- /**
2
- * Per-signal `results[]` rows synthesized for a batch-level early exit — the exits that return
3
- * before the per-signal loop and would otherwise leave the scan's signals with no recorded outcome.
4
- * Entry shape matches the loop's own rows so the derived per-signal telemetry is identical in
5
- * structure: normalized `dex`, `direction`/`score` only when usable, and a zero-width work window
6
- * (both stamps present — a half window is dropped downstream, and a missing one is
7
- * indistinguishable from an unstamped legacy row).
8
- *
9
- * Each row carries `__signalIndex`, its position in the INPUT list, so the event mapper pairs the
10
- * row with THIS signal's `meta` rather than with the first signal sharing its asset. It is read
11
- * inside the loop, not zipped on by the caller: a dropped signal shifts every later output
12
- * position. The input list is the scan's own signal array, which is what the mapper indexes into;
13
- * close-position's static-params fallback list has no scan array behind it, so its index matches
14
- * nothing and the mapper degrades to its asset join, as it does for any unmatched index.
15
- *
16
- * A signal with no usable asset is dropped: an outcome that names no asset is not attributable.
17
- * A drop is a hole in the "no signal goes unrecorded" contract, so it is logged (once per call,
18
- * with the count) rather than passing silently. Counts are unaffected — the row is still absent.
19
- * Total by construction — it runs on the trading path and must never throw on a malformed entry.
20
- */
21
- export declare function skippedSignalResults(signals: readonly unknown[] | undefined, reason: string, nowMs: number, overrides?: {
22
- success?: boolean;
23
- error?: string;
24
- }): Array<Record<string, unknown>>;
25
- //# sourceMappingURL=skipped-signal-results.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"skipped-signal-results.d.ts","sourceRoot":"","sources":["../../src/actions/skipped-signal-results.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,SAAS,OAAO,EAAE,GAAG,SAAS,EACvC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA8ChC"}
@@ -1,71 +0,0 @@
1
- import { createLogger } from '../utils/logger.js';
2
- const logger = createLogger('[actions][skipped-signal-results]');
3
- /**
4
- * Per-signal `results[]` rows synthesized for a batch-level early exit — the exits that return
5
- * before the per-signal loop and would otherwise leave the scan's signals with no recorded outcome.
6
- * Entry shape matches the loop's own rows so the derived per-signal telemetry is identical in
7
- * structure: normalized `dex`, `direction`/`score` only when usable, and a zero-width work window
8
- * (both stamps present — a half window is dropped downstream, and a missing one is
9
- * indistinguishable from an unstamped legacy row).
10
- *
11
- * Each row carries `__signalIndex`, its position in the INPUT list, so the event mapper pairs the
12
- * row with THIS signal's `meta` rather than with the first signal sharing its asset. It is read
13
- * inside the loop, not zipped on by the caller: a dropped signal shifts every later output
14
- * position. The input list is the scan's own signal array, which is what the mapper indexes into;
15
- * close-position's static-params fallback list has no scan array behind it, so its index matches
16
- * nothing and the mapper degrades to its asset join, as it does for any unmatched index.
17
- *
18
- * A signal with no usable asset is dropped: an outcome that names no asset is not attributable.
19
- * A drop is a hole in the "no signal goes unrecorded" contract, so it is logged (once per call,
20
- * with the count) rather than passing silently. Counts are unaffected — the row is still absent.
21
- * Total by construction — it runs on the trading path and must never throw on a malformed entry.
22
- */
23
- export function skippedSignalResults(signals, reason, nowMs, overrides) {
24
- if (!Array.isArray(signals))
25
- return [];
26
- const rows = [];
27
- let dropped = 0;
28
- for (const [index, raw] of signals.entries()) {
29
- if (raw === null || typeof raw !== 'object') {
30
- dropped++;
31
- continue;
32
- }
33
- const signal = raw;
34
- const rawAsset = signal.asset;
35
- // Kept verbatim (not trimmed) so it still joins the scanner signal it came from.
36
- const asset = typeof rawAsset === 'string' ? rawAsset : typeof rawAsset === 'number' ? String(rawAsset) : '';
37
- if (asset.trim() === '') {
38
- dropped++;
39
- continue;
40
- }
41
- const direction = signal.direction;
42
- const score = signal.score;
43
- // A decision-payload signal carries the book top-level (the strategy hoists it there); a raw
44
- // scanner signal carries it only on `meta`, since `Signal` has no `dex` field. Both call
45
- // shapes reach this helper, so both are read — top-level first, matching the per-signal loop.
46
- const meta = signal.meta;
47
- const metaDex = meta !== null && typeof meta === 'object' ? meta.dex : undefined;
48
- const dex = typeof signal.dex === 'string' && signal.dex.trim() !== '' ? signal.dex : metaDex;
49
- rows.push({
50
- asset,
51
- ...(direction === 'LONG' || direction === 'SHORT' ? { direction } : {}),
52
- dex: typeof dex === 'string' && dex.trim() !== '' ? dex.trim() : 'main',
53
- ...(typeof score === 'number' && Number.isFinite(score) ? { score } : {}),
54
- success: overrides?.success ?? true,
55
- reason,
56
- ...(overrides?.error !== undefined ? { error: overrides.error } : {}),
57
- startedAt: nowMs,
58
- endedAt: nowMs,
59
- __signalIndex: index,
60
- });
61
- }
62
- if (dropped > 0) {
63
- logger.warn('signals dropped from the skip rows: no usable asset to attribute the outcome to', undefined, {
64
- reason,
65
- dropped,
66
- recorded: rows.length,
67
- });
68
- }
69
- return rows;
70
- }
71
- //# sourceMappingURL=skipped-signal-results.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"skipped-signal-results.js","sourceRoot":"","sources":["../../src/actions/skipped-signal-results.ts"],"names":[],"mappings":"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"}
@@ -1,17 +0,0 @@
1
- /**
2
- * IntakeSignal → ExternalScannerIngestRequest.
3
- *
4
- * The single mapping between the intake wire shape and the engine's ingest shape. Both accept
5
- * seams call it: the live route closure in `src/index.ts` and `buildIntakeMount`'s `onAccepted`.
6
- */
7
- import type { ExternalScannerIngestRequest } from "../../scanners/external-scanner-receiver.js";
8
- import type { ScannerId } from "../../scanners/types.js";
9
- import type { IntakeSignal } from "./types.js";
10
- /**
11
- * Narrow one accepted intake signal to the ingest request the engine takes.
12
- *
13
- * @param scannerName Configured scanner NAME resolved from the registry, not the wire `scanner_id`.
14
- * @param correlationId Intake-minted id of the acceptance row that admitted this signal.
15
- */
16
- export declare function toIngestRequest(signal: IntakeSignal, correlationId: string, scannerName: ScannerId): ExternalScannerIngestRequest;
17
- //# sourceMappingURL=ingest-request.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ingest-request.d.ts","sourceRoot":"","sources":["../../../src/runtime-api/intake/ingest-request.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,6CAA6C,CAAC;AAChG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,YAAY,EACpB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,SAAS,GACrB,4BAA4B,CAoB9B"}
@@ -1,34 +0,0 @@
1
- /**
2
- * IntakeSignal → ExternalScannerIngestRequest.
3
- *
4
- * The single mapping between the intake wire shape and the engine's ingest shape. Both accept
5
- * seams call it: the live route closure in `src/index.ts` and `buildIntakeMount`'s `onAccepted`.
6
- */
7
- /**
8
- * Narrow one accepted intake signal to the ingest request the engine takes.
9
- *
10
- * @param scannerName Configured scanner NAME resolved from the registry, not the wire `scanner_id`.
11
- * @param correlationId Intake-minted id of the acceptance row that admitted this signal.
12
- */
13
- export function toIngestRequest(signal, correlationId, scannerName) {
14
- return {
15
- scanner: scannerName,
16
- signal_id: signal.signal_id, // greppable handle across intake→ingest (obs only)
17
- asset: signal.asset,
18
- direction: signal.direction,
19
- ...(signal.signal_type !== undefined && { signal_type: signal.signal_type }),
20
- data: signal.data,
21
- // Per-signal sizing rides at the top level; the open-position action reads
22
- // request.marginPct / request.leverage directly, else a supervised signal's
23
- // sizing is lost ("no margin source resolved").
24
- ...(signal.marginPct !== undefined && { marginPct: signal.marginPct }),
25
- ...(signal.leverage !== undefined && { leverage: signal.leverage }),
26
- // The producing scan and the admitting acceptance row.
27
- tick_id: signal.tick_id,
28
- correlationId,
29
- // Intentionally omitted: score (intake has none, defaults to 0 downstream),
30
- // valid_until/produced_at (acceptance-pipeline concerns, not ingest fields),
31
- // signals[] (single-signal shape: data, not signals[]).
32
- };
33
- }
34
- //# sourceMappingURL=ingest-request.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ingest-request.js","sourceRoot":"","sources":["../../../src/runtime-api/intake/ingest-request.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAoB,EACpB,aAAqB,EACrB,WAAsB;IAEtB,OAAO;QACL,OAAO,EAAE,WAAW;QACpB,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,mDAAmD;QAChF,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,GAAG,CAAC,MAAM,CAAC,WAAW,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;QAC5E,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,2EAA2E;QAC3E,4EAA4E;QAC5E,gDAAgD;QAChD,GAAG,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;QACtE,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;QACnE,uDAAuD;QACvD,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,aAAa;QACb,4EAA4E;QAC5E,6EAA6E;QAC7E,wDAAwD;KACzD,CAAC;AACJ,CAAC"}
@@ -1,39 +0,0 @@
1
- /**
2
- * The `/signals` and `/errors` routes' `onTick` — one implementation, used by both.
3
- *
4
- * A supervised external scanner runs in its own Python process, so the only facts the runtime has
5
- * about one of its ticks are the ones that arrive over the intake. Both routes already fire once
6
- * per tick — `/signals` on every clean tick including a quiet one, `/errors` on every failed one —
7
- * so the facts ride the request that tick already makes. No second channel, no extra POST, and a
8
- * producer that sends none behaves exactly as it did before.
9
- *
10
- * What this does with them is hand the run to the SAME process sink the in-process scanner runtime
11
- * hands its own finished runs to ({@link ../../telemetry/scanner-tick-feed.js}), which is a no-op
12
- * until a client is watching. Nothing here reaches `logger.event` or `appendDomainEvent`: a tick is
13
- * a LEVEL, and per-tick records would evict real decision rows from the on-disk ring and the
14
- * publisher's bounded buffer.
15
- *
16
- * ABSENT IS NOT ZERO, end to end. A field the producer did not send is left off the run rather than
17
- * defaulted, so the publisher can leave it off the frame and the screen can print "unknown" instead
18
- * of a number nobody measured.
19
- */
20
- import { type ScannerTickExtras } from "../../telemetry/scanner-tick-feed.js";
21
- import type { IntakeContext } from "./intake-context.js";
22
- import type { IntakeTickFacts } from "./types.js";
23
- /** The producer's facts as the tick feed's extras, with every unreadable field left off. */
24
- export declare function toTickExtras(facts: IntakeTickFacts): ScannerTickExtras;
25
- /**
26
- * Build the `onTick` both intake routes call.
27
- *
28
- * Resolves against the SHARED IntakeContext registry, like `onAccepted` and `onScaffoldError`, so
29
- * the tick is attributed to the scanner's STABLE name and its runtime's wallet rather than to the
30
- * ephemeral scanner_id a relaunch re-mints — which is the key a client joins a tick to its stats
31
- * row on.
32
- *
33
- * `now` is the runtime clock at the POST, used as the run's finish. The producer's own clock is not
34
- * used: it is a different machine's wall time, and a frame mixing the two would put ticks in an
35
- * order neither machine saw. `startedAt` is derived from the duration the producer measured, which
36
- * keeps `ms` the producer's own number while `t` stays on this box's clock.
37
- */
38
- export declare function buildScaffoldTickRouter(ctx: IntakeContext, now?: () => number): (scannerId: string, facts: IntakeTickFacts) => void;
39
- //# sourceMappingURL=scaffold-tick-router.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scaffold-tick-router.d.ts","sourceRoot":"","sources":["../../../src/runtime-api/intake/scaffold-tick-router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,sCAAsC,CAAC;AAE9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAkB,eAAe,EAAE,MAAM,YAAY,CAAC;AAkClE,4FAA4F;AAC5F,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,GAAG,iBAAiB,CA+BtE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,aAAa,EAClB,GAAG,GAAE,MAAM,MAAyB,GACnC,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,KAAK,IAAI,CAqBrD"}
@@ -1,122 +0,0 @@
1
- /**
2
- * The `/signals` and `/errors` routes' `onTick` — one implementation, used by both.
3
- *
4
- * A supervised external scanner runs in its own Python process, so the only facts the runtime has
5
- * about one of its ticks are the ones that arrive over the intake. Both routes already fire once
6
- * per tick — `/signals` on every clean tick including a quiet one, `/errors` on every failed one —
7
- * so the facts ride the request that tick already makes. No second channel, no extra POST, and a
8
- * producer that sends none behaves exactly as it did before.
9
- *
10
- * What this does with them is hand the run to the SAME process sink the in-process scanner runtime
11
- * hands its own finished runs to ({@link ../../telemetry/scanner-tick-feed.js}), which is a no-op
12
- * until a client is watching. Nothing here reaches `logger.event` or `appendDomainEvent`: a tick is
13
- * a LEVEL, and per-tick records would evict real decision rows from the on-disk ring and the
14
- * publisher's bounded buffer.
15
- *
16
- * ABSENT IS NOT ZERO, end to end. A field the producer did not send is left off the run rather than
17
- * defaulted, so the publisher can leave it off the frame and the screen can print "unknown" instead
18
- * of a number nobody measured.
19
- */
20
- import { hasScannerTickSink, recordScannerTick, } from "../../telemetry/scanner-tick-feed.js";
21
- /** The commit endings this box publishes. Anything else a producer sends is dropped, not relayed. */
22
- const COMMIT_OUTCOMES = new Set([
23
- "committed",
24
- "rolled_back",
25
- "persist_failed",
26
- ]);
27
- /** A finite, non-negative number, or `undefined` — which is how an unknown stays unknown. */
28
- function count(value) {
29
- return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined;
30
- }
31
- function calls(rows) {
32
- if (!Array.isArray(rows))
33
- return undefined;
34
- const out = [];
35
- for (const row of rows) {
36
- if (row === null || typeof row !== "object")
37
- continue;
38
- if (typeof row.tool !== "string" || row.tool.length === 0)
39
- continue;
40
- out.push({
41
- tool: row.tool,
42
- ...(count(row.ms) === undefined ? {} : { ms: count(row.ms) }),
43
- ...(row.args !== null && typeof row.args === "object" && !Array.isArray(row.args)
44
- ? { args: row.args }
45
- : {}),
46
- ...(typeof row.error_type === "string" && row.error_type.length > 0
47
- ? { errorType: row.error_type }
48
- : {}),
49
- });
50
- }
51
- return out;
52
- }
53
- /** The producer's facts as the tick feed's extras, with every unreadable field left off. */
54
- export function toTickExtras(facts) {
55
- const commit = typeof facts.commit === "string" && COMMIT_OUTCOMES.has(facts.commit)
56
- ? facts.commit
57
- : undefined;
58
- const state = facts.state !== null && typeof facts.state === "object" && !Array.isArray(facts.state)
59
- ? facts.state
60
- : undefined;
61
- const mcpCalls = calls(facts.mcp_calls);
62
- return {
63
- ...(count(facts.mcp_failures) === undefined ? {} : { mcpFailures: count(facts.mcp_failures) }),
64
- ...(mcpCalls === undefined ? {} : { mcpCalls }),
65
- ...(count(facts.mcp_ms) === undefined ? {} : { mcpMs: count(facts.mcp_ms) }),
66
- ...(count(facts.quiet_ticks) === undefined ? {} : { quietTicks: count(facts.quiet_ticks) }),
67
- // The only signed field: a tick that ran EARLY reports a negative lag, and the frame omits it.
68
- ...(typeof facts.lag_ms === "number" && Number.isFinite(facts.lag_ms)
69
- ? { lagMs: facts.lag_ms }
70
- : {}),
71
- ...(count(facts.journal_pending) === undefined
72
- ? {}
73
- : { journalPending: count(facts.journal_pending) }),
74
- ...(commit === undefined ? {} : { commit }),
75
- ...(state === undefined ? {} : { state }),
76
- ...(count(facts.state_fields) === undefined
77
- ? {}
78
- : { stateFieldCount: count(facts.state_fields) }),
79
- ...(count(facts.state_changed) === undefined
80
- ? {}
81
- : { stateChangedCount: count(facts.state_changed) }),
82
- };
83
- }
84
- /**
85
- * Build the `onTick` both intake routes call.
86
- *
87
- * Resolves against the SHARED IntakeContext registry, like `onAccepted` and `onScaffoldError`, so
88
- * the tick is attributed to the scanner's STABLE name and its runtime's wallet rather than to the
89
- * ephemeral scanner_id a relaunch re-mints — which is the key a client joins a tick to its stats
90
- * row on.
91
- *
92
- * `now` is the runtime clock at the POST, used as the run's finish. The producer's own clock is not
93
- * used: it is a different machine's wall time, and a frame mixing the two would put ticks in an
94
- * order neither machine saw. `startedAt` is derived from the duration the producer measured, which
95
- * keeps `ms` the producer's own number while `t` stays on this box's clock.
96
- */
97
- export function buildScaffoldTickRouter(ctx, now = () => Date.now()) {
98
- return (scannerId, facts) => {
99
- if (facts === null || typeof facts !== "object")
100
- return;
101
- // Checked first, before anything is built: a box no client has ever reached pays one
102
- // comparison per tick and allocates nothing.
103
- if (!hasScannerTickSink())
104
- return;
105
- const entry = ctx.registry.resolve(scannerId);
106
- if (!entry)
107
- return; // zombie fence — a relaunch re-mints the id and unregisters the old one
108
- const finishedAt = now();
109
- const durationMs = count(facts.duration_ms);
110
- const run = {
111
- address: entry.wallet,
112
- scannerId: entry.scannerName,
113
- status: typeof facts.status === "string" && facts.status.length > 0 ? facts.status : "ok",
114
- ...(count(facts.candidate_count) === undefined
115
- ? {}
116
- : { signalCount: count(facts.candidate_count) }),
117
- tick: toTickExtras(facts),
118
- };
119
- recordScannerTick(run, durationMs === undefined ? undefined : finishedAt - durationMs, finishedAt);
120
- };
121
- }
122
- //# sourceMappingURL=scaffold-tick-router.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scaffold-tick-router.js","sourceRoot":"","sources":["../../../src/runtime-api/intake/scaffold-tick-router.ts"],"names":[],"mappings":"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"}
@@ -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()